github.com/readium/readium-lcp-server@v0.0.0-20240101192032-6e95190e99f1/license/store.go (about) 1 // Copyright 2017 European Digital Reading Lab. All rights reserved. 2 // Licensed to the Readium Foundation under one or more contributor license agreements. 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the LICENSE file exposed on Github (readium) in the project repository. 5 6 package license 7 8 import ( 9 "database/sql" 10 "errors" 11 "log" 12 "time" 13 14 "github.com/readium/readium-lcp-server/config" 15 ) 16 17 var ErrNotFound = errors.New("License not found") 18 19 type Store interface { 20 ListAll(page int, pageNum int) func() (LicenseReport, error) 21 ListByContentID(ContentID string, page int, pageNum int) func() (LicenseReport, error) 22 UpdateRights(l License) error 23 Update(l License) error 24 UpdateLsdStatus(id string, status int32) error 25 Add(l License) error 26 Get(id string) (License, error) 27 } 28 29 type sqlStore struct { 30 db *sql.DB 31 dbGetByID *sql.Stmt 32 dbList *sql.Stmt 33 dbListByContentID *sql.Stmt 34 } 35 36 // ListAll lists all licenses in ante-chronological order 37 // pageNum starts at 0 38 func (s *sqlStore) ListAll(pageSize int, pageNum int) func() (LicenseReport, error) { 39 40 var rows *sql.Rows 41 var err error 42 driver, _ := config.GetDatabase(config.Config.LcpServer.Database) 43 if driver == "mssql" { 44 rows, err = s.dbList.Query(pageNum*pageSize, pageSize) 45 } else { 46 rows, err = s.dbList.Query(pageSize, pageNum*pageSize) 47 } 48 if err != nil { 49 return func() (LicenseReport, error) { return LicenseReport{}, err } 50 } 51 return func() (LicenseReport, error) { 52 var l LicenseReport 53 var err error 54 l.User = UserInfo{} 55 l.Rights = new(UserRights) 56 if rows.Next() { 57 err = rows.Scan(&l.ID, &l.User.ID, &l.Provider, &l.Issued, &l.Updated, 58 &l.Rights.Print, &l.Rights.Copy, &l.Rights.Start, &l.Rights.End, &l.ContentID) 59 } else { 60 rows.Close() 61 err = ErrNotFound 62 } 63 return l, err 64 } 65 } 66 67 // ListByContentID lists licenses for a given ContentID 68 // pageNum starting at 0 69 func (s *sqlStore) ListByContentID(contentID string, pageSize int, pageNum int) func() (LicenseReport, error) { 70 71 var rows *sql.Rows 72 var err error 73 driver, _ := config.GetDatabase(config.Config.LcpServer.Database) 74 if driver == "mssql" { 75 rows, err = s.dbListByContentID.Query(contentID, pageNum*pageSize, pageSize) 76 } else { 77 rows, err = s.dbListByContentID.Query(contentID, pageSize, pageNum*pageSize) 78 } 79 if err != nil { 80 return func() (LicenseReport, error) { return LicenseReport{}, err } 81 } 82 return func() (LicenseReport, error) { 83 var l LicenseReport 84 var err error 85 l.User = UserInfo{} 86 l.Rights = new(UserRights) 87 if rows.Next() { 88 err = rows.Scan(&l.ID, &l.User.ID, &l.Provider, &l.Issued, &l.Updated, 89 &l.Rights.Print, &l.Rights.Copy, &l.Rights.Start, &l.Rights.End, &l.ContentID) 90 } else { 91 rows.Close() 92 err = ErrNotFound 93 } 94 return l, err 95 } 96 } 97 98 // UpdateRights 99 func (s *sqlStore) UpdateRights(l License) error { 100 101 result, err := s.db.Exec("UPDATE license SET rights_print=?, rights_copy=?, rights_start=?, rights_end=?, updated=? WHERE id=?", 102 l.Rights.Print, l.Rights.Copy, l.Rights.Start, l.Rights.End, time.Now().UTC().Truncate(time.Second), l.ID) 103 104 if err == nil { 105 if r, _ := result.RowsAffected(); r == 0 { 106 return ErrNotFound 107 } 108 } 109 return err 110 } 111 112 // Add creates a new record in the license table 113 func (s *sqlStore) Add(l License) error { 114 115 _, err := s.db.Exec(`INSERT INTO license (id, user_id, provider, issued, updated, 116 rights_print, rights_copy, rights_start, rights_end, content_fk) 117 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, 118 l.ID, l.User.ID, l.Provider, l.Issued, nil, 119 l.Rights.Print, l.Rights.Copy, l.Rights.Start, l.Rights.End, 120 l.ContentID) 121 return err 122 } 123 124 // Update updates a record in the license table 125 func (s *sqlStore) Update(l License) error { 126 127 _, err := s.db.Exec(`UPDATE license SET user_id=?,provider=?,updated=?, 128 rights_print=?, rights_copy=?, rights_start=?, rights_end=?, content_fk =? 129 WHERE id=?`, 130 l.User.ID, l.Provider, 131 time.Now().UTC().Truncate(time.Second), 132 l.Rights.Print, l.Rights.Copy, l.Rights.Start, l.Rights.End, 133 l.ContentID, 134 l.ID) 135 136 return err 137 } 138 139 // UpdateLsdStatus 140 func (s *sqlStore) UpdateLsdStatus(id string, status int32) error { 141 142 _, err := s.db.Exec(`UPDATE license SET lsd_status =? WHERE id=?`, 143 status, id) 144 145 return err 146 } 147 148 // Get a license from the db 149 func (s *sqlStore) Get(id string) (License, error) { 150 151 row := s.dbGetByID.QueryRow(id) 152 var l License 153 l.Rights = new(UserRights) 154 err := row.Scan(&l.ID, &l.User.ID, &l.Provider, &l.Issued, &l.Updated, 155 &l.Rights.Print, &l.Rights.Copy, &l.Rights.Start, &l.Rights.End, &l.ContentID) 156 if err == sql.ErrNoRows { 157 err = ErrNotFound 158 } 159 return l, err 160 } 161 162 // Open 163 func Open(db *sql.DB) (store Store, err error) { 164 165 driver, _ := config.GetDatabase(config.Config.LcpServer.Database) 166 167 // if sqlite, create the license table if it does not exist 168 if driver == "sqlite3" { 169 _, err := db.Exec(tableDef) 170 if err != nil { 171 log.Println("Error creating sqlite license table") 172 return nil, err 173 } 174 } 175 176 var dbList *sql.Stmt 177 if driver == "mssql" { 178 dbList, err = db.Prepare(`SELECT id, user_id, provider, issued, updated, rights_print, rights_copy, rights_start, rights_end, content_fk 179 FROM license ORDER BY issued desc OFFSET ? ROWS FETCH NEXT ? ROWS ONLY`) 180 } else { 181 dbList, err = db.Prepare(`SELECT id, user_id, provider, issued, updated, rights_print, rights_copy, rights_start, rights_end, content_fk 182 FROM license ORDER BY issued desc LIMIT ? OFFSET ?`) 183 } 184 if err != nil { 185 log.Println("Error preparing dbList") 186 return 187 } 188 189 var dbListByContentID *sql.Stmt 190 if driver == "mssql" { 191 dbListByContentID, err = db.Prepare(`SELECT id, user_id, provider, issued, updated, 192 rights_print, rights_copy, rights_start, rights_end, content_fk 193 FROM license WHERE content_fk = ? ORDER BY issued desc OFFSET ? ROWS FETCH NEXT ? ROWS ONLY`) 194 } else { 195 dbListByContentID, err = db.Prepare(`SELECT id, user_id, provider, issued, updated, 196 rights_print, rights_copy, rights_start, rights_end, content_fk 197 FROM license WHERE content_fk = ? ORDER BY issued desc LIMIT ? OFFSET ?`) 198 199 } 200 if err != nil { 201 log.Println("Error preparing dbListByContentID") 202 return 203 } 204 205 var dbGetByID *sql.Stmt 206 dbGetByID, err = db.Prepare(`SELECT id, user_id, provider, issued, updated, rights_print, rights_copy, 207 rights_start, rights_end, content_fk 208 FROM license WHERE id = ?`) 209 if err != nil { 210 log.Println("Error preparing dbGetByID") 211 return 212 } 213 214 store = &sqlStore{db, dbGetByID, dbList, dbListByContentID} 215 return 216 } 217 218 const tableDef = "CREATE TABLE IF NOT EXISTS license (" + 219 "id varchar(255) PRIMARY KEY," + 220 "user_id varchar(255) NOT NULL," + 221 "provider varchar(255) NOT NULL," + 222 "issued datetime NOT NULL," + 223 "updated datetime DEFAULT NULL," + 224 "rights_print int(11) DEFAULT NULL," + 225 "rights_copy int(11) DEFAULT NULL," + 226 "rights_start datetime DEFAULT NULL," + 227 "rights_end datetime DEFAULT NULL," + 228 "content_fk varchar(255) NOT NULL," + 229 "lsd_status integer default 0," + 230 "FOREIGN KEY(content_fk) REFERENCES content(id))"