lastlogin.go 2.17 KB
Newer Older
shammash's avatar
shammash committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
package server

import (
	"database/sql"
	"errors"

	"git.autistici.org/id/usermetadb"
)

var lastloginDBStatements = map[string]string{
	"insert_or_replace_last_login": `
		INSERT OR REPLACE INTO lastlogin (
			username, service, timestamp
		) VALUES (
			?, ?, ?
		)`,
	"get_service_last_login": `
		SELECT
			username, service, timestamp
		FROM
			lastlogin
		WHERE
			username = ? AND service = ?`,
	"get_last_login": `
		SELECT
			username, service, timestamp
		FROM
			lastlogin
		WHERE
			username = ?
		ORDER BY timestamp DESC`,
}

type lastloginDB struct {
	db    *sql.DB
	stmts statementMap
}

func newLastloginDB(db *sql.DB) (*lastloginDB, error) {
	stmts, err := newStatementMap(db, lastloginDBStatements)
	if err != nil {
		return nil, err
	}

	return &lastloginDB{
		db:    db,
		stmts: stmts,
	}, nil
}

func (l *lastloginDB) Close() {
	l.stmts.Close()
}

func (l *lastloginDB) AddLastLogin(entry *usermetadb.LastLoginEntry) error {
	if entry == nil {
		return errors.New("received nil entry")
	}

	if err := entry.Validate(); err != nil {
		return err
	}

	tx, err := l.db.Begin()
	if err != nil {
		return err
	}
ale's avatar
ale committed
68
	defer tx.Rollback() // nolint
shammash's avatar
shammash committed
69 70 71 72 73

	stmt := "insert_or_replace_last_login"
	args := []interface{}{
		entry.Username,
		entry.Service,
ale's avatar
ale committed
74
		roundTimestamp(entry.Timestamp),
shammash's avatar
shammash committed
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
	}

	if _, err = l.stmts.get(tx, stmt).Exec(args...); err != nil {
		return err
	}

	return tx.Commit()
}

func (l *lastloginDB) GetLastLogin(username string, service string) ([]*usermetadb.LastLoginEntry, error) {

	tx, err := l.db.Begin()
	if err != nil {
		return nil, err
	}
ale's avatar
ale committed
90
	defer tx.Rollback() // nolint
shammash's avatar
shammash committed
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

	var stmt string
	var args []interface{}
	if service != "" {
		stmt = "get_service_last_login"
		args = []interface{}{
			username,
			service,
		}
	} else {
		stmt = "get_last_login"
		args = []interface{}{
			username,
		}
	}
	rows, err := l.stmts.get(tx, stmt).Query(args...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var entries []*usermetadb.LastLoginEntry
	for rows.Next() {
		e := &usermetadb.LastLoginEntry{}
		if err := rows.Scan(
			&e.Username,
			&e.Service,
			&e.Timestamp,
		); err != nil {
			return nil, err
		}
		entries = append(entries, e)
	}

	return entries, rows.Err()
}