auth
2015-06-29
Parent:cf1aef6eb81f
auth/client_postgres.go
Create Docker image for authd. Create a Dockerfile for authd, which will wrap the compiled Go binary up into a tiny little Docker image. Create an authd/build-docker.sh script that will build the statically-linked binary in a Docker container, so the authd Docker image can use it. We had to include ca-certificates.crt in the Dockerfile, as well, so we could communicate over SSL with things. A wrapper.sh file is included that will pull the JWT_SECRET environment variable out of a kubernetes secrets file, which is a handy wrapper to have. Finally, we added the authd/docker-authd binary to the .hgignore.
| 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 } |