2014-08-29 11:32:52 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2020-01-24 22:00:29 +03:00
// Copyright 2020 The Gitea Authors.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2014-08-29 11:32:52 +04:00
package admin
import (
2024-02-04 16:29:09 +03:00
"errors"
2021-04-05 18:30:52 +03:00
"net/http"
2021-11-16 21:18:25 +03:00
"net/url"
2020-12-25 12:59:32 +03:00
"strconv"
2014-08-29 11:32:52 +04:00
"strings"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/models"
2022-01-02 16:12:35 +03:00
"code.gitea.io/gitea/models/auth"
2021-09-24 14:32:56 +03:00
"code.gitea.io/gitea/models/db"
2023-08-31 12:21:18 +03:00
org_model "code.gitea.io/gitea/models/organization"
repo_model "code.gitea.io/gitea/models/repo"
2021-11-11 10:03:30 +03:00
user_model "code.gitea.io/gitea/models/user"
2023-02-19 10:35:20 +03:00
"code.gitea.io/gitea/modules/auth/password"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
2024-02-04 16:29:09 +03:00
"code.gitea.io/gitea/modules/optional"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/setting"
2021-10-12 21:11:35 +03:00
"code.gitea.io/gitea/modules/util"
2021-01-26 18:36:53 +03:00
"code.gitea.io/gitea/modules/web"
2021-06-09 02:33:54 +03:00
"code.gitea.io/gitea/routers/web/explore"
2021-11-22 18:21:55 +03:00
user_setting "code.gitea.io/gitea/routers/web/user/setting"
2024-02-27 10:12:22 +03:00
"code.gitea.io/gitea/services/context"
2021-04-06 22:44:05 +03:00
"code.gitea.io/gitea/services/forms"
2019-09-24 08:02:49 +03:00
"code.gitea.io/gitea/services/mailer"
2021-11-22 18:21:55 +03:00
user_service "code.gitea.io/gitea/services/user"
2014-08-29 11:32:52 +04:00
)
const (
2016-11-21 06:21:24 +03:00
tplUsers base . TplName = "admin/user/list"
tplUserNew base . TplName = "admin/user/new"
2023-08-31 12:21:18 +03:00
tplUserView base . TplName = "admin/user/view"
2016-11-21 06:21:24 +03:00
tplUserEdit base . TplName = "admin/user/edit"
2014-08-29 11:32:52 +04:00
)
2023-11-09 13:11:45 +03:00
// UserSearchDefaultAdminSort is the default sort type for admin view
const UserSearchDefaultAdminSort = "alphabetically"
2016-11-21 06:21:24 +03:00
// Users show all the users
2016-03-11 19:56:52 +03:00
func Users ( ctx * context . Context ) {
2014-08-29 16:50:43 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.users" )
ctx . Data [ "PageIsAdminUsers" ] = true
2022-03-02 18:30:14 +03:00
extraParamStrings := map [ string ] string { }
2021-10-12 21:11:35 +03:00
statusFilterKeys := [ ] string { "is_active" , "is_admin" , "is_restricted" , "is_2fa_enabled" , "is_prohibit_login" }
statusFilterMap := map [ string ] string { }
for _ , filterKey := range statusFilterKeys {
2022-03-02 18:30:14 +03:00
paramKey := "status_filter[" + filterKey + "]"
paramVal := ctx . FormString ( paramKey )
statusFilterMap [ filterKey ] = paramVal
if paramVal != "" {
extraParamStrings [ paramKey ] = paramVal
}
2021-10-12 21:11:35 +03:00
}
sortType := ctx . FormString ( "sort" )
if sortType == "" {
2023-11-09 13:11:45 +03:00
sortType = UserSearchDefaultAdminSort
2023-05-06 17:04:55 +03:00
ctx . SetFormString ( "sort" , sortType )
2021-10-12 21:11:35 +03:00
}
2023-07-04 21:36:08 +03:00
ctx . PageData [ "adminUserListSearchForm" ] = map [ string ] any {
2021-10-12 21:11:35 +03:00
"StatusFilterMap" : statusFilterMap ,
"SortType" : sortType ,
}
2021-11-24 12:49:20 +03:00
explore . RenderUserSearch ( ctx , & user_model . SearchUserOptions {
2022-03-22 10:03:22 +03:00
Actor : ctx . Doer ,
2021-11-24 12:49:20 +03:00
Type : user_model . UserTypeIndividual ,
2021-09-24 14:32:56 +03:00
ListOptions : db . ListOptions {
2020-01-24 22:00:29 +03:00
PageSize : setting . UI . Admin . UserPagingNum ,
} ,
2021-10-12 21:11:35 +03:00
SearchByEmail : true ,
IsActive : util . OptionalBoolParse ( statusFilterMap [ "is_active" ] ) ,
IsAdmin : util . OptionalBoolParse ( statusFilterMap [ "is_admin" ] ) ,
IsRestricted : util . OptionalBoolParse ( statusFilterMap [ "is_restricted" ] ) ,
IsTwoFactorEnabled : util . OptionalBoolParse ( statusFilterMap [ "is_2fa_enabled" ] ) ,
IsProhibitLogin : util . OptionalBoolParse ( statusFilterMap [ "is_prohibit_login" ] ) ,
2024-04-27 11:03:49 +03:00
IncludeReserved : true , // administrator needs to list all accounts include reserved, bot, remote ones
2022-03-02 18:30:14 +03:00
ExtraParamStrings : extraParamStrings ,
2017-10-24 20:36:19 +03:00
} , tplUsers )
2014-08-29 11:32:52 +04:00
}
2016-11-21 06:21:24 +03:00
// NewUser render adding a new user page
2016-03-11 19:56:52 +03:00
func NewUser ( ctx * context . Context ) {
2014-08-29 11:32:52 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.users.new_account" )
ctx . Data [ "PageIsAdminUsers" ] = true
2021-06-26 22:53:14 +03:00
ctx . Data [ "DefaultUserVisibilityMode" ] = setting . Service . DefaultUserVisibilityMode
2021-06-27 21:47:35 +03:00
ctx . Data [ "AllowedUserVisibilityModes" ] = setting . Service . AllowedUserVisibilityModesSlice . ToVisibleTypeSlice ( )
2014-08-29 11:32:52 +04:00
2015-09-13 16:51:51 +03:00
ctx . Data [ "login_type" ] = "0-0"
2023-11-24 06:49:41 +03:00
sources , err := db . Find [ auth . Source ] ( ctx , auth . FindSourcesOptions {
2024-03-02 18:42:31 +03:00
IsActive : optional . Some ( true ) ,
2023-11-03 04:41:00 +03:00
} )
2014-08-29 11:32:52 +04:00
if err != nil {
2022-01-02 16:12:35 +03:00
ctx . ServerError ( "auth.Sources" , err )
2014-08-29 11:32:52 +04:00
return
}
2015-09-13 16:51:51 +03:00
ctx . Data [ "Sources" ] = sources
2015-09-26 02:45:44 +03:00
ctx . Data [ "CanSendEmail" ] = setting . MailService != nil
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplUserNew )
2014-08-29 11:32:52 +04:00
}
2016-11-21 06:21:24 +03:00
// NewUserPost response for adding a new user
2021-01-26 18:36:53 +03:00
func NewUserPost ( ctx * context . Context ) {
2021-04-06 22:44:05 +03:00
form := web . GetForm ( ctx ) . ( * forms . AdminCreateUserForm )
2014-08-29 11:32:52 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.users.new_account" )
ctx . Data [ "PageIsAdminUsers" ] = true
2021-06-26 22:53:14 +03:00
ctx . Data [ "DefaultUserVisibilityMode" ] = setting . Service . DefaultUserVisibilityMode
2023-03-30 19:29:57 +03:00
ctx . Data [ "AllowedUserVisibilityModes" ] = setting . Service . AllowedUserVisibilityModesSlice . ToVisibleTypeSlice ( )
2014-08-29 11:32:52 +04:00
2023-11-24 06:49:41 +03:00
sources , err := db . Find [ auth . Source ] ( ctx , auth . FindSourcesOptions {
2024-03-02 18:42:31 +03:00
IsActive : optional . Some ( true ) ,
2023-11-03 04:41:00 +03:00
} )
2015-09-13 16:51:51 +03:00
if err != nil {
2022-01-02 16:12:35 +03:00
ctx . ServerError ( "auth.Sources" , err )
2014-08-29 11:32:52 +04:00
return
}
2015-09-13 16:51:51 +03:00
ctx . Data [ "Sources" ] = sources
2014-08-29 11:32:52 +04:00
2015-09-26 02:45:44 +03:00
ctx . Data [ "CanSendEmail" ] = setting . MailService != nil
2015-09-13 16:51:51 +03:00
if ctx . HasError ( ) {
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplUserNew )
2014-08-29 11:32:52 +04:00
return
}
2021-11-24 12:49:20 +03:00
u := & user_model . User {
2019-11-04 22:10:37 +03:00
Name : form . UserName ,
Email : form . Email ,
Passwd : form . Password ,
2022-01-02 16:12:35 +03:00
LoginType : auth . Plain ,
2014-08-29 11:32:52 +04:00
}
2022-04-29 22:38:11 +03:00
overwriteDefault := & user_model . CreateUserOverwriteOptions {
2024-02-23 05:18:33 +03:00
IsActive : optional . Some ( true ) ,
2022-04-29 22:38:11 +03:00
Visibility : & form . Visibility ,
}
2014-08-29 11:32:52 +04:00
if len ( form . LoginType ) > 0 {
fields := strings . Split ( form . LoginType , "-" )
2015-09-13 16:51:51 +03:00
if len ( fields ) == 2 {
2020-12-25 12:59:32 +03:00
lType , _ := strconv . ParseInt ( fields [ 0 ] , 10 , 0 )
2022-01-02 16:12:35 +03:00
u . LoginType = auth . Type ( lType )
2020-12-25 12:59:32 +03:00
u . LoginSource , _ = strconv . ParseInt ( fields [ 1 ] , 10 , 64 )
2015-09-13 16:51:51 +03:00
u . LoginName = form . LoginName
}
2014-08-29 11:32:52 +04:00
}
2022-01-02 16:12:35 +03:00
if u . LoginType == auth . NoType || u . LoginType == auth . Plain {
2019-11-20 03:07:51 +03:00
if len ( form . Password ) < setting . MinPasswordLength {
ctx . Data [ "Err_Password" ] = true
ctx . RenderWithErr ( ctx . Tr ( "auth.password_too_short" , setting . MinPasswordLength ) , tplUserNew , & form )
return
}
2019-11-04 22:10:37 +03:00
if ! password . IsComplexEnough ( form . Password ) {
2019-11-20 03:07:51 +03:00
ctx . Data [ "Err_Password" ] = true
2023-05-08 12:36:54 +03:00
ctx . RenderWithErr ( password . BuildComplexityError ( ctx . Locale ) , tplUserNew , & form )
2019-11-04 22:10:37 +03:00
return
}
2024-02-04 16:29:09 +03:00
if err := password . IsPwned ( ctx , form . Password ) ; err != nil {
2020-09-09 01:06:39 +03:00
ctx . Data [ "Err_Password" ] = true
errMsg := ctx . Tr ( "auth.password_pwned" )
2024-02-04 16:29:09 +03:00
if password . IsErrIsPwnedRequest ( err ) {
2020-09-09 01:06:39 +03:00
log . Error ( err . Error ( ) )
errMsg = ctx . Tr ( "auth.password_pwned_err" )
}
ctx . RenderWithErr ( errMsg , tplUserNew , & form )
return
}
2019-11-04 22:10:37 +03:00
u . MustChangePassword = form . MustChangePassword
2019-10-14 18:24:26 +03:00
}
2021-06-26 22:53:14 +03:00
2024-03-05 08:55:47 +03:00
if err := user_model . AdminCreateUser ( ctx , u , overwriteDefault ) ; err != nil {
2015-03-27 00:11:47 +03:00
switch {
2021-11-24 12:49:20 +03:00
case user_model . IsErrUserAlreadyExist ( err ) :
2014-08-29 11:32:52 +04:00
ctx . Data [ "Err_UserName" ] = true
2016-11-21 06:21:24 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.username_been_taken" ) , tplUserNew , & form )
2021-11-11 10:03:30 +03:00
case user_model . IsErrEmailAlreadyUsed ( err ) :
2014-08-29 11:32:52 +04:00
ctx . Data [ "Err_Email" ] = true
2016-11-21 06:21:24 +03:00
ctx . RenderWithErr ( ctx . Tr ( "form.email_been_used" ) , tplUserNew , & form )
2024-02-04 16:29:09 +03:00
case user_model . IsErrEmailInvalid ( err ) , user_model . IsErrEmailCharIsNotSupported ( err ) :
2020-11-14 19:53:43 +03:00
ctx . Data [ "Err_Email" ] = true
ctx . RenderWithErr ( ctx . Tr ( "form.email_invalid" ) , tplUserNew , & form )
2021-11-24 12:49:20 +03:00
case db . IsErrNameReserved ( err ) :
2014-08-29 11:32:52 +04:00
ctx . Data [ "Err_UserName" ] = true
2021-11-24 12:49:20 +03:00
ctx . RenderWithErr ( ctx . Tr ( "user.form.name_reserved" , err . ( db . ErrNameReserved ) . Name ) , tplUserNew , & form )
case db . IsErrNamePatternNotAllowed ( err ) :
2015-03-27 00:11:47 +03:00
ctx . Data [ "Err_UserName" ] = true
2021-11-24 12:49:20 +03:00
ctx . RenderWithErr ( ctx . Tr ( "user.form.name_pattern_not_allowed" , err . ( db . ErrNamePatternNotAllowed ) . Pattern ) , tplUserNew , & form )
case db . IsErrNameCharsNotAllowed ( err ) :
2020-02-23 22:52:05 +03:00
ctx . Data [ "Err_UserName" ] = true
2021-11-24 12:49:20 +03:00
ctx . RenderWithErr ( ctx . Tr ( "user.form.name_chars_not_allowed" , err . ( db . ErrNameCharsNotAllowed ) . Name ) , tplUserNew , & form )
2014-08-29 11:32:52 +04:00
default :
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "CreateUser" , err )
2014-08-29 11:32:52 +04:00
}
return
}
2024-03-11 09:07:36 +03:00
if ! user_model . IsEmailDomainAllowed ( u . Email ) {
ctx . Flash . Warning ( ctx . Tr ( "form.email_domain_is_not_allowed" , u . Email ) )
}
2022-03-22 10:03:22 +03:00
log . Trace ( "Account created by admin (%s): %s" , ctx . Doer . Name , u . Name )
2015-09-13 16:51:51 +03:00
2016-07-15 19:36:39 +03:00
// Send email notification.
2019-09-24 08:02:49 +03:00
if form . SendNotify {
2021-04-02 13:25:13 +03:00
mailer . SendRegisterNotifyMail ( u )
2015-09-26 02:45:44 +03:00
}
2015-09-13 16:51:51 +03:00
ctx . Flash . Success ( ctx . Tr ( "admin.users.new_success" , u . Name ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin/users/" + strconv . FormatInt ( u . ID , 10 ) )
2014-08-29 11:32:52 +04:00
}
2021-11-24 12:49:20 +03:00
func prepareUserInfo ( ctx * context . Context ) * user_model . User {
2022-12-03 05:48:26 +03:00
u , err := user_model . GetUserByID ( ctx , ctx . ParamsInt64 ( ":userid" ) )
2014-08-29 11:32:52 +04:00
if err != nil {
2022-08-29 16:44:39 +03:00
if user_model . IsErrUserNotExist ( err ) {
ctx . Redirect ( setting . AppSubURL + "/admin/users" )
} else {
ctx . ServerError ( "GetUserByID" , err )
}
2015-09-13 18:07:21 +03:00
return nil
2014-08-29 11:32:52 +04:00
}
ctx . Data [ "User" ] = u
2015-09-13 16:51:51 +03:00
2015-09-13 18:07:21 +03:00
if u . LoginSource > 0 {
2023-10-11 07:24:07 +03:00
ctx . Data [ "LoginSource" ] , err = auth . GetSourceByID ( ctx , u . LoginSource )
2015-09-13 18:07:21 +03:00
if err != nil {
2022-01-02 16:12:35 +03:00
ctx . ServerError ( "auth.GetSourceByID" , err )
2015-09-13 18:07:21 +03:00
return nil
}
} else {
2022-01-02 16:12:35 +03:00
ctx . Data [ "LoginSource" ] = & auth . Source { }
2015-09-13 18:07:21 +03:00
}
2023-11-24 06:49:41 +03:00
sources , err := db . Find [ auth . Source ] ( ctx , auth . FindSourcesOptions { } )
2014-08-29 11:32:52 +04:00
if err != nil {
2022-01-02 16:12:35 +03:00
ctx . ServerError ( "auth.Sources" , err )
2015-09-13 18:07:21 +03:00
return nil
2014-08-29 11:32:52 +04:00
}
2015-09-13 18:07:21 +03:00
ctx . Data [ "Sources" ] = sources
2023-09-15 09:13:19 +03:00
hasTOTP , err := auth . HasTwoFactorByUID ( ctx , u . ID )
2021-01-05 16:54:48 +03:00
if err != nil {
2022-03-02 03:24:31 +03:00
ctx . ServerError ( "auth.HasTwoFactorByUID" , err )
return nil
}
2023-09-16 17:39:12 +03:00
hasWebAuthn , err := auth . HasWebAuthnRegistrationsByUID ( ctx , u . ID )
2022-03-02 03:24:31 +03:00
if err != nil {
ctx . ServerError ( "auth.HasWebAuthnRegistrationsByUID" , err )
return nil
2021-01-05 16:54:48 +03:00
}
2022-03-02 03:24:31 +03:00
ctx . Data [ "TwoFactorEnabled" ] = hasTOTP || hasWebAuthn
2021-01-05 16:54:48 +03:00
2015-09-13 18:07:21 +03:00
return u
2014-08-29 11:32:52 +04:00
}
2023-08-31 12:21:18 +03:00
func ViewUser ( ctx * context . Context ) {
ctx . Data [ "Title" ] = ctx . Tr ( "admin.users.details" )
ctx . Data [ "PageIsAdminUsers" ] = true
ctx . Data [ "DisableRegularOrgCreation" ] = setting . Admin . DisableRegularOrgCreation
ctx . Data [ "DisableMigrations" ] = setting . Repository . DisableMigrations
ctx . Data [ "AllowedUserVisibilityModes" ] = setting . Service . AllowedUserVisibilityModesSlice . ToVisibleTypeSlice ( )
u := prepareUserInfo ( ctx )
if ctx . Written ( ) {
return
}
repos , count , err := repo_model . SearchRepository ( ctx , & repo_model . SearchRepoOptions {
2024-03-22 15:53:52 +03:00
ListOptions : db . ListOptionsAll ,
2023-08-31 12:21:18 +03:00
OwnerID : u . ID ,
OrderBy : db . SearchOrderByAlphabetically ,
Private : true ,
2024-02-29 21:52:49 +03:00
Collaborate : optional . Some ( false ) ,
2023-08-31 12:21:18 +03:00
} )
if err != nil {
ctx . ServerError ( "SearchRepository" , err )
return
}
ctx . Data [ "Repos" ] = repos
ctx . Data [ "ReposTotal" ] = int ( count )
2023-09-14 20:09:32 +03:00
emails , err := user_model . GetEmailAddresses ( ctx , u . ID )
2023-08-31 12:21:18 +03:00
if err != nil {
ctx . ServerError ( "GetEmailAddresses" , err )
return
}
ctx . Data [ "Emails" ] = emails
ctx . Data [ "EmailsTotal" ] = len ( emails )
2023-11-24 06:49:41 +03:00
orgs , err := db . Find [ org_model . Organization ] ( ctx , org_model . FindOrgOptions {
2024-03-22 15:53:52 +03:00
ListOptions : db . ListOptionsAll ,
2023-08-31 12:21:18 +03:00
UserID : u . ID ,
IncludePrivate : true ,
} )
if err != nil {
ctx . ServerError ( "FindOrgs" , err )
return
}
ctx . Data [ "Users" ] = orgs // needed to be able to use explore/user_list template
ctx . Data [ "OrgsTotal" ] = len ( orgs )
ctx . HTML ( http . StatusOK , tplUserView )
}
2023-10-05 04:08:19 +03:00
func editUserCommon ( ctx * context . Context ) {
2014-08-29 11:32:52 +04:00
ctx . Data [ "Title" ] = ctx . Tr ( "admin.users.edit_account" )
ctx . Data [ "PageIsAdminUsers" ] = true
2017-02-14 15:16:00 +03:00
ctx . Data [ "DisableRegularOrgCreation" ] = setting . Admin . DisableRegularOrgCreation
2020-12-21 17:39:41 +03:00
ctx . Data [ "DisableMigrations" ] = setting . Repository . DisableMigrations
2021-06-27 21:47:35 +03:00
ctx . Data [ "AllowedUserVisibilityModes" ] = setting . Service . AllowedUserVisibilityModesSlice . ToVisibleTypeSlice ( )
2023-10-05 04:08:19 +03:00
ctx . Data [ "DisableGravatar" ] = setting . Config ( ) . Picture . DisableGravatar . Value ( ctx )
}
2014-08-29 11:32:52 +04:00
2023-10-05 04:08:19 +03:00
// EditUser show editing user page
func EditUser ( ctx * context . Context ) {
editUserCommon ( ctx )
2015-09-13 18:07:21 +03:00
prepareUserInfo ( ctx )
if ctx . Written ( ) {
2014-08-29 11:32:52 +04:00
return
}
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplUserEdit )
2015-09-13 18:07:21 +03:00
}
2021-07-08 14:38:13 +03:00
// EditUserPost response for editing user
2021-01-26 18:36:53 +03:00
func EditUserPost ( ctx * context . Context ) {
2023-10-05 04:08:19 +03:00
editUserCommon ( ctx )
2015-09-13 18:07:21 +03:00
u := prepareUserInfo ( ctx )
if ctx . Written ( ) {
2014-08-29 11:32:52 +04:00
return
}
2023-10-05 04:08:19 +03:00
form := web . GetForm ( ctx ) . ( * forms . AdminEditUserForm )
2014-08-29 11:32:52 +04:00
if ctx . HasError ( ) {
2021-04-05 18:30:52 +03:00
ctx . HTML ( http . StatusOK , tplUserEdit )
2014-08-29 11:32:52 +04:00
return
}
2024-02-04 16:29:09 +03:00
if form . UserName != "" {
if err := user_service . RenameUser ( ctx , u , form . UserName ) ; err != nil {
switch {
case user_model . IsErrUserIsNotLocal ( err ) :
ctx . Data [ "Err_UserName" ] = true
ctx . RenderWithErr ( ctx . Tr ( "form.username_change_not_local_user" ) , tplUserEdit , & form )
case user_model . IsErrUserAlreadyExist ( err ) :
ctx . Data [ "Err_UserName" ] = true
ctx . RenderWithErr ( ctx . Tr ( "form.username_been_taken" ) , tplUserEdit , & form )
case db . IsErrNameReserved ( err ) :
ctx . Data [ "Err_UserName" ] = true
ctx . RenderWithErr ( ctx . Tr ( "user.form.name_reserved" , form . UserName ) , tplUserEdit , & form )
case db . IsErrNamePatternNotAllowed ( err ) :
ctx . Data [ "Err_UserName" ] = true
ctx . RenderWithErr ( ctx . Tr ( "user.form.name_pattern_not_allowed" , form . UserName ) , tplUserEdit , & form )
case db . IsErrNameCharsNotAllowed ( err ) :
ctx . Data [ "Err_UserName" ] = true
ctx . RenderWithErr ( ctx . Tr ( "user.form.name_chars_not_allowed" , form . UserName ) , tplUserEdit , & form )
default :
ctx . ServerError ( "RenameUser" , err )
}
return
}
}
authOpts := & user_service . UpdateAuthOptions {
Password : optional . FromNonDefault ( form . Password ) ,
LoginName : optional . Some ( form . LoginName ) ,
}
// skip self Prohibit Login
if ctx . Doer . ID == u . ID {
authOpts . ProhibitLogin = optional . Some ( false )
} else {
authOpts . ProhibitLogin = optional . Some ( form . ProhibitLogin )
}
2015-09-13 18:07:21 +03:00
fields := strings . Split ( form . LoginType , "-" )
if len ( fields ) == 2 {
2022-01-02 16:12:35 +03:00
authSource , _ := strconv . ParseInt ( fields [ 1 ] , 10 , 64 )
2015-09-13 18:07:21 +03:00
2024-02-04 16:29:09 +03:00
authOpts . LoginSource = optional . Some ( authSource )
2015-09-13 18:07:21 +03:00
}
2024-02-04 16:29:09 +03:00
if err := user_service . UpdateAuth ( ctx , u , authOpts ) ; err != nil {
switch {
case errors . Is ( err , password . ErrMinLength ) :
2019-11-20 03:07:51 +03:00
ctx . Data [ "Err_Password" ] = true
ctx . RenderWithErr ( ctx . Tr ( "auth.password_too_short" , setting . MinPasswordLength ) , tplUserEdit , & form )
2024-02-04 16:29:09 +03:00
case errors . Is ( err , password . ErrComplexity ) :
ctx . Data [ "Err_Password" ] = true
2023-05-08 12:36:54 +03:00
ctx . RenderWithErr ( password . BuildComplexityError ( ctx . Locale ) , tplUserEdit , & form )
2024-02-04 16:29:09 +03:00
case errors . Is ( err , password . ErrIsPwned ) :
2020-09-09 01:06:39 +03:00
ctx . Data [ "Err_Password" ] = true
2024-02-04 16:29:09 +03:00
ctx . RenderWithErr ( ctx . Tr ( "auth.password_pwned" ) , tplUserEdit , & form )
case password . IsErrIsPwnedRequest ( err ) :
ctx . Data [ "Err_Password" ] = true
ctx . RenderWithErr ( ctx . Tr ( "auth.password_pwned_err" ) , tplUserEdit , & form )
default :
ctx . ServerError ( "UpdateUser" , err )
2020-09-09 01:06:39 +03:00
}
2024-02-04 16:29:09 +03:00
return
}
2021-11-26 04:56:16 +03:00
2024-02-04 16:29:09 +03:00
if form . Email != "" {
2024-03-05 19:51:56 +03:00
if err := user_service . AdminAddOrSetPrimaryEmailAddress ( ctx , u , form . Email ) ; err != nil {
2024-02-04 16:29:09 +03:00
switch {
case user_model . IsErrEmailCharIsNotSupported ( err ) , user_model . IsErrEmailInvalid ( err ) :
ctx . Data [ "Err_Email" ] = true
ctx . RenderWithErr ( ctx . Tr ( "form.email_invalid" ) , tplUserEdit , & form )
case user_model . IsErrEmailAlreadyUsed ( err ) :
ctx . Data [ "Err_Email" ] = true
ctx . RenderWithErr ( ctx . Tr ( "form.email_been_used" ) , tplUserEdit , & form )
default :
ctx . ServerError ( "AddOrSetPrimaryEmailAddress" , err )
}
2021-11-26 04:56:16 +03:00
return
}
2024-03-11 09:07:36 +03:00
if ! user_model . IsEmailDomainAllowed ( form . Email ) {
ctx . Flash . Warning ( ctx . Tr ( "form.email_domain_is_not_allowed" , form . Email ) )
}
2024-02-04 16:29:09 +03:00
}
2021-11-26 04:56:16 +03:00
2024-02-04 16:29:09 +03:00
opts := & user_service . UpdateOptions {
FullName : optional . Some ( form . FullName ) ,
Website : optional . Some ( form . Website ) ,
Location : optional . Some ( form . Location ) ,
IsActive : optional . Some ( form . Active ) ,
IsAdmin : optional . Some ( form . Admin ) ,
AllowGitHook : optional . Some ( form . AllowGitHook ) ,
AllowImportLocal : optional . Some ( form . AllowImportLocal ) ,
MaxRepoCreation : optional . Some ( form . MaxRepoCreation ) ,
AllowCreateOrganization : optional . Some ( form . AllowCreateOrganization ) ,
IsRestricted : optional . Some ( form . Restricted ) ,
Visibility : optional . Some ( form . Visibility ) ,
2024-03-03 00:55:02 +03:00
Language : optional . Some ( form . Language ) ,
2014-08-29 11:32:52 +04:00
}
2024-02-04 16:29:09 +03:00
if err := user_service . UpdateUser ( ctx , u , opts ) ; err != nil {
if models . IsErrDeleteLastAdminUser ( err ) {
ctx . RenderWithErr ( ctx . Tr ( "auth.last_admin" ) , tplUserEdit , & form )
} else {
ctx . ServerError ( "UpdateUser" , err )
2021-01-10 15:14:02 +03:00
}
2024-02-04 16:29:09 +03:00
return
2021-01-10 15:14:02 +03:00
}
2024-02-04 16:29:09 +03:00
log . Trace ( "Account profile updated by admin (%s): %s" , ctx . Doer . Name , u . Name )
2021-01-10 15:14:02 +03:00
2021-01-05 16:54:48 +03:00
if form . Reset2FA {
2023-09-15 09:13:19 +03:00
tf , err := auth . GetTwoFactorByUID ( ctx , u . ID )
2022-01-02 16:12:35 +03:00
if err != nil && ! auth . IsErrTwoFactorNotEnrolled ( err ) {
2022-03-02 03:24:31 +03:00
ctx . ServerError ( "auth.GetTwoFactorByUID" , err )
2021-01-05 16:54:48 +03:00
return
2022-03-02 03:24:31 +03:00
} else if tf != nil {
2023-09-15 09:13:19 +03:00
if err := auth . DeleteTwoFactorByID ( ctx , tf . ID , u . ID ) ; err != nil {
2022-03-02 03:24:31 +03:00
ctx . ServerError ( "auth.DeleteTwoFactorByID" , err )
return
}
2021-01-05 16:54:48 +03:00
}
2023-09-16 17:39:12 +03:00
wn , err := auth . GetWebAuthnCredentialsByUID ( ctx , u . ID )
2022-03-02 03:24:31 +03:00
if err != nil {
ctx . ServerError ( "auth.GetTwoFactorByUID" , err )
2021-01-05 16:54:48 +03:00
return
}
2022-03-02 03:24:31 +03:00
for _ , cred := range wn {
2023-09-16 17:39:12 +03:00
if _ , err := auth . DeleteCredential ( ctx , cred . ID , u . ID ) ; err != nil {
2022-03-02 03:24:31 +03:00
ctx . ServerError ( "auth.DeleteCredential" , err )
return
}
}
2014-08-29 11:32:52 +04:00
}
2015-09-13 18:07:21 +03:00
2014-08-29 11:32:52 +04:00
ctx . Flash . Success ( ctx . Tr ( "admin.users.update_profile_success" ) )
2021-11-16 21:18:25 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin/users/" + url . PathEscape ( ctx . Params ( ":userid" ) ) )
2014-08-29 11:32:52 +04:00
}
2016-11-21 06:21:24 +03:00
// DeleteUser response for deleting a user
2016-03-11 19:56:52 +03:00
func DeleteUser ( ctx * context . Context ) {
2022-12-03 05:48:26 +03:00
u , err := user_model . GetUserByID ( ctx , ctx . ParamsInt64 ( ":userid" ) )
2014-08-29 11:32:52 +04:00
if err != nil {
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "GetUserByID" , err )
2014-08-29 11:32:52 +04:00
return
}
2022-05-08 23:22:55 +03:00
// admin should not delete themself
if u . ID == ctx . Doer . ID {
ctx . Flash . Error ( ctx . Tr ( "admin.users.cannot_delete_self" ) )
2022-07-14 10:22:09 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin/users/" + url . PathEscape ( ctx . Params ( ":userid" ) ) )
2022-05-08 23:22:55 +03:00
return
}
2022-07-14 10:22:09 +03:00
if err = user_service . DeleteUser ( ctx , u , ctx . FormBool ( "purge" ) ) ; err != nil {
2015-03-18 04:51:39 +03:00
switch {
case models . IsErrUserOwnRepos ( err ) :
2014-08-29 11:32:52 +04:00
ctx . Flash . Error ( ctx . Tr ( "admin.users.still_own_repo" ) )
2022-07-14 10:22:09 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin/users/" + url . PathEscape ( ctx . Params ( ":userid" ) ) )
2015-03-18 04:51:39 +03:00
case models . IsErrUserHasOrgs ( err ) :
2014-11-13 13:27:01 +03:00
ctx . Flash . Error ( ctx . Tr ( "admin.users.still_has_org" ) )
2022-07-14 10:22:09 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin/users/" + url . PathEscape ( ctx . Params ( ":userid" ) ) )
2022-03-30 11:42:47 +03:00
case models . IsErrUserOwnPackages ( err ) :
ctx . Flash . Error ( ctx . Tr ( "admin.users.still_own_packages" ) )
2024-01-15 09:51:43 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin/users/" + url . PathEscape ( ctx . Params ( ":userid" ) ) )
case models . IsErrDeleteLastAdminUser ( err ) :
ctx . Flash . Error ( ctx . Tr ( "auth.last_admin" ) )
ctx . Redirect ( setting . AppSubURL + "/admin/users/" + url . PathEscape ( ctx . Params ( ":userid" ) ) )
2014-08-29 11:32:52 +04:00
default :
2018-01-11 00:34:17 +03:00
ctx . ServerError ( "DeleteUser" , err )
2014-08-29 11:32:52 +04:00
}
return
}
2022-03-22 10:03:22 +03:00
log . Trace ( "Account deleted by admin (%s): %s" , ctx . Doer . Name , u . Name )
2015-09-13 20:26:20 +03:00
ctx . Flash . Success ( ctx . Tr ( "admin.users.deletion_success" ) )
2022-07-14 10:22:09 +03:00
ctx . Redirect ( setting . AppSubURL + "/admin/users" )
2014-08-29 11:32:52 +04:00
}
2021-11-16 22:13:13 +03:00
// AvatarPost response for change user's avatar request
func AvatarPost ( ctx * context . Context ) {
u := prepareUserInfo ( ctx )
if ctx . Written ( ) {
return
}
form := web . GetForm ( ctx ) . ( * forms . AvatarForm )
2021-11-22 18:21:55 +03:00
if err := user_setting . UpdateAvatarSetting ( ctx , form , u ) ; err != nil {
2021-11-16 22:13:13 +03:00
ctx . Flash . Error ( err . Error ( ) )
} else {
ctx . Flash . Success ( ctx . Tr ( "settings.update_user_avatar_success" ) )
}
ctx . Redirect ( setting . AppSubURL + "/admin/users/" + strconv . FormatInt ( u . ID , 10 ) )
}
// DeleteAvatar render delete avatar page
func DeleteAvatar ( ctx * context . Context ) {
u := prepareUserInfo ( ctx )
if ctx . Written ( ) {
return
}
2023-10-11 07:24:07 +03:00
if err := user_service . DeleteAvatar ( ctx , u ) ; err != nil {
2021-11-16 22:13:13 +03:00
ctx . Flash . Error ( err . Error ( ) )
}
2023-08-23 12:36:57 +03:00
ctx . JSONRedirect ( setting . AppSubURL + "/admin/users/" + strconv . FormatInt ( u . ID , 10 ) )
2021-11-16 22:13:13 +03:00
}