github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/misc_logs.go (about) 1 package common 2 3 import ( 4 "database/sql" 5 "time" 6 7 qgen "github.com/Azareal/Gosora/query_gen" 8 ) 9 10 var RegLogs RegLogStore 11 var LoginLogs LoginLogStore 12 13 type RegLogItem struct { 14 ID int 15 Username string 16 Email string 17 FailureReason string 18 Success bool 19 IP string 20 DoneAt string 21 } 22 23 type RegLogStmts struct { 24 update *sql.Stmt 25 create *sql.Stmt 26 } 27 28 var regLogStmts RegLogStmts 29 30 func init() { 31 DbInits.Add(func(acc *qgen.Accumulator) error { 32 rl := "registration_logs" 33 regLogStmts = RegLogStmts{ 34 update: acc.Update(rl).Set("username=?,email=?,failureReason=?,success=?,doneAt=?").Where("rlid=?").Prepare(), 35 create: acc.Insert(rl).Columns("username,email,failureReason,success,ipaddress,doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(), 36 } 37 return acc.FirstError() 38 }) 39 } 40 41 // TODO: Reload this item in the store, probably doesn't matter right now, but it might when we start caching this stuff in memory 42 // ! Retroactive updates of date are not permitted for integrity reasons 43 // TODO: Do we even use this anymore or can we just make the logs immutable (except for deletes) for simplicity sake? 44 func (l *RegLogItem) Commit() error { 45 _, e := regLogStmts.update.Exec(l.Username, l.Email, l.FailureReason, l.Success, l.DoneAt, l.ID) 46 return e 47 } 48 49 func (l *RegLogItem) Create() (id int, e error) { 50 id, e = Createf(regLogStmts.create, l.Username, l.Email, l.FailureReason, l.Success, l.IP) 51 l.ID = id 52 return l.ID, e 53 } 54 55 type RegLogStore interface { 56 Count() (count int) 57 GetOffset(offset, perPage int) (logs []RegLogItem, err error) 58 Purge() error 59 60 DeleteOlderThanDays(days int) error 61 } 62 63 type SQLRegLogStore struct { 64 count *sql.Stmt 65 getOffset *sql.Stmt 66 purge *sql.Stmt 67 68 deleteOlderThanDays *sql.Stmt 69 } 70 71 func NewRegLogStore(acc *qgen.Accumulator) (*SQLRegLogStore, error) { 72 rl := "registration_logs" 73 return &SQLRegLogStore{ 74 count: acc.Count(rl).Prepare(), 75 getOffset: acc.Select(rl).Columns("rlid,username,email,failureReason,success,ipaddress,doneAt").Orderby("doneAt DESC").Limit("?,?").Prepare(), 76 purge: acc.Purge(rl), 77 78 deleteOlderThanDays: acc.Delete(rl).DateOlderThanQ("doneAt", "day").Prepare(), 79 }, acc.FirstError() 80 } 81 82 func (s *SQLRegLogStore) Count() (count int) { 83 return Count(s.count) 84 } 85 86 func (s *SQLRegLogStore) GetOffset(offset, perPage int) (logs []RegLogItem, e error) { 87 rows, e := s.getOffset.Query(offset, perPage) 88 if e != nil { 89 return logs, e 90 } 91 defer rows.Close() 92 93 for rows.Next() { 94 var l RegLogItem 95 var doneAt time.Time 96 e := rows.Scan(&l.ID, &l.Username, &l.Email, &l.FailureReason, &l.Success, &l.IP, &doneAt) 97 if e != nil { 98 return logs, e 99 } 100 l.DoneAt = doneAt.Format("2006-01-02 15:04:05") 101 logs = append(logs, l) 102 } 103 return logs, rows.Err() 104 } 105 106 func (s *SQLRegLogStore) DeleteOlderThanDays(days int) error { 107 _, e := s.deleteOlderThanDays.Exec(days) 108 return e 109 } 110 111 // Delete all registration logs 112 func (s *SQLRegLogStore) Purge() error { 113 _, e := s.purge.Exec() 114 return e 115 } 116 117 type LoginLogItem struct { 118 ID int 119 UID int 120 Success bool 121 IP string 122 DoneAt string 123 } 124 125 type LoginLogStmts struct { 126 update *sql.Stmt 127 create *sql.Stmt 128 } 129 130 var loginLogStmts LoginLogStmts 131 132 func init() { 133 DbInits.Add(func(acc *qgen.Accumulator) error { 134 ll := "login_logs" 135 loginLogStmts = LoginLogStmts{ 136 update: acc.Update(ll).Set("uid=?,success=?,doneAt=?").Where("lid=?").Prepare(), 137 create: acc.Insert(ll).Columns("uid,success,ipaddress,doneAt").Fields("?,?,?,UTC_TIMESTAMP()").Prepare(), 138 } 139 return acc.FirstError() 140 }) 141 } 142 143 // TODO: Reload this item in the store, probably doesn't matter right now, but it might when we start caching this stuff in memory 144 // ! Retroactive updates of date are not permitted for integrity reasons 145 func (l *LoginLogItem) Commit() error { 146 _, e := loginLogStmts.update.Exec(l.UID, l.Success, l.DoneAt, l.ID) 147 return e 148 } 149 150 func (l *LoginLogItem) Create() (id int, e error) { 151 res, e := loginLogStmts.create.Exec(l.UID, l.Success, l.IP) 152 if e != nil { 153 return 0, e 154 } 155 id64, e := res.LastInsertId() 156 l.ID = int(id64) 157 return l.ID, e 158 } 159 160 type LoginLogStore interface { 161 Count() (count int) 162 CountUser(uid int) (count int) 163 GetOffset(uid, offset, perPage int) (logs []LoginLogItem, err error) 164 Purge() error 165 166 DeleteOlderThanDays(days int) error 167 } 168 169 type SQLLoginLogStore struct { 170 count *sql.Stmt 171 countForUser *sql.Stmt 172 getOffsetByUser *sql.Stmt 173 purge *sql.Stmt 174 175 deleteOlderThanDays *sql.Stmt 176 } 177 178 func NewLoginLogStore(acc *qgen.Accumulator) (*SQLLoginLogStore, error) { 179 ll := "login_logs" 180 return &SQLLoginLogStore{ 181 count: acc.Count(ll).Prepare(), 182 countForUser: acc.Count(ll).Where("uid=?").Prepare(), 183 getOffsetByUser: acc.Select(ll).Columns("lid,success,ipaddress,doneAt").Where("uid=?").Orderby("doneAt DESC").Limit("?,?").Prepare(), 184 purge: acc.Purge(ll), 185 186 deleteOlderThanDays: acc.Delete(ll).DateOlderThanQ("doneAt", "day").Prepare(), 187 }, acc.FirstError() 188 } 189 190 func (s *SQLLoginLogStore) Count() (count int) { 191 return Count(s.count) 192 } 193 194 func (s *SQLLoginLogStore) CountUser(uid int) (count int) { 195 return Countf(s.countForUser, uid) 196 } 197 198 func (s *SQLLoginLogStore) GetOffset(uid, offset, perPage int) (logs []LoginLogItem, e error) { 199 rows, e := s.getOffsetByUser.Query(uid, offset, perPage) 200 if e != nil { 201 return logs, e 202 } 203 defer rows.Close() 204 205 for rows.Next() { 206 l := LoginLogItem{UID: uid} 207 var doneAt time.Time 208 e := rows.Scan(&l.ID, &l.Success, &l.IP, &doneAt) 209 if e != nil { 210 return logs, e 211 } 212 l.DoneAt = doneAt.Format("2006-01-02 15:04:05") 213 logs = append(logs, l) 214 } 215 return logs, rows.Err() 216 } 217 218 func (s *SQLLoginLogStore) DeleteOlderThanDays(days int) error { 219 _, e := s.deleteOlderThanDays.Exec(days) 220 return e 221 } 222 223 // Delete all login logs 224 func (s *SQLLoginLogStore) Purge() error { 225 _, e := s.purge.Exec() 226 return e 227 }