* 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
Этот коммит содержится в:
Jesús Espino
2019-07-22 22:13:39 +02:00
коммит произвёл GitHub
родитель fdde7c8287
Коммит fe8a0f6485
48 изменённых файлов: 2630 добавлений и 133 удалений

Просмотреть файл

@@ -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)