auth

Paddy 2015-04-11 Parent:849f3820b164 Child:73e12d5a1124

162:6f473576c6ae Browse Files

Clean up sessions and tokens after Profile is deleted. Add a terminateSessionsByProfile method to our sessionStore to mark Sessions associated with a Profile as inactive. Implement memstore and postgres implementations of the terminateSessionsByProfile method. Add a TerminateSessionsByProfile wrapper method to Context. Add a revokeTokensByProfileID method to our tokenStore to mark Tokens associated with a Profile as revoked. Implement memstore and postgres implementation of the revokeTokensByProfileID method. Add a RevokeTokensByProfileID wrapper method to Context. Call our RevokeTokensByProfileID and TerminateSessionsByProfile methods after a Profile is deleted, to clean up the Tokens and Sessions associated with it.

context.go profile.go session.go session_postgres.go token.go token_postgres.go

     1.1 --- a/context.go	Sat Apr 11 17:58:15 2015 -0400
     1.2 +++ b/context.go	Sat Apr 11 19:07:26 2015 -0400
     1.3 @@ -328,6 +328,15 @@
     1.4  	return c.tokens.revokeToken(token, refresh)
     1.5  }
     1.6  
     1.7 +// RevokeTokensByProfileID revokes the Tokens associated with the Profile identified by the passed ID in
     1.8 +// the tokenStore associated with the Context.
     1.9 +func (c Context) RevokeTokensByProfileID(profileID uuid.ID) error {
    1.10 +	if c.tokens == nil {
    1.11 +		return ErrNoTokenStore
    1.12 +	}
    1.13 +	return c.tokens.revokeTokensByProfileID(profileID)
    1.14 +}
    1.15 +
    1.16  // GetTokensByProfileID returns a slice of up to num Tokens with a ProfileID that matches the specified
    1.17  // profileID from the tokenStore associated with the Context, skipping offset Tokens.
    1.18  func (c Context) GetTokensByProfileID(profileID uuid.ID, num, offset int) ([]Token, error) {
    1.19 @@ -362,6 +371,15 @@
    1.20  	return c.sessions.terminateSession(id)
    1.21  }
    1.22  
    1.23 +// TerminateSessionsByProfile sets the Sessions associated with the passed Profile ID as inactive in the
    1.24 +// sessionStore associated with the Context.
    1.25 +func (c Context) TerminateSessionsByProfile(profile uuid.ID) error {
    1.26 +	if c.sessions == nil {
    1.27 +		return ErrNoSessionStore
    1.28 +	}
    1.29 +	return c.sessions.terminateSessionsByProfile(profile)
    1.30 +}
    1.31 +
    1.32  // RemoveSession removes the Session identified by the passed ID from the sessionStore associated with
    1.33  // the Context.
    1.34  func (c Context) RemoveSession(id string) error {
     2.1 --- a/profile.go	Sat Apr 11 17:58:15 2015 -0400
     2.2 +++ b/profile.go	Sat Apr 11 19:07:26 2015 -0400
     2.3 @@ -432,9 +432,16 @@
     2.4  	if err != nil {
     2.5  		log.Printf("Error removing logins from profile %s: %+v\n", profile, err)
     2.6  	}
     2.7 -	// BUG(paddy): need to terminate all sessions associated with the Profile
     2.8 -	// BUG(paddy): need to invalidate all tokens associated with the Profile
     2.9 +	err = context.TerminateSessionsByProfile(profile)
    2.10 +	if err != nil {
    2.11 +		log.Printf("Error terminating sessions associated with profile %s: %+v\n", profile, err)
    2.12 +	}
    2.13 +	err = context.RevokeTokensByProfileID(profile)
    2.14 +	if err != nil {
    2.15 +		log.Printf("Error revoking tokens associated with profile %s: %+v\n", profile, err)
    2.16 +	}
    2.17  	// BUG(paddy): need to delete all the grants associated with the Profile
    2.18 +	// BUG(paddy): need to delete all clients associated with the Profile
    2.19  }
    2.20  
    2.21  // RegisterProfileHandlers adds handlers to the passed router to handle the profile endpoints, like registration and user retrieval.
     3.1 --- a/session.go	Sat Apr 11 17:58:15 2015 -0400
     3.2 +++ b/session.go	Sat Apr 11 19:07:26 2015 -0400
     3.3 @@ -94,6 +94,7 @@
     3.4  	terminateSession(id string) error
     3.5  	removeSession(id string) error
     3.6  	listSessions(profile uuid.ID, before time.Time, num int64) ([]Session, error)
     3.7 +	terminateSessionsByProfile(profile uuid.ID) error
     3.8  }
     3.9  
    3.10  func (m *memstore) createSession(session Session) error {
    3.11 @@ -127,6 +128,23 @@
    3.12  	return nil
    3.13  }
    3.14  
    3.15 +func (m *memstore) terminateSessionsByProfile(profile uuid.ID) error {
    3.16 +	m.sessionLock.RLock()
    3.17 +	defer m.sessionLock.RUnlock()
    3.18 +	var found bool
    3.19 +	for _, session := range m.sessions {
    3.20 +		if profile.Equal(session.ProfileID) {
    3.21 +			session.Active = false
    3.22 +			m.sessions[session.ID] = session
    3.23 +			found = true
    3.24 +		}
    3.25 +	}
    3.26 +	if !found {
    3.27 +		return ErrProfileNotFound
    3.28 +	}
    3.29 +	return nil
    3.30 +}
    3.31 +
    3.32  func (m *memstore) removeSession(id string) error {
    3.33  	m.sessionLock.Lock()
    3.34  	defer m.sessionLock.Unlock()
     4.1 --- a/session_postgres.go	Sat Apr 11 17:58:15 2015 -0400
     4.2 +++ b/session_postgres.go	Sat Apr 11 19:07:26 2015 -0400
     4.3 @@ -89,6 +89,31 @@
     4.4  	return nil
     4.5  }
     4.6  
     4.7 +func (p *postgres) terminateSessionsByProfileSQL(profile uuid.ID) *pan.Query {
     4.8 +	var session Session
     4.9 +	query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(session)+" SET")
    4.10 +	query.Include(pan.GetUnquotedColumn(session, "Active")+" = ?", false)
    4.11 +	query.IncludeWhere()
    4.12 +	query.Include(pan.GetUnquotedColumn(session, "ProfileID")+" = ?", profile)
    4.13 +	return query.FlushExpressions(" ")
    4.14 +}
    4.15 +
    4.16 +func (p *postgres) terminateSessionsByProfile(profile uuid.ID) error {
    4.17 +	query := p.terminateSessionsByProfileSQL(profile)
    4.18 +	res, err := p.db.Exec(query.String(), query.Args...)
    4.19 +	if err != nil {
    4.20 +		return err
    4.21 +	}
    4.22 +	rows, err := res.RowsAffected()
    4.23 +	if err != nil {
    4.24 +		return err
    4.25 +	}
    4.26 +	if rows < 1 {
    4.27 +		return ErrProfileNotFound
    4.28 +	}
    4.29 +	return nil
    4.30 +}
    4.31 +
    4.32  func (p *postgres) removeSessionSQL(id string) *pan.Query {
    4.33  	var session Session
    4.34  	query := pan.New(pan.POSTGRES, "DELETE FROM "+pan.GetTableName(session))
     5.1 --- a/token.go	Sat Apr 11 17:58:15 2015 -0400
     5.2 +++ b/token.go	Sat Apr 11 19:07:26 2015 -0400
     5.3 @@ -55,6 +55,7 @@
     5.4  	saveToken(token Token) error
     5.5  	revokeToken(token string, refresh bool) error
     5.6  	getTokensByProfileID(profileID uuid.ID, num, offset int) ([]Token, error)
     5.7 +	revokeTokensByProfileID(profileID uuid.ID) error
     5.8  }
     5.9  
    5.10  func (m *memstore) getToken(token string, refresh bool) (Token, error) {
    5.11 @@ -116,6 +117,22 @@
    5.12  	return nil
    5.13  }
    5.14  
    5.15 +func (m *memstore) revokeTokensByProfileID(profileID uuid.ID) error {
    5.16 +	ids, err := m.lookupTokensByProfileID(profileID.String())
    5.17 +	if err != nil {
    5.18 +		return err
    5.19 +	}
    5.20 +	if len(ids) < 1 {
    5.21 +		return ErrProfileNotFound
    5.22 +	}
    5.23 +	m.tokenLock.Lock()
    5.24 +	defer m.tokenLock.Unlock()
    5.25 +	for _, id := range ids {
    5.26 +		delete(m.tokens, id)
    5.27 +	}
    5.28 +	return nil
    5.29 +}
    5.30 +
    5.31  func (m *memstore) getTokensByProfileID(profileID uuid.ID, num, offset int) ([]Token, error) {
    5.32  	ids, err := m.lookupTokensByProfileID(profileID.String())
    5.33  	if err != nil {
     6.1 --- a/token_postgres.go	Sat Apr 11 17:58:15 2015 -0400
     6.2 +++ b/token_postgres.go	Sat Apr 11 19:07:26 2015 -0400
     6.3 @@ -142,6 +142,31 @@
     6.4  	return nil
     6.5  }
     6.6  
     6.7 +func (p *postgres) revokeTokensByProfileIDSQL(profileID uuid.ID) *pan.Query {
     6.8 +	var t Token
     6.9 +	query := pan.New(pan.POSTGRES, "UPDATE "+pan.GetTableName(t)+" SET ")
    6.10 +	query.Include(pan.GetUnquotedColumn(t, "Revoked")+" = ?", true)
    6.11 +	query.IncludeWhere()
    6.12 +	query.Include(pan.GetUnquotedColumn(t, "ProfileID")+" = ?", profileID)
    6.13 +	return query.FlushExpressions(" ")
    6.14 +}
    6.15 +
    6.16 +func (p *postgres) revokeTokensByProfileID(profileID uuid.ID) error {
    6.17 +	query := p.revokeTokensByProfileIDSQL(profileID)
    6.18 +	res, err := p.db.Exec(query.String(), query.Args...)
    6.19 +	if err != nil {
    6.20 +		return err
    6.21 +	}
    6.22 +	rows, err := res.RowsAffected()
    6.23 +	if err != nil {
    6.24 +		return err
    6.25 +	}
    6.26 +	if rows == 0 {
    6.27 +		return ErrProfileNotFound
    6.28 +	}
    6.29 +	return nil
    6.30 +}
    6.31 +
    6.32  func (p *postgres) getTokensByProfileIDSQL(profileID uuid.ID, num, offset int) *pan.Query {
    6.33  	var token Token
    6.34  	fields, _ := pan.GetFields(token)