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  }