2022-02-13 23:39:27 +08:00
// Copyright 2021 The Casdoor Authors. All Rights Reserved.
2020-10-20 23:14:03 +08:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package object
import (
2025-03-19 22:57:35 +08:00
"encoding/base64"
2024-02-17 15:24:36 +08:00
"encoding/json"
2021-02-21 23:51:40 +08:00
"fmt"
2025-03-19 22:57:35 +08:00
"io"
2024-02-17 15:24:36 +08:00
"reflect"
2023-09-20 22:45:00 +08:00
"strconv"
2021-12-29 19:12:11 +08:00
"strings"
2021-02-21 23:51:40 +08:00
2022-09-13 20:31:22 +08:00
"github.com/casdoor/casdoor/conf"
2025-03-19 22:57:35 +08:00
"github.com/casdoor/casdoor/faceId"
2025-06-06 23:05:01 +08:00
"github.com/casdoor/casdoor/i18n"
2025-03-19 22:57:35 +08:00
"github.com/casdoor/casdoor/proxy"
2022-01-20 14:11:46 +08:00
"github.com/casdoor/casdoor/util"
2023-03-07 13:38:48 +08:00
"github.com/go-webauthn/webauthn/webauthn"
2023-11-26 18:11:49 +03:00
"github.com/xorm-io/builder"
2023-02-12 09:33:24 +08:00
"github.com/xorm-io/core"
2020-10-20 23:14:03 +08:00
)
2022-08-08 18:43:12 +08:00
const (
2022-08-09 16:50:49 +08:00
UserPropertiesWechatUnionId = "wechatUnionId"
UserPropertiesWechatOpenId = "wechatOpenId"
2022-08-08 18:43:12 +08:00
)
2023-08-11 10:59:18 +08:00
const UserEnforcerId = "built-in/user-enforcer-built-in"
var userEnforcer * UserGroupEnforcer
func InitUserManager ( ) {
2023-08-11 12:31:49 +08:00
enforcer , err := GetInitializedEnforcer ( UserEnforcerId )
2023-08-11 10:59:18 +08:00
if err != nil {
panic ( err )
}
userEnforcer = NewUserGroupEnforcer ( enforcer . Enforcer )
}
2020-10-20 23:14:03 +08:00
type User struct {
Owner string ` xorm:"varchar(100) notnull pk" json:"owner" `
2025-03-01 00:44:34 +08:00
Name string ` xorm:"varchar(255) notnull pk" json:"name" `
2023-06-01 22:51:01 +08:00
CreatedTime string ` xorm:"varchar(100) index" json:"createdTime" `
2021-06-01 20:37:00 +08:00
UpdatedTime string ` xorm:"varchar(100)" json:"updatedTime" `
2024-01-30 07:18:32 -08:00
DeletedTime string ` xorm:"varchar(100)" json:"deletedTime" `
2020-10-20 23:14:03 +08:00
2022-01-14 17:42:11 +08:00
Id string ` xorm:"varchar(100) index" json:"id" `
2023-10-12 00:09:47 +08:00
ExternalId string ` xorm:"varchar(100) index" json:"externalId" `
2021-06-21 10:22:47 +08:00
Type string ` xorm:"varchar(100)" json:"type" `
2024-01-31 00:06:06 +08:00
Password string ` xorm:"varchar(150)" json:"password" `
2021-11-04 21:08:43 +08:00
PasswordSalt string ` xorm:"varchar(100)" json:"passwordSalt" `
2023-05-16 15:11:19 +03:00
PasswordType string ` xorm:"varchar(100)" json:"passwordType" `
2021-06-21 10:22:47 +08:00
DisplayName string ` xorm:"varchar(100)" json:"displayName" `
2022-02-27 14:02:52 +08:00
FirstName string ` xorm:"varchar(100)" json:"firstName" `
LastName string ` xorm:"varchar(100)" json:"lastName" `
2025-05-18 09:47:56 +08:00
Avatar string ` xorm:"varchar(500)" json:"avatar" `
2023-06-17 11:43:46 +08:00
AvatarType string ` xorm:"varchar(100)" json:"avatarType" `
2021-12-24 00:36:53 +08:00
PermanentAvatar string ` xorm:"varchar(500)" json:"permanentAvatar" `
2022-01-04 19:52:29 +08:00
Email string ` xorm:"varchar(100) index" json:"email" `
2022-04-06 20:38:14 +08:00
EmailVerified bool ` json:"emailVerified" `
2024-01-30 19:06:18 +08:00
Phone string ` xorm:"varchar(100) index" json:"phone" `
2023-02-16 22:53:28 +08:00
CountryCode string ` xorm:"varchar(6)" json:"countryCode" `
2023-04-15 16:05:33 +08:00
Region string ` xorm:"varchar(100)" json:"region" `
2021-08-21 10:58:34 +08:00
Location string ` xorm:"varchar(100)" json:"location" `
2021-06-21 10:22:47 +08:00
Address [ ] string ` json:"address" `
Affiliation string ` xorm:"varchar(100)" json:"affiliation" `
2021-08-21 10:58:34 +08:00
Title string ` xorm:"varchar(100)" json:"title" `
2021-11-19 21:37:13 +08:00
IdCardType string ` xorm:"varchar(100)" json:"idCardType" `
2022-01-04 19:52:29 +08:00
IdCard string ` xorm:"varchar(100) index" json:"idCard" `
2021-08-21 10:58:34 +08:00
Homepage string ` xorm:"varchar(100)" json:"homepage" `
2021-08-25 08:07:08 +08:00
Bio string ` xorm:"varchar(100)" json:"bio" `
2021-06-21 10:22:47 +08:00
Tag string ` xorm:"varchar(100)" json:"tag" `
Language string ` xorm:"varchar(100)" json:"language" `
2021-11-19 21:37:13 +08:00
Gender string ` xorm:"varchar(100)" json:"gender" `
Birthday string ` xorm:"varchar(100)" json:"birthday" `
Education string ` xorm:"varchar(100)" json:"education" `
2021-06-21 10:22:47 +08:00
Score int ` json:"score" `
2022-02-28 16:25:09 +08:00
Karma int ` json:"karma" `
2021-12-12 22:50:57 +08:00
Ranking int ` json:"ranking" `
2024-02-28 16:54:30 +08:00
Balance float64 ` json:"balance" `
Currency string ` xorm:"varchar(100)" json:"currency" `
2021-12-01 21:26:28 +08:00
IsDefaultAvatar bool ` json:"isDefaultAvatar" `
2021-08-21 10:58:34 +08:00
IsOnline bool ` json:"isOnline" `
2021-06-21 10:22:47 +08:00
IsAdmin bool ` json:"isAdmin" `
IsForbidden bool ` json:"isForbidden" `
2021-11-06 15:52:03 +08:00
IsDeleted bool ` json:"isDeleted" `
2021-06-21 10:22:47 +08:00
SignupApplication string ` xorm:"varchar(100)" json:"signupApplication" `
Hash string ` xorm:"varchar(100)" json:"hash" `
PreHash string ` xorm:"varchar(100)" json:"preHash" `
2023-06-13 22:18:17 +08:00
AccessKey string ` xorm:"varchar(100)" json:"accessKey" `
2023-06-16 20:42:15 +08:00
AccessSecret string ` xorm:"varchar(100)" json:"accessSecret" `
2024-03-17 22:01:28 +08:00
AccessToken string ` xorm:"mediumtext" json:"accessToken" `
2021-02-14 00:22:24 +08:00
2021-11-19 21:37:13 +08:00
CreatedIp string ` xorm:"varchar(100)" json:"createdIp" `
LastSigninTime string ` xorm:"varchar(100)" json:"lastSigninTime" `
LastSigninIp string ` xorm:"varchar(100)" json:"lastSigninIp" `
2023-02-04 12:20:18 +08:00
GitHub string ` xorm:"github varchar(100)" json:"github" `
Google string ` xorm:"varchar(100)" json:"google" `
QQ string ` xorm:"qq varchar(100)" json:"qq" `
WeChat string ` xorm:"wechat varchar(100)" json:"wechat" `
Facebook string ` xorm:"facebook varchar(100)" json:"facebook" `
DingTalk string ` xorm:"dingtalk varchar(100)" json:"dingtalk" `
Weibo string ` xorm:"weibo varchar(100)" json:"weibo" `
Gitee string ` xorm:"gitee varchar(100)" json:"gitee" `
LinkedIn string ` xorm:"linkedin varchar(100)" json:"linkedin" `
Wecom string ` xorm:"wecom varchar(100)" json:"wecom" `
Lark string ` xorm:"lark varchar(100)" json:"lark" `
Gitlab string ` xorm:"gitlab varchar(100)" json:"gitlab" `
Adfs string ` xorm:"adfs varchar(100)" json:"adfs" `
Baidu string ` xorm:"baidu varchar(100)" json:"baidu" `
Alipay string ` xorm:"alipay varchar(100)" json:"alipay" `
Casdoor string ` xorm:"casdoor varchar(100)" json:"casdoor" `
Infoflow string ` xorm:"infoflow varchar(100)" json:"infoflow" `
Apple string ` xorm:"apple varchar(100)" json:"apple" `
AzureAD string ` xorm:"azuread varchar(100)" json:"azuread" `
2023-12-17 02:37:28 +08:00
AzureADB2c string ` xorm:"azureadb2c varchar(100)" json:"azureadb2c" `
2023-02-04 12:20:18 +08:00
Slack string ` xorm:"slack varchar(100)" json:"slack" `
Steam string ` xorm:"steam varchar(100)" json:"steam" `
Bilibili string ` xorm:"bilibili varchar(100)" json:"bilibili" `
Okta string ` xorm:"okta varchar(100)" json:"okta" `
Douyin string ` xorm:"douyin varchar(100)" json:"douyin" `
2025-01-08 00:09:16 +08:00
Kwai string ` xorm:"kwai varchar(100)" json:"kwai" `
2023-02-04 12:20:18 +08:00
Line string ` xorm:"line varchar(100)" json:"line" `
Amazon string ` xorm:"amazon varchar(100)" json:"amazon" `
Auth0 string ` xorm:"auth0 varchar(100)" json:"auth0" `
BattleNet string ` xorm:"battlenet varchar(100)" json:"battlenet" `
Bitbucket string ` xorm:"bitbucket varchar(100)" json:"bitbucket" `
Box string ` xorm:"box varchar(100)" json:"box" `
CloudFoundry string ` xorm:"cloudfoundry varchar(100)" json:"cloudfoundry" `
Dailymotion string ` xorm:"dailymotion varchar(100)" json:"dailymotion" `
Deezer string ` xorm:"deezer varchar(100)" json:"deezer" `
DigitalOcean string ` xorm:"digitalocean varchar(100)" json:"digitalocean" `
Discord string ` xorm:"discord varchar(100)" json:"discord" `
Dropbox string ` xorm:"dropbox varchar(100)" json:"dropbox" `
EveOnline string ` xorm:"eveonline varchar(100)" json:"eveonline" `
Fitbit string ` xorm:"fitbit varchar(100)" json:"fitbit" `
Gitea string ` xorm:"gitea varchar(100)" json:"gitea" `
Heroku string ` xorm:"heroku varchar(100)" json:"heroku" `
InfluxCloud string ` xorm:"influxcloud varchar(100)" json:"influxcloud" `
Instagram string ` xorm:"instagram varchar(100)" json:"instagram" `
Intercom string ` xorm:"intercom varchar(100)" json:"intercom" `
Kakao string ` xorm:"kakao varchar(100)" json:"kakao" `
Lastfm string ` xorm:"lastfm varchar(100)" json:"lastfm" `
Mailru string ` xorm:"mailru varchar(100)" json:"mailru" `
Meetup string ` xorm:"meetup varchar(100)" json:"meetup" `
MicrosoftOnline string ` xorm:"microsoftonline varchar(100)" json:"microsoftonline" `
Naver string ` xorm:"naver varchar(100)" json:"naver" `
Nextcloud string ` xorm:"nextcloud varchar(100)" json:"nextcloud" `
OneDrive string ` xorm:"onedrive varchar(100)" json:"onedrive" `
Oura string ` xorm:"oura varchar(100)" json:"oura" `
Patreon string ` xorm:"patreon varchar(100)" json:"patreon" `
Paypal string ` xorm:"paypal varchar(100)" json:"paypal" `
SalesForce string ` xorm:"salesforce varchar(100)" json:"salesforce" `
Shopify string ` xorm:"shopify varchar(100)" json:"shopify" `
Soundcloud string ` xorm:"soundcloud varchar(100)" json:"soundcloud" `
Spotify string ` xorm:"spotify varchar(100)" json:"spotify" `
Strava string ` xorm:"strava varchar(100)" json:"strava" `
Stripe string ` xorm:"stripe varchar(100)" json:"stripe" `
TikTok string ` xorm:"tiktok varchar(100)" json:"tiktok" `
Tumblr string ` xorm:"tumblr varchar(100)" json:"tumblr" `
Twitch string ` xorm:"twitch varchar(100)" json:"twitch" `
Twitter string ` xorm:"twitter varchar(100)" json:"twitter" `
Typetalk string ` xorm:"typetalk varchar(100)" json:"typetalk" `
Uber string ` xorm:"uber varchar(100)" json:"uber" `
VK string ` xorm:"vk varchar(100)" json:"vk" `
Wepay string ` xorm:"wepay varchar(100)" json:"wepay" `
Xero string ` xorm:"xero varchar(100)" json:"xero" `
Yahoo string ` xorm:"yahoo varchar(100)" json:"yahoo" `
Yammer string ` xorm:"yammer varchar(100)" json:"yammer" `
Yandex string ` xorm:"yandex varchar(100)" json:"yandex" `
Zoom string ` xorm:"zoom varchar(100)" json:"zoom" `
2023-07-20 17:51:36 +08:00
MetaMask string ` xorm:"metamask varchar(100)" json:"metamask" `
2023-08-13 23:58:57 +08:00
Web3Onboard string ` xorm:"web3onboard varchar(100)" json:"web3onboard" `
2023-02-04 12:20:18 +08:00
Custom string ` xorm:"custom varchar(100)" json:"custom" `
2021-05-30 15:13:43 +08:00
2022-07-12 20:06:01 +08:00
WebauthnCredentials [ ] webauthn . Credential ` xorm:"webauthnCredentials blob" json:"webauthnCredentials" `
2023-06-21 18:56:37 +08:00
PreferredMfaType string ` xorm:"varchar(100)" json:"preferredMfaType" `
2023-07-07 12:30:07 +08:00
RecoveryCodes [ ] string ` xorm:"varchar(1000)" json:"recoveryCodes" `
TotpSecret string ` xorm:"varchar(100)" json:"totpSecret" `
2023-06-21 18:56:37 +08:00
MfaPhoneEnabled bool ` json:"mfaPhoneEnabled" `
MfaEmailEnabled bool ` json:"mfaEmailEnabled" `
MultiFactorAuths [ ] * MfaProps ` xorm:"-" json:"multiFactorAuths,omitempty" `
2024-01-22 02:25:13 +08:00
Invitation string ` xorm:"varchar(100) index" json:"invitation" `
InvitationCode string ` xorm:"varchar(100) index" json:"invitationCode" `
2024-03-16 09:04:00 +08:00
FaceIds [ ] * FaceId ` json:"faceIds" `
2022-07-12 20:06:01 +08:00
2021-07-17 14:13:00 +08:00
Ldap string ` xorm:"ldap varchar(100)" json:"ldap" `
2021-05-30 15:13:43 +08:00
Properties map [ string ] string ` json:"properties" `
2022-07-30 17:31:56 +08:00
2023-01-23 00:36:55 +08:00
Roles [ ] * Role ` json:"roles" `
Permissions [ ] * Permission ` json:"permissions" `
2023-06-18 23:33:13 +08:00
Groups [ ] string ` xorm:"groups varchar(1000)" json:"groups" `
2022-08-17 01:39:53 +08:00
2024-11-19 21:06:52 +08:00
LastChangePasswordTime string ` xorm:"varchar(100)" json:"lastChangePasswordTime" `
LastSigninWrongTime string ` xorm:"varchar(100)" json:"lastSigninWrongTime" `
SigninWrongTimes int ` json:"signinWrongTimes" `
2022-08-22 00:25:39 +08:00
2024-06-02 01:00:55 +08:00
ManagedAccounts [ ] ManagedAccount ` xorm:"managedAccounts blob" json:"managedAccounts" `
2024-07-20 22:51:15 +08:00
MfaAccounts [ ] MfaAccount ` xorm:"mfaAccounts blob" json:"mfaAccounts" `
2024-06-02 01:00:55 +08:00
NeedUpdatePassword bool ` json:"needUpdatePassword" `
2024-10-15 20:40:14 +08:00
IpWhitelist string ` xorm:"varchar(200)" json:"ipWhitelist" `
2020-10-20 23:14:03 +08:00
}
2022-02-18 12:36:11 +08:00
type Userinfo struct {
2023-09-08 18:27:14 +08:00
Sub string ` json:"sub" `
Iss string ` json:"iss" `
Aud string ` json:"aud" `
Name string ` json:"preferred_username,omitempty" `
DisplayName string ` json:"name,omitempty" `
Email string ` json:"email,omitempty" `
2023-09-11 18:33:24 +08:00
EmailVerified bool ` json:"email_verified,omitempty" `
2023-09-08 18:27:14 +08:00
Avatar string ` json:"picture,omitempty" `
Address string ` json:"address,omitempty" `
Phone string ` json:"phone,omitempty" `
Groups [ ] string ` json:"groups,omitempty" `
2024-03-10 12:34:56 +08:00
Roles [ ] string ` json:"roles,omitempty" `
Permissions [ ] string ` json:"permissions,omitempty" `
2022-02-18 12:36:11 +08:00
}
2022-08-22 00:25:39 +08:00
type ManagedAccount struct {
Application string ` xorm:"varchar(100)" json:"application" `
Username string ` xorm:"varchar(100)" json:"username" `
Password string ` xorm:"varchar(100)" json:"password" `
SigninUrl string ` xorm:"varchar(200)" json:"signinUrl" `
}
2024-07-20 22:51:15 +08:00
type MfaAccount struct {
AccountName string ` xorm:"varchar(100)" json:"accountName" `
Issuer string ` xorm:"varchar(100)" json:"issuer" `
SecretKey string ` xorm:"varchar(100)" json:"secretKey" `
2024-12-29 22:51:21 +08:00
Origin string ` xorm:"varchar(100)" json:"origin" `
2024-07-20 22:51:15 +08:00
}
2024-03-16 09:04:00 +08:00
type FaceId struct {
Name string ` xorm:"varchar(100) notnull pk" json:"name" `
FaceIdData [ ] float64 ` json:"faceIdData" `
2025-03-19 22:57:35 +08:00
ImageUrl string ` json:"ImageUrl" `
2024-03-16 09:04:00 +08:00
}
2024-02-17 15:24:36 +08:00
func GetUserFieldStringValue ( user * User , fieldName string ) ( bool , string , error ) {
val := reflect . ValueOf ( * user )
fieldValue := val . FieldByName ( fieldName )
if ! fieldValue . IsValid ( ) {
return false , "" , nil
}
if fieldValue . Kind ( ) == reflect . String {
return true , fieldValue . String ( ) , nil
}
marshalValue , err := json . Marshal ( fieldValue . Interface ( ) )
if err != nil {
return false , "" , err
}
return true , string ( marshalValue ) , nil
}
2023-05-30 15:49:39 +08:00
func GetGlobalUserCount ( field , value string ) ( int64 , error ) {
2022-01-26 19:36:36 +08:00
session := GetSession ( "" , - 1 , - 1 , field , value , "" , "" )
2023-05-30 15:49:39 +08:00
return session . Count ( & User { } )
2021-11-06 11:32:22 +08:00
}
2023-05-30 15:49:39 +08:00
func GetGlobalUsers ( ) ( [ ] * User , error ) {
2021-02-13 00:11:12 +08:00
users := [ ] * User { }
2023-07-29 15:07:04 +08:00
err := ormer . Engine . Desc ( "created_time" ) . Find ( & users )
2021-02-13 00:11:12 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2021-02-13 00:11:12 +08:00
}
2023-05-30 15:49:39 +08:00
return users , nil
2021-02-13 00:11:12 +08:00
}
2023-11-26 18:11:49 +03:00
func GetGlobalUsersWithFilter ( cond builder . Cond ) ( [ ] * User , error ) {
users := [ ] * User { }
session := ormer . Engine . Desc ( "created_time" )
if cond != nil {
session = session . Where ( cond )
}
err := session . Find ( & users )
if err != nil {
return nil , err
}
return users , nil
}
2023-05-30 15:49:39 +08:00
func GetPaginationGlobalUsers ( offset , limit int , field , value , sortField , sortOrder string ) ( [ ] * User , error ) {
2021-11-06 11:32:22 +08:00
users := [ ] * User { }
2023-06-01 22:51:01 +08:00
session := GetSessionForUser ( "" , offset , limit , field , value , sortField , sortOrder )
2021-12-25 10:55:10 +08:00
err := session . Find ( & users )
2021-11-06 11:32:22 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2021-11-06 11:32:22 +08:00
}
2023-05-30 15:49:39 +08:00
return users , nil
2021-11-06 11:32:22 +08:00
}
2023-06-19 19:08:45 +08:00
func GetUserCount ( owner , field , value string , groupName string ) ( int64 , error ) {
2022-01-26 19:36:36 +08:00
session := GetSession ( owner , - 1 , - 1 , field , value , "" , "" )
2023-06-12 09:27:16 +08:00
2023-06-19 19:08:45 +08:00
if groupName != "" {
2023-08-06 20:16:44 +08:00
return GetGroupUserCount ( util . GetId ( owner , groupName ) , field , value )
2023-06-12 09:27:16 +08:00
}
2023-05-30 15:49:39 +08:00
return session . Count ( & User { } )
2021-11-06 11:32:22 +08:00
}
2023-05-30 15:49:39 +08:00
func GetOnlineUserCount ( owner string , isOnline int ) ( int64 , error ) {
2023-07-29 15:07:04 +08:00
return ormer . Engine . Where ( "is_online = ?" , isOnline ) . Count ( & User { Owner : owner } )
2021-11-19 10:43:14 +08:00
}
2023-05-30 15:49:39 +08:00
func GetUsers ( owner string ) ( [ ] * User , error ) {
2020-10-20 23:14:03 +08:00
users := [ ] * User { }
2023-07-29 15:07:04 +08:00
err := ormer . Engine . Desc ( "created_time" ) . Find ( & users , & User { Owner : owner } )
2020-10-20 23:14:03 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2020-10-20 23:14:03 +08:00
}
2023-05-30 15:49:39 +08:00
return users , nil
2020-10-20 23:14:03 +08:00
}
2023-11-26 18:11:49 +03:00
func GetUsersWithFilter ( owner string , cond builder . Cond ) ( [ ] * User , error ) {
2023-05-12 13:03:43 +08:00
users := [ ] * User { }
2023-11-26 18:11:49 +03:00
session := ormer . Engine . Desc ( "created_time" )
if cond != nil {
session = session . Where ( cond )
}
err := session . Find ( & users , & User { Owner : owner } )
if err != nil {
return nil , err
}
return users , nil
}
func GetUsersByTagWithFilter ( owner string , tag string , cond builder . Cond ) ( [ ] * User , error ) {
users := [ ] * User { }
session := ormer . Engine . Desc ( "created_time" )
if cond != nil {
session = session . Where ( cond )
}
err := session . Find ( & users , & User { Owner : owner , Tag : tag } )
2023-05-12 13:03:43 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2023-05-12 13:03:43 +08:00
}
2023-05-30 15:49:39 +08:00
return users , nil
2023-05-12 13:03:43 +08:00
}
2023-05-30 15:49:39 +08:00
func GetSortedUsers ( owner string , sorter string , limit int ) ( [ ] * User , error ) {
2021-11-19 10:43:14 +08:00
users := [ ] * User { }
2023-07-29 15:07:04 +08:00
err := ormer . Engine . Desc ( sorter ) . Limit ( limit , 0 ) . Find ( & users , & User { Owner : owner } )
2021-11-19 10:43:14 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2021-11-19 10:43:14 +08:00
}
2023-05-30 15:49:39 +08:00
return users , nil
2021-11-19 10:43:14 +08:00
}
2023-06-19 19:08:45 +08:00
func GetPaginationUsers ( owner string , offset , limit int , field , value , sortField , sortOrder string , groupName string ) ( [ ] * User , error ) {
2021-11-06 11:32:22 +08:00
users := [ ] * User { }
2023-06-12 09:27:16 +08:00
2023-06-19 19:08:45 +08:00
if groupName != "" {
2023-08-06 20:16:44 +08:00
return GetPaginationGroupUsers ( util . GetId ( owner , groupName ) , offset , limit , field , value , sortField , sortOrder )
2023-06-12 09:27:16 +08:00
}
2023-06-01 22:51:01 +08:00
session := GetSessionForUser ( owner , offset , limit , field , value , sortField , sortOrder )
2021-12-25 10:55:10 +08:00
err := session . Find ( & users )
2021-11-06 11:32:22 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2021-11-06 11:32:22 +08:00
}
2023-06-12 09:27:16 +08:00
return users , nil
}
2023-05-30 15:49:39 +08:00
func getUser ( owner string , name string ) ( * User , error ) {
2021-06-21 01:01:16 +08:00
if owner == "" || name == "" {
2023-05-30 15:49:39 +08:00
return nil , nil
2021-06-21 01:01:16 +08:00
}
2020-10-20 23:14:03 +08:00
user := User { Owner : owner , Name : name }
2023-07-29 15:07:04 +08:00
existed , err := ormer . Engine . Get ( & user )
2020-10-20 23:14:03 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2020-10-20 23:14:03 +08:00
}
2021-11-19 10:43:14 +08:00
if existed {
2023-05-30 15:49:39 +08:00
return & user , nil
2021-11-19 10:43:14 +08:00
} else {
2023-05-30 15:49:39 +08:00
return nil , nil
2021-11-19 10:43:14 +08:00
}
}
2021-12-25 00:19:17 +08:00
2023-05-30 15:49:39 +08:00
func getUserById ( owner string , id string ) ( * User , error ) {
2021-12-25 00:19:17 +08:00
if owner == "" || id == "" {
2023-05-30 15:49:39 +08:00
return nil , nil
2021-12-25 00:19:17 +08:00
}
user := User { Owner : owner , Id : id }
2023-07-29 15:07:04 +08:00
existed , err := ormer . Engine . Get ( & user )
2021-12-25 00:19:17 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2021-12-25 00:19:17 +08:00
}
if existed {
2023-05-30 15:49:39 +08:00
return & user , nil
2021-12-25 00:19:17 +08:00
} else {
2023-05-30 15:49:39 +08:00
return nil , nil
2021-12-25 00:19:17 +08:00
}
}
2021-11-19 10:43:14 +08:00
2023-06-21 20:54:19 +08:00
func getUserByWechatId ( owner string , wechatOpenId string , wechatUnionId string ) ( * User , error ) {
2022-04-15 11:49:56 +08:00
if wechatUnionId == "" {
wechatUnionId = wechatOpenId
}
user := & User { }
2023-07-29 15:07:04 +08:00
existed , err := ormer . Engine . Where ( "owner = ?" , owner ) . Where ( "wechat = ? OR wechat = ?" , wechatOpenId , wechatUnionId ) . Get ( user )
2022-04-15 11:49:56 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2022-04-15 11:49:56 +08:00
}
if existed {
2023-05-30 15:49:39 +08:00
return user , nil
2022-04-15 11:49:56 +08:00
} else {
2023-05-30 15:49:39 +08:00
return nil , nil
2022-04-15 11:49:56 +08:00
}
}
2023-05-30 15:49:39 +08:00
func GetUserByEmail ( owner string , email string ) ( * User , error ) {
2021-11-19 10:43:14 +08:00
if owner == "" || email == "" {
2023-05-30 15:49:39 +08:00
return nil , nil
2021-11-19 10:43:14 +08:00
}
user := User { Owner : owner , Email : email }
2023-07-29 15:07:04 +08:00
existed , err := ormer . Engine . Get ( & user )
2021-11-19 10:43:14 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2021-11-19 10:43:14 +08:00
}
2020-10-20 23:14:03 +08:00
if existed {
2023-05-30 15:49:39 +08:00
return & user , nil
2020-10-20 23:14:03 +08:00
} else {
2023-05-30 15:49:39 +08:00
return nil , nil
2020-10-20 23:14:03 +08:00
}
}
2025-04-01 16:35:59 +08:00
func GetUserByWebauthID ( webauthId string ) ( * User , error ) {
user := User { }
2025-04-08 17:51:32 +08:00
existed := false
var err error
if ormer . driverName == "postgres" {
existed , err = ormer . Engine . Where ( builder . Like { "\"webauthnCredentials\"" , webauthId } ) . Get ( & user )
} else if ormer . driverName == "mssql" {
existed , err = ormer . Engine . Where ( "CAST(webauthnCredentials AS VARCHAR(MAX)) like ?" , "%" + webauthId + "%" ) . Get ( & user )
2025-04-09 22:26:47 +08:00
} else if ormer . driverName == "sqlite" {
existed , err = ormer . Engine . Where ( "CAST(webauthnCredentials AS text) like ?" , "%" + webauthId + "%" ) . Get ( & user )
2025-04-08 17:51:32 +08:00
} else {
existed , err = ormer . Engine . Where ( "webauthnCredentials like ?" , "%" + webauthId + "%" ) . Get ( & user )
}
2025-04-01 16:35:59 +08:00
if err != nil {
return nil , err
}
if ! existed {
return nil , fmt . Errorf ( "user not exist" )
}
return & user , err
}
2023-10-12 15:48:55 -03:00
func GetUserByEmailOnly ( email string ) ( * User , error ) {
if email == "" {
return nil , nil
}
user := User { Email : email }
existed , err := ormer . Engine . Get ( & user )
if err != nil {
return nil , err
}
if existed {
return & user , nil
} else {
return nil , nil
}
}
2023-05-30 15:49:39 +08:00
func GetUserByPhone ( owner string , phone string ) ( * User , error ) {
2022-07-31 01:02:28 +08:00
if owner == "" || phone == "" {
2023-05-30 15:49:39 +08:00
return nil , nil
2022-07-31 01:02:28 +08:00
}
user := User { Owner : owner , Phone : phone }
2023-07-29 15:07:04 +08:00
existed , err := ormer . Engine . Get ( & user )
2022-07-31 01:02:28 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2022-07-31 01:02:28 +08:00
}
if existed {
2023-05-30 15:49:39 +08:00
return & user , nil
2022-07-31 01:02:28 +08:00
} else {
2023-05-30 15:49:39 +08:00
return nil , nil
2022-07-31 01:02:28 +08:00
}
}
2023-10-12 15:48:55 -03:00
func GetUserByPhoneOnly ( phone string ) ( * User , error ) {
if phone == "" {
return nil , nil
}
user := User { Phone : phone }
existed , err := ormer . Engine . Get ( & user )
if err != nil {
return nil , err
}
if existed {
return & user , nil
} else {
return nil , nil
}
}
2023-05-30 15:49:39 +08:00
func GetUserByUserId ( owner string , userId string ) ( * User , error ) {
2022-07-14 21:46:13 +08:00
if owner == "" || userId == "" {
2023-05-30 15:49:39 +08:00
return nil , nil
2022-07-14 21:46:13 +08:00
}
user := User { Owner : owner , Id : userId }
2023-07-29 15:07:04 +08:00
existed , err := ormer . Engine . Get ( & user )
2022-07-14 21:46:13 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2022-07-14 21:46:13 +08:00
}
if existed {
2023-05-30 15:49:39 +08:00
return & user , nil
2022-07-14 21:46:13 +08:00
} else {
2023-05-30 15:49:39 +08:00
return nil , nil
2022-07-14 21:46:13 +08:00
}
}
2023-10-12 00:09:47 +08:00
func GetUserByUserIdOnly ( userId string ) ( * User , error ) {
if userId == "" {
return nil , nil
}
user := User { Id : userId }
existed , err := ormer . Engine . Get ( & user )
if err != nil {
return nil , err
}
if existed {
return & user , nil
} else {
return nil , nil
}
}
2024-01-22 02:25:13 +08:00
func GetUserByInvitationCode ( owner string , invitationCode string ) ( * User , error ) {
if owner == "" || invitationCode == "" {
return nil , nil
}
user := User { Owner : owner , InvitationCode : invitationCode }
existed , err := ormer . Engine . Get ( & user )
if err != nil {
return nil , err
}
if existed {
return & user , nil
} else {
return nil , nil
}
}
2023-06-13 22:18:17 +08:00
func GetUserByAccessKey ( accessKey string ) ( * User , error ) {
if accessKey == "" {
return nil , nil
}
user := User { AccessKey : accessKey }
2023-07-29 15:07:04 +08:00
existed , err := ormer . Engine . Get ( & user )
2023-06-13 22:18:17 +08:00
if err != nil {
return nil , err
}
if existed {
return & user , nil
} else {
return nil , nil
}
}
2023-05-30 15:49:39 +08:00
func GetUser ( id string ) ( * User , error ) {
2020-10-20 23:14:03 +08:00
owner , name := util . GetOwnerAndNameFromId ( id )
return getUser ( owner , name )
}
2023-05-30 15:49:39 +08:00
func GetUserNoCheck ( id string ) ( * User , error ) {
2021-11-20 15:46:54 +08:00
owner , name := util . GetOwnerAndNameFromIdNoCheck ( id )
return getUser ( owner , name )
}
2023-07-19 19:14:53 +08:00
func GetMaskedUser ( user * User , isAdminOrSelf bool , errs ... error ) ( * User , error ) {
2023-05-30 15:49:39 +08:00
if len ( errs ) > 0 && errs [ 0 ] != nil {
return nil , errs [ 0 ]
}
2021-06-12 12:27:13 +08:00
if user == nil {
2023-05-30 15:49:39 +08:00
return nil , nil
2021-06-12 12:27:13 +08:00
}
2021-05-30 13:37:34 +08:00
if user . Password != "" {
user . Password = "***"
}
2023-07-19 19:14:53 +08:00
if ! isAdminOrSelf {
if user . AccessSecret != "" {
user . AccessSecret = "***"
}
2023-06-21 18:56:37 +08:00
}
2023-07-19 19:14:53 +08:00
2022-08-22 00:25:39 +08:00
if user . ManagedAccounts != nil {
for _ , manageAccount := range user . ManagedAccounts {
manageAccount . Password = "***"
}
}
2023-05-05 21:23:59 +08:00
2024-07-20 22:51:15 +08:00
if user . MfaAccounts != nil {
for _ , mfaAccount := range user . MfaAccounts {
mfaAccount . SecretKey = "***"
}
}
2023-06-24 18:39:54 +08:00
if user . TotpSecret != "" {
user . TotpSecret = ""
}
if user . RecoveryCodes != nil {
user . RecoveryCodes = nil
}
2023-05-30 15:49:39 +08:00
return user , nil
2021-05-30 13:37:34 +08:00
}
2025-06-16 20:09:21 +08:00
func GetFilteredUser ( user * User , isAdmin bool , isAdminOrSelf bool , accountItems [ ] * AccountItem ) ( * User , error ) {
if accountItems == nil || len ( accountItems ) == 0 {
return user , nil
}
userFieldMap := map [ string ] int { }
reflectedUserField := reflect . TypeOf ( User { } )
for i := 0 ; i < reflectedUserField . NumField ( ) ; i ++ {
userFieldMap [ strings . ToLower ( reflectedUserField . Field ( i ) . Name ) ] = i
}
reflectedUser := reflect . ValueOf ( user ) . Elem ( )
for _ , accountItem := range accountItems {
if accountItem . ViewRule == "Public" {
continue
} else if accountItem . ViewRule == "Self" && isAdminOrSelf {
continue
} else if accountItem . ViewRule == "Admin" && isAdmin {
continue
}
lowerCaseAccountItemName := strings . ToLower ( accountItem . Name )
lowerCaseAccountItemName = strings . ReplaceAll ( lowerCaseAccountItemName , " " , "" )
switch accountItem . Name {
case "Multi-factor authentication" :
lowerCaseAccountItemName = strings . ToLower ( "PreferredMfaType" )
case "User type" :
lowerCaseAccountItemName = "type"
case "Country/Region" :
lowerCaseAccountItemName = "region"
case "ID card info" :
{
infoKeys := [ ] string { "idCardWithPerson" , "idCardFront" , "idCardWithPerson" }
for _ , infoKey := range infoKeys {
if _ , ok := user . Properties [ infoKey ] ; ok {
user . Properties [ infoKey ] = ""
}
}
continue
}
}
fieldIdx , ok := userFieldMap [ lowerCaseAccountItemName ]
if ! ok {
continue
}
reflectedUser . Field ( fieldIdx ) . SetZero ( )
}
return user , nil
}
2023-05-30 15:49:39 +08:00
func GetMaskedUsers ( users [ ] * User , errs ... error ) ( [ ] * User , error ) {
if len ( errs ) > 0 && errs [ 0 ] != nil {
return nil , errs [ 0 ]
}
var err error
2021-05-30 13:37:34 +08:00
for _ , user := range users {
2023-07-19 19:14:53 +08:00
user , err = GetMaskedUser ( user , false )
2023-05-30 15:49:39 +08:00
if err != nil {
return nil , err
}
2021-05-30 13:37:34 +08:00
}
2023-05-30 15:49:39 +08:00
return users , nil
2021-05-30 13:37:34 +08:00
}
2023-09-20 22:45:00 +08:00
func getLastUser ( owner string ) ( * User , error ) {
2021-06-17 00:49:02 +08:00
user := User { Owner : owner }
2023-07-29 15:07:04 +08:00
existed , err := ormer . Engine . Desc ( "created_time" , "id" ) . Get ( & user )
2021-06-17 00:49:02 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return nil , err
2021-06-17 00:49:02 +08:00
}
if existed {
2023-05-30 15:49:39 +08:00
return & user , nil
2021-06-17 00:49:02 +08:00
}
2021-08-07 22:02:56 +08:00
2023-05-30 15:49:39 +08:00
return nil , nil
2021-06-17 00:49:02 +08:00
}
2023-05-30 15:49:39 +08:00
func UpdateUser ( id string , user * User , columns [ ] string , isAdmin bool ) ( bool , error ) {
var err error
2021-11-20 15:46:54 +08:00
owner , name := util . GetOwnerAndNameFromIdNoCheck ( id )
2023-05-30 15:49:39 +08:00
oldUser , err := getUser ( owner , name )
if err != nil {
return false , err
}
2021-08-21 22:52:29 +08:00
if oldUser == nil {
2023-10-31 13:20:44 +08:00
return false , fmt . Errorf ( "the user: %s is not found" , id )
2020-10-20 23:14:03 +08:00
}
2022-11-02 00:17:38 +08:00
if name != user . Name {
err := userChangeTrigger ( name , user . Name )
if err != nil {
2023-06-19 19:08:45 +08:00
return false , err
2022-11-02 00:17:38 +08:00
}
}
2022-05-10 17:37:12 +08:00
if user . Password == "***" {
user . Password = oldUser . Password
}
2021-05-08 18:51:37 +08:00
2024-12-18 02:56:44 +03:00
if user . Id != oldUser . Id && user . Id == "" {
user . Id = oldUser . Id
}
2021-11-20 16:21:15 +08:00
if user . Avatar != oldUser . Avatar && user . Avatar != "" && user . PermanentAvatar != "*" {
2023-05-30 15:49:39 +08:00
user . PermanentAvatar , err = getPermanentAvatarUrl ( user . Owner , user . Name , user . Avatar , false )
if err != nil {
return false , err
}
2021-08-21 23:17:33 +08:00
}
2021-12-11 14:45:08 +08:00
if len ( columns ) == 0 {
2022-07-14 21:46:13 +08:00
columns = [ ] string {
2023-10-12 00:09:47 +08:00
"owner" , "display_name" , "avatar" , "first_name" , "last_name" ,
2024-01-26 08:18:48 +08:00
"location" , "address" , "country_code" , "region" , "language" , "affiliation" , "title" , "id_card_type" , "id_card" , "homepage" , "bio" , "tag" , "language" , "gender" , "birthday" , "education" , "score" , "karma" , "ranking" , "signup_application" ,
2024-07-20 22:51:15 +08:00
"is_admin" , "is_forbidden" , "is_deleted" , "hash" , "is_default_avatar" , "properties" , "webauthnCredentials" , "managedAccounts" , "face_ids" , "mfaAccounts" ,
2024-11-19 21:06:52 +08:00
"signin_wrong_times" , "last_change_password_time" , "last_signin_wrong_time" , "groups" , "access_key" , "access_secret" , "mfa_phone_enabled" , "mfa_email_enabled" ,
2023-05-18 15:58:41 +08:00
"github" , "google" , "qq" , "wechat" , "facebook" , "dingtalk" , "weibo" , "gitee" , "linkedin" , "wecom" , "lark" , "gitlab" , "adfs" ,
2025-01-08 00:09:16 +08:00
"baidu" , "alipay" , "casdoor" , "infoflow" , "apple" , "azuread" , "azureadb2c" , "slack" , "steam" , "bilibili" , "okta" , "douyin" , "kwai" , "line" , "amazon" ,
2023-05-18 15:58:41 +08:00
"auth0" , "battlenet" , "bitbucket" , "box" , "cloudfoundry" , "dailymotion" , "deezer" , "digitalocean" , "discord" , "dropbox" ,
"eveonline" , "fitbit" , "gitea" , "heroku" , "influxcloud" , "instagram" , "intercom" , "kakao" , "lastfm" , "mailru" , "meetup" ,
"microsoftonline" , "naver" , "nextcloud" , "onedrive" , "oura" , "patreon" , "paypal" , "salesforce" , "shopify" , "soundcloud" ,
2023-08-21 22:52:35 +08:00
"spotify" , "strava" , "stripe" , "type" , "tiktok" , "tumblr" , "twitch" , "twitter" , "typetalk" , "uber" , "vk" , "wepay" , "xero" , "yahoo" ,
2024-10-15 20:40:14 +08:00
"yammer" , "yandex" , "zoom" , "custom" , "need_update_password" , "ip_whitelist" ,
2022-07-14 21:46:13 +08:00
}
2021-12-11 14:45:08 +08:00
}
2023-04-25 23:05:53 +08:00
if isAdmin {
2024-06-22 14:05:53 +08:00
columns = append ( columns , "name" , "id" , "email" , "phone" , "country_code" , "type" , "balance" )
2022-01-13 23:19:36 +08:00
}
2021-12-11 14:45:08 +08:00
2023-10-12 00:09:47 +08:00
columns = append ( columns , "updated_time" )
user . UpdatedTime = util . GetCurrentTime ( )
2024-01-30 07:18:32 -08:00
if len ( user . DeletedTime ) > 0 {
columns = append ( columns , "deleted_time" )
}
2023-08-11 10:59:18 +08:00
if util . ContainsString ( columns , "groups" ) {
_ , err := userEnforcer . UpdateGroupsForUser ( user . GetId ( ) , user . Groups )
if err != nil {
return false , err
}
}
2023-06-19 19:08:45 +08:00
affected , err := updateUser ( id , user , columns )
2020-10-20 23:14:03 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return false , err
2020-10-20 23:14:03 +08:00
}
2023-05-30 15:49:39 +08:00
return affected != 0 , nil
2021-05-09 15:44:12 +08:00
}
2023-06-19 19:08:45 +08:00
func updateUser ( id string , user * User , columns [ ] string ) ( int64 , error ) {
owner , name := util . GetOwnerAndNameFromIdNoCheck ( id )
err := user . UpdateUserHash ( )
2023-06-12 09:27:16 +08:00
if err != nil {
2023-06-19 19:08:45 +08:00
return 0 , err
2023-06-12 09:27:16 +08:00
}
2023-07-29 15:07:04 +08:00
affected , err := ormer . Engine . ID ( core . PK { owner , name } ) . Cols ( columns ... ) . Update ( user )
2023-06-12 09:27:16 +08:00
if err != nil {
return 0 , err
}
return affected , nil
}
2023-05-30 15:49:39 +08:00
func UpdateUserForAllFields ( id string , user * User ) ( bool , error ) {
var err error
2021-06-09 21:41:27 +08:00
owner , name := util . GetOwnerAndNameFromId ( id )
2023-05-30 15:49:39 +08:00
oldUser , err := getUser ( owner , name )
if err != nil {
return false , err
}
2021-08-21 22:52:29 +08:00
if oldUser == nil {
2023-10-31 13:20:44 +08:00
return false , fmt . Errorf ( "the user: %s is not found" , id )
2021-06-09 21:41:27 +08:00
}
2022-11-02 00:17:38 +08:00
if name != user . Name {
err := userChangeTrigger ( name , user . Name )
if err != nil {
2023-08-03 18:45:49 +08:00
return false , err
2022-11-02 00:17:38 +08:00
}
}
2023-05-30 15:49:39 +08:00
err = user . UpdateUserHash ( )
if err != nil {
return false , err
}
2021-06-09 21:41:27 +08:00
2021-08-21 23:17:33 +08:00
if user . Avatar != oldUser . Avatar && user . Avatar != "" {
2023-05-30 15:49:39 +08:00
user . PermanentAvatar , err = getPermanentAvatarUrl ( user . Owner , user . Name , user . Avatar , false )
if err != nil {
return false , err
}
2021-08-21 23:17:33 +08:00
}
2023-11-08 20:22:28 +08:00
user . UpdatedTime = util . GetCurrentTime ( )
2023-07-29 15:07:04 +08:00
affected , err := ormer . Engine . ID ( core . PK { owner , name } ) . AllCols ( ) . Update ( user )
2021-06-09 21:41:27 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return false , err
2021-06-09 21:41:27 +08:00
}
2023-05-30 15:49:39 +08:00
return affected != 0 , nil
2021-06-09 21:41:27 +08:00
}
2025-06-06 23:05:01 +08:00
func AddUser ( user * User , lang string ) ( bool , error ) {
2021-06-17 01:12:03 +08:00
if user . Id == "" {
2023-09-20 22:50:17 +08:00
application , err := GetApplicationByUser ( user )
if err != nil {
return false , err
}
id , err := GenerateIdForNewUser ( application )
if err != nil {
return false , err
}
user . Id = id
2021-06-17 01:12:03 +08:00
}
2021-05-16 21:22:20 +08:00
2021-12-12 19:59:55 +08:00
if user . Owner == "" || user . Name == "" {
2025-06-06 23:05:01 +08:00
return false , fmt . Errorf ( i18n . Translate ( lang , "user:the user's owner and name should not be empty" ) )
2021-12-12 19:59:55 +08:00
}
2025-05-16 18:40:50 +08:00
if CheckUsernameWithEmail ( user . Name , "en" ) != "" {
2025-04-23 21:30:19 +08:00
user . Name = util . GetRandomName ( )
}
2023-10-31 13:20:44 +08:00
organization , err := GetOrganizationByUser ( user )
if err != nil {
return false , err
}
2022-08-06 17:30:56 +03:00
if organization == nil {
2025-06-06 23:05:01 +08:00
return false , fmt . Errorf ( i18n . Translate ( lang , "auth:the organization: %s is not found" ) , user . Owner )
2022-08-06 17:30:56 +03:00
}
2025-04-05 16:38:20 +08:00
if user . Owner != "built-in" {
applicationCount , err := GetOrganizationApplicationCount ( organization . Owner , organization . Name , "" , "" )
if err != nil {
return false , err
}
if applicationCount == 0 {
2025-06-06 23:05:01 +08:00
return false , fmt . Errorf ( i18n . Translate ( lang , "general:The organization: %s should have one application at least" ) , organization . Owner )
2025-04-05 16:38:20 +08:00
}
}
2025-06-06 23:05:01 +08:00
if organization . Name == "built-in" && ! organization . HasPrivilegeConsent && user . Name != "admin" {
return false , fmt . Errorf ( i18n . Translate ( lang , "organization:adding a new user to the 'built-in' organization is currently disabled. Please note: all users in the 'built-in' organization are global administrators in Casdoor. Refer to the docs: https://casdoor.org/docs/basic/core-concepts#how-does-casdoor-manage-itself. If you still wish to create a user for the 'built-in' organization, go to the organization's settings page and enable the 'Has privilege consent' option." ) )
}
2023-10-18 11:58:25 +08:00
if organization . DefaultPassword != "" && user . Password == "123" {
user . Password = organization . DefaultPassword
}
2023-08-31 17:49:36 +08:00
if user . PasswordType == "" || user . PasswordType == "plain" {
user . UpdateUserPassword ( organization )
2023-06-01 22:25:19 +08:00
}
2024-10-24 18:06:05 +03:00
if user . CreatedTime == "" {
user . CreatedTime = util . GetCurrentTime ( )
}
2023-10-31 13:23:06 +08:00
err = user . UpdateUserHash ( )
2023-05-30 15:49:39 +08:00
if err != nil {
return false , err
}
2021-05-16 21:22:20 +08:00
user . PreHash = user . Hash
2023-05-30 15:49:39 +08:00
updated , err := user . refreshAvatar ( )
if err != nil {
return false , err
}
2023-04-16 00:59:20 +08:00
if updated && user . PermanentAvatar != "*" {
2023-05-30 15:49:39 +08:00
user . PermanentAvatar , err = getPermanentAvatarUrl ( user . Owner , user . Name , user . Avatar , false )
if err != nil {
return false , err
}
2023-04-16 00:59:20 +08:00
}
2021-08-21 23:17:33 +08:00
2025-01-14 22:43:49 +08:00
rankingItem := GetAccountItemByName ( "Ranking" , organization )
if rankingItem != nil {
count , err := GetUserCount ( user . Owner , "" , "" , "" )
if err != nil {
return false , err
}
user . Ranking = int ( count + 1 )
2023-05-30 15:49:39 +08:00
}
2022-03-04 13:06:21 +08:00
2024-02-08 20:46:40 +08:00
if user . Groups != nil && len ( user . Groups ) > 0 {
_ , err = userEnforcer . UpdateGroupsForUser ( user . GetId ( ) , user . Groups )
if err != nil {
return false , err
}
}
2024-04-02 21:54:16 +08:00
isUsernameLowered := conf . GetConfigBool ( "isUsernameLowered" )
if isUsernameLowered {
user . Name = strings . ToLower ( user . Name )
}
2023-07-29 15:07:04 +08:00
affected , err := ormer . Engine . Insert ( user )
2020-10-20 23:14:03 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return false , err
2020-10-20 23:14:03 +08:00
}
2023-05-30 15:49:39 +08:00
return affected != 0 , nil
2020-10-20 23:14:03 +08:00
}
2023-05-30 15:49:39 +08:00
func AddUsers ( users [ ] * User ) ( bool , error ) {
2021-05-16 21:04:26 +08:00
if len ( users ) == 0 {
2023-10-31 13:20:44 +08:00
return false , fmt . Errorf ( "no users are provided" )
2021-05-16 21:04:26 +08:00
}
2024-04-02 21:54:16 +08:00
isUsernameLowered := conf . GetConfigBool ( "isUsernameLowered" )
2022-07-14 21:46:13 +08:00
// organization := GetOrganizationByUser(users[0])
2021-05-08 18:51:37 +08:00
for _ , user := range users {
2022-01-17 13:26:30 +08:00
// this function is only used for syncer or batch upload, so no need to encrypt the password
2022-07-14 21:46:13 +08:00
// user.UpdateUserPassword(organization)
2021-05-16 21:22:20 +08:00
2023-10-31 13:20:44 +08:00
err := user . UpdateUserHash ( )
2023-05-30 15:49:39 +08:00
if err != nil {
return false , err
}
2021-05-09 14:54:17 +08:00
user . PreHash = user . Hash
2021-08-21 23:17:33 +08:00
2023-05-30 15:49:39 +08:00
user . PermanentAvatar , err = getPermanentAvatarUrl ( user . Owner , user . Name , user . Avatar , true )
if err != nil {
return false , err
}
2024-02-08 20:46:40 +08:00
if user . Groups != nil && len ( user . Groups ) > 0 {
_ , err = userEnforcer . UpdateGroupsForUser ( user . GetId ( ) , user . Groups )
if err != nil {
return false , err
}
}
2024-04-02 21:54:16 +08:00
2024-05-17 11:43:19 +08:00
user . Name = strings . TrimSpace ( user . Name )
2024-04-02 21:54:16 +08:00
if isUsernameLowered {
user . Name = strings . ToLower ( user . Name )
}
2021-05-08 18:51:37 +08:00
}
2023-07-29 15:07:04 +08:00
affected , err := ormer . Engine . Insert ( users )
2021-05-02 23:06:08 +08:00
if err != nil {
2022-03-13 20:53:05 +08:00
if ! strings . Contains ( err . Error ( ) , "Duplicate entry" ) {
2023-05-30 15:49:39 +08:00
return false , err
2022-03-13 20:53:05 +08:00
}
2021-05-02 23:06:08 +08:00
}
2023-05-30 15:49:39 +08:00
return affected != 0 , nil
2021-05-02 23:06:08 +08:00
}
2023-05-30 15:49:39 +08:00
func AddUsersInBatch ( users [ ] * User ) ( bool , error ) {
2021-05-02 23:06:08 +08:00
if len ( users ) == 0 {
2023-10-31 13:20:44 +08:00
return false , fmt . Errorf ( "no users are provided" )
2021-05-02 23:06:08 +08:00
}
2023-10-31 13:20:44 +08:00
batchSize := conf . GetConfigBatchSize ( )
2021-05-02 23:06:08 +08:00
affected := false
2023-10-08 19:33:28 +08:00
for i := 0 ; i < len ( users ) ; i += batchSize {
start := i
end := i + batchSize
2021-05-02 23:06:08 +08:00
if end > len ( users ) {
end = len ( users )
}
tmp := users [ start : end ]
2023-10-08 19:33:28 +08:00
fmt . Printf ( "The syncer adds users: [%d - %d]\n" , start , end )
2023-05-30 15:49:39 +08:00
if ok , err := AddUsers ( tmp ) ; err != nil {
return false , err
} else if ok {
2021-05-02 23:06:08 +08:00
affected = true
}
}
2023-05-30 15:49:39 +08:00
return affected , nil
2021-05-02 23:06:08 +08:00
}
2024-05-07 23:11:08 +08:00
func deleteUser ( user * User ) ( bool , error ) {
affected , err := ormer . Engine . ID ( core . PK { user . Owner , user . Name } ) . Delete ( & User { } )
2023-05-30 15:49:39 +08:00
if err != nil {
return false , err
}
2023-01-06 15:04:13 +08:00
2024-05-07 23:11:08 +08:00
return affected != 0 , nil
}
func DeleteUser ( user * User ) ( bool , error ) {
// Forced offline the user first
_ , err := DeleteSession ( util . GetSessionId ( user . Owner , user . Name , CasdoorApplication ) )
2020-10-20 23:14:03 +08:00
if err != nil {
2023-05-30 15:49:39 +08:00
return false , err
2020-10-20 23:14:03 +08:00
}
2025-02-02 17:54:05 +08:00
_ , err = userEnforcer . DeleteGroupsForUser ( user . GetId ( ) )
2025-01-23 09:46:33 +08:00
if err != nil {
return false , err
}
2024-09-15 14:35:44 +08:00
organization , err := GetOrganizationByUser ( user )
if err != nil {
return false , err
}
if organization != nil && organization . EnableSoftDeletion {
user . IsDeleted = true
user . DeletedTime = util . GetCurrentTime ( )
return UpdateUser ( user . GetId ( ) , user , [ ] string { "is_deleted" , "deleted_time" } , false )
} else {
return deleteUser ( user )
}
2020-10-20 23:14:03 +08:00
}
2021-02-14 00:22:24 +08:00
2024-03-10 12:34:56 +08:00
func GetUserInfo ( user * User , scope string , aud string , host string ) ( * Userinfo , error ) {
2022-02-18 12:36:11 +08:00
_ , originBackend := getOriginFromHost ( host )
resp := Userinfo {
Sub : user . Id ,
Iss : originBackend ,
Aud : aud ,
}
2024-03-10 12:34:56 +08:00
2022-02-18 12:36:11 +08:00
if strings . Contains ( scope , "profile" ) {
resp . Name = user . Name
resp . DisplayName = user . DisplayName
resp . Avatar = user . Avatar
2023-06-19 11:06:55 +08:00
resp . Groups = user . Groups
2024-03-10 12:34:56 +08:00
err := ExtendUserWithRolesAndPermissions ( user )
if err != nil {
return nil , err
}
resp . Roles = [ ] string { }
for _ , role := range user . Roles {
resp . Roles = append ( resp . Roles , role . Name )
}
resp . Permissions = [ ] string { }
for _ , permission := range user . Permissions {
resp . Permissions = append ( resp . Permissions , permission . Name )
}
2022-02-18 12:36:11 +08:00
}
2024-03-10 12:34:56 +08:00
2022-02-18 12:36:11 +08:00
if strings . Contains ( scope , "email" ) {
resp . Email = user . Email
2024-01-05 09:37:42 +08:00
// resp.EmailVerified = user.EmailVerified
resp . EmailVerified = true
2022-02-18 12:36:11 +08:00
}
2024-03-10 12:34:56 +08:00
2022-02-18 12:36:11 +08:00
if strings . Contains ( scope , "address" ) {
resp . Address = user . Location
}
2024-03-10 12:34:56 +08:00
2022-02-18 12:36:11 +08:00
if strings . Contains ( scope , "phone" ) {
resp . Phone = user . Phone
}
2024-03-10 12:34:56 +08:00
return & resp , nil
2022-02-18 12:36:11 +08:00
}
2023-05-30 15:49:39 +08:00
func LinkUserAccount ( user * User , field string , value string ) ( bool , error ) {
2021-04-27 19:35:40 +08:00
return SetUserField ( user , field , value )
}
2021-05-08 22:04:45 +08:00
func ( user * User ) GetId ( ) string {
return fmt . Sprintf ( "%s/%s" , user . Owner , user . Name )
}
2021-12-29 19:12:11 +08:00
2023-12-30 00:47:10 +08:00
func ( user * User ) GetFriendlyName ( ) string {
if user . FirstName != "" && user . LastName != "" {
return fmt . Sprintf ( "%s, %s" , user . FirstName , user . LastName )
} else if user . DisplayName != "" {
return user . DisplayName
} else if user . Name != "" {
return user . Name
} else {
return user . Id
}
}
2021-12-29 19:12:11 +08:00
func isUserIdGlobalAdmin ( userId string ) bool {
2024-04-24 01:10:38 +08:00
return strings . HasPrefix ( userId , "built-in/" ) || IsAppUser ( userId )
2021-12-29 19:12:11 +08:00
}
2022-08-24 01:41:26 +08:00
2023-05-30 15:49:39 +08:00
func ExtendUserWithRolesAndPermissions ( user * User ) ( err error ) {
2022-08-24 01:41:26 +08:00
if user == nil {
return
}
2023-09-24 08:01:18 +08:00
user . Permissions , user . Roles , err = getPermissionsAndRolesByUser ( user . GetId ( ) )
2023-05-30 15:49:39 +08:00
if err != nil {
2023-06-16 21:44:21 +07:00
return err
2023-05-30 15:49:39 +08:00
}
2023-06-19 09:42:17 +08:00
if user . Groups == nil {
user . Groups = [ ] string { }
}
2023-05-30 15:49:39 +08:00
return
2022-08-24 01:41:26 +08:00
}
2022-11-02 00:17:38 +08:00
2023-08-11 10:59:18 +08:00
func DeleteGroupForUser ( user string , group string ) ( bool , error ) {
2025-05-28 22:29:40 +08:00
userObj , err := GetUser ( user )
if err != nil {
return false , err
}
userObj . Groups = util . DeleteVal ( userObj . Groups , group )
_ , err = updateUser ( user , userObj , [ ] string { "groups" } )
if err != nil {
return false , err
}
2023-08-11 10:59:18 +08:00
return userEnforcer . DeleteGroupForUser ( user , group )
}
2022-11-02 00:17:38 +08:00
func userChangeTrigger ( oldName string , newName string ) error {
2023-07-29 15:07:04 +08:00
session := ormer . Engine . NewSession ( )
2022-11-02 00:17:38 +08:00
defer session . Close ( )
err := session . Begin ( )
if err != nil {
return err
}
var roles [ ] * Role
2023-07-29 15:07:04 +08:00
err = ormer . Engine . Find ( & roles )
2022-11-02 00:17:38 +08:00
if err != nil {
return err
}
2023-05-30 15:49:39 +08:00
2022-11-02 00:17:38 +08:00
for _ , role := range roles {
for j , u := range role . Users {
// u = organization/username
2023-04-22 21:15:06 +08:00
owner , name := util . GetOwnerAndNameFromId ( u )
if name == oldName {
role . Users [ j ] = util . GetId ( owner , newName )
2022-11-02 00:17:38 +08:00
}
}
2023-04-22 21:15:06 +08:00
_ , err = session . Where ( "name=?" , role . Name ) . And ( "owner=?" , role . Owner ) . Update ( role )
2022-11-02 00:17:38 +08:00
if err != nil {
return err
}
}
var permissions [ ] * Permission
2023-07-29 15:07:04 +08:00
err = ormer . Engine . Find ( & permissions )
2022-11-02 00:17:38 +08:00
if err != nil {
return err
}
for _ , permission := range permissions {
for j , u := range permission . Users {
2024-02-21 01:14:32 +08:00
if u == "*" {
continue
}
2022-11-02 00:17:38 +08:00
// u = organization/username
2023-04-22 21:15:06 +08:00
owner , name := util . GetOwnerAndNameFromId ( u )
if name == oldName {
permission . Users [ j ] = util . GetId ( owner , newName )
2022-11-02 00:17:38 +08:00
}
}
2023-04-22 21:15:06 +08:00
_ , err = session . Where ( "name=?" , permission . Name ) . And ( "owner=?" , permission . Owner ) . Update ( permission )
2022-11-02 00:17:38 +08:00
if err != nil {
return err
}
}
resource := new ( Resource )
resource . User = newName
_ , err = session . Where ( "user=?" , oldName ) . Update ( resource )
if err != nil {
return err
}
return session . Commit ( )
}
2023-04-16 00:29:56 +08:00
2023-05-05 21:23:59 +08:00
func ( user * User ) IsMfaEnabled ( ) bool {
2023-07-07 12:30:07 +08:00
if user == nil {
return false
}
2023-06-21 18:56:37 +08:00
return user . PreferredMfaType != ""
2023-05-05 21:23:59 +08:00
}
2023-06-21 18:56:37 +08:00
func ( user * User ) GetPreferredMfaProps ( masked bool ) * MfaProps {
2023-07-07 12:30:07 +08:00
if user == nil || user . PreferredMfaType == "" {
2023-05-05 21:23:59 +08:00
return nil
}
2023-06-21 18:56:37 +08:00
return user . GetMfaProps ( user . PreferredMfaType , masked )
2023-05-05 21:23:59 +08:00
}
2023-06-13 22:18:17 +08:00
2023-10-31 13:23:06 +08:00
func AddUserKeys ( user * User , isAdmin bool ) ( bool , error ) {
2023-06-13 22:18:17 +08:00
if user == nil {
2023-10-31 13:20:44 +08:00
return false , fmt . Errorf ( "the user is not found" )
2023-06-13 22:18:17 +08:00
}
user . AccessKey = util . GenerateId ( )
2023-06-16 20:42:15 +08:00
user . AccessSecret = util . GenerateId ( )
2023-06-13 22:18:17 +08:00
return UpdateUser ( user . GetId ( ) , user , [ ] string { } , isAdmin )
}
2023-07-26 16:17:49 +07:00
func ( user * User ) IsApplicationAdmin ( application * Application ) bool {
if user == nil {
return false
}
2024-08-09 15:43:25 +08:00
return ( user . Owner == application . Organization && user . IsAdmin ) || user . IsGlobalAdmin ( ) || ( user . IsAdmin && application . IsShared )
2023-08-19 12:23:15 +08:00
}
func ( user * User ) IsGlobalAdmin ( ) bool {
if user == nil {
return false
}
return user . Owner == "built-in"
2023-07-26 16:17:49 +07:00
}
2023-09-20 22:45:00 +08:00
2025-03-19 22:57:35 +08:00
func ( user * User ) CheckUserFace ( faceIdImage [ ] string , provider * Provider ) ( bool , error ) {
faceIdChecker := faceId . GetFaceIdProvider ( provider . Type , provider . ClientId , provider . ClientSecret , provider . Endpoint )
httpClient := proxy . DefaultHttpClient
errList := [ ] error { }
for _ , userFaceId := range user . FaceIds {
if userFaceId . ImageUrl != "" {
imgResp , err := httpClient . Get ( userFaceId . ImageUrl )
if err != nil {
continue
}
imgByte , err := io . ReadAll ( imgResp . Body )
if err != nil {
continue
}
base64Img := base64 . StdEncoding . EncodeToString ( imgByte )
for _ , imgBase64 := range faceIdImage {
isSuccess , err := faceIdChecker . Check ( imgBase64 , base64Img )
if err != nil {
errList = append ( errList , err )
continue
}
if isSuccess {
return true , nil
}
}
}
}
if len ( errList ) > 0 {
return false , errList [ 0 ]
}
return false , nil
}
2023-09-20 22:45:00 +08:00
func GenerateIdForNewUser ( application * Application ) ( string , error ) {
2023-09-26 19:12:28 +08:00
if application == nil || application . GetSignupItemRule ( "ID" ) != "Incremental" {
2023-09-20 22:45:00 +08:00
return util . GenerateId ( ) , nil
}
lastUser , err := getLastUser ( application . Organization )
if err != nil {
return "" , err
}
lastUserId := - 1
if lastUser != nil {
2023-12-14 10:11:06 +08:00
lastUserId , err = util . ParseIntWithError ( lastUser . Id )
if err != nil {
return util . GenerateId ( ) , nil
}
2023-09-20 22:45:00 +08:00
}
res := strconv . Itoa ( lastUserId + 1 )
return res , nil
}
2024-06-22 14:05:53 +08:00
2024-07-12 15:48:37 +08:00
func UpdateUserBalance ( owner string , name string , balance float64 ) error {
2024-06-22 14:05:53 +08:00
user , err := getUser ( owner , name )
if err != nil {
return err
}
user . Balance += balance
_ , err = UpdateUser ( user . GetId ( ) , user , [ ] string { "balance" } , true )
return err
}