auth
auth/session_postgres.go
Wire up the postgres database for authd. Have authd use the AUTH_PG_DB environment variable to detect support for the postgres *Stores, and if postgres is supported, use it. If postgres isn't supported, fall back on the in-memory store. Also create-if-not-exists the test scopes, instead of panicking when the scope already exists.
1 package auth
3 import (
4 "time"
6 "code.secondbit.org/uuid.hg"
8 "github.com/lib/pq"
9 "github.com/secondbit/pan"
10 )
12 func (s Session) GetSQLTableName() string {
13 return "sessions"
14 }
16 func (p *postgres) createSessionSQL(session Session) *pan.Query {
17 fields, values := pan.GetFields(session)
18 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(session))
19 query.Include("(" + pan.QueryList(fields) + ")")
20 query.Include("VALUES")
21 query.Include("("+pan.VariableList(len(values))+")", values...)
22 return query.FlushExpressions(" ")
23 }
25 func (p *postgres) createSession(session Session) error {
26 query := p.createSessionSQL(session)
27 _, err := p.db.Exec(query.String(), query.Args...)
28 if e, ok := err.(*pq.Error); ok && e.Constraint == "sessions_pkey" {
29 err = ErrSessionAlreadyExists
30 }
31 return err
32 }
34 func (p *postgres) getSessionSQL(id string) *pan.Query {
35 var session Session
36 fields, _ := pan.GetFields(session)
37 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(session))
38 query.IncludeWhere()
39 query.Include(pan.GetUnquotedColumn(session, "ID")+" = ?", id)
40 return query.FlushExpressions(" ")
41 }
43 func (p *postgres) getSession(id string) (Session, error) {
44 query := p.getSessionSQL(id)
45 rows, err := p.db.Query(query.String(), query.Args...)
46 if err != nil {
47 return Session{}, err
48 }
49 var session Session
50 var found bool
51 for rows.Next() {
52 err := pan.Unmarshal(rows, &session)
53 if err != nil {
54 return session, err
55 }
56 found = true
57 }
58 if err = rows.Err(); err != nil {
59 return session, err
60 }
61 if !found {
62 return session, ErrSessionNotFound
63 }
64 return session, nil
65 }
67 func (p *postgres) removeSessionSQL(id string) *pan.Query {
68 var session Session
69 query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(session))
70 query.IncludeWhere()
71 query.Include(pan.GetUnquotedColumn(session, "ID")+" = ?", id)
72 return query.FlushExpressions(" ")
73 }
75 func (p *postgres) removeSession(id string) error {
76 query := p.removeSessionSQL(id)
77 res, err := p.db.Exec(query.String(), query.Args...)
78 if err != nil {
79 return err
80 }
81 rows, err := res.RowsAffected()
82 if err != nil {
83 return err
84 }
85 if rows < 1 {
86 return ErrSessionNotFound
87 }
88 return nil
89 }
91 func (p *postgres) listSessionsSQL(profile uuid.ID, before time.Time, num int64) *pan.Query {
92 var session Session
93 fields, _ := pan.GetFields(session)
94 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(session))
95 query.IncludeWhere()
96 query.Include(pan.GetUnquotedColumn(session, "ProfileID")+" = ?", profile)
97 if !before.IsZero() {
98 query.Include(pan.GetUnquotedColumn(session, "Created")+" < ?", before)
99 }
100 query.FlushExpressions(" AND ")
101 if num > 0 {
102 query.IncludeLimit(num)
103 }
104 return query.FlushExpressions(" ")
105 }
107 func (p *postgres) listSessions(profile uuid.ID, before time.Time, num int64) ([]Session, error) {
108 query := p.listSessionsSQL(profile, before, num)
109 rows, err := p.db.Query(query.String(), query.Args...)
110 if err != nil {
111 return []Session{}, err
112 }
113 var sessions []Session
114 for rows.Next() {
115 var session Session
116 err := pan.Unmarshal(rows, &session)
117 if err != nil {
118 return sessions, err
119 }
120 sessions = append(sessions, session)
121 }
122 if err = rows.Err(); err != nil {
123 return sessions, err
124 }
125 return sessions, nil
126 }