github.com/spreadshirt/mattermost-server@v5.3.2-0.20180927191755-a257d501df3d+incompatible/api4/user.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package api4
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"io/ioutil"
    10  	"net/http"
    11  	"strconv"
    12  	"time"
    13  
    14  	"github.com/mattermost/mattermost-server/app"
    15  	"github.com/mattermost/mattermost-server/mlog"
    16  	"github.com/mattermost/mattermost-server/model"
    17  	"github.com/mattermost/mattermost-server/store"
    18  )
    19  
    20  func (api *API) InitUser() {
    21  	api.BaseRoutes.Users.Handle("", api.ApiHandler(createUser)).Methods("POST")
    22  	api.BaseRoutes.Users.Handle("", api.ApiSessionRequired(getUsers)).Methods("GET")
    23  	api.BaseRoutes.Users.Handle("/ids", api.ApiSessionRequired(getUsersByIds)).Methods("POST")
    24  	api.BaseRoutes.Users.Handle("/usernames", api.ApiSessionRequired(getUsersByNames)).Methods("POST")
    25  	api.BaseRoutes.Users.Handle("/search", api.ApiSessionRequired(searchUsers)).Methods("POST")
    26  	api.BaseRoutes.Users.Handle("/autocomplete", api.ApiSessionRequired(autocompleteUsers)).Methods("GET")
    27  	api.BaseRoutes.Users.Handle("/stats", api.ApiSessionRequired(getTotalUsersStats)).Methods("GET")
    28  
    29  	api.BaseRoutes.User.Handle("", api.ApiSessionRequired(getUser)).Methods("GET")
    30  	api.BaseRoutes.User.Handle("/image", api.ApiSessionRequiredTrustRequester(getProfileImage)).Methods("GET")
    31  	api.BaseRoutes.User.Handle("/image", api.ApiSessionRequired(setProfileImage)).Methods("POST")
    32  	api.BaseRoutes.User.Handle("", api.ApiSessionRequired(updateUser)).Methods("PUT")
    33  	api.BaseRoutes.User.Handle("/patch", api.ApiSessionRequired(patchUser)).Methods("PUT")
    34  	api.BaseRoutes.User.Handle("", api.ApiSessionRequired(deleteUser)).Methods("DELETE")
    35  	api.BaseRoutes.User.Handle("/roles", api.ApiSessionRequired(updateUserRoles)).Methods("PUT")
    36  	api.BaseRoutes.User.Handle("/active", api.ApiSessionRequired(updateUserActive)).Methods("PUT")
    37  	api.BaseRoutes.User.Handle("/password", api.ApiSessionRequired(updatePassword)).Methods("PUT")
    38  	api.BaseRoutes.Users.Handle("/password/reset", api.ApiHandler(resetPassword)).Methods("POST")
    39  	api.BaseRoutes.Users.Handle("/password/reset/send", api.ApiHandler(sendPasswordReset)).Methods("POST")
    40  	api.BaseRoutes.Users.Handle("/email/verify", api.ApiHandler(verifyUserEmail)).Methods("POST")
    41  	api.BaseRoutes.Users.Handle("/email/verify/send", api.ApiHandler(sendVerificationEmail)).Methods("POST")
    42  	api.BaseRoutes.User.Handle("/terms_of_service", api.ApiSessionRequired(registerServiceTermsAction)).Methods("POST")
    43  
    44  	api.BaseRoutes.User.Handle("/auth", api.ApiSessionRequiredTrustRequester(updateUserAuth)).Methods("PUT")
    45  
    46  	api.BaseRoutes.Users.Handle("/mfa", api.ApiHandler(checkUserMfa)).Methods("POST")
    47  	api.BaseRoutes.User.Handle("/mfa", api.ApiSessionRequiredMfa(updateUserMfa)).Methods("PUT")
    48  	api.BaseRoutes.User.Handle("/mfa/generate", api.ApiSessionRequiredMfa(generateMfaSecret)).Methods("POST")
    49  
    50  	api.BaseRoutes.Users.Handle("/login", api.ApiHandler(login)).Methods("POST")
    51  	api.BaseRoutes.Users.Handle("/login/switch", api.ApiHandler(switchAccountType)).Methods("POST")
    52  	api.BaseRoutes.Users.Handle("/logout", api.ApiHandler(logout)).Methods("POST")
    53  
    54  	api.BaseRoutes.UserByUsername.Handle("", api.ApiSessionRequired(getUserByUsername)).Methods("GET")
    55  	api.BaseRoutes.UserByEmail.Handle("", api.ApiSessionRequired(getUserByEmail)).Methods("GET")
    56  
    57  	api.BaseRoutes.User.Handle("/sessions", api.ApiSessionRequired(getSessions)).Methods("GET")
    58  	api.BaseRoutes.User.Handle("/sessions/revoke", api.ApiSessionRequired(revokeSession)).Methods("POST")
    59  	api.BaseRoutes.User.Handle("/sessions/revoke/all", api.ApiSessionRequired(revokeAllSessionsForUser)).Methods("POST")
    60  	api.BaseRoutes.Users.Handle("/sessions/device", api.ApiSessionRequired(attachDeviceId)).Methods("PUT")
    61  	api.BaseRoutes.User.Handle("/audits", api.ApiSessionRequired(getUserAudits)).Methods("GET")
    62  
    63  	api.BaseRoutes.User.Handle("/tokens", api.ApiSessionRequired(createUserAccessToken)).Methods("POST")
    64  	api.BaseRoutes.User.Handle("/tokens", api.ApiSessionRequired(getUserAccessTokensForUser)).Methods("GET")
    65  	api.BaseRoutes.Users.Handle("/tokens", api.ApiSessionRequired(getUserAccessTokens)).Methods("GET")
    66  	api.BaseRoutes.Users.Handle("/tokens/search", api.ApiSessionRequired(searchUserAccessTokens)).Methods("POST")
    67  	api.BaseRoutes.Users.Handle("/tokens/{token_id:[A-Za-z0-9]+}", api.ApiSessionRequired(getUserAccessToken)).Methods("GET")
    68  	api.BaseRoutes.Users.Handle("/tokens/revoke", api.ApiSessionRequired(revokeUserAccessToken)).Methods("POST")
    69  	api.BaseRoutes.Users.Handle("/tokens/disable", api.ApiSessionRequired(disableUserAccessToken)).Methods("POST")
    70  	api.BaseRoutes.Users.Handle("/tokens/enable", api.ApiSessionRequired(enableUserAccessToken)).Methods("POST")
    71  }
    72  
    73  func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
    74  	user := model.UserFromJson(r.Body)
    75  	if user == nil {
    76  		c.SetInvalidParam("user")
    77  		return
    78  	}
    79  
    80  	tokenId := r.URL.Query().Get("t")
    81  	inviteId := r.URL.Query().Get("iid")
    82  
    83  	// No permission check required
    84  
    85  	var ruser *model.User
    86  	var err *model.AppError
    87  	if len(tokenId) > 0 {
    88  		ruser, err = c.App.CreateUserWithToken(user, tokenId)
    89  	} else if len(inviteId) > 0 {
    90  		ruser, err = c.App.CreateUserWithInviteId(user, inviteId)
    91  	} else if c.IsSystemAdmin() {
    92  		ruser, err = c.App.CreateUserAsAdmin(user)
    93  	} else {
    94  		ruser, err = c.App.CreateUserFromSignup(user)
    95  	}
    96  
    97  	if err != nil {
    98  		c.Err = err
    99  		return
   100  	}
   101  
   102  	w.WriteHeader(http.StatusCreated)
   103  	w.Write([]byte(ruser.ToJson()))
   104  }
   105  
   106  func getUser(c *Context, w http.ResponseWriter, r *http.Request) {
   107  	c.RequireUserId()
   108  	if c.Err != nil {
   109  		return
   110  	}
   111  
   112  	// No permission check required
   113  
   114  	var user *model.User
   115  	var err *model.AppError
   116  
   117  	if user, err = c.App.GetUser(c.Params.UserId); err != nil {
   118  		c.Err = err
   119  		return
   120  	}
   121  
   122  	etag := user.Etag(c.App.Config().PrivacySettings.ShowFullName, c.App.Config().PrivacySettings.ShowEmailAddress)
   123  
   124  	if c.HandleEtag(etag, "Get User", w, r) {
   125  		return
   126  	}
   127  
   128  	if c.Session.UserId == user.Id {
   129  		user.Sanitize(map[string]bool{})
   130  	} else {
   131  		c.App.SanitizeProfile(user, c.IsSystemAdmin())
   132  	}
   133  	c.App.UpdateLastActivityAtIfNeeded(c.Session)
   134  	w.Header().Set(model.HEADER_ETAG_SERVER, etag)
   135  	w.Write([]byte(user.ToJson()))
   136  }
   137  
   138  func getUserByUsername(c *Context, w http.ResponseWriter, r *http.Request) {
   139  	c.RequireUsername()
   140  	if c.Err != nil {
   141  		return
   142  	}
   143  
   144  	// No permission check required
   145  
   146  	var user *model.User
   147  	var err *model.AppError
   148  
   149  	if user, err = c.App.GetUserByUsername(c.Params.Username); err != nil {
   150  		c.Err = err
   151  		return
   152  	}
   153  
   154  	etag := user.Etag(c.App.Config().PrivacySettings.ShowFullName, c.App.Config().PrivacySettings.ShowEmailAddress)
   155  
   156  	if c.HandleEtag(etag, "Get User", w, r) {
   157  		return
   158  	}
   159  
   160  	if c.Session.UserId == user.Id {
   161  		user.Sanitize(map[string]bool{})
   162  	} else {
   163  		c.App.SanitizeProfile(user, c.IsSystemAdmin())
   164  	}
   165  	w.Header().Set(model.HEADER_ETAG_SERVER, etag)
   166  	w.Write([]byte(user.ToJson()))
   167  }
   168  
   169  func getUserByEmail(c *Context, w http.ResponseWriter, r *http.Request) {
   170  	c.RequireEmail()
   171  	if c.Err != nil {
   172  		return
   173  	}
   174  
   175  	// No permission check required
   176  
   177  	var user *model.User
   178  	var err *model.AppError
   179  
   180  	if user, err = c.App.GetUserByEmail(c.Params.Email); err != nil {
   181  		c.Err = err
   182  		return
   183  	}
   184  
   185  	etag := user.Etag(c.App.Config().PrivacySettings.ShowFullName, c.App.Config().PrivacySettings.ShowEmailAddress)
   186  
   187  	if c.HandleEtag(etag, "Get User", w, r) {
   188  		return
   189  	}
   190  
   191  	c.App.SanitizeProfile(user, c.IsSystemAdmin())
   192  	w.Header().Set(model.HEADER_ETAG_SERVER, etag)
   193  	w.Write([]byte(user.ToJson()))
   194  }
   195  
   196  func getProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
   197  	c.RequireUserId()
   198  	if c.Err != nil {
   199  		return
   200  	}
   201  
   202  	users, err := c.App.GetUsersByIds([]string{c.Params.UserId}, c.IsSystemAdmin())
   203  	if err != nil {
   204  		c.Err = err
   205  		return
   206  	}
   207  
   208  	if len(users) == 0 {
   209  		c.Err = model.NewAppError("getProfileImage", "api.user.get_profile_image.not_found.app_error", nil, "", http.StatusNotFound)
   210  		return
   211  	}
   212  
   213  	user := users[0]
   214  	etag := strconv.FormatInt(user.LastPictureUpdate, 10)
   215  	if c.HandleEtag(etag, "Get Profile Image", w, r) {
   216  		return
   217  	}
   218  
   219  	var img []byte
   220  	img, readFailed, err := c.App.GetProfileImage(user)
   221  	if err != nil {
   222  		c.Err = err
   223  		return
   224  	}
   225  
   226  	if readFailed {
   227  		w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%v, public", 5*60)) // 5 mins
   228  	} else {
   229  		w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%v, public", 24*60*60)) // 24 hrs
   230  		w.Header().Set(model.HEADER_ETAG_SERVER, etag)
   231  	}
   232  
   233  	w.Header().Set("Content-Type", "image/png")
   234  	w.Write(img)
   235  }
   236  
   237  func setProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
   238  	defer io.Copy(ioutil.Discard, r.Body)
   239  
   240  	c.RequireUserId()
   241  	if c.Err != nil {
   242  		return
   243  	}
   244  
   245  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
   246  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   247  		return
   248  	}
   249  
   250  	if len(*c.App.Config().FileSettings.DriverName) == 0 {
   251  		c.Err = model.NewAppError("uploadProfileImage", "api.user.upload_profile_user.storage.app_error", nil, "", http.StatusNotImplemented)
   252  		return
   253  	}
   254  
   255  	if r.ContentLength > *c.App.Config().FileSettings.MaxFileSize {
   256  		c.Err = model.NewAppError("uploadProfileImage", "api.user.upload_profile_user.too_large.app_error", nil, "", http.StatusRequestEntityTooLarge)
   257  		return
   258  	}
   259  
   260  	if err := r.ParseMultipartForm(*c.App.Config().FileSettings.MaxFileSize); err != nil {
   261  		c.Err = model.NewAppError("uploadProfileImage", "api.user.upload_profile_user.parse.app_error", nil, err.Error(), http.StatusInternalServerError)
   262  		return
   263  	}
   264  
   265  	m := r.MultipartForm
   266  
   267  	imageArray, ok := m.File["image"]
   268  	if !ok {
   269  		c.Err = model.NewAppError("uploadProfileImage", "api.user.upload_profile_user.no_file.app_error", nil, "", http.StatusBadRequest)
   270  		return
   271  	}
   272  
   273  	if len(imageArray) <= 0 {
   274  		c.Err = model.NewAppError("uploadProfileImage", "api.user.upload_profile_user.array.app_error", nil, "", http.StatusBadRequest)
   275  		return
   276  	}
   277  
   278  	imageData := imageArray[0]
   279  
   280  	if err := c.App.SetProfileImage(c.Params.UserId, imageData); err != nil {
   281  		c.Err = err
   282  		return
   283  	}
   284  
   285  	c.LogAudit("")
   286  	ReturnStatusOK(w)
   287  }
   288  
   289  func getTotalUsersStats(c *Context, w http.ResponseWriter, r *http.Request) {
   290  	if c.Err != nil {
   291  		return
   292  	}
   293  
   294  	stats, err := c.App.GetTotalUsersStats()
   295  	if err != nil {
   296  		c.Err = err
   297  		return
   298  	}
   299  
   300  	w.Write([]byte(stats.ToJson()))
   301  }
   302  
   303  func getUsers(c *Context, w http.ResponseWriter, r *http.Request) {
   304  	inTeamId := r.URL.Query().Get("in_team")
   305  	notInTeamId := r.URL.Query().Get("not_in_team")
   306  	inChannelId := r.URL.Query().Get("in_channel")
   307  	notInChannelId := r.URL.Query().Get("not_in_channel")
   308  	withoutTeam := r.URL.Query().Get("without_team")
   309  	sort := r.URL.Query().Get("sort")
   310  
   311  	if len(notInChannelId) > 0 && len(inTeamId) == 0 {
   312  		c.SetInvalidUrlParam("team_id")
   313  		return
   314  	}
   315  
   316  	if sort != "" && sort != "last_activity_at" && sort != "create_at" && sort != "status" {
   317  		c.SetInvalidUrlParam("sort")
   318  		return
   319  	}
   320  
   321  	// Currently only supports sorting on a team
   322  	// or sort="status" on inChannelId
   323  	if (sort == "last_activity_at" || sort == "create_at") && (inTeamId == "" || notInTeamId != "" || inChannelId != "" || notInChannelId != "" || withoutTeam != "") {
   324  		c.SetInvalidUrlParam("sort")
   325  		return
   326  	}
   327  	if sort == "status" && inChannelId == "" {
   328  		c.SetInvalidUrlParam("sort")
   329  		return
   330  	}
   331  
   332  	var profiles []*model.User
   333  	var err *model.AppError
   334  	etag := ""
   335  
   336  	if withoutTeamBool, _ := strconv.ParseBool(withoutTeam); withoutTeamBool {
   337  		// Use a special permission for now
   338  		if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_LIST_USERS_WITHOUT_TEAM) {
   339  			c.SetPermissionError(model.PERMISSION_LIST_USERS_WITHOUT_TEAM)
   340  			return
   341  		}
   342  
   343  		profiles, err = c.App.GetUsersWithoutTeamPage(c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   344  	} else if len(notInChannelId) > 0 {
   345  		if !c.App.SessionHasPermissionToChannel(c.Session, notInChannelId, model.PERMISSION_READ_CHANNEL) {
   346  			c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
   347  			return
   348  		}
   349  
   350  		profiles, err = c.App.GetUsersNotInChannelPage(inTeamId, notInChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   351  	} else if len(notInTeamId) > 0 {
   352  		if !c.App.SessionHasPermissionToTeam(c.Session, notInTeamId, model.PERMISSION_VIEW_TEAM) {
   353  			c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   354  			return
   355  		}
   356  
   357  		etag = c.App.GetUsersNotInTeamEtag(inTeamId)
   358  		if c.HandleEtag(etag, "Get Users Not in Team", w, r) {
   359  			return
   360  		}
   361  
   362  		profiles, err = c.App.GetUsersNotInTeamPage(notInTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   363  	} else if len(inTeamId) > 0 {
   364  		if !c.App.SessionHasPermissionToTeam(c.Session, inTeamId, model.PERMISSION_VIEW_TEAM) {
   365  			c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   366  			return
   367  		}
   368  
   369  		if sort == "last_activity_at" {
   370  			profiles, err = c.App.GetRecentlyActiveUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   371  		} else if sort == "create_at" {
   372  			profiles, err = c.App.GetNewUsersForTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   373  		} else {
   374  			etag = c.App.GetUsersInTeamEtag(inTeamId)
   375  			if c.HandleEtag(etag, "Get Users in Team", w, r) {
   376  				return
   377  			}
   378  
   379  			profiles, err = c.App.GetUsersInTeamPage(inTeamId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   380  		}
   381  	} else if len(inChannelId) > 0 {
   382  		if !c.App.SessionHasPermissionToChannel(c.Session, inChannelId, model.PERMISSION_READ_CHANNEL) {
   383  			c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
   384  			return
   385  		}
   386  		if sort == "status" {
   387  			profiles, err = c.App.GetUsersInChannelPageByStatus(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   388  		} else {
   389  			profiles, err = c.App.GetUsersInChannelPage(inChannelId, c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   390  		}
   391  	} else {
   392  		// No permission check required
   393  
   394  		etag = c.App.GetUsersEtag()
   395  		if c.HandleEtag(etag, "Get Users", w, r) {
   396  			return
   397  		}
   398  		profiles, err = c.App.GetUsersPage(c.Params.Page, c.Params.PerPage, c.IsSystemAdmin())
   399  	}
   400  
   401  	if err != nil {
   402  		c.Err = err
   403  		return
   404  	}
   405  
   406  	if len(etag) > 0 {
   407  		w.Header().Set(model.HEADER_ETAG_SERVER, etag)
   408  	}
   409  	c.App.UpdateLastActivityAtIfNeeded(c.Session)
   410  	w.Write([]byte(model.UserListToJson(profiles)))
   411  }
   412  
   413  func getUsersByIds(c *Context, w http.ResponseWriter, r *http.Request) {
   414  	userIds := model.ArrayFromJson(r.Body)
   415  
   416  	if len(userIds) == 0 {
   417  		c.SetInvalidParam("user_ids")
   418  		return
   419  	}
   420  
   421  	// No permission check required
   422  
   423  	users, err := c.App.GetUsersByIds(userIds, c.IsSystemAdmin())
   424  	if err != nil {
   425  		c.Err = err
   426  		return
   427  	}
   428  
   429  	w.Write([]byte(model.UserListToJson(users)))
   430  }
   431  
   432  func getUsersByNames(c *Context, w http.ResponseWriter, r *http.Request) {
   433  	usernames := model.ArrayFromJson(r.Body)
   434  
   435  	if len(usernames) == 0 {
   436  		c.SetInvalidParam("usernames")
   437  		return
   438  	}
   439  
   440  	// No permission check required
   441  
   442  	users, err := c.App.GetUsersByUsernames(usernames, c.IsSystemAdmin())
   443  	if err != nil {
   444  		c.Err = err
   445  		return
   446  	}
   447  
   448  	w.Write([]byte(model.UserListToJson(users)))
   449  }
   450  
   451  func searchUsers(c *Context, w http.ResponseWriter, r *http.Request) {
   452  	props := model.UserSearchFromJson(r.Body)
   453  	if props == nil {
   454  		c.SetInvalidParam("")
   455  		return
   456  	}
   457  
   458  	if len(props.Term) == 0 {
   459  		c.SetInvalidParam("term")
   460  		return
   461  	}
   462  
   463  	if props.TeamId == "" && props.NotInChannelId != "" {
   464  		c.SetInvalidParam("team_id")
   465  		return
   466  	}
   467  
   468  	if props.InChannelId != "" && !c.App.SessionHasPermissionToChannel(c.Session, props.InChannelId, model.PERMISSION_READ_CHANNEL) {
   469  		c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
   470  		return
   471  	}
   472  
   473  	if props.NotInChannelId != "" && !c.App.SessionHasPermissionToChannel(c.Session, props.NotInChannelId, model.PERMISSION_READ_CHANNEL) {
   474  		c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
   475  		return
   476  	}
   477  
   478  	if props.TeamId != "" && !c.App.SessionHasPermissionToTeam(c.Session, props.TeamId, model.PERMISSION_VIEW_TEAM) {
   479  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   480  		return
   481  	}
   482  
   483  	if props.NotInTeamId != "" && !c.App.SessionHasPermissionToTeam(c.Session, props.NotInTeamId, model.PERMISSION_VIEW_TEAM) {
   484  		c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   485  		return
   486  	}
   487  
   488  	searchOptions := map[string]bool{}
   489  	searchOptions[store.USER_SEARCH_OPTION_ALLOW_INACTIVE] = props.AllowInactive
   490  
   491  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
   492  		hideFullName := !c.App.Config().PrivacySettings.ShowFullName
   493  		hideEmail := !c.App.Config().PrivacySettings.ShowEmailAddress
   494  
   495  		if hideFullName && hideEmail {
   496  			searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME] = true
   497  		} else if hideFullName {
   498  			searchOptions[store.USER_SEARCH_OPTION_ALL_NO_FULL_NAME] = true
   499  		} else if hideEmail {
   500  			searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
   501  		}
   502  	}
   503  
   504  	profiles, err := c.App.SearchUsers(props, searchOptions, c.IsSystemAdmin())
   505  	if err != nil {
   506  		c.Err = err
   507  		return
   508  	}
   509  
   510  	w.Write([]byte(model.UserListToJson(profiles)))
   511  }
   512  
   513  func autocompleteUsers(c *Context, w http.ResponseWriter, r *http.Request) {
   514  	channelId := r.URL.Query().Get("in_channel")
   515  	teamId := r.URL.Query().Get("in_team")
   516  	name := r.URL.Query().Get("name")
   517  
   518  	autocomplete := new(model.UserAutocomplete)
   519  	var err *model.AppError
   520  
   521  	searchOptions := map[string]bool{}
   522  
   523  	hideFullName := !c.App.Config().PrivacySettings.ShowFullName
   524  	if hideFullName && !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
   525  		searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME] = true
   526  	} else {
   527  		searchOptions[store.USER_SEARCH_OPTION_NAMES_ONLY] = true
   528  	}
   529  
   530  	if len(channelId) > 0 {
   531  		if !c.App.SessionHasPermissionToChannel(c.Session, channelId, model.PERMISSION_READ_CHANNEL) {
   532  			c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
   533  			return
   534  		}
   535  
   536  		result, err := c.App.AutocompleteUsersInChannel(teamId, channelId, name, searchOptions, c.IsSystemAdmin())
   537  		if err != nil {
   538  			c.Err = err
   539  			return
   540  		}
   541  
   542  		autocomplete.Users = result.InChannel
   543  		autocomplete.OutOfChannel = result.OutOfChannel
   544  	} else if len(teamId) > 0 {
   545  		if !c.App.SessionHasPermissionToTeam(c.Session, teamId, model.PERMISSION_VIEW_TEAM) {
   546  			c.SetPermissionError(model.PERMISSION_VIEW_TEAM)
   547  			return
   548  		}
   549  
   550  		result, err := c.App.AutocompleteUsersInTeam(teamId, name, searchOptions, c.IsSystemAdmin())
   551  		if err != nil {
   552  			c.Err = err
   553  			return
   554  		}
   555  
   556  		autocomplete.Users = result.InTeam
   557  	} else {
   558  		// No permission check required
   559  		result, err := c.App.SearchUsersInTeam("", name, searchOptions, c.IsSystemAdmin())
   560  		if err != nil {
   561  			c.Err = err
   562  			return
   563  		}
   564  		autocomplete.Users = result
   565  	}
   566  
   567  	if err != nil {
   568  		c.Err = err
   569  		return
   570  	}
   571  
   572  	w.Write([]byte((autocomplete.ToJson())))
   573  }
   574  
   575  func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
   576  	c.RequireUserId()
   577  	if c.Err != nil {
   578  		return
   579  	}
   580  
   581  	user := model.UserFromJson(r.Body)
   582  	if user == nil {
   583  		c.SetInvalidParam("user")
   584  		return
   585  	}
   586  
   587  	// The user being updated in the payload must be the same one as indicated in the URL.
   588  	if user.Id != c.Params.UserId {
   589  		c.SetInvalidParam("user_id")
   590  		return
   591  	}
   592  
   593  	if !c.App.SessionHasPermissionToUser(c.Session, user.Id) {
   594  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   595  		return
   596  	}
   597  
   598  	if c.Session.IsOAuth {
   599  		ouser, err := c.App.GetUser(user.Id)
   600  		if err != nil {
   601  			c.Err = err
   602  			return
   603  		}
   604  
   605  		if ouser.Email != user.Email {
   606  			c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   607  			c.Err.DetailedError += ", attempted email update by oauth app"
   608  			return
   609  		}
   610  	}
   611  
   612  	ruser, err := c.App.UpdateUserAsUser(user, c.IsSystemAdmin())
   613  	if err != nil {
   614  		c.Err = err
   615  		return
   616  	}
   617  
   618  	c.LogAudit("")
   619  	w.Write([]byte(ruser.ToJson()))
   620  }
   621  
   622  func patchUser(c *Context, w http.ResponseWriter, r *http.Request) {
   623  	c.RequireUserId()
   624  	if c.Err != nil {
   625  		return
   626  	}
   627  
   628  	patch := model.UserPatchFromJson(r.Body)
   629  	if patch == nil {
   630  		c.SetInvalidParam("user")
   631  		return
   632  	}
   633  
   634  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
   635  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   636  		return
   637  	}
   638  
   639  	ouser, err := c.App.GetUser(c.Params.UserId)
   640  	if err != nil {
   641  		c.SetInvalidParam("user_id")
   642  		return
   643  	}
   644  
   645  	if c.Session.IsOAuth && patch.Email != nil {
   646  		if err != nil {
   647  			c.Err = err
   648  			return
   649  		}
   650  
   651  		if ouser.Email != *patch.Email {
   652  			c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   653  			c.Err.DetailedError += ", attempted email update by oauth app"
   654  			return
   655  		}
   656  	}
   657  
   658  	ruser, err := c.App.PatchUser(c.Params.UserId, patch, c.IsSystemAdmin())
   659  	if err != nil {
   660  		c.Err = err
   661  		return
   662  	}
   663  
   664  	c.App.SetAutoResponderStatus(ruser, ouser.NotifyProps)
   665  	c.LogAudit("")
   666  	w.Write([]byte(ruser.ToJson()))
   667  }
   668  
   669  func deleteUser(c *Context, w http.ResponseWriter, r *http.Request) {
   670  	c.RequireUserId()
   671  	if c.Err != nil {
   672  		return
   673  	}
   674  
   675  	userId := c.Params.UserId
   676  
   677  	if !c.App.SessionHasPermissionToUser(c.Session, userId) {
   678  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   679  		return
   680  	}
   681  
   682  	var user *model.User
   683  	var err *model.AppError
   684  
   685  	if user, err = c.App.GetUser(userId); err != nil {
   686  		c.Err = err
   687  		return
   688  	}
   689  
   690  	if _, err := c.App.UpdateActive(user, false); err != nil {
   691  		c.Err = err
   692  		return
   693  	}
   694  
   695  	ReturnStatusOK(w)
   696  }
   697  
   698  func updateUserRoles(c *Context, w http.ResponseWriter, r *http.Request) {
   699  	c.RequireUserId()
   700  	if c.Err != nil {
   701  		return
   702  	}
   703  
   704  	props := model.MapFromJson(r.Body)
   705  
   706  	newRoles := props["roles"]
   707  	if !model.IsValidUserRoles(newRoles) {
   708  		c.SetInvalidParam("roles")
   709  		return
   710  	}
   711  
   712  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_ROLES) {
   713  		c.SetPermissionError(model.PERMISSION_MANAGE_ROLES)
   714  		return
   715  	}
   716  
   717  	if _, err := c.App.UpdateUserRoles(c.Params.UserId, newRoles, true); err != nil {
   718  		c.Err = err
   719  		return
   720  	}
   721  
   722  	c.LogAuditWithUserId(c.Params.UserId, "roles="+newRoles)
   723  	ReturnStatusOK(w)
   724  }
   725  
   726  func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) {
   727  	c.RequireUserId()
   728  	if c.Err != nil {
   729  		return
   730  	}
   731  
   732  	props := model.StringInterfaceFromJson(r.Body)
   733  
   734  	active, ok := props["active"].(bool)
   735  	if !ok {
   736  		c.SetInvalidParam("active")
   737  		return
   738  	}
   739  
   740  	// true when you're trying to de-activate yourself
   741  	isSelfDeactive := !active && c.Params.UserId == c.Session.UserId
   742  
   743  	if !isSelfDeactive && !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
   744  		c.Err = model.NewAppError("updateUserActive", "api.user.update_active.permissions.app_error", nil, "userId="+c.Params.UserId, http.StatusForbidden)
   745  		return
   746  	}
   747  
   748  	// if EnableUserDeactivation flag is disabled the user cannot deactivate himself.
   749  	if isSelfDeactive && !*c.App.GetConfig().TeamSettings.EnableUserDeactivation {
   750  		c.Err = model.NewAppError("updateUserActive", "api.user.update_active.not_enable.app_error", nil, "userId="+c.Params.UserId, http.StatusUnauthorized)
   751  		return
   752  	}
   753  
   754  	var user *model.User
   755  	var err *model.AppError
   756  
   757  	if user, err = c.App.GetUser(c.Params.UserId); err != nil {
   758  		c.Err = err
   759  		return
   760  	}
   761  
   762  	if _, err := c.App.UpdateActive(user, active); err != nil {
   763  		c.Err = err
   764  	}
   765  
   766  	c.LogAuditWithUserId(user.Id, fmt.Sprintf("active=%v", active))
   767  	if isSelfDeactive {
   768  		c.App.Go(func() {
   769  			if err = c.App.SendDeactivateAccountEmail(user.Email, user.Locale, c.App.GetSiteURL()); err != nil {
   770  				mlog.Error(err.Error())
   771  			}
   772  		})
   773  	}
   774  	ReturnStatusOK(w)
   775  }
   776  
   777  func updateUserAuth(c *Context, w http.ResponseWriter, r *http.Request) {
   778  	if !c.IsSystemAdmin() {
   779  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   780  		return
   781  	}
   782  
   783  	c.RequireUserId()
   784  	if c.Err != nil {
   785  		return
   786  	}
   787  
   788  	userAuth := model.UserAuthFromJson(r.Body)
   789  	if userAuth == nil {
   790  		c.SetInvalidParam("user")
   791  		return
   792  	}
   793  
   794  	user, err := c.App.UpdateUserAuth(c.Params.UserId, userAuth)
   795  	if err != nil {
   796  		c.Err = err
   797  	}
   798  
   799  	c.LogAuditWithUserId(c.Params.UserId, fmt.Sprintf("updated user auth to service=%v", user.AuthService))
   800  	w.Write([]byte(user.ToJson()))
   801  }
   802  
   803  func checkUserMfa(c *Context, w http.ResponseWriter, r *http.Request) {
   804  	props := model.MapFromJson(r.Body)
   805  
   806  	loginId := props["login_id"]
   807  	if len(loginId) == 0 {
   808  		c.SetInvalidParam("login_id")
   809  		return
   810  	}
   811  
   812  	resp := map[string]interface{}{}
   813  	resp["mfa_required"] = false
   814  
   815  	if license := c.App.License(); license == nil || !*license.Features.MFA || !*c.App.Config().ServiceSettings.EnableMultifactorAuthentication {
   816  		w.Write([]byte(model.StringInterfaceToJson(resp)))
   817  		return
   818  	}
   819  
   820  	if *c.App.Config().ServiceSettings.ExperimentalEnableHardenedMode {
   821  		resp["mfa_required"] = true
   822  	} else if user, err := c.App.GetUserForLogin("", loginId); err == nil {
   823  		resp["mfa_required"] = user.MfaActive
   824  	}
   825  
   826  	w.Write([]byte(model.StringInterfaceToJson(resp)))
   827  }
   828  
   829  func updateUserMfa(c *Context, w http.ResponseWriter, r *http.Request) {
   830  	c.RequireUserId()
   831  	if c.Err != nil {
   832  		return
   833  	}
   834  
   835  	if c.Session.IsOAuth {
   836  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   837  		c.Err.DetailedError += ", attempted access by oauth app"
   838  		return
   839  	}
   840  
   841  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
   842  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   843  		return
   844  	}
   845  
   846  	props := model.StringInterfaceFromJson(r.Body)
   847  
   848  	activate, ok := props["activate"].(bool)
   849  	if !ok {
   850  		c.SetInvalidParam("activate")
   851  		return
   852  	}
   853  
   854  	code := ""
   855  	if activate {
   856  		code, ok = props["code"].(string)
   857  		if !ok || len(code) == 0 {
   858  			c.SetInvalidParam("code")
   859  			return
   860  		}
   861  	}
   862  
   863  	c.LogAudit("attempt")
   864  
   865  	if err := c.App.UpdateMfa(activate, c.Params.UserId, code); err != nil {
   866  		c.Err = err
   867  		return
   868  	}
   869  
   870  	c.LogAudit("success - mfa updated")
   871  	ReturnStatusOK(w)
   872  }
   873  
   874  func generateMfaSecret(c *Context, w http.ResponseWriter, r *http.Request) {
   875  	c.RequireUserId()
   876  	if c.Err != nil {
   877  		return
   878  	}
   879  
   880  	if c.Session.IsOAuth {
   881  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   882  		c.Err.DetailedError += ", attempted access by oauth app"
   883  		return
   884  	}
   885  
   886  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
   887  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
   888  		return
   889  	}
   890  
   891  	secret, err := c.App.GenerateMfaSecret(c.Params.UserId)
   892  	if err != nil {
   893  		c.Err = err
   894  		return
   895  	}
   896  
   897  	w.Header().Set("Cache-Control", "no-cache")
   898  	w.Header().Set("Pragma", "no-cache")
   899  	w.Header().Set("Expires", "0")
   900  	w.Write([]byte(secret.ToJson()))
   901  }
   902  
   903  func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
   904  	c.RequireUserId()
   905  	if c.Err != nil {
   906  		return
   907  	}
   908  
   909  	props := model.MapFromJson(r.Body)
   910  
   911  	newPassword := props["new_password"]
   912  
   913  	c.LogAudit("attempted")
   914  
   915  	var err *model.AppError
   916  	if c.Params.UserId == c.Session.UserId {
   917  		currentPassword := props["current_password"]
   918  		if len(currentPassword) <= 0 {
   919  			c.SetInvalidParam("current_password")
   920  			return
   921  		}
   922  
   923  		err = c.App.UpdatePasswordAsUser(c.Params.UserId, currentPassword, newPassword)
   924  	} else if c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
   925  		err = c.App.UpdatePasswordByUserIdSendEmail(c.Params.UserId, newPassword, c.T("api.user.reset_password.method"))
   926  	} else {
   927  		err = model.NewAppError("updatePassword", "api.user.update_password.context.app_error", nil, "", http.StatusForbidden)
   928  	}
   929  
   930  	if err != nil {
   931  		c.LogAudit("failed")
   932  		c.Err = err
   933  		return
   934  	}
   935  
   936  	c.LogAudit("completed")
   937  	ReturnStatusOK(w)
   938  }
   939  
   940  func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
   941  	props := model.MapFromJson(r.Body)
   942  
   943  	token := props["token"]
   944  	if len(token) != model.TOKEN_SIZE {
   945  		c.SetInvalidParam("token")
   946  		return
   947  	}
   948  
   949  	newPassword := props["new_password"]
   950  
   951  	c.LogAudit("attempt - token=" + token)
   952  
   953  	if err := c.App.ResetPasswordFromToken(token, newPassword); err != nil {
   954  		c.LogAudit("fail - token=" + token)
   955  		c.Err = err
   956  		return
   957  	}
   958  
   959  	c.LogAudit("success - token=" + token)
   960  
   961  	ReturnStatusOK(w)
   962  }
   963  
   964  func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
   965  	props := model.MapFromJson(r.Body)
   966  
   967  	email := props["email"]
   968  	if len(email) == 0 {
   969  		c.SetInvalidParam("email")
   970  		return
   971  	}
   972  
   973  	sent, err := c.App.SendPasswordReset(email, c.App.GetSiteURL())
   974  	if err != nil {
   975  		if *c.App.Config().ServiceSettings.ExperimentalEnableHardenedMode {
   976  			ReturnStatusOK(w)
   977  		} else {
   978  			c.Err = err
   979  		}
   980  		return
   981  	}
   982  
   983  	if sent {
   984  		c.LogAudit("sent=" + email)
   985  	}
   986  
   987  	ReturnStatusOK(w)
   988  }
   989  
   990  func login(c *Context, w http.ResponseWriter, r *http.Request) {
   991  	// For hardened mode, translate all login errors to generic.
   992  	defer func() {
   993  		if *c.App.Config().ServiceSettings.ExperimentalEnableHardenedMode && c.Err != nil {
   994  			c.Err = model.NewAppError("login", "api.user.login.invalid_credentials", nil, "", http.StatusUnauthorized)
   995  		}
   996  	}()
   997  
   998  	props := model.MapFromJson(r.Body)
   999  
  1000  	id := props["id"]
  1001  	loginId := props["login_id"]
  1002  	password := props["password"]
  1003  	mfaToken := props["token"]
  1004  	deviceId := props["device_id"]
  1005  	ldapOnly := props["ldap_only"] == "true"
  1006  
  1007  	if *c.App.Config().ExperimentalSettings.ClientSideCertEnable {
  1008  		if license := c.App.License(); license == nil || !*license.Features.SAML {
  1009  			c.Err = model.NewAppError("ClientSideCertNotAllowed", "api.user.login.client_side_cert.license.app_error", nil, "", http.StatusBadRequest)
  1010  			return
  1011  		} else {
  1012  			certPem, certSubject, certEmail := c.App.CheckForClienSideCert(r)
  1013  			mlog.Debug("Client Cert", mlog.String("cert_subject", certSubject), mlog.String("cert_email", certEmail))
  1014  
  1015  			if len(certPem) == 0 || len(certEmail) == 0 {
  1016  				c.Err = model.NewAppError("ClientSideCertMissing", "api.user.login.client_side_cert.certificate.app_error", nil, "", http.StatusBadRequest)
  1017  				return
  1018  			} else if *c.App.Config().ExperimentalSettings.ClientSideCertCheck == model.CLIENT_SIDE_CERT_CHECK_PRIMARY_AUTH {
  1019  				loginId = certEmail
  1020  				password = "certificate"
  1021  			}
  1022  		}
  1023  	}
  1024  
  1025  	c.LogAuditWithUserId(id, "attempt - login_id="+loginId)
  1026  	user, err := c.App.AuthenticateUserForLogin(id, loginId, password, mfaToken, ldapOnly)
  1027  
  1028  	if err != nil {
  1029  		c.LogAuditWithUserId(id, "failure - login_id="+loginId)
  1030  		c.Err = err
  1031  		return
  1032  	}
  1033  
  1034  	c.LogAuditWithUserId(user.Id, "authenticated")
  1035  
  1036  	var session *model.Session
  1037  	session, err = c.App.DoLogin(w, r, user, deviceId)
  1038  	if err != nil {
  1039  		c.Err = err
  1040  		return
  1041  	}
  1042  
  1043  	c.LogAuditWithUserId(user.Id, "success")
  1044  
  1045  	c.Session = *session
  1046  
  1047  	user.Sanitize(map[string]bool{})
  1048  
  1049  	w.Write([]byte(user.ToJson()))
  1050  }
  1051  
  1052  func logout(c *Context, w http.ResponseWriter, r *http.Request) {
  1053  	Logout(c, w, r)
  1054  }
  1055  
  1056  func Logout(c *Context, w http.ResponseWriter, r *http.Request) {
  1057  	c.LogAudit("")
  1058  	c.RemoveSessionCookie(w, r)
  1059  	if c.Session.Id != "" {
  1060  		if err := c.App.RevokeSessionById(c.Session.Id); err != nil {
  1061  			c.Err = err
  1062  			return
  1063  		}
  1064  	}
  1065  
  1066  	ReturnStatusOK(w)
  1067  }
  1068  
  1069  func getSessions(c *Context, w http.ResponseWriter, r *http.Request) {
  1070  	c.RequireUserId()
  1071  	if c.Err != nil {
  1072  		return
  1073  	}
  1074  
  1075  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
  1076  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1077  		return
  1078  	}
  1079  
  1080  	sessions, err := c.App.GetSessions(c.Params.UserId)
  1081  	if err != nil {
  1082  		c.Err = err
  1083  		return
  1084  	}
  1085  
  1086  	for _, session := range sessions {
  1087  		session.Sanitize()
  1088  	}
  1089  
  1090  	w.Write([]byte(model.SessionsToJson(sessions)))
  1091  }
  1092  
  1093  func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
  1094  	c.RequireUserId()
  1095  	if c.Err != nil {
  1096  		return
  1097  	}
  1098  
  1099  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
  1100  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1101  		return
  1102  	}
  1103  
  1104  	props := model.MapFromJson(r.Body)
  1105  	sessionId := props["session_id"]
  1106  
  1107  	if sessionId == "" {
  1108  		c.SetInvalidParam("session_id")
  1109  		return
  1110  	}
  1111  
  1112  	var session *model.Session
  1113  	var err *model.AppError
  1114  	if session, err = c.App.GetSessionById(sessionId); err != nil {
  1115  		c.Err = err
  1116  		return
  1117  	}
  1118  
  1119  	if session.UserId != c.Params.UserId {
  1120  		c.SetInvalidUrlParam("user_id")
  1121  		return
  1122  	}
  1123  
  1124  	if err := c.App.RevokeSession(session); err != nil {
  1125  		c.Err = err
  1126  		return
  1127  	}
  1128  
  1129  	ReturnStatusOK(w)
  1130  }
  1131  
  1132  func revokeAllSessionsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
  1133  	c.RequireUserId()
  1134  	if c.Err != nil {
  1135  		return
  1136  	}
  1137  
  1138  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
  1139  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1140  		return
  1141  	}
  1142  
  1143  	if err := c.App.RevokeAllSessions(c.Params.UserId); err != nil {
  1144  		c.Err = err
  1145  		return
  1146  	}
  1147  
  1148  	ReturnStatusOK(w)
  1149  }
  1150  
  1151  func attachDeviceId(c *Context, w http.ResponseWriter, r *http.Request) {
  1152  	props := model.MapFromJson(r.Body)
  1153  
  1154  	deviceId := props["device_id"]
  1155  	if len(deviceId) == 0 {
  1156  		c.SetInvalidParam("device_id")
  1157  		return
  1158  	}
  1159  
  1160  	// A special case where we logout of all other sessions with the same device id
  1161  	if err := c.App.RevokeSessionsForDeviceId(c.Session.UserId, deviceId, c.Session.Id); err != nil {
  1162  		c.Err = err
  1163  		return
  1164  	}
  1165  
  1166  	c.App.ClearSessionCacheForUser(c.Session.UserId)
  1167  	c.Session.SetExpireInDays(*c.App.Config().ServiceSettings.SessionLengthMobileInDays)
  1168  
  1169  	maxAge := *c.App.Config().ServiceSettings.SessionLengthMobileInDays * 60 * 60 * 24
  1170  
  1171  	secure := false
  1172  	if app.GetProtocol(r) == "https" {
  1173  		secure = true
  1174  	}
  1175  
  1176  	expiresAt := time.Unix(model.GetMillis()/1000+int64(maxAge), 0)
  1177  	sessionCookie := &http.Cookie{
  1178  		Name:     model.SESSION_COOKIE_TOKEN,
  1179  		Value:    c.Session.Token,
  1180  		Path:     "/",
  1181  		MaxAge:   maxAge,
  1182  		Expires:  expiresAt,
  1183  		HttpOnly: true,
  1184  		Domain:   c.App.GetCookieDomain(),
  1185  		Secure:   secure,
  1186  	}
  1187  
  1188  	http.SetCookie(w, sessionCookie)
  1189  
  1190  	if err := c.App.AttachDeviceId(c.Session.Id, deviceId, c.Session.ExpiresAt); err != nil {
  1191  		c.Err = err
  1192  		return
  1193  	}
  1194  
  1195  	c.LogAudit("")
  1196  	ReturnStatusOK(w)
  1197  }
  1198  
  1199  func getUserAudits(c *Context, w http.ResponseWriter, r *http.Request) {
  1200  	c.RequireUserId()
  1201  	if c.Err != nil {
  1202  		return
  1203  	}
  1204  
  1205  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
  1206  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1207  		return
  1208  	}
  1209  
  1210  	audits, err := c.App.GetAuditsPage(c.Params.UserId, c.Params.Page, c.Params.PerPage)
  1211  	if err != nil {
  1212  		c.Err = err
  1213  		return
  1214  	}
  1215  
  1216  	w.Write([]byte(audits.ToJson()))
  1217  }
  1218  
  1219  func verifyUserEmail(c *Context, w http.ResponseWriter, r *http.Request) {
  1220  	props := model.MapFromJson(r.Body)
  1221  
  1222  	token := props["token"]
  1223  	if len(token) != model.TOKEN_SIZE {
  1224  		c.SetInvalidParam("token")
  1225  		return
  1226  	}
  1227  
  1228  	if err := c.App.VerifyEmailFromToken(token); err != nil {
  1229  		c.Err = model.NewAppError("verifyUserEmail", "api.user.verify_email.bad_link.app_error", nil, err.Error(), http.StatusBadRequest)
  1230  		return
  1231  	}
  1232  
  1233  	c.LogAudit("Email Verified")
  1234  	ReturnStatusOK(w)
  1235  }
  1236  
  1237  func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) {
  1238  	props := model.MapFromJson(r.Body)
  1239  
  1240  	email := props["email"]
  1241  	if len(email) == 0 {
  1242  		c.SetInvalidParam("email")
  1243  		return
  1244  	}
  1245  
  1246  	user, err := c.App.GetUserForLogin("", email)
  1247  	if err != nil {
  1248  		// Don't want to leak whether the email is valid or not
  1249  		ReturnStatusOK(w)
  1250  		return
  1251  	}
  1252  
  1253  	err = c.App.SendEmailVerification(user)
  1254  	if err != nil {
  1255  		// Don't want to leak whether the email is valid or not
  1256  		mlog.Error(err.Error())
  1257  		ReturnStatusOK(w)
  1258  		return
  1259  	}
  1260  
  1261  	ReturnStatusOK(w)
  1262  }
  1263  
  1264  func switchAccountType(c *Context, w http.ResponseWriter, r *http.Request) {
  1265  	switchRequest := model.SwitchRequestFromJson(r.Body)
  1266  	if switchRequest == nil {
  1267  		c.SetInvalidParam("switch_request")
  1268  		return
  1269  	}
  1270  
  1271  	link := ""
  1272  	var err *model.AppError
  1273  
  1274  	if switchRequest.EmailToOAuth() {
  1275  		link, err = c.App.SwitchEmailToOAuth(w, r, switchRequest.Email, switchRequest.Password, switchRequest.MfaCode, switchRequest.NewService)
  1276  	} else if switchRequest.OAuthToEmail() {
  1277  		c.SessionRequired()
  1278  		if c.Err != nil {
  1279  			return
  1280  		}
  1281  
  1282  		link, err = c.App.SwitchOAuthToEmail(switchRequest.Email, switchRequest.NewPassword, c.Session.UserId)
  1283  	} else if switchRequest.EmailToLdap() {
  1284  		link, err = c.App.SwitchEmailToLdap(switchRequest.Email, switchRequest.Password, switchRequest.MfaCode, switchRequest.LdapLoginId, switchRequest.NewPassword)
  1285  	} else if switchRequest.LdapToEmail() {
  1286  		link, err = c.App.SwitchLdapToEmail(switchRequest.Password, switchRequest.MfaCode, switchRequest.Email, switchRequest.NewPassword)
  1287  	} else {
  1288  		c.SetInvalidParam("switch_request")
  1289  		return
  1290  	}
  1291  
  1292  	if err != nil {
  1293  		c.Err = err
  1294  		return
  1295  	}
  1296  
  1297  	c.LogAudit("success")
  1298  	w.Write([]byte(model.MapToJson(map[string]string{"follow_link": link})))
  1299  }
  1300  
  1301  func createUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
  1302  	c.RequireUserId()
  1303  	if c.Err != nil {
  1304  		return
  1305  	}
  1306  
  1307  	if c.Session.IsOAuth {
  1308  		c.SetPermissionError(model.PERMISSION_CREATE_USER_ACCESS_TOKEN)
  1309  		c.Err.DetailedError += ", attempted access by oauth app"
  1310  		return
  1311  	}
  1312  
  1313  	accessToken := model.UserAccessTokenFromJson(r.Body)
  1314  	if accessToken == nil {
  1315  		c.SetInvalidParam("user_access_token")
  1316  		return
  1317  	}
  1318  
  1319  	if accessToken.Description == "" {
  1320  		c.SetInvalidParam("description")
  1321  		return
  1322  	}
  1323  
  1324  	c.LogAudit("")
  1325  
  1326  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_CREATE_USER_ACCESS_TOKEN) {
  1327  		c.SetPermissionError(model.PERMISSION_CREATE_USER_ACCESS_TOKEN)
  1328  		return
  1329  	}
  1330  
  1331  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
  1332  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1333  		return
  1334  	}
  1335  
  1336  	accessToken.UserId = c.Params.UserId
  1337  	accessToken.Token = ""
  1338  
  1339  	var err *model.AppError
  1340  	accessToken, err = c.App.CreateUserAccessToken(accessToken)
  1341  	if err != nil {
  1342  		c.Err = err
  1343  		return
  1344  	}
  1345  
  1346  	c.LogAudit("success - token_id=" + accessToken.Id)
  1347  	w.Write([]byte(accessToken.ToJson()))
  1348  }
  1349  
  1350  func searchUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) {
  1351  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
  1352  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
  1353  		return
  1354  	}
  1355  	props := model.UserAccessTokenSearchFromJson(r.Body)
  1356  	if props == nil {
  1357  		c.SetInvalidParam("user_access_token_search")
  1358  		return
  1359  	}
  1360  
  1361  	if len(props.Term) == 0 {
  1362  		c.SetInvalidParam("term")
  1363  		return
  1364  	}
  1365  	accessTokens, err := c.App.SearchUserAccessTokens(props.Term)
  1366  	if err != nil {
  1367  		c.Err = err
  1368  		return
  1369  	}
  1370  
  1371  	w.Write([]byte(model.UserAccessTokenListToJson(accessTokens)))
  1372  }
  1373  
  1374  func getUserAccessTokens(c *Context, w http.ResponseWriter, r *http.Request) {
  1375  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
  1376  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
  1377  		return
  1378  	}
  1379  
  1380  	accessTokens, err := c.App.GetUserAccessTokens(c.Params.Page, c.Params.PerPage)
  1381  	if err != nil {
  1382  		c.Err = err
  1383  		return
  1384  	}
  1385  
  1386  	w.Write([]byte(model.UserAccessTokenListToJson(accessTokens)))
  1387  }
  1388  
  1389  func getUserAccessTokensForUser(c *Context, w http.ResponseWriter, r *http.Request) {
  1390  	c.RequireUserId()
  1391  	if c.Err != nil {
  1392  		return
  1393  	}
  1394  
  1395  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_READ_USER_ACCESS_TOKEN) {
  1396  		c.SetPermissionError(model.PERMISSION_READ_USER_ACCESS_TOKEN)
  1397  		return
  1398  	}
  1399  
  1400  	if !c.App.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
  1401  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1402  		return
  1403  	}
  1404  
  1405  	accessTokens, err := c.App.GetUserAccessTokensForUser(c.Params.UserId, c.Params.Page, c.Params.PerPage)
  1406  	if err != nil {
  1407  		c.Err = err
  1408  		return
  1409  	}
  1410  
  1411  	w.Write([]byte(model.UserAccessTokenListToJson(accessTokens)))
  1412  }
  1413  
  1414  func getUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
  1415  	c.RequireTokenId()
  1416  	if c.Err != nil {
  1417  		return
  1418  	}
  1419  
  1420  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_READ_USER_ACCESS_TOKEN) {
  1421  		c.SetPermissionError(model.PERMISSION_READ_USER_ACCESS_TOKEN)
  1422  		return
  1423  	}
  1424  
  1425  	accessToken, err := c.App.GetUserAccessToken(c.Params.TokenId, true)
  1426  	if err != nil {
  1427  		c.Err = err
  1428  		return
  1429  	}
  1430  
  1431  	if !c.App.SessionHasPermissionToUser(c.Session, accessToken.UserId) {
  1432  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1433  		return
  1434  	}
  1435  
  1436  	w.Write([]byte(accessToken.ToJson()))
  1437  }
  1438  
  1439  func revokeUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
  1440  	props := model.MapFromJson(r.Body)
  1441  	tokenId := props["token_id"]
  1442  
  1443  	if tokenId == "" {
  1444  		c.SetInvalidParam("token_id")
  1445  	}
  1446  
  1447  	c.LogAudit("")
  1448  
  1449  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_REVOKE_USER_ACCESS_TOKEN) {
  1450  		c.SetPermissionError(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN)
  1451  		return
  1452  	}
  1453  
  1454  	accessToken, err := c.App.GetUserAccessToken(tokenId, false)
  1455  	if err != nil {
  1456  		c.Err = err
  1457  		return
  1458  	}
  1459  
  1460  	if !c.App.SessionHasPermissionToUser(c.Session, accessToken.UserId) {
  1461  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1462  		return
  1463  	}
  1464  
  1465  	err = c.App.RevokeUserAccessToken(accessToken)
  1466  	if err != nil {
  1467  		c.Err = err
  1468  		return
  1469  	}
  1470  
  1471  	c.LogAudit("success - token_id=" + accessToken.Id)
  1472  	ReturnStatusOK(w)
  1473  }
  1474  
  1475  func disableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
  1476  	props := model.MapFromJson(r.Body)
  1477  	tokenId := props["token_id"]
  1478  
  1479  	if tokenId == "" {
  1480  		c.SetInvalidParam("token_id")
  1481  	}
  1482  
  1483  	c.LogAudit("")
  1484  
  1485  	// No separate permission for this action for now
  1486  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_REVOKE_USER_ACCESS_TOKEN) {
  1487  		c.SetPermissionError(model.PERMISSION_REVOKE_USER_ACCESS_TOKEN)
  1488  		return
  1489  	}
  1490  
  1491  	accessToken, err := c.App.GetUserAccessToken(tokenId, false)
  1492  	if err != nil {
  1493  		c.Err = err
  1494  		return
  1495  	}
  1496  
  1497  	if !c.App.SessionHasPermissionToUser(c.Session, accessToken.UserId) {
  1498  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1499  		return
  1500  	}
  1501  
  1502  	err = c.App.DisableUserAccessToken(accessToken)
  1503  	if err != nil {
  1504  		c.Err = err
  1505  		return
  1506  	}
  1507  
  1508  	c.LogAudit("success - token_id=" + accessToken.Id)
  1509  	ReturnStatusOK(w)
  1510  }
  1511  
  1512  func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
  1513  	props := model.MapFromJson(r.Body)
  1514  	tokenId := props["token_id"]
  1515  
  1516  	if tokenId == "" {
  1517  		c.SetInvalidParam("token_id")
  1518  	}
  1519  
  1520  	c.LogAudit("")
  1521  
  1522  	// No separate permission for this action for now
  1523  	if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_CREATE_USER_ACCESS_TOKEN) {
  1524  		c.SetPermissionError(model.PERMISSION_CREATE_USER_ACCESS_TOKEN)
  1525  		return
  1526  	}
  1527  
  1528  	accessToken, err := c.App.GetUserAccessToken(tokenId, false)
  1529  	if err != nil {
  1530  		c.Err = err
  1531  		return
  1532  	}
  1533  
  1534  	if !c.App.SessionHasPermissionToUser(c.Session, accessToken.UserId) {
  1535  		c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
  1536  		return
  1537  	}
  1538  
  1539  	err = c.App.EnableUserAccessToken(accessToken)
  1540  	if err != nil {
  1541  		c.Err = err
  1542  		return
  1543  	}
  1544  
  1545  	c.LogAudit("success - token_id=" + accessToken.Id)
  1546  	ReturnStatusOK(w)
  1547  }
  1548  
  1549  func registerServiceTermsAction(c *Context, w http.ResponseWriter, r *http.Request) {
  1550  	props := model.StringInterfaceFromJson(r.Body)
  1551  
  1552  	userId := c.Session.UserId
  1553  	serviceTermsId := props["serviceTermsId"].(string)
  1554  	accepted := props["accepted"].(bool)
  1555  
  1556  	if _, err := c.App.GetServiceTerms(serviceTermsId); err != nil {
  1557  		c.Err = err
  1558  		return
  1559  	}
  1560  
  1561  	if err := c.App.RecordUserServiceTermsAction(userId, serviceTermsId, accepted); err != nil {
  1562  		c.Err = err
  1563  		return
  1564  	}
  1565  
  1566  	c.LogAudit("ServiceTermsId=" + serviceTermsId + ", accepted=" + strconv.FormatBool(accepted))
  1567  	ReturnStatusOK(w)
  1568  }