auth

Paddy 2015-05-17 Parent:8ecb60d29b0d Child:0a2c3d677161

173:b0d1b3e39fc8 Go to Latest

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