mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2024-11-10 08:57:25 +01:00
Add role helper functions, add project role barebone, add valid role arr
- HasAnyRoles([]string): Checks if user has *one* of the roles - HasAllRoles([]string): Cheks if user has *all* of the roles - HasNotRoles([]string): Checks if user has *none* of the roles - IsValidRole(string): Checks if given string is known valid role
This commit is contained in:
parent
5abd3641b2
commit
834f9d9085
@ -23,8 +23,11 @@ const (
|
|||||||
RoleSupport string = "support"
|
RoleSupport string = "support"
|
||||||
RoleApi string = "api"
|
RoleApi string = "api"
|
||||||
RoleUser string = "user"
|
RoleUser string = "user"
|
||||||
|
RoleProject string = "project"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var validRoles = [5]string{RoleAdmin, RoleSupport, RoleApi, RoleUser, RoleProject}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AuthViaLocalPassword int8 = 0
|
AuthViaLocalPassword int8 = 0
|
||||||
AuthViaLDAP int8 = 1
|
AuthViaLDAP int8 = 1
|
||||||
@ -38,6 +41,7 @@ type User struct {
|
|||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
AuthSource int8 `json:"via"`
|
AuthSource int8 `json:"via"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
|
Project string `json:"project"`
|
||||||
Expiration time.Time
|
Expiration time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +54,66 @@ func (u *User) HasRole(role string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Role-Arrays are short: performance not impacted by nested loop
|
||||||
|
func (u *User) HasAnyRole(queryroles []string) bool {
|
||||||
|
for _, ur := range u.Roles {
|
||||||
|
for _, qr := range queryroles {
|
||||||
|
if ur == qr {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role-Arrays are short: performance not impacted by nested loop
|
||||||
|
func (u *User) HasAllRoles(queryroles []string) bool {
|
||||||
|
target := len(queryroles)
|
||||||
|
matches := 0
|
||||||
|
for _, ur := range u.Roles {
|
||||||
|
for _, qr := range queryroles {
|
||||||
|
if ur == qr {
|
||||||
|
matches += 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches == target {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role-Arrays are short: performance not impacted by nested loop
|
||||||
|
func (u *User) HasNotRoles(queryroles []string) bool {
|
||||||
|
matches := 0
|
||||||
|
for _, ur := range u.Roles {
|
||||||
|
for _, qr := range queryroles {
|
||||||
|
if ur == qr {
|
||||||
|
matches += 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if matches == 0 {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsValidRole(role string) bool {
|
||||||
|
for _, r := range validRoles {
|
||||||
|
if r == role {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func GetUser(ctx context.Context) *User {
|
func GetUser(ctx context.Context) *User {
|
||||||
x := ctx.Value(ContextUserKey)
|
x := ctx.Value(ContextUserKey)
|
||||||
if x == nil {
|
if x == nil {
|
||||||
|
@ -120,15 +120,13 @@ func (auth *Authentication) AddRole(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if role != RoleAdmin && role != RoleApi && role != RoleUser && role != RoleSupport {
|
if !IsValidRole(role) {
|
||||||
return fmt.Errorf("invalid user role: %#v", role)
|
return fmt.Errorf("invalid user role: %#v", role)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range user.Roles {
|
if user.HasRole(role) {
|
||||||
if r == role {
|
|
||||||
return fmt.Errorf("user %#v already has role %#v", username, role)
|
return fmt.Errorf("user %#v already has role %#v", username, role)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
roles, _ := json.Marshal(append(user.Roles, role))
|
roles, _ := json.Marshal(append(user.Roles, role))
|
||||||
if _, err := sq.Update("user").Set("roles", roles).Where("user.username = ?", username).RunWith(auth.db).Exec(); err != nil {
|
if _, err := sq.Update("user").Set("roles", roles).Where("user.username = ?", username).RunWith(auth.db).Exec(); err != nil {
|
||||||
@ -143,7 +141,7 @@ func (auth *Authentication) RemoveRole(ctx context.Context, username string, rol
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if role != RoleAdmin && role != RoleApi && role != RoleUser && role != RoleSupport {
|
if !IsValidRole(role) {
|
||||||
return fmt.Errorf("invalid user role: %#v", role)
|
return fmt.Errorf("invalid user role: %#v", role)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +168,7 @@ func (auth *Authentication) RemoveRole(ctx context.Context, username string, rol
|
|||||||
|
|
||||||
func FetchUser(ctx context.Context, db *sqlx.DB, username string) (*model.User, error) {
|
func FetchUser(ctx context.Context, db *sqlx.DB, username string) (*model.User, error) {
|
||||||
me := GetUser(ctx)
|
me := GetUser(ctx)
|
||||||
if me != nil && !me.HasRole(RoleAdmin) && !me.HasRole(RoleSupport) && me.Username != username {
|
if me != nil && me.Username != username && me.HasNotRoles([]string{RoleAdmin, RoleSupport}) {
|
||||||
return nil, errors.New("forbidden")
|
return nil, errors.New("forbidden")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ func (r *queryResolver) Job(ctx context.Context, id string) (*schema.Job, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if user := auth.GetUser(ctx); user != nil && !user.HasRole(auth.RoleAdmin) && !user.HasRole(auth.RoleSupport) && job.User != user.Username {
|
if user := auth.GetUser(ctx); user != nil && job.User != user.Username && user.HasNotRoles([]string{auth.RoleAdmin, auth.RoleSupport}){
|
||||||
return nil, errors.New("you are not allowed to see this job")
|
return nil, errors.New("you are not allowed to see this job")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +423,7 @@ func (r *JobRepository) FindJobOrUser(ctx context.Context, searchterm string) (j
|
|||||||
user := auth.GetUser(ctx)
|
user := auth.GetUser(ctx)
|
||||||
if id, err := strconv.Atoi(searchterm); err == nil {
|
if id, err := strconv.Atoi(searchterm); err == nil {
|
||||||
qb := sq.Select("job.id").From("job").Where("job.job_id = ?", id)
|
qb := sq.Select("job.id").From("job").Where("job.job_id = ?", id)
|
||||||
if user != nil && !user.HasRole(auth.RoleAdmin) && !user.HasRole(auth.RoleSupport) {
|
if user != nil && user.HasNotRoles([]string{auth.RoleAdmin, auth.RoleSupport}) {
|
||||||
qb = qb.Where("job.user = ?", user.Username)
|
qb = qb.Where("job.user = ?", user.Username)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,7 +435,7 @@ func (r *JobRepository) FindJobOrUser(ctx context.Context, searchterm string) (j
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleSupport) {
|
if user == nil || user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleSupport}) {
|
||||||
err := sq.Select("job.user").Distinct().From("job").
|
err := sq.Select("job.user").Distinct().From("job").
|
||||||
Where("job.user = ?", searchterm).
|
Where("job.user = ?", searchterm).
|
||||||
RunWith(r.stmtCache).QueryRow().Scan(&username)
|
RunWith(r.stmtCache).QueryRow().Scan(&username)
|
||||||
|
@ -94,7 +94,7 @@ func (r *JobRepository) CountJobs(
|
|||||||
|
|
||||||
func SecurityCheck(ctx context.Context, query sq.SelectBuilder) sq.SelectBuilder {
|
func SecurityCheck(ctx context.Context, query sq.SelectBuilder) sq.SelectBuilder {
|
||||||
user := auth.GetUser(ctx)
|
user := auth.GetUser(ctx)
|
||||||
if user == nil || user.HasRole(auth.RoleAdmin) || user.HasRole(auth.RoleApi) || user.HasRole(auth.RoleSupport) {
|
if user == nil || user.HasAnyRole([]string{auth.RoleAdmin, auth.RoleApi, auth.RoleSupport}) {
|
||||||
return query
|
return query
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user