Exemplo n.º 1
0
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
	}

	system := m.AddSystemsCommand{}
	system.OrgId = cmd.Result.OrgId
	system.SystemsName = []string{"Cloudwiz"}
	if err := bus.Dispatch(&system); err != nil {
		log.Error(3, "Failed to create defalut system for admin", err)
		return
	}
	log.Info("Created default Cloudwiz system")
	log.Info("Created default admin user: %v", setting.AdminUser)
}
Exemplo n.º 2
0
func (mg *Migrator) exec(m Migration) error {
	if mg.LogLevel <= log.INFO {
		log.Info("Migrator: exec migration id: %v", m.Id())
	}

	err := mg.inTransaction(func(sess *xorm.Session) error {

		condition := m.GetCondition()
		if condition != nil {
			sql, args := condition.Sql(mg.dialect)
			results, err := sess.Query(sql, args...)
			if err != nil || len(results) == 0 {
				log.Info("Migrator: skipping migration id: %v, condition not fulfilled", m.Id())
				return sess.Rollback()
			}
		}

		_, err := sess.Exec(m.Sql(mg.dialect))
		if err != nil {
			log.Error(3, "Migrator: exec FAILED migration id: %v, err: %v", m.Id(), err)
			return err
		}
		return nil
	})

	if err != nil {
		return err
	}

	return nil
}
Exemplo n.º 3
0
func GetDataSources(c *middleware.Context) {
	log.Info("DataSource Url: %v", setting.DataSource.DataSourceUrlRoot)

	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)
}
Exemplo n.º 4
0
func LogConfigurationInfo() {
	var text bytes.Buffer
	text.WriteString("Configuration Info\n")

	text.WriteString("Config files:\n")
	for i, file := range configFiles {
		text.WriteString(fmt.Sprintf("  [%d]: %s\n", i, file))
	}

	if len(appliedCommandLineProperties) > 0 {
		text.WriteString("Command lines overrides:\n")
		for i, prop := range appliedCommandLineProperties {
			text.WriteString(fmt.Sprintf("  [%d]: %s\n", i, prop))
		}
	}

	if len(appliedEnvOverrides) > 0 {
		text.WriteString("\tEnvironment variables used:\n")
		for i, prop := range appliedEnvOverrides {
			text.WriteString(fmt.Sprintf("  [%d]: %s\n", i, prop))
		}
	}

	text.WriteString("Paths:\n")
	text.WriteString(fmt.Sprintf("  home: %s\n", HomePath))
	text.WriteString(fmt.Sprintf("  data: %s\n", DataPath))
	text.WriteString(fmt.Sprintf("  logs: %s\n", LogsPath))

	log.Info(text.String())
}
Exemplo n.º 5
0
func (a *ldapAuther) initialBind(username, userPassword string) error {
	if a.server.BindPassword != "" || a.server.BindDN == "" {
		userPassword = a.server.BindPassword
		a.requireSecondBind = true
	}

	bindPath := a.server.BindDN
	if strings.Contains(bindPath, "%s") {
		bindPath = fmt.Sprintf(a.server.BindDN, username)
	}

	if err := a.conn.Bind(bindPath, userPassword); err != nil {
		if ldapCfg.VerboseLogging {
			log.Info("LDAP initial bind failed, %v", err)
		}

		if ldapErr, ok := err.(*ldap.Error); ok {
			if ldapErr.ResultCode == 49 {
				return ErrInvalidCredentials
			}
		}
		return err
	}

	return nil
}
Exemplo n.º 6
0
func getEngine() (*xorm.Engine, error) {
	LoadConfig()

	cnnstr := ""
	switch DbCfg.Type {
	case "mysql":
		cnnstr = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",
			DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name)
	case "postgres":
		var host, port = "127.0.0.1", "5432"
		fields := strings.Split(DbCfg.Host, ":")
		if len(fields) > 0 && len(strings.TrimSpace(fields[0])) > 0 {
			host = fields[0]
		}
		if len(fields) > 1 && len(strings.TrimSpace(fields[1])) > 0 {
			port = fields[1]
		}
		cnnstr = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s",
			DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode)
	case "sqlite3":
		if !filepath.IsAbs(DbCfg.Path) {
			DbCfg.Path = filepath.Join(setting.DataPath, DbCfg.Path)
		}
		os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm)
		cnnstr = "file:" + DbCfg.Path + "?cache=shared&mode=rwc&_loc=Local"
	default:
		return nil, fmt.Errorf("Unknown database type: %s", DbCfg.Type)
	}

	log.Info("Database: %v", DbCfg.Type)

	return xorm.NewEngine(DbCfg.Type, cnnstr)
}
Exemplo n.º 7
0
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
}
Exemplo n.º 8
0
func loadLdapConfig() {
	if !setting.LdapEnabled {
		return
	}

	log.Info("Login: Ldap enabled, reading config file: %s", setting.LdapConfigFile)

	_, err := toml.DecodeFile(setting.LdapConfigFile, &ldapCfg)
	if err != nil {
		log.Fatal(3, "Failed to load ldap config file: %s", err)
	}

	if len(ldapCfg.Servers) == 0 {
		log.Fatal(3, "ldap enabled but no ldap servers defined in config file: %s", setting.LdapConfigFile)
	}

	// set default org id
	for _, server := range ldapCfg.Servers {
		assertNotEmptyCfg(server.SearchFilter, "search_filter")
		assertNotEmptyCfg(server.SearchBaseDNs, "search_base_dns")

		for _, groupMap := range server.LdapGroups {
			if groupMap.OrgId == 0 {
				groupMap.OrgId = 1
			}
		}
	}
}
Exemplo n.º 9
0
func AddDatasourceFromConfig() {

	// Read datasource from OrgId 1 and compare with the current setting:
	// If same, do nothing
	// If different, need to update the entries in the data_source table for all the OrgIds.

	// Read data source from OrgId 1 (default Main.org)
	query := m.GetDataSourceByNameQuery{
		OrgId: MAINORG_ID,
		Name:  "opentsdb",
	}

	if err := bus.Dispatch(&query); err != nil {
		log.Info("Could not find data source with OrgId = 1: %v", err)
	} else {
		log.Info("Data source read from OrgId 1 (MAINORG_ID) is %s", query.Result.Url)

		if setting.DataSource.DataSourceUrlRoot == query.Result.Url {
			return
		}
	}

	// If initially OrgId 1 does not have data source defined in data_source table, add it.
	// This should only happen when the system runs at the first time.
	if query.Result.Url == "" {
		log.Info("Add default data source for OrgId = 1 from config: %v", setting.DataSource.DataSourceUrlRoot)
		if err := bus.Dispatch(&m.AddDataSourceCommand{
			OrgId:     MAINORG_ID,
			Name:      "opentsdb",
			Type:      m.DS_OPENTSDB,
			Access:    m.DS_ACCESS_DIRECT,
			Url:       setting.DataSource.DataSourceUrlRoot,
			IsDefault: true,
		}); err != nil {
			log.Fatal(3, "Could not add default datasource for OrgId 1 from config: %v", err)
			return
		}
	} else {
		log.Info("Update default datasource for all the Orgs")
		if err := bus.Dispatch(&m.UpdateDataSourceForAllOrgCommand{
			Url: setting.DataSource.DataSourceUrlRoot,
		}); err != nil {
			log.Fatal(3, "Could not update default datasource for all Orgs: %v", err)
			return
		}
	}
}
Exemplo n.º 10
0
func NewJsonDashIndex(path string) *JsonDashIndex {
	log.Info("Creating json dashboard index for path: %v", path)

	index := JsonDashIndex{}
	index.path = path
	index.updateIndex()
	return &index
}
Exemplo n.º 11
0
func initRuntime() {
	err := setting.NewConfigContext(&setting.CommandLineArgs{
		Config:   *configFile,
		HomePath: *homePath,
		Args:     flag.Args(),
	})

	if err != nil {
		log.Fatal(3, err.Error())
	}

	log.Info("Starting Grafana")
	log.Info("Version: %v, Commit: %v, Build date: %v", setting.BuildVersion, setting.BuildCommit, time.Unix(setting.BuildStamp, 0))
	setting.LogConfigurationInfo()

	sqlstore.NewEngine()
	sqlstore.EnsureAdminUser()
	sqlstore.AddDatasourceFromConfig()
}
Exemplo n.º 12
0
func GetAlertSource(c *middleware.Context) {
	log.Info("Alert Url: %v", setting.Alert.AlertUrlRoot)

	alert := make(map[string]interface{})
	jsonAlertUrl := make(map[string]interface{})
	jsonAlertUrl["alert_urlroot"] = setting.Alert.AlertUrlRoot
	alert["alert"] = jsonAlertUrl

	c.JSON(200, alert)
}
Exemplo n.º 13
0
func DeleteDatasourceForOrg(orgId int64) (err error) {
	log.Info("DeleteDatasourceForOrg: orgId=%v", orgId)
	if err = bus.Dispatch(&m.DeleteAllDataSourceInOrgCommand{
		OrgId: orgId,
	}); err != nil {
		log.Error(3, "Could not delete data source with OrgId = %v: %v", orgId, err)
		return err
	}

	return nil
}
Exemplo n.º 14
0
func listenToSystemSignels() {
	signalChan := make(chan os.Signal, 1)
	code := 0

	signal.Notify(signalChan, os.Interrupt)
	signal.Notify(signalChan, os.Kill)
	signal.Notify(signalChan, syscall.SIGTERM)

	select {
	case sig := <-signalChan:
		log.Info("Received signal %s. shutting down", sig)
	case code = <-exitChan:
		switch code {
		case 0:
			log.Info("Shutting down")
		default:
			log.Warn("Shutting down")
		}
	}

	log.Close()
	os.Exit(code)
}
Exemplo n.º 15
0
func (a *ldapAuther) syncUserInfo(user *m.User, ldapUser *ldapUserInfo) error {
	var name = fmt.Sprintf("%s %s", ldapUser.FirstName, ldapUser.LastName)
	if user.Email == ldapUser.Email && user.Name == name {
		return nil
	}

	log.Info("Ldap: Syncing user info %s", ldapUser.Username)
	updateCmd := m.UpdateUserCommand{}
	updateCmd.UserId = user.Id
	updateCmd.Login = user.Login
	updateCmd.Email = ldapUser.Email
	updateCmd.Name = fmt.Sprintf("%s %s", ldapUser.FirstName, ldapUser.LastName)
	return bus.Dispatch(&updateCmd)
}
Exemplo n.º 16
0
func (a *ldapAuther) secondBind(ldapUser *ldapUserInfo, userPassword string) error {
	if err := a.conn.Bind(ldapUser.DN, userPassword); err != nil {
		if ldapCfg.VerboseLogging {
			log.Info("LDAP second bind failed, %v", err)
		}

		if ldapErr, ok := err.(*ldap.Error); ok {
			if ldapErr.ResultCode == 49 {
				return ErrInvalidCredentials
			}
		}
		return err
	}

	return nil
}
Exemplo n.º 17
0
func AddDatasourceForOrg(orgId int64) (err error) {
	log.Info("AddDatasourceForOrg: orgId=%v", orgId)
	if err = bus.Dispatch(&m.AddDataSourceCommand{
		OrgId:     orgId,
		Name:      "opentsdb",
		Type:      m.DS_OPENTSDB,
		Access:    m.DS_ACCESS_DIRECT,
		Url:       setting.DataSource.DataSourceUrlRoot,
		IsDefault: true,
	}); err != nil {
		log.Error(3, "Could not add default datasource from config: %v", err)
		return err
	}

	return nil
}
Exemplo n.º 18
0
func RenderToPng(params *RenderOpts) (string, error) {
	log.Info("PhantomRenderer::renderToPng url %v", params.Url)
	binPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "phantomjs"))
	scriptPath, _ := filepath.Abs(filepath.Join(setting.PhantomDir, "render.js"))
	pngPath, _ := filepath.Abs(filepath.Join(setting.ImagesDir, util.GetRandomString(20)))
	pngPath = pngPath + ".png"

	cmd := exec.Command(binPath, "--ignore-ssl-errors=true", "--ssl-protocol=any", scriptPath, "url="+params.Url, "width="+params.Width,
		"height="+params.Height, "png="+pngPath, "cookiename="+setting.SessionOptions.CookieName,
		"domain="+setting.Domain, "sessionid="+params.SessionId)
	stdout, err := cmd.StdoutPipe()

	if err != nil {
		return "", err
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return "", err
	}

	err = cmd.Start()
	if err != nil {
		return "", err
	}

	go io.Copy(os.Stdout, stdout)
	go io.Copy(os.Stdout, stderr)

	done := make(chan error)
	go func() {
		cmd.Wait()
		close(done)
	}()

	select {
	case <-time.After(15 * time.Second):
		if err := cmd.Process.Kill(); err != nil {
			log.Error(4, "failed to kill: %v", err)
		}
	case <-done:
	}

	return pngPath, nil
}
Exemplo n.º 19
0
func (mg *Migrator) Start() error {
	if mg.LogLevel <= log.INFO {
		log.Info("Migrator: Starting DB migration")
	}

	logMap, err := mg.GetMigrationLog()
	if err != nil {
		return err
	}

	for _, m := range mg.migrations {
		_, exists := logMap[m.Id()]
		if exists {
			if mg.LogLevel <= log.DEBUG {
				log.Debug("Migrator: Skipping migration: %v, Already executed", m.Id())
			}
			continue
		}

		sql := m.Sql(mg.dialect)

		record := MigrationLog{
			MigrationId: m.Id(),
			Sql:         sql,
			Timestamp:   time.Now(),
		}

		if mg.LogLevel <= log.DEBUG {
			log.Debug("Migrator: Executing SQL: \n %v \n", sql)
		}

		if err := mg.exec(m); err != nil {
			log.Error(3, "Migrator: error: \n%s:\n%s", err, sql)
			record.Error = err.Error()
			mg.x.Insert(&record)
			return err
		} else {
			record.Success = true
			mg.x.Insert(&record)
		}
	}

	return nil
}
Exemplo n.º 20
0
func (a *ldapAuther) login(query *LoginUserQuery) error {
	if err := a.Dial(); err != nil {
		return err
	}
	defer a.conn.Close()

	// perform initial authentication
	if err := a.initialBind(query.Username, query.Password); err != nil {
		return err
	}

	// find user entry & attributes
	if ldapUser, err := a.searchForUser(query.Username); err != nil {
		return err
	} else {
		if ldapCfg.VerboseLogging {
			log.Info("Ldap User Info: %s", spew.Sdump(ldapUser))
		}

		// check if a second user bind is needed
		if a.requireSecondBind {
			if err := a.secondBind(ldapUser, query.Password); err != nil {
				return err
			}
		}

		if grafanaUser, err := a.getGrafanaUserFor(ldapUser); err != nil {
			return err
		} else {
			// sync user details
			if err := a.syncUserInfo(grafanaUser, ldapUser); err != nil {
				return err
			}
			// sync org roles
			if err := a.syncOrgRoles(grafanaUser, ldapUser); err != nil {
				return err
			}
			query.User = grafanaUser
			return nil
		}
	}
}
Exemplo n.º 21
0
func signUpStartedHandler(evt *events.SignUpStarted) error {
	if !setting.VerifyEmailEnabled {
		return nil
	}

	log.Info("User signup started: %s", evt.Email)

	if evt.Email == "" {
		return nil
	}

	return sendEmailCommandHandler(&m.SendEmailCommand{
		To:       []string{evt.Email},
		Template: tmplSignUpStarted,
		Data: map[string]interface{}{
			"Email":     evt.Email,
			"Code":      evt.Code,
			"SignUpUrl": setting.ToAbsUrl(fmt.Sprintf("signup/?email=%s&code=%s", url.QueryEscape(evt.Email), url.QueryEscape(evt.Code))),
		},
	})
}
Exemplo n.º 22
0
func StartServer() {

	var err error
	m := newMacaron()
	api.Register(m)

	listenAddr := fmt.Sprintf("%s:%s", setting.HttpAddr, setting.HttpPort)
	log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubUrl)
	switch setting.Protocol {
	case setting.HTTP:
		err = http.ListenAndServe(listenAddr, m)
	case setting.HTTPS:
		err = http.ListenAndServeTLS(listenAddr, setting.CertFile, setting.KeyFile, m)
	default:
		log.Fatal(4, "Invalid protocol: %s", setting.Protocol)
	}

	if err != nil {
		log.Fatal(4, "Fail to start server: %v", err)
	}
}
Exemplo n.º 23
0
func Logger() macaron.Handler {
	return func(res http.ResponseWriter, req *http.Request, c *macaron.Context) {
		start := time.Now()

		rw := res.(macaron.ResponseWriter)
		c.Next()

		content := fmt.Sprintf("Completed %s %v %s in %v", req.URL.Path, rw.Status(), http.StatusText(rw.Status()), time.Since(start))

		switch rw.Status() {
		case 200, 304:
			content = fmt.Sprintf("%s", content)
			if !setting.RouterLogging {
				return
			}
		case 404:
			content = fmt.Sprintf("%s", content)
		case 500:
			content = fmt.Sprintf("%s", content)
		}

		log.Info(content)
	}
}
Exemplo n.º 24
0
func (a *ldapAuther) searchForUser(username string) (*ldapUserInfo, error) {
	var searchResult *ldap.SearchResult
	var err error

	for _, searchBase := range a.server.SearchBaseDNs {
		searchReq := ldap.SearchRequest{
			BaseDN:       searchBase,
			Scope:        ldap.ScopeWholeSubtree,
			DerefAliases: ldap.NeverDerefAliases,
			Attributes: []string{
				a.server.Attr.Username,
				a.server.Attr.Surname,
				a.server.Attr.Email,
				a.server.Attr.Name,
				a.server.Attr.MemberOf,
			},
			Filter: strings.Replace(a.server.SearchFilter, "%s", username, -1),
		}

		searchResult, err = a.conn.Search(&searchReq)
		if err != nil {
			return nil, err
		}

		if len(searchResult.Entries) > 0 {
			break
		}
	}

	if len(searchResult.Entries) == 0 {
		return nil, ErrInvalidCredentials
	}

	if len(searchResult.Entries) > 1 {
		return nil, errors.New("Ldap search matched more than one entry, please review your filter setting")
	}

	var memberOf []string
	if a.server.GroupSearchFilter == "" {
		memberOf = getLdapAttrArray(a.server.Attr.MemberOf, searchResult)
	} else {
		// If we are using a POSIX LDAP schema it won't support memberOf, so we manually search the groups
		var groupSearchResult *ldap.SearchResult
		for _, groupSearchBase := range a.server.GroupSearchBaseDNs {
			filter := strings.Replace(a.server.GroupSearchFilter, "%s", username, -1)

			if ldapCfg.VerboseLogging {
				log.Info("LDAP: Searching for user's groups: %s", filter)
			}

			groupSearchReq := ldap.SearchRequest{
				BaseDN:       groupSearchBase,
				Scope:        ldap.ScopeWholeSubtree,
				DerefAliases: ldap.NeverDerefAliases,
				Attributes: []string{
					// Here MemberOf would be the thing that identifies the group, which is normally 'cn'
					a.server.Attr.MemberOf,
				},
				Filter: filter,
			}

			groupSearchResult, err = a.conn.Search(&groupSearchReq)
			if err != nil {
				return nil, err
			}

			if len(groupSearchResult.Entries) > 0 {
				for i := range groupSearchResult.Entries {
					memberOf = append(memberOf, getLdapAttrN(a.server.Attr.MemberOf, groupSearchResult, i))
				}
				break
			}
		}
	}

	return &ldapUserInfo{
		DN:        searchResult.Entries[0].DN,
		LastName:  getLdapAttr(a.server.Attr.Surname, searchResult),
		FirstName: getLdapAttr(a.server.Attr.Name, searchResult),
		Username:  getLdapAttr(a.server.Attr.Username, searchResult),
		Email:     getLdapAttr(a.server.Attr.Email, searchResult),
		MemberOf:  memberOf,
	}, nil
}
Exemplo n.º 25
0
func OAuthLogin(ctx *middleware.Context) {
	if setting.OAuthService == nil {
		ctx.Handle(404, "login.OAuthLogin(oauth service not enabled)", nil)
		return
	}

	name := ctx.Params(":name")
	connect, ok := social.SocialMap[name]
	if !ok {
		ctx.Handle(404, "login.OAuthLogin(social login not enabled)", errors.New(name))
		return
	}

	code := ctx.Query("code")
	if code == "" {
		ctx.Redirect(connect.AuthCodeURL("", oauth2.AccessTypeOnline))
		return
	}

	// handle call back
	token, err := connect.Exchange(oauth2.NoContext, code)
	if err != nil {
		ctx.Handle(500, "login.OAuthLogin(NewTransportWithCode)", err)
		return
	}

	log.Trace("login.OAuthLogin(Got token)")

	userInfo, err := connect.UserInfo(token)
	if err != nil {
		if err == social.ErrMissingTeamMembership {
			ctx.Redirect(setting.AppSubUrl + "/login?failedMsg=" + url.QueryEscape("Required Github team membership not fulfilled"))
		} else if err == social.ErrMissingOrganizationMembership {
			ctx.Redirect(setting.AppSubUrl + "/login?failedMsg=" + url.QueryEscape("Required Github organization membership not fulfilled"))
		} else {
			ctx.Handle(500, fmt.Sprintf("login.OAuthLogin(get info from %s)", name), err)
		}
		return
	}

	log.Trace("login.OAuthLogin(social login): %s", userInfo)

	// validate that the email is allowed to login to grafana
	if !connect.IsEmailAllowed(userInfo.Email) {
		log.Info("OAuth login attempt with unallowed email, %s", userInfo.Email)
		ctx.Redirect(setting.AppSubUrl + "/login?failedMsg=" + url.QueryEscape("Required email domain not fulfilled"))
		return
	}

	userQuery := m.GetUserByLoginQuery{LoginOrEmail: userInfo.Email}
	err = bus.Dispatch(&userQuery)

	// create account if missing
	if err == m.ErrUserNotFound {
		if !connect.IsSignupAllowed() {
			ctx.Redirect(setting.AppSubUrl + "/login")
			return
		}
		limitReached, err := middleware.QuotaReached(ctx, "user")
		if err != nil {
			ctx.Handle(500, "Failed to get user quota", err)
			return
		}
		if limitReached {
			ctx.Redirect(setting.AppSubUrl + "/login")
			return
		}
		cmd := m.CreateUserCommand{
			Login:   userInfo.Email,
			Email:   userInfo.Email,
			Name:    userInfo.Name,
			Company: userInfo.Company,
		}

		if err = bus.Dispatch(&cmd); err != nil {
			ctx.Handle(500, "Failed to create account", err)
			return
		}

		userQuery.Result = &cmd.Result
	} else if err != nil {
		ctx.Handle(500, "Unexpected error", err)
	}

	// login
	loginUserWithUser(userQuery.Result, ctx)

	metrics.M_Api_Login_OAuth.Inc(1)

	ctx.Redirect(setting.AppSubUrl + "/")
}