Exemple #1
0
// ServerError returns an error suitable for returning to an API
// client, with an error code suitable for various kinds of errors
// generated in packages outside the API.
func ServerError(err error) *params.Error {
	if err == nil {
		return nil
	}
	logger.Tracef("server RPC error %v", errors.Details(err))
	msg := err.Error()
	// Skip past annotations when looking for the code.
	err = errors.Cause(err)
	code, ok := singletonCode(err)
	var info *params.ErrorInfo
	switch {
	case ok:
	case errors.IsUnauthorized(err):
		code = params.CodeUnauthorized
	case errors.IsNotFound(err):
		code = params.CodeNotFound
	case errors.IsUserNotFound(err):
		code = params.CodeUserNotFound
	case errors.IsAlreadyExists(err):
		code = params.CodeAlreadyExists
	case errors.IsNotAssigned(err):
		code = params.CodeNotAssigned
	case state.IsHasAssignedUnitsError(err):
		code = params.CodeHasAssignedUnits
	case state.IsHasHostedModelsError(err):
		code = params.CodeHasHostedModels
	case isNoAddressSetError(err):
		code = params.CodeNoAddressSet
	case errors.IsNotProvisioned(err):
		code = params.CodeNotProvisioned
	case IsUpgradeInProgressError(err):
		code = params.CodeUpgradeInProgress
	case state.IsHasAttachmentsError(err):
		code = params.CodeMachineHasAttachedStorage
	case isUnknownModelError(err):
		code = params.CodeModelNotFound
	case errors.IsNotSupported(err):
		code = params.CodeNotSupported
	case errors.IsBadRequest(err):
		code = params.CodeBadRequest
	case errors.IsMethodNotAllowed(err):
		code = params.CodeMethodNotAllowed
	default:
		if err, ok := err.(*DischargeRequiredError); ok {
			code = params.CodeDischargeRequired
			info = &params.ErrorInfo{
				Macaroon: err.Macaroon,
				// One macaroon fits all.
				MacaroonPath: "/",
			}
			break
		}
		code = params.ErrCode(err)
	}
	return &params.Error{
		Message: msg,
		Code:    code,
		Info:    info,
	}
}
Exemple #2
0
// RemoveUser permanently removes a user from the current controller for each
// entity provided. While the user is permanently removed we keep it's
// information around for auditing purposes.
// TODO(redir): Add information about getting deleted user information when we
// add that capability.
func (api *UserManagerAPI) RemoveUser(entities params.Entities) (params.ErrorResults, error) {
	var deletions params.ErrorResults

	if err := api.check.ChangeAllowed(); err != nil {
		return deletions, errors.Trace(err)
	}

	// Get a handle on the controller model.
	controllerModel, err := api.state.ControllerModel()
	if err != nil {
		return deletions, errors.Trace(err)
	}

	// Create the results list to populate.
	deletions.Results = make([]params.ErrorResult, len(entities.Entities))

	isSuperUser, err := api.hasControllerAdminAccess()
	if err != nil {
		return deletions, errors.Trace(err)
	}
	if !api.isAdmin && !isSuperUser {
		return deletions, common.ErrPerm
	}

	// Remove the entities.
	for i, e := range entities.Entities {
		user, err := names.ParseUserTag(e.Tag)
		if err != nil {
			deletions.Results[i].Error = common.ServerError(err)
			continue
		}

		if controllerModel.Owner().Id() == user.Id() {
			deletions.Results[i].Error = common.ServerError(
				errors.Errorf("cannot delete controller owner %q", user.Name()))
			continue
		}
		err = api.state.RemoveUser(user)
		if err != nil {
			if errors.IsUserNotFound(err) {
				deletions.Results[i].Error = common.ServerError(err)
			} else {
				deletions.Results[i].Error = common.ServerError(
					errors.Annotatef(err, "failed to delete user %q", user.Name()))
			}
			continue
		}
		deletions.Results[i].Error = nil
	}
	return deletions, nil
}
Exemple #3
0
func getAdminEmail(rl *readline.Instance, d db.DB) (string, error) {
	none := ""

	rl.SetPrompt("Enter email: ")
	defer rl.SetPrompt("> ")

	email, err := rl.Readline()
	if err != nil {
		return none, err
	}

	if err := admin.IsAdminEmail(d, email); err != nil {
		if errors.IsUserNotFound(err) {
			return email, nil
		}
		return none, err
	}

	return none, fmt.Errorf("admin %s already exists", email)
}
Exemple #4
0
// Users returns a slice of all users for this model.
func (m *Model) Users() ([]permission.UserAccess, error) {
	if m.st.ModelUUID() != m.UUID() {
		return nil, errors.New("cannot lookup model users outside the current model")
	}
	coll, closer := m.st.getCollection(modelUsersC)
	defer closer()

	var userDocs []userAccessDoc
	err := coll.Find(nil).All(&userDocs)
	if err != nil {
		return nil, errors.Trace(err)
	}

	var modelUsers []permission.UserAccess
	for _, doc := range userDocs {
		// check if the User belonging to this model user has
		// been deleted, in this case we should not return it.
		userTag := names.NewUserTag(doc.UserName)
		if userTag.IsLocal() {
			_, err := m.st.User(userTag)
			if errors.IsUserNotFound(err) {
				continue
			}
			if err != nil {
				return nil, errors.Trace(err)
			}
		}
		mu, err := NewModelUserAccess(m.st, doc)
		if err != nil {
			return nil, errors.Trace(err)
		}
		modelUsers = append(modelUsers, mu)
	}

	return modelUsers, nil
}