Raw
 1package storage
 2
 3import (
 4	"context"
 5	"database/sql"
 6	"time"
 7)
 8
 9func (s *Store) inAuditedTx(ctx context.Context, operation string, audits []AppendAuditInput, write func(tx *sql.Tx) error) error {
10	if err := s.checkOpen(operation); err != nil {
11		return err
12	}
13	tx, err := s.sql.BeginTx(ctx, nil)
14	if err != nil {
15		return classify("begin "+operation, err)
16	}
17	defer tx.Rollback()
18	if err := write(tx); err != nil {
19		return err
20	}
21	at := canonicalTime(s.now())
22	for _, audit := range audits {
23		if _, err := appendAudit(ctx, tx, operation+" audit", audit, at); err != nil {
24			return err
25		}
26	}
27	return classify("commit "+operation, tx.Commit())
28}
29
30func (s *Store) CreateForwardSessionAudited(ctx context.Context, input CreateForwardSessionInput, audits ...AppendAuditInput) (ForwardSession, error) {
31	var row ForwardSession
32	err := s.inAuditedTx(ctx, "create forward session", audits, func(tx *sql.Tx) error {
33		var err error
34		row, err = createForwardSession(ctx, tx, input)
35		return err
36	})
37	if err != nil {
38		return ForwardSession{}, err
39	}
40	return row, nil
41}
42
43func (s *Store) MarkReauthenticatedAudited(ctx context.Context, id string, at time.Time, audit AppendAuditInput) error {
44	return s.inAuditedTx(ctx, "mark forward session reauthenticated", []AppendAuditInput{audit}, func(tx *sql.Tx) error {
45		return markReauthenticated(ctx, tx, id, at)
46	})
47}
48
49func (s *Store) RecordLoginAudited(ctx context.Context, userID string, at time.Time, audit AppendAuditInput) error {
50	const operation = "record login"
51	return s.inAuditedTx(ctx, operation, []AppendAuditInput{audit}, func(tx *sql.Tx) error {
52		result, err := tx.ExecContext(ctx, `UPDATE users SET last_login_at = ? WHERE id = ?`, timeToInt(at), userID)
53		if err != nil {
54			return classify(operation, err)
55		}
56		return requireChanged(operation, result)
57	})
58}