auth: Moved token and user to models package, added graphql endpoint to check token
the build failed
the build failed
This commit is contained in:
+12
-57
@@ -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) {
|
||||
|
||||
@@ -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")
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user