func canUseRole(t auth.Token, roleName, contextValue string) error { role, err := permission.FindRole(roleName) if err != nil { if err == permission.ErrRoleNotFound { return &errors.HTTP{ Code: http.StatusNotFound, Message: err.Error(), } } return err } userPerms, err := t.Permissions() if err != nil { return err } perms := role.PermissionsFor(contextValue) for _, p := range perms { if !permission.CheckFromPermList(userPerms, p.Scheme, p.Context) { return &errors.HTTP{ Code: http.StatusForbidden, Message: fmt.Sprintf("User not authorized to use permission %s", p.String()), } } } return nil }
func createApiUser(perms []permission.Permission, user *auth.User, roleMap map[string]*permission.Role, includeAll bool) (*apiUser, error) { var permData []rolePermissionData roleData := make([]rolePermissionData, 0, len(user.Roles)) if roleMap == nil { roleMap = make(map[string]*permission.Role) } allGlobal := true for _, userRole := range user.Roles { role := roleMap[userRole.Name] if role == nil { r, err := permission.FindRole(userRole.Name) if err != nil { return nil, err } role = &r roleMap[userRole.Name] = role } allPermsMatch := true permissions := role.PermissionsFor(userRole.ContextValue) if len(permissions) == 0 && !includeAll { continue } rolePerms := make([]rolePermissionData, len(permissions)) for i, p := range permissions { if perms != nil && allPermsMatch && !permission.CheckFromPermList(perms, p.Scheme, p.Context) { allPermsMatch = false break } rolePerms[i] = rolePermissionData{ Name: p.Scheme.FullName(), ContextType: string(p.Context.CtxType), ContextValue: p.Context.Value, } } if !allPermsMatch { continue } roleData = append(roleData, rolePermissionData{ Name: userRole.Name, ContextType: string(role.ContextType), ContextValue: userRole.ContextValue, }) permData = append(permData, rolePerms...) if role.ContextType != permission.CtxGlobal { allGlobal = false } } if len(roleData) == 0 || (!includeAll && allGlobal) { return nil, nil } return &apiUser{ Email: user.Email, Roles: roleData, Permissions: permData, }, nil }
// Revoke removes the access from a team. It returns an error if the team do // not have access to the app. func (app *App) Revoke(team *auth.Team) error { if len(app.Teams) == 1 { return ErrCannotOrphanApp } index, found := app.findTeam(team) if !found { return ErrNoAccess } last := len(app.Teams) - 1 app.Teams[index] = app.Teams[last] app.Teams = app.Teams[:last] conn, err := db.Conn() if err != nil { return err } defer conn.Close() err = conn.Apps().Update(bson.M{"name": app.Name}, bson.M{"$pull": bson.M{"teams": team.Name}}) if err != nil { return err } users, err := auth.ListUsersWithPermissions(permission.Permission{ Scheme: permission.PermAppDeploy, Context: permission.Context(permission.CtxTeam, team.Name), }) if err != nil { conn.Apps().Update(bson.M{"name": app.Name}, bson.M{"$addToSet": bson.M{"teams": team.Name}}) return err } for _, user := range users { perms, err := user.Permissions() if err != nil { conn.Apps().Update(bson.M{"name": app.Name}, bson.M{"$addToSet": bson.M{"teams": team.Name}}) return err } canDeploy := permission.CheckFromPermList(perms, permission.PermAppDeploy, append(permission.Contexts(permission.CtxTeam, app.Teams), permission.Context(permission.CtxApp, app.Name), permission.Context(permission.CtxPool, app.Pool), )..., ) if canDeploy { continue } err = repository.Manager().RevokeAccess(app.Name, user.Email) if err != nil { conn.Apps().Update(bson.M{"name": app.Name}, bson.M{"$addToSet": bson.M{"teams": team.Name}}) return err } } return nil }
func teamList(w http.ResponseWriter, r *http.Request, t auth.Token) error { rec.Log(t.GetUserName(), "list-teams") permsForTeam := permission.PermissionRegistry.PermissionsWithContextType(permission.CtxTeam) teams, err := auth.ListTeams() if err != nil { return err } teamsMap := map[string][]string{} perms, err := t.Permissions() if err != nil { return err } for _, team := range teams { teamCtx := permission.Context(permission.CtxTeam, team.Name) var parent *permission.PermissionScheme for _, p := range permsForTeam { if parent != nil && parent.IsParent(p) { continue } if permission.CheckFromPermList(perms, p, teamCtx) { parent = p teamsMap[team.Name] = append(teamsMap[team.Name], p.FullName()) } } } if len(teamsMap) == 0 { w.WriteHeader(http.StatusNoContent) return nil } var result []map[string]interface{} for name, permissions := range teamsMap { result = append(result, map[string]interface{}{ "name": name, "permissions": permissions, }) } w.Header().Set("Content-Type", "application/json") b, err := json.Marshal(result) if err != nil { return err } n, err := w.Write(b) if err != nil { return err } if n != len(b) { return &errors.HTTP{Code: http.StatusInternalServerError, Message: "Failed to write response body."} } return nil }
func ListUsersWithPermissions(wantedPerms ...permission.Permission) ([]User, error) { allUsers, err := ListUsers() if err != nil { return nil, err } var filteredUsers []User // TODO(cezarsa): Too slow! Think about faster implementation in the future. usersLoop: for _, u := range allUsers { perms, err := u.Permissions() if err != nil { return nil, err } for _, p := range wantedPerms { if permission.CheckFromPermList(perms, p.Scheme, p.Context) { filteredUsers = append(filteredUsers, u) continue usersLoop } } } return filteredUsers, nil }
func createApiUser(perms []permission.Permission, user *auth.User, roleMap map[string]*permission.Role) (*apiUser, error) { permData := make([]rolePermissionData, 0, len(user.Roles)) roleData := make([]rolePermissionData, len(user.Roles)) if roleMap == nil { roleMap = make(map[string]*permission.Role) } for i, userRole := range user.Roles { role := roleMap[userRole.Name] if role == nil { r, err := permission.FindRole(userRole.Name) if err != nil { return nil, err } role = &r roleMap[userRole.Name] = role } roleData[i] = rolePermissionData{ Name: userRole.Name, ContextType: string(role.ContextType), ContextValue: userRole.ContextValue, } permissions := role.PermissionsFor(userRole.ContextValue) for _, p := range permissions { if !permission.CheckFromPermList(perms, p.Scheme, p.Context) { return nil, nil } permData = append(permData, rolePermissionData{ Name: p.Scheme.FullName(), ContextType: string(p.Context.CtxType), ContextValue: p.Context.Value, }) } } return &apiUser{ Email: user.Email, Roles: roleData, Permissions: permData, }, nil }
// title: team list // path: /teams // method: GET // produce: application/json // responses: // 200: List teams // 204: No content // 401: Unauthorized func teamList(w http.ResponseWriter, r *http.Request, t auth.Token) error { permsForTeam := permission.PermissionRegistry.PermissionsWithContextType(permission.CtxTeam) teams, err := auth.ListTeams() if err != nil { return err } teamsMap := map[string][]string{} perms, err := t.Permissions() if err != nil { return err } for _, team := range teams { teamCtx := permission.Context(permission.CtxTeam, team.Name) var parent *permission.PermissionScheme for _, p := range permsForTeam { if parent != nil && parent.IsParent(p) { continue } if permission.CheckFromPermList(perms, p, teamCtx) { parent = p teamsMap[team.Name] = append(teamsMap[team.Name], p.FullName()) } } } if len(teamsMap) == 0 { w.WriteHeader(http.StatusNoContent) return nil } var result []map[string]interface{} for name, permissions := range teamsMap { result = append(result, map[string]interface{}{ "name": name, "permissions": permissions, }) } w.Header().Set("Content-Type", "application/json") return json.NewEncoder(w).Encode(result) }