From 84bac7e52028e7bb2f9ca8efe2d6fcbb27b39f5d Mon Sep 17 00:00:00 2001 From: Michael Schwarz Date: Tue, 23 Aug 2022 13:33:25 +0200 Subject: [PATCH] Add new role support. This enables designated users to see all jobs. --- cmd/cc-backend/main.go | 2 +- internal/auth/auth.go | 7 ++++--- internal/auth/users.go | 4 ++-- internal/graph/schema.resolvers.go | 2 +- internal/repository/job.go | 4 ++-- internal/repository/query.go | 2 +- internal/routerConfig/routes.go | 6 ++++-- web/templates/config.tmpl | 5 +++++ web/web.go | 1 + 9 files changed, 21 insertions(+), 12 deletions(-) diff --git a/cmd/cc-backend/main.go b/cmd/cc-backend/main.go index 19c9830..b6a6280 100644 --- a/cmd/cc-backend/main.go +++ b/cmd/cc-backend/main.go @@ -142,7 +142,7 @@ func main() { flag.BoolVar(&flagStopImmediately, "no-server", false, "Do not start a server, stop right after initialization and argument handling") flag.BoolVar(&flagGops, "gops", false, "Listen via github.com/google/gops/agent (for debugging)") flag.StringVar(&flagConfigFile, "config", "./config.json", "Overwrite the global config options by those specified in `config.json`") - flag.StringVar(&flagNewUser, "add-user", "", "Add a new user. Argument format: `:[admin,api,user]:`") + flag.StringVar(&flagNewUser, "add-user", "", "Add a new user. Argument format: `:[admin,support,api,user]:`") flag.StringVar(&flagDelUser, "del-user", "", "Remove user by `username`") flag.StringVar(&flagGenJWT, "jwt", "", "Generate and print a JWT for the user specified by its `username`") flag.StringVar(&flagImportJob, "import-job", "", "Import a job. Argument format: `:,...`") diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 3f2c359..73c6917 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -19,9 +19,10 @@ import ( ) const ( - RoleAdmin string = "admin" - RoleApi string = "api" - RoleUser string = "user" + RoleAdmin string = "admin" + RoleSupport string = "support" + RoleApi string = "api" + RoleUser string = "user" ) const ( diff --git a/internal/auth/users.go b/internal/auth/users.go index 63f18c2..4d3a658 100644 --- a/internal/auth/users.go +++ b/internal/auth/users.go @@ -112,7 +112,7 @@ func (auth *Authentication) AddRole(ctx context.Context, username string, role s return err } - if role != RoleAdmin && role != RoleApi && role != RoleUser { + if role != RoleAdmin && role != RoleApi && role != RoleUser && role != RoleSupport { return fmt.Errorf("invalid user role: %#v", role) } @@ -131,7 +131,7 @@ func (auth *Authentication) AddRole(ctx context.Context, username string, role s func FetchUser(ctx context.Context, db *sqlx.DB, username string) (*model.User, error) { me := GetUser(ctx) - if me != nil && !me.HasRole(RoleAdmin) && me.Username != username { + if me != nil && !me.HasRole(RoleAdmin) && !me.HasRole(RoleSupport) && me.Username != username { return nil, errors.New("forbidden") } diff --git a/internal/graph/schema.resolvers.go b/internal/graph/schema.resolvers.go index 7fe30aa..b8b3bcb 100644 --- a/internal/graph/schema.resolvers.go +++ b/internal/graph/schema.resolvers.go @@ -142,7 +142,7 @@ func (r *queryResolver) Job(ctx context.Context, id string) (*schema.Job, error) return nil, err } - if user := auth.GetUser(ctx); user != nil && !user.HasRole(auth.RoleAdmin) && job.User != user.Username { + if user := auth.GetUser(ctx); user != nil && !user.HasRole(auth.RoleAdmin) && !user.HasRole(auth.RoleSupport) && job.User != user.Username { return nil, errors.New("you are not allowed to see this job") } diff --git a/internal/repository/job.go b/internal/repository/job.go index 6417efd..7a8ce8e 100644 --- a/internal/repository/job.go +++ b/internal/repository/job.go @@ -309,7 +309,7 @@ func (r *JobRepository) FindJobOrUser(ctx context.Context, searchterm string) (j user := auth.GetUser(ctx) if id, err := strconv.Atoi(searchterm); err == nil { qb := sq.Select("job.id").From("job").Where("job.job_id = ?", id) - if user != nil && !user.HasRole(auth.RoleAdmin) { + if user != nil && !user.HasRole(auth.RoleAdmin) && !user.HasRole(auth.RoleSupport) { qb = qb.Where("job.user = ?", user.Username) } @@ -321,7 +321,7 @@ func (r *JobRepository) FindJobOrUser(ctx context.Context, searchterm string) (j } } - if user == nil || user.HasRole(auth.RoleAdmin) { + if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleSupport) { err := sq.Select("job.user").Distinct().From("job"). Where("job.user = ?", searchterm). RunWith(r.stmtCache).QueryRow().Scan(&username) diff --git a/internal/repository/query.go b/internal/repository/query.go index beed7bc..e207aed 100644 --- a/internal/repository/query.go +++ b/internal/repository/query.go @@ -94,7 +94,7 @@ func (r *JobRepository) CountJobs( func SecurityCheck(ctx context.Context, query sq.SelectBuilder) sq.SelectBuilder { user := auth.GetUser(ctx) - if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleApi) { + if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleApi) || user.HasRole(auth.RoleSupport) { return query } diff --git a/internal/routerConfig/routes.go b/internal/routerConfig/routes.go index ad3a103..dbd3d01 100644 --- a/internal/routerConfig/routes.go +++ b/internal/routerConfig/routes.go @@ -269,15 +269,17 @@ func SetupRoutes(router *mux.Router) { title = strings.Replace(route.Title, "", id.(string), 1) } - username, isAdmin := "", true + username, isAdmin, isSupporter := "", true, true + if user := auth.GetUser(r.Context()); user != nil { username = user.Username isAdmin = user.HasRole(auth.RoleAdmin) + isSupporter = user.HasRole(auth.RoleSupport) } page := web.Page{ Title: title, - User: web.User{Username: username, IsAdmin: isAdmin}, + User: web.User{Username: username, IsAdmin: isAdmin, IsSupporter: isSupporter}, Config: conf, Infos: infos, } diff --git a/web/templates/config.tmpl b/web/templates/config.tmpl index deccf92..bacf8b8 100644 --- a/web/templates/config.tmpl +++ b/web/templates/config.tmpl @@ -38,6 +38,10 @@ +
+ + +

@@ -131,6 +135,7 @@ + diff --git a/web/web.go b/web/web.go index 9d0ea6d..7435b9f 100644 --- a/web/web.go +++ b/web/web.go @@ -55,6 +55,7 @@ func init() { type User struct { Username string // Username of the currently logged in user IsAdmin bool + IsSupporter bool } type Page struct {