func getTeamIdFromQuery(query url.Values) (string, *model.AppError) { hash := query.Get("h") inviteId := query.Get("id") if len(hash) > 0 { data := query.Get("d") props := model.MapFromJson(strings.NewReader(data)) if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { return "", model.NewLocAppError("getTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "") } t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours return "", model.NewLocAppError("getTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "") } return props["id"], nil } else if len(inviteId) > 0 { if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil { // soft fail, so we still create user but don't auto-join team l4g.Error("%v", result.Err) } else { return result.Data.(*model.Team).Id, nil } } return "", nil }
func checkUserPassword(c *Context, user *model.User, password string) bool { if user.FailedAttempts >= utils.Cfg.ServiceSettings.MaximumLoginAttempts { c.LogAuditWithUserId(user.Id, "fail") c.Err = model.NewAppError("checkUserPassword", "Your account is locked because of too many failed password attempts. Please reset your password.", "user_id="+user.Id) c.Err.StatusCode = http.StatusForbidden return false } if !model.ComparePassword(user.Password, password) { c.LogAuditWithUserId(user.Id, "fail") c.Err = model.NewAppError("checkUserPassword", "Login failed because of invalid password", "user_id="+user.Id) c.Err.StatusCode = http.StatusForbidden if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, user.FailedAttempts+1); result.Err != nil { c.LogError(result.Err) } return false } else { if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, 0); result.Err != nil { c.LogError(result.Err) } return true } }
func signupWithOAuth(c *api.Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) service := params["service"] teamName := params["team"] if !utils.Cfg.TeamSettings.EnableUserCreation { c.Err = model.NewAppError("signupTeam", "User sign-up is disabled.", "") c.Err.StatusCode = http.StatusNotImplemented return } if len(teamName) == 0 { c.Err = model.NewAppError("signupWithOAuth", "Invalid team name", "team_name="+teamName) c.Err.StatusCode = http.StatusBadRequest return } hash := r.URL.Query().Get("h") var team *model.Team if result := <-api.Srv.Store.Team().GetByName(teamName); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } if api.IsVerifyHashRequired(nil, team, hash) { data := r.URL.Query().Get("d") props := model.MapFromJson(strings.NewReader(data)) if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { c.Err = model.NewAppError("signupWithOAuth", "The signup link does not appear to be valid", "") return } t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours c.Err = model.NewAppError("signupWithOAuth", "The signup link has expired", "") return } if team.Id != props["id"] { c.Err = model.NewAppError("signupWithOAuth", "Invalid team name", data) return } } stateProps := map[string]string{} stateProps["action"] = model.OAUTH_ACTION_SIGNUP if authUrl, err := api.GetAuthorizationCode(c, service, teamName, stateProps, ""); err != nil { c.Err = err return } else { http.Redirect(w, r, authUrl, http.StatusFound) } }
func checkUserPassword(c *Context, user *model.User, password string) bool { if !model.ComparePassword(user.Password, password) { c.LogAuditWithUserId(user.Id, "fail") c.Err = model.NewAppError("checkUserPassword", "Login failed because of invalid password", "user_id="+user.Id) c.Err.StatusCode = http.StatusForbidden return false } return true }
func signupUserComplete(c *api.Context, w http.ResponseWriter, r *http.Request) { id := r.FormValue("id") data := r.FormValue("d") hash := r.FormValue("h") var props map[string]string if len(id) > 0 { props = make(map[string]string) if result := <-api.Srv.Store.Team().Get(id); result.Err != nil { c.Err = result.Err return } else { team := result.Data.(*model.Team) if !(team.Type == model.TEAM_OPEN || (team.Type == model.TEAM_INVITE && len(team.AllowedDomains) > 0)) { c.Err = model.NewAppError("signupUserComplete", "The team type doesn't allow open invites", "id="+id) return } props["email"] = "" props["display_name"] = team.DisplayName props["name"] = team.Name props["id"] = team.Id data = model.MapToJson(props) hash = "" } } else { if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) { c.Err = model.NewAppError("signupTeamComplete", "The signup link does not appear to be valid", "") return } props = model.MapFromJson(strings.NewReader(data)) t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hour c.Err = model.NewAppError("signupTeamComplete", "The signup link has expired", "") return } } page := NewHtmlTemplatePage("signup_user_complete", "Complete User Sign Up") page.Props["Email"] = props["email"] page.Props["TeamDisplayName"] = props["display_name"] page.Props["TeamName"] = props["name"] page.Props["TeamId"] = props["id"] page.Props["Data"] = data page.Props["Hash"] = hash page.Props["AuthServices"] = model.ArrayToJson(utils.GetAllowedAuthServices()) page.Render(c, w) }
func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) service := params["service"] if !utils.Cfg.TeamSettings.EnableUserCreation { c.Err = model.NewLocAppError("signupWithOAuth", "web.singup_with_oauth.disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } hash := r.URL.Query().Get("h") teamId := "" inviteId := r.URL.Query().Get("id") if len(hash) > 0 { data := r.URL.Query().Get("d") props := model.MapFromJson(strings.NewReader(data)) if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { c.Err = model.NewLocAppError("signupWithOAuth", "web.singup_with_oauth.invalid_link.app_error", nil, "") return } t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours c.Err = model.NewLocAppError("signupWithOAuth", "web.singup_with_oauth.expired_link.app_error", nil, "") return } teamId = props["id"] } else if len(inviteId) != 0 { if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil { // soft fail, so we still create user but don't auto-join team l4g.Error("%v", result.Err) } else { teamId = result.Data.(*model.Team).Id } } stateProps := map[string]string{} stateProps["action"] = model.OAUTH_ACTION_SIGNUP if len(teamId) != 0 { stateProps["team_id"] = teamId } if authUrl, err := GetAuthorizationCode(c, service, stateProps, ""); err != nil { c.Err = err return } else { http.Redirect(w, r, authUrl, http.StatusFound) } }
func verifyEmail(c *api.Context, w http.ResponseWriter, r *http.Request) { resend := r.URL.Query().Get("resend") resendSuccess := r.URL.Query().Get("resend_success") name := r.URL.Query().Get("teamname") email := r.URL.Query().Get("email") hashedId := r.URL.Query().Get("hid") userId := r.URL.Query().Get("uid") var team *model.Team if result := <-api.Srv.Store.Team().GetByName(name); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } if resend == "true" { if result := <-api.Srv.Store.User().GetByEmail(team.Id, email); result.Err != nil { c.Err = result.Err return } else { user := result.Data.(*model.User) api.FireAndForgetVerifyEmail(user.Id, user.Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team)) newAddress := strings.Replace(r.URL.String(), "&resend=true", "&resend_success=true", -1) http.Redirect(w, r, newAddress, http.StatusFound) return } } var isVerified string if len(userId) != 26 { isVerified = "false" } else if len(hashedId) == 0 { isVerified = "false" } else if model.ComparePassword(hashedId, userId) { isVerified = "true" if c.Err = (<-api.Srv.Store.User().VerifyEmail(userId)).Err; c.Err != nil { return } else { c.LogAudit("") } } else { isVerified = "false" } page := NewHtmlTemplatePage("verify", "Email Verified") page.Props["IsVerified"] = isVerified page.Props["TeamURL"] = c.GetTeamURLFromTeam(team) page.Props["UserEmail"] = email page.Props["ResendSuccess"] = resendSuccess page.Render(c, w) }
func signupUserComplete(c *api.Context, w http.ResponseWriter, r *http.Request) { id := r.FormValue("id") data := r.FormValue("d") hash := r.FormValue("h") var props map[string]string if len(id) > 0 { props = make(map[string]string) if result := <-api.Srv.Store.Team().GetByInviteId(id); result.Err != nil { c.Err = result.Err return } else { team := result.Data.(*model.Team) if !(team.Type == model.TEAM_OPEN || (team.Type == model.TEAM_INVITE && len(team.AllowedDomains) > 0)) { c.Err = model.NewLocAppError("signupUserComplete", "web.signup_user_complete.no_invites.app_error", nil, "id="+id) return } props["email"] = "" props["display_name"] = team.DisplayName props["name"] = team.Name props["id"] = team.Id data = model.MapToJson(props) hash = "" } } else { if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { c.Err = model.NewLocAppError("signupTeamComplete", "web.signup_user_complete.link_invalid.app_error", nil, "") return } props = model.MapFromJson(strings.NewReader(data)) t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hour c.Err = model.NewLocAppError("signupTeamComplete", "web.signup_user_complete.link_expired.app_error", nil, "") return } } page := NewHtmlTemplatePage("signup_user_complete", c.T("web.signup_user_complete.title"), c.Locale) page.Props["Email"] = props["email"] page.Props["TeamDisplayName"] = props["display_name"] page.Props["TeamName"] = props["name"] page.Props["TeamId"] = props["id"] page.Props["Data"] = data page.Props["Hash"] = hash page.Render(c, w) }
func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser, *model.AppError) { if s, ok := utils.Cfg.SSOSettings[service]; !ok || !s.Allow { return nil, model.NewAppError("AuthorizeOAuthUser", "Unsupported OAuth service provider", "service="+service) } if !model.ComparePassword(state, utils.Cfg.SSOSettings[service].Id) { return nil, model.NewAppError("AuthorizeOAuthUser", "Invalid state", "") } p := url.Values{} p.Set("client_id", utils.Cfg.SSOSettings[service].Id) p.Set("client_secret", utils.Cfg.SSOSettings[service].Secret) p.Set("code", code) p.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE) p.Set("redirect_uri", redirectUri) client := &http.Client{} req, _ := http.NewRequest("POST", utils.Cfg.SSOSettings[service].TokenEndpoint, strings.NewReader(p.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Accept", "application/json") var ar *model.AccessResponse if resp, err := client.Do(req); err != nil { return nil, model.NewAppError("AuthorizeOAuthUser", "Token request failed", err.Error()) } else { ar = model.AccessResponseFromJson(resp.Body) } if ar.TokenType != model.ACCESS_TOKEN_TYPE { return nil, model.NewAppError("AuthorizeOAuthUser", "Bad token type", "token_type="+ar.TokenType) } if len(ar.AccessToken) == 0 { return nil, model.NewAppError("AuthorizeOAuthUser", "Missing access token", "") } p = url.Values{} p.Set("access_token", ar.AccessToken) req, _ = http.NewRequest("GET", utils.Cfg.SSOSettings[service].UserApiEndpoint, strings.NewReader("")) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Accept", "application/json") req.Header.Set("Authorization", "Bearer "+ar.AccessToken) if resp, err := client.Do(req); err != nil { return nil, model.NewAppError("AuthorizeOAuthUser", "Token request to "+service+" failed", err.Error()) } else { return resp.Body, nil } }
func verifyEmail(c *api.Context, w http.ResponseWriter, r *http.Request) { resend := r.URL.Query().Get("resend") resendSuccess := r.URL.Query().Get("resend_success") name := r.URL.Query().Get("teamname") email := r.URL.Query().Get("email") hashedId := r.URL.Query().Get("hid") userId := r.URL.Query().Get("uid") var team *model.Team if result := <-api.Srv.Store.Team().GetByName(name); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } if resend == "true" { if result := <-api.Srv.Store.User().GetByEmail(team.Id, email); result.Err != nil { c.Err = result.Err return } else { user := result.Data.(*model.User) if user.LastActivityAt > 0 { api.SendEmailChangeVerifyEmailAndForget(user.Id, user.Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team)) } else { api.SendVerifyEmailAndForget(user.Id, user.Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team)) } newAddress := strings.Replace(r.URL.String(), "&resend=true", "&resend_success=true", -1) http.Redirect(w, r, newAddress, http.StatusFound) return } } if len(userId) == 26 && len(hashedId) != 0 && model.ComparePassword(hashedId, userId) { if c.Err = (<-api.Srv.Store.User().VerifyEmail(userId)).Err; c.Err != nil { return } else { c.LogAudit("Email Verified") http.Redirect(w, r, api.GetProtocol(r)+"://"+r.Host+"/"+name+"/login?verified=true&email="+email, http.StatusTemporaryRedirect) return } } page := NewHtmlTemplatePage("verify", "Email Verified") page.Props["TeamURL"] = c.GetTeamURLFromTeam(team) page.Props["UserEmail"] = email page.Props["ResendSuccess"] = resendSuccess page.Render(c, w) }
func resetPassword(c *api.Context, w http.ResponseWriter, r *http.Request) { isResetLink := true hash := r.URL.Query().Get("h") data := r.URL.Query().Get("d") if len(hash) == 0 || len(data) == 0 { isResetLink = false } else { if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.ResetSalt)) { c.Err = model.NewAppError("resetPassword", "The reset link does not appear to be valid", "") return } props := model.MapFromJson(strings.NewReader(data)) t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60 { // one hour c.Err = model.NewAppError("resetPassword", "The signup link has expired", "") return } } teamName := "Developer/Beta" domain := "" if utils.Cfg.ServiceSettings.Mode != utils.MODE_DEV { domain, _ = model.GetSubDomain(c.TeamUrl) var team *model.Team if tResult := <-api.Srv.Store.Team().GetByDomain(domain); tResult.Err != nil { c.Err = tResult.Err return } else { team = tResult.Data.(*model.Team) } if team != nil { teamName = team.Name } } page := NewHtmlTemplatePage("password_reset", "") page.Title = "Reset Password - " + page.SiteName page.Props["TeamName"] = teamName page.Props["Hash"] = hash page.Props["Data"] = data page.Props["Domain"] = domain page.Props["IsReset"] = strconv.FormatBool(isResetLink) page.Render(c, w) }
func checkUserPassword(user *model.User, password string) *model.AppError { if !model.ComparePassword(user.Password, password) { if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, user.FailedAttempts+1); result.Err != nil { return result.Err } return model.NewLocAppError("checkUserPassword", "api.user.check_user_password.invalid.app_error", nil, "user_id="+user.Id) } else { if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, 0); result.Err != nil { return result.Err } return nil } }
func verifyEmail(c *api.Context, w http.ResponseWriter, r *http.Request) { resend := r.URL.Query().Get("resend") domain := r.URL.Query().Get("domain") email := r.URL.Query().Get("email") hashedId := r.URL.Query().Get("hid") userId := r.URL.Query().Get("uid") if resend == "true" { teamId := "" if result := <-api.Srv.Store.Team().GetByDomain(domain); result.Err != nil { c.Err = result.Err return } else { teamId = result.Data.(*model.Team).Id } if result := <-api.Srv.Store.User().GetByEmail(teamId, email); result.Err != nil { c.Err = result.Err return } else { user := result.Data.(*model.User) api.FireAndForgetVerifyEmail(user.Id, strings.Split(user.FullName, " ")[0], user.Email, domain, c.TeamUrl) http.Redirect(w, r, "/", http.StatusFound) return } } var isVerified string if len(userId) != 26 { isVerified = "false" } else if len(hashedId) == 0 { isVerified = "false" } else if model.ComparePassword(hashedId, userId) { isVerified = "true" if c.Err = (<-api.Srv.Store.User().VerifyEmail(userId)).Err; c.Err != nil { return } else { c.LogAudit("") } } else { isVerified = "false" } page := NewHtmlTemplatePage("verify", "Email Verified") page.Props["IsVerified"] = isVerified page.Render(c, w) }
func resetPassword(c *api.Context, w http.ResponseWriter, r *http.Request) { isResetLink := true hash := r.URL.Query().Get("h") data := r.URL.Query().Get("d") params := mux.Vars(r) teamName := params["team"] if len(hash) == 0 || len(data) == 0 { isResetLink = false } else { if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.PasswordResetSalt)) { c.Err = model.NewAppError("resetPassword", "The reset link does not appear to be valid", "") return } props := model.MapFromJson(strings.NewReader(data)) t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60 { // one hour c.Err = model.NewAppError("resetPassword", "The signup link has expired", "") return } } teamDisplayName := "Developer/Beta" var team *model.Team if tResult := <-api.Srv.Store.Team().GetByName(teamName); tResult.Err != nil { c.Err = tResult.Err return } else { team = tResult.Data.(*model.Team) } if team != nil { teamDisplayName = team.DisplayName } page := NewHtmlTemplatePage("password_reset", "", c.Locale) page.Props["Title"] = "Reset Password " + page.ClientCfg["SiteName"] page.Props["TeamDisplayName"] = teamDisplayName page.Props["TeamName"] = teamName page.Props["Hash"] = hash page.Props["Data"] = data page.Props["TeamName"] = teamName page.Props["IsReset"] = strconv.FormatBool(isResetLink) page.Render(c, w) }
func signupWithOAuth(c *api.Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) service := params["service"] teamName := params["team"] if len(teamName) == 0 { c.Err = model.NewAppError("signupWithOAuth", "Invalid team name", "team_name="+teamName) c.Err.StatusCode = http.StatusBadRequest return } hash := r.URL.Query().Get("h") var team *model.Team if result := <-api.Srv.Store.Team().GetByName(teamName); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } if api.IsVerifyHashRequired(nil, team, hash) { data := r.URL.Query().Get("d") props := model.MapFromJson(strings.NewReader(data)) if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) { c.Err = model.NewAppError("signupWithOAuth", "The signup link does not appear to be valid", "") return } t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours c.Err = model.NewAppError("signupWithOAuth", "The signup link has expired", "") return } if team.Id != props["id"] { c.Err = model.NewAppError("signupWithOAuth", "Invalid team name", data) return } } redirectUri := c.GetSiteURL() + "/signup/" + service + "/complete" api.GetAuthorizationCode(c, w, r, teamName, service, redirectUri, "") }
func signupTeamComplete(c *api.Context, w http.ResponseWriter, r *http.Request) { data := r.FormValue("d") hash := r.FormValue("h") if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.InviteSalt)) { c.Err = model.NewAppError("signupTeamComplete", "The signup link does not appear to be valid", "") return } props := model.MapFromJson(strings.NewReader(data)) t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*24*30 { // 30 days c.Err = model.NewAppError("signupTeamComplete", "The signup link has expired", "") return } page := NewHtmlTemplatePage("signup_team_complete", "Complete Team Sign Up") page.Props["Email"] = props["email"] page.Props["Data"] = data page.Props["Hash"] = hash page.Render(c, w) }
func signupTeamComplete(c *api.Context, w http.ResponseWriter, r *http.Request) { data := r.FormValue("d") hash := r.FormValue("h") if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { c.Err = model.NewLocAppError("signupTeamComplete", "web.signup_team_complete.invalid_link.app_error", nil, "") return } props := model.MapFromJson(strings.NewReader(data)) t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*24*30 { // 30 days c.Err = model.NewLocAppError("signupTeamComplete", "web.signup_team_complete.link_expired.app_error", nil, "") return } page := NewHtmlTemplatePage("signup_team_complete", c.T("web.signup_team_complete.title"), c.Locale) page.Props["Email"] = props["email"] page.Props["Data"] = data page.Props["Hash"] = hash page.Render(c, w) }
func CreateUserWithHash(user *model.User, hash string, data string) (*model.User, *model.AppError) { props := model.MapFromJson(strings.NewReader(data)) if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { return nil, model.NewLocAppError("CreateUserWithHash", "api.user.create_user.signup_link_invalid.app_error", nil, "") } if t, err := strconv.ParseInt(props["time"], 10, 64); err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours return nil, model.NewLocAppError("CreateUserWithHash", "api.user.create_user.signup_link_expired.app_error", nil, "") } teamId := props["id"] var team *model.Team if result := <-Srv.Store.Team().Get(teamId); result.Err != nil { return nil, result.Err } else { team = result.Data.(*model.Team) } user.Email = props["email"] user.EmailVerified = true var ruser *model.User var err *model.AppError if ruser, err = CreateUser(user); err != nil { return nil, err } if err := JoinUserToTeam(team, ruser); err != nil { return nil, err } AddDirectChannels(team.Id, ruser) return ruser, nil }
func getPublicFile(c *Context, w http.ResponseWriter, r *http.Request) { params := mux.Vars(r) teamId := params["team_id"] channelId := params["channel_id"] userId := params["user_id"] filename := params["filename"] hash := r.URL.Query().Get("h") data := r.URL.Query().Get("d") if !utils.Cfg.FileSettings.EnablePublicLink { c.Err = model.NewLocAppError("getPublicFile", "api.file.get_file.public_disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } if len(hash) > 0 && len(data) > 0 { if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt)) { c.Err = model.NewLocAppError("getPublicFile", "api.file.get_file.public_invalid.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } } else { c.Err = model.NewLocAppError("getPublicFile", "api.file.get_file.public_invalid.app_error", nil, "") c.Err.StatusCode = http.StatusBadRequest return } if err, bytes := getFileData(teamId, channelId, userId, filename); err != nil { c.Err = err return } else if err := writeFileResponse(filename, bytes, w, r); err != nil { c.Err = err return } }
func getAccessToken(c *api.Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewAppError("getAccessToken", "The system admin has turned off OAuth service providing.", "") c.Err.StatusCode = http.StatusNotImplemented return } c.LogAudit("attempt") r.ParseForm() grantType := r.FormValue("grant_type") if grantType != model.ACCESS_TOKEN_GRANT_TYPE { c.Err = model.NewAppError("getAccessToken", "invalid_request: Bad grant_type", "") return } clientId := r.FormValue("client_id") if len(clientId) != 26 { c.Err = model.NewAppError("getAccessToken", "invalid_request: Bad client_id", "") return } secret := r.FormValue("client_secret") if len(secret) == 0 { c.Err = model.NewAppError("getAccessToken", "invalid_request: Missing client_secret", "") return } code := r.FormValue("code") if len(code) == 0 { c.Err = model.NewAppError("getAccessToken", "invalid_request: Missing code", "") return } redirectUri := r.FormValue("redirect_uri") achan := api.Srv.Store.OAuth().GetApp(clientId) tchan := api.Srv.Store.OAuth().GetAccessDataByAuthCode(code) authData := api.GetAuthData(code) if authData == nil { c.LogAudit("fail - invalid auth code") c.Err = model.NewAppError("getAccessToken", "invalid_grant: Invalid or expired authorization code", "") return } uchan := api.Srv.Store.User().Get(authData.UserId) if authData.IsExpired() { c.LogAudit("fail - auth code expired") c.Err = model.NewAppError("getAccessToken", "invalid_grant: Invalid or expired authorization code", "") return } if authData.RedirectUri != redirectUri { c.LogAudit("fail - redirect uri provided did not match previous redirect uri") c.Err = model.NewAppError("getAccessToken", "invalid_request: Supplied redirect_uri does not match authorization code redirect_uri", "") return } if !model.ComparePassword(code, fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, authData.UserId)) { c.LogAudit("fail - auth code is invalid") c.Err = model.NewAppError("getAccessToken", "invalid_grant: Invalid or expired authorization code", "") return } var app *model.OAuthApp if result := <-achan; result.Err != nil { c.Err = model.NewAppError("getAccessToken", "invalid_client: Invalid client credentials", "") return } else { app = result.Data.(*model.OAuthApp) } if !model.ComparePassword(app.ClientSecret, secret) { c.LogAudit("fail - invalid client credentials") c.Err = model.NewAppError("getAccessToken", "invalid_client: Invalid client credentials", "") return } callback := redirectUri if len(callback) == 0 { callback = app.CallbackUrls[0] } if result := <-tchan; result.Err != nil { c.Err = model.NewAppError("getAccessToken", "server_error: Encountered internal server error while accessing database", "") return } else if result.Data != nil { c.LogAudit("fail - auth code has been used previously") accessData := result.Data.(*model.AccessData) // Revoke access token, related auth code, and session from DB as well as from cache if err := api.RevokeAccessToken(accessData.Token); err != nil { l4g.Error("Encountered an error revoking an access token, err=" + err.Message) } c.Err = model.NewAppError("getAccessToken", "invalid_grant: Authorization code already exchanged for an access token", "") return } var user *model.User if result := <-uchan; result.Err != nil { c.Err = model.NewAppError("getAccessToken", "server_error: Encountered internal server error while pulling user from database", "") return } else { user = result.Data.(*model.User) } session := &model.Session{UserId: user.Id, TeamId: user.TeamId, Roles: user.Roles, IsOAuth: true} if result := <-api.Srv.Store.Session().Save(session); result.Err != nil { c.Err = model.NewAppError("getAccessToken", "server_error: Encountered internal server error while saving session to database", "") return } else { session = result.Data.(*model.Session) api.AddSessionToCache(session) } accessData := &model.AccessData{AuthCode: authData.Code, Token: session.Token, RedirectUri: callback} if result := <-api.Srv.Store.OAuth().SaveAccessData(accessData); result.Err != nil { l4g.Error(result.Err) c.Err = model.NewAppError("getAccessToken", "server_error: Encountered internal server error while saving access token to database", "") return } accessRsp := &model.AccessResponse{AccessToken: session.Token, TokenType: model.ACCESS_TOKEN_TYPE, ExpiresIn: model.SESSION_TIME_OAUTH_IN_SECS} w.Header().Set("Content-Type", "application/json") w.Header().Set("Cache-Control", "no-store") w.Header().Set("Pragma", "no-cache") c.LogAuditWithUserId(user.Id, "success") w.Write([]byte(accessRsp.ToJson())) }
func addUserToTeamFromInvite(c *Context, w http.ResponseWriter, r *http.Request) { params := model.MapFromJson(r.Body) hash := params["hash"] data := params["data"] inviteId := params["invite_id"] teamId := "" var team *model.Team if len(hash) > 0 { props := model.MapFromJson(strings.NewReader(data)) if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_invalid.app_error", nil, "") return } t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_expired.app_error", nil, "") return } teamId = props["id"] // try to load the team to make sure it exists if result := <-Srv.Store.Team().Get(teamId); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } } if len(inviteId) > 0 { if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) teamId = team.Id } } if len(teamId) == 0 { c.Err = model.NewLocAppError("addUserToTeamFromInvite", "api.user.create_user.signup_link_invalid.app_error", nil, "") return } uchan := Srv.Store.User().Get(c.Session.UserId) var user *model.User if result := <-uchan; result.Err != nil { c.Err = result.Err return } else { user = result.Data.(*model.User) } tm := c.Session.GetTeamByTeamId(teamId) if tm == nil { err := JoinUserToTeam(team, user) if err != nil { c.Err = err return } } team.Sanitize() w.Write([]byte(team.ToJson())) }
func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser, string, map[string]string, *model.AppError) { sso := utils.Cfg.GetSSOService(service) if sso == nil || !sso.Enable { return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.unsupported.app_error", nil, "service="+service) } stateStr := "" if b, err := b64.StdEncoding.DecodeString(state); err != nil { return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, err.Error()) } else { stateStr = string(b) } stateProps := model.MapFromJson(strings.NewReader(stateStr)) if !model.ComparePassword(stateProps["hash"], sso.Id) { return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "") } teamId := stateProps["team_id"] p := url.Values{} p.Set("client_id", sso.Id) p.Set("client_secret", sso.Secret) p.Set("code", code) p.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE) p.Set("redirect_uri", redirectUri) tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections}, } client := &http.Client{Transport: tr} req, _ := http.NewRequest("POST", sso.TokenEndpoint, strings.NewReader(p.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Accept", "application/json") var ar *model.AccessResponse var respBody []byte if resp, err := client.Do(req); err != nil { return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, err.Error()) } else { ar = model.AccessResponseFromJson(resp.Body) defer func() { ioutil.ReadAll(resp.Body) resp.Body.Close() }() if ar == nil { return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, "") } } if strings.ToLower(ar.TokenType) != model.ACCESS_TOKEN_TYPE { return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_token.app_error", nil, "token_type="+ar.TokenType+", response_body="+string(respBody)) } if len(ar.AccessToken) == 0 { return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.missing.app_error", nil, "") } p = url.Values{} p.Set("access_token", ar.AccessToken) req, _ = http.NewRequest("GET", sso.UserApiEndpoint, strings.NewReader("")) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Accept", "application/json") req.Header.Set("Authorization", "Bearer "+ar.AccessToken) if resp, err := client.Do(req); err != nil { return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error", map[string]interface{}{"Service": service}, err.Error()) } else { return resp.Body, teamId, stateProps, nil } }
func createUser(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.EmailSettings.EnableSignUpWithEmail { c.Err = model.NewAppError("signupTeam", "User sign-up with email is disabled.", "") c.Err.StatusCode = http.StatusNotImplemented return } user := model.UserFromJson(r.Body) if user == nil { c.SetInvalidParam("createUser", "user") return } // the user's username is checked to be valid when they are saved to the database user.EmailVerified = false var team *model.Team if result := <-Srv.Store.Team().Get(user.TeamId); result.Err != nil { c.Err = result.Err return } else { team = result.Data.(*model.Team) } hash := r.URL.Query().Get("h") if IsVerifyHashRequired(user, team, hash) { data := r.URL.Query().Get("d") props := model.MapFromJson(strings.NewReader(data)) if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) { c.Err = model.NewAppError("createUser", "The signup link does not appear to be valid", "") return } t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours c.Err = model.NewAppError("createUser", "The signup link has expired", "") return } if user.TeamId != props["id"] { c.Err = model.NewAppError("createUser", "Invalid team name", data) return } user.Email = props["email"] user.EmailVerified = true } if len(user.AuthData) > 0 && len(user.AuthService) > 0 { user.EmailVerified = true } ruser := CreateUser(c, team, user) if c.Err != nil { return } w.Write([]byte(ruser.ToJson())) }
func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } c.LogAudit("attempt") r.ParseForm() code := r.FormValue("code") refreshToken := r.FormValue("refresh_token") grantType := r.FormValue("grant_type") switch grantType { case model.ACCESS_TOKEN_GRANT_TYPE: if len(code) == 0 { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.missing_code.app_error", nil, "") return } case model.REFRESH_TOKEN_GRANT_TYPE: if len(refreshToken) == 0 { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.missing_refresh_token.app_error", nil, "") return } default: c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.bad_grant.app_error", nil, "") return } clientId := r.FormValue("client_id") if len(clientId) != 26 { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.bad_client_id.app_error", nil, "") return } secret := r.FormValue("client_secret") if len(secret) == 0 { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.bad_client_secret.app_error", nil, "") return } var app *model.OAuthApp achan := Srv.Store.OAuth().GetApp(clientId) if result := <-achan; result.Err != nil { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.credentials.app_error", nil, "") return } else { app = result.Data.(*model.OAuthApp) } if app.ClientSecret != secret { c.LogAudit("fail - invalid client credentials") c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.credentials.app_error", nil, "") return } var user *model.User var accessData *model.AccessData var accessRsp *model.AccessResponse if grantType == model.ACCESS_TOKEN_GRANT_TYPE { redirectUri := r.FormValue("redirect_uri") authData := GetAuthData(code) if authData == nil { c.LogAudit("fail - invalid auth code") c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "") return } if authData.IsExpired() { <-Srv.Store.OAuth().RemoveAuthData(authData.Code) c.LogAudit("fail - auth code expired") c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "") return } if authData.RedirectUri != redirectUri { c.LogAudit("fail - redirect uri provided did not match previous redirect uri") c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.redirect_uri.app_error", nil, "") return } if !model.ComparePassword(code, fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, authData.UserId)) { c.LogAudit("fail - auth code is invalid") c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "") return } uchan := Srv.Store.User().Get(authData.UserId) if result := <-uchan; result.Err != nil { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "") return } else { user = result.Data.(*model.User) } tchan := Srv.Store.OAuth().GetPreviousAccessData(user.Id, clientId) if result := <-tchan; result.Err != nil { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal.app_error", nil, "") return } else if result.Data != nil { accessData := result.Data.(*model.AccessData) if accessData.IsExpired() { if access, err := newSessionUpdateToken(app.Name, accessData, user); err != nil { c.Err = err return } else { accessRsp = access } } else { //return the same token and no need to create a new session accessRsp = &model.AccessResponse{ AccessToken: accessData.Token, TokenType: model.ACCESS_TOKEN_TYPE, ExpiresIn: int32((accessData.ExpiresAt - model.GetMillis()) / 1000), } } } else { // create a new session and return new access token var session *model.Session if result, err := newSession(app.Name, user); err != nil { c.Err = err return } else { session = result } accessData = &model.AccessData{ClientId: clientId, UserId: user.Id, Token: session.Token, RefreshToken: model.NewId(), RedirectUri: redirectUri, ExpiresAt: session.ExpiresAt} if result := <-Srv.Store.OAuth().SaveAccessData(accessData); result.Err != nil { l4g.Error(result.Err) c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_saving.app_error", nil, "") return } accessRsp = &model.AccessResponse{ AccessToken: session.Token, TokenType: model.ACCESS_TOKEN_TYPE, RefreshToken: accessData.RefreshToken, ExpiresIn: int32(*utils.Cfg.ServiceSettings.SessionLengthSSOInDays * 60 * 60 * 24), } } <-Srv.Store.OAuth().RemoveAuthData(authData.Code) } else { // when grantType is refresh_token if result := <-Srv.Store.OAuth().GetAccessDataByRefreshToken(refreshToken); result.Err != nil { c.LogAudit("fail - refresh token is invalid") c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.refresh_token.app_error", nil, "") return } else { accessData = result.Data.(*model.AccessData) } uchan := Srv.Store.User().Get(accessData.UserId) if result := <-uchan; result.Err != nil { c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "") return } else { user = result.Data.(*model.User) } if access, err := newSessionUpdateToken(app.Name, accessData, user); err != nil { c.Err = err return } else { accessRsp = access } } w.Header().Set("Content-Type", "application/json") w.Header().Set("Cache-Control", "no-store") w.Header().Set("Pragma", "no-cache") c.LogAuditWithUserId(user.Id, "success") w.Write([]byte(accessRsp.ToJson())) }
func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) { if utils.Cfg.ServiceSettings.DisableEmailSignUp { c.Err = model.NewAppError("createTeamFromSignup", "Team sign-up with email is disabled.", "") c.Err.StatusCode = http.StatusNotImplemented return } teamSignup := model.TeamSignupFromJson(r.Body) if teamSignup == nil { c.SetInvalidParam("createTeam", "teamSignup") return } props := model.MapFromJson(strings.NewReader(teamSignup.Data)) teamSignup.Team.Email = props["email"] teamSignup.User.Email = props["email"] teamSignup.Team.PreSave() if err := teamSignup.Team.IsValid(); err != nil { c.Err = err return } if !isTreamCreationAllowed(c, teamSignup.Team.Email) { return } teamSignup.Team.Id = "" password := teamSignup.User.Password teamSignup.User.PreSave() teamSignup.User.TeamId = model.NewId() if err := teamSignup.User.IsValid(); err != nil { c.Err = err return } teamSignup.User.Id = "" teamSignup.User.TeamId = "" teamSignup.User.Password = password if !model.ComparePassword(teamSignup.Hash, fmt.Sprintf("%v:%v", teamSignup.Data, utils.Cfg.ServiceSettings.InviteSalt)) { c.Err = model.NewAppError("createTeamFromSignup", "The signup link does not appear to be valid", "") return } t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60 { // one hour c.Err = model.NewAppError("createTeamFromSignup", "The signup link has expired", "") return } found := FindTeamByName(c, teamSignup.Team.Name, "true") if c.Err != nil { return } if found { c.Err = model.NewAppError("createTeamFromSignup", "This URL is unavailable. Please try another.", "d="+teamSignup.Team.Name) return } teamSignup.Team.AllowValet = utils.Cfg.TeamSettings.AllowValetDefault if result := <-Srv.Store.Team().Save(&teamSignup.Team); result.Err != nil { c.Err = result.Err return } else { rteam := result.Data.(*model.Team) if _, err := CreateDefaultChannels(c, rteam.Id); err != nil { c.Err = nil return } teamSignup.User.TeamId = rteam.Id teamSignup.User.EmailVerified = true ruser := CreateUser(c, rteam, &teamSignup.User) if c.Err != nil { return } if teamSignup.Team.AllowValet { CreateValet(c, rteam) if c.Err != nil { return } } InviteMembers(c, rteam, ruser, teamSignup.Invites) teamSignup.Team = *rteam teamSignup.User = *ruser w.Write([]byte(teamSignup.ToJson())) } }
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 createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.Cfg.EmailSettings.EnableSignUpWithEmail { c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.email_disabled.app_error", nil, "") c.Err.StatusCode = http.StatusNotImplemented return } teamSignup := model.TeamSignupFromJson(r.Body) if teamSignup == nil { c.SetInvalidParam("createTeam", "teamSignup") return } props := model.MapFromJson(strings.NewReader(teamSignup.Data)) teamSignup.Team.Email = props["email"] teamSignup.User.Email = props["email"] teamSignup.Team.PreSave() if err := teamSignup.Team.IsValid(); err != nil { c.Err = err return } if !isTeamCreationAllowed(c, teamSignup.Team.Email) { return } teamSignup.Team.Id = "" password := teamSignup.User.Password teamSignup.User.PreSave() if err := teamSignup.User.IsValid(); err != nil { c.Err = err return } teamSignup.User.Id = "" teamSignup.User.Password = password if !model.ComparePassword(teamSignup.Hash, fmt.Sprintf("%v:%v", teamSignup.Data, utils.Cfg.EmailSettings.InviteSalt)) { c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.invalid_link.app_error", nil, "") return } t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60 { // one hour c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.expired_link.app_error", nil, "") return } found := FindTeamByName(teamSignup.Team.Name) if found { c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.unavailable.app_error", nil, "d="+teamSignup.Team.Name) return } if result := <-Srv.Store.Team().Save(&teamSignup.Team); result.Err != nil { c.Err = result.Err return } else { rteam := result.Data.(*model.Team) if _, err := CreateDefaultChannels(c, rteam.Id); err != nil { c.Err = nil return } teamSignup.User.EmailVerified = true ruser, err := CreateUser(&teamSignup.User) if err != nil { c.Err = err return } JoinUserToTeam(rteam, ruser) InviteMembers(c, rteam, ruser, teamSignup.Invites) teamSignup.Team = *rteam teamSignup.User = *ruser w.Write([]byte(teamSignup.ToJson())) } }
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))) }
func getFile(c *Context, w http.ResponseWriter, r *http.Request) { if !utils.IsS3Configured() && !utils.Cfg.ServiceSettings.UseLocalStorage { c.Err = model.NewAppError("getFile", "Unable to get file. Amazon S3 not configured and local server storage turned off. ", "") c.Err.StatusCode = http.StatusNotImplemented return } params := mux.Vars(r) channelId := params["channel_id"] if len(channelId) != 26 { c.SetInvalidParam("getFile", "channel_id") return } userId := params["user_id"] if len(userId) != 26 { c.SetInvalidParam("getFile", "user_id") return } filename := params["filename"] if len(filename) == 0 { c.SetInvalidParam("getFile", "filename") return } hash := r.URL.Query().Get("h") data := r.URL.Query().Get("d") teamId := r.URL.Query().Get("t") cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId) path := "" if len(teamId) == 26 { path = "teams/" + teamId + "/channels/" + channelId + "/users/" + userId + "/" + filename } else { path = "teams/" + c.Session.TeamId + "/channels/" + channelId + "/users/" + userId + "/" + filename } fileData := make(chan []byte) asyncGetFile(path, fileData) if len(hash) > 0 && len(data) > 0 && len(teamId) == 26 { if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.ServiceSettings.PublicLinkSalt)) { c.Err = model.NewAppError("getFile", "The public link does not appear to be valid", "") return } props := model.MapFromJson(strings.NewReader(data)) t, err := strconv.ParseInt(props["time"], 10, 64) if err != nil || model.GetMillis()-t > 1000*60*60*24*7 { // one week c.Err = model.NewAppError("getFile", "The public link has expired", "") return } } else if !c.HasPermissionsToChannel(cchan, "getFile") { return } f := <-fileData if f == nil { c.Err = model.NewAppError("getFile", "Could not find file.", "path="+path) c.Err.StatusCode = http.StatusNotFound return } w.Header().Set("Cache-Control", "max-age=2592000, public") w.Header().Set("Content-Length", strconv.Itoa(len(f))) w.Header().Set("Content-Type", "") // need to provide proper Content-Type in the future w.Write(f) }
func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser, *model.Team, *model.AppError) { sso := utils.Cfg.GetSSOService(service) if sso == nil || !sso.Enable { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Unsupported OAuth service provider", "service="+service) } stateStr := "" if b, err := b64.StdEncoding.DecodeString(state); err != nil { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Invalid state", err.Error()) } else { stateStr = string(b) } stateProps := model.MapFromJson(strings.NewReader(stateStr)) if !model.ComparePassword(stateProps["hash"], sso.Id) { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Invalid state", "") } teamName := stateProps["team"] if len(teamName) == 0 { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Invalid state; missing team name", "") } tchan := Srv.Store.Team().GetByName(teamName) p := url.Values{} p.Set("client_id", sso.Id) p.Set("client_secret", sso.Secret) p.Set("code", code) p.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE) p.Set("redirect_uri", redirectUri) client := &http.Client{} req, _ := http.NewRequest("POST", sso.TokenEndpoint, strings.NewReader(p.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Accept", "application/json") var ar *model.AccessResponse if resp, err := client.Do(req); err != nil { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Token request failed", err.Error()) } else { ar = model.AccessResponseFromJson(resp.Body) if ar == nil { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Bad response from token request", "") } } if strings.ToLower(ar.TokenType) != model.ACCESS_TOKEN_TYPE { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Bad token type", "token_type="+ar.TokenType) } if len(ar.AccessToken) == 0 { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Missing access token", "") } p = url.Values{} p.Set("access_token", ar.AccessToken) req, _ = http.NewRequest("GET", sso.UserApiEndpoint, strings.NewReader("")) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.Header.Set("Accept", "application/json") req.Header.Set("Authorization", "Bearer "+ar.AccessToken) if resp, err := client.Do(req); err != nil { return nil, nil, model.NewAppError("AuthorizeOAuthUser", "Token request to "+service+" failed", err.Error()) } else { if result := <-tchan; result.Err != nil { return nil, nil, result.Err } else { return resp.Body, result.Data.(*model.Team), nil } } }