diff --git a/cmd/root.go b/cmd/root.go
index 539b327..8b72e71 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -185,6 +185,6 @@ func initDB() {
globals.Logger.Println("Connecting to SQLite3", db_path)
globals.DB = database.InitSQLite3(db_path, globals.DB_schema, globals.Logger, []byte(viper.GetString("database.secret")), viper.GetString("database.initialAdmin.userName"), viper.GetString("database.initialAdmin.password"))
- globals.DB.CleanExpiredRefreshTokensTicker(time.Minute * 10)
- globals.DB.CleanRevokedAccessTokensTicker(time.Minute * 10)
+ globals.DB.CleanExpiredRefreshTokensTicker(time.Minute * 10) //TODO: add to viper
+ globals.DB.CleanRevokedAccessTokensTicker(time.Minute * 10) //TODO: add to viper
}
diff --git a/database/crypto_helpers.go b/database/crypto_helpers.go
index dc95a0e..9af8326 100644
--- a/database/crypto_helpers.go
+++ b/database/crypto_helpers.go
@@ -94,13 +94,13 @@ func (db CustomDB) GenerateHashFromPassword(password string) (passwordHash []byt
}
// GetRefreshTokenOwner takes a tokenId and return the owner's userId. Call before Update/Get/DeleteRefreshToken when not IS_admin.
-func (db CustomDB) GetRefreshTokenOwner(tokenId string) (string, error) {
+func (db CustomDB) GetRefreshTokenOwner(tokenId string) (ownerId string, err error) {
numTokenId, err := strconv.Atoi(tokenId)
if err != nil {
- return "", errors.New("invalid tokenId")
+ return "", errors.New("malformed refresh token Id")
}
- statement, err := db.connection.Prepare("SELECT FK_User_userId, FROM RefreshToken WHERE tokenId = ?")
+ statement, err := db.connection.Prepare("SELECT FK_User_userId FROM RefreshToken WHERE tokenId = ?")
if err != nil {
return "", err
}
@@ -108,6 +108,9 @@ func (db CustomDB) GetRefreshTokenOwner(tokenId string) (string, error) {
result := statement.QueryRow(numTokenId)
var owner string
if err := result.Scan(&owner); err != nil {
+ if err == sql.ErrNoRows {
+ return "", errors.New("invalid refresh token Id")
+ }
return "", err
}
@@ -118,7 +121,7 @@ func (db CustomDB) ValidateUserCredentials(userId *string, userName *string, pas
var result *sql.Row
var hash string
- if userId != nil { // user userId
+ if userId != nil { // use userId
numUserId, err := strconv.Atoi(*userId)
if err != nil {
return "", errors.New("userId not numeric")
@@ -131,9 +134,12 @@ func (db CustomDB) ValidateUserCredentials(userId *string, userName *string, pas
result = statement.QueryRow(numUserId)
if err := result.Scan(&hash); err != nil {
+ if err == sql.ErrNoRows {
+ return "", errors.New("invalid user Id")
+ }
return "", err
}
- } else if userName != nil { // user userName
+ } else if userName != nil { // use userName
statement, err := db.connection.Prepare("SELECT userId, passwordHash FROM User WHERE userName = ?")
if err != nil {
return "", err
@@ -141,6 +147,9 @@ func (db CustomDB) ValidateUserCredentials(userId *string, userName *string, pas
result = statement.QueryRow(&userName)
if err := result.Scan(&userId, &hash); err != nil {
+ if err == sql.ErrNoRows {
+ return "", errors.New("invalid user Id")
+ }
return "", err
}
} else {
@@ -184,6 +193,9 @@ func (db CustomDB) IssueRefreshToken(userId string, tokenName *string) (refreshT
result := statement.QueryRow(numUserId, encSelector, base64.RawURLEncoding.EncodeToString(tokenHash[:]), &tokenName)
if err := result.Scan(&tokenId, &expiryDate); err != nil {
+ if err == sql.ErrNoRows {
+ return nil, "", errors.New("failed to add new refresh token")
+ }
return nil, "", err
}
@@ -193,7 +205,7 @@ func (db CustomDB) IssueRefreshToken(userId string, tokenName *string) (refreshT
func (db CustomDB) GetRefreshToken(token *model.RefreshToken) (*model.RefreshToken, error) {
numTokenId, err := strconv.Atoi(token.ID)
if err != nil {
- return nil, errors.New("invalid tokenId")
+ return nil, errors.New("malformed refresh token Id")
}
statement, err := db.connection.Prepare("SELECT expiryDate, tokenName FROM RefreshToken WHERE tokenId = ?")
@@ -202,7 +214,10 @@ func (db CustomDB) GetRefreshToken(token *model.RefreshToken) (*model.RefreshTok
}
result := statement.QueryRow(numTokenId)
- if err := result.Scan(&token.ID, &token.ExpiryDate, &token.TokenName); err != nil {
+ if err := result.Scan(&token.ExpiryDate, &token.TokenName); err != nil {
+ if err == sql.ErrNoRows {
+ return nil, errors.New("invalid refresh token Id")
+ }
return nil, err
}
@@ -212,7 +227,7 @@ func (db CustomDB) GetRefreshToken(token *model.RefreshToken) (*model.RefreshTok
func (db CustomDB) GetRefreshTokensFrom(userId string) ([]*model.RefreshToken, error) {
numUserId, err := strconv.Atoi(userId)
if err != nil {
- return nil, errors.New("invalid userId")
+ return nil, errors.New("malformed userId")
}
statement, err := db.connection.Prepare("SELECT tokenId, expiaryDate, tokenName FROM RefreshToken WHERE FK_User_userId = ?")
if err != nil {
@@ -264,10 +279,10 @@ func (db CustomDB) GetAllRefreshTokens() ([]*model.RefreshToken, error) {
func (db CustomDB) UpdateRefreshToken(tokenId string, changes *model.UpdateRefreshToken) (*model.RefreshToken, error) {
numTokenId, err := strconv.Atoi(tokenId)
if err != nil {
- return nil, errors.New("invalid tokenId")
+ return nil, errors.New("malformed refresh token Id")
}
- statement, err := db.connection.Prepare("UPDATE AuthToken SET tokenName = ? WHERE tokenId = ?")
+ statement, err := db.connection.Prepare("UPDATE RefreshToken SET tokenName = ? WHERE tokenId = ?")
if err != nil {
return nil, err
}
@@ -300,7 +315,7 @@ func (db CustomDB) RevokeRefreshToken(tokenId string) (*string, error) {
// TODO: return string instead of *string
numTokenId, err := strconv.Atoi(tokenId)
if err != nil {
- return nil, errors.New("invalid tokenId")
+ return nil, errors.New("malformed refresh token Id")
}
statement, err := db.connection.Prepare("DELETE FROM RefreshToken WHERE tokenId = ? RETURNING FK_User_userId")
@@ -312,6 +327,9 @@ func (db CustomDB) RevokeRefreshToken(tokenId string) (*string, error) {
var userId string
if err := result.Scan(&userId); err != nil {
+ if err == sql.ErrNoRows {
+ return nil, errors.New("invalid refresh token Id")
+ }
return nil, err
}
@@ -321,7 +339,7 @@ func (db CustomDB) RevokeRefreshToken(tokenId string) (*string, error) {
// IssueAccessToken issues an access token if the passed refresh token is valid. Returned access token must be passed to SignAccessToken to be accepted.
func (db CustomDB) IssueAccessToken(refreshToken *RefreshToken) (*AccessToken, error) {
- statement, err := db.connection.Prepare("SELECT RefreshToken.tokenHash, RefreshToken.FK_User_userId, Role.IS_admin, ROLE.IS_userCreator FROM RefreshToken INNER JOIN R_User_Role ON RefreshToken.FK_User_userId = R_User_Role.FK_User_userId INNER JOIN Role ON R_User_Role.FK_Role_roleId = Role.roleId WHERE RefreshToken.selector = ? AND RefreshToken.expiryDate >= unixepoch('now')")
+ statement, err := db.connection.Prepare("SELECT tokenHash, FK_User_userId FROM RefreshToken WHERE selector = ? AND expiryDate >= unixepoch('now')")
if err != nil {
return nil, err
}
@@ -330,7 +348,15 @@ func (db CustomDB) IssueAccessToken(refreshToken *RefreshToken) (*AccessToken, e
var tokenHash string
var newAccessToken AccessToken
- if err := result.Scan(&tokenHash, &newAccessToken.UserId, &newAccessToken.IsAdmin, &newAccessToken.IsUserCreator); err != nil {
+ if err := result.Scan(&tokenHash, &newAccessToken.UserId); err != nil {
+ if err == sql.ErrNoRows {
+ return nil, errors.New("invalid refresh token selector")
+ }
+ return nil, err
+ }
+
+ newAccessToken.IsAdmin, newAccessToken.IsUserCreator, err = db.GetUserPermissions(newAccessToken.UserId)
+ if err != nil {
return nil, err
}
diff --git a/database/role.go b/database/role.go
index 1b6f0a0..4ca2005 100644
--- a/database/role.go
+++ b/database/role.go
@@ -17,6 +17,7 @@ along with this program. If not, see .
package database
import (
+ "database/sql"
"errors"
"strconv"
@@ -62,6 +63,9 @@ func (db CustomDB) GetRole(role *model.Role) (*model.Role, error) {
result := statement.QueryRow(id)
if err := result.Scan(&role.RoleName, &role.IsAdmin, &role.IsUserCreator); err != nil {
+ if err == sql.ErrNoRows {
+ return nil, errors.New("invalid role Id")
+ }
return nil, err
}
@@ -71,7 +75,7 @@ func (db CustomDB) GetRole(role *model.Role) (*model.Role, error) {
func (db CustomDB) GetRolesFrom(userId string) ([]*model.RelationUserRole, error) {
numUserId, err := strconv.Atoi(userId)
if err != nil {
- return nil, errors.New("invalid userId")
+ return nil, errors.New("malformed userId")
}
statement, err := db.connection.Prepare("SELECT Role.roleId, Role.roleName, Role.IS_admin, Role.IS_userCreator, R_User_Role.IS_roleManager FROM Role INNER JOIN R_User_Role ON R_User_Role.FK_Role_roleId = Role.roleId WHERE R_User_Role.FK_User_userId = ?")
if err != nil {
@@ -152,7 +156,7 @@ func (db CustomDB) UpdateRole(roleId string, changes *model.UpdateRole) (*model.
id, err := strconv.Atoi(roleId)
if err != nil {
- return nil, errors.New("invalid userId")
+ return nil, errors.New("malformed userId")
}
statement, err := db.connection.Prepare("UPDATE Role SET roleName = IFNULL(?, roleName), IS_admin = IFNULL(?, IS_admin), IS_userCreator = IFNULL(?, IS_userCreator) WHERE roleId = ?")
diff --git a/database/todo.go b/database/todo.go
index 262ba9d..3afccaa 100644
--- a/database/todo.go
+++ b/database/todo.go
@@ -17,6 +17,7 @@ along with this program. If not, see .
package database
import (
+ "database/sql"
"errors"
"strconv"
@@ -27,7 +28,7 @@ import (
func (db CustomDB) GetOwner(todoId string) (string, error) {
numTodoId, err := strconv.Atoi(todoId)
if err != nil {
- return "", errors.New("invalid todoId")
+ return "", errors.New("malformed todoId")
}
statement, err := db.connection.Prepare("SELECT FK_User_userId, FROM Todo WHERE todoId = ?")
@@ -38,6 +39,9 @@ func (db CustomDB) GetOwner(todoId string) (string, error) {
result := statement.QueryRow(numTodoId)
var owner string
if err := result.Scan(&owner); err != nil {
+ if err == sql.ErrNoRows {
+ return "", errors.New("invalid todo Id")
+ }
return "", err
}
@@ -48,7 +52,7 @@ func (db CustomDB) GetOwner(todoId string) (string, error) {
func (db CustomDB) GetTodo(todo *model.Todo) (*model.Todo, error) {
numTodoId, err := strconv.Atoi(todo.ID)
if err != nil {
- return nil, errors.New("invalid todoId")
+ return nil, errors.New("malformed todoId malformatted todoId")
}
statement, err := db.connection.Prepare("SELECT text, IS_done, FK_User_userId FROM Todo WHERE todoId = ?")
@@ -59,6 +63,9 @@ func (db CustomDB) GetTodo(todo *model.Todo) (*model.Todo, error) {
todo.User = &model.User{} // TODO: check if this overrides something
result := statement.QueryRow(numTodoId)
if err := result.Scan(&todo.Text, &todo.Done, &todo.User.ID); err != nil {
+ if err == sql.ErrNoRows {
+ return nil, errors.New("invalid todo Id")
+ }
return nil, err
}
@@ -69,7 +76,7 @@ func (db CustomDB) GetTodo(todo *model.Todo) (*model.Todo, error) {
func (db CustomDB) GetTodosFrom(user *model.User) ([]*model.Todo, error) {
id, err := strconv.Atoi(user.ID)
if err != nil {
- return nil, errors.New("invalid userId")
+ return nil, errors.New("malformed userId")
}
statement, err := db.connection.Prepare("SELECT todoId, text, IS_done FROM Todo WHERE FK_User_userId = ?")
if err != nil {
@@ -146,7 +153,7 @@ func (db CustomDB) UpdateTodo(todoId string, changes *model.UpdateTodo) (*model.
numTodoId, err := strconv.Atoi(todoId)
if err != nil {
- return nil, errors.New("invalid todoId")
+ return nil, errors.New("malformed todoId")
}
statement, err := db.connection.Prepare("UPDATE Todo SET text = IFNULL(?, text), IS_done = IFNULL(?, IS_done) WHERE todoId = ?")
@@ -174,7 +181,7 @@ func (db CustomDB) UpdateTodo(todoId string, changes *model.UpdateTodo) (*model.
func (db CustomDB) DeleteTodo(todoId string) (deletedTodoId *string, err error) {
numTodoId, err := strconv.Atoi(todoId)
if err != nil {
- return nil, errors.New("invalid todoId")
+ return nil, errors.New("malformed todoId")
}
statement, err := db.connection.Prepare("DELETE FROM Todo WHERE todoId = ?")
@@ -198,3 +205,27 @@ func (db CustomDB) DeleteTodo(todoId string) (deletedTodoId *string, err error)
return &todoId, nil
}
+
+// GetTodoOwner takes a *model.Todo with at least ID set and returns an *model.User with Id set to the todo's owner Id.
+func (db CustomDB) GetTodoOwner(todo *model.Todo) (owner *model.User, err error) {
+ numTodoId, err := strconv.Atoi(todo.ID)
+ if err != nil {
+ return nil, errors.New("malformed todoId")
+ }
+
+ statement, err := db.connection.Prepare("SELECT FK_User_userId FROM Todo WHERE todoId = ?")
+ if err != nil {
+ return nil, err
+ }
+
+ user := &model.User{} // TODO: check if this overrides something
+ result := statement.QueryRow(numTodoId)
+ if err := result.Scan(&user.ID); err != nil {
+ if err == sql.ErrNoRows {
+ return nil, errors.New("invalid todo Id")
+ }
+ return nil, err
+ }
+
+ return user, nil
+}
diff --git a/database/user.go b/database/user.go
index b1f72f4..99955c2 100644
--- a/database/user.go
+++ b/database/user.go
@@ -17,6 +17,7 @@ along with this program. If not, see .
package database
import (
+ "database/sql"
"errors"
"strconv"
"time"
@@ -68,7 +69,7 @@ func (db CustomDB) CreateUser(newUser model.NewUser) (*model.User, error) {
func (db CustomDB) GetUser(user *model.User) (*model.User, error) {
numUserId, err := strconv.Atoi(user.ID)
if err != nil {
- return nil, errors.New("invalid userId")
+ return nil, errors.New("malformed userId")
}
statement, err := db.connection.Prepare("SELECT userID, userName, fullName FROM User WHERE userId = ? OR userName = ?")
if err != nil {
@@ -77,6 +78,9 @@ func (db CustomDB) GetUser(user *model.User) (*model.User, error) {
result := statement.QueryRow(numUserId, user.UserName)
if err := result.Scan(&user.ID, &user.UserName, &user.FullName); err != nil {
+ if err == sql.ErrNoRows {
+ return nil, errors.New("invalid user Id")
+ }
return nil, err
}
@@ -108,24 +112,22 @@ func (db CustomDB) UpdateUser(userId string, changes *model.UpdateUser) (*model.
id, err := strconv.Atoi(userId)
if err != nil {
- return nil, errors.New("invalid userId")
+ return nil, errors.New("malformed userId")
}
- statement, err := db.connection.Prepare("UPDATE User SET userName = IFNULL(?, userName), fullName = IFNULL(NULLIF(?, ''), fullName), passwordHash = IFNULL(?, passwordHash) WHERE userId = ?")
+ statement, err := db.connection.Prepare("UPDATE User SET userName = IFNULL(?, userName), fullName = NULLIF(?, ''), passwordHash = IFNULL(?, passwordHash) WHERE userId = ?")
if err != nil {
return nil, err
}
- if *changes.UserName == "" { // interpret empty string as nil
- changes.UserName = nil
- } else {
+ if changes.UserName != nil && *changes.UserName != "" { // ignore empty string
if err := ValidateUserName(*changes.UserName); err != nil {
return nil, err
}
needAccessTokenRefresh = true
}
- if *changes.Password == "" { // interpret empty string as nil
+ if changes.Password == nil { // interpret empty string as nil
passwordHash = nil
} else {
if err := ValidatePassword(*changes.Password); err != nil {
@@ -188,7 +190,7 @@ func (db CustomDB) DeleteUser(userId string) (*string, error) {
func (db CustomDB) AddUserRole(userId string, roleId string, isRoleManager bool) (relationId string, err error) {
encUserId, err := strconv.Atoi(userId)
if err != nil {
- return "", errors.New("invalid userId")
+ return "", errors.New("malformed userId")
}
encRoleId, err := strconv.Atoi(roleId)
if err != nil {
@@ -226,7 +228,7 @@ func (db CustomDB) AddUserRole(userId string, roleId string, isRoleManager bool)
func (db CustomDB) UpdateUserRole(userId string, roleId string, isRoleManager bool) (relationId string, err error) {
encUserId, err := strconv.Atoi(userId)
if err != nil {
- return "", errors.New("invalid userId")
+ return "", errors.New("malformed userId")
}
encRoleId, err := strconv.Atoi(roleId)
if err != nil {
@@ -264,7 +266,7 @@ func (db CustomDB) UpdateUserRole(userId string, roleId string, isRoleManager bo
func (db CustomDB) RemoveUserRole(userId string, roleId string) (relationId string, err error) {
encUserId, err := strconv.Atoi(userId)
if err != nil {
- return "", errors.New("invalid userId")
+ return "", errors.New("malformed userId")
}
encRoleId, err := strconv.Atoi(roleId)
if err != nil {
@@ -293,3 +295,36 @@ func (db CustomDB) RemoveUserRole(userId string, roleId string) (relationId stri
RevokeAccessToken(&AccessToken{UserId: userId, ExpiryDate: int(time.Now().Add(accessTokenLifetime).Unix())})
return strconv.FormatInt(int64(encRoleId), 10), nil
}
+
+func (db CustomDB) GetUserPermissions(userId string) (isAdmin bool, isUserCreator bool, err error) {
+ numUserId, err := strconv.Atoi(userId)
+ if err != nil {
+ return false, false, errors.New("malformed userId")
+ }
+ statement, err := db.connection.Prepare("SELECT Role.IS_admin, Role.IS_userCreator FROM R_User_Role INNER JOIN Role ON R_User_Role.FK_Role_roleId = Role.roleId WHERE R_User_Role.FK_User_userId = ?")
+ if err != nil {
+ return false, false, err
+ }
+
+ rows, err := statement.Query(numUserId)
+ if err != nil {
+ return false, false, err
+ }
+
+ defer rows.Close()
+
+ var admin, userCreator bool
+ for rows.Next() {
+ var gotAdmin, gotUserCreator bool
+ if err := rows.Scan(&gotAdmin, &gotUserCreator); err != nil {
+ return false, false, err
+ }
+ if gotAdmin {
+ admin = true
+ }
+ if gotUserCreator {
+ userCreator = true
+ }
+ }
+ return admin, userCreator, nil
+}
diff --git a/graph/generated.go b/graph/generated.go
index 042fe29..b283935 100644
--- a/graph/generated.go
+++ b/graph/generated.go
@@ -47,6 +47,8 @@ type ResolverRoot interface {
}
type DirectiveRoot struct {
+ AsUser func(ctx context.Context, obj interface{}, next graphql.Resolver, id string) (res interface{}, err error)
+ HasPrivilege func(ctx context.Context, obj interface{}, next graphql.Resolver, privilege model.Privilege) (res interface{}, err error)
}
type ComplexityRoot struct {
@@ -347,12 +349,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.UpdateUser(childComplexity, args["id"].(string), args["changes"].(model.UpdateUser)), true
- case "Mutation.UpdateUserRole":
+ case "Mutation.updateUserRole":
if e.complexity.Mutation.UpdateUserRole == nil {
break
}
- args, err := ec.field_Mutation_UpdateUserRole_args(context.TODO(), rawArgs)
+ args, err := ec.field_Mutation_updateUserRole_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
@@ -630,7 +632,9 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
if first {
first = false
ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap)
- data = ec._Query(ctx, rc.Operation.SelectionSet)
+ data = ec._queryMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error) {
+ return ec._Query(ctx, rc.Operation.SelectionSet), nil
+ })
} else {
if atomic.LoadInt32(&ec.pendingDeferred) > 0 {
result := <-ec.deferredResults
@@ -660,7 +664,9 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler {
}
first = false
ctx = graphql.WithUnmarshalerMap(ctx, inputUnmarshalMap)
- data := ec._Mutation(ctx, rc.Operation.SelectionSet)
+ data := ec._mutationMiddleware(ctx, rc.Operation, func(ctx context.Context) (interface{}, error) {
+ return ec._Mutation(ctx, rc.Operation.SelectionSet), nil
+ })
var buf bytes.Buffer
data.MarshalGQL(&buf)
@@ -735,36 +741,33 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...)
// region ***************************** args.gotpl *****************************
-func (ec *executionContext) field_Mutation_UpdateUserRole_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
+func (ec *executionContext) dir_asUser_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 string
- if tmp, ok := rawArgs["userId"]; ok {
- ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userId"))
+ if tmp, ok := rawArgs["id"]; ok {
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id"))
arg0, err = ec.unmarshalNID2string(ctx, tmp)
if err != nil {
return nil, err
}
}
- args["userId"] = arg0
- var arg1 string
- if tmp, ok := rawArgs["roleId"]; ok {
- ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("roleId"))
- arg1, err = ec.unmarshalNID2string(ctx, tmp)
+ args["id"] = arg0
+ return args, nil
+}
+
+func (ec *executionContext) dir_hasPrivilege_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
+ var err error
+ args := map[string]interface{}{}
+ var arg0 model.Privilege
+ if tmp, ok := rawArgs["privilege"]; ok {
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("privilege"))
+ arg0, err = ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, tmp)
if err != nil {
return nil, err
}
}
- args["roleId"] = arg1
- var arg2 bool
- if tmp, ok := rawArgs["userIsRoleManager"]; ok {
- ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userIsRoleManager"))
- arg2, err = ec.unmarshalNBoolean2bool(ctx, tmp)
- if err != nil {
- return nil, err
- }
- }
- args["userIsRoleManager"] = arg2
+ args["privilege"] = arg0
return args, nil
}
@@ -1017,6 +1020,39 @@ func (ec *executionContext) field_Mutation_updateTodo_args(ctx context.Context,
return args, nil
}
+func (ec *executionContext) field_Mutation_updateUserRole_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
+ var err error
+ args := map[string]interface{}{}
+ var arg0 string
+ if tmp, ok := rawArgs["userId"]; ok {
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userId"))
+ arg0, err = ec.unmarshalNID2string(ctx, tmp)
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["userId"] = arg0
+ var arg1 string
+ if tmp, ok := rawArgs["roleId"]; ok {
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("roleId"))
+ arg1, err = ec.unmarshalNID2string(ctx, tmp)
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["roleId"] = arg1
+ var arg2 bool
+ if tmp, ok := rawArgs["userIsRoleManager"]; ok {
+ ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("userIsRoleManager"))
+ arg2, err = ec.unmarshalNBoolean2bool(ctx, tmp)
+ if err != nil {
+ return nil, err
+ }
+ }
+ args["userIsRoleManager"] = arg2
+ return args, nil
+}
+
func (ec *executionContext) field_Mutation_updateUser_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
@@ -1150,6 +1186,72 @@ func (ec *executionContext) field___Type_fields_args(ctx context.Context, rawArg
// region ************************** directives.gotpl **************************
+func (ec *executionContext) _queryMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) graphql.Marshaler {
+
+ for _, d := range obj.Directives {
+ switch d.Name {
+ case "asUser":
+ rawArgs := d.ArgumentMap(ec.Variables)
+ args, err := ec.dir_asUser_args(ctx, rawArgs)
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ n := next
+ next = func(ctx context.Context) (interface{}, error) {
+ if ec.directives.AsUser == nil {
+ return nil, errors.New("directive asUser is not implemented")
+ }
+ return ec.directives.AsUser(ctx, obj, n, args["id"].(string))
+ }
+ }
+ }
+ tmp, err := next(ctx)
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if data, ok := tmp.(graphql.Marshaler); ok {
+ return data
+ }
+ ec.Errorf(ctx, `unexpected type %T from directive, should be graphql.Marshaler`, tmp)
+ return graphql.Null
+
+}
+
+func (ec *executionContext) _mutationMiddleware(ctx context.Context, obj *ast.OperationDefinition, next func(ctx context.Context) (interface{}, error)) graphql.Marshaler {
+
+ for _, d := range obj.Directives {
+ switch d.Name {
+ case "asUser":
+ rawArgs := d.ArgumentMap(ec.Variables)
+ args, err := ec.dir_asUser_args(ctx, rawArgs)
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ n := next
+ next = func(ctx context.Context) (interface{}, error) {
+ if ec.directives.AsUser == nil {
+ return nil, errors.New("directive asUser is not implemented")
+ }
+ return ec.directives.AsUser(ctx, obj, n, args["id"].(string))
+ }
+ }
+ }
+ tmp, err := next(ctx)
+ if err != nil {
+ ec.Error(ctx, err)
+ return graphql.Null
+ }
+ if data, ok := tmp.(graphql.Marshaler); ok {
+ return data
+ }
+ ec.Errorf(ctx, `unexpected type %T from directive, should be graphql.Marshaler`, tmp)
+ return graphql.Null
+
+}
+
// endregion ************************** directives.gotpl **************************
// region **************************** field.gotpl *****************************
@@ -1167,8 +1269,32 @@ func (ec *executionContext) _Mutation_createUser(ctx context.Context, field grap
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().CreateUser(rctx, fc.Args["input"].(model.NewUser))
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().CreateUser(rctx, fc.Args["input"].(model.NewUser))
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isUserCreator")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.(*model.User); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be *somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model.User`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -1299,8 +1425,32 @@ func (ec *executionContext) _Mutation_createRole(ctx context.Context, field grap
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().CreateRole(rctx, fc.Args["input"].(model.NewRole))
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().CreateRole(rctx, fc.Args["input"].(model.NewRole))
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.(*model.Role); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be *somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model.Role`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -1567,8 +1717,32 @@ func (ec *executionContext) _Mutation_updateRole(ctx context.Context, field grap
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().UpdateRole(rctx, fc.Args["id"].(string), fc.Args["changes"].(model.UpdateRole))
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().UpdateRole(rctx, fc.Args["id"].(string), fc.Args["changes"].(model.UpdateRole))
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.(*model.Role); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be *somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model.Role`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -1703,8 +1877,32 @@ func (ec *executionContext) _Mutation_deleteUser(ctx context.Context, field grap
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().DeleteUser(rctx, fc.Args["id"].(string))
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().DeleteUser(rctx, fc.Args["id"].(string))
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.(*string); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -1807,8 +2005,32 @@ func (ec *executionContext) _Mutation_deleteRole(ctx context.Context, field grap
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().DeleteRole(rctx, fc.Args["id"].(string))
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().DeleteRole(rctx, fc.Args["id"].(string))
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.(*string); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be *string`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -1911,8 +2133,32 @@ func (ec *executionContext) _Mutation_addUserRole(ctx context.Context, field gra
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().AddUserRole(rctx, fc.Args["userId"].(string), fc.Args["roleId"].(string), fc.Args["userIsRoleManager"].(bool))
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().AddUserRole(rctx, fc.Args["userId"].(string), fc.Args["roleId"].(string), fc.Args["userIsRoleManager"].(bool))
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.([]*model.RelationUserRole); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be []*somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model.RelationUserRole`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -1959,8 +2205,8 @@ func (ec *executionContext) fieldContext_Mutation_addUserRole(ctx context.Contex
return fc, nil
}
-func (ec *executionContext) _Mutation_UpdateUserRole(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
- fc, err := ec.fieldContext_Mutation_UpdateUserRole(ctx, field)
+func (ec *executionContext) _Mutation_updateUserRole(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+ fc, err := ec.fieldContext_Mutation_updateUserRole(ctx, field)
if err != nil {
return graphql.Null
}
@@ -1972,8 +2218,32 @@ func (ec *executionContext) _Mutation_UpdateUserRole(ctx context.Context, field
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().UpdateUserRole(rctx, fc.Args["userId"].(string), fc.Args["roleId"].(string), fc.Args["userIsRoleManager"].(bool))
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().UpdateUserRole(rctx, fc.Args["userId"].(string), fc.Args["roleId"].(string), fc.Args["userIsRoleManager"].(bool))
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.([]*model.RelationUserRole); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be []*somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model.RelationUserRole`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -1990,7 +2260,7 @@ func (ec *executionContext) _Mutation_UpdateUserRole(ctx context.Context, field
return ec.marshalNRelationUserRole2ᚕᚖsomepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐRelationUserRoleᚄ(ctx, field.Selections, res)
}
-func (ec *executionContext) fieldContext_Mutation_UpdateUserRole(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+func (ec *executionContext) fieldContext_Mutation_updateUserRole(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Mutation",
Field: field,
@@ -2013,7 +2283,7 @@ func (ec *executionContext) fieldContext_Mutation_UpdateUserRole(ctx context.Con
}
}()
ctx = graphql.WithFieldContext(ctx, fc)
- if fc.Args, err = ec.field_Mutation_UpdateUserRole_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
+ if fc.Args, err = ec.field_Mutation_updateUserRole_args(ctx, field.ArgumentMap(ec.Variables)); err != nil {
ec.Error(ctx, err)
return fc, err
}
@@ -2033,8 +2303,32 @@ func (ec *executionContext) _Mutation_removeUserRole(ctx context.Context, field
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Mutation().RemoveUserRole(rctx, fc.Args["userId"].(string), fc.Args["roleId"].(string))
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Mutation().RemoveUserRole(rctx, fc.Args["userId"].(string), fc.Args["roleId"].(string))
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.([]*model.RelationUserRole); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be []*somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model.RelationUserRole`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -2094,8 +2388,32 @@ func (ec *executionContext) _Query_todos(ctx context.Context, field graphql.Coll
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Query().Todos(rctx)
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Query().Todos(rctx)
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.([]*model.Todo); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be []*somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model.Todo`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -2260,8 +2578,32 @@ func (ec *executionContext) _Query_refreshTokens(ctx context.Context, field grap
}
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
- ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Query().RefreshTokens(rctx)
+ directive0 := func(rctx context.Context) (interface{}, error) {
+ ctx = rctx // use context from middleware stack in children
+ return ec.resolvers.Query().RefreshTokens(rctx)
+ }
+ directive1 := func(ctx context.Context) (interface{}, error) {
+ privilege, err := ec.unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx, "isAdmin")
+ if err != nil {
+ return nil, err
+ }
+ if ec.directives.HasPrivilege == nil {
+ return nil, errors.New("directive hasPrivilege is not implemented")
+ }
+ return ec.directives.HasPrivilege(ctx, nil, directive0, privilege)
+ }
+
+ tmp, err := directive1(rctx)
+ if err != nil {
+ return nil, graphql.ErrorOnPath(ctx, err)
+ }
+ if tmp == nil {
+ return nil, nil
+ }
+ if data, ok := tmp.([]*model.RefreshToken); ok {
+ return data, nil
+ }
+ return nil, fmt.Errorf(`unexpected type %T from directive, should be []*somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model.RefreshToken`, tmp)
})
if err != nil {
ec.Error(ctx, err)
@@ -6005,9 +6347,9 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
out.Invalids++
}
- case "UpdateUserRole":
+ case "updateUserRole":
out.Values[i] = ec.OperationContext.RootResolverMiddleware(innerCtx, func(ctx context.Context) (res graphql.Marshaler) {
- return ec._Mutation_UpdateUserRole(ctx, field)
+ return ec._Mutation_updateUserRole(ctx, field)
})
if out.Values[i] == graphql.Null {
out.Invalids++
@@ -7095,6 +7437,16 @@ func (ec *executionContext) unmarshalNNewUser2somepiᚗddnsᚗnetᚋgiteaᚋgile
return res, graphql.ErrorOnPath(ctx, err)
}
+func (ec *executionContext) unmarshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx context.Context, v interface{}) (model.Privilege, error) {
+ var res model.Privilege
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNPrivilege2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐPrivilege(ctx context.Context, sel ast.SelectionSet, v model.Privilege) graphql.Marshaler {
+ return v
+}
+
func (ec *executionContext) marshalNRefreshToken2somepiᚗddnsᚗnetᚋgiteaᚋgilexᚑdevᚋYetAnotherToDoListᚋgraphᚋmodelᚐRefreshToken(ctx context.Context, sel ast.SelectionSet, v model.RefreshToken) graphql.Marshaler {
return ec._RefreshToken(ctx, sel, &v)
}
diff --git a/graph/model/models_gen.go b/graph/model/models_gen.go
index e169de4..edb4618 100644
--- a/graph/model/models_gen.go
+++ b/graph/model/models_gen.go
@@ -2,6 +2,12 @@
package model
+import (
+ "fmt"
+ "io"
+ "strconv"
+)
+
type NewRefreshToken struct {
TokenName *string `json:"tokenName,omitempty"`
}
@@ -78,3 +84,44 @@ type User struct {
Todos []*Todo `json:"todos"`
Roles []*RelationUserRole `json:"roles"`
}
+
+type Privilege string
+
+const (
+ PrivilegeIsAdmin Privilege = "isAdmin"
+ PrivilegeIsUserCreator Privilege = "isUserCreator"
+)
+
+var AllPrivilege = []Privilege{
+ PrivilegeIsAdmin,
+ PrivilegeIsUserCreator,
+}
+
+func (e Privilege) IsValid() bool {
+ switch e {
+ case PrivilegeIsAdmin, PrivilegeIsUserCreator:
+ return true
+ }
+ return false
+}
+
+func (e Privilege) String() string {
+ return string(e)
+}
+
+func (e *Privilege) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = Privilege(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid Privilege", str)
+ }
+ return nil
+}
+
+func (e Privilege) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
diff --git a/graph/schema.graphqls b/graph/schema.graphqls
index 0fe6eee..9cb2705 100644
--- a/graph/schema.graphqls
+++ b/graph/schema.graphqls
@@ -60,10 +60,10 @@ type RefreshToken {
}
type Query {
- todos: [Todo!]!
+ todos: [Todo!]! @hasPrivilege(privilege: isAdmin)
users: [User!]!
roles: [Role!]!
- refreshTokens: [RefreshToken!]!
+ refreshTokens: [RefreshToken!]! @hasPrivilege(privilege: isAdmin)
user(id: ID!): User!
todo(id: ID!): Todo!
role(id: ID!): Role!
@@ -113,27 +113,38 @@ input UpdateRefreshToken {
}
type Mutation {
- createUser(input: NewUser!): User!
+ createUser(input: NewUser!): User! @hasPrivilege(privilege: isUserCreator)
createTodo(input: NewTodo!): Todo!
- createRole(input: NewRole!): Role!
+ createRole(input: NewRole!): Role! @hasPrivilege(privilege: isAdmin)
createRefreshToken(input: NewRefreshToken!): RefreshToken!
updateTodo(id: ID!, changes: UpdateTodo!): Todo!
updateUser(id: ID!, changes: UpdateUser!): User!
updateRole(id: ID!, changes: UpdateRole!): Role!
+ @hasPrivilege(privilege: isAdmin)
updateRefreshToken(id: ID!, changes: UpdateRefreshToken!): RefreshToken!
- deleteUser(id: ID!): ID
+ deleteUser(id: ID!): ID @hasPrivilege(privilege: isAdmin)
deleteTodo(id: ID!): ID
- deleteRole(id: ID!): ID
+ deleteRole(id: ID!): ID @hasPrivilege(privilege: isAdmin)
deleteRefreshToken(id: ID!): ID
addUserRole(
userId: ID!
roleId: ID!
userIsRoleManager: Boolean!
- ): [RelationUserRole!]!
- UpdateUserRole(
+ ): [RelationUserRole!]! @hasPrivilege(privilege: isAdmin)
+ updateUserRole(
userId: ID!
roleId: ID!
userIsRoleManager: Boolean!
- ): [RelationUserRole!]!
+ ): [RelationUserRole!]! @hasPrivilege(privilege: isAdmin)
removeUserRole(userId: ID!, roleId: ID!): [RelationUserRole!]!
+ @hasPrivilege(privilege: isAdmin)
+}
+
+directive @hasPrivilege(privilege: Privilege!) on FIELD_DEFINITION
+
+directive @asUser(id: ID!) on MUTATION | QUERY
+
+enum Privilege {
+ isAdmin
+ isUserCreator
}
diff --git a/graph/schema.resolvers.go b/graph/schema.resolvers.go
index 4d3a7b0..8ebd08a 100644
--- a/graph/schema.resolvers.go
+++ b/graph/schema.resolvers.go
@@ -15,6 +15,7 @@ import (
// CreateUser is the resolver for the createUser field.
func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) {
+ // Access managed by directive
todo, err := globals.DB.CreateUser(input)
if err != nil {
globals.Logger.Println("Failed to add new user:", err)
@@ -25,6 +26,9 @@ func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser)
// CreateTodo is the resolver for the createTodo field.
func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) {
+ if auth.ForContext(ctx).UserId != input.UserID {
+ return nil, errors.New("only the owner can create a todo")
+ }
todo, err := globals.DB.CreateTodo(input)
if err != nil {
globals.Logger.Println("Failed to add new todo:", err)
@@ -35,6 +39,9 @@ func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo)
// CreateRole is the resolver for the createRole field.
func (r *mutationResolver) CreateRole(ctx context.Context, input model.NewRole) (*model.Role, error) {
+ if !auth.ForContext(ctx).IsAdmin {
+ return nil, errors.New("only an admin can create a role")
+ }
role, err := globals.DB.CreateRole(&input)
if err != nil {
globals.Logger.Println("Failed to add new role:", err)
@@ -46,57 +53,92 @@ func (r *mutationResolver) CreateRole(ctx context.Context, input model.NewRole)
// CreateRefreshToken is the resolver for the createRefreshToken field.
func (r *mutationResolver) CreateRefreshToken(ctx context.Context, input model.NewRefreshToken) (*model.RefreshToken, error) {
// TODO: unify model.RefreshToken & auth.RefreshToken
- userToken := auth.ForContext(ctx)
- refreshToken, tokenId, err := globals.DB.IssueRefreshToken(userToken.UserId, input.TokenName)
+ userId := auth.ForContext(ctx).UserId
+ refreshToken, tokenId, err := globals.DB.IssueRefreshToken(userId, input.TokenName)
if err != nil {
globals.Logger.Println("Failed to create refresh token:", err)
return nil, errors.New("failed to create refresh token")
}
- return &model.RefreshToken{ID: tokenId, ExpiryDate: refreshToken.ExpiryDate, TokenName: input.TokenName, Selector: &refreshToken.Selector, Token: &refreshToken.Token, UserID: userToken.UserId}, nil
+ return &model.RefreshToken{ID: tokenId, ExpiryDate: refreshToken.ExpiryDate, TokenName: input.TokenName, Selector: &refreshToken.Selector, Token: &refreshToken.Token, UserID: userId}, nil
}
// UpdateTodo is the resolver for the updateTodo field.
func (r *mutationResolver) UpdateTodo(ctx context.Context, id string, changes model.UpdateTodo) (*model.Todo, error) {
+ owner, err := globals.DB.GetTodoOwner(&model.Todo{ID: id})
+ if err != nil {
+ return nil, err
+ }
+ if owner.ID != auth.ForContext(ctx).UserId && !auth.ForContext(ctx).IsAdmin {
+ return nil, errors.New("only the owner can update a todo")
+ }
return globals.DB.UpdateTodo(id, &changes)
}
// UpdateUser is the resolver for the updateUser field.
func (r *mutationResolver) UpdateUser(ctx context.Context, id string, changes model.UpdateUser) (*model.User, error) {
+ if auth.ForContext(ctx).UserId != id {
+ return nil, errors.New("can only update yourself")
+ }
return globals.DB.UpdateUser(id, &changes)
}
// UpdateRole is the resolver for the updateRole field.
func (r *mutationResolver) UpdateRole(ctx context.Context, id string, changes model.UpdateRole) (*model.Role, error) {
+ // Access managed by directive
return globals.DB.UpdateRole(id, &changes)
}
// UpdateRefreshToken is the resolver for the updateRefreshToken field.
func (r *mutationResolver) UpdateRefreshToken(ctx context.Context, id string, changes model.UpdateRefreshToken) (*model.RefreshToken, error) {
+ ownerId, err := globals.DB.GetRefreshTokenOwner(id)
+ if err != nil {
+ return nil, err
+ }
+ if ownerId != auth.ForContext(ctx).UserId && !auth.ForContext(ctx).IsAdmin {
+ return nil, errors.New("only the owner can update a refresh token")
+ }
return globals.DB.UpdateRefreshToken(id, &changes)
}
// DeleteUser is the resolver for the deleteUser field.
func (r *mutationResolver) DeleteUser(ctx context.Context, id string) (*string, error) {
+ // Access managed by directive
return globals.DB.DeleteUser(id)
}
// DeleteTodo is the resolver for the deleteTodo field.
func (r *mutationResolver) DeleteTodo(ctx context.Context, id string) (*string, error) {
+ owner, err := globals.DB.GetTodoOwner(&model.Todo{ID: id})
+ if err != nil {
+ return nil, err
+ }
+ if owner.ID != auth.ForContext(ctx).UserId && !auth.ForContext(ctx).IsAdmin {
+ return nil, errors.New("only the owner can delete a todo")
+ }
return globals.DB.DeleteTodo(id)
}
// DeleteRole is the resolver for the deleteRole field.
func (r *mutationResolver) DeleteRole(ctx context.Context, id string) (*string, error) {
+ // Access managed by directive
return globals.DB.DeleteRole(id)
}
// DeleteRefreshToken is the resolver for the deleteRefreshToken field.
func (r *mutationResolver) DeleteRefreshToken(ctx context.Context, id string) (*string, error) {
+ ownerId, err := globals.DB.GetRefreshTokenOwner(id)
+ if err != nil {
+ return nil, err
+ }
+ if ownerId != auth.ForContext(ctx).UserId && !auth.ForContext(ctx).IsAdmin {
+ return nil, errors.New("only the owner can delete a refresh token")
+ }
return globals.DB.RevokeRefreshToken(id)
}
// AddUserRole is the resolver for the addUserRole field.
func (r *mutationResolver) AddUserRole(ctx context.Context, userID string, roleID string, userIsRoleManager bool) ([]*model.RelationUserRole, error) {
+ // Access managed by directive
if _, err := globals.DB.AddUserRole(userID, roleID, userIsRoleManager); err != nil {
return nil, err
}
@@ -105,6 +147,7 @@ func (r *mutationResolver) AddUserRole(ctx context.Context, userID string, roleI
// UpdateUserRole is the resolver for the UpdateUserRole field.
func (r *mutationResolver) UpdateUserRole(ctx context.Context, userID string, roleID string, userIsRoleManager bool) ([]*model.RelationUserRole, error) {
+ // Access managed by directive
if _, err := globals.DB.UpdateUserRole(userID, roleID, userIsRoleManager); err != nil {
return nil, err
}
@@ -113,6 +156,7 @@ func (r *mutationResolver) UpdateUserRole(ctx context.Context, userID string, ro
// RemoveUserRole is the resolver for the RemoveUserRole field.
func (r *mutationResolver) RemoveUserRole(ctx context.Context, userID string, roleID string) ([]*model.RelationUserRole, error) {
+ // Access managed by directive
if _, err := globals.DB.RemoveUserRole(userID, roleID); err != nil {
return nil, err
}
@@ -121,6 +165,7 @@ func (r *mutationResolver) RemoveUserRole(ctx context.Context, userID string, ro
// Todos is the resolver for the todos field.
func (r *queryResolver) Todos(ctx context.Context) ([]*model.Todo, error) {
+ // Access managed by directive
return globals.DB.GetAllTodos()
}
@@ -136,6 +181,7 @@ func (r *queryResolver) Roles(ctx context.Context) ([]*model.Role, error) {
// RefreshTokens is the resolver for the refreshTokens field.
func (r *queryResolver) RefreshTokens(ctx context.Context) ([]*model.RefreshToken, error) {
+ // Access managed by directive
return globals.DB.GetAllRefreshTokens()
}
@@ -146,6 +192,13 @@ func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error
// Todo is the resolver for the todo field.
func (r *queryResolver) Todo(ctx context.Context, id string) (*model.Todo, error) {
+ owner, err := globals.DB.GetTodoOwner(&model.Todo{ID: id})
+ if err != nil {
+ return nil, err
+ }
+ if owner.ID != auth.ForContext(ctx).UserId && !auth.ForContext(ctx).IsAdmin {
+ return nil, errors.New("only the owner can view a todo")
+ }
return globals.DB.GetTodo(&model.Todo{ID: id})
}
@@ -156,7 +209,14 @@ func (r *queryResolver) Role(ctx context.Context, id string) (*model.Role, error
// RefreshToken is the resolver for the refreshToken field.
func (r *queryResolver) RefreshToken(ctx context.Context, id string) (*model.RefreshToken, error) {
- return globals.DB.GetRefreshToken(&model.RefreshToken{ID: id})
+ ownerId, err := globals.DB.GetRefreshTokenOwner(id)
+ if err != nil {
+ return nil, err
+ }
+ if ownerId != auth.ForContext(ctx).UserId && !auth.ForContext(ctx).IsAdmin {
+ return nil, errors.New("only the owner can view a refresh token")
+ }
+ return globals.DB.GetRefreshToken(&model.RefreshToken{ID: id, UserID: ownerId})
}
// RoleMembers is the resolver for the roleMembers field.
@@ -172,6 +232,9 @@ func (r *todoResolver) User(ctx context.Context, obj *model.Todo) (*model.User,
// Todos is the resolver for the todos field.
func (r *userResolver) Todos(ctx context.Context, obj *model.User) ([]*model.Todo, error) {
+ if auth.ForContext(ctx).UserId != obj.ID && !auth.ForContext(ctx).IsAdmin {
+ return nil, errors.New("only the owner can see this")
+ }
return globals.DB.GetTodosFrom(obj)
}
diff --git a/server/main.go b/server/main.go
index 6a0f055..010bcfc 100644
--- a/server/main.go
+++ b/server/main.go
@@ -17,15 +17,18 @@ along with this program. If not, see .
package server
import (
+ "context"
"fmt"
"net/http"
"strconv"
+ "github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/globals"
"somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph"
+ "somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/graph/model"
"somepi.ddns.net/gitea/gilex-dev/YetAnotherToDoList/server/auth"
)
@@ -39,11 +42,40 @@ func StartServer(portHTTP int, portHTTPS int, certFile string, keyFile string) {
fmt.Fprintf(w, "%s %s", globals.Version, globals.CommitHash)
})
- srv := handler.NewDefaultServer(graph.NewExecutableSchema(graph.Config{Resolvers: &graph.Resolver{}}))
router.HandleFunc("/auth/login", auth.IssueRefreshTokenHandler)
router.HandleFunc("/auth", auth.IssueAccessTokenHandler)
router.Group(func(r chi.Router) {
+ config := graph.Config{Resolvers: &graph.Resolver{}}
+ config.Directives.HasPrivilege = func(ctx context.Context, obj interface{}, next graphql.Resolver, privilege model.Privilege) (interface{}, error) {
+ switch privilege {
+ case model.PrivilegeIsUserCreator:
+ if !auth.ForContext(ctx).IsUserCreator {
+ return nil, fmt.Errorf("access denied: you need IsUserCreator")
+
+ }
+ case model.PrivilegeIsAdmin:
+ if !auth.ForContext(ctx).IsAdmin {
+ return nil, fmt.Errorf("access denied: you need IsAdmin")
+ }
+
+ }
+ // or let it pass through
+ return next(ctx)
+ }
+
+ config.Directives.AsUser = func(ctx context.Context, obj interface{}, next graphql.Resolver, id string) (interface{}, error) {
+ if !auth.ForContext(ctx).IsAdmin {
+ // block calling the next resolver
+ return nil, fmt.Errorf("access denied: you need IsAdmin to use the asUser directive")
+ }
+ // or let it pass through
+ fmt.Printf("Running as %s instead of %s\n", id, auth.ForContext(ctx).UserId) //DEBUG
+ auth.ForContext(ctx).UserId = id
+ return next(ctx)
+ }
+
+ srv := handler.NewDefaultServer(graph.NewExecutableSchema(config))
r.Use(auth.Middleware())
r.Handle("/api", srv)
r.HandleFunc("/protected", func(w http.ResponseWriter, r *http.Request) {