auth
2015-12-14
Parent:b7e685839a1b
auth/context.go
Update nsq import path. go-nsq has moved to nsqio/go-nsq, so we need to update the import path appropriately.
1 package auth
3 import (
4 "html/template"
5 "io"
6 "log"
7 "net/url"
8 "time"
10 "code.secondbit.org/events.hg"
11 "code.secondbit.org/uuid.hg"
12 )
14 // Context wraps the different storage interfaces and should
15 // be used as the main point of interaction for the data storage
16 // layer.
17 type Context struct {
18 template *template.Template
19 loginURI *url.URL
20 clients clientStore
21 authCodes authorizationCodeStore
22 profiles profileStore
23 tokens tokenStore
24 sessions sessionStore
25 eventsPublisher events.Publisher
26 config Config
27 }
29 // NewContext takes a Config instance and uses it to bootstrap a Context
30 // using the information provided in the Config variable.
31 func NewContext(config Config) (Context, error) {
32 if config.iterations == 0 {
33 return Context{}, ErrConfigNotInitialized
34 }
35 context := Context{
36 clients: config.ClientStore,
37 authCodes: config.AuthCodeStore,
38 profiles: config.ProfileStore,
39 tokens: config.TokenStore,
40 sessions: config.SessionStore,
41 eventsPublisher: config.EventsPublisher,
42 template: config.Template,
43 config: config,
44 }
45 var err error
46 context.loginURI, err = url.Parse(config.LoginURI)
47 if err != nil {
48 log.Println(err)
49 return Context{}, ErrInvalidLoginURI
50 }
51 return context, nil
52 }
54 // Render uses the HTML templates associated with the Context to render the
55 // template specified by name to out using data to fill any template variables.
56 func (c Context) Render(out io.Writer, name string, data interface{}) {
57 if c.template == nil {
58 log.Println("No template set on Context, can't render anything!")
59 return
60 }
61 err := c.template.ExecuteTemplate(out, name, data)
62 if err != nil {
63 log.Println("Error executing template", name, ":", err)
64 }
65 }
67 // GetClient returns a single Client by its ID from the
68 // clientStore associated with the Context.
69 func (c Context) GetClient(id uuid.ID) (Client, error) {
70 if c.clients == nil {
71 return Client{}, ErrNoClientStore
72 }
73 return c.clients.getClient(id)
74 }
76 // SaveClient stores the passed Client in the clientStore
77 // associated with the Context.
78 func (c Context) SaveClient(client Client) error {
79 if c.clients == nil {
80 return ErrNoClientStore
81 }
82 return c.clients.saveClient(client)
83 }
85 // UpdateClient applies the specified ClientChange to the Client
86 // with the specified ID in the clientStore associated with the
87 // Context.
88 func (c Context) UpdateClient(id uuid.ID, change ClientChange) error {
89 if c.clients == nil {
90 return ErrNoClientStore
91 }
92 return c.clients.updateClient(id, change)
93 }
95 // ListClientsByOwner returns a slice of up to num Clients, starting at offset (inclusive)
96 // that have the specified OwnerID in the clientStore associated with the Context.
97 func (c Context) ListClientsByOwner(ownerID uuid.ID, num, offset int) ([]Client, error) {
98 if c.clients == nil {
99 return []Client{}, ErrNoClientStore
100 }
101 return c.clients.listClientsByOwner(ownerID, num, offset)
102 }
104 func (c Context) DeleteClientsByOwner(ownerID uuid.ID) error {
105 if c.clients == nil {
106 return ErrNoClientStore
107 }
108 return c.clients.deleteClientsByOwner(ownerID)
109 }
111 // AddEndpoints stores the specified Endpoints in the clientStore associated with the Context.
112 func (c Context) AddEndpoints(endpoints []Endpoint) error {
113 if c.clients == nil {
114 return ErrNoClientStore
115 }
116 for pos, endpoint := range endpoints {
117 u, err := normalizeURIString(endpoint.URI)
118 if err != nil {
119 return err
120 }
121 endpoint.NormalizedURI = u
122 endpoints[pos] = endpoint
123 }
124 return c.clients.addEndpoints(endpoints)
125 }
127 // GetEndpoint retrieves the Endpoint with the specified ID from the clientStore associated
128 // with the Context, if and only if it belongs to the Client with the specified ID.
129 func (c Context) GetEndpoint(client, endpoint uuid.ID) (Endpoint, error) {
130 if c.clients == nil {
131 return Endpoint{}, ErrNoClientStore
132 }
133 return c.clients.getEndpoint(client, endpoint)
134 }
136 // RemoveEndpoint deletes the Endpoint with the specified ID from the clientStore associated
137 // with the Context, and disassociates the Endpoint from the specified Client.
138 func (c Context) RemoveEndpoint(client, endpoint uuid.ID) error {
139 if c.clients == nil {
140 return ErrNoClientStore
141 }
142 return c.clients.removeEndpoint(client, endpoint)
143 }
145 // CheckEndpoint finds Endpoints in the clientStore associated with the Context that belong
146 // to the Client specified by the passed ID and match the URI passed. URI matches must be
147 // performed according to RFC 3986 Section 6.
148 func (c Context) CheckEndpoint(client uuid.ID, URI string) (bool, error) {
149 if c.clients == nil {
150 return false, ErrNoClientStore
151 }
152 u, err := normalizeURIString(URI)
153 if err != nil {
154 return false, err
155 }
156 return c.clients.checkEndpoint(client, u)
157 }
159 // ListEndpoints finds Endpoints in the clientStore associated with the Context that belong
160 // to the Client specified by the passed ID. It returns up to num endpoints, starting at offset,
161 // exclusive.
162 func (c Context) ListEndpoints(client uuid.ID, num, offset int) ([]Endpoint, error) {
163 if c.clients == nil {
164 return []Endpoint{}, ErrNoClientStore
165 }
166 return c.clients.listEndpoints(client, num, offset)
167 }
169 func (c Context) RemoveEndpointsByClientID(client uuid.ID) error {
170 if c.clients == nil {
171 return ErrNoClientStore
172 }
173 return c.clients.removeEndpointsByClientID(client)
174 }
176 // CountEndpoints returns the number of Endpoints the are associated with the Client specified by the
177 // passed ID in the clientStore associated with the Context.
178 func (c Context) CountEndpoints(client uuid.ID) (int64, error) {
179 if c.clients == nil {
180 return 0, ErrNoClientStore
181 }
182 return c.clients.countEndpoints(client)
183 }
185 // GetAuthorizationCode returns the AuthorizationCode specified by the provided code from the authorizationCodeStore associated with the
186 // Context.
187 func (c Context) GetAuthorizationCode(code string) (AuthorizationCode, error) {
188 if c.authCodes == nil {
189 return AuthorizationCode{}, ErrNoAuthorizationCodeStore
190 }
191 return c.authCodes.getAuthorizationCode(code)
192 }
194 // SaveAuthorizationCode stores the passed AuthorizationCode in the authorizationCodeStore associated with the Context.
195 func (c Context) SaveAuthorizationCode(authCode AuthorizationCode) error {
196 if c.authCodes == nil {
197 return ErrNoAuthorizationCodeStore
198 }
199 return c.authCodes.saveAuthorizationCode(authCode)
200 }
202 // DeleteAuthorizationCode removes the AuthorizationCode specified by the provided code from the authorizationCodeStore associated with
203 // the Context.
204 func (c Context) DeleteAuthorizationCode(code string) error {
205 if c.authCodes == nil {
206 return ErrNoAuthorizationCodeStore
207 }
208 return c.authCodes.deleteAuthorizationCode(code)
209 }
211 // DeleteAuthorizationCodesByProfileID removes the AuthorizationCodes associated with the Profile specified by the provided ID from the
212 // authorizationCodeStore associated with the Context.
213 func (c Context) DeleteAuthorizationCodesByProfileID(profileID uuid.ID) error {
214 if c.authCodes == nil {
215 return ErrNoAuthorizationCodeStore
216 }
217 return c.authCodes.deleteAuthorizationCodesByProfileID(profileID)
218 }
220 func (c Context) DeleteAuthorizationCodesByClientID(clientID uuid.ID) error {
221 if c.authCodes == nil {
222 return ErrNoAuthorizationCodeStore
223 }
224 return c.authCodes.deleteAuthorizationCodesByClientID(clientID)
225 }
227 // UseAuthorizationCode marks the AuthorizationCode specified by the provided code as used in the authorizationCodeStore associated with
228 // the Context. Once an AuthorizationCode is marked as used, its Used property will be set to true when retrieved from the authorizationCodeStore.
229 func (c Context) UseAuthorizationCode(code string) error {
230 if c.authCodes == nil {
231 return ErrNoAuthorizationCodeStore
232 }
233 return c.authCodes.useAuthorizationCode(code)
234 }
236 // GetProfileByID returns the Profile specified by the provided ID from the profileStore associated with
237 // the Context.
238 func (c Context) GetProfileByID(id uuid.ID) (Profile, error) {
239 if c.profiles == nil {
240 return Profile{}, ErrNoProfileStore
241 }
242 return c.profiles.getProfileByID(id)
243 }
245 // GetProfileByLogin returns the Profile associated with the specified Login from the profileStore associated
246 // with the Context.
247 func (c Context) GetProfileByLogin(value string) (Profile, error) {
248 if c.profiles == nil {
249 return Profile{}, ErrNoProfileStore
250 }
251 return c.profiles.getProfileByLogin(value)
252 }
254 // SaveProfile inserts the passed Profile into the profileStore associated with the Context.
255 func (c Context) SaveProfile(profile Profile) error {
256 if c.profiles == nil {
257 return ErrNoProfileStore
258 }
259 return c.profiles.saveProfile(profile)
260 }
262 // UpdateProfile applies the supplied ProfileChange to the Profile that matches the specified ID
263 // in the profileStore associated with the Context.
264 func (c Context) UpdateProfile(id uuid.ID, change ProfileChange) error {
265 if c.profiles == nil {
266 return ErrNoProfileStore
267 }
268 return c.profiles.updateProfile(id, change)
269 }
271 // UpdateProfiles applies the supplied BulkProfileChange to every Profile that matches one of the
272 // specified IDs in the profileStore associated with the Context.
273 func (c Context) UpdateProfiles(ids []uuid.ID, change BulkProfileChange) error {
274 if c.profiles == nil {
275 return ErrNoProfileStore
276 }
277 return c.profiles.updateProfiles(ids, change)
278 }
280 // DeleteProfile removes the specified Profile from the profileStore associated with the Context.
281 func (c Context) DeleteProfile(id uuid.ID) error {
282 if c.profiles == nil {
283 return ErrNoProfileStore
284 }
285 return c.profiles.deleteProfile(id)
286 }
288 // AddLogin stores the passed Login in the profileStore associated with the Context. It also associates
289 // the newly-created Login with the Orofile in login.ProfileID.
290 func (c Context) AddLogin(login Login) error {
291 if c.profiles == nil {
292 return ErrNoProfileStore
293 }
294 return c.profiles.addLogin(login)
295 }
297 // GetLogin returns the Login specified from the profileStore associated with the Context.
298 func (c Context) GetLogin(value string) (Login, error) {
299 if c.profiles == nil {
300 return Login{}, ErrNoProfileStore
301 }
302 return c.profiles.getLogin(value)
303 }
305 // RemoveLogin removes the specified Login from the profileStore associated with the Context, provided
306 // the Login has a ProfileID property that matches the profile ID passed in. It also disassociates the
307 // deleted Login from the Profile in login.ProfileID.
308 func (c Context) RemoveLogin(value string, profile uuid.ID) error {
309 if c.profiles == nil {
310 return ErrNoProfileStore
311 }
312 return c.profiles.removeLogin(value, profile)
313 }
315 // RemoveLoginsByProfile removes all Logins connected to the specified Profile in the profileStore
316 // associated with the Context and disassociates them from the Profile.
317 func (c Context) RemoveLoginsByProfile(profile uuid.ID) error {
318 if c.profiles == nil {
319 return ErrNoProfileStore
320 }
321 return c.profiles.removeLoginsByProfile(profile)
322 }
324 // RecordLoginUse sets the LastUsed property of the Login specified in the profileStore associated with
325 // the Context to the value passed in as when.
326 func (c Context) RecordLoginUse(value string, when time.Time) error {
327 if c.profiles == nil {
328 return ErrNoProfileStore
329 }
330 return c.profiles.recordLoginUse(value, when)
331 }
333 // VerifyLogin sets the Verified property of the Login specied to true in the profileStore associated with
334 // the Context, assuming the Verification property of the Login in the profileStore matches the verification
335 // passed. If the verifications do not match, an ErrLoginVerificationInvalid error is returned.
336 func (c Context) VerifyLogin(value, verification string) error {
337 if c.profiles == nil {
338 return ErrNoProfileStore
339 }
340 return c.profiles.verifyLogin(value, verification)
341 }
343 // ListLogins returns a slice of up to num Logins associated with the specified Profile from the profileStore
344 // associated with the Context, skipping offset Profiles.
345 func (c Context) ListLogins(profile uuid.ID, num, offset int) ([]Login, error) {
346 if c.profiles == nil {
347 return []Login{}, ErrNoProfileStore
348 }
349 return c.profiles.listLogins(profile, num, offset)
350 }
352 // GetToken returns the Token specified from the tokenStore associated with the Context.
353 // If refresh is true, the token input should be compared against the refresh tokens, not the
354 // access tokens.
355 func (c Context) GetToken(token string, refresh bool) (Token, error) {
356 if c.tokens == nil {
357 return Token{}, ErrNoTokenStore
358 }
359 return c.tokens.getToken(token, refresh)
360 }
362 // SaveToken stores the passed Token in the tokenStore associated with the Context.
363 func (c Context) SaveToken(token Token) error {
364 if c.tokens == nil {
365 return ErrNoTokenStore
366 }
367 return c.tokens.saveToken(token)
368 }
370 // RevokeToken revokes the Token identfied by the passed token string from the tokenStore associated
371 // with the context.
372 func (c Context) RevokeToken(token string) error {
373 if c.tokens == nil {
374 return ErrNoTokenStore
375 }
376 return c.tokens.revokeToken(token)
377 }
379 // RevokeTokensByProfileID revokes the Tokens associated with the Profile identified by the passed ID in
380 // the tokenStore associated with the Context.
381 func (c Context) RevokeTokensByProfileID(profileID uuid.ID) error {
382 if c.tokens == nil {
383 return ErrNoTokenStore
384 }
385 return c.tokens.revokeTokensByProfileID(profileID)
386 }
388 func (c Context) RevokeTokensByClientID(clientID uuid.ID) error {
389 if c.tokens == nil {
390 return ErrNoTokenStore
391 }
392 return c.tokens.revokeTokensByClientID(clientID)
393 }
395 // GetTokensByProfileID returns a slice of up to num Tokens with a ProfileID that matches the specified
396 // profileID from the tokenStore associated with the Context, skipping offset Tokens.
397 func (c Context) GetTokensByProfileID(profileID uuid.ID, num, offset int) ([]Token, error) {
398 if c.tokens == nil {
399 return []Token{}, ErrNoTokenStore
400 }
401 return c.tokens.getTokensByProfileID(profileID, num, offset)
402 }
404 // CreateSession stores the passed Session in the sessionStore associated with the Context.
405 func (c Context) CreateSession(session Session) error {
406 if c.sessions == nil {
407 return ErrNoSessionStore
408 }
409 return c.sessions.createSession(session)
410 }
412 // GetSession returns the Session specified from the sessionStore associated with the Context.
413 func (c Context) GetSession(id string) (Session, error) {
414 if c.sessions == nil {
415 return Session{}, ErrNoSessionStore
416 }
417 return c.sessions.getSession(id)
418 }
420 // TerminateSession sets the Session identified by the passed ID as inactive in the sessionStore assocated
421 // with the Context.
422 func (c Context) TerminateSession(id string) error {
423 if c.sessions == nil {
424 return ErrNoSessionStore
425 }
426 return c.sessions.terminateSession(id)
427 }
429 // TerminateSessionsByProfile sets the Sessions associated with the passed Profile ID as inactive in the
430 // sessionStore associated with the Context.
431 func (c Context) TerminateSessionsByProfile(profile uuid.ID) error {
432 if c.sessions == nil {
433 return ErrNoSessionStore
434 }
435 return c.sessions.terminateSessionsByProfile(profile)
436 }
438 // RemoveSession removes the Session identified by the passed ID from the sessionStore associated with
439 // the Context.
440 func (c Context) RemoveSession(id string) error {
441 if c.sessions == nil {
442 return ErrNoSessionStore
443 }
444 return c.sessions.removeSession(id)
445 }
447 // ListSessions returns a slice of up to num Sessions from the sessionStore associated with the Context,
448 // ordered by the date they were created, descending. If before.IsZero() returns false, only Sessions
449 // that were created before that time will be returned. If profile is not nil, only Sessions belonging to
450 // that Profile will be returned.
451 func (c Context) ListSessions(profile uuid.ID, before time.Time, num int64) ([]Session, error) {
452 if c.sessions == nil {
453 return []Session{}, ErrNoSessionStore
454 }
455 return c.sessions.listSessions(profile, before, num)
456 }
458 func (c Context) SendModelEvent(m events.Model, action string) error {
459 if c.eventsPublisher == nil {
460 log.Println("Event publisher not set!")
461 }
462 return events.PublishModelEvent(c.eventsPublisher, m, action)
463 }