func removeKeyFromGandalf(key *auth.Key, u *auth.User) error { gURL := repository.ServerURL() if err := (&gandalf.Client{Endpoint: gURL}).RemoveKey(u.Email, key.Name); err != nil { return fmt.Errorf("Failed to remove the key from git server: %s", err) } return nil }
func createUser(w http.ResponseWriter, r *http.Request) error { var u auth.User err := json.NewDecoder(r.Body).Decode(&u) if err != nil { return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()} } if !validation.ValidateEmail(u.Email) { return &errors.HTTP{Code: http.StatusBadRequest, Message: emailError} } if !validation.ValidateLength(u.Password, passwordMinLen, passwordMaxLen) { return &errors.HTTP{Code: http.StatusBadRequest, Message: passwordError} } if _, err = auth.GetUserByEmail(u.Email); err == nil { return &errors.HTTP{Code: http.StatusConflict, Message: "This email is already registered"} } gURL := repository.ServerURL() c := gandalf.Client{Endpoint: gURL} if _, err := c.NewUser(u.Email, keyToMap(u.Keys)); err != nil { return fmt.Errorf("Failed to create user in the git server: %s", err) } u.Quota = quota.Unlimited if limit, err := config.GetInt("quota:apps-per-user"); err == nil && limit > -1 { u.Quota.Limit = limit } if err := u.Create(); err == nil { rec.Log(u.Email, "create-user") w.WriteHeader(http.StatusCreated) return nil } return err }
func removeUserFromTeamInGandalf(u *auth.User, team *auth.Team) error { gURL := repository.ServerURL() teamApps, err := team.AllowedApps() if err != nil { return err } userApps, err := u.AllowedApps() if err != nil { return err } appsToRemove := make([]string, 0, len(teamApps)) for _, teamApp := range teamApps { found := false for _, userApp := range userApps { if userApp == teamApp { found = true break } } if !found { appsToRemove = append(appsToRemove, teamApp) } } client := gandalf.Client{Endpoint: gURL} if err := client.RevokeAccess(appsToRemove, []string{u.Email}); err != nil { return fmt.Errorf("Failed to revoke access from git repositories: %s", err) } return nil }
func (u *User) CreateOnGandalf() error { gURL := repository.ServerURL() c := gandalf.Client{Endpoint: gURL} if _, err := c.NewUser(u.Email, keyToMap(u.Keys)); err != nil { return fmt.Errorf("Failed to create user in the git server: %s", err) } return nil }
func (u *User) AddKeyGandalf(key *Key) error { key.Name = fmt.Sprintf("%s-%d", u.Email, len(u.Keys)+1) gURL := repository.ServerURL() if err := (&gandalf.Client{Endpoint: gURL}).AddKey(u.Email, keyToMap([]Key{*key})); err != nil { return fmt.Errorf("Failed to add key to git server: %s", err) } return nil }
func addUserToTeamInGandalf(user *auth.User, t *auth.Team) error { gURL := repository.ServerURL() alwdApps, err := t.AllowedApps() if err != nil { return fmt.Errorf("Failed to obtain allowed apps to grant: %s", err) } if err := (&gandalf.Client{Endpoint: gURL}).GrantAccess(alwdApps, []string{user.Email}); err != nil { return fmt.Errorf("Failed to grant access to git repositories: %s", err) } return nil }
// removeUser removes the user from the database and from gandalf server // // If the user is the only one in a team an error will be returned. func removeUser(w http.ResponseWriter, r *http.Request, t *auth.Token) error { u, err := t.User() if err != nil { return err } gURL := repository.ServerURL() c := gandalf.Client{Endpoint: gURL} alwdApps, err := u.AllowedApps() if err != nil { return err } if err := c.RevokeAccess(alwdApps, []string{u.Email}); err != nil { log.Errorf("Failed to revoke access in Gandalf: %s", err) return fmt.Errorf("Failed to revoke acess from git repositories: %s", err) } teams, err := u.Teams() if err != nil { return err } conn, err := db.Conn() if err != nil { return err } defer conn.Close() for _, team := range teams { if len(team.Users) < 2 { msg := fmt.Sprintf(`This user is the last member of the team "%s", so it cannot be removed. Please remove the team, then remove the user.`, team.Name) return &errors.HTTP{Code: http.StatusForbidden, Message: msg} } err = team.RemoveUser(u) if err != nil { return err } // this can be done without the loop err = conn.Teams().Update(bson.M{"_id": team.Name}, team) if err != nil { return err } } rec.Log(u.Email, "remove-user") if err := c.RemoveUser(u.Email); err != nil { log.Errorf("Failed to remove user from gandalf: %s", err) return fmt.Errorf("Failed to remove the user from the git server: %s", err) } return conn.Users().Remove(bson.M{"email": u.Email}) }
func revokeAppAccess(w http.ResponseWriter, r *http.Request, t *auth.Token) error { u, err := t.User() if err != nil { return err } appName := r.URL.Query().Get(":app") teamName := r.URL.Query().Get(":team") rec.Log(u.Email, "revoke-app-access", "app="+appName, "team="+teamName) team := new(auth.Team) app, err := getApp(appName, u) if err != nil { return err } conn, err := db.Conn() if err != nil { return err } defer conn.Close() err = conn.Teams().Find(bson.M{"_id": teamName}).One(team) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: "Team not found"} } if len(app.Teams) == 1 { msg := "You can not revoke the access from this team, because it is the unique team with access to the app, and an app can not be orphaned" return &errors.HTTP{Code: http.StatusForbidden, Message: msg} } err = app.Revoke(team) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()} } err = conn.Apps().Update(bson.M{"name": app.Name}, app) if err != nil { return err } users := getEmailsForRevoking(&app, team) if len(users) > 0 { gURL := repository.ServerURL() if err := (&gandalf.Client{Endpoint: gURL}).RevokeAccess([]string{app.Name}, users); err != nil { return fmt.Errorf("Failed to revoke access in the git server: %s", err) } } return nil }
// Delete deletes an app. // // Delete an app is a process composed of four steps: // // 1. Destroy the app unit // 2. Unbind all service instances from the app // 4. Remove the app from the database func Delete(app *App) error { gURL := repository.ServerURL() (&gandalf.Client{Endpoint: gURL}).RemoveRepository(app.Name) if len(app.Units) > 0 { Provisioner.Destroy(app) app.unbind() } token := app.Env["TSURU_APP_TOKEN"].Value auth.DeleteToken(token) if owner, err := auth.GetUserByEmail(app.Owner); err == nil { auth.ReleaseApp(owner) } conn, err := db.Conn() if err != nil { return err } defer conn.Close() return conn.Apps().Remove(bson.M{"name": app.Name}) }
func GetDiffInDeploys(d *deploy) (string, error) { var list []deploy conn, err := db.Conn() if err != nil { return "", err } defer conn.Close() if err := conn.Deploys().Find(bson.M{"app": d.App}).Sort("-timestamp").All(&list); err != nil { return "", err } if len(list) < 2 { return "The deployment must have at least two commits for the diff.", nil } gandalfClient := gandalf.Client{Endpoint: repository.ServerURL()} diffOutput, err := gandalfClient.GetDiff(d.App, list[1].Commit, list[0].Commit) if err != nil { return "", fmt.Errorf("Caught error getting repository metadata: %s", err.Error()) } return diffOutput, nil }
// Delete deletes an app. // // Delete an app is a process composed of three steps: // // 1. Destroy the app unit // 2. Unbind all service instances from the app // 3. Remove the app from the database func Delete(app *App) error { appName := app.Name wg := asyncDestroyAppProvisioner(app) wg.Add(1) defer wg.Done() go func() { defer ReleaseApplicationLock(appName) wg.Wait() conn, err := db.Conn() if err != nil { log.Errorf("Unable to delete app %s from db: %s", appName, err.Error()) } defer conn.Close() err = conn.Logs(appName).DropCollection() if err != nil { log.Errorf("Ignored error dropping logs collection for app %s: %s", appName, err.Error()) } err = conn.Apps().Remove(bson.M{"name": appName}) if err != nil { log.Errorf("Error trying to destroy app %s from db: %s", appName, err.Error()) } }() gandalfClient := gandalf.Client{Endpoint: repository.ServerURL()} gandalfClient.RemoveRepository(appName) token := app.Env["TSURU_APP_TOKEN"].Value err := AuthScheme.Logout(token) if err != nil { log.Errorf("Unable to remove app token in destroy: %s", err.Error()) } owner, err := auth.GetUserByEmail(app.Owner) if err != nil { log.Errorf("Unable to get app owner in destroy: %s", err.Error()) } else { err = auth.ReleaseApp(owner) if err != nil { log.Errorf("Unable to release app quota: %s", err.Error()) } } return nil }
// Delete deletes an app. // // Delete an app is a process composed of three steps: // // 1. Destroy the app unit // 2. Unbind all service instances from the app // 3. Remove the app from the database func Delete(app *App) error { gURL := repository.ServerURL() (&gandalf.Client{Endpoint: gURL}).RemoveRepository(app.Name) if len(app.Units()) > 0 { Provisioner.Destroy(app) app.unbind() } token := app.Env["TSURU_APP_TOKEN"].Value AuthScheme.Logout(token) if owner, err := auth.GetUserByEmail(app.Owner); err == nil { auth.ReleaseApp(owner) } conn, err := db.Conn() if err != nil { return err } defer conn.Close() err = conn.Logs(app.Name).DropCollection() if err != nil { log.Errorf("Ignored error dropping logs collection for app %s", app.Name) } return conn.Apps().Remove(bson.M{"name": app.Name}) }
func grantAppAccess(w http.ResponseWriter, r *http.Request, t *auth.Token) error { u, err := t.User() if err != nil { return err } appName := r.URL.Query().Get(":app") teamName := r.URL.Query().Get(":team") rec.Log(u.Email, "grant-app-access", "app="+appName, "team="+teamName) team := new(auth.Team) app, err := getApp(appName, u) if err != nil { return err } conn, err := db.Conn() if err != nil { return err } defer conn.Close() err = conn.Teams().Find(bson.M{"_id": teamName}).One(team) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: "Team not found"} } err = app.Grant(team) if err != nil { return &errors.HTTP{Code: http.StatusConflict, Message: err.Error()} } err = conn.Apps().Update(bson.M{"name": app.Name}, app) if err != nil { return err } gURL := repository.ServerURL() gClient := gandalf.Client{Endpoint: gURL} if err := gClient.GrantAccess([]string{app.Name}, team.Users); err != nil { return fmt.Errorf("Failed to grant access in the git server: %s.", err) } return nil }
} // createRepository creates a repository for the app in Gandalf. var createRepository = action.Action{ Name: "create-repository", Forward: func(ctx action.FWContext) (action.Result, error) { var app App switch ctx.Params[0].(type) { case App: app = ctx.Params[0].(App) case *App: app = *ctx.Params[0].(*App) default: return nil, errors.New("First parameter must be App or *App.") } gURL := repository.ServerURL() var users []string for _, t := range app.GetTeams() { users = append(users, t.Users...) } c := gandalf.Client{Endpoint: gURL} _, err := c.NewRepository(app.Name, users, false) return &app, err }, Backward: func(ctx action.BWContext) { app := ctx.FWResult.(*App) gURL := repository.ServerURL() c := gandalf.Client{Endpoint: gURL} c.RemoveRepository(app.Name) }, MinParams: 1,
func (u *User) ListKeys() (map[string]string, error) { gURL := repository.ServerURL() c := gandalf.Client{Endpoint: gURL} return c.ListKeys(u.Email) }