func regenerateAPIToken(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	email := r.URL.Query().Get("user")
	if email == "" {
		email = t.GetUserName()
	}
	allowed := permission.Check(t, permission.PermUserUpdateToken,
		permission.Context(permTypes.CtxUser, email),
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	evt, err := event.New(&event.Opts{
		Target:     userTarget(email),
		Kind:       permission.PermUserUpdateToken,
		Owner:      t,
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermUserReadEvents, permission.Context(permTypes.CtxUser, email)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	u, err := auth.GetUserByEmail(email)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	apiKey, err := u.RegenerateAPIKey()
	if err != nil {
		return err
	}
	w.Header().Add("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(apiKey)
}
title: regenerate token
path: /users/api-key
method: POST
produce: application/json
responses:
200: OK
401: Unauthorized
404: User not found
package api
import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"reflect"
	"runtime"
	"github.com/tsuru/config"
	"github.com/tsuru/tsuru/app"
	"github.com/tsuru/tsuru/auth"
	"github.com/tsuru/tsuru/errors"
	"github.com/tsuru/tsuru/event"
	"github.com/tsuru/tsuru/log"
	"github.com/tsuru/tsuru/permission"
	"github.com/tsuru/tsuru/provision/pool"
	"github.com/tsuru/tsuru/service"
	"github.com/tsuru/tsuru/servicemanager"
	authTypes "github.com/tsuru/tsuru/types/auth"
	permTypes "github.com/tsuru/tsuru/types/permission"
	"github.com/tsuru/tsuru/volume"
)
const (
	nonManagedSchemeMsg = "Authentication scheme does not allow this operation."
	createDisabledMsg   = "User registration is disabled for non-admin users."
)
var createDisabledErr = &errors.HTTP{Code: http.StatusUnauthorized, Message: createDisabledMsg}
func handleAuthError(err error) error {
	if err == authTypes.ErrUserNotFound {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	switch err.(type) {
	case *errors.ValidationError:
		return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	case *errors.ConflictError:
		return &errors.HTTP{Code: http.StatusConflict, Message: err.Error()}
	case *errors.NotAuthorizedError:
		return &errors.HTTP{Code: http.StatusForbidden, Message: err.Error()}
	case auth.AuthenticationFailure:
		return &errors.HTTP{Code: http.StatusUnauthorized, Message: err.Error()}
	default:
		return err
	}
}
func userTarget(u string) event.Target {
	return event.Target{Type: event.TargetTypeUser, Value: u}
}
func teamTarget(t string) event.Target {
	return event.Target{Type: event.TargetTypeTeam, Value: t}
}
func createUser(w http.ResponseWriter, r *http.Request) error {
	ctx := r.Context()
	registrationEnabled, _ := config.GetBool("auth:user-registration")
	if !registrationEnabled {
		token := r.Header.Get("Authorization")
		t, err := app.AuthScheme.Auth(ctx, token)
		if err != nil {
			return createDisabledErr
		}
		if !permission.Check(t, permission.PermUserCreate) {
			return createDisabledErr
		}
	}
	email := InputValue(r, "email")
	password := InputValue(r, "password")
	evt, err := event.New(&event.Opts{
		Target:     userTarget(email),
		Kind:       permission.PermUserCreate,
		RawOwner:   event.Owner{Type: event.OwnerTypeUser, Name: email},
		CustomData: event.FormToCustomData(InputFields(r, "password")),
		Allowed:    event.Allowed(permission.PermUserReadEvents, permission.Context(permTypes.CtxUser, email)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	u := auth.User{
		Email:    email,
		Password: password,
	}
	_, err = app.AuthScheme.Create(ctx, &u)
	if err != nil {
		return handleAuthError(err)
	}
	w.WriteHeader(http.StatusCreated)
	return nil
}
func login(w http.ResponseWriter, r *http.Request) (err error) {
	ctx := r.Context()
	params := map[string]string{
		"email": r.URL.Query().Get(":email"),
	}
	fields := InputFields(r)
	for key, values := range fields {
		params[key] = values[0]
	}
	token, err := app.AuthScheme.Login(ctx, params)
	if err != nil {
		return handleAuthError(err)
	}
	return json.NewEncoder(w).Encode(map[string]string{"token": token.GetValue()})
}
func logout(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	return app.AuthScheme.Logout(r.Context(), t.GetValue())
}
func changePassword(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	ctx := r.Context()
	managed, ok := app.AuthScheme.(auth.ManagedScheme)
	if !ok {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: nonManagedSchemeMsg}
	}
	evt, err := event.New(&event.Opts{
		Target:  userTarget(t.GetUserName()),
		Kind:    permission.PermUserUpdatePassword,
		Owner:   t,
		Allowed: event.Allowed(permission.PermUserReadEvents, permission.Context(permTypes.CtxUser, t.GetUserName())),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	oldPassword := InputValue(r, "old")
	newPassword := InputValue(r, "new")
	confirmPassword := InputValue(r, "confirm")
	if oldPassword == "" || newPassword == "" {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "Both the old and the new passwords are required.",
		}
	}
	if newPassword != confirmPassword {
		return &errors.HTTP{
			Code:    http.StatusBadRequest,
			Message: "New password and password confirmation didn't match.",
		}
	}
	err = managed.ChangePassword(ctx, t, oldPassword, newPassword)
	if err != nil {
		return handleAuthError(err)
	}
	return nil
}
func resetPassword(w http.ResponseWriter, r *http.Request) (err error) {
	ctx := r.Context()
	managed, ok := app.AuthScheme.(auth.ManagedScheme)
	if !ok {
		return &errors.HTTP{Code: http.StatusBadRequest, Message: nonManagedSchemeMsg}
	}
	email := r.URL.Query().Get(":email")
	token := InputValue(r, "token")
	evt, err := event.New(&event.Opts{
		Target:     userTarget(email),
		Kind:       permission.PermUserUpdateReset,
		RawOwner:   event.Owner{Type: event.OwnerTypeUser, Name: email},
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermUserReadEvents, permission.Context(permTypes.CtxUser, email)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	u, err := auth.GetUserByEmail(email)
	if err != nil {
		if err == authTypes.ErrUserNotFound {
			return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
		}
		return err
	}
	if token == "" {
		return managed.StartPasswordReset(ctx, u)
	}
	return managed.ResetPassword(ctx, u, token)
}
var teamRenameFns = []func(ctx context.Context, oldName, newName string) error{
	app.RenameTeam,
	service.RenameServiceTeam,
	service.RenameServiceInstanceTeam,
	volume.RenameTeam,
	pool.RenamePoolTeam,
}
func updateTeam(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	ctx := r.Context()
	name := r.URL.Query().Get(":name")
	type teamChange struct {
		NewName string
		Tags    []string
	}
	changeRequest := teamChange{}
	if err := ParseInput(r, &changeRequest); err != nil {
		return err
	}
	tags, _ := InputValues(r, "tag")
	changeRequest.Tags = append(changeRequest.Tags, tags...)  
	allowed := permission.Check(t, permission.PermTeamUpdate,
		permission.Context(permTypes.CtxTeam, name),
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	_, err := servicemanager.Team.FindByName(ctx, name)
	if err != nil {
		if err == authTypes.ErrTeamNotFound {
			return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
		}
		return err
	}
	evt, err := event.New(&event.Opts{
		Target:     teamTarget(name),
		Kind:       permission.PermTeamUpdate,
		Owner:      t,
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermTeamReadEvents, permission.Context(permTypes.CtxTeam, name)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	if changeRequest.NewName == "" {
		return servicemanager.Team.Update(ctx, name, changeRequest.Tags)
	}
	u, err := t.User()
	if err != nil {
		return err
	}
	err = servicemanager.Team.Create(ctx, changeRequest.NewName, changeRequest.Tags, u)
	if err != nil {
		return err
	}
	var toRollback []func(ctx context.Context, oldName, newName string) error
	defer func() {
		if err == nil {
			return
		}
		rollbackErr := servicemanager.Team.Remove(ctx, changeRequest.NewName)
		if rollbackErr != nil {
			log.Errorf("error rolling back team creation from %v to %v", name, changeRequest.NewName)
		}
		for _, rollbackFn := range toRollback {
			rollbackErr := rollbackFn(ctx, changeRequest.NewName, name)
			if rollbackErr != nil {
				fnName := runtime.FuncForPC(reflect.ValueOf(rollbackFn).Pointer()).Name()
				log.Errorf("error rolling back team name change in %v from %q to %q", fnName, name, changeRequest.NewName)
			}
		}
	}()
	for _, fn := range teamRenameFns {
		err = fn(ctx, name, changeRequest.NewName)
		if err != nil {
			return err
		}
		toRollback = append(toRollback, fn)
	}
	return servicemanager.Team.Remove(ctx, name)
}
func createTeam(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	ctx := r.Context()
	allowed := permission.Check(t, permission.PermTeamCreate)
	if !allowed {
		return permission.ErrUnauthorized
	}
	var team authTypes.Team
	if err := ParseInput(r, &team); err != nil {
		return err
	}
	tags, _ := InputValues(r, "tag")
	team.Tags = append(team.Tags, tags...)  
	evt, err := event.New(&event.Opts{
		Target:     teamTarget(team.Name),
		Kind:       permission.PermTeamCreate,
		Owner:      t,
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermTeamReadEvents, permission.Context(permTypes.CtxTeam, team.Name)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	u, err := t.User()
	if err != nil {
		return err
	}
	err = servicemanager.Team.Create(ctx, team.Name, team.Tags, u)
	switch err {
	case authTypes.ErrInvalidTeamName:
		return &errors.HTTP{Code: http.StatusBadRequest, Message: err.Error()}
	case authTypes.ErrTeamAlreadyExists:
		return &errors.HTTP{Code: http.StatusConflict, Message: err.Error()}
	}
	if err == nil {
		w.WriteHeader(http.StatusCreated)
	}
	return err
}
func removeTeam(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	ctx := r.Context()
	name := r.URL.Query().Get(":name")
	allowed := permission.Check(t, permission.PermTeamDelete,
		permission.Context(permTypes.CtxTeam, name),
	)
	if !allowed {
		return &errors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf(`Team "%s" not found.`, name)}
	}
	evt, err := event.New(&event.Opts{
		Target:     teamTarget(name),
		Kind:       permission.PermTeamDelete,
		Owner:      t,
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermTeamReadEvents, permission.Context(permTypes.CtxTeam, name)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	err = servicemanager.Team.Remove(ctx, name)
	if err != nil {
		if _, ok := err.(*authTypes.ErrTeamStillUsed); ok {
			msg := fmt.Sprintf("This team cannot be removed because there are still references to it:\n%s", err)
			return &errors.HTTP{Code: http.StatusForbidden, Message: msg}
		}
		if err == authTypes.ErrTeamNotFound {
			return &errors.HTTP{Code: http.StatusNotFound, Message: fmt.Sprintf(`Team "%s" not found.`, name)}
		}
		return err
	}
	return nil
}
func teamList(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	ctx := r.Context()
	permsForTeam := permission.PermissionRegistry.PermissionsWithContextType(permTypes.CtxTeam)
	teams, err := servicemanager.Team.List(ctx)
	if err != nil {
		return err
	}
	teamsMap := map[string]authTypes.Team{}
	permsMap := map[string][]string{}
	perms, err := t.Permissions()
	if err != nil {
		return err
	}
	for _, team := range teams {
		teamsMap[team.Name] = team
		teamCtx := permission.Context(permTypes.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
				permsMap[team.Name] = append(permsMap[team.Name], p.FullName())
			}
		}
	}
	if len(permsMap) == 0 {
		w.WriteHeader(http.StatusNoContent)
		return nil
	}
	var result []map[string]interface{}
	for name, permissions := range permsMap {
		result = append(result, map[string]interface{}{
			"name":        name,
			"tags":        teamsMap[name].Tags,
			"permissions": permissions,
		})
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(result)
}
func teamInfo(w http.ResponseWriter, r *http.Request, t auth.Token) error {
	ctx := r.Context()
	teamName := r.URL.Query().Get(":name")
	team, err := servicemanager.Team.FindByName(ctx, teamName)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	canRead := permission.Check(t, permission.PermTeamRead)
	if !canRead {
		return permission.ErrUnauthorized
	}
	apps, err := app.List(ctx, &app.Filter{
		Extra:     map[string][]string{"teams": {team.Name}},
		TeamOwner: team.Name})
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	pools, err := pool.ListPoolsForTeam(ctx, team.Name)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	users, err := auth.ListUsers()
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	cachedRoles := make(map[string]permission.Role)
	includedUsers := make([]*apiUser, 0)
	for _, user := range users {
		for _, roleInstance := range user.Roles {
			role, ok := cachedRoles[roleInstance.Name]
			if !ok {
				roleFound, err := permission.FindRole(roleInstance.Name)
				if err != nil {
					return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
				}
				cachedRoles[roleInstance.Name] = roleFound
				role = cachedRoles[roleInstance.Name]
			}
			if role.ContextType == permTypes.CtxGlobal || (role.ContextType == permTypes.CtxTeam && roleInstance.ContextValue == team.Name) {
				canInclude := permission.Check(t, permission.PermTeam)
				if canInclude {
					roleMap := make(map[string]*permission.Role)
					perms, err := t.Permissions()
					if err != nil {
						return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
					}
					userData, err := createAPIUser(perms, &user, roleMap, canInclude)
					if err != nil {
						return &errors.HTTP{Code: http.StatusInternalServerError, Message: err.Error()}
					}
					includedUsers = append(includedUsers, userData)
					break
				}
			}
		}
	}
	result := map[string]interface{}{
		"name":  team.Name,
		"tags":  team.Tags,
		"users": includedUsers,
		"pools": pools,
		"apps":  apps,
	}
	w.Header().Set("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(result)
}
func removeUser(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) {
	ctx := r.Context()
	email := r.URL.Query().Get("user")
	if email == "" {
		email = t.GetUserName()
	}
	allowed := permission.Check(t, permission.PermUserDelete,
		permission.Context(permTypes.CtxUser, email),
	)
	if !allowed {
		return permission.ErrUnauthorized
	}
	evt, err := event.New(&event.Opts{
		Target:     userTarget(email),
		Kind:       permission.PermUserDelete,
		Owner:      t,
		CustomData: event.FormToCustomData(InputFields(r)),
		Allowed:    event.Allowed(permission.PermUserReadEvents, permission.Context(permTypes.CtxUser, email)),
	})
	if err != nil {
		return err
	}
	defer func() { evt.Done(err) }()
	u, err := auth.GetUserByEmail(email)
	if err != nil {
		return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()}
	}
	return app.AuthScheme.Remove(ctx, u)
}
type schemeData struct {
	Name string          `json:"name"`
	Data auth.SchemeInfo `json:"data"`
}
func authScheme(w http.ResponseWriter, r *http.Request) error {
	info, err := app.AuthScheme.Info(r.Context())
	if err != nil {
		return err
	}
	data := schemeData{Name: app.AuthScheme.Name(), Data: info}
	w.Header().Add("Content-Type", "application/json")
	return json.NewEncoder(w).Encode(data)
}