auth
2015-07-13
Parent:581c60f8dd23
auth/token_postgres.go
Add notes about model events. We need to sensibly trigger events about models, so I left some basic notes about triggering an event when a Profile is created.
| paddy@155 | 1 package auth |
| paddy@155 | 2 |
| paddy@155 | 3 import ( |
| paddy@155 | 4 "code.secondbit.org/uuid.hg" |
| paddy@155 | 5 |
| paddy@155 | 6 "github.com/lib/pq" |
| paddy@155 | 7 "github.com/secondbit/pan" |
| paddy@155 | 8 ) |
| paddy@155 | 9 |
| paddy@155 | 10 func (t Token) GetSQLTableName() string { |
| paddy@155 | 11 return "tokens" |
| paddy@155 | 12 } |
| paddy@155 | 13 |
| paddy@155 | 14 func (p *postgres) getTokenSQL(token string, refresh bool) *pan.Query { |
| paddy@155 | 15 var t Token |
| paddy@155 | 16 fields, _ := pan.GetFields(t) |
| paddy@155 | 17 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(t)) |
| paddy@155 | 18 query.IncludeWhere() |
| paddy@155 | 19 if !refresh { |
| paddy@155 | 20 query.Include(pan.GetUnquotedColumn(t, "AccessToken")+" = ?", token) |
| paddy@155 | 21 } else { |
| paddy@155 | 22 query.Include(pan.GetUnquotedColumn(t, "RefreshToken")+" = ?", token) |
| paddy@155 | 23 } |
| paddy@155 | 24 return query.FlushExpressions(" ") |
| paddy@155 | 25 } |
| paddy@155 | 26 |
| paddy@155 | 27 func (p *postgres) getToken(token string, refresh bool) (Token, error) { |
| paddy@155 | 28 query := p.getTokenSQL(token, refresh) |
| paddy@155 | 29 rows, err := p.db.Query(query.String(), query.Args...) |
| paddy@155 | 30 if err != nil { |
| paddy@155 | 31 return Token{}, err |
| paddy@155 | 32 } |
| paddy@155 | 33 var t Token |
| paddy@155 | 34 var found bool |
| paddy@155 | 35 for rows.Next() { |
| paddy@155 | 36 err := pan.Unmarshal(rows, &t) |
| paddy@155 | 37 if err != nil { |
| paddy@155 | 38 return t, err |
| paddy@155 | 39 } |
| paddy@155 | 40 found = true |
| paddy@155 | 41 } |
| paddy@155 | 42 if err = rows.Err(); err != nil { |
| paddy@155 | 43 return t, err |
| paddy@155 | 44 } |
| paddy@155 | 45 if !found { |
| paddy@155 | 46 return t, ErrTokenNotFound |
| paddy@155 | 47 } |
| paddy@155 | 48 return t, nil |
| paddy@155 | 49 } |
| paddy@155 | 50 |
| paddy@155 | 51 func (p *postgres) saveTokenSQL(token Token) *pan.Query { |
| paddy@155 | 52 fields, values := pan.GetFields(token) |
| paddy@155 | 53 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(token)) |
| paddy@155 | 54 query.Include("(" + pan.QueryList(fields) + ")") |
| paddy@155 | 55 query.Include("VALUES") |
| paddy@155 | 56 query.Include("("+pan.VariableList(len(values))+")", values...) |
| paddy@155 | 57 return query.FlushExpressions(" ") |
| paddy@155 | 58 } |
| paddy@155 | 59 |
| paddy@155 | 60 func (p *postgres) saveToken(token Token) error { |
| paddy@155 | 61 query := p.saveTokenSQL(token) |
| paddy@155 | 62 _, err := p.db.Exec(query.String(), query.Args...) |
| paddy@155 | 63 if e, ok := err.(*pq.Error); ok && e.Constraint == "tokens_pkey" { |
| paddy@155 | 64 err = ErrTokenAlreadyExists |
| paddy@155 | 65 } |
| paddy@155 | 66 if err != nil || len(token.Scopes) < 1 { |
| paddy@155 | 67 return err |
| paddy@155 | 68 } |
| paddy@155 | 69 return err |
| paddy@155 | 70 } |
| paddy@155 | 71 |
| paddy@168 | 72 func (p *postgres) revokeTokenSQL(token string) *pan.Query { |
| paddy@155 | 73 var t Token |
| paddy@155 | 74 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(t)+" SET ") |
| paddy@155 | 75 query.Include(pan.GetUnquotedColumn(t, "Revoked")+" = ?", true) |
| paddy@155 | 76 query.IncludeWhere() |
| paddy@168 | 77 query.Include(pan.GetUnquotedColumn(t, "RefreshToken")+" = ?", token) |
| paddy@155 | 78 return query.FlushExpressions(" ") |
| paddy@155 | 79 } |
| paddy@155 | 80 |
| paddy@168 | 81 func (p *postgres) revokeToken(token string) error { |
| paddy@168 | 82 query := p.revokeTokenSQL(token) |
| paddy@155 | 83 res, err := p.db.Exec(query.String(), query.Args...) |
| paddy@155 | 84 if err != nil { |
| paddy@155 | 85 return err |
| paddy@155 | 86 } |
| paddy@155 | 87 rows, err := res.RowsAffected() |
| paddy@155 | 88 if err != nil { |
| paddy@155 | 89 return err |
| paddy@155 | 90 } |
| paddy@155 | 91 if rows == 0 { |
| paddy@155 | 92 return ErrTokenNotFound |
| paddy@155 | 93 } |
| paddy@155 | 94 return nil |
| paddy@155 | 95 } |
| paddy@155 | 96 |
| paddy@162 | 97 func (p *postgres) revokeTokensByProfileIDSQL(profileID uuid.ID) *pan.Query { |
| paddy@162 | 98 var t Token |
| paddy@162 | 99 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(t)+" SET ") |
| paddy@162 | 100 query.Include(pan.GetUnquotedColumn(t, "Revoked")+" = ?", true) |
| paddy@162 | 101 query.IncludeWhere() |
| paddy@162 | 102 query.Include(pan.GetUnquotedColumn(t, "ProfileID")+" = ?", profileID) |
| paddy@162 | 103 return query.FlushExpressions(" ") |
| paddy@162 | 104 } |
| paddy@162 | 105 |
| paddy@162 | 106 func (p *postgres) revokeTokensByProfileID(profileID uuid.ID) error { |
| paddy@162 | 107 query := p.revokeTokensByProfileIDSQL(profileID) |
| paddy@162 | 108 res, err := p.db.Exec(query.String(), query.Args...) |
| paddy@162 | 109 if err != nil { |
| paddy@162 | 110 return err |
| paddy@162 | 111 } |
| paddy@162 | 112 rows, err := res.RowsAffected() |
| paddy@162 | 113 if err != nil { |
| paddy@162 | 114 return err |
| paddy@162 | 115 } |
| paddy@162 | 116 if rows == 0 { |
| paddy@162 | 117 return ErrProfileNotFound |
| paddy@162 | 118 } |
| paddy@162 | 119 return nil |
| paddy@162 | 120 } |
| paddy@162 | 121 |
| paddy@164 | 122 func (p *postgres) revokeTokensByClientIDSQL(clientID uuid.ID) *pan.Query { |
| paddy@164 | 123 var t Token |
| paddy@164 | 124 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(t)+" SET ") |
| paddy@164 | 125 query.Include(pan.GetUnquotedColumn(t, "Revoked")+" = ?", true) |
| paddy@164 | 126 query.IncludeWhere() |
| paddy@164 | 127 query.Include(pan.GetUnquotedColumn(t, "ClientID")+" = ?", clientID) |
| paddy@164 | 128 return query.FlushExpressions(" ") |
| paddy@164 | 129 } |
| paddy@164 | 130 |
| paddy@164 | 131 func (p *postgres) revokeTokensByClientID(clientID uuid.ID) error { |
| paddy@164 | 132 query := p.revokeTokensByClientIDSQL(clientID) |
| paddy@164 | 133 res, err := p.db.Exec(query.String(), query.Args...) |
| paddy@164 | 134 if err != nil { |
| paddy@164 | 135 return err |
| paddy@164 | 136 } |
| paddy@164 | 137 rows, err := res.RowsAffected() |
| paddy@164 | 138 if err != nil { |
| paddy@164 | 139 return err |
| paddy@164 | 140 } |
| paddy@164 | 141 if rows == 0 { |
| paddy@164 | 142 return ErrClientNotFound |
| paddy@164 | 143 } |
| paddy@164 | 144 return nil |
| paddy@164 | 145 } |
| paddy@164 | 146 |
| paddy@155 | 147 func (p *postgres) getTokensByProfileIDSQL(profileID uuid.ID, num, offset int) *pan.Query { |
| paddy@155 | 148 var token Token |
| paddy@155 | 149 fields, _ := pan.GetFields(token) |
| paddy@155 | 150 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(token)) |
| paddy@155 | 151 query.IncludeWhere() |
| paddy@155 | 152 query.Include(pan.GetUnquotedColumn(token, "ProfileID")+" = ?", profileID) |
| paddy@155 | 153 query.IncludeLimit(int64(num)) |
| paddy@155 | 154 query.IncludeOffset(int64(offset)) |
| paddy@155 | 155 return query.FlushExpressions(" ") |
| paddy@155 | 156 } |
| paddy@155 | 157 |
| paddy@155 | 158 func (p *postgres) getTokensByProfileID(profileID uuid.ID, num, offset int) ([]Token, error) { |
| paddy@155 | 159 query := p.getTokensByProfileIDSQL(profileID, num, offset) |
| paddy@155 | 160 rows, err := p.db.Query(query.String(), query.Args...) |
| paddy@155 | 161 if err != nil { |
| paddy@155 | 162 return []Token{}, err |
| paddy@155 | 163 } |
| paddy@155 | 164 var tokens []Token |
| paddy@155 | 165 var tokenIDs []string |
| paddy@155 | 166 for rows.Next() { |
| paddy@155 | 167 var token Token |
| paddy@155 | 168 err = pan.Unmarshal(rows, &token) |
| paddy@155 | 169 if err != nil { |
| paddy@155 | 170 return tokens, err |
| paddy@155 | 171 } |
| paddy@155 | 172 tokens = append(tokens, token) |
| paddy@155 | 173 tokenIDs = append(tokenIDs, token.AccessToken) |
| paddy@155 | 174 } |
| paddy@155 | 175 if err = rows.Err(); err != nil { |
| paddy@155 | 176 return tokens, err |
| paddy@155 | 177 } |
| paddy@155 | 178 return tokens, nil |
| paddy@155 | 179 } |