func (si *ServiceInstance) Revoke(teamName string) error { team, err := auth.GetTeam(teamName) if err != nil { return err } return si.update(bson.M{"$pull": bson.M{"teams": team.Name}}) }
func addUserToTeam(w http.ResponseWriter, r *http.Request, t auth.Token) error { teamName := r.URL.Query().Get(":team") email := r.URL.Query().Get(":user") u, err := t.User() if err != nil { return err } rec.Log(u.Email, "add-user-to-team", "team="+teamName, "user="******"Team not found"} } if !team.ContainsUser(u) { msg := fmt.Sprintf("You are not authorized to add new users to the team %s", team.Name) return &errors.HTTP{Code: http.StatusForbidden, Message: msg} } user, err := auth.GetUserByEmail(email) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: "User not found"} } actions := []*action.Action{ &addUserToTeamInRepositoryAction, &addUserToTeamInDatabaseAction, } pipeline := action.NewPipeline(actions...) return pipeline.Execute(user, team) }
func removeUserFromTeam(w http.ResponseWriter, r *http.Request, t auth.Token) error { email := r.URL.Query().Get(":user") teamName := r.URL.Query().Get(":team") u, err := t.User() if err != nil { return err } rec.Log(u.Email, "remove-user-from-team", "team="+teamName, "user="******"Team not found"} } if !team.ContainsUser(u) { msg := fmt.Sprintf("You are not authorized to remove a member from the team %s", team.Name) return &errors.HTTP{Code: http.StatusUnauthorized, Message: msg} } if len(team.Users) == 1 { msg := "You can not remove this user from this team, because it is the last user within the team, and a team can not be orphaned" return &errors.HTTP{Code: http.StatusForbidden, Message: msg} } user, err := auth.GetUserByEmail(email) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()} } err = removeUserFromTeamInDatabase(user, team) if err != nil { return err } return removeUserFromTeamInRepository(user, team) }
func revokeServiceAccess(w http.ResponseWriter, r *http.Request, t auth.Token) error { serviceName := r.URL.Query().Get(":service") s, err := getService(serviceName) if err != nil { return err } allowed := permission.Check(t, permission.PermServiceUpdateRevokeAccess, append(permission.Contexts(permission.CtxTeam, s.OwnerTeams), permission.Context(permission.CtxService, s.Name), )..., ) if !allowed { return permission.ErrUnauthorized } teamName := r.URL.Query().Get(":team") team, err := auth.GetTeam(teamName) if err != nil { if err == auth.ErrTeamNotFound { return &errors.HTTP{Code: http.StatusNotFound, Message: "Team not found"} } return err } if len(s.Teams) < 2 { msg := "You can not revoke the access from this team, because it is the unique team with access to this service, and a service can not be orphaned" return &errors.HTTP{Code: http.StatusForbidden, Message: msg} } rec.Log(t.GetUserName(), "revoke-service-access", "service="+serviceName, "team="+teamName) err = s.RevokeAccess(team) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()} } return s.Update() }
func setTeamOwner(w http.ResponseWriter, r *http.Request, t auth.Token) error { if r.Body == nil { return &errors.HTTP{Code: http.StatusBadRequest, Message: "You must provide a team name."} } defer r.Body.Close() b, err := ioutil.ReadAll(r.Body) if err != nil { return err } teamName := string(b) team, err := auth.GetTeam(teamName) if err != nil { return err } u, err := t.User() if err != nil { return err } a, err := getAppFromContext(r.URL.Query().Get(":app"), u, r) if err != nil { return err } err = a.SetTeamOwner(team, u) if err != nil { return err } return nil }
func grantServiceAccess(w http.ResponseWriter, r *http.Request, t auth.Token) error { serviceName := r.URL.Query().Get(":service") s, err := getService(serviceName) if err != nil { return err } allowed := permission.Check(t, permission.PermServiceUpdateGrantAccess, append(permission.Contexts(permission.CtxTeam, s.OwnerTeams), permission.Context(permission.CtxService, s.Name), )..., ) if !allowed { return permission.ErrUnauthorized } teamName := r.URL.Query().Get(":team") team, err := auth.GetTeam(teamName) if err != nil { if err == auth.ErrTeamNotFound { return &errors.HTTP{Code: http.StatusNotFound, Message: "Team not found"} } return err } rec.Log(t.GetUserName(), "grant-service-access", "service="+serviceName, "team="+teamName) err = s.GrantAccess(team) if err != nil { return &errors.HTTP{Code: http.StatusConflict, Message: err.Error()} } return s.Update() }
func getTeam(w http.ResponseWriter, r *http.Request, t auth.Token) error { teamName := r.URL.Query().Get(":name") _, err := auth.GetTeam(teamName) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: "Team not found"} } permsForTeam := permission.PermissionRegistry.PermissionsWithContextType(permission.CtxTeam) var permissions []string for _, p := range permsForTeam { if permission.Check(t, p, permission.Context(permission.CtxTeam, teamName)) { permissions = append(permissions, p.FullName()) } } if len(permissions) == 0 { return &errors.HTTP{Code: http.StatusNotFound, Message: "Team not found"} } rec.Log(t.GetUserName(), "get-team", teamName) result := map[string]interface{}{ "name": teamName, "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 }
// Update changes informations of the application. func (app *App) Update(updateData App, w io.Writer) error { description := updateData.Description planName := updateData.Plan.Name poolName := updateData.Pool teamOwner := updateData.TeamOwner if description != "" { app.Description = description } if poolName != "" { app.Pool = poolName _, err := app.GetPoolForApp(app.Pool) if err != nil { return err } } conn, err := db.Conn() if err != nil { return err } defer conn.Close() if planName != "" { plan, err := findPlanByName(planName) if err != nil { return err } var oldPlan Plan oldPlan, app.Plan = app.Plan, *plan actions := []*action.Action{ &moveRouterUnits, &saveApp, &restartApp, &removeOldBackend, } err = action.NewPipeline(actions...).Execute(app, &oldPlan, w) if err != nil { return err } } if teamOwner != "" { team, err := auth.GetTeam(teamOwner) if err != nil { return err } app.TeamOwner = team.Name err = app.validateTeamOwner() if err != nil { return err } app.Grant(team) } return conn.Apps().Update(bson.M{"name": app.Name}, app) }
func getTeam(w http.ResponseWriter, r *http.Request, t auth.Token) error { teamName := r.URL.Query().Get(":name") user, err := t.User() if err != nil { return err } rec.Log(user.Email, "get-team", teamName) team, err := auth.GetTeam(teamName) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: "Team not found"} } if !team.ContainsUser(user) { return &errors.HTTP{Code: http.StatusForbidden, Message: "User is not member of this team"} } w.Header().Set("Content-Type", "application/json") return json.NewEncoder(w).Encode(team) }
func (app *App) ValidateTeamOwner(user *auth.User) error { if _, err := auth.GetTeam(app.TeamOwner); err == auth.ErrTeamNotFound { return err } if user.IsAdmin() { return nil } teams, err := user.Teams() if err != nil { return err } for _, t := range teams { if t.Name == app.TeamOwner { return nil } } errorMsg := fmt.Sprintf("You can not set %s team as app's owner. Please set one of your teams as app's owner.", app.TeamOwner) return stderr.New(errorMsg) }
// title: revoke access to a service // path: /services/{service}/team/{team} // method: DELETE // responses: // 200: Access revoked // 400: Team not found // 401: Unauthorized // 404: Service not found // 409: Team does not has access to this service func revokeServiceAccess(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) { r.ParseForm() serviceName := r.URL.Query().Get(":service") s, err := getService(serviceName) if err != nil { return err } allowed := permission.Check(t, permission.PermServiceUpdateRevokeAccess, contextsForServiceProvision(&s)..., ) if !allowed { return permission.ErrUnauthorized } teamName := r.URL.Query().Get(":team") team, err := auth.GetTeam(teamName) if err != nil { if err == auth.ErrTeamNotFound { return &errors.HTTP{Code: http.StatusBadRequest, Message: "Team not found"} } return err } if len(s.Teams) < 2 { msg := "You can not revoke the access from this team, because it is the unique team with access to this service, and a service can not be orphaned" return &errors.HTTP{Code: http.StatusForbidden, Message: msg} } evt, err := event.New(&event.Opts{ Target: serviceTarget(s.Name), Kind: permission.PermServiceUpdateRevokeAccess, Owner: t, CustomData: event.FormToCustomData(r.Form), Allowed: event.Allowed(permission.PermServiceReadEvents, contextsForServiceProvision(&s)...), }) if err != nil { return err } defer func() { evt.Done(err) }() err = s.RevokeAccess(team) if err != nil { return &errors.HTTP{Code: http.StatusConflict, Message: err.Error()} } return s.Update() }
func setTeamOwner(w http.ResponseWriter, r *http.Request, t auth.Token) error { if r.Body == nil { return &errors.HTTP{Code: http.StatusBadRequest, Message: "You must provide a team name."} } defer r.Body.Close() b, err := ioutil.ReadAll(r.Body) if err != nil { return err } teamName := string(b) team, err := auth.GetTeam(teamName) if err != nil { return err } a, err := app.GetByName(r.URL.Query().Get(":app")) if err != nil { return err } canSetTeamOwner := permission.Check(t, permission.PermAppUpdateTeamowner, append(permission.Contexts(permission.CtxTeam, a.Teams), permission.Context(permission.CtxApp, a.Name), permission.Context(permission.CtxPool, a.Pool), )..., ) if !canSetTeamOwner { return &errors.HTTP{ Code: http.StatusForbidden, Message: permission.ErrUnauthorized.Error(), } } u, err := t.User() if err != nil { return err } err = a.SetTeamOwner(team, u) if err != nil { return err } return nil }
// title: grant access to a service // path: /services/{service}/team/{team} // method: PUT // responses: // 200: Service updated // 400: Team not found // 401: Unauthorized // 404: Service not found // 409: Team already has access to this service func grantServiceAccess(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) { r.ParseForm() serviceName := r.URL.Query().Get(":service") s, err := getService(serviceName) if err != nil { return err } allowed := permission.Check(t, permission.PermServiceUpdateGrantAccess, contextsForServiceProvision(&s)..., ) if !allowed { return permission.ErrUnauthorized } teamName := r.URL.Query().Get(":team") team, err := auth.GetTeam(teamName) if err != nil { if err == auth.ErrTeamNotFound { return &errors.HTTP{Code: http.StatusBadRequest, Message: "Team not found"} } return err } evt, err := event.New(&event.Opts{ Target: serviceTarget(s.Name), Kind: permission.PermServiceUpdateGrantAccess, Owner: t, CustomData: event.FormToCustomData(r.Form), Allowed: event.Allowed(permission.PermServiceReadEvents, contextsForServiceProvision(&s)...), }) if err != nil { return err } defer func() { evt.Done(err) }() err = s.GrantAccess(team) if err != nil { return &errors.HTTP{Code: http.StatusConflict, Message: err.Error()} } return s.Update() }
func (app *App) validateTeamOwner() error { _, err := auth.GetTeam(app.TeamOwner) return err }