Skip to content

Commit

Permalink
Implemented the token flow and added test cases. (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
qqiao committed Apr 5, 2022
1 parent fde1d1e commit dfd1db9
Show file tree
Hide file tree
Showing 13 changed files with 453 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ jobs:

steps:
- uses: actions/checkout@v2
- run: go test -v ./...
- run: firebase emulators:exec --only firestore "go test -cover -v ./..."
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,4 @@ _testmain.go
*.exe
*.test
*.prof

/.idea/
*.log
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/webapp.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 83 additions & 8 deletions auth/rememberme/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

// Errors
var (
ErrTokenInvalid = errors.New("Token invalid")
ErrTokenInvalid = errors.New("token invalid")
)

// Token represents a rememberme token stored in the firestore.
Expand Down Expand Up @@ -46,7 +46,8 @@ func NewTokenManager(client *firestore.Client, collectionName string) TokenManag
//
// This function DELETES all matching tokens, regardless of whether the token
// has been revoked.
func (m TokenManager) PurgeTokens(ctx context.Context, username string, cutoff time.Time) <-chan error {
func (m TokenManager) PurgeTokens(ctx context.Context, username string,
cutoff time.Time) <-chan error {
errCh := make(chan error)

go func() {
Expand Down Expand Up @@ -96,13 +97,46 @@ func (m TokenManager) PurgeTokens(ctx context.Context, username string, cutoff t
// Although both revoking a token and removing a token will make the
// ValidateToken call fail, RevokeToken leaves the token stored in the data
// store.
func (m TokenManager) RevokeToken(ctx context.Context, token Token) <-chan error {
func (m TokenManager) RevokeToken(ctx context.Context,
token Token) <-chan error {
errCh := make(chan error)

go func() {
defer close(errCh)

// TODO implement this
if err := m.client.RunTransaction(ctx, func(ctx context.Context,
t *firestore.Transaction) error {
q := f.ApplyQuery(m.client.Collection(m.collectionName), f.Query{
Filters: []f.Filter{
{
Path: "Username",
Operator: "==",
Value: token.Username,
},
{
Path: "Identifier",
Operator: "==",
Value: token.Identifier,
},
},
})

iter := q.Documents(ctx)
defer iter.Stop()

if doc, err := iter.Next(); err != nil {
return err
} else {
m := doc.Data()
m["Revoked"] = true
if err = t.Set(doc.Ref, m); err != nil {
return err
}
return nil
}
}); err != nil {
errCh <- err
}
}()

return errCh
Expand All @@ -129,17 +163,58 @@ func (m TokenManager) SaveToken(ctx context.Context, token Token) <-chan error {

// ValidateToken validates if the given token is stored in the datastore.
//
// If the token is valid, that is the token existed and it has not been
// If the token is valid, that is the token existed, and it has not been
// revoked, its LastUsed will be updated to the current time to record the
// fact that the token has recently be used, otherwise a ErrTokenInvalid will
// fact that the token has recently been used, otherwise a ErrTokenInvalid will
// be returned.
func (m TokenManager) ValidateToken(ctx context.Context, token Token) <-chan error {
func (m TokenManager) ValidateToken(ctx context.Context,
token Token) <-chan error {
errCh := make(chan error)

go func() {
defer close(errCh)

// TODO implement this
if err := m.client.RunTransaction(ctx, func(ctx context.Context,
t *firestore.Transaction) error {
q := f.ApplyQuery(m.client.Collection(m.collectionName), f.Query{
Filters: []f.Filter{
{
Path: "Username",
Operator: "==",
Value: token.Username,
},
{
Path: "Identifier",
Operator: "==",
Value: token.Identifier,
},
{
Path: "Revoked",
Operator: "==",
Value: false,
},
},
})

iter := q.Documents(ctx)
defer iter.Stop()

if doc, err := iter.Next(); err != nil {
if err == iterator.Done {
return ErrTokenInvalid
}
return err
} else {
m := doc.Data()
m["LastUsed"] = time.Now().Unix()
if err = t.Set(doc.Ref, m); err != nil {
return err
}
return nil
}
}); err != nil {
errCh <- err
}
}()

return errCh
Expand Down
Loading

0 comments on commit dfd1db9

Please sign in to comment.