diff options
Diffstat (limited to 'model')
-rw-r--r-- | model/client.go | 308 | ||||
-rw-r--r-- | model/command.go | 2 | ||||
-rw-r--r-- | model/command_test.go | 81 | ||||
-rw-r--r-- | model/config.go | 18 | ||||
-rw-r--r-- | model/gitlab.go | 8 | ||||
-rw-r--r-- | model/gitlab/gitlab.go | 10 | ||||
-rw-r--r-- | model/initial_load.go | 40 | ||||
-rw-r--r-- | model/initial_load_test.go | 20 | ||||
-rw-r--r-- | model/password_recovery.go | 37 | ||||
-rw-r--r-- | model/session.go | 32 | ||||
-rw-r--r-- | model/team.go | 25 | ||||
-rw-r--r-- | model/team_member.go | 78 | ||||
-rw-r--r-- | model/team_member_test.go | 43 | ||||
-rw-r--r-- | model/user.go | 20 | ||||
-rw-r--r-- | model/user_test.go | 9 | ||||
-rw-r--r-- | model/utils.go | 11 | ||||
-rw-r--r-- | model/version.go | 1 |
17 files changed, 596 insertions, 147 deletions
diff --git a/model/client.go b/model/client.go index 89b4d134f..4edb859e2 100644 --- a/model/client.go +++ b/model/client.go @@ -28,7 +28,10 @@ const ( HEADER_AUTH = "Authorization" HEADER_REQUESTED_WITH = "X-Requested-With" HEADER_REQUESTED_WITH_XML = "XMLHttpRequest" - API_URL_SUFFIX = "/api/v1" + + API_URL_SUFFIX_V1 = "/api/v1" + API_URL_SUFFIX_V3 = "/api/v3" + API_URL_SUFFIX = API_URL_SUFFIX_V3 ) type Result struct { @@ -39,16 +42,52 @@ type Result struct { type Client struct { Url string // The location of the server like "http://localhost:8065" - ApiUrl string // The api location of the server like "http://localhost:8065/api/v1" + ApiUrl string // The api location of the server like "http://localhost:8065/api/v3" HttpClient *http.Client // The http client AuthToken string AuthType string + TeamId string } // NewClient constructs a new client with convienence methods for talking to // the server. func NewClient(url string) *Client { - return &Client{url, url + API_URL_SUFFIX, &http.Client{}, "", ""} + return &Client{url, url + API_URL_SUFFIX, &http.Client{}, "", "", ""} +} + +func (c *Client) SetOAuthToken(token string) { + c.AuthToken = token + c.AuthType = HEADER_TOKEN +} + +func (c *Client) ClearOAuthToken() { + c.AuthToken = "" + c.AuthType = HEADER_BEARER +} + +func (c *Client) SetTeamId(teamId string) { + c.TeamId = teamId +} + +func (c *Client) GetTeamId() string { + if len(c.TeamId) == 0 { + println(`You are trying to use a route that requires a team_id, + but you have not called SetTeamId() in client.go`) + } + + return c.TeamId +} + +func (c *Client) ClearTeamId() { + c.TeamId = "" +} + +func (c *Client) GetTeamRoute() string { + return fmt.Sprintf("/teams/%v", c.GetTeamId()) +} + +func (c *Client) GetChannelRoute(channelId string) string { + return fmt.Sprintf("/teams/%v/channels/%v", c.GetTeamId(), channelId) } func (c *Client) DoPost(url, data, contentType string) (*http.Response, *AppError) { @@ -162,10 +201,19 @@ func (c *Client) GetAllTeams() (*Result, *AppError) { } } -func (c *Client) FindTeamByName(name string, allServers bool) (*Result, *AppError) { +func (c *Client) GetAllTeamListings() (*Result, *AppError) { + if r, err := c.DoApiGet("/teams/all_team_listings", "", ""); err != nil { + return nil, err + } else { + + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), TeamMapFromJson(r.Body)}, nil + } +} + +func (c *Client) FindTeamByName(name string) (*Result, *AppError) { m := make(map[string]string) m["name"] = name - m["all"] = fmt.Sprintf("%v", allServers) if r, err := c.DoApiPost("/teams/find_team_by_name", MapToJson(m)); err != nil { return nil, err } else { @@ -179,8 +227,32 @@ func (c *Client) FindTeamByName(name string, allServers bool) (*Result, *AppErro } } +func (c *Client) AddUserToTeam(userId string) (*Result, *AppError) { + data := make(map[string]string) + data["user_id"] = userId + if r, err := c.DoApiPost(c.GetTeamRoute()+"/add_user_to_team", MapToJson(data)); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + } +} + +func (c *Client) AddUserToTeamFromInvite(hash, dataToHash, inviteId string) (*Result, *AppError) { + data := make(map[string]string) + data["hash"] = hash + data["data"] = dataToHash + data["invite_id"] = inviteId + if r, err := c.DoApiPost("/teams/add_user_to_team_from_invite", MapToJson(data)); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil + } +} + func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) { - if r, err := c.DoApiPost("/teams/invite_members", invites.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/invite_members", invites.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -189,7 +261,7 @@ func (c *Client) InviteMembers(invites *Invites) (*Result, *AppError) { } func (c *Client) UpdateTeam(team *Team) (*Result, *AppError) { - if r, err := c.DoApiPost("/teams/update", team.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/update", team.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -206,6 +278,18 @@ func (c *Client) CreateUser(user *User, hash string) (*Result, *AppError) { } } +func (c *Client) CreateUserWithInvite(user *User, hash string, data string, inviteId string) (*Result, *AppError) { + + url := "/users/create?d=" + url.QueryEscape(data) + "&h=" + url.QueryEscape(hash) + "&iid=" + url.QueryEscape(inviteId) + + if r, err := c.DoApiPost(url, user.ToJson()); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), UserFromJson(r.Body)}, nil + } +} + func (c *Client) CreateUserFromSignup(user *User, data string, hash string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/create?d="+url.QueryEscape(data)+"&h="+hash, user.ToJson()); err != nil { return nil, err @@ -216,7 +300,7 @@ func (c *Client) CreateUserFromSignup(user *User, data string, hash string) (*Re } func (c *Client) GetUser(id string, etag string) (*Result, *AppError) { - if r, err := c.DoApiGet("/users/"+id, "", etag); err != nil { + if r, err := c.DoApiGet("/users/"+id+"/get", "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -242,6 +326,24 @@ func (c *Client) GetProfiles(teamId string, etag string) (*Result, *AppError) { } } +func (c *Client) GetProfilesForTeam(teamId string, etag string) (*Result, *AppError) { + if r, err := c.DoApiGet("/users/profiles/"+teamId+"?skip_direct=true", "", etag); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil + } +} + +func (c *Client) GetDirectProfiles(etag string) (*Result, *AppError) { + if r, err := c.DoApiGet("/users/direct_profiles", "", etag); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), UserMapFromJson(r.Body)}, nil + } +} + func (c *Client) LoginById(id string, password string) (*Result, *AppError) { m := make(map[string]string) m["id"] = id @@ -274,6 +376,26 @@ func (c *Client) LoginByEmailWithDevice(name string, email string, password stri return c.login(m) } +func (c *Client) LoginByLdap(userid string, password string, mfatoken string) (*Result, *AppError) { + m := make(map[string]string) + m["id"] = userid + m["password"] = password + m["token"] = mfatoken + if r, err := c.DoApiPost("/users/login_ldap", MapToJson(m)); err != nil { + return nil, err + } else { + c.AuthToken = r.Header.Get(HEADER_TOKEN) + c.AuthType = HEADER_BEARER + sessionToken := getCookie(SESSION_COOKIE_TOKEN, r) + + if c.AuthToken != sessionToken.Value { + NewLocAppError("/users/login_ldap", "model.client.login.app_error", nil, "") + } + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + } +} + func (c *Client) login(m map[string]string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/login", MapToJson(m)); err != nil { return nil, err @@ -297,16 +419,16 @@ func (c *Client) Logout() (*Result, *AppError) { } else { c.AuthToken = "" c.AuthType = HEADER_BEARER + c.TeamId = "" return &Result{r.Header.Get(HEADER_REQUEST_ID), r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil } } -func (c *Client) CheckMfa(method, teamName, loginId string) (*Result, *AppError) { +func (c *Client) CheckMfa(method, loginId string) (*Result, *AppError) { m := make(map[string]string) m["method"] = method - m["team_name"] = teamName m["login_id"] = loginId if r, err := c.DoApiPost("/users/mfa", MapToJson(m)); err != nil { @@ -339,14 +461,16 @@ func (c *Client) UpdateMfa(activate bool, token string) (*Result, *AppError) { } } -func (c *Client) SetOAuthToken(token string) { - c.AuthToken = token - c.AuthType = HEADER_TOKEN -} +func (c *Client) AdminResetMfa(userId string) (*Result, *AppError) { + m := make(map[string]string) + m["user_id"] = userId -func (c *Client) ClearOAuthToken() { - c.AuthToken = "" - c.AuthType = HEADER_BEARER + if r, err := c.DoApiPost("/admin/reset_mfa", MapToJson(m)); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + } } func (c *Client) RevokeSession(sessionAltId string) (*Result, *AppError) { @@ -411,7 +535,7 @@ func (c *Client) Command(channelId string, command string, suggest bool) (*Resul m["command"] = command m["channelId"] = channelId m["suggest"] = strconv.FormatBool(suggest) - if r, err := c.DoApiPost("/commands/execute", MapToJson(m)); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/execute", MapToJson(m)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -420,7 +544,7 @@ func (c *Client) Command(channelId string, command string, suggest bool) (*Resul } func (c *Client) ListCommands() (*Result, *AppError) { - if r, err := c.DoApiGet("/commands/list", "", ""); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/commands/list", "", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -429,7 +553,7 @@ func (c *Client) ListCommands() (*Result, *AppError) { } func (c *Client) ListTeamCommands() (*Result, *AppError) { - if r, err := c.DoApiGet("/commands/list_team_commands", "", ""); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/commands/list_team_commands", "", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -438,7 +562,7 @@ func (c *Client) ListTeamCommands() (*Result, *AppError) { } func (c *Client) CreateCommand(cmd *Command) (*Result, *AppError) { - if r, err := c.DoApiPost("/commands/create", cmd.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/create", cmd.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -447,7 +571,7 @@ func (c *Client) CreateCommand(cmd *Command) (*Result, *AppError) { } func (c *Client) RegenCommandToken(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/commands/regen_token", MapToJson(data)); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/regen_token", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -456,7 +580,7 @@ func (c *Client) RegenCommandToken(data map[string]string) (*Result, *AppError) } func (c *Client) DeleteCommand(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/commands/delete", MapToJson(data)); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/commands/delete", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -582,7 +706,7 @@ func (c *Client) GetSystemAnalytics(name string) (*Result, *AppError) { } func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/create", channel.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create", channel.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -590,8 +714,10 @@ func (c *Client) CreateChannel(channel *Channel) (*Result, *AppError) { } } -func (c *Client) CreateDirectChannel(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/create_direct", MapToJson(data)); err != nil { +func (c *Client) CreateDirectChannel(userId string) (*Result, *AppError) { + data := make(map[string]string) + data["user_id"] = userId + if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/create_direct", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -600,7 +726,7 @@ func (c *Client) CreateDirectChannel(data map[string]string) (*Result, *AppError } func (c *Client) UpdateChannel(channel *Channel) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/update", channel.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update", channel.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -609,7 +735,7 @@ func (c *Client) UpdateChannel(channel *Channel) (*Result, *AppError) { } func (c *Client) UpdateChannelHeader(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/update_header", MapToJson(data)); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_header", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -618,7 +744,7 @@ func (c *Client) UpdateChannelHeader(data map[string]string) (*Result, *AppError } func (c *Client) UpdateChannelPurpose(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/update_purpose", MapToJson(data)); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_purpose", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -627,7 +753,7 @@ func (c *Client) UpdateChannelPurpose(data map[string]string) (*Result, *AppErro } func (c *Client) UpdateNotifyProps(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/update_notify_props", MapToJson(data)); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/channels/update_notify_props", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -636,7 +762,7 @@ func (c *Client) UpdateNotifyProps(data map[string]string) (*Result, *AppError) } func (c *Client) GetChannels(etag string) (*Result, *AppError) { - if r, err := c.DoApiGet("/channels/", "", etag); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/", "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -645,7 +771,7 @@ func (c *Client) GetChannels(etag string) (*Result, *AppError) { } func (c *Client) GetChannel(id, etag string) (*Result, *AppError) { - if r, err := c.DoApiGet("/channels/"+id+"/", "", etag); err != nil { + if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/", "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -654,7 +780,7 @@ func (c *Client) GetChannel(id, etag string) (*Result, *AppError) { } func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) { - if r, err := c.DoApiGet("/channels/more", "", etag); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/more", "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -663,7 +789,7 @@ func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) { } func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) { - if r, err := c.DoApiGet("/channels/counts", "", etag); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/channels/counts", "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -672,7 +798,7 @@ func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) { } func (c *Client) JoinChannel(id string) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/"+id+"/join", ""); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/join", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -681,7 +807,7 @@ func (c *Client) JoinChannel(id string) (*Result, *AppError) { } func (c *Client) LeaveChannel(id string) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/"+id+"/leave", ""); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/leave", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -690,7 +816,7 @@ func (c *Client) LeaveChannel(id string) (*Result, *AppError) { } func (c *Client) DeleteChannel(id string) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/"+id+"/delete", ""); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/delete", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -701,7 +827,7 @@ func (c *Client) DeleteChannel(id string) (*Result, *AppError) { func (c *Client) AddChannelMember(id, user_id string) (*Result, *AppError) { data := make(map[string]string) data["user_id"] = user_id - if r, err := c.DoApiPost("/channels/"+id+"/add", MapToJson(data)); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/add", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -712,7 +838,7 @@ func (c *Client) AddChannelMember(id, user_id string) (*Result, *AppError) { func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) { data := make(map[string]string) data["user_id"] = user_id - if r, err := c.DoApiPost("/channels/"+id+"/remove", MapToJson(data)); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(id)+"/remove", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -721,7 +847,7 @@ func (c *Client) RemoveChannelMember(id, user_id string) (*Result, *AppError) { } func (c *Client) UpdateLastViewedAt(channelId string) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/"+channelId+"/update_last_viewed_at", ""); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+"/update_last_viewed_at", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -730,7 +856,7 @@ func (c *Client) UpdateLastViewedAt(channelId string) (*Result, *AppError) { } func (c *Client) GetChannelExtraInfo(id string, memberLimit int, etag string) (*Result, *AppError) { - if r, err := c.DoApiGet("/channels/"+id+"/extra_info/"+strconv.FormatInt(int64(memberLimit), 10), "", etag); err != nil { + if r, err := c.DoApiGet(c.GetChannelRoute(id)+"/extra_info/"+strconv.FormatInt(int64(memberLimit), 10), "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -739,7 +865,7 @@ func (c *Client) GetChannelExtraInfo(id string, memberLimit int, etag string) (* } func (c *Client) CreatePost(post *Post) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/"+post.ChannelId+"/create", post.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/create", post.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -748,7 +874,7 @@ func (c *Client) CreatePost(post *Post) (*Result, *AppError) { } func (c *Client) UpdatePost(post *Post) (*Result, *AppError) { - if r, err := c.DoApiPost("/channels/"+post.ChannelId+"/update", post.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(post.ChannelId)+"/posts/update", post.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -757,7 +883,7 @@ func (c *Client) UpdatePost(post *Post) (*Result, *AppError) { } func (c *Client) GetPosts(channelId string, offset int, limit int, etag string) (*Result, *AppError) { - if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/posts/%v/%v", channelId, offset, limit), "", etag); err != nil { + if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/page/%v/%v", offset, limit), "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -766,7 +892,7 @@ func (c *Client) GetPosts(channelId string, offset int, limit int, etag string) } func (c *Client) GetPostsSince(channelId string, time int64) (*Result, *AppError) { - if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/posts/%v", channelId, time), "", ""); err != nil { + if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/since/%v", time), "", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -775,7 +901,7 @@ func (c *Client) GetPostsSince(channelId string, time int64) (*Result, *AppError } func (c *Client) GetPostsBefore(channelId string, postid string, offset int, limit int, etag string) (*Result, *AppError) { - if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/post/%v/before/%v/%v", channelId, postid, offset, limit), "", etag); err != nil { + if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/before/%v/%v", postid, offset, limit), "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -784,7 +910,7 @@ func (c *Client) GetPostsBefore(channelId string, postid string, offset int, lim } func (c *Client) GetPostsAfter(channelId string, postid string, offset int, limit int, etag string) (*Result, *AppError) { - if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/post/%v/after/%v/%v", channelId, postid, offset, limit), "", etag); err != nil { + if r, err := c.DoApiGet(fmt.Sprintf(c.GetChannelRoute(channelId)+"/posts/%v/after/%v/%v", postid, offset, limit), "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -793,7 +919,7 @@ func (c *Client) GetPostsAfter(channelId string, postid string, offset int, limi } func (c *Client) GetPost(channelId string, postId string, etag string) (*Result, *AppError) { - if r, err := c.DoApiGet(fmt.Sprintf("/channels/%v/post/%v", channelId, postId), "", etag); err != nil { + if r, err := c.DoApiGet(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/get", postId), "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -802,7 +928,7 @@ func (c *Client) GetPost(channelId string, postId string, etag string) (*Result, } func (c *Client) DeletePost(channelId string, postId string) (*Result, *AppError) { - if r, err := c.DoApiPost(fmt.Sprintf("/channels/%v/post/%v/delete", channelId, postId), ""); err != nil { + if r, err := c.DoApiPost(c.GetChannelRoute(channelId)+fmt.Sprintf("/posts/%v/delete", postId), ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -811,7 +937,7 @@ func (c *Client) DeletePost(channelId string, postId string) (*Result, *AppError } func (c *Client) SearchPosts(terms string) (*Result, *AppError) { - if r, err := c.DoApiGet("/posts/search?terms="+url.QueryEscape(terms), "", ""); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/posts/search?terms="+url.QueryEscape(terms), "", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -819,8 +945,16 @@ func (c *Client) SearchPosts(terms string) (*Result, *AppError) { } } -func (c *Client) UploadFile(url string, data []byte, contentType string) (*Result, *AppError) { - rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data)) +func (c *Client) UploadProfileFile(data []byte, contentType string) (*Result, *AppError) { + return c.uploadFile(c.ApiUrl+"/users/newimage", data, contentType) +} + +func (c *Client) UploadPostAttachment(data []byte, contentType string) (*Result, *AppError) { + return c.uploadFile(c.ApiUrl+c.GetTeamRoute()+"/files/upload", data, contentType) +} + +func (c *Client) uploadFile(url string, data []byte, contentType string) (*Result, *AppError) { + rq, _ := http.NewRequest("POST", url, bytes.NewReader(data)) rq.Header.Set("Content-Type", contentType) if len(c.AuthToken) > 0 { @@ -842,7 +976,7 @@ func (c *Client) GetFile(url string, isFullUrl bool) (*Result, *AppError) { if isFullUrl { rq, _ = http.NewRequest("GET", url, nil) } else { - rq, _ = http.NewRequest("GET", c.ApiUrl+"/files/get"+url, nil) + rq, _ = http.NewRequest("GET", c.ApiUrl+c.GetTeamRoute()+"/files/get"+url, nil) } if len(c.AuthToken) > 0 { @@ -861,7 +995,7 @@ func (c *Client) GetFile(url string, isFullUrl bool) (*Result, *AppError) { func (c *Client) GetFileInfo(url string) (*Result, *AppError) { var rq *http.Request - rq, _ = http.NewRequest("GET", c.ApiUrl+"/files/get_info"+url, nil) + rq, _ = http.NewRequest("GET", c.ApiUrl+c.GetTeamRoute()+"/files/get_info"+url, nil) if len(c.AuthToken) > 0 { rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken) @@ -878,7 +1012,7 @@ func (c *Client) GetFileInfo(url string) (*Result, *AppError) { } func (c *Client) GetPublicLink(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/files/get_public_link", MapToJson(data)); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/files/get_public_link", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -950,7 +1084,9 @@ func (c *Client) UpdateUserPassword(userId, currentPassword, newPassword string) } } -func (c *Client) SendPasswordReset(data map[string]string) (*Result, *AppError) { +func (c *Client) SendPasswordReset(email string) (*Result, *AppError) { + data := map[string]string{} + data["email"] = email if r, err := c.DoApiPost("/users/send_password_reset", MapToJson(data)); err != nil { return nil, err } else { @@ -959,7 +1095,10 @@ func (c *Client) SendPasswordReset(data map[string]string) (*Result, *AppError) } } -func (c *Client) ResetPassword(data map[string]string) (*Result, *AppError) { +func (c *Client) ResetPassword(code, newPassword string) (*Result, *AppError) { + data := map[string]string{} + data["code"] = code + data["new_password"] = newPassword if r, err := c.DoApiPost("/users/reset_password", MapToJson(data)); err != nil { return nil, err } else { @@ -968,6 +1107,18 @@ func (c *Client) ResetPassword(data map[string]string) (*Result, *AppError) { } } +func (c *Client) AdminResetPassword(userId, newPassword string) (*Result, *AppError) { + data := map[string]string{} + data["user_id"] = userId + data["new_password"] = newPassword + if r, err := c.DoApiPost("/admin/reset_password", MapToJson(data)); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + } +} + func (c *Client) GetStatuses(data []string) (*Result, *AppError) { if r, err := c.DoApiPost("/users/status", ArrayToJson(data)); err != nil { return nil, err @@ -978,7 +1129,7 @@ func (c *Client) GetStatuses(data []string) (*Result, *AppError) { } func (c *Client) GetMyTeam(etag string) (*Result, *AppError) { - if r, err := c.DoApiGet("/teams/me", "", etag); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/me", "", etag); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -986,6 +1137,15 @@ func (c *Client) GetMyTeam(etag string) (*Result, *AppError) { } } +func (c *Client) GetTeamMembers(teamId string) (*Result, *AppError) { + if r, err := c.DoApiGet("/teams/members/"+teamId, "", ""); err != nil { + return nil, err + } else { + return &Result{r.Header.Get(HEADER_REQUEST_ID), + r.Header.Get(HEADER_ETAG_SERVER), TeamMembersFromJson(r.Body)}, nil + } +} + func (c *Client) RegisterApp(app *OAuthApp) (*Result, *AppError) { if r, err := c.DoApiPost("/oauth/register", app.ToJson()); err != nil { return nil, err @@ -1014,7 +1174,7 @@ func (c *Client) GetAccessToken(data url.Values) (*Result, *AppError) { } func (c *Client) CreateIncomingWebhook(hook *IncomingWebhook) (*Result, *AppError) { - if r, err := c.DoApiPost("/hooks/incoming/create", hook.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/create", hook.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -1031,8 +1191,10 @@ func (c *Client) PostToWebhook(id, payload string) (*Result, *AppError) { } } -func (c *Client) DeleteIncomingWebhook(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/hooks/incoming/delete", MapToJson(data)); err != nil { +func (c *Client) DeleteIncomingWebhook(id string) (*Result, *AppError) { + data := make(map[string]string) + data["id"] = id + if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/incoming/delete", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -1041,7 +1203,7 @@ func (c *Client) DeleteIncomingWebhook(data map[string]string) (*Result, *AppErr } func (c *Client) ListIncomingWebhooks() (*Result, *AppError) { - if r, err := c.DoApiGet("/hooks/incoming/list", "", ""); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/hooks/incoming/list", "", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -1085,7 +1247,7 @@ func (c *Client) GetPreferenceCategory(category string) (*Result, *AppError) { } func (c *Client) CreateOutgoingWebhook(hook *OutgoingWebhook) (*Result, *AppError) { - if r, err := c.DoApiPost("/hooks/outgoing/create", hook.ToJson()); err != nil { + if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/create", hook.ToJson()); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -1093,8 +1255,10 @@ func (c *Client) CreateOutgoingWebhook(hook *OutgoingWebhook) (*Result, *AppErro } } -func (c *Client) DeleteOutgoingWebhook(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/hooks/outgoing/delete", MapToJson(data)); err != nil { +func (c *Client) DeleteOutgoingWebhook(id string) (*Result, *AppError) { + data := make(map[string]string) + data["id"] = id + if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/delete", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -1103,7 +1267,7 @@ func (c *Client) DeleteOutgoingWebhook(data map[string]string) (*Result, *AppErr } func (c *Client) ListOutgoingWebhooks() (*Result, *AppError) { - if r, err := c.DoApiGet("/hooks/outgoing/list", "", ""); err != nil { + if r, err := c.DoApiGet(c.GetTeamRoute()+"/hooks/outgoing/list", "", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -1111,8 +1275,10 @@ func (c *Client) ListOutgoingWebhooks() (*Result, *AppError) { } } -func (c *Client) RegenOutgoingWebhookToken(data map[string]string) (*Result, *AppError) { - if r, err := c.DoApiPost("/hooks/outgoing/regen_token", MapToJson(data)); err != nil { +func (c *Client) RegenOutgoingWebhookToken(id string) (*Result, *AppError) { + data := make(map[string]string) + data["id"] = id + if r, err := c.DoApiPost(c.GetTeamRoute()+"/hooks/outgoing/regen_token", MapToJson(data)); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), @@ -1134,11 +1300,11 @@ func (c *Client) GetClientLicenceConfig(etag string) (*Result, *AppError) { } } -func (c *Client) GetMeLoggedIn() (*Result, *AppError) { - if r, err := c.DoApiGet("/users/me_logged_in", "", ""); err != nil { +func (c *Client) GetInitialLoad() (*Result, *AppError) { + if r, err := c.DoApiGet("/users/initial_load", "", ""); err != nil { return nil, err } else { return &Result{r.Header.Get(HEADER_REQUEST_ID), - r.Header.Get(HEADER_ETAG_SERVER), MapFromJson(r.Body)}, nil + r.Header.Get(HEADER_ETAG_SERVER), InitialLoadFromJson(r.Body)}, nil } } diff --git a/model/command.go b/model/command.go index b854ae76a..4d5f7ace9 100644 --- a/model/command.go +++ b/model/command.go @@ -99,7 +99,7 @@ func (o *Command) IsValid() *AppError { return NewLocAppError("Command.IsValid", "model.command.is_valid.team_id.app_error", nil, "") } - if len(o.Trigger) > 128 { + if len(o.Trigger) == 0 || len(o.Trigger) > 128 { return NewLocAppError("Command.IsValid", "model.command.is_valid.trigger.app_error", nil, "") } diff --git a/model/command_test.go b/model/command_test.go index d362d8f2c..2376e2ef7 100644 --- a/model/command_test.go +++ b/model/command_test.go @@ -19,63 +19,115 @@ func TestCommandJson(t *testing.T) { } func TestCommandIsValid(t *testing.T) { - o := Command{} + o := Command{ + Id: NewId(), + Token: NewId(), + CreateAt: GetMillis(), + UpdateAt: GetMillis(), + CreatorId: NewId(), + TeamId: NewId(), + Trigger: "trigger", + URL: "http://example.com", + Method: COMMAND_METHOD_GET, + DisplayName: "", + Description: "", + } + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + + o.Id = "" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } o.Id = NewId() + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + + o.Token = "" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.CreateAt = GetMillis() + o.Token = NewId() + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + + o.CreateAt = 0 if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.UpdateAt = GetMillis() + o.CreateAt = GetMillis() + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + + o.UpdateAt = 0 if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.CreatorId = "123" + o.UpdateAt = GetMillis() + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + + o.CreatorId = "" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } o.CreatorId = NewId() - if err := o.IsValid(); err == nil { - t.Fatal("should be invalid") + if err := o.IsValid(); err != nil { + t.Fatal(err) } - o.Token = "123" + o.TeamId = "" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.Token = NewId() + o.TeamId = NewId() + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + + o.Trigger = "" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.TeamId = "123" + o.Trigger = strings.Repeat("1", 129) if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.TeamId = NewId() + o.Trigger = strings.Repeat("1", 128) + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + + o.URL = "" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.URL = "nowhere.com/" + o.URL = "1234" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } - o.URL = "http://nowhere.com/" + o.URL = "https://example.com" + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + + o.Method = "https://example.com" if err := o.IsValid(); err == nil { t.Fatal("should be invalid") } @@ -85,6 +137,11 @@ func TestCommandIsValid(t *testing.T) { t.Fatal(err) } + o.Method = COMMAND_METHOD_POST + if err := o.IsValid(); err != nil { + t.Fatal(err) + } + o.DisplayName = strings.Repeat("1", 65) if err := o.IsValid(); err == nil { t.Fatal("should be invalid") diff --git a/model/config.go b/model/config.go index 6803fe069..fd033c7cf 100644 --- a/model/config.go +++ b/model/config.go @@ -155,9 +155,9 @@ type TeamSettings struct { MaxUsersPerTeam int EnableTeamCreation bool EnableUserCreation bool + EnableOpenServer *bool RestrictCreationToDomains string RestrictTeamNames *bool - EnableTeamListing *bool EnableCustomBrand *bool CustomBrandText *string } @@ -180,6 +180,7 @@ type LdapSettings struct { LastNameAttribute *string EmailAttribute *string UsernameAttribute *string + NicknameAttribute *string IdAttribute *string // Advanced @@ -297,11 +298,6 @@ func (o *Config) SetDefaults() { *o.TeamSettings.RestrictTeamNames = true } - if o.TeamSettings.EnableTeamListing == nil { - o.TeamSettings.EnableTeamListing = new(bool) - *o.TeamSettings.EnableTeamListing = false - } - if o.TeamSettings.EnableCustomBrand == nil { o.TeamSettings.EnableCustomBrand = new(bool) *o.TeamSettings.EnableCustomBrand = false @@ -312,6 +308,11 @@ func (o *Config) SetDefaults() { *o.TeamSettings.CustomBrandText = "" } + if o.TeamSettings.EnableOpenServer == nil { + o.TeamSettings.EnableOpenServer = new(bool) + *o.TeamSettings.EnableOpenServer = false + } + if o.EmailSettings.EnableSignInWithEmail == nil { o.EmailSettings.EnableSignInWithEmail = new(bool) @@ -476,6 +477,11 @@ func (o *Config) SetDefaults() { o.LdapSettings.SkipCertificateVerification = new(bool) *o.LdapSettings.SkipCertificateVerification = false } + + if o.LdapSettings.NicknameAttribute == nil { + o.LdapSettings.NicknameAttribute = new(string) + *o.LdapSettings.NicknameAttribute = "" + } } func (o *Config) IsValid() *AppError { diff --git a/model/gitlab.go b/model/gitlab.go new file mode 100644 index 000000000..3dfb1016a --- /dev/null +++ b/model/gitlab.go @@ -0,0 +1,8 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +const ( + USER_AUTH_SERVICE_GITLAB = "gitlab" +) diff --git a/model/gitlab/gitlab.go b/model/gitlab/gitlab.go index 3ca499976..7df29c139 100644 --- a/model/gitlab/gitlab.go +++ b/model/gitlab/gitlab.go @@ -12,10 +12,6 @@ import ( "strings" ) -const ( - USER_AUTH_SERVICE_GITLAB = "gitlab" -) - type GitLabProvider struct { } @@ -29,7 +25,7 @@ type GitLabUser struct { func init() { provider := &GitLabProvider{} - einterfaces.RegisterOauthProvider(USER_AUTH_SERVICE_GITLAB, provider) + einterfaces.RegisterOauthProvider(model.USER_AUTH_SERVICE_GITLAB, provider) } func userFromGitLabUser(glu *GitLabUser) *model.User { @@ -51,7 +47,7 @@ func userFromGitLabUser(glu *GitLabUser) *model.User { } user.Email = glu.Email user.AuthData = strconv.FormatInt(glu.Id, 10) - user.AuthService = USER_AUTH_SERVICE_GITLAB + user.AuthService = model.USER_AUTH_SERVICE_GITLAB return user } @@ -84,7 +80,7 @@ func (glu *GitLabUser) getAuthData() string { } func (m *GitLabProvider) GetIdentifier() string { - return USER_AUTH_SERVICE_GITLAB + return model.USER_AUTH_SERVICE_GITLAB } func (m *GitLabProvider) GetUserFromJson(data io.Reader) *model.User { diff --git a/model/initial_load.go b/model/initial_load.go new file mode 100644 index 000000000..d7587e6d4 --- /dev/null +++ b/model/initial_load.go @@ -0,0 +1,40 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" +) + +type InitialLoad struct { + User *User `json:"user"` + TeamMembers []*TeamMember `json:"team_members"` + Teams []*Team `json:"teams"` + DirectProfiles map[string]*User `json:"direct_profiles"` + Preferences Preferences `json:"preferences"` + ClientCfg map[string]string `json:"client_cfg"` + LicenseCfg map[string]string `json:"license_cfg"` + NoAccounts bool `json:"no_accounts"` +} + +func (me *InitialLoad) ToJson() string { + b, err := json.Marshal(me) + if err != nil { + return "" + } else { + return string(b) + } +} + +func InitialLoadFromJson(data io.Reader) *InitialLoad { + decoder := json.NewDecoder(data) + var o InitialLoad + err := decoder.Decode(&o) + if err == nil { + return &o + } else { + return nil + } +} diff --git a/model/initial_load_test.go b/model/initial_load_test.go new file mode 100644 index 000000000..24a07e412 --- /dev/null +++ b/model/initial_load_test.go @@ -0,0 +1,20 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "strings" + "testing" +) + +func TestInitialLoadJson(t *testing.T) { + u := &User{Id: NewId()} + o := InitialLoad{User: u} + json := o.ToJson() + ro := InitialLoadFromJson(strings.NewReader(json)) + + if o.User.Id != ro.User.Id { + t.Fatal("Ids do not match") + } +} diff --git a/model/password_recovery.go b/model/password_recovery.go new file mode 100644 index 000000000..303d4a12e --- /dev/null +++ b/model/password_recovery.go @@ -0,0 +1,37 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +const ( + PASSWORD_RECOVERY_CODE_SIZE = 128 + PASSWORD_RECOVER_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour +) + +type PasswordRecovery struct { + UserId string + Code string + CreateAt int64 +} + +func (p *PasswordRecovery) IsValid() *AppError { + + if len(p.UserId) != 26 { + return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.user_id.app_error", nil, "") + } + + if len(p.Code) != PASSWORD_RECOVERY_CODE_SIZE { + return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.code.app_error", nil, "") + } + + if p.CreateAt == 0 { + return NewLocAppError("User.IsValid", "model.password_recovery.is_valid.create_at.app_error", nil, "") + } + + return nil +} + +func (p *PasswordRecovery) PreSave() { + p.Code = NewRandomString(PASSWORD_RECOVERY_CODE_SIZE) + p.CreateAt = GetMillis() +} diff --git a/model/session.go b/model/session.go index bf0d9531e..8a5eec74c 100644 --- a/model/session.go +++ b/model/session.go @@ -17,17 +17,17 @@ const ( ) type Session struct { - Id string `json:"id"` - Token string `json:"token"` - CreateAt int64 `json:"create_at"` - ExpiresAt int64 `json:"expires_at"` - LastActivityAt int64 `json:"last_activity_at"` - UserId string `json:"user_id"` - TeamId string `json:"team_id"` - DeviceId string `json:"device_id"` - Roles string `json:"roles"` - IsOAuth bool `json:"is_oauth"` - Props StringMap `json:"props"` + Id string `json:"id"` + Token string `json:"token"` + CreateAt int64 `json:"create_at"` + ExpiresAt int64 `json:"expires_at"` + LastActivityAt int64 `json:"last_activity_at"` + UserId string `json:"user_id"` + DeviceId string `json:"device_id"` + Roles string `json:"roles"` + IsOAuth bool `json:"is_oauth"` + Props StringMap `json:"props"` + TeamMembers []*TeamMember `json:"team_members" db:"-"` } func (me *Session) ToJson() string { @@ -95,6 +95,16 @@ func (me *Session) AddProp(key string, value string) { me.Props[key] = value } +func (me *Session) GetTeamByTeamId(teamId string) *TeamMember { + for _, team := range me.TeamMembers { + if team.TeamId == teamId { + return team + } + } + + return nil +} + func SessionsToJson(o []*Session) string { if b, err := json.Marshal(o); err != nil { return "[]" diff --git a/model/team.go b/model/team.go index d95dea110..072e0a8c0 100644 --- a/model/team.go +++ b/model/team.go @@ -18,19 +18,18 @@ const ( ) type Team struct { - Id string `json:"id"` - CreateAt int64 `json:"create_at"` - UpdateAt int64 `json:"update_at"` - DeleteAt int64 `json:"delete_at"` - DisplayName string `json:"display_name"` - Name string `json:"name"` - Email string `json:"email"` - Type string `json:"type"` - CompanyName string `json:"company_name"` - AllowedDomains string `json:"allowed_domains"` - InviteId string `json:"invite_id"` - AllowOpenInvite bool `json:"allow_open_invite"` - AllowTeamListing bool `json:"allow_team_listing"` + Id string `json:"id"` + CreateAt int64 `json:"create_at"` + UpdateAt int64 `json:"update_at"` + DeleteAt int64 `json:"delete_at"` + DisplayName string `json:"display_name"` + Name string `json:"name"` + Email string `json:"email"` + Type string `json:"type"` + CompanyName string `json:"company_name"` + AllowedDomains string `json:"allowed_domains"` + InviteId string `json:"invite_id"` + AllowOpenInvite bool `json:"allow_open_invite"` } type Invites struct { diff --git a/model/team_member.go b/model/team_member.go new file mode 100644 index 000000000..80ca9f2a3 --- /dev/null +++ b/model/team_member.go @@ -0,0 +1,78 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "io" + "strings" +) + +const ( + ROLE_TEAM_ADMIN = "admin" +) + +type TeamMember struct { + TeamId string `json:"team_id"` + UserId string `json:"user_id"` + Roles string `json:"roles"` +} + +func (o *TeamMember) ToJson() string { + b, err := json.Marshal(o) + if err != nil { + return "" + } else { + return string(b) + } +} + +func TeamMemberFromJson(data io.Reader) *TeamMember { + decoder := json.NewDecoder(data) + var o TeamMember + err := decoder.Decode(&o) + if err == nil { + return &o + } else { + return nil + } +} + +func TeamMembersToJson(o []*TeamMember) string { + if b, err := json.Marshal(o); err != nil { + return "[]" + } else { + return string(b) + } +} + +func TeamMembersFromJson(data io.Reader) []*TeamMember { + decoder := json.NewDecoder(data) + var o []*TeamMember + err := decoder.Decode(&o) + if err == nil { + return o + } else { + return nil + } +} + +func (o *TeamMember) IsValid() *AppError { + + if len(o.TeamId) != 26 { + return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.team_id.app_error", nil, "") + } + + if len(o.UserId) != 26 { + return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.user_id.app_error", nil, "") + } + + for _, role := range strings.Split(o.Roles, " ") { + if !(role == "" || role == ROLE_TEAM_ADMIN) { + return NewLocAppError("TeamMember.IsValid", "model.team_member.is_valid.role.app_error", nil, "role="+role) + } + } + + return nil +} diff --git a/model/team_member_test.go b/model/team_member_test.go new file mode 100644 index 000000000..d5b2e3b79 --- /dev/null +++ b/model/team_member_test.go @@ -0,0 +1,43 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "strings" + "testing" +) + +func TestTeamMemberJson(t *testing.T) { + o := TeamMember{TeamId: NewId(), UserId: NewId()} + json := o.ToJson() + ro := TeamMemberFromJson(strings.NewReader(json)) + + if o.TeamId != ro.TeamId { + t.Fatal("Ids do not match") + } +} + +func TestTeamMemberIsValid(t *testing.T) { + o := TeamMember{} + + if err := o.IsValid(); err == nil { + t.Fatal("should be invalid") + } + + o.TeamId = NewId() + if err := o.IsValid(); err == nil { + t.Fatal("should be invalid") + } + + o.UserId = NewId() + o.Roles = "blahblah" + if err := o.IsValid(); err == nil { + t.Fatal("should be invalid") + } + + o.Roles = "" + if err := o.IsValid(); err != nil { + t.Fatal(err) + } +} diff --git a/model/user.go b/model/user.go index 173fe2b4e..f43fc2089 100644 --- a/model/user.go +++ b/model/user.go @@ -15,7 +15,6 @@ import ( ) const ( - ROLE_TEAM_ADMIN = "admin" ROLE_SYSTEM_ADMIN = "system_admin" USER_AWAY_TIMEOUT = 5 * 60 * 1000 // 5 minutes USER_OFFLINE_TIMEOUT = 1 * 60 * 1000 // 1 minute @@ -28,6 +27,7 @@ const ( DEFAULT_LOCALE = "en" USER_AUTH_SERVICE_EMAIL = "email" USER_AUTH_SERVICE_USERNAME = "username" + MIN_PASSWORD_LENGTH = 5 ) type User struct { @@ -35,7 +35,6 @@ type User struct { CreateAt int64 `json:"create_at,omitempty"` UpdateAt int64 `json:"update_at,omitempty"` DeleteAt int64 `json:"delete_at"` - TeamId string `json:"team_id"` Username string `json:"username"` Password string `json:"password,omitempty"` AuthData string `json:"auth_data,omitempty"` @@ -76,10 +75,6 @@ func (u *User) IsValid() *AppError { return NewLocAppError("User.IsValid", "model.user.is_valid.update_at.app_error", nil, "user_id="+u.Id) } - if len(u.TeamId) != 26 { - return NewLocAppError("User.IsValid", "model.user.is_valid.team_id.app_error", nil, "") - } - if !IsValidUsername(u.Username) { return NewLocAppError("User.IsValid", "model.user.is_valid.username.app_error", nil, "user_id="+u.Id) } @@ -228,6 +223,7 @@ func (u *User) IsAway() bool { func (u *User) Sanitize(options map[string]bool) { u.Password = "" u.AuthData = "" + u.MfaSecret = "" if len(options) != 0 && !options["email"] { u.Email = "" @@ -246,6 +242,8 @@ func (u *User) ClearNonProfileFields() { u.Password = "" u.AuthData = "" u.AuthService = "" + u.MfaActive = false + u.MfaSecret = "" u.EmailVerified = false u.LastPingAt = 0 u.AllowMarketing = false @@ -301,7 +299,7 @@ func (u *User) GetDisplayName() string { } } -func IsValidRoles(userRoles string) bool { +func IsValidUserRoles(userRoles string) bool { roles := strings.Split(userRoles, " ") @@ -319,10 +317,6 @@ func isValidRole(role string) bool { return true } - if role == ROLE_TEAM_ADMIN { - return true - } - if role == ROLE_SYSTEM_ADMIN { return true } @@ -351,8 +345,8 @@ func IsInRole(userRoles string, inRole string) bool { return false } -func (u *User) IsSSOUser() bool { - if len(u.AuthData) != 0 && len(u.AuthService) != 0 && u.AuthService != USER_AUTH_SERVICE_LDAP { +func (u *User) IsOAuthUser() bool { + if u.AuthService == USER_AUTH_SERVICE_GITLAB { return true } return false diff --git a/model/user_test.go b/model/user_test.go index 662ae35a6..286c92a66 100644 --- a/model/user_test.go +++ b/model/user_test.go @@ -63,11 +63,6 @@ func TestUserIsValid(t *testing.T) { t.Fatal() } - user.TeamId = NewId() - if err := user.IsValid(); err == nil { - t.Fatal() - } - user.Username = NewId() + "^hello#" if err := user.IsValid(); err == nil { t.Fatal() @@ -195,11 +190,11 @@ func TestCleanUsername(t *testing.T) { func TestRoles(t *testing.T) { - if !IsValidRoles("admin") { + if IsValidUserRoles("admin") { t.Fatal() } - if IsValidRoles("junk") { + if IsValidUserRoles("junk") { t.Fatal() } diff --git a/model/utils.go b/model/utils.go index bb02f345d..03215490d 100644 --- a/model/utils.go +++ b/model/utils.go @@ -41,12 +41,10 @@ func (er *AppError) Error() string { } func (er *AppError) Translate(T goi18n.TranslateFunc) { - if len(er.Message) == 0 { - if er.params == nil { - er.Message = T(er.Id) - } else { - er.Message = T(er.Id, er.params) - } + if er.params == nil { + er.Message = T(er.Id) + } else { + er.Message = T(er.Id, er.params) } } @@ -83,6 +81,7 @@ func NewLocAppError(where string, id string, params map[string]interface{}, deta ap := &AppError{} ap.Id = id ap.params = params + ap.Message = id ap.Where = where ap.DetailedError = details ap.StatusCode = 500 diff --git a/model/version.go b/model/version.go index e9a2c2bd0..4a47f06ef 100644 --- a/model/version.go +++ b/model/version.go @@ -13,6 +13,7 @@ import ( // It should be maitained in chronological order with most current // release at the front of the list. var versions = []string{ + "3.0.0", "2.2.0", "2.1.0", "2.0.0", |