Guest accounts feature (#11428)
* MM-14139: Creating permissions for invite/promote/demote guests (#10778) * MM-14139: Creating permissions for invite/promote/demote guests * Fixing tests * Adding invite guest api endpoint (#10792) * Adding invite guest api endpoint * Adding i18n * Adding some tests * WIP * Migrating Token.Extra info to bigger size (2048) * Fixing tests * Adding client function for invite guests * Adding send guests invites tests * Renaming file from guest to guest_invite * Adding Promote/Demote users from/to guest endpoints (#10791) * Adding Promote/Demote users from/to guest endpoints * Adding i18n translations * Adding the client functions * Using getQueryBuilder function * Addressing PR review comments * Adding default channels to users on promte from guest (#10851) * Adding default channels to users on promte from guest * Addressing PR review comments * Fixing merge problems * Sending websockets events on promote/demote (#11403) * Sending websockets events on promote/demote * Fixing merge problems * Fixing govet shadowing problem * Fixing feature branch tests * Avoiding leaking users data through websockets for guest accounts (#11489) * Avoiding leaking users data through websockets for guest accounts * Adding tests and fixing code error * Fixing i18n * Allow to enable/disable guests and other extra config settings (#11481) * Allow to enable/disable guests and other extra config settings * Fixing tests and moving license and config validation to api level * Update api4/role_test.go Co-Authored-By: George Goldberg <george@gberg.me> * Update api4/role_test.go Co-Authored-By: George Goldberg <george@gberg.me> * Fixing typo * fixing tests * Managing correctly the guest channel leave behavior (#11578) * MM-15134: Removing guests from teams or system on leave channels if needed * WIP * No deactivating the guest user when leave the last team * Adding a couple of tests * Fixing shadow variables * Fixing tests * fixing tests * fixing shadow variables * Adding guest counts for channel stats (#11646) * Adding guest counts for channel stats * Adding tests * Fixing tests * Fixing guest domain restrictions (#11660) * Adding needed migration for the database * Fixing migration
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
fdde7c8287
Коммит
fe8a0f6485
106
app/user.go
106
app/user.go
@@ -40,26 +40,22 @@ const (
|
||||
TOKEN_TYPE_PASSWORD_RECOVERY = "password_recovery"
|
||||
TOKEN_TYPE_VERIFY_EMAIL = "verify_email"
|
||||
TOKEN_TYPE_TEAM_INVITATION = "team_invitation"
|
||||
TOKEN_TYPE_GUEST_INVITATION = "guest_invitation"
|
||||
PASSWORD_RECOVER_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour
|
||||
TEAM_INVITATION_EXPIRY_TIME = 1000 * 60 * 60 * 48 // 48 hours
|
||||
INVITATION_EXPIRY_TIME = 1000 * 60 * 60 * 48 // 48 hours
|
||||
IMAGE_PROFILE_PIXEL_DIMENSION = 128
|
||||
)
|
||||
|
||||
func (a *App) CreateUserWithToken(user *model.User, tokenId string) (*model.User, *model.AppError) {
|
||||
func (a *App) CreateUserWithToken(user *model.User, token *model.Token) (*model.User, *model.AppError) {
|
||||
if err := a.IsUserSignUpAllowed(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
token, err := a.Srv.Store.Token().GetByToken(tokenId)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("CreateUserWithToken", "api.user.create_user.signup_link_invalid.app_error", nil, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if token.Type != TOKEN_TYPE_TEAM_INVITATION {
|
||||
if token.Type != TOKEN_TYPE_TEAM_INVITATION && token.Type != TOKEN_TYPE_GUEST_INVITATION {
|
||||
return nil, model.NewAppError("CreateUserWithToken", "api.user.create_user.signup_link_invalid.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if model.GetMillis()-token.CreateAt >= TEAM_INVITATION_EXPIRY_TIME {
|
||||
if model.GetMillis()-token.CreateAt >= INVITATION_EXPIRY_TIME {
|
||||
a.DeleteToken(token)
|
||||
return nil, model.NewAppError("CreateUserWithToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
@@ -71,10 +67,20 @@ func (a *App) CreateUserWithToken(user *model.User, tokenId string) (*model.User
|
||||
return nil, err
|
||||
}
|
||||
|
||||
channels, err := a.Srv.Store.Channel().GetChannelsByIds(strings.Split(tokenData["channels"], " "))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
user.Email = tokenData["email"]
|
||||
user.EmailVerified = true
|
||||
|
||||
ruser, err := a.CreateUser(user)
|
||||
var ruser *model.User
|
||||
if token.Type == TOKEN_TYPE_TEAM_INVITATION {
|
||||
ruser, err = a.CreateUser(user)
|
||||
} else {
|
||||
ruser, err = a.CreateGuest(user)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -85,6 +91,15 @@ func (a *App) CreateUserWithToken(user *model.User, tokenId string) (*model.User
|
||||
|
||||
a.AddDirectChannels(team.Id, ruser)
|
||||
|
||||
if token.Type == TOKEN_TYPE_GUEST_INVITATION {
|
||||
for _, channel := range channels {
|
||||
_, err := a.AddUserToChannel(ruser, channel)
|
||||
if err != nil {
|
||||
mlog.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := a.DeleteToken(token); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -233,15 +248,19 @@ func (a *App) CreateGuest(user *model.User) (*model.User, *model.AppError) {
|
||||
}
|
||||
|
||||
func (a *App) createUserOrGuest(user *model.User, guest bool) (*model.User, *model.AppError) {
|
||||
if !user.IsLDAPUser() && !user.IsSAMLUser() && !CheckUserDomain(user, *a.Config().TeamSettings.RestrictCreationToDomains) {
|
||||
return nil, model.NewAppError("CreateUser", "api.user.create_user.accepted_domain.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
user.Roles = model.SYSTEM_USER_ROLE_ID
|
||||
if guest {
|
||||
user.Roles = model.SYSTEM_GUEST_ROLE_ID
|
||||
}
|
||||
|
||||
if !user.IsLDAPUser() && !user.IsSAMLUser() && !user.IsGuest() && !CheckUserDomain(user, *a.Config().TeamSettings.RestrictCreationToDomains) {
|
||||
return nil, model.NewAppError("CreateUser", "api.user.create_user.accepted_domain.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if !user.IsLDAPUser() && !user.IsSAMLUser() && user.IsGuest() && !CheckUserDomain(user, *a.Config().GuestAccountsSettings.RestrictCreationToDomains) {
|
||||
return nil, model.NewAppError("CreateUser", "api.user.create_user.accepted_domain.app_error", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
// Below is a special case where the first user in the entire
|
||||
// system is granted the system_admin role
|
||||
count, err := a.Srv.Store.User().Count(model.UserCountOptions{IncludeDeleted: true})
|
||||
@@ -1056,13 +1075,13 @@ func (a *App) sendUpdatedUserEvent(user model.User) {
|
||||
adminCopyOfUser := user.DeepCopy()
|
||||
a.SanitizeProfile(adminCopyOfUser, true)
|
||||
adminMessage := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", nil)
|
||||
adminMessage.Add("user", *adminCopyOfUser)
|
||||
adminMessage.Add("user", &adminCopyOfUser)
|
||||
adminMessage.Broadcast.ContainsSensitiveData = true
|
||||
a.Publish(adminMessage)
|
||||
|
||||
a.SanitizeProfile(&user, false)
|
||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", nil)
|
||||
message.Add("user", user)
|
||||
message.Add("user", &user)
|
||||
message.Broadcast.ContainsSanitizedData = true
|
||||
a.Publish(message)
|
||||
}
|
||||
@@ -2200,6 +2219,61 @@ func (a *App) getListOfAllowedChannelsForTeam(teamId string, viewRestrictions *m
|
||||
return listOfAllowedChannels, nil
|
||||
}
|
||||
|
||||
// PromoteGuestToUser Convert user's roles and all his mermbership's roles from
|
||||
// guest roles to regular user roles.
|
||||
func (a *App) PromoteGuestToUser(user *model.User, requestorId string) *model.AppError {
|
||||
err := a.Srv.Store.User().PromoteGuestToUser(user.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userTeams, err := a.Srv.Store.Team().GetTeamsByUserId(user.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, team := range userTeams {
|
||||
// Soft error if there is an issue joining the default channels
|
||||
if err = a.JoinDefaultChannels(team.Id, user, false, requestorId); err != nil {
|
||||
mlog.Error(fmt.Sprintf("Encountered an issue joining default channels err=%v", err), mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.String("requestor_id", requestorId))
|
||||
}
|
||||
}
|
||||
|
||||
promotedUser, err := a.GetUser(user.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", nil)
|
||||
message.Add("user", promotedUser)
|
||||
a.Publish(message)
|
||||
|
||||
a.UpdateSessionsIsGuest(promotedUser.Id, promotedUser.IsGuest())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DemoteUserToGuest Convert user's roles and all his mermbership's roles from
|
||||
// regular user roles to guest roles.
|
||||
func (a *App) DemoteUserToGuest(user *model.User) *model.AppError {
|
||||
err := a.Srv.Store.User().DemoteUserToGuest(user.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
demotedUser, err := a.GetUser(user.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", nil)
|
||||
message.Add("user", demotedUser)
|
||||
a.Publish(message)
|
||||
|
||||
a.UpdateSessionsIsGuest(demotedUser.Id, demotedUser.IsGuest())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// invalidateUserCacheAndPublish Invalidates cache for a user and publishes user updated event
|
||||
func (a *App) invalidateUserCacheAndPublish(userId string) {
|
||||
a.InvalidateCacheForUser(userId)
|
||||
|
||||
Ссылка в новой задаче
Block a user