// POST /api/user/signup func SignUp(c *middleware.Context, form dtos.SignUpForm) Response { if !setting.AllowUserSignUp { return ApiError(401, "User signup is disabled", nil) } existing := m.GetUserByLoginQuery{LoginOrEmail: form.Email} if err := bus.Dispatch(&existing); err == nil { return ApiError(422, "User with same email address already exists", nil) } cmd := m.CreateTempUserCommand{} cmd.OrgId = -1 cmd.Email = form.Email cmd.Status = m.TmpUserSignUpStarted cmd.InvitedByUserId = c.UserId cmd.Code = util.GetRandomString(20) cmd.RemoteAddr = c.Req.RemoteAddr if err := bus.Dispatch(&cmd); err != nil { return ApiError(500, "Failed to create signup", err) } bus.Publish(&events.SignUpStarted{ Email: form.Email, Code: cmd.Code, }) metrics.M_Api_User_SignUpStarted.Inc(1) return Json(200, util.DynMap{"status": "SignUpCreated"}) }
func EnsureAdminUser() { statsQuery := m.GetSystemStatsQuery{} if err := bus.Dispatch(&statsQuery); err != nil { log.Fatal(3, "Could not determine if admin user exists: %v", err) return } if statsQuery.Result.UserCount > 0 { return } cmd := m.CreateUserCommand{} cmd.Login = setting.AdminUser cmd.Email = setting.AdminUser + "@localhost" cmd.Password = setting.AdminPassword cmd.IsAdmin = true if err := bus.Dispatch(&cmd); err != nil { log.Error(3, "Failed to create default admin user", err) return } log.Info("Created default admin user: %v", setting.AdminUser) }
func inviteExistingUserToOrg(c *middleware.Context, user *m.User, inviteDto *dtos.AddInviteForm) Response { // user exists, add org role createOrgUserCmd := m.AddOrgUserCommand{OrgId: c.OrgId, UserId: user.Id, Role: inviteDto.Role} if err := bus.Dispatch(&createOrgUserCmd); err != nil { if err == m.ErrOrgUserAlreadyAdded { return ApiError(412, fmt.Sprintf("User %s is already added to organization", inviteDto.LoginOrEmail), err) } return ApiError(500, "Error while trying to create org user", err) } else { if !inviteDto.SkipEmails && util.IsEmail(user.Email) { emailCmd := m.SendEmailCommand{ To: []string{user.Email}, Template: "invited_to_org.html", Data: map[string]interface{}{ "Name": user.NameOrFallback(), "OrgName": c.OrgName, "InvitedBy": util.StringsFallback3(c.Name, c.Email, c.Login), }, } if err := bus.Dispatch(&emailCmd); err != nil { return ApiError(500, "Failed to send email invited_to_org", err) } } return ApiSuccess(fmt.Sprintf("Existing Grafana user %s added to org %s", user.NameOrFallback(), c.OrgName)) } }
func addOrgUserHelper(cmd m.AddOrgUserCommand) Response { if !cmd.Role.IsValid() { return ApiError(400, "Invalid role specified", nil) } userQuery := m.GetUserByLoginQuery{LoginOrEmail: cmd.LoginOrEmail} err := bus.Dispatch(&userQuery) if err != nil { return ApiError(404, "User not found", nil) } userToAdd := userQuery.Result // if userToAdd.Id == c.UserId { // return ApiError(400, "Cannot add yourself as user", nil) // } cmd.UserId = userToAdd.Id if err := bus.Dispatch(&cmd); err != nil { return ApiError(500, "Could not add user to organization", err) } return ApiSuccess("User added to organization") }
func AdminUpdateUserPassword(c *middleware.Context, form dtos.AdminUpdateUserPasswordForm) { userId := c.ParamsInt64(":id") if len(form.Password) < 4 { c.JsonApiErr(400, "New password too short", nil) return } userQuery := m.GetUserByIdQuery{Id: userId} if err := bus.Dispatch(&userQuery); err != nil { c.JsonApiErr(500, "Could not read user from database", err) return } passwordHashed := util.EncodePassword(form.Password, userQuery.Result.Salt) cmd := m.ChangeUserPasswordCommand{ UserId: userId, NewPassword: passwordHashed, } if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to update user password", err) return } c.JsonOK("User password updated") }
func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) Response { userQuery := m.GetUserByIdQuery{Id: c.UserId} if err := bus.Dispatch(&userQuery); err != nil { return ApiError(500, "Could not read user from database", err) } passwordHashed := util.EncodePassword(cmd.OldPassword, userQuery.Result.Salt) if passwordHashed != userQuery.Result.Password { return ApiError(401, "Invalid old password", nil) } if len(cmd.NewPassword) < 4 { return ApiError(400, "New password too short", nil) } cmd.UserId = c.UserId cmd.NewPassword = util.EncodePassword(cmd.NewPassword, userQuery.Result.Salt) if err := bus.Dispatch(&cmd); err != nil { return ApiError(500, "Failed to change user password", err) } return ApiSuccess("User password changed") }
func sendUsageStats() { log.Trace("Sending anonymous usage stats to stats.grafana.org") version := strings.Replace(setting.BuildVersion, ".", "_", -1) metrics := map[string]interface{}{} report := map[string]interface{}{ "version": version, "metrics": metrics, } UsageStats.Each(func(name string, i interface{}) { switch metric := i.(type) { case Counter: if metric.Count() > 0 { metrics[name+".count"] = metric.Count() metric.Clear() } } }) statsQuery := m.GetSystemStatsQuery{} if err := bus.Dispatch(&statsQuery); err != nil { log.Error(3, "Failed to get system stats", err) return } metrics["stats.dashboards.count"] = statsQuery.Result.DashboardCount metrics["stats.users.count"] = statsQuery.Result.UserCount metrics["stats.orgs.count"] = statsQuery.Result.OrgCount dsStats := m.GetDataSourceStatsQuery{} if err := bus.Dispatch(&dsStats); err != nil { log.Error(3, "Failed to get datasource stats", err) return } // send counters for each data source // but ignore any custom data sources // as sending that name could be sensitive information dsOtherCount := 0 for _, dsStat := range dsStats.Result { if m.IsKnownDataSourcePlugin(dsStat.Type) { metrics["stats.ds."+dsStat.Type+".count"] = dsStat.Count } else { dsOtherCount += dsStat.Count } } metrics["stats.ds.other.count"] = dsOtherCount out, _ := json.MarshalIndent(report, "", " ") data := bytes.NewBuffer(out) client := http.Client{Timeout: time.Duration(5 * time.Second)} go client.Post("https://stats.grafana.org/grafana-usage-report", "application/json", data) }
func AddOrgInvite(c *middleware.Context, inviteDto dtos.AddInviteForm) Response { if !inviteDto.Role.IsValid() { return ApiError(400, "Invalid role specified", nil) } // first try get existing user userQuery := m.GetUserByLoginQuery{LoginOrEmail: inviteDto.LoginOrEmail} if err := bus.Dispatch(&userQuery); err != nil { if err != m.ErrUserNotFound { return ApiError(500, "Failed to query db for existing user check", err) } } else { return inviteExistingUserToOrg(c, userQuery.Result, &inviteDto) } cmd := m.CreateTempUserCommand{} cmd.OrgId = c.OrgId cmd.Email = inviteDto.LoginOrEmail cmd.Name = inviteDto.Name cmd.Status = m.TmpUserInvitePending cmd.InvitedByUserId = c.UserId cmd.Code = util.GetRandomString(30) cmd.Role = inviteDto.Role cmd.RemoteAddr = c.Req.RemoteAddr if err := bus.Dispatch(&cmd); err != nil { return ApiError(500, "Failed to save invite to database", err) } // send invite email if !inviteDto.SkipEmails && util.IsEmail(inviteDto.LoginOrEmail) { emailCmd := m.SendEmailCommand{ To: []string{inviteDto.LoginOrEmail}, Template: "new_user_invite.html", Data: map[string]interface{}{ "Name": util.StringsFallback2(cmd.Name, cmd.Email), "OrgName": c.OrgName, "Email": c.Email, "LinkUrl": setting.ToAbsUrl("invite/" + cmd.Code), "InvitedBy": util.StringsFallback3(c.Name, c.Email, c.Login), }, } if err := bus.Dispatch(&emailCmd); err != nil { return ApiError(500, "Failed to send email invite", err) } return ApiSuccess(fmt.Sprintf("Sent invite to %s", inviteDto.LoginOrEmail)) } return ApiSuccess(fmt.Sprintf("Created invite for %s", inviteDto.LoginOrEmail)) }
func AdminCreateUser(c *middleware.Context, form dtos.AdminCreateUserForm) { cmd := m.CreateUserCommand{ Login: form.Login, Email: form.Email, Password: form.Password, Name: form.Name, } if len(cmd.Login) == 0 { cmd.Login = cmd.Email if len(cmd.Login) == 0 { c.JsonApiErr(400, "Validation error, need specify either username or email", nil) return } } if len(cmd.Password) < 4 { c.JsonApiErr(400, "Password is missing or too short", nil) return } if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "failed to create user", err) return } metrics.M_Api_Admin_User_Create.Inc(1) c.JsonOK("User created") }
func initContextWithApiKey(ctx *Context) bool { var keyString string if keyString = getApiKey(ctx); keyString == "" { return false } // base64 decode key decoded, err := apikeygen.Decode(keyString) if err != nil { ctx.JsonApiErr(401, "Invalid API key", err) return true } // fetch key keyQuery := m.GetApiKeyByNameQuery{KeyName: decoded.Name, OrgId: decoded.OrgId} if err := bus.Dispatch(&keyQuery); err != nil { ctx.JsonApiErr(401, "Invalid API key", err) return true } else { apikey := keyQuery.Result // validate api key if !apikeygen.IsValid(decoded, apikey.Key) { ctx.JsonApiErr(401, "Invalid API key", err) return true } ctx.IsSignedIn = true ctx.SignedInUser = &m.SignedInUser{} ctx.OrgRole = apikey.Role ctx.ApiKeyId = apikey.Id ctx.OrgId = apikey.OrgId return true } }
func CreateDashboardSnapshot(c *middleware.Context, cmd m.CreateDashboardSnapshotCommand) { if cmd.External { // external snapshot ref requires key and delete key if cmd.Key == "" || cmd.DeleteKey == "" { c.JsonApiErr(400, "Missing key and delete key for external snapshot", nil) return } cmd.OrgId = -1 cmd.UserId = -1 metrics.M_Api_Dashboard_Snapshot_External.Inc(1) } else { cmd.Key = util.GetRandomString(32) cmd.DeleteKey = util.GetRandomString(32) cmd.OrgId = c.OrgId cmd.UserId = c.UserId metrics.M_Api_Dashboard_Snapshot_Create.Inc(1) } if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to create snaphost", err) return } c.JSON(200, util.DynMap{ "key": cmd.Key, "deleteKey": cmd.DeleteKey, "url": setting.ToAbsUrl("dashboard/snapshot/" + cmd.Key), "deleteUrl": setting.ToAbsUrl("api/snapshots-delete/" + cmd.DeleteKey), }) }
func getOrgHelper(orgId int64) Response { query := m.GetOrgByIdQuery{Id: orgId} if err := bus.Dispatch(&query); err != nil { if err == m.ErrOrgNotFound { return ApiError(404, "Organization not found", err) } return ApiError(500, "Failed to get organization", err) } org := query.Result result := m.OrgDetailsDTO{ Id: org.Id, Name: org.Name, Address: m.Address{ Address1: org.Address1, Address2: org.Address2, City: org.City, ZipCode: org.ZipCode, State: org.State, Country: org.Country, }, } return Json(200, &result) }
func tryLoginUsingRememberCookie(c *middleware.Context) bool { // Check auto-login. uname := c.GetCookie(setting.CookieUserName) if len(uname) == 0 { return false } isSucceed := false defer func() { if !isSucceed { log.Trace("auto-login cookie cleared: %s", uname) c.SetCookie(setting.CookieUserName, "", -1, setting.AppSubUrl+"/") c.SetCookie(setting.CookieRememberName, "", -1, setting.AppSubUrl+"/") return } }() userQuery := m.GetUserByLoginQuery{LoginOrEmail: uname} if err := bus.Dispatch(&userQuery); err != nil { return false } user := userQuery.Result // validate remember me cookie if val, _ := c.GetSuperSecureCookie( util.EncodeMd5(user.Rands+user.Password), setting.CookieRememberName); val != user.Login { return false } isSucceed = true loginUserWithUser(user, c) return true }
func Search(c *middleware.Context) { query := c.Query("query") tags := c.QueryStrings("tag") starred := c.Query("starred") limit := c.QueryInt("limit") if limit == 0 { limit = 1000 } searchQuery := search.Query{ Title: query, Tags: tags, UserId: c.UserId, Limit: limit, IsStarred: starred == "true", OrgId: c.OrgId, } err := bus.Dispatch(&searchQuery) if err != nil { c.JsonApiErr(500, "Search failed", err) return } c.JSON(200, searchQuery.Result) }
func (a *ldapAuther) getGrafanaUserFor(ldapUser *ldapUserInfo) (*m.User, error) { // validate that the user has access // if there are no ldap group mappings access is true // otherwise a single group must match access := len(a.server.LdapGroups) == 0 for _, ldapGroup := range a.server.LdapGroups { if ldapUser.isMemberOf(ldapGroup.GroupDN) { access = true break } } if !access { log.Info("Ldap Auth: user %s does not belong in any of the specified ldap groups, ldapUser groups: %v", ldapUser.Username, ldapUser.MemberOf) return nil, ErrInvalidCredentials } // get user from grafana db userQuery := m.GetUserByLoginQuery{LoginOrEmail: ldapUser.Username} if err := bus.Dispatch(&userQuery); err != nil { if err == m.ErrUserNotFound { return a.createGrafanaUser(ldapUser) } else { return nil, err } } return userQuery.Result, nil }
func GetDataSources(c *middleware.Context) { query := m.GetDataSourcesQuery{OrgId: c.OrgId} if err := bus.Dispatch(&query); err != nil { c.JsonApiErr(500, "Failed to query datasources", err) return } result := make([]*dtos.DataSource, len(query.Result)) for i, ds := range query.Result { result[i] = &dtos.DataSource{ Id: ds.Id, OrgId: ds.OrgId, Name: ds.Name, Url: ds.Url, Type: ds.Type, Access: ds.Access, Password: ds.Password, Database: ds.Database, User: ds.User, BasicAuth: ds.BasicAuth, IsDefault: ds.IsDefault, } } c.JSON(200, result) }
func GetDataSourceById(c *middleware.Context) { query := m.GetDataSourceByIdQuery{ Id: c.ParamsInt64(":id"), OrgId: c.OrgId, } if err := bus.Dispatch(&query); err != nil { c.JsonApiErr(500, "Failed to query datasources", err) return } ds := query.Result c.JSON(200, &dtos.DataSource{ Id: ds.Id, OrgId: ds.OrgId, Name: ds.Name, Url: ds.Url, Type: ds.Type, Access: ds.Access, Password: ds.Password, Database: ds.Database, User: ds.User, BasicAuth: ds.BasicAuth, BasicAuthUser: ds.BasicAuthUser, BasicAuthPassword: ds.BasicAuthPassword, IsDefault: ds.IsDefault, JsonData: ds.JsonData, }) }
func LoginPost(c *middleware.Context, cmd dtos.LoginCommand) Response { authQuery := login.LoginUserQuery{ Username: cmd.User, Password: cmd.Password, } if err := bus.Dispatch(&authQuery); err != nil { if err == login.ErrInvalidCredentials { return ApiError(401, "Invalid username or password", err) } return ApiError(500, "Error while trying to authenticate user", err) } user := authQuery.User loginUserWithUser(user, c) result := map[string]interface{}{ "message": "Logged in", } if redirectTo, _ := url.QueryUnescape(c.GetCookie("redirect_to")); len(redirectTo) > 0 { result["redirectUrl"] = redirectTo c.SetCookie("redirect_to", "", -1, setting.AppSubUrl+"/") } metrics.M_Api_Login_Post.Inc(1) return Json(200, result) }
func GetDashboardSnapshot(c *middleware.Context) { key := c.Params(":key") query := &m.GetDashboardSnapshotQuery{Key: key} err := bus.Dispatch(query) if err != nil { c.JsonApiErr(500, "Failed to get dashboard snapshot", err) return } snapshot := query.Result // expired snapshots should also be removed from db if snapshot.Expires.Before(time.Now()) { c.JsonApiErr(404, "Dashboard snapshot not found", err) return } dto := dtos.DashboardFullWithMeta{ Dashboard: snapshot.Dashboard, Meta: dtos.DashboardMeta{ Type: m.DashTypeSnapshot, IsSnapshot: true, Created: snapshot.Created, Expires: snapshot.Expires, }, } metrics.M_Api_Dashboard_Snapshot_Get.Inc(1) c.Resp.Header().Set("Cache-Control", "public, max-age=3600") c.JSON(200, dto) }
func GetDashboard(c *middleware.Context) { metrics.M_Api_Dashboard_Get.Inc(1) slug := strings.ToLower(c.Params(":slug")) query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId} err := bus.Dispatch(&query) if err != nil { c.JsonApiErr(404, "Dashboard not found", nil) return } isStarred, err := isDasboardStarredByUser(c, query.Result.Id) if err != nil { c.JsonApiErr(500, "Error while checking if dashboard was starred by user", err) return } dash := query.Result dto := dtos.DashboardFullWithMeta{ Dashboard: dash.Data, Meta: dtos.DashboardMeta{ IsStarred: isStarred, Slug: slug, Type: m.DashTypeDB, CanStar: c.IsSignedIn, CanSave: c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR, CanEdit: canEditDashboard(c.OrgRole), }, } c.JSON(200, dto) }
// GET /api/users func SearchUsers(c *middleware.Context) Response { query := m.SearchUsersQuery{Query: "", Page: 0, Limit: 1000} if err := bus.Dispatch(&query); err != nil { return ApiError(500, "Failed to fetch users", err) } return Json(200, query.Result) }
func CompleteInvite(c *middleware.Context, completeInvite dtos.CompleteInviteForm) Response { query := m.GetTempUserByCodeQuery{Code: completeInvite.InviteCode} if err := bus.Dispatch(&query); err != nil { if err == m.ErrTempUserNotFound { return ApiError(404, "Invite not found", nil) } return ApiError(500, "Failed to get invite", err) } invite := query.Result if invite.Status != m.TmpUserInvitePending { return ApiError(412, fmt.Sprintf("Invite cannot be used in status %s", invite.Status), nil) } cmd := m.CreateUserCommand{ Email: completeInvite.Email, Name: completeInvite.Name, Login: completeInvite.Username, Password: completeInvite.Password, SkipOrgSetup: true, } if err := bus.Dispatch(&cmd); err != nil { return ApiError(500, "failed to create user", err) } user := &cmd.Result bus.Publish(&events.SignUpCompleted{ Name: user.NameOrFallback(), Email: user.Email, }) if ok, rsp := applyUserInvite(user, invite, true); !ok { return rsp } loginUserWithUser(user, c) metrics.M_Api_User_SignUpCompleted.Inc(1) metrics.M_Api_User_SignUpInvite.Inc(1) return ApiSuccess("User created and logged in") }
func initContextWithAuthProxy(ctx *Context) bool { if !setting.AuthProxyEnabled { return false } proxyHeaderValue := ctx.Req.Header.Get(setting.AuthProxyHeaderName) if len(proxyHeaderValue) == 0 { return false } query := getSignedInUserQueryForProxyAuth(proxyHeaderValue) if err := bus.Dispatch(query); err != nil { if err != m.ErrUserNotFound { ctx.Handle(500, "Failed find user specifed in auth proxy header", err) return true } if setting.AuthProxyAutoSignUp { cmd := getCreateUserCommandForProxyAuth(proxyHeaderValue) if err := bus.Dispatch(cmd); err != nil { ctx.Handle(500, "Failed to create user specified in auth proxy header", err) return true } query = &m.GetSignedInUserQuery{UserId: cmd.Result.Id} if err := bus.Dispatch(query); err != nil { ctx.Handle(500, "Failed find user after creation", err) return true } } else { return false } } // initialize session if err := ctx.Session.Start(ctx); err != nil { log.Error(3, "Failed to start session", err) return false } ctx.SignedInUser = query.Result ctx.IsSignedIn = true ctx.Session.Set(SESS_KEY_USERID, ctx.UserId) return true }
func updateTempUserStatus(code string, status m.TempUserStatus) (bool, Response) { // update temp user status updateTmpUserCmd := m.UpdateTempUserStatusCommand{Code: code, Status: status} if err := bus.Dispatch(&updateTmpUserCmd); err != nil { return false, ApiError(500, "Failed to update invite status", err) } return true, nil }
func getUserUserProfile(userId int64) Response { query := m.GetUserProfileQuery{UserId: userId} if err := bus.Dispatch(&query); err != nil { return ApiError(500, "Failed to get user", err) } return Json(200, query.Result) }
func getOrgUsersHelper(orgId int64) Response { query := m.GetOrgUsersQuery{OrgId: orgId} if err := bus.Dispatch(&query); err != nil { return ApiError(500, "Failed to get account user", err) } return Json(200, query.Result) }
func getUserOrgList(userId int64) Response { query := m.GetUserOrgListQuery{UserId: userId} if err := bus.Dispatch(&query); err != nil { return ApiError(500, "Faile to get user organziations", err) } return Json(200, query.Result) }
/** * @function name: func loginWithOpenFalconCookie(c *Context, username string) * @description: This function gets user logged in if "sig" cookie of Open-Falcon is valid. * @related issues: OWL-201, OWL-115, OWL-110 * @param: c *middleware.Context * @param: username string * @return: void * @author: Don Hsieh * @since: 10/06/2015 * @last modified: 12/09/2015 * @called by: func Auth(options *AuthOptions) macaron.Handler * in pkg/middleware/auth.go */ func loginWithOpenFalconCookie(c *Context, username string) { userQuery := m.GetUserByLoginQuery{LoginOrEmail: username} err := bus.Dispatch(&userQuery) if err == nil { user := userQuery.Result loginUserWithUser(user, c) } else { username = "******" userQuery = m.GetUserByLoginQuery{LoginOrEmail: username} err := bus.Dispatch(&userQuery) if err == nil { user := userQuery.Result loginUserWithUser(user, c) } else { log.Println("Error =", err.Error()) } } }
func searchHandler(query *Query) error { hits := make(HitList, 0) dashQuery := FindPersistedDashboardsQuery{ Title: query.Title, UserId: query.UserId, IsStarred: query.IsStarred, OrgId: query.OrgId, } if err := bus.Dispatch(&dashQuery); err != nil { return err } hits = append(hits, dashQuery.Result...) if jsonDashIndex != nil { jsonHits, err := jsonDashIndex.Search(query) if err != nil { return err } hits = append(hits, jsonHits...) } // filter out results with tag filter if len(query.Tags) > 0 { filtered := HitList{} for _, hit := range hits { if hasRequiredTags(query.Tags, hit.Tags) { filtered = append(filtered, hit) } } hits = filtered } // sort main result array sort.Sort(hits) if len(hits) > query.Limit { hits = hits[0:query.Limit] } // sort tags for _, hit := range hits { sort.Strings(hit.Tags) } // add isStarred info if err := setIsStarredFlagOnSearchResults(query.UserId, hits); err != nil { return err } query.Result = hits return nil }
func AddDataSource(c *middleware.Context, cmd m.AddDataSourceCommand) { cmd.OrgId = c.OrgId if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to add datasource", err) return } c.JSON(200, util.DynMap{"message": "Datasource added", "id": cmd.Result.Id}) }