func cmdResetPassword() { if flagCmdResetPassword { if len(flagEmail) == 0 { fmt.Fprintln(os.Stderr, "flag needs an argument: -email") os.Exit(1) } if len(flagPassword) == 0 { fmt.Fprintln(os.Stderr, "flag needs an argument: -password") os.Exit(1) } if len(flagPassword) < 5 { fmt.Fprintln(os.Stderr, "flag invalid argument needs to be more than 4 characters: -password") os.Exit(1) } var user *model.User if result := <-app.Srv.Store.User().GetByEmail(flagEmail); result.Err != nil { l4g.Error("%v", result.Err) flushLogAndExit(1) } else { user = result.Data.(*model.User) } if result := <-app.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(flagPassword)); result.Err != nil { l4g.Error("%v", result.Err) flushLogAndExit(1) } os.Exit(0) } }
func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) { m := model.MapFromJson(r.Body) email := strings.ToLower(strings.TrimSpace(m["email"])) if len(email) == 0 { c.SetInvalidParam("signupTeam", "email") return } subjectPage := NewServerTemplatePage("signup_team_subject", c.GetSiteURL()) bodyPage := NewServerTemplatePage("signup_team_body", c.GetSiteURL()) bodyPage.Props["TourUrl"] = utils.Cfg.TeamSettings.TourLink props := make(map[string]string) props["email"] = email props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_team_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { c.Err = err return } if utils.Cfg.ServiceSettings.Mode == utils.MODE_DEV || utils.Cfg.EmailSettings.ByPassEmail { m["follow_link"] = bodyPage.Props["Link"] } w.Header().Set("Access-Control-Allow-Origin", " *") w.Write([]byte(model.MapToJson(m))) }
func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) { props := model.MapFromJson(r.Body) email := props["email"] if len(email) == 0 { c.SetInvalidParam("sendPasswordReset", "email") return } name := props["name"] if len(name) == 0 { c.SetInvalidParam("sendPasswordReset", "name") return } var team *model.Team if result := <-Srv.Store.Team().GetByName(name); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } var user *model.User if result := <-Srv.Store.User().GetByEmail(team.Id, email); result.Err != nil { c.Err = model.NewAppError("sendPasswordReset", "We couldn’t find an account with that address.", "email="+email+" team_id="+team.Id) return } else { user = result.Data.(*model.User) } if len(user.AuthData) != 0 { c.Err = model.NewAppError("sendPasswordReset", "Cannot reset password for SSO accounts", "userId="+user.Id+", teamId="+team.Id) return } newProps := make(map[string]string) newProps["user_id"] = user.Id newProps["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(newProps) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.PasswordResetSalt)) link := fmt.Sprintf("%s/reset_password?d=%s&h=%s", c.GetTeamURLFromTeam(team), url.QueryEscape(data), url.QueryEscape(hash)) subjectPage := NewServerTemplatePage("reset_subject") subjectPage.Props["SiteURL"] = c.GetSiteURL() bodyPage := NewServerTemplatePage("reset_body") bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["ResetUrl"] = link if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { c.Err = model.NewAppError("sendPasswordReset", "Failed to send password reset email successfully", "err="+err.Message) return } c.LogAuditWithUserId(user.Id, "sent="+email) w.Write([]byte(model.MapToJson(props))) }
func TestUserStoreUpdatePassword(t *testing.T) { Setup() teamId := model.NewId() u1 := &model.User{} u1.Email = model.NewId() Must(store.User().Save(u1)) Must(store.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id})) hashedPassword := model.HashPassword("newpwd") if err := (<-store.User().UpdatePassword(u1.Id, hashedPassword)).Err; err != nil { t.Fatal(err) } if r1 := <-store.User().GetByEmail(u1.Email); r1.Err != nil { t.Fatal(r1.Err) } else { user := r1.Data.(*model.User) if user.Password != hashedPassword { t.Fatal("Password was not updated correctly") } } }
func GetAuthorizationCode(c *Context, w http.ResponseWriter, r *http.Request, teamName, service, redirectUri, loginHint string) { sso := utils.Cfg.GetSSOService(service) if sso != nil && !sso.Enable { c.Err = model.NewAppError("GetAuthorizationCode", "Unsupported OAuth service provider", "service="+service) c.Err.StatusCode = http.StatusBadRequest return } clientId := sso.Id endpoint := sso.AuthEndpoint scope := sso.Scope stateProps := map[string]string{"team": teamName, "hash": model.HashPassword(clientId)} state := b64.StdEncoding.EncodeToString([]byte(model.MapToJson(stateProps))) authUrl := endpoint + "?response_type=code&client_id=" + clientId + "&redirect_uri=" + url.QueryEscape(redirectUri) + "&state=" + url.QueryEscape(state) if len(scope) > 0 { authUrl += "&scope=" + utils.UrlEncode(scope) } if len(loginHint) > 0 { authUrl += "&login_hint=" + utils.UrlEncode(loginHint) } http.Redirect(w, r, authUrl, http.StatusFound) }
func GetAuthorizationCode(c *Context, service string, props map[string]string, loginHint string) (string, *model.AppError) { sso := utils.Cfg.GetSSOService(service) if sso != nil && !sso.Enable { return "", model.NewLocAppError("GetAuthorizationCode", "api.user.get_authorization_code.unsupported.app_error", nil, "service="+service) } clientId := sso.Id endpoint := sso.AuthEndpoint scope := sso.Scope props["hash"] = model.HashPassword(clientId) state := b64.StdEncoding.EncodeToString([]byte(model.MapToJson(props))) redirectUri := c.GetSiteURL() + "/signup/" + service + "/complete" authUrl := endpoint + "?response_type=code&client_id=" + clientId + "&redirect_uri=" + url.QueryEscape(redirectUri) + "&state=" + url.QueryEscape(state) if len(scope) > 0 { authUrl += "&scope=" + utils.UrlEncode(scope) } if len(loginHint) > 0 { authUrl += "&login_hint=" + utils.UrlEncode(loginHint) } return authUrl, nil }
func BenchmarkGetFile(b *testing.B) { team, _, channel := SetupBenchmark() testPoster := NewAutoPostCreator(Client, channel.Id) filenames, err := testPoster.UploadTestFile() if err == false { b.Fatal("Unable to upload file for benchmark") } newProps := make(map[string]string) newProps["filename"] = filenames[0] newProps["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(newProps) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt)) // wait a bit for files to ready time.Sleep(5 * time.Second) // Benchmark Start b.ResetTimer() for i := 0; i < b.N; i++ { if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h="+url.QueryEscape(hash)+"&t="+team.Id, true); downErr != nil { b.Fatal(downErr) } } }
func InviteMembers(team *model.Team, user *model.User, invites []string) { for _, invite := range invites { if len(invite) > 0 { teamUrl := "" if utils.Cfg.ServiceSettings.Mode == utils.MODE_DEV { teamUrl = "http://localhost:8065" } else if utils.Cfg.ServiceSettings.UseSSL { teamUrl = fmt.Sprintf("https://%v.%v", team.Domain, utils.Cfg.ServiceSettings.Domain) } else { teamUrl = fmt.Sprintf("http://%v.%v", team.Domain, utils.Cfg.ServiceSettings.Domain) } sender := "" if len(strings.TrimSpace(user.FullName)) == 0 { sender = user.Username } else { sender = user.FullName } senderRole := "" if strings.Contains(user.Roles, model.ROLE_ADMIN) || strings.Contains(user.Roles, model.ROLE_SYSTEM_ADMIN) { senderRole = "administrator" } else { senderRole = "member" } subjectPage := NewServerTemplatePage("invite_subject", teamUrl) subjectPage.Props["SenderName"] = sender subjectPage.Props["TeamName"] = team.Name bodyPage := NewServerTemplatePage("invite_body", teamUrl) bodyPage.Props["TeamName"] = team.Name bodyPage.Props["SenderName"] = sender bodyPage.Props["SenderStatus"] = senderRole bodyPage.Props["Email"] = invite props := make(map[string]string) props["email"] = invite props["id"] = team.Id props["name"] = team.Name props["domain"] = team.Domain props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", teamUrl, url.QueryEscape(data), url.QueryEscape(hash)) if utils.Cfg.ServiceSettings.Mode == utils.MODE_DEV { l4g.Info("sending invitation to %v %v", invite, bodyPage.Props["Link"]) } if err := utils.SendMail(invite, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error("Failed to send invite email successfully err=%v", err) } } } }
func cmdResetPassword() { if flagCmdResetPassword { if len(flagTeamName) == 0 { fmt.Fprintln(os.Stderr, "flag needs an argument: -team_name") flag.Usage() os.Exit(1) } if len(flagEmail) == 0 { fmt.Fprintln(os.Stderr, "flag needs an argument: -email") flag.Usage() os.Exit(1) } if len(flagPassword) == 0 { fmt.Fprintln(os.Stderr, "flag needs an argument: -password") flag.Usage() os.Exit(1) } if len(flagPassword) < 5 { fmt.Fprintln(os.Stderr, "flag invalid argument needs to be more than 4 characters: -password") flag.Usage() os.Exit(1) } c := &api.Context{} c.RequestId = model.NewId() c.IpAddress = "cmd_line" var team *model.Team if result := <-api.Srv.Store.Team().GetByName(flagTeamName); result.Err != nil { l4g.Error("%v", result.Err) flushLogAndExit(1) } else { team = result.Data.(*model.Team) } var user *model.User if result := <-api.Srv.Store.User().GetByEmail(team.Id, flagEmail); result.Err != nil { l4g.Error("%v", result.Err) flushLogAndExit(1) } else { user = result.Data.(*model.User) } if result := <-api.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(flagPassword)); result.Err != nil { l4g.Error("%v", result.Err) flushLogAndExit(1) } os.Exit(0) } }
func TestAddUserToTeamFromInvite(t *testing.T) { th := Setup().InitBasic() th.BasicClient.Logout() Client := th.BasicClient props := make(map[string]string) props["email"] = strings.ToLower(model.NewId()) + "*****@*****.**" props["name"] = "Test Company name" props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: props["email"], Type: model.TEAM_OPEN} user := model.User{Email: props["email"], Nickname: "Corey Hulen", Password: "******"} ts := model.TeamSignup{Team: team, User: user, Invites: []string{"*****@*****.**"}, Data: data, Hash: hash} rts, err := Client.CreateTeamFromSignup(&ts) if err != nil { t.Fatal(err) } if rts.Data.(*model.TeamSignup).Team.DisplayName != team.DisplayName { t.Fatal("full name didn't match") } ruser := rts.Data.(*model.TeamSignup).User rteam := rts.Data.(*model.TeamSignup).Team Client.SetTeamId(rteam.Id) if result, err := Client.LoginById(ruser.Id, user.Password); err != nil { t.Fatal(err) } else { if result.Data.(*model.User).Email != user.Email { t.Fatal("email's didn't match") } } user2 := th.CreateUser(th.BasicClient) Client.Must(Client.Logout()) Client.Must(Client.Login(user2.Email, user2.Password)) if result, err := th.BasicClient.AddUserToTeamFromInvite("", "", rteam.InviteId); err != nil { t.Fatal(err) } else { rtm := result.Data.(*model.Team) if rtm.Id != rteam.Id { t.Fatal() } } }
func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.EmailSettings.EnableSignUpWithEmail { c.Err = model.NewLocAppError("signupTeam", "api.team.signup_team.email_disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } m := model.MapFromJson(r.Body) email := strings.ToLower(strings.TrimSpace(m["email"])) if len(email) == 0 { c.SetInvalidParam("signupTeam", "email") return } if !isTeamCreationAllowed(c, email) { return } subjectPage := utils.NewHTMLTemplate("signup_team_subject", c.Locale) subjectPage.Props["Subject"] = c.T("api.templates.signup_team_subject", map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]}) bodyPage := utils.NewHTMLTemplate("signup_team_body", c.Locale) bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["Title"] = c.T("api.templates.signup_team_body.title") bodyPage.Props["Button"] = c.T("api.templates.signup_team_body.button") bodyPage.Html["Info"] = template.HTML(c.T("api.templates.signup_team_body.info", map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})) props := make(map[string]string) props["email"] = email props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_team_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { c.Err = err return } if !utils.Cfg.EmailSettings.RequireEmailVerification { m["follow_link"] = fmt.Sprintf("/signup_team_complete/?d=%s&h=%s", url.QueryEscape(data), url.QueryEscape(hash)) } w.Header().Set("Access-Control-Allow-Origin", " *") w.Write([]byte(model.MapToJson(m))) }
func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.TeamSettings.AllowPublicLink { c.Err = model.NewAppError("getPublicLink", "Public links have been disabled", "") c.Err.StatusCode = http.StatusForbidden } if !utils.IsS3Configured() { c.Err = model.NewAppError("getPublicLink", "Unable to get link. Amazon S3 not configured. ", "") c.Err.StatusCode = http.StatusNotImplemented return } props := model.MapFromJson(r.Body) filename := props["filename"] if len(filename) == 0 { c.SetInvalidParam("getPublicLink", "filename") return } matches := model.PartialUrlRegex.FindAllStringSubmatch(filename, -1) if len(matches) == 0 || len(matches[0]) < 5 { c.SetInvalidParam("getPublicLink", "filename") return } getType := matches[0][1] channelId := matches[0][2] userId := matches[0][3] filename = matches[0][4] cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) newProps := make(map[string]string) newProps["filename"] = filename newProps["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(newProps) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.PublicLinkSalt)) url := fmt.Sprintf("%s/api/v1/files/%s/%s/%s/%s?d=%s&h=%s&t=%s", c.TeamUrl, getType, channelId, userId, filename, url.QueryEscape(data), url.QueryEscape(hash), c.Session.TeamId) if !c.HasPermissionsToChannel(cchan, "getPublicLink") { return } rData := make(map[string]string) rData["public_link"] = url w.Write([]byte(model.MapToJson(rData))) }
func TestCreateFromSignupTeam(t *testing.T) { th := Setup().InitBasic() th.BasicClient.Logout() Client := th.BasicClient props := make(map[string]string) props["email"] = strings.ToLower(model.NewId()) + "*****@*****.**" props["name"] = "Test Company name" props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "*****@*****.**", Type: model.TEAM_OPEN} user := model.User{Email: props["email"], Nickname: "Corey Hulen", Password: "******"} ts := model.TeamSignup{Team: team, User: user, Invites: []string{"*****@*****.**"}, Data: data, Hash: hash} rts, err := Client.CreateTeamFromSignup(&ts) if err != nil { t.Fatal(err) } if rts.Data.(*model.TeamSignup).Team.DisplayName != team.DisplayName { t.Fatal("full name didn't match") } ruser := rts.Data.(*model.TeamSignup).User rteam := rts.Data.(*model.TeamSignup).Team Client.SetTeamId(rteam.Id) if result, err := Client.LoginById(ruser.Id, user.Password); err != nil { t.Fatal(err) } else { if result.Data.(*model.User).Email != user.Email { t.Fatal("email's didn't match") } } c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList) if len(*c1) != 2 { t.Fatal("default channels not created") } ts.Data = "garbage" _, err = Client.CreateTeamFromSignup(&ts) if err == nil { t.Fatal(err) } }
func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) { if len(utils.Cfg.FileSettings.DriverName) == 0 { c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.storage.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } if !utils.Cfg.FileSettings.EnablePublicLink { c.Err = model.NewLocAppError("getPublicLink", "api.file.get_public_link.disabled.app_error", nil, "") c.Err.StatusCode = http.StatusForbidden } props := model.MapFromJson(r.Body) filename := props["filename"] if len(filename) == 0 { c.SetInvalidParam("getPublicLink", "filename") return } matches := model.PartialUrlRegex.FindAllStringSubmatch(filename, -1) if len(matches) == 0 || len(matches[0]) < 4 { c.SetInvalidParam("getPublicLink", "filename") return } channelId := matches[0][1] userId := matches[0][2] filename = matches[0][3] cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) newProps := make(map[string]string) newProps["filename"] = filename newProps["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(newProps) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt)) url := fmt.Sprintf("%s/api/v1/files/get/%s/%s/%s?d=%s&h=%s&t=%s", c.GetSiteURL(), channelId, userId, filename, url.QueryEscape(data), url.QueryEscape(hash), c.Session.TeamId) if !c.HasPermissionsToChannel(cchan, "getPublicLink") { return } rData := make(map[string]string) rData["public_link"] = url w.Write([]byte(model.MapToJson(rData))) }
func GetAuthorizationCode(c *Context, w http.ResponseWriter, r *http.Request, teamName, service, redirectUri string) { if s, ok := utils.Cfg.SSOSettings[service]; !ok || !s.Allow { c.Err = model.NewAppError("GetAuthorizationCode", "Unsupported OAuth service provider", "service="+service) c.Err.StatusCode = http.StatusBadRequest return } clientId := utils.Cfg.SSOSettings[service].Id endpoint := utils.Cfg.SSOSettings[service].AuthEndpoint state := model.HashPassword(clientId) authUrl := endpoint + "?response_type=code&client_id=" + clientId + "&redirect_uri=" + url.QueryEscape(redirectUri+"?team="+teamName) + "&state=" + url.QueryEscape(state) http.Redirect(w, r, authUrl, http.StatusFound) }
func TestCreateFromSignupTeam(t *testing.T) { Setup() props := make(map[string]string) props["email"] = strings.ToLower(model.NewId()) + "*****@*****.**" props["name"] = "Test Company name" props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) team := model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "*****@*****.**", Type: model.TEAM_OPEN} user := model.User{Email: props["email"], FullName: "Corey Hulen", Password: "******"} ts := model.TeamSignup{Team: team, User: user, Invites: []string{"*****@*****.**"}, Data: data, Hash: hash} rts, err := Client.CreateTeamFromSignup(&ts) if err != nil { t.Fatal(err) } if rts.Data.(*model.TeamSignup).Team.Name != team.Name { t.Fatal("full name didn't match") } ruser := rts.Data.(*model.TeamSignup).User if result, err := Client.LoginById(ruser.Id, user.Password); err != nil { t.Fatal(err) } else { if result.Data.(*model.User).Email != user.Email { t.Fatal("email's didn't match") } } c1 := Client.Must(Client.GetChannels("")).Data.(*model.ChannelList) if len(c1.Channels) != 2 { t.Fatal("default channels not created") } ts.Data = "garbage" _, err = Client.CreateTeamFromSignup(&ts) if err == nil { t.Fatal(err) } }
func FireAndForgetVerifyEmail(userId, name, email, teamName, teamUrl string) { go func() { link := fmt.Sprintf("%s/verify?uid=%s&hid=%s", teamUrl, userId, model.HashPassword(userId)) subjectPage := NewServerTemplatePage("verify_subject", teamUrl) subjectPage.Props["TeamName"] = teamName bodyPage := NewServerTemplatePage("verify_body", teamUrl) bodyPage.Props["FullName"] = name bodyPage.Props["TeamName"] = teamName bodyPage.Props["VerifyUrl"] = link if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error("Failed to send verification email successfully err=%v", err) } }() }
func InviteMembers(c *Context, team *model.Team, user *model.User, invites []string) { for _, invite := range invites { if len(invite) > 0 { sender := user.GetDisplayName() senderRole := "" if c.IsTeamAdmin() { senderRole = c.T("api.team.invite_members.admin") } else { senderRole = c.T("api.team.invite_members.member") } subjectPage := utils.NewHTMLTemplate("invite_subject", c.Locale) subjectPage.Props["Subject"] = c.T("api.templates.invite_subject", map[string]interface{}{"SenderName": sender, "TeamDisplayName": team.DisplayName, "SiteName": utils.ClientCfg["SiteName"]}) bodyPage := utils.NewHTMLTemplate("invite_body", c.Locale) bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["Title"] = c.T("api.templates.invite_body.title") bodyPage.Html["Info"] = template.HTML(c.T("api.templates.invite_body.info", map[string]interface{}{"SenderStatus": senderRole, "SenderName": sender, "TeamDisplayName": team.DisplayName})) bodyPage.Props["Button"] = c.T("api.templates.invite_body.button") bodyPage.Html["ExtraInfo"] = template.HTML(c.T("api.templates.invite_body.extra_info", map[string]interface{}{"TeamDisplayName": team.DisplayName, "TeamURL": c.GetTeamURL()})) props := make(map[string]string) props["email"] = invite props["id"] = team.Id props["display_name"] = team.DisplayName props["name"] = team.Name props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if !utils.Cfg.EmailSettings.SendEmailNotifications { l4g.Info(utils.T("api.team.invite_members.sending.info"), invite, bodyPage.Props["Link"]) } if err := utils.SendMail(invite, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error(utils.T("api.team.invite_members.send.error"), err) } } } }
func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.EmailSettings.EnableSignUpWithEmail { c.Err = model.NewAppError("signupTeam", "Team sign-up with email is disabled.", "") c.Err.StatusCode = http.StatusNotImplemented return } m := model.MapFromJson(r.Body) email := strings.ToLower(strings.TrimSpace(m["email"])) if len(email) == 0 { c.SetInvalidParam("signupTeam", "email") return } if !isTreamCreationAllowed(c, email) { return } subjectPage := NewServerTemplatePage("signup_team_subject") subjectPage.Props["SiteURL"] = c.GetSiteURL() bodyPage := NewServerTemplatePage("signup_team_body") bodyPage.Props["SiteURL"] = c.GetSiteURL() props := make(map[string]string) props["email"] = email props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_team_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { c.Err = err return } if !utils.Cfg.EmailSettings.RequireEmailVerification { m["follow_link"] = bodyPage.Props["Link"] } w.Header().Set("Access-Control-Allow-Origin", " *") w.Write([]byte(model.MapToJson(m))) }
func InviteMembers(c *Context, team *model.Team, user *model.User, invites []string) { for _, invite := range invites { if len(invite) > 0 { teamURL := "" teamURL = c.GetTeamURLFromTeam(team) sender := user.GetDisplayName() senderRole := "" if strings.Contains(user.Roles, model.ROLE_ADMIN) || strings.Contains(user.Roles, model.ROLE_SYSTEM_ADMIN) { senderRole = "administrator" } else { senderRole = "member" } subjectPage := NewServerTemplatePage("invite_subject", teamURL) subjectPage.Props["SenderName"] = sender subjectPage.Props["TeamDisplayName"] = team.DisplayName bodyPage := NewServerTemplatePage("invite_body", teamURL) bodyPage.Props["TeamDisplayName"] = team.DisplayName bodyPage.Props["SenderName"] = sender bodyPage.Props["SenderStatus"] = senderRole bodyPage.Props["Email"] = invite props := make(map[string]string) props["email"] = invite props["id"] = team.Id props["display_name"] = team.DisplayName props["name"] = team.Name props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if utils.Cfg.ServiceSettings.Mode == utils.MODE_DEV { l4g.Info("sending invitation to %v %v", invite, bodyPage.Props["Link"]) } if err := utils.SendMail(invite, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error("Failed to send invite email successfully err=%v", err) } } } }
func resetUserPasswordCmdF(cmd *cobra.Command, args []string) error { initDBCommandContextCobra(cmd) if len(args) != 2 { return errors.New("Incorect number of arguments.") } user := getUserFromUserArg(args[0]) if user == nil { return errors.New("Unable to find user '" + args[0] + "'") } password := args[1] if result := <-api.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(password)); result.Err != nil { return result.Err } return nil }
func InviteMembers(c *Context, team *model.Team, user *model.User, invites []string) { for _, invite := range invites { if len(invite) > 0 { sender := user.GetDisplayName() senderRole := "" if c.IsTeamAdmin() { senderRole = c.T("api.team.invite_members.admin") } else { senderRole = c.T("api.team.invite_members.member") } subjectPage := NewServerTemplatePage("invite_subject") subjectPage.Props["SenderName"] = sender subjectPage.Props["TeamDisplayName"] = team.DisplayName bodyPage := NewServerTemplatePage("invite_body") bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["TeamURL"] = c.GetTeamURL() bodyPage.Props["TeamDisplayName"] = team.DisplayName bodyPage.Props["SenderName"] = sender bodyPage.Props["SenderStatus"] = senderRole props := make(map[string]string) props["email"] = invite props["id"] = team.Id props["display_name"] = team.DisplayName props["name"] = team.Name props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash)) if !utils.Cfg.EmailSettings.SendEmailNotifications { l4g.Info(utils.T("api.team.invite_members.sending.info"), invite, bodyPage.Props["Link"]) } if err := utils.SendMail(invite, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error(utils.T("api.team.invite_members.send.error"), err) } } } }
func InviteMembers(team *model.Team, senderName string, invites []string) { for _, invite := range invites { if len(invite) > 0 { senderRole := utils.T("api.team.invite_members.member") subject := utils.T("api.templates.invite_subject", map[string]interface{}{"SenderName": senderName, "TeamDisplayName": team.DisplayName, "SiteName": utils.ClientCfg["SiteName"]}) bodyPage := utils.NewHTMLTemplate("invite_body", model.DEFAULT_LOCALE) bodyPage.Props["SiteURL"] = *utils.Cfg.ServiceSettings.SiteURL bodyPage.Props["Title"] = utils.T("api.templates.invite_body.title") bodyPage.Html["Info"] = template.HTML(utils.T("api.templates.invite_body.info", map[string]interface{}{"SenderStatus": senderRole, "SenderName": senderName, "TeamDisplayName": team.DisplayName})) bodyPage.Props["Button"] = utils.T("api.templates.invite_body.button") bodyPage.Html["ExtraInfo"] = template.HTML(utils.T("api.templates.invite_body.extra_info", map[string]interface{}{"TeamDisplayName": team.DisplayName, "TeamURL": *utils.Cfg.ServiceSettings.SiteURL + "/" + team.Name})) props := make(map[string]string) props["email"] = invite props["id"] = team.Id props["display_name"] = team.DisplayName props["name"] = team.Name props["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(props) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", *utils.Cfg.ServiceSettings.SiteURL, url.QueryEscape(data), url.QueryEscape(hash)) if !utils.Cfg.EmailSettings.SendEmailNotifications { l4g.Info(utils.T("api.team.invite_members.sending.info"), invite, bodyPage.Props["Link"]) } if err := utils.SendMail(invite, subject, bodyPage.Render()); err != nil { l4g.Error(utils.T("api.team.invite_members.send.error"), err) } } } }
func TestResetPassword(t *testing.T) { Setup() team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "*****@*****.**", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user := &model.User{TeamId: team.Id, Email: strings.ToLower(model.NewId()) + "*****@*****.**", Nickname: "Corey Hulen", Password: "******"} user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User) store.Must(Srv.Store.User().VerifyEmail(user.Id)) data := make(map[string]string) data["new_password"] = "******" props := make(map[string]string) props["user_id"] = user.Id props["time"] = fmt.Sprintf("%v", model.GetMillis()) data["data"] = model.MapToJson(props) data["hash"] = model.HashPassword(fmt.Sprintf("%v:%v", data["data"], utils.Cfg.ServiceSettings.ResetSalt)) data["name"] = team.Name if _, err := Client.ResetPassword(data); err != nil { t.Fatal(err) } data["new_password"] = "" if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - no password") } data["new_password"] = "******" if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - password too short") } data["new_password"] = "******" data["hash"] = "" if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - no hash") } data["hash"] = "junk" if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - bad hash") } props["user_id"] = "" data["data"] = model.MapToJson(props) if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - no user id") } data["user_id"] = "12345678901234567890123456" data["data"] = model.MapToJson(props) if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - bad user id") } props["user_id"] = user.Id props["time"] = "" data["data"] = model.MapToJson(props) if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - no time") } props["time"] = fmt.Sprintf("%v", model.GetMillis()) data["data"] = model.MapToJson(props) data["domain"] = "" if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - no domain") } data["domain"] = "junk" if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - bad domain") } team2 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "*****@*****.**", Type: model.TEAM_OPEN} team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) data["domain"] = team2.Name if _, err := Client.ResetPassword(data); err == nil { t.Fatal("Should have errored - domain team doesn't match user team") } }
func TestGetFile(t *testing.T) { Setup() team := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "*****@*****.**", Type: model.TEAM_OPEN} team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team) user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "*****@*****.**", FullName: "Corey Hulen", Password: "******"} user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User) Srv.Store.User().VerifyEmail(user1.Id) Client.LoginByEmail(team.Domain, user1.Email, "pwd") channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id} channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel) if utils.IsS3Configured() { body := &bytes.Buffer{} writer := multipart.NewWriter(body) part, err := writer.CreateFormFile("files", "test.png") if err != nil { t.Fatal(err) } path := utils.FindDir("web/static/images") file, err := os.Open(path + "/test.png") if err != nil { t.Fatal(err) } defer file.Close() _, err = io.Copy(part, file) if err != nil { t.Fatal(err) } field, err := writer.CreateFormField("channel_id") if err != nil { t.Fatal(err) } _, err = field.Write([]byte(channel1.Id)) if err != nil { t.Fatal(err) } err = writer.Close() if err != nil { t.Fatal(err) } resp, upErr := Client.UploadFile("/files/upload", body.Bytes(), writer.FormDataContentType()) if upErr != nil { t.Fatal(upErr) } filenames := resp.Data.(*model.FileUploadResponse).Filenames // wait a bit for files to ready time.Sleep(5 * time.Second) if _, downErr := Client.GetFile(filenames[0], true); downErr != nil { t.Fatal("file get failed") } team2 := &model.Team{Name: "Name", Domain: "z-z-" + model.NewId() + "a", Email: "*****@*****.**", Type: model.TEAM_OPEN} team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team) user2 := &model.User{TeamId: team2.Id, Email: model.NewId() + "*****@*****.**", FullName: "Corey Hulen", Password: "******"} user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User) Srv.Store.User().VerifyEmail(user2.Id) newProps := make(map[string]string) newProps["filename"] = filenames[0] newProps["time"] = fmt.Sprintf("%v", model.GetMillis()) data := model.MapToJson(newProps) hash := model.HashPassword(fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.PublicLinkSalt)) Client.LoginByEmail(team2.Domain, user2.Email, "pwd") if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h="+url.QueryEscape(hash)+"&t="+team.Id, true); downErr != nil { t.Fatal(downErr) } if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h="+url.QueryEscape(hash), true); downErr == nil { t.Fatal("Should have errored - missing team id") } if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h="+url.QueryEscape(hash)+"&t=junk", true); downErr == nil { t.Fatal("Should have errored - bad team id") } if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h="+url.QueryEscape(hash)+"&t=12345678901234567890123456", true); downErr == nil { t.Fatal("Should have errored - bad team id") } if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&t="+team.Id, true); downErr == nil { t.Fatal("Should have errored - missing hash") } if _, downErr := Client.GetFile(filenames[0]+"?d="+url.QueryEscape(data)+"&h=junk&t="+team.Id, true); downErr == nil { t.Fatal("Should have errored - bad hash") } if _, downErr := Client.GetFile(filenames[0]+"?h="+url.QueryEscape(hash)+"&t="+team.Id, true); downErr == nil { t.Fatal("Should have errored - missing data") } if _, downErr := Client.GetFile(filenames[0]+"?d=junk&h="+url.QueryEscape(hash)+"&t="+team.Id, true); downErr == nil { t.Fatal("Should have errored - bad data") } if _, downErr := Client.GetFile(filenames[0], true); downErr == nil { t.Fatal("Should have errored - user not logged in and link not public") } var auth aws.Auth auth.AccessKey = utils.Cfg.AWSSettings.S3AccessKeyId auth.SecretKey = utils.Cfg.AWSSettings.S3SecretAccessKey s := s3.New(auth, aws.Regions[utils.Cfg.AWSSettings.S3Region]) bucket := s.Bucket(utils.Cfg.AWSSettings.S3Bucket) fileId := strings.Split(filenames[0], ".")[0] err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + filenames[0]) if err != nil { t.Fatal(err) } err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_thumb.jpg") if err != nil { t.Fatal(err) } err = bucket.Del("teams/" + team.Id + "/channels/" + channel1.Id + "/users/" + user1.Id + "/" + fileId + "_preview.png") if err != nil { t.Fatal(err) } } else { if _, downErr := Client.GetFile("/files/get/yxebdmbz5pgupx7q6ez88rw11a/n3btzxu9hbnapqk36iwaxkjxhc/junk.jpg", false); downErr.StatusCode != http.StatusNotImplemented { t.Fatal("Status code should have been 501 - Not Implemented") } } }
func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.turn_off.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } c.LogAudit("attempt") responseData := map[string]string{} responseType := r.URL.Query().Get("response_type") if len(responseType) == 0 { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_response.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } clientId := r.URL.Query().Get("client_id") if len(clientId) != 26 { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_client.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } redirectUri := r.URL.Query().Get("redirect_uri") if len(redirectUri) == 0 { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_redirect.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } scope := r.URL.Query().Get("scope") state := r.URL.Query().Get("state") if len(scope) == 0 { scope = model.DEFAULT_SCOPE } var app *model.OAuthApp if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil { c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.database.app_error", nil, "") return } else { app = result.Data.(*model.OAuthApp) } if !app.IsValidRedirectURL(redirectUri) { c.LogAudit("fail - redirect_uri did not match registered callback") c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.redirect_callback.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } if responseType != model.AUTHCODE_RESPONSE_TYPE { responseData["redirect"] = redirectUri + "?error=unsupported_response_type&state=" + state w.Write([]byte(model.MapToJson(responseData))) return } authData := &model.AuthData{UserId: c.Session.UserId, ClientId: clientId, CreateAt: model.GetMillis(), RedirectUri: redirectUri, State: state, Scope: scope} authData.Code = model.HashPassword(fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, c.Session.UserId)) // this saves the OAuth2 app as authorized authorizedApp := model.Preference{ UserId: c.Session.UserId, Category: model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP, Name: clientId, Value: scope, } if result := <-Srv.Store.Preference().Save(&model.Preferences{authorizedApp}); result.Err != nil { responseData["redirect"] = redirectUri + "?error=server_error&state=" + state w.Write([]byte(model.MapToJson(responseData))) return } if result := <-Srv.Store.OAuth().SaveAuthData(authData); result.Err != nil { responseData["redirect"] = redirectUri + "?error=server_error&state=" + state w.Write([]byte(model.MapToJson(responseData))) return } c.LogAudit("success") responseData["redirect"] = redirectUri + "?code=" + url.QueryEscape(authData.Code) + "&state=" + url.QueryEscape(authData.State) w.Write([]byte(model.MapToJson(responseData))) }
func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) { c.LogAudit("attempted") props := model.MapFromJson(r.Body) userId := props["user_id"] if len(userId) != 26 { c.SetInvalidParam("updatePassword", "user_id") return } currentPassword := props["current_password"] if len(currentPassword) <= 0 { c.SetInvalidParam("updatePassword", "current_password") return } newPassword := props["new_password"] if len(newPassword) < 5 { c.SetInvalidParam("updatePassword", "new_password") return } if userId != c.Session.UserId { c.Err = model.NewAppError("updatePassword", "Update password failed because context user_id did not match props user_id", "") c.Err.StatusCode = http.StatusForbidden return } var result store.StoreResult if result = <-Srv.Store.User().Get(userId); result.Err != nil { c.Err = result.Err return } if result.Data == nil { c.Err = model.NewAppError("updatePassword", "Update password failed because we couldn't find a valid account", "") c.Err.StatusCode = http.StatusBadRequest return } user := result.Data.(*model.User) tchan := Srv.Store.Team().Get(user.TeamId) if user.AuthData != "" { c.LogAudit("failed - tried to update user password who was logged in through oauth") c.Err = model.NewAppError("updatePassword", "Update password failed because the user is logged in through an OAuth service", "auth_service="+user.AuthService) c.Err.StatusCode = http.StatusForbidden return } if !model.ComparePassword(user.Password, currentPassword) { c.Err = model.NewAppError("updatePassword", "The \"Current Password\" you entered is incorrect. Please check that Caps Lock is off and try again.", "") c.Err.StatusCode = http.StatusForbidden return } if uresult := <-Srv.Store.User().UpdatePassword(c.Session.UserId, model.HashPassword(newPassword)); uresult.Err != nil { c.Err = model.NewAppError("updatePassword", "Update password failed", uresult.Err.Error()) c.Err.StatusCode = http.StatusForbidden return } else { c.LogAudit("completed") if tresult := <-tchan; tresult.Err != nil { l4g.Error(tresult.Err.Message) } else { team := tresult.Data.(*model.Team) sendPasswordChangeEmailAndForget(user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL(), "using the settings menu") } data := make(map[string]string) data["user_id"] = uresult.Data.(string) w.Write([]byte(model.MapToJson(data))) } }
func SendVerifyEmailAndForget(userId, userEmail, teamName, teamDisplayName, siteURL, teamURL string) { go func() { link := fmt.Sprintf("%s/verify_email?uid=%s&hid=%s&teamname=%s&email=%s", siteURL, userId, model.HashPassword(userId), teamName, userEmail) subjectPage := NewServerTemplatePage("verify_subject") subjectPage.Props["SiteURL"] = siteURL subjectPage.Props["TeamDisplayName"] = teamDisplayName bodyPage := NewServerTemplatePage("verify_body") bodyPage.Props["SiteURL"] = siteURL bodyPage.Props["TeamDisplayName"] = teamDisplayName bodyPage.Props["VerifyUrl"] = link if err := utils.SendMail(userEmail, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error("Failed to send verification email successfully err=%v", err) } }() }
func sendWelcomeEmailAndForget(userId, email, teamName, teamDisplayName, siteURL, teamURL string, verified bool) { go func() { subjectPage := NewServerTemplatePage("welcome_subject") subjectPage.Props["TeamDisplayName"] = teamDisplayName bodyPage := NewServerTemplatePage("welcome_body") bodyPage.Props["SiteURL"] = siteURL bodyPage.Props["TeamURL"] = teamURL if !verified { link := fmt.Sprintf("%s/verify_email?uid=%s&hid=%s&teamname=%s&email=%s", siteURL, userId, model.HashPassword(userId), teamName, email) bodyPage.Props["VerifyUrl"] = link } if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil { l4g.Error("Failed to send welcome email successfully err=%v", err) } }() }
func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) { props := model.MapFromJson(r.Body) newPassword := props["new_password"] if len(newPassword) < 5 { c.SetInvalidParam("resetPassword", "new_password") return } name := props["name"] if len(name) == 0 { c.SetInvalidParam("resetPassword", "name") return } userId := props["user_id"] hash := props["hash"] timeStr := "" if !c.IsSystemAdmin() { if len(hash) == 0 { c.SetInvalidParam("resetPassword", "hash") return } data := model.MapFromJson(strings.NewReader(props["data"])) userId = data["user_id"] timeStr = data["time"] if len(timeStr) == 0 { c.SetInvalidParam("resetPassword", "data:time") return } } if len(userId) != 26 { c.SetInvalidParam("resetPassword", "user_id") return } c.LogAuditWithUserId(userId, "attempt") var team *model.Team if result := <-Srv.Store.Team().GetByName(name); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } var user *model.User if result := <-Srv.Store.User().Get(userId); result.Err != nil { c.Err = result.Err return } else { user = result.Data.(*model.User) } if len(user.AuthData) != 0 { c.Err = model.NewAppError("resetPassword", "Cannot reset password for SSO accounts", "userId="+user.Id+", teamId="+team.Id) return } if user.TeamId != team.Id { c.Err = model.NewAppError("resetPassword", "Trying to reset password for user on wrong team.", "userId="+user.Id+", teamId="+team.Id) c.Err.StatusCode = http.StatusForbidden return } if !c.IsSystemAdmin() { if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", props["data"], utils.Cfg.EmailSettings.PasswordResetSalt)) { c.Err = model.NewAppError("resetPassword", "The reset password link does not appear to be valid", "") return } t, err := strconv.ParseInt(timeStr, 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60 { // one hour c.Err = model.NewAppError("resetPassword", "The reset link has expired", "") return } } if result := <-Srv.Store.User().UpdatePassword(userId, model.HashPassword(newPassword)); result.Err != nil { c.Err = result.Err return } else { c.LogAuditWithUserId(userId, "success") } sendPasswordChangeEmailAndForget(user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL(), "using a reset password link") props["new_password"] = "" w.Write([]byte(model.MapToJson(props))) }