auth

Paddy 2015-04-06 Child:cf6c1f05eb21

154:5f670aba87b4 Go to Latest

auth/session_postgres.go

Implement a session store in postgres. Write the postgres implementation of our sessionStore type. Write the SQL statements to initialize the database for us. Include the postgres implementation of our sessionStore type in our sessionStore tests when the appropriate environment variable is passed.

History
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/session_postgres.go	Mon Apr 06 07:58:10 2015 -0400
     1.3 @@ -0,0 +1,126 @@
     1.4 +package auth
     1.5 +
     1.6 +import (
     1.7 +	"time"
     1.8 +
     1.9 +	"code.secondbit.org/uuid.hg"
    1.10 +
    1.11 +	"github.com/lib/pq"
    1.12 +	"github.com/secondbit/pan"
    1.13 +)
    1.14 +
    1.15 +func (s Session) GetSQLTableName() string {
    1.16 +	return "sessions"
    1.17 +}
    1.18 +
    1.19 +func (p *postgres) createSessionSQL(session Session) *pan.Query {
    1.20 +	fields, values := pan.GetFields(session)
    1.21 +	query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(session))
    1.22 +	query.Include("(" + pan.QueryList(fields) + ")")
    1.23 +	query.Include("VALUES")
    1.24 +	query.Include("("+pan.VariableList(len(values))+")", values...)
    1.25 +	return query.FlushExpressions(" ")
    1.26 +}
    1.27 +
    1.28 +func (p *postgres) createSession(session Session) error {
    1.29 +	query := p.createSessionSQL(session)
    1.30 +	_, err := p.db.Exec(query.String(), query.Args...)
    1.31 +	if e, ok := err.(*pq.Error); ok && e.Constraint == "sessions_pkey" {
    1.32 +		err = ErrSessionAlreadyExists
    1.33 +	}
    1.34 +	return err
    1.35 +}
    1.36 +
    1.37 +func (p *postgres) getSessionSQL(id string) *pan.Query {
    1.38 +	var session Session
    1.39 +	fields, _ := pan.GetFields(session)
    1.40 +	query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(session))
    1.41 +	query.IncludeWhere()
    1.42 +	query.Include(pan.GetUnquotedColumn(session, "ID")+" = ?", id)
    1.43 +	return query.FlushExpressions(" ")
    1.44 +}
    1.45 +
    1.46 +func (p *postgres) getSession(id string) (Session, error) {
    1.47 +	query := p.getSessionSQL(id)
    1.48 +	rows, err := p.db.Query(query.String(), query.Args...)
    1.49 +	if err != nil {
    1.50 +		return Session{}, err
    1.51 +	}
    1.52 +	var session Session
    1.53 +	var found bool
    1.54 +	for rows.Next() {
    1.55 +		err := pan.Unmarshal(rows, &session)
    1.56 +		if err != nil {
    1.57 +			return session, err
    1.58 +		}
    1.59 +		found = true
    1.60 +	}
    1.61 +	if err = rows.Err(); err != nil {
    1.62 +		return session, err
    1.63 +	}
    1.64 +	if !found {
    1.65 +		return session, ErrSessionNotFound
    1.66 +	}
    1.67 +	return session, nil
    1.68 +}
    1.69 +
    1.70 +func (p *postgres) removeSessionSQL(id string) *pan.Query {
    1.71 +	var session Session
    1.72 +	query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(session))
    1.73 +	query.IncludeWhere()
    1.74 +	query.Include(pan.GetUnquotedColumn(session, "ID")+" = ?", id)
    1.75 +	return query.FlushExpressions(" ")
    1.76 +}
    1.77 +
    1.78 +func (p *postgres) removeSession(id string) error {
    1.79 +	query := p.removeSessionSQL(id)
    1.80 +	res, err := p.db.Exec(query.String(), query.Args...)
    1.81 +	if err != nil {
    1.82 +		return err
    1.83 +	}
    1.84 +	rows, err := res.RowsAffected()
    1.85 +	if err != nil {
    1.86 +		return err
    1.87 +	}
    1.88 +	if rows < 1 {
    1.89 +		return ErrSessionNotFound
    1.90 +	}
    1.91 +	return nil
    1.92 +}
    1.93 +
    1.94 +func (p *postgres) listSessionsSQL(profile uuid.ID, before time.Time, num int64) *pan.Query {
    1.95 +	var session Session
    1.96 +	fields, _ := pan.GetFields(session)
    1.97 +	query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(session))
    1.98 +	query.IncludeWhere()
    1.99 +	query.Include(pan.GetUnquotedColumn(session, "ProfileID")+" = ?", profile)
   1.100 +	if !before.IsZero() {
   1.101 +		query.Include(pan.GetUnquotedColumn(session, "Created")+" < ?", before)
   1.102 +	}
   1.103 +	query.FlushExpressions(" AND ")
   1.104 +	if num > 0 {
   1.105 +		query.IncludeLimit(num)
   1.106 +	}
   1.107 +	return query.FlushExpressions(" ")
   1.108 +}
   1.109 +
   1.110 +func (p *postgres) listSessions(profile uuid.ID, before time.Time, num int64) ([]Session, error) {
   1.111 +	query := p.listSessionsSQL(profile, before, num)
   1.112 +	rows, err := p.db.Query(query.String(), query.Args...)
   1.113 +	if err != nil {
   1.114 +		return []Session{}, err
   1.115 +	}
   1.116 +	var sessions []Session
   1.117 +	for rows.Next() {
   1.118 +		var session Session
   1.119 +		err := pan.Unmarshal(rows, &session)
   1.120 +		if err != nil {
   1.121 +			return sessions, err
   1.122 +		}
   1.123 +		sessions = append(sessions, session)
   1.124 +	}
   1.125 +	if err = rows.Err(); err != nil {
   1.126 +		return sessions, err
   1.127 +	}
   1.128 +	return sessions, nil
   1.129 +}