package service import ( "context" "errors" "git.itzana.me/strafesnet/go-grpc/auth" "git.itzana.me/strafesnet/maps-service/pkg/api" ) var ( // ErrMissingSessionID there is no session id ErrMissingSessionID = errors.New("SessionID missing") // ErrInvalidSession caller does not have a valid session ErrInvalidSession = errors.New("Session invalid") ) // Submissions roles bitflag type Roles int32 var ( // Only users with this role are allowed to submit models they don't own RolesSubmissionCreateNotModelOwner Roles = 1<<8 RolesMapfixCreateNotModelOwner Roles = 1<<7 RolesSubmissionUpload Roles = 1<<6 RolesSubmissionReview Roles = 1<<5 RolesSubmissionRelease Roles = 1<<4 RolesScriptWrite Roles = 1<<3 RolesMapfixUpload Roles = 1<<2 RolesMapfixReview Roles = 1<<1 RolesMapDownload Roles = 1<<0 RolesEmpty Roles = 0 ) // StrafesNET group roles type GroupRole int32 var ( // has ScriptWrite RoleQuat GroupRole = 255 RoleItzaname GroupRole = 254 RoleStagingDeveloper GroupRole = 240 RolesAll Roles = ^RolesEmpty // has SubmissionUpload RoleMapAdmin GroupRole = 128 RolesMapAdmin Roles = RolesSubmissionRelease|RolesSubmissionUpload|RolesSubmissionReview|RolesSubmissionCreateNotModelOwner|RolesMapCouncil // has MapfixReview RoleMapCouncil GroupRole = 64 RolesMapCouncil Roles = RolesMapfixReview|RolesMapfixUpload|RolesMapfixCreateNotModelOwner|RolesMapAccess // access to downloading maps RoleMapAccess GroupRole = 32 RolesMapAccess Roles = RolesMapDownload ) type UserInfoHandle struct { // Would love to know a better way to do this svc *SecurityHandler ctx *context.Context sessionId string } type UserInfo struct { UserID uint64 Username string AvatarURL string } func (usr UserInfoHandle) GetUserInfo() (userInfo UserInfo, err error) { session, err := usr.svc.Client.GetSessionUser(*usr.ctx, &auth.IdMessage{ SessionID: usr.sessionId, }) if err != nil { return userInfo, err } userInfo.UserID = session.UserID userInfo.Username = session.Username userInfo.AvatarURL = session.AvatarURL return userInfo, nil } func (usr UserInfoHandle) GetUserID() (uint64, error) { session, err := usr.svc.Client.GetSessionUser(*usr.ctx, &auth.IdMessage{ SessionID: usr.sessionId, }) if err != nil { return 0, err } return session.UserID, nil } func (usr UserInfoHandle) Validate() (bool, error) { validate, err := usr.svc.Client.ValidateSession(*usr.ctx, &auth.IdMessage{ SessionID: usr.sessionId, }) if err != nil { return false, err } return validate.Valid, nil } func (usr UserInfoHandle) IsSubmitter(submitter uint64) (bool, error) { userId, err := usr.GetUserID() if err != nil { return false, err } return userId == submitter, nil } func (usr UserInfoHandle) hasRoles(wantRoles Roles) (bool, error) { haveroles, err := usr.GetRoles() if err != nil { return false, err } return haveroles & wantRoles == wantRoles, nil } func (usr UserInfoHandle) GetRoles() (Roles, error) { roles, err := usr.svc.Client.GetGroupRole(*usr.ctx, &auth.IdMessage{ SessionID: usr.sessionId, }) if err != nil { return RolesEmpty, err } // map roles into bitflag rolesBitflag := RolesEmpty; for _, r := range roles.Roles { switch GroupRole(r.Rank){ case RoleQuat, RoleItzaname, RoleStagingDeveloper: rolesBitflag|=RolesAll case RoleMapAdmin: rolesBitflag|=RolesMapAdmin case RoleMapCouncil: rolesBitflag|=RolesMapCouncil case RoleMapAccess: rolesBitflag|=RolesMapAccess } } return rolesBitflag, nil } // RoleThumbnail func (usr UserInfoHandle) HasRoleMapfixCreateNotModelOwner() (bool, error) { return usr.hasRoles(RolesMapfixCreateNotModelOwner) } func (usr UserInfoHandle) HasRoleSubmissionCreateNotModelOwner() (bool, error) { return usr.hasRoles(RolesSubmissionCreateNotModelOwner) } func (usr UserInfoHandle) HasRoleMapfixUpload() (bool, error) { return usr.hasRoles(RolesMapfixUpload) } func (usr UserInfoHandle) HasRoleMapfixReview() (bool, error) { return usr.hasRoles(RolesMapfixReview) } func (usr UserInfoHandle) HasRoleMapDownload() (bool, error) { return usr.hasRoles(RolesMapDownload) } func (usr UserInfoHandle) HasRoleSubmissionRelease() (bool, error) { return usr.hasRoles(RolesSubmissionRelease) } func (usr UserInfoHandle) HasRoleSubmissionUpload() (bool, error) { return usr.hasRoles(RolesSubmissionUpload) } func (usr UserInfoHandle) HasRoleSubmissionReview() (bool, error) { return usr.hasRoles(RolesSubmissionReview) } func (usr UserInfoHandle) HasRoleScriptWrite() (bool, error) { return usr.hasRoles(RolesScriptWrite) } /// Not implemented func (usr UserInfoHandle) HasRoleMaptest() (bool, error) { println("HasRoleMaptest is not implemented!") return false, nil } type SecurityHandler struct { Client auth.AuthServiceClient } func (svc SecurityHandler) HandleCookieAuth(ctx context.Context, operationName api.OperationName, t api.CookieAuth) (context.Context, error) { sessionId := t.GetAPIKey() if sessionId == "" { return nil, ErrMissingSessionID } newCtx := context.WithValue(ctx, "UserInfo", UserInfoHandle{ svc: &svc, ctx: &ctx, sessionId: sessionId, }) return newCtx, nil }