auth: Moved token and user to models package, added graphql endpoint to check token
the build failed

This commit is contained in:
2018-09-16 16:57:40 +02:00
parent 07b94b3cab
commit 2ab933149e
14 changed files with 206 additions and 120 deletions
+12 -57
View File
@@ -8,6 +8,8 @@ import (
"strings"
"time"
"git.aiterp.net/rpdata/api/models"
"git.aiterp.net/rpdata/api/models/users"
jwt "github.com/dgrijalva/jwt-go"
)
@@ -34,56 +36,9 @@ var ErrWrongPermissions = errors.New("User does not have these permissions")
// ErrDeletedUser is returned by CheckToken if the key can represent this user, but the user doesn't exist.
var ErrDeletedUser = errors.New("User was not found")
// A Token contains the parsed results from an bearer token. Its methods are safe to use with a nil receiver, but
// the userID should be checked.
type Token struct {
UserID string
Permissions []string
}
// Authenticated returns true if the token is non-nil and parsed
func (token *Token) Authenticated() bool {
return token != nil && token.UserID != ""
}
// Permitted returns true if the token is non-nil and has the given permission or the "admin" permission
func (token *Token) Permitted(permissions ...string) bool {
if token == nil {
return false
}
for _, tokenPermission := range token.Permissions {
if tokenPermission == "admin" {
return true
}
for _, permission := range permissions {
if permission == tokenPermission {
return true
}
}
}
return false
}
// PermittedUser checks the first permission if the user matches, the second otherwise. This is a common
// pattern.
func (token *Token) PermittedUser(userID, permissionIfUser, permissionOtherwise string) bool {
if token == nil {
return false
}
if token.UserID == userID {
return token.Permitted(permissionIfUser)
}
return token.Permitted(permissionOtherwise)
}
// TokenFromContext gets the token from context.
func TokenFromContext(ctx context.Context) *Token {
token, ok := ctx.Value(contextKey).(*Token)
func TokenFromContext(ctx context.Context) *models.Token {
token, ok := ctx.Value(contextKey).(*models.Token)
if !ok {
return nil
}
@@ -112,7 +67,7 @@ func RequestWithToken(r *http.Request) *http.Request {
}
// CheckToken reads the token string and returns a token if everything is kosher.
func CheckToken(tokenString string) (token Token, err error) {
func CheckToken(tokenString string) (token models.Token, err error) {
var key Key
jwtToken, err := jwt.Parse(tokenString, func(jwtToken *jwt.Token) (interface{}, error) {
@@ -133,21 +88,21 @@ func CheckToken(tokenString string) (token Token, err error) {
return []byte(key.Secret), nil
})
if err != nil {
return Token{}, err
return models.Token{}, err
}
userid, permissions, err := parseClaims(jwtToken.Claims)
if err != nil {
return Token{}, err
return models.Token{}, err
}
if !key.ValidForUser(userid) {
return Token{}, ErrWrongUser
return models.Token{}, ErrWrongUser
}
user, err := FindUser(userid)
user, err := users.Ensure(userid)
if err != nil {
return Token{}, ErrDeletedUser
return models.Token{}, ErrDeletedUser
}
for _, permission := range permissions {
@@ -161,11 +116,11 @@ func CheckToken(tokenString string) (token Token, err error) {
}
if !found {
return Token{}, ErrWrongPermissions
return models.Token{}, ErrWrongPermissions
}
}
return Token{UserID: token.UserID, Permissions: permissions}, nil
return models.Token{UserID: user.ID, Permissions: permissions}, nil
}
func parseClaims(jwtClaims jwt.Claims) (userid string, permissions []string, err error) {
-63
View File
@@ -1,63 +0,0 @@
package auth
import (
"git.aiterp.net/rpdata/api/internal/store"
"github.com/globalsign/mgo"
)
var userCollection *mgo.Collection
// A User represents user information about a user that has logged in.
type User struct {
ID string `bson:"_id" json:"id"`
Nick string `bson:"nick,omitempty" json:"nick,omitempty"`
Permissions []string `bson:"permissions" json:"permissions"`
}
// Permitted returns true if either of the permissions can be found
//
// `token.UserID == page.Author || token.Permitted("story.edit")`
func (user *User) Permitted(permissions ...string) bool {
for i := range permissions {
for j := range user.Permissions {
if permissions[i] == user.Permissions[j] {
return true
}
}
}
return false
}
// FindUser finds a user by userid
func FindUser(userid string) (User, error) {
user := User{}
err := userCollection.FindId(userid).One(&user)
if err == mgo.ErrNotFound {
user := User{
ID: userid,
Nick: "",
Permissions: []string{
"member",
"log.edit",
"post.edit",
"post.move",
"file.upload",
},
}
err := userCollection.Insert(user)
if err != nil {
return User{}, err
}
}
return user, err
}
func init() {
store.HandleInit(func(db *mgo.Database) {
userCollection = db.C("core.users")
})
}