Break out scopes and events.
This repo has gotten unwieldy, and there are portions of it that need to be
imported by a large number of other packages.
For example, scopes will be used in almost every API we write. Rather than
importing the entirety of this codebase into every API we write, I've opted to
move the scope logic out into a scopes package, with a subpackage for the
defined types, which is all most projects actually want to import.
We also define some event type constants, and importing those shouldn't require
a project to import all our dependencies, either. So I made an events subpackage
that just holds those constants.
This package has become a little bit of a red-headed stepchild and is do for a
refactor, but I'm trying to put that off as long as I can.
The refactoring of our scopes stuff has left a bug wherein a token can be
granted for scopes that don't exist. I'm going to need to revisit that, and also
how to limit scopes to only be granted to the users that should be able to
request them. But that's a battle for another day.
4 "code.secondbit.org/uuid.hg"
6 "github.com/secondbit/pan"
9 func (c Client) GetSQLTableName() string {
13 func (e Endpoint) GetSQLTableName() string {
17 func (p *postgres) getClientSQL(id uuid.ID) *pan.Query {
19 fields, _ := pan.GetFields(client)
20 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(client))
22 query.Include(pan.GetUnquotedColumn(client, "ID")+" = ? AND "+pan.GetUnquotedColumn(client, "Deleted")+" = ?", id, false)
23 return query.FlushExpressions(" ")
26 func (p *postgres) getClient(id uuid.ID) (Client, error) {
27 query := p.getClientSQL(id)
28 rows, err := p.db.Query(query.String(), query.Args...)
35 err := pan.Unmarshal(rows, &client)
41 if err = rows.Err(); err != nil {
45 return client, ErrClientNotFound
50 func (p *postgres) saveClientSQL(client Client) *pan.Query {
51 fields, values := pan.GetFields(client)
52 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(client))
53 query.Include("(" + pan.QueryList(fields) + ")")
54 query.Include("VALUES")
55 query.Include("("+pan.VariableList(len(values))+")", values...)
56 return query.FlushExpressions(" ")
59 func (p *postgres) saveClient(client Client) error {
60 query := p.saveClientSQL(client)
61 _, err := p.db.Exec(query.String(), query.Args...)
62 if e, ok := err.(*pq.Error); ok && e.Constraint == "clients_pkey" {
63 err = ErrClientAlreadyExists
68 func (p *postgres) updateClientSQL(id uuid.ID, change ClientChange) *pan.Query {
70 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(client)+" SET ")
71 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Secret")+" = ?", change.Secret)
72 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "OwnerID")+" = ?", change.OwnerID)
73 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Name")+" = ?", change.Name)
74 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Logo")+" = ?", change.Logo)
75 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Website")+" = ?", change.Website)
76 query.IncludeIfNotNil(pan.GetUnquotedColumn(client, "Deleted")+" = ?", change.Deleted)
77 query.FlushExpressions(", ")
79 query.Include(pan.GetUnquotedColumn(client, "ID")+" = ?", id)
80 return query.FlushExpressions(" ")
83 func (p *postgres) updateClient(id uuid.ID, change ClientChange) error {
87 query := p.updateClientSQL(id, change)
88 _, err := p.db.Exec(query.String(), query.Args...)
92 func (p *postgres) listClientsByOwnerSQL(ownerID uuid.ID, num, offset int) *pan.Query {
94 fields, _ := pan.GetFields(client)
95 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(client))
97 query.Include(pan.GetUnquotedColumn(client, "OwnerID")+" = ? AND "+pan.GetUnquotedColumn(client, "Deleted")+" = ?", ownerID, false)
99 query.IncludeLimit(int64(num))
101 query.IncludeOffset(int64(offset))
102 return query.FlushExpressions(" ")
105 func (p *postgres) listClientsByOwner(ownerID uuid.ID, num, offset int) ([]Client, error) {
106 query := p.listClientsByOwnerSQL(ownerID, num, offset)
107 rows, err := p.db.Query(query.String(), query.Args...)
109 return []Client{}, err
114 err = pan.Unmarshal(rows, &client)
118 clients = append(clients, client)
120 if err = rows.Err(); err != nil {
126 func (p *postgres) deleteClientsByOwnerSQL(ownerID uuid.ID) *pan.Query {
128 query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(client)+" SET")
129 query.Include(pan.GetUnquotedColumn(client, "Deleted")+"= ?", true)
131 query.Include(pan.GetUnquotedColumn(client, "OwnerID")+" = ?", ownerID)
132 return query.FlushExpressions(" ")
135 func (p *postgres) deleteClientsByOwner(ownerID uuid.ID) error {
136 query := p.deleteClientsByOwnerSQL(ownerID)
137 _, err := p.db.Exec(query.String(), query.Args...)
141 func (p *postgres) addEndpointsSQL(endpoints []Endpoint) *pan.Query {
142 fields, _ := pan.GetFields(endpoints[0])
143 query := pan.New(pan.POSTGRES, "INSERT INTO "+pan.GetTableName(endpoints[0]))
144 query.Include("(" + pan.QueryList(fields) + ")")
145 query.Include("VALUES")
146 query.FlushExpressions(" ")
147 for _, endpoint := range endpoints {
148 _, values := pan.GetFields(endpoint)
149 query.Include("("+pan.VariableList(len(values))+")", values...)
151 return query.FlushExpressions(", ")
154 func (p *postgres) addEndpoints(endpoints []Endpoint) error {
155 if len(endpoints) < 1 {
158 query := p.addEndpointsSQL(endpoints)
159 _, err := p.db.Exec(query.String(), query.Args...)
160 if e, ok := err.(*pq.Error); ok && e.Constraint == "endpoints_pkey" {
161 return ErrEndpointAlreadyExists
166 func (p *postgres) removeEndpointSQL(client, endpoint uuid.ID) *pan.Query {
168 query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(e))
170 query.Include(pan.GetUnquotedColumn(e, "ID")+" = ? AND "+pan.GetUnquotedColumn(e, "ClientID")+" = ?", endpoint, client)
171 return query.FlushExpressions(" ")
174 func (p *postgres) removeEndpoint(client, endpoint uuid.ID) error {
175 query := p.removeEndpointSQL(client, endpoint)
176 res, err := p.db.Exec(query.String(), query.Args...)
180 rows, err := res.RowsAffected()
185 return ErrEndpointNotFound
190 func (p *postgres) removeEndpointsByClientIDSQL(client uuid.ID) *pan.Query {
192 query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(e))
194 query.Include(pan.GetUnquotedColumn(e, "ClientID")+" = ?", client)
195 return query.FlushExpressions(" ")
198 func (p *postgres) removeEndpointsByClientID(client uuid.ID) error {
199 query := p.removeEndpointsByClientIDSQL(client)
200 res, err := p.db.Exec(query.String(), query.Args...)
204 rows, err := res.RowsAffected()
209 return ErrClientNotFound
214 func (p *postgres) getEndpointSQL(client, endpoint uuid.ID) *pan.Query {
216 fields, _ := pan.GetFields(e)
217 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(e))
219 query.FlushExpressions(" ")
220 query.Include(pan.GetUnquotedColumn(e, "ID")+" = ?", endpoint)
221 query.Include(pan.GetUnquotedColumn(e, "ClientID")+" = ?", client)
222 return query.FlushExpressions(" AND ")
225 func (p *postgres) getEndpoint(client, endpoint uuid.ID) (Endpoint, error) {
226 query := p.getEndpointSQL(client, endpoint)
227 rows, err := p.db.Query(query.String(), query.Args...)
229 return Endpoint{}, err
234 err := pan.Unmarshal(rows, &e)
240 if err = rows.Err(); err != nil {
244 return e, ErrEndpointNotFound
249 func (p *postgres) checkEndpointSQL(client uuid.ID, endpoint string) *pan.Query {
251 fields, _ := pan.GetFields(e)
252 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(e))
254 query.FlushExpressions(" ")
255 query.Include(pan.GetUnquotedColumn(e, "ClientID")+" = ?", client)
256 query.Include(pan.GetUnquotedColumn(e, "NormalizedURI")+" = ?", endpoint)
257 return query.FlushExpressions(" AND ")
260 func (p *postgres) checkEndpoint(client uuid.ID, endpoint string) (bool, error) {
261 query := p.checkEndpointSQL(client, endpoint)
262 rows, err := p.db.Query(query.String(), query.Args...)
270 if err = rows.Err(); err != nil {
276 func (p *postgres) listEndpointsSQL(client uuid.ID, num, offset int) *pan.Query {
277 var endpoint Endpoint
278 fields, _ := pan.GetFields(endpoint)
279 query := pan.New(pan.POSTGRES, "SELECT "+pan.QueryList(fields)+" FROM "+pan.GetTableName(endpoint))
281 query.Include(pan.GetUnquotedColumn(endpoint, "ClientID")+" = ?", client)
282 query.IncludeLimit(int64(num))
283 query.IncludeOffset(int64(offset))
284 return query.FlushExpressions(" ")
287 func (p *postgres) listEndpoints(client uuid.ID, num, offset int) ([]Endpoint, error) {
288 query := p.listEndpointsSQL(client, num, offset)
289 rows, err := p.db.Query(query.String(), query.Args...)
291 return []Endpoint{}, err
293 var endpoints []Endpoint
295 var endpoint Endpoint
296 err = pan.Unmarshal(rows, &endpoint)
298 return endpoints, err
300 endpoints = append(endpoints, endpoint)
302 if err = rows.Err(); err != nil {
303 return endpoints, err
305 return endpoints, nil
308 func (p *postgres) countEndpointsSQL(client uuid.ID) *pan.Query {
309 var endpoint Endpoint
310 query := pan.New(pan.POSTGRES, "SELECT COUNT(*) FROM "+pan.GetTableName(endpoint))
312 query.Include(pan.GetUnquotedColumn(endpoint, "ClientID")+" = ?", client)
313 return query.FlushExpressions(" ")
316 func (p *postgres) countEndpoints(client uuid.ID) (int64, error) {
317 query := p.countEndpointsSQL(client)
318 rows, err := p.db.Query(query.String(), query.Args...)
324 err = pan.Unmarshal(rows, &results)
329 if err = rows.Err(); err != nil {