auth

Paddy 2015-05-17 Parent:cf1aef6eb81f

173:b0d1b3e39fc8 Go to Latest

auth/client_postgres.go

Make client use our auth(n/z) scheme. Our auth(n/z) scheme can be loosely defined as "encrypted tokens that nginx transforms into headers" and "scopes for bypassing ACL". Our Go client, which is what we'll be using to have services communicate with each other, follows this paradigm now by auto-injecting the headers we'll need to identify ourselves. This will work behind our firewall, but will be useless for the rest of the world, which will need to go through the nginx bastion that can strip the headers and replace them with the headers appropriate to the token attached to the request. This did involve setting a static client ID as the client for our email_verification listener. Ideally, this would cause Client registration (using that ID) when the listener starts up, ignoring ErrClientAlreadyExists. I don't want to have to write the code that will allow us to bypass the Client ACL properly right now, though, so we're just going to have to remember to manually create that Client. Or not. I don't think it will do any harm (outside the OAuth flow) to be using a Client ID that doesn't actually point to a Client. I just think it'd be good for record-keeping purposes.

History
paddy@151 1 package auth
paddy@151 2
paddy@151 3 import (
paddy@151 4 "code.secondbit.org/uuid.hg"
paddy@151 5 "github.com/lib/pq"
paddy@151 6 "github.com/secondbit/pan"
paddy@151 7 )
paddy@151 8
paddy@151 9 func (c Client) GetSQLTableName() string {
paddy@151 10 return "clients"
paddy@151 11 }
paddy@151 12
paddy@151 13 func (e Endpoint) GetSQLTableName() string {
paddy@151 14 return "endpoints"
paddy@151 15 }
paddy@151 16
paddy@151 17 func (p *postgres) getClientSQL(id uuid.ID) *pan.Query {
paddy@151 18 var client Client
paddy@151 19 fields, _ := pan.GetFields(client)
paddy@151 20 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(client))
paddy@151 21 query.IncludeWhere()
paddy@151 22 query.Include(pan.GetUnquotedColumn(client, "ID")+" = ? AND "+pan.GetUnquotedColumn(client, "Deleted")+" = ?", id, false)
paddy@151 23 return query.FlushExpressions(" ")
paddy@151 24 }
paddy@151 25
paddy@151 26 func (p *postgres) getClient(id uuid.ID) (Client, error) {
paddy@151 27 query := p.getClientSQL(id)
paddy@151 28 rows, err := p.db.Query(query.String(), query.Args...)
paddy@151 29 if err != nil {
paddy@151 30 return Client{}, err
paddy@151 31 }
paddy@151 32 var client Client
paddy@151 33 var found bool
paddy@151 34 for rows.Next() {
paddy@151 35 err := pan.Unmarshal(rows, &client)
paddy@151 36 if err != nil {
paddy@151 37 return client, err
paddy@151 38 }
paddy@151 39 found = true
paddy@151 40 }
paddy@151 41 if err = rows.Err(); err != nil {
paddy@151 42 return client, err
paddy@151 43 }
paddy@151 44 if !found {
paddy@151 45 return client, ErrClientNotFound
paddy@151 46 }
paddy@151 47 return client, nil
paddy@151 48 }
paddy@151 49
paddy@151 50 func (p *postgres) saveClientSQL(client Client) *pan.Query {
paddy@151 51 fields, values := pan.GetFields(client)
paddy@151 52 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(client))
paddy@151 53 query.Include("(" + pan.QueryList(fields) + ")")
paddy@151 54 query.Include("VALUES")
paddy@151 55 query.Include("("+pan.VariableList(len(values))+")", values...)
paddy@151 56 return query.FlushExpressions(" ")
paddy@151 57 }
paddy@151 58
paddy@151 59 func (p *postgres) saveClient(client Client) error {
paddy@151 60 query := p.saveClientSQL(client)
paddy@151 61 _, err := p.db.Exec(query.String(), query.Args...)
paddy@151 62 if e, ok := err.(*pq.Error); ok && e.Constraint == "clients_pkey" {
paddy@151 63 err = ErrClientAlreadyExists
paddy@151 64 }
paddy@151 65 return err
paddy@151 66 }
paddy@151 67
paddy@151 68 func (p *postgres) updateClientSQL(id uuid.ID, change ClientChange) *pan.Query {
paddy@151 69 var client Client
paddy@151 70 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(client)+" SET ")
paddy@151 71 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Secret")+" = ?", change.Secret)
paddy@151 72 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "OwnerID")+" = ?", change.OwnerID)
paddy@151 73 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Name")+" = ?", change.Name)
paddy@151 74 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Logo")+" = ?", change.Logo)
paddy@151 75 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Website")+" = ?", change.Website)
paddy@151 76 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Deleted")+" = ?", change.Deleted)
paddy@151 77 query.FlushExpressions(", ")
paddy@151 78 query.IncludeWhere()
paddy@151 79 query.Include(pan.GetUnquotedColumn(client, "ID")+" = ?", id)
paddy@151 80 return query.FlushExpressions(" ")
paddy@151 81 }
paddy@151 82
paddy@151 83 func (p *postgres) updateClient(id uuid.ID, change ClientChange) error {
paddy@151 84 if change.Empty() {
paddy@151 85 return nil
paddy@151 86 }
paddy@151 87 query := p.updateClientSQL(id, change)
paddy@151 88 _, err := p.db.Exec(query.String(), query.Args...)
paddy@151 89 return err
paddy@151 90 }
paddy@151 91
paddy@151 92 func (p *postgres) listClientsByOwnerSQL(ownerID uuid.ID, num, offset int) *pan.Query {
paddy@151 93 var client Client
paddy@151 94 fields, _ := pan.GetFields(client)
paddy@151 95 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(client))
paddy@151 96 query.IncludeWhere()
paddy@151 97 query.Include(pan.GetUnquotedColumn(client, "OwnerID")+" = ? AND "+pan.GetUnquotedColumn(client, "Deleted")+" = ?", ownerID, false)
paddy@164 98 if num > 0 {
paddy@164 99 query.IncludeLimit(int64(num))
paddy@164 100 }
paddy@151 101 query.IncludeOffset(int64(offset))
paddy@151 102 return query.FlushExpressions(" ")
paddy@151 103 }
paddy@151 104
paddy@151 105 func (p *postgres) listClientsByOwner(ownerID uuid.ID, num, offset int) ([]Client, error) {
paddy@151 106 query := p.listClientsByOwnerSQL(ownerID, num, offset)
paddy@151 107 rows, err := p.db.Query(query.String(), query.Args...)
paddy@151 108 if err != nil {
paddy@151 109 return []Client{}, err
paddy@151 110 }
paddy@151 111 var clients []Client
paddy@151 112 for rows.Next() {
paddy@151 113 var client Client
paddy@151 114 err = pan.Unmarshal(rows, &client)
paddy@151 115 if err != nil {
paddy@151 116 return clients, err
paddy@151 117 }
paddy@151 118 clients = append(clients, client)
paddy@151 119 }
paddy@151 120 if err = rows.Err(); err != nil {
paddy@151 121 return clients, err
paddy@151 122 }
paddy@151 123 return clients, nil
paddy@151 124 }
paddy@151 125
paddy@164 126 func (p *postgres) deleteClientsByOwnerSQL(ownerID uuid.ID) *pan.Query {
paddy@164 127 var client Client
paddy@164 128 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(client)+" SET")
paddy@164 129 query.Include(pan.GetUnquotedColumn(client, "Deleted")+"= ?", true)
paddy@164 130 query.IncludeWhere()
paddy@164 131 query.Include(pan.GetUnquotedColumn(client, "OwnerID")+" = ?", ownerID)
paddy@164 132 return query.FlushExpressions(" ")
paddy@164 133 }
paddy@164 134
paddy@164 135 func (p *postgres) deleteClientsByOwner(ownerID uuid.ID) error {
paddy@164 136 query := p.deleteClientsByOwnerSQL(ownerID)
paddy@164 137 _, err := p.db.Exec(query.String(), query.Args...)
paddy@164 138 return err
paddy@164 139 }
paddy@164 140
paddy@151 141 func (p *postgres) addEndpointsSQL(endpoints []Endpoint) *pan.Query {
paddy@151 142 fields, _ := pan.GetFields(endpoints[0])
paddy@151 143 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(endpoints[0]))
paddy@151 144 query.Include("(" + pan.QueryList(fields) + ")")
paddy@151 145 query.Include("VALUES")
paddy@151 146 query.FlushExpressions(" ")
paddy@151 147 for _, endpoint := range endpoints {
paddy@151 148 _, values := pan.GetFields(endpoint)
paddy@151 149 query.Include("("+pan.VariableList(len(values))+")", values...)
paddy@151 150 }
paddy@151 151 return query.FlushExpressions(", ")
paddy@151 152 }
paddy@151 153
paddy@151 154 func (p *postgres) addEndpoints(endpoints []Endpoint) error {
paddy@151 155 if len(endpoints) < 1 {
paddy@151 156 return nil
paddy@151 157 }
paddy@151 158 query := p.addEndpointsSQL(endpoints)
paddy@151 159 _, err := p.db.Exec(query.String(), query.Args...)
paddy@151 160 if e, ok := err.(*pq.Error); ok && e.Constraint == "endpoints_pkey" {
paddy@151 161 return ErrEndpointAlreadyExists
paddy@151 162 }
paddy@151 163 return err
paddy@151 164 }
paddy@151 165
paddy@151 166 func (p *postgres) removeEndpointSQL(client, endpoint uuid.ID) *pan.Query {
paddy@151 167 var e Endpoint
paddy@151 168 query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(e))
paddy@151 169 query.IncludeWhere()
paddy@151 170 query.Include(pan.GetUnquotedColumn(e, "ID")+" = ? AND "+pan.GetUnquotedColumn(e, "ClientID")+" = ?", endpoint, client)
paddy@151 171 return query.FlushExpressions(" ")
paddy@151 172 }
paddy@151 173
paddy@151 174 func (p *postgres) removeEndpoint(client, endpoint uuid.ID) error {
paddy@151 175 query := p.removeEndpointSQL(client, endpoint)
paddy@151 176 res, err := p.db.Exec(query.String(), query.Args...)
paddy@151 177 if err != nil {
paddy@151 178 return err
paddy@151 179 }
paddy@151 180 rows, err := res.RowsAffected()
paddy@151 181 if err != nil {
paddy@151 182 return err
paddy@151 183 }
paddy@151 184 if rows == 0 {
paddy@151 185 return ErrEndpointNotFound
paddy@151 186 }
paddy@151 187 return nil
paddy@151 188 }
paddy@151 189
paddy@164 190 func (p *postgres) removeEndpointsByClientIDSQL(client uuid.ID) *pan.Query {
paddy@164 191 var e Endpoint
paddy@164 192 query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(e))
paddy@164 193 query.IncludeWhere()
paddy@164 194 query.Include(pan.GetUnquotedColumn(e, "ClientID")+" = ?", client)
paddy@164 195 return query.FlushExpressions(" ")
paddy@164 196 }
paddy@164 197
paddy@164 198 func (p *postgres) removeEndpointsByClientID(client uuid.ID) error {
paddy@164 199 query := p.removeEndpointsByClientIDSQL(client)
paddy@164 200 res, err := p.db.Exec(query.String(), query.Args...)
paddy@164 201 if err != nil {
paddy@164 202 return err
paddy@164 203 }
paddy@164 204 rows, err := res.RowsAffected()
paddy@164 205 if err != nil {
paddy@164 206 return err
paddy@164 207 }
paddy@164 208 if rows == 0 {
paddy@164 209 return ErrClientNotFound
paddy@164 210 }
paddy@164 211 return nil
paddy@164 212 }
paddy@164 213
paddy@151 214 func (p *postgres) getEndpointSQL(client, endpoint uuid.ID) *pan.Query {
paddy@151 215 var e Endpoint
paddy@151 216 fields, _ := pan.GetFields(e)
paddy@151 217 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(e))
paddy@151 218 query.IncludeWhere()
paddy@151 219 query.FlushExpressions(" ")
paddy@151 220 query.Include(pan.GetUnquotedColumn(e, "ID")+" = ?", endpoint)
paddy@151 221 query.Include(pan.GetUnquotedColumn(e, "ClientID")+" = ?", client)
paddy@151 222 return query.FlushExpressions(" AND ")
paddy@151 223 }
paddy@151 224
paddy@151 225 func (p *postgres) getEndpoint(client, endpoint uuid.ID) (Endpoint, error) {
paddy@151 226 query := p.getEndpointSQL(client, endpoint)
paddy@151 227 rows, err := p.db.Query(query.String(), query.Args...)
paddy@151 228 if err != nil {
paddy@151 229 return Endpoint{}, err
paddy@151 230 }
paddy@151 231 var e Endpoint
paddy@151 232 var found bool
paddy@151 233 for rows.Next() {
paddy@151 234 err := pan.Unmarshal(rows, &e)
paddy@151 235 if err != nil {
paddy@151 236 return e, err
paddy@151 237 }
paddy@151 238 found = true
paddy@151 239 }
paddy@151 240 if err = rows.Err(); err != nil {
paddy@151 241 return e, err
paddy@151 242 }
paddy@151 243 if !found {
paddy@151 244 return e, ErrEndpointNotFound
paddy@151 245 }
paddy@151 246 return e, nil
paddy@151 247 }
paddy@151 248
paddy@151 249 func (p *postgres) checkEndpointSQL(client uuid.ID, endpoint string) *pan.Query {
paddy@151 250 var e Endpoint
paddy@151 251 fields, _ := pan.GetFields(e)
paddy@151 252 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(e))
paddy@151 253 query.IncludeWhere()
paddy@151 254 query.FlushExpressions(" ")
paddy@151 255 query.Include(pan.GetUnquotedColumn(e, "ClientID")+" = ?", client)
paddy@151 256 query.Include(pan.GetUnquotedColumn(e, "NormalizedURI")+" = ?", endpoint)
paddy@151 257 return query.FlushExpressions(" AND ")
paddy@151 258 }
paddy@151 259
paddy@151 260 func (p *postgres) checkEndpoint(client uuid.ID, endpoint string) (bool, error) {
paddy@151 261 query := p.checkEndpointSQL(client, endpoint)
paddy@151 262 rows, err := p.db.Query(query.String(), query.Args...)
paddy@151 263 if err != nil {
paddy@151 264 return false, err
paddy@151 265 }
paddy@151 266 var found bool
paddy@151 267 for rows.Next() {
paddy@151 268 found = true
paddy@151 269 }
paddy@151 270 if err = rows.Err(); err != nil {
paddy@151 271 return found, err
paddy@151 272 }
paddy@151 273 return found, nil
paddy@151 274 }
paddy@151 275
paddy@151 276 func (p *postgres) listEndpointsSQL(client uuid.ID, num, offset int) *pan.Query {
paddy@151 277 var endpoint Endpoint
paddy@151 278 fields, _ := pan.GetFields(endpoint)
paddy@151 279 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(endpoint))
paddy@151 280 query.IncludeWhere()
paddy@151 281 query.Include(pan.GetUnquotedColumn(endpoint, "ClientID")+" = ?", client)
paddy@151 282 query.IncludeLimit(int64(num))
paddy@151 283 query.IncludeOffset(int64(offset))
paddy@151 284 return query.FlushExpressions(" ")
paddy@151 285 }
paddy@151 286
paddy@151 287 func (p *postgres) listEndpoints(client uuid.ID, num, offset int) ([]Endpoint, error) {
paddy@151 288 query := p.listEndpointsSQL(client, num, offset)
paddy@151 289 rows, err := p.db.Query(query.String(), query.Args...)
paddy@151 290 if err != nil {
paddy@151 291 return []Endpoint{}, err
paddy@151 292 }
paddy@151 293 var endpoints []Endpoint
paddy@151 294 for rows.Next() {
paddy@151 295 var endpoint Endpoint
paddy@151 296 err = pan.Unmarshal(rows, &endpoint)
paddy@151 297 if err != nil {
paddy@151 298 return endpoints, err
paddy@151 299 }
paddy@151 300 endpoints = append(endpoints, endpoint)
paddy@151 301 }
paddy@151 302 if err = rows.Err(); err != nil {
paddy@151 303 return endpoints, err
paddy@151 304 }
paddy@151 305 return endpoints, nil
paddy@151 306 }
paddy@151 307
paddy@151 308 func (p *postgres) countEndpointsSQL(client uuid.ID) *pan.Query {
paddy@151 309 var endpoint Endpoint
paddy@151 310 query := pan.New(pan.POSTGRES, "SELECT COUNT(*) FROM "+pan.GetTableName(endpoint))
paddy@151 311 query.IncludeWhere()
paddy@151 312 query.Include(pan.GetUnquotedColumn(endpoint, "ClientID")+" = ?", client)
paddy@151 313 return query.FlushExpressions(" ")
paddy@151 314 }
paddy@151 315
paddy@151 316 func (p *postgres) countEndpoints(client uuid.ID) (int64, error) {
paddy@151 317 query := p.countEndpointsSQL(client)
paddy@151 318 rows, err := p.db.Query(query.String(), query.Args...)
paddy@151 319 if err != nil {
paddy@151 320 return 0, err
paddy@151 321 }
paddy@151 322 var results int64
paddy@151 323 for rows.Next() {
paddy@151 324 err = pan.Unmarshal(rows, &results)
paddy@151 325 if err != nil {
paddy@151 326 return results, err
paddy@151 327 }
paddy@151 328 }
paddy@151 329 if err = rows.Err(); err != nil {
paddy@151 330 return results, err
paddy@151 331 }
paddy@151 332 return results, nil
paddy@151 333 }