auth

Paddy 2014-12-14 Parent:e57a57a944c4 Child:c03b5eb3179e

102:267483f168b5 Go to Latest

auth/context.go

Require config.Init in Context, add comment. Add comment to config.Init explaining what it is, to make golint happy. Create an ErrConfigNotInitialized error to use when a Config object is used to create a Context before it is initialized. Check for Config initialization in NewContext and throw ErrConfigNotInitialized if the Config hasn't been initialized.

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@50 10 "code.secondbit.org/uuid"
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@87 17 template *template.Template
paddy@87 18 loginURI *url.URL
paddy@87 19 clients clientStore
paddy@87 20 authCodes authorizationCodeStore
paddy@87 21 profiles profileStore
paddy@87 22 tokens tokenStore
paddy@87 23 sessions sessionStore
paddy@96 24 config Config
paddy@96 25 }
paddy@96 26
paddy@96 27 // NewContext takes a Config instance and uses it to bootstrap a Context
paddy@96 28 // using the information provided in the Config variable.
paddy@96 29 func NewContext(config Config) (Context, error) {
paddy@102 30 if config.iterations == 0 {
paddy@102 31 return Context{}, ErrConfigNotInitialized
paddy@102 32 }
paddy@96 33 context := Context{
paddy@96 34 clients: config.ClientStore,
paddy@96 35 authCodes: config.AuthCodeStore,
paddy@96 36 profiles: config.ProfileStore,
paddy@96 37 tokens: config.TokenStore,
paddy@96 38 sessions: config.SessionStore,
paddy@96 39 template: config.Template,
paddy@96 40 config: config,
paddy@96 41 }
paddy@96 42 var err error
paddy@96 43 context.loginURI, err = url.Parse(config.LoginURI)
paddy@96 44 if err != nil {
paddy@96 45 log.Println(err)
paddy@96 46 return Context{}, ErrInvalidLoginURI
paddy@96 47 }
paddy@96 48 return context, nil
paddy@50 49 }
paddy@50 50
paddy@57 51 // Render uses the HTML templates associated with the Context to render the
paddy@57 52 // template specified by name to out using data to fill any template variables.
paddy@55 53 func (c Context) Render(out io.Writer, name string, data interface{}) {
paddy@50 54 if c.template == nil {
paddy@57 55 log.Println("No template set on Context, can't render anything!")
paddy@57 56 return
paddy@50 57 }
paddy@55 58 err := c.template.ExecuteTemplate(out, name, data)
paddy@55 59 if err != nil {
paddy@55 60 log.Println("Error executing template", name, ":", err)
paddy@55 61 }
paddy@50 62 }
paddy@50 63
paddy@57 64 // GetClient returns a single Client by its ID from the
paddy@57 65 // clientStore associated with the Context.
paddy@50 66 func (c Context) GetClient(id uuid.ID) (Client, error) {
paddy@50 67 if c.clients == nil {
paddy@50 68 return Client{}, ErrNoClientStore
paddy@50 69 }
paddy@57 70 return c.clients.getClient(id)
paddy@50 71 }
paddy@50 72
paddy@57 73 // SaveClient stores the passed Client in the clientStore
paddy@57 74 // associated with the Context.
paddy@50 75 func (c Context) SaveClient(client Client) error {
paddy@50 76 if c.clients == nil {
paddy@50 77 return ErrNoClientStore
paddy@50 78 }
paddy@57 79 return c.clients.saveClient(client)
paddy@50 80 }
paddy@50 81
paddy@57 82 // UpdateClient applies the specified ClientChange to the Client
paddy@57 83 // with the specified ID in the clientStore associated with the
paddy@57 84 // Context.
paddy@50 85 func (c Context) UpdateClient(id uuid.ID, change ClientChange) error {
paddy@50 86 if c.clients == nil {
paddy@50 87 return ErrNoClientStore
paddy@50 88 }
paddy@57 89 return c.clients.updateClient(id, change)
paddy@50 90 }
paddy@50 91
paddy@57 92 // DeleteClient removes the client with the specified ID from the
paddy@57 93 // clientStore associated with the Context.
paddy@50 94 func (c Context) DeleteClient(id uuid.ID) error {
paddy@50 95 if c.clients == nil {
paddy@50 96 return ErrNoClientStore
paddy@50 97 }
paddy@57 98 return c.clients.deleteClient(id)
paddy@50 99 }
paddy@50 100
paddy@57 101 // ListClientsByOwner returns a slice of up to num Clients, starting at offset (inclusive)
paddy@57 102 // that have the specified OwnerID in the clientStore associated with the Context.
paddy@50 103 func (c Context) ListClientsByOwner(ownerID uuid.ID, num, offset int) ([]Client, error) {
paddy@50 104 if c.clients == nil {
paddy@50 105 return []Client{}, ErrNoClientStore
paddy@50 106 }
paddy@57 107 return c.clients.listClientsByOwner(ownerID, num, offset)
paddy@50 108 }
paddy@50 109
paddy@57 110 // AddEndpoint stores the specified Endpoint in the clientStore associated with the Context,
paddy@57 111 // and associates the newly-stored Endpoint with the Client specified by the passed ID.
paddy@50 112 func (c Context) AddEndpoint(client uuid.ID, endpoint Endpoint) error {
paddy@50 113 if c.clients == nil {
paddy@50 114 return ErrNoClientStore
paddy@50 115 }
paddy@57 116 return c.clients.addEndpoint(client, endpoint)
paddy@50 117 }
paddy@50 118
paddy@57 119 // RemoveEndpoint deletes the Endpoint with the specified ID from the clientStore associated
paddy@57 120 // with the Context, and disassociates the Endpoint from the specified Client.
paddy@50 121 func (c Context) RemoveEndpoint(client, endpoint uuid.ID) error {
paddy@50 122 if c.clients == nil {
paddy@50 123 return ErrNoClientStore
paddy@50 124 }
paddy@57 125 return c.clients.removeEndpoint(client, endpoint)
paddy@50 126 }
paddy@50 127
paddy@57 128 // CheckEndpoint finds Endpoints in the clientStore associated with the Context that belong
paddy@58 129 // to the Client specified by the passed ID and match the URI passed. URI matches must be
paddy@58 130 // performed according to RFC 3986 Section 6.
paddy@58 131 func (c Context) CheckEndpoint(client uuid.ID, URI string) (bool, error) {
paddy@50 132 if c.clients == nil {
paddy@50 133 return false, ErrNoClientStore
paddy@50 134 }
paddy@58 135 return c.clients.checkEndpoint(client, URI)
paddy@50 136 }
paddy@50 137
paddy@57 138 // ListEndpoints finds Endpoints in the clientStore associated with the Context that belong
paddy@57 139 // to the Client specified by the passed ID. It returns up to num endpoints, starting at offset,
paddy@57 140 // exclusive.
paddy@50 141 func (c Context) ListEndpoints(client uuid.ID, num, offset int) ([]Endpoint, error) {
paddy@50 142 if c.clients == nil {
paddy@50 143 return []Endpoint{}, ErrNoClientStore
paddy@50 144 }
paddy@57 145 return c.clients.listEndpoints(client, num, offset)
paddy@50 146 }
paddy@50 147
paddy@57 148 // CountEndpoints returns the number of Endpoints the are associated with the Client specified by the
paddy@57 149 // passed ID in the clientStore associated with the Context.
paddy@55 150 func (c Context) CountEndpoints(client uuid.ID) (int64, error) {
paddy@55 151 if c.clients == nil {
paddy@55 152 return 0, ErrNoClientStore
paddy@55 153 }
paddy@57 154 return c.clients.countEndpoints(client)
paddy@55 155 }
paddy@55 156
paddy@87 157 // GetAuthorizationCode returns the AuthorizationCode specified by the provided code from the authorizationCodeStore associated with the
paddy@57 158 // Context.
paddy@87 159 func (c Context) GetAuthorizationCode(code string) (AuthorizationCode, error) {
paddy@87 160 if c.authCodes == nil {
paddy@87 161 return AuthorizationCode{}, ErrNoAuthorizationCodeStore
paddy@50 162 }
paddy@87 163 return c.authCodes.getAuthorizationCode(code)
paddy@50 164 }
paddy@50 165
paddy@87 166 // SaveAuthorizationCode stores the passed AuthorizationCode in the authorizationCodeStore associated with the Context.
paddy@87 167 func (c Context) SaveAuthorizationCode(authCode AuthorizationCode) error {
paddy@87 168 if c.authCodes == nil {
paddy@87 169 return ErrNoAuthorizationCodeStore
paddy@50 170 }
paddy@87 171 return c.authCodes.saveAuthorizationCode(authCode)
paddy@50 172 }
paddy@50 173
paddy@87 174 // DeleteAuthorizationCode removes the AuthorizationCode specified by the provided code from the authorizationCodeStore associated with
paddy@57 175 // the Context.
paddy@87 176 func (c Context) DeleteAuthorizationCode(code string) error {
paddy@87 177 if c.authCodes == nil {
paddy@87 178 return ErrNoAuthorizationCodeStore
paddy@50 179 }
paddy@87 180 return c.authCodes.deleteAuthorizationCode(code)
paddy@50 181 }
paddy@50 182
paddy@94 183 // UseAuthorizationCode marks the AuthorizationCode specified by the provided code as used in the authorizationCodeStore associated with
paddy@94 184 // the Context. Once an AuthorizationCode is marked as used, its Used property will be set to true when retrieved from the authorizationCodeStore.
paddy@94 185 func (c Context) UseAuthorizationCode(code string) error {
paddy@94 186 if c.authCodes == nil {
paddy@94 187 return ErrNoAuthorizationCodeStore
paddy@94 188 }
paddy@94 189 return c.authCodes.useAuthorizationCode(code)
paddy@94 190 }
paddy@94 191
paddy@57 192 // GetProfileByID returns the Profile specified by the provided ID from the profileStore associated with
paddy@57 193 // the Context.
paddy@50 194 func (c Context) GetProfileByID(id uuid.ID) (Profile, error) {
paddy@50 195 if c.profiles == nil {
paddy@50 196 return Profile{}, ErrNoProfileStore
paddy@50 197 }
paddy@57 198 return c.profiles.getProfileByID(id)
paddy@50 199 }
paddy@50 200
paddy@57 201 // GetProfileByLogin returns the Profile associated with the specified Login from the profileStore associated
paddy@57 202 // with the Context.
paddy@69 203 func (c Context) GetProfileByLogin(value string) (Profile, error) {
paddy@50 204 if c.profiles == nil {
paddy@50 205 return Profile{}, ErrNoProfileStore
paddy@50 206 }
paddy@69 207 return c.profiles.getProfileByLogin(value)
paddy@50 208 }
paddy@50 209
paddy@57 210 // SaveProfile inserts the passed Profile into the profileStore associated with the Context.
paddy@50 211 func (c Context) SaveProfile(profile Profile) error {
paddy@50 212 if c.profiles == nil {
paddy@50 213 return ErrNoProfileStore
paddy@50 214 }
paddy@57 215 return c.profiles.saveProfile(profile)
paddy@50 216 }
paddy@50 217
paddy@57 218 // UpdateProfile applies the supplied ProfileChange to the Profile that matches the specified ID
paddy@57 219 // in the profileStore associated with the Context.
paddy@50 220 func (c Context) UpdateProfile(id uuid.ID, change ProfileChange) error {
paddy@50 221 if c.profiles == nil {
paddy@50 222 return ErrNoProfileStore
paddy@50 223 }
paddy@57 224 return c.profiles.updateProfile(id, change)
paddy@50 225 }
paddy@50 226
paddy@57 227 // UpdateProfiles applies the supplied BulkProfileChange to every Profile that matches one of the
paddy@57 228 // specified IDs in the profileStore associated with the Context.
paddy@50 229 func (c Context) UpdateProfiles(ids []uuid.ID, change BulkProfileChange) error {
paddy@50 230 if c.profiles == nil {
paddy@50 231 return ErrNoProfileStore
paddy@50 232 }
paddy@57 233 return c.profiles.updateProfiles(ids, change)
paddy@50 234 }
paddy@50 235
paddy@57 236 // DeleteProfile removes the Profile specified by the passed ID from the profileStore associated
paddy@57 237 // with the Context.
paddy@50 238 func (c Context) DeleteProfile(id uuid.ID) error {
paddy@50 239 if c.profiles == nil {
paddy@50 240 return ErrNoProfileStore
paddy@50 241 }
paddy@57 242 return c.profiles.deleteProfile(id)
paddy@50 243 }
paddy@50 244
paddy@57 245 // AddLogin stores the passed Login in the profileStore associated with the Context. It also associates
paddy@57 246 // the newly-created Login with the Orofile in login.ProfileID.
paddy@50 247 func (c Context) AddLogin(login Login) error {
paddy@50 248 if c.profiles == nil {
paddy@50 249 return ErrNoProfileStore
paddy@50 250 }
paddy@57 251 return c.profiles.addLogin(login)
paddy@50 252 }
paddy@50 253
paddy@57 254 // RemoveLogin removes the specified Login from the profileStore associated with the Context, provided
paddy@57 255 // the Login has a ProfileID property that matches the profile ID passed in. It also disassociates the
paddy@57 256 // deleted Login from the Profile in login.ProfileID.
paddy@69 257 func (c Context) RemoveLogin(value string, profile uuid.ID) error {
paddy@50 258 if c.profiles == nil {
paddy@50 259 return ErrNoProfileStore
paddy@50 260 }
paddy@69 261 return c.profiles.removeLogin(value, profile)
paddy@50 262 }
paddy@50 263
paddy@57 264 // RecordLoginUse sets the LastUsed property of the Login specified in the profileStore associated with
paddy@57 265 // the Context to the value passed in as when.
paddy@69 266 func (c Context) RecordLoginUse(value string, when time.Time) error {
paddy@50 267 if c.profiles == nil {
paddy@50 268 return ErrNoProfileStore
paddy@50 269 }
paddy@69 270 return c.profiles.recordLoginUse(value, when)
paddy@50 271 }
paddy@50 272
paddy@57 273 // ListLogins returns a slice of up to num Logins associated with the specified Profile from the profileStore
paddy@57 274 // associated with the Context, skipping offset Profiles.
paddy@50 275 func (c Context) ListLogins(profile uuid.ID, num, offset int) ([]Login, error) {
paddy@50 276 if c.profiles == nil {
paddy@50 277 return []Login{}, ErrNoProfileStore
paddy@50 278 }
paddy@57 279 return c.profiles.listLogins(profile, num, offset)
paddy@50 280 }
paddy@50 281
paddy@57 282 // GetToken returns the Token specified from the tokenStore associated with the Context.
paddy@57 283 // If refresh is true, the token input should be compared against the refresh tokens, not the
paddy@57 284 // access tokens.
paddy@50 285 func (c Context) GetToken(token string, refresh bool) (Token, error) {
paddy@50 286 if c.tokens == nil {
paddy@50 287 return Token{}, ErrNoTokenStore
paddy@50 288 }
paddy@57 289 return c.tokens.getToken(token, refresh)
paddy@50 290 }
paddy@50 291
paddy@57 292 // SaveToken stores the passed Token in the tokenStore associated with the Context.
paddy@50 293 func (c Context) SaveToken(token Token) error {
paddy@50 294 if c.tokens == nil {
paddy@50 295 return ErrNoTokenStore
paddy@50 296 }
paddy@57 297 return c.tokens.saveToken(token)
paddy@50 298 }
paddy@50 299
paddy@57 300 // RemoveToken removes the Token identified by the passed token string from the tokenStore associated
paddy@57 301 // with the Context.
paddy@50 302 func (c Context) RemoveToken(token string) error {
paddy@50 303 if c.tokens == nil {
paddy@50 304 return ErrNoTokenStore
paddy@50 305 }
paddy@57 306 return c.tokens.removeToken(token)
paddy@50 307 }
paddy@50 308
paddy@93 309 // RevokeToken revokes the Token identfied by the passed token string from the tokenStore associated
paddy@93 310 // with the context. If refresh is true, the token input should be compared against the refresh tokens,
paddy@93 311 // not the access tokens.
paddy@93 312 func (c Context) RevokeToken(token string, refresh bool) error {
paddy@93 313 if c.tokens == nil {
paddy@93 314 return ErrNoTokenStore
paddy@93 315 }
paddy@93 316 return c.tokens.revokeToken(token, refresh)
paddy@93 317 }
paddy@93 318
paddy@57 319 // GetTokensByProfileID returns a slice of up to num Tokens with a ProfileID that matches the specified
paddy@57 320 // profileID from the tokenStore associated with the Context, skipping offset Tokens.
paddy@50 321 func (c Context) GetTokensByProfileID(profileID uuid.ID, num, offset int) ([]Token, error) {
paddy@50 322 if c.tokens == nil {
paddy@50 323 return []Token{}, ErrNoTokenStore
paddy@50 324 }
paddy@57 325 return c.tokens.getTokensByProfileID(profileID, num, offset)
paddy@50 326 }
paddy@69 327
paddy@69 328 // CreateSession stores the passed Session in the sessionStore associated with the Context.
paddy@69 329 func (c Context) CreateSession(session Session) error {
paddy@69 330 if c.sessions == nil {
paddy@69 331 return ErrNoSessionStore
paddy@69 332 }
paddy@69 333 return c.sessions.createSession(session)
paddy@69 334 }
paddy@69 335
paddy@69 336 // GetSession returns the Session specified from the sessionStore associated with the Context.
paddy@69 337 func (c Context) GetSession(id string) (Session, error) {
paddy@69 338 if c.sessions == nil {
paddy@69 339 return Session{}, ErrNoSessionStore
paddy@69 340 }
paddy@69 341 return c.sessions.getSession(id)
paddy@69 342 }
paddy@69 343
paddy@69 344 // RemoveSession removes the Session identified by the passed ID from the sessionStore associated with
paddy@69 345 // the Context.
paddy@69 346 func (c Context) RemoveSession(id string) error {
paddy@69 347 if c.sessions == nil {
paddy@69 348 return ErrNoSessionStore
paddy@69 349 }
paddy@69 350 return c.sessions.removeSession(id)
paddy@69 351 }
paddy@69 352
paddy@69 353 // ListSessions returns a slice of up to num Sessions from the sessionStore associated with the Context,
paddy@69 354 // ordered by the date they were created, descending. If before.IsZero() returns false, only Sessions
paddy@69 355 // that were created before that time will be returned. If profile is not nil, only Sessions belonging to
paddy@69 356 // that Profile will be returned.
paddy@69 357 func (c Context) ListSessions(profile uuid.ID, before time.Time, num int64) ([]Session, error) {
paddy@69 358 if c.sessions != nil {
paddy@69 359 return []Session{}, ErrNoSessionStore
paddy@69 360 }
paddy@69 361 return c.sessions.listSessions(profile, before, num)
paddy@69 362 }