Beispiel #1
0
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
}
Beispiel #2
0
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
}
Beispiel #3
0
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
}
Beispiel #4
0
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
}
Beispiel #5
0
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
}
Beispiel #6
0
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
}
Beispiel #7
0
// 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})
}
Beispiel #8
0
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
}
Beispiel #9
0
// 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})
}
Beispiel #10
0
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
}
Beispiel #11
0
// 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
}
Beispiel #12
0
// 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})
}
Beispiel #13
0
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
}
Beispiel #14
0
}

// 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,
Beispiel #15
0
func (u *User) ListKeys() (map[string]string, error) {
	gURL := repository.ServerURL()
	c := gandalf.Client{Endpoint: gURL}
	return c.ListKeys(u.Email)
}