auth
auth/scope_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.
| paddy@152 | 1 package auth |
| paddy@152 | 2 |
| paddy@152 | 3 import ( |
| paddy@153 | 4 "github.com/lib/pq" |
| paddy@152 | 5 "github.com/secondbit/pan" |
| paddy@152 | 6 ) |
| paddy@152 | 7 |
| paddy@152 | 8 func (s Scope) GetSQLTableName() string { |
| paddy@152 | 9 return "scopes" |
| paddy@152 | 10 } |
| paddy@152 | 11 |
| paddy@152 | 12 func (p *postgres) createScopesSQL(scopes []Scope) *pan.Query { |
| paddy@152 | 13 fields, _ := pan.GetFields(scopes[0]) |
| paddy@152 | 14 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(scopes[0])) |
| paddy@152 | 15 query.Include("(" + pan.QueryList(fields) + ")") |
| paddy@152 | 16 query.Include("VALUES") |
| paddy@153 | 17 query.FlushExpressions(" ") |
| paddy@152 | 18 for _, scope := range scopes { |
| paddy@152 | 19 _, values := pan.GetFields(scope) |
| paddy@152 | 20 query.Include("("+pan.VariableList(len(values))+")", values...) |
| paddy@152 | 21 } |
| paddy@153 | 22 return query.FlushExpressions(", ") |
| paddy@152 | 23 } |
| paddy@152 | 24 |
| paddy@152 | 25 func (p *postgres) createScopes(scopes []Scope) error { |
| paddy@152 | 26 if len(scopes) < 1 { |
| paddy@152 | 27 return nil |
| paddy@152 | 28 } |
| paddy@152 | 29 query := p.createScopesSQL(scopes) |
| paddy@152 | 30 _, err := p.db.Exec(query.String(), query.Args...) |
| paddy@153 | 31 if e, ok := err.(*pq.Error); ok && e.Constraint == "scopes_pkey" { |
| paddy@153 | 32 err = ErrScopeAlreadyExists |
| paddy@153 | 33 } |
| paddy@152 | 34 return err |
| paddy@152 | 35 } |
| paddy@152 | 36 |
| paddy@152 | 37 func (p *postgres) getScopesSQL(ids []string) *pan.Query { |
| paddy@152 | 38 var scope Scope |
| paddy@152 | 39 intids := make([]interface{}, len(ids)) |
| paddy@152 | 40 for pos, id := range ids { |
| paddy@152 | 41 intids[pos] = id |
| paddy@152 | 42 } |
| paddy@152 | 43 fields, _ := pan.GetFields(scope) |
| paddy@152 | 44 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(scope)) |
| paddy@152 | 45 query.IncludeWhere() |
| paddy@152 | 46 query.Include(pan.GetUnquotedColumn(scope, "ID") + " IN") |
| paddy@152 | 47 query.Include("("+pan.VariableList(len(ids))+")", intids...) |
| paddy@152 | 48 return query.FlushExpressions(" ") |
| paddy@152 | 49 } |
| paddy@152 | 50 |
| paddy@152 | 51 func (p *postgres) getScopes(ids []string) ([]Scope, error) { |
| paddy@152 | 52 query := p.getScopesSQL(ids) |
| paddy@152 | 53 rows, err := p.db.Query(query.String(), query.Args...) |
| paddy@152 | 54 if err != nil { |
| paddy@152 | 55 return []Scope{}, err |
| paddy@152 | 56 } |
| paddy@152 | 57 var scopes []Scope |
| paddy@152 | 58 for rows.Next() { |
| paddy@152 | 59 var scope Scope |
| paddy@152 | 60 err := pan.Unmarshal(rows, &scope) |
| paddy@152 | 61 if err != nil { |
| paddy@152 | 62 return scopes, err |
| paddy@152 | 63 } |
| paddy@152 | 64 scopes = append(scopes, scope) |
| paddy@152 | 65 } |
| paddy@152 | 66 if err = rows.Err(); err != nil { |
| paddy@152 | 67 return scopes, err |
| paddy@152 | 68 } |
| paddy@152 | 69 return scopes, nil |
| paddy@152 | 70 } |
| paddy@152 | 71 |
| paddy@152 | 72 func (p *postgres) updateScopeSQL(id string, change ScopeChange) *pan.Query { |
| paddy@152 | 73 var scope Scope |
| paddy@152 | 74 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(scope)+" SET ") |
| paddy@152 | 75 query.IncludeIfNotNil(pan.GetUnquotedColumn(scope, "Name")+" = ?", change.Name) |
| paddy@152 | 76 query.IncludeIfNotNil(pan.GetUnquotedColumn(scope, "Description")+" = ?", change.Description) |
| paddy@152 | 77 query.FlushExpressions(", ") |
| paddy@152 | 78 query.IncludeWhere() |
| paddy@152 | 79 query.Include(pan.GetUnquotedColumn(scope, "ID")+" = ?", id) |
| paddy@152 | 80 return query.FlushExpressions(" ") |
| paddy@152 | 81 } |
| paddy@152 | 82 |
| paddy@152 | 83 func (p *postgres) updateScope(id string, change ScopeChange) error { |
| paddy@152 | 84 if change.Empty() { |
| paddy@152 | 85 return nil |
| paddy@152 | 86 } |
| paddy@152 | 87 query := p.updateScopeSQL(id, change) |
| paddy@153 | 88 res, err := p.db.Exec(query.String(), query.Args...) |
| paddy@153 | 89 if err != nil { |
| paddy@153 | 90 return err |
| paddy@153 | 91 } |
| paddy@153 | 92 rows, err := res.RowsAffected() |
| paddy@153 | 93 if err != nil { |
| paddy@153 | 94 return err |
| paddy@153 | 95 } |
| paddy@153 | 96 if rows < 1 { |
| paddy@153 | 97 return ErrScopeNotFound |
| paddy@153 | 98 } |
| paddy@152 | 99 return err |
| paddy@152 | 100 } |
| paddy@152 | 101 |
| paddy@152 | 102 func (p *postgres) removeScopesSQL(ids []string) *pan.Query { |
| paddy@152 | 103 var scope Scope |
| paddy@152 | 104 intids := make([]interface{}, len(ids)) |
| paddy@152 | 105 for pos, id := range ids { |
| paddy@152 | 106 intids[pos] = id |
| paddy@152 | 107 } |
| paddy@152 | 108 query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(scope)) |
| paddy@152 | 109 query.IncludeWhere() |
| paddy@152 | 110 query.Include(pan.GetUnquotedColumn(scope, "ID") + " IN") |
| paddy@152 | 111 query.Include("("+pan.VariableList(len(ids))+")", intids...) |
| paddy@152 | 112 return query.FlushExpressions(" ") |
| paddy@152 | 113 } |
| paddy@152 | 114 |
| paddy@152 | 115 func (p *postgres) removeScopes(ids []string) error { |
| paddy@152 | 116 query := p.removeScopesSQL(ids) |
| paddy@153 | 117 res, err := p.db.Exec(query.String(), query.Args...) |
| paddy@152 | 118 if err != nil { |
| paddy@152 | 119 return err |
| paddy@152 | 120 } |
| paddy@153 | 121 rows, err := res.RowsAffected() |
| paddy@153 | 122 if err != nil { |
| paddy@153 | 123 return err |
| paddy@153 | 124 } |
| paddy@153 | 125 if rows < 1 { |
| paddy@153 | 126 return ErrScopeNotFound |
| paddy@153 | 127 } |
| paddy@152 | 128 return nil |
| paddy@152 | 129 } |
| paddy@152 | 130 |
| paddy@152 | 131 func (p *postgres) listScopesSQL() *pan.Query { |
| paddy@152 | 132 var scope Scope |
| paddy@152 | 133 fields, _ := pan.GetFields(scope) |
| paddy@152 | 134 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(scope)) |
| paddy@152 | 135 return query.FlushExpressions(" ") |
| paddy@152 | 136 } |
| paddy@152 | 137 |
| paddy@152 | 138 func (p *postgres) listScopes() ([]Scope, error) { |
| paddy@152 | 139 query := p.listScopesSQL() |
| paddy@152 | 140 rows, err := p.db.Query(query.String(), query.Args...) |
| paddy@152 | 141 if err != nil { |
| paddy@152 | 142 return []Scope{}, err |
| paddy@152 | 143 } |
| paddy@152 | 144 var scopes []Scope |
| paddy@152 | 145 for rows.Next() { |
| paddy@152 | 146 var scope Scope |
| paddy@152 | 147 err = pan.Unmarshal(rows, &scope) |
| paddy@152 | 148 if err != nil { |
| paddy@152 | 149 return scopes, err |
| paddy@152 | 150 } |
| paddy@152 | 151 scopes = append(scopes, scope) |
| paddy@152 | 152 } |
| paddy@152 | 153 if err = rows.Err(); err != nil { |
| paddy@152 | 154 return scopes, err |
| paddy@152 | 155 } |
| paddy@152 | 156 return scopes, nil |
| paddy@152 | 157 } |