// GenerateRandomAvatar generates a random avatar for user. func (u *User) GenerateRandomAvatar() error { seed := u.Email if len(seed) == 0 { seed = u.Name } img, err := avatar.RandomImage([]byte(seed)) if err != nil { return fmt.Errorf("RandomImage: %v", err) } if err = os.MkdirAll(filepath.Dir(u.CustomAvatarPath()), os.ModePerm); err != nil { return fmt.Errorf("MkdirAll: %v", err) } fw, err := os.Create(u.CustomAvatarPath()) if err != nil { return fmt.Errorf("Create: %v", err) } defer fw.Close() if err = jpeg.Encode(fw, img, nil); err != nil { return fmt.Errorf("Encode: %v", err) } log.Info("New random avatar created: %d", u.Id) return nil }
func (c *Comment) AfterDelete() { _, err := DeleteAttachmentsByComment(c.ID, true) if err != nil { log.Info("Could not delete files for comment %d on issue #%d: %s", c.ID, c.IssueID, err) } }
func newNotifyMailService() { if !Cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").MustBool() { return } else if MailService == nil { log.Warn("Notify Mail Service: Mail Service is not enabled") return } Service.EnableNotifyMail = true log.Info("Notify Mail Service Enabled") }
func newRegisterMailService() { if !Cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").MustBool() { return } else if MailService == nil { log.Warn("Register Mail Service: Mail Service is not enabled") return } Service.RegisterEmailConfirm = true log.Info("Register Mail Service Enabled") }
func checkRunMode() { switch setting.Cfg.Section("").Key("RUN_MODE").String() { case "prod": macaron.Env = macaron.PROD macaron.ColorLog = false setting.ProdMode = true default: git.Debug = true } log.Info("Run Mode: %s", strings.Title(macaron.Env)) }
// GlobalInit is for global configuration reload-able. func GlobalInit() { setting.NewContext() highlight.NewContext() log.Trace("Custom path: %s", setting.CustomPath) log.Trace("Log path: %s", setting.LogRootPath) models.LoadConfigs() NewServices() if setting.InstallLock { models.LoadRepoConfig() models.NewRepoContext() if err := models.NewEngine(); err != nil { log.Fatal(4, "Fail to initialize ORM engine: %v", err) } models.HasEngine = true cron.NewContext() models.InitDeliverHooks() models.InitTestPullRequests() log.NewGitLogger(path.Join(setting.LogRootPath, "http.log")) } if models.EnableSQLite3 { log.Info("SQLite3 Supported") } if models.EnableTidb { log.Info("TiDB Supported") } if setting.SupportMiniWinService { log.Info("Builtin Windows Service Supported") } checkRunMode() if setting.SSH.StartBuiltinServer { ssh.Listen(setting.SSH.ListenPort) log.Info("SSH server started on :%v", setting.SSH.ListenPort) } // Build Sanitizer markdown.BuildSanitizer() }
func newSessionService() { SessionConfig.Provider = Cfg.Section("session").Key("PROVIDER").In("memory", []string{"memory", "file", "redis", "mysql"}) SessionConfig.ProviderConfig = strings.Trim(Cfg.Section("session").Key("PROVIDER_CONFIG").String(), "\" ") SessionConfig.CookieName = Cfg.Section("session").Key("COOKIE_NAME").MustString("i_like_gogits") SessionConfig.CookiePath = AppSubUrl SessionConfig.Secure = Cfg.Section("session").Key("COOKIE_SECURE").MustBool() SessionConfig.Gclifetime = Cfg.Section("session").Key("GC_INTERVAL_TIME").MustInt64(86400) SessionConfig.Maxlifetime = Cfg.Section("session").Key("SESSION_LIFE_TIME").MustInt64(86400) log.Info("Session Service Enabled") }
func newCacheService() { CacheAdapter = Cfg.Section("cache").Key("ADAPTER").In("memory", []string{"memory", "redis", "memcache"}) switch CacheAdapter { case "memory": CacheInternal = Cfg.Section("cache").Key("INTERVAL").MustInt(60) case "redis", "memcache": CacheConn = strings.Trim(Cfg.Section("cache").Key("HOST").String(), "\" ") default: log.Fatal(4, "Unknown cache adapter: %s", CacheAdapter) } log.Info("Cache Service Enabled") }
// Migrate database to current version func Migrate(x *xorm.Engine) error { if err := x.Sync(new(Version)); err != nil { return fmt.Errorf("sync: %v", err) } currentVersion := &Version{Id: 1} has, err := x.Get(currentVersion) if err != nil { return fmt.Errorf("get: %v", err) } else if !has { // If the version record does not exist we think // it is a fresh installation and we can skip all migrations. currentVersion.Version = int64(_MIN_DB_VER + len(migrations)) if _, err = x.InsertOne(currentVersion); err != nil { return fmt.Errorf("insert: %v", err) } } v := currentVersion.Version if _MIN_DB_VER > v { log.Fatal(4, `Gogs no longer supports auto-migration from your previously installed version. Please try to upgrade to a lower version (>= v0.6.0) first, then upgrade to current version.`) return nil } if int(v-_MIN_DB_VER) > len(migrations) { // User downgraded Gogs. currentVersion.Version = int64(len(migrations) + _MIN_DB_VER) _, err = x.Id(1).Update(currentVersion) return err } for i, m := range migrations[v-_MIN_DB_VER:] { log.Info("Migration: %s", m.Description()) if err = m.Migrate(x); err != nil { return fmt.Errorf("do migrate: %v", err) } currentVersion.Version = v + int64(i) + 1 if _, err = x.Id(1).Update(currentVersion); err != nil { return err } } return nil }
func newMailService() { sec := Cfg.Section("mailer") // Check mailer setting. if !sec.Key("ENABLED").MustBool() { return } MailService = &Mailer{ QueueLength: sec.Key("SEND_BUFFER_LEN").MustInt(100), Name: sec.Key("NAME").MustString(AppName), Host: sec.Key("HOST").String(), User: sec.Key("USER").String(), Passwd: sec.Key("PASSWD").String(), DisableHelo: sec.Key("DISABLE_HELO").MustBool(), HeloHostname: sec.Key("HELO_HOSTNAME").String(), SkipVerify: sec.Key("SKIP_VERIFY").MustBool(), UseCertificate: sec.Key("USE_CERTIFICATE").MustBool(), CertFile: sec.Key("CERT_FILE").String(), KeyFile: sec.Key("KEY_FILE").String(), } MailService.From = sec.Key("FROM").MustString(MailService.User) log.Info("Mail Service Enabled") }
func runWeb(ctx *cli.Context) { if ctx.IsSet("config") { setting.CustomConf = ctx.String("config") } routers.GlobalInit() checkVersion() m := newMacaron() reqSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: true}) ignSignIn := context.Toggle(&context.ToggleOptions{SignInRequired: setting.Service.RequireSignInView}) ignSignInAndCsrf := context.Toggle(&context.ToggleOptions{DisableCSRF: true}) reqSignOut := context.Toggle(&context.ToggleOptions{SignOutRequired: true}) bindIgnErr := binding.BindIgnErr // FIXME: not all routes need go through same middlewares. // Especially some AJAX requests, we can reduce middleware number to improve performance. // Routers. m.Get("/", ignSignIn, routers.Home) m.Group("/explore", func() { m.Get("", func(ctx *context.Context) { ctx.Redirect(setting.AppSubUrl + "/explore/repos") }) m.Get("/repos", routers.ExploreRepos) m.Get("/users", routers.ExploreUsers) }, ignSignIn) m.Combo("/install", routers.InstallInit).Get(routers.Install). Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost) m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues) // ***** START: User ***** m.Group("/user", func() { m.Get("/login", user.SignIn) m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost) m.Get("/sign_up", user.SignUp) m.Post("/sign_up", bindIgnErr(auth.RegisterForm{}), user.SignUpPost) m.Group("/oauth", func() { m.Get("/authorize", user.OauthAuthorize) m.Get("/redirect", user.OauthRedirect) }) m.Get("/reset_password", user.ResetPasswd) m.Post("/reset_password", user.ResetPasswdPost) }, reqSignOut) m.Group("/user/settings", func() { m.Get("", user.Settings) m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost) m.Post("/avatar", binding.MultipartForm(auth.UploadAvatarForm{}), user.SettingsAvatar) m.Post("/avatar/delete", user.SettingsDeleteAvatar) m.Combo("/email").Get(user.SettingsEmails). Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost) m.Post("/email/delete", user.DeleteEmail) m.Get("/password", user.SettingsPassword) m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost) m.Combo("/ssh").Get(user.SettingsSSHKeys). Post(bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost) m.Post("/ssh/delete", user.DeleteSSHKey) m.Combo("/applications").Get(user.SettingsApplications). Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost) m.Post("/applications/delete", user.SettingsDeleteApplication) m.Route("/delete", "GET,POST", user.SettingsDelete) }, reqSignIn, func(ctx *context.Context) { ctx.Data["PageIsUserSettings"] = true }) m.Group("/user", func() { // r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) m.Any("/activate", user.Activate) m.Any("/activate_email", user.ActivateEmail) m.Get("/email2user", user.Email2User) m.Get("/forget_password", user.ForgotPasswd) m.Post("/forget_password", user.ForgotPasswdPost) m.Get("/logout", user.SignOut) }) // ***** END: User ***** adminReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, AdminRequired: true}) // ***** START: Admin ***** m.Group("/admin", func() { m.Get("", adminReq, admin.Dashboard) m.Get("/config", admin.Config) m.Post("/config/test_mail", admin.SendTestMail) m.Get("/monitor", admin.Monitor) m.Group("/users", func() { m.Get("", admin.Users) m.Combo("/new").Get(admin.NewUser).Post(bindIgnErr(auth.AdminCrateUserForm{}), admin.NewUserPost) m.Combo("/:userid").Get(admin.EditUser).Post(bindIgnErr(auth.AdminEditUserForm{}), admin.EditUserPost) m.Post("/:userid/delete", admin.DeleteUser) }) m.Group("/orgs", func() { m.Get("", admin.Organizations) }) m.Group("/repos", func() { m.Get("", admin.Repos) m.Post("/delete", admin.DeleteRepo) }) m.Group("/auths", func() { m.Get("", admin.Authentications) m.Combo("/new").Get(admin.NewAuthSource).Post(bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost) m.Combo("/:authid").Get(admin.EditAuthSource). Post(bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost) m.Post("/:authid/delete", admin.DeleteAuthSource) }) m.Group("/notices", func() { m.Get("", admin.Notices) m.Post("/delete", admin.DeleteNotices) m.Get("/empty", admin.EmptyNotices) }) }, adminReq) // ***** END: Admin ***** m.Group("", func() { m.Group("/:username", func() { m.Get("", user.Profile) m.Get("/followers", user.Followers) m.Get("/following", user.Following) m.Get("/stars", user.Stars) }) m.Get("/attachments/:uuid", func(ctx *context.Context) { attach, err := models.GetAttachmentByUUID(ctx.Params(":uuid")) if err != nil { if models.IsErrAttachmentNotExist(err) { ctx.Error(404) } else { ctx.Handle(500, "GetAttachmentByUUID", err) } return } fr, err := os.Open(attach.LocalPath()) if err != nil { ctx.Handle(500, "Open", err) return } defer fr.Close() ctx.Header().Set("Cache-Control", "public,max-age=86400") // Fix #312. Attachments with , in their name are not handled correctly by Google Chrome. // We must put the name in " manually. if err = repo.ServeData(ctx, "\""+attach.Name+"\"", fr); err != nil { ctx.Handle(500, "ServeData", err) return } }) m.Post("/issues/attachments", repo.UploadIssueAttachment) }, ignSignIn) m.Group("/:username", func() { m.Get("/action/:action", user.Action) }, reqSignIn) if macaron.Env == macaron.DEV { m.Get("/template/*", dev.TemplatePreview) } reqRepoAdmin := context.RequireRepoAdmin() reqRepoWriter := context.RequireRepoWriter() // ***** START: Organization ***** m.Group("/org", func() { m.Get("/create", org.Create) m.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost) m.Group("/:org", func() { m.Get("/dashboard", user.Dashboard) m.Get("/^:type(issues|pulls)$", user.Issues) m.Get("/members", org.Members) m.Get("/members/action/:action", org.MembersAction) m.Get("/teams", org.Teams) }, context.OrgAssignment(true)) m.Group("/:org", func() { m.Get("/teams/:team", org.TeamMembers) m.Get("/teams/:team/repositories", org.TeamRepositories) m.Route("/teams/:team/action/:action", "GET,POST", org.TeamsAction) m.Route("/teams/:team/action/repo/:action", "GET,POST", org.TeamsRepoAction) }, context.OrgAssignment(true, false, true)) m.Group("/:org", func() { m.Get("/teams/new", org.NewTeam) m.Post("/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost) m.Get("/teams/:team/edit", org.EditTeam) m.Post("/teams/:team/edit", bindIgnErr(auth.CreateTeamForm{}), org.EditTeamPost) m.Post("/teams/:team/delete", org.DeleteTeam) m.Group("/settings", func() { m.Combo("").Get(org.Settings). Post(bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost) m.Post("/avatar", binding.MultipartForm(auth.UploadAvatarForm{}), org.SettingsAvatar) m.Post("/avatar/delete", org.SettingsDeleteAvatar) m.Group("/hooks", func() { m.Get("", org.Webhooks) m.Post("/delete", org.DeleteWebhook) m.Get("/:type/new", repo.WebhooksNew) m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Get("/:id", repo.WebHooksEdit) m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost) }) m.Route("/delete", "GET,POST", org.SettingsDelete) }) m.Route("/invitations/new", "GET,POST", org.Invitation) }, context.OrgAssignment(true, true)) }, reqSignIn) // ***** END: Organization ***** // ***** START: Repository ***** m.Group("/repo", func() { m.Get("/create", repo.Create) m.Post("/create", bindIgnErr(auth.CreateRepoForm{}), repo.CreatePost) m.Get("/migrate", repo.Migrate) m.Post("/migrate", bindIgnErr(auth.MigrateRepoForm{}), repo.MigratePost) m.Combo("/fork/:repoid").Get(repo.Fork). Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost) }, reqSignIn) m.Group("/:username/:reponame", func() { m.Group("/settings", func() { m.Combo("").Get(repo.Settings). Post(bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost) m.Group("/collaboration", func() { m.Combo("").Get(repo.Collaboration).Post(repo.CollaborationPost) m.Post("/access_mode", repo.ChangeCollaborationAccessMode) m.Post("/delete", repo.DeleteCollaboration) }) m.Group("/hooks", func() { m.Get("", repo.Webhooks) m.Post("/delete", repo.DeleteWebhook) m.Get("/:type/new", repo.WebhooksNew) m.Post("/gogs/new", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksNewPost) m.Post("/slack/new", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksNewPost) m.Get("/:id", repo.WebHooksEdit) m.Post("/:id/test", repo.TestWebhook) m.Post("/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) m.Post("/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost) m.Group("/git", func() { m.Get("", repo.GitHooks) m.Combo("/:name").Get(repo.GitHooksEdit). Post(repo.GitHooksEditPost) }, context.GitHookService()) }) m.Group("/keys", func() { m.Combo("").Get(repo.DeployKeys). Post(bindIgnErr(auth.AddSSHKeyForm{}), repo.DeployKeysPost) m.Post("/delete", repo.DeleteDeployKey) }) }, func(ctx *context.Context) { ctx.Data["PageIsSettings"] = true }) }, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef()) m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action) m.Group("/:username/:reponame", func() { m.Group("/issues", func() { m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue). Post(bindIgnErr(auth.CreateIssueForm{}), repo.NewIssuePost) m.Combo("/:index/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment) m.Group("/:index", func() { m.Post("/label", repo.UpdateIssueLabel) m.Post("/milestone", repo.UpdateIssueMilestone) m.Post("/assignee", repo.UpdateIssueAssignee) }, reqRepoWriter) m.Group("/:index", func() { m.Post("/title", repo.UpdateIssueTitle) m.Post("/content", repo.UpdateIssueContent) }) }) m.Post("/comments/:id", repo.UpdateCommentContent) m.Group("/labels", func() { m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel) m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel) m.Post("/delete", repo.DeleteLabel) }, reqRepoWriter, context.RepoRef()) m.Group("/milestones", func() { m.Combo("/new").Get(repo.NewMilestone). Post(bindIgnErr(auth.CreateMilestoneForm{}), repo.NewMilestonePost) m.Get("/:id/edit", repo.EditMilestone) m.Post("/:id/edit", bindIgnErr(auth.CreateMilestoneForm{}), repo.EditMilestonePost) m.Get("/:id/:action", repo.ChangeMilestonStatus) m.Post("/delete", repo.DeleteMilestone) }, reqRepoWriter, context.RepoRef()) m.Group("/releases", func() { m.Get("/new", repo.NewRelease) m.Post("/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost) m.Get("/edit/:tagname", repo.EditRelease) m.Post("/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost) m.Post("/delete", repo.DeleteRelease) }, reqRepoWriter, context.RepoRef()) m.Combo("/compare/*", repo.MustAllowPulls).Get(repo.CompareAndPullRequest). Post(bindIgnErr(auth.CreateIssueForm{}), repo.CompareAndPullRequestPost) }, reqSignIn, context.RepoAssignment(), repo.MustBeNotBare) m.Group("/:username/:reponame", func() { m.Group("", func() { m.Get("/releases", repo.Releases) m.Get("/^:type(issues|pulls)$", repo.RetrieveLabels, repo.Issues) m.Get("/^:type(issues|pulls)$/:index", repo.ViewIssue) m.Get("/labels/", repo.RetrieveLabels, repo.Labels) m.Get("/milestones", repo.Milestones) }, context.RepoRef()) // m.Get("/branches", repo.Branches) m.Group("/wiki", func() { m.Get("/?:page", repo.Wiki) m.Get("/_pages", repo.WikiPages) m.Group("", func() { m.Combo("/_new").Get(repo.NewWiki). Post(bindIgnErr(auth.NewWikiForm{}), repo.NewWikiPost) m.Combo("/:page/_edit").Get(repo.EditWiki). Post(bindIgnErr(auth.NewWikiForm{}), repo.EditWikiPost) m.Post("/:page/delete", repo.DeleteWikiPagePost) }, reqSignIn, reqRepoWriter) }, repo.MustEnableWiki, context.RepoRef()) m.Get("/archive/*", repo.Download) m.Group("/pulls/:index", func() { m.Get("/commits", context.RepoRef(), repo.ViewPullCommits) m.Get("/files", context.RepoRef(), repo.ViewPullFiles) m.Post("/merge", reqRepoWriter, repo.MergePullRequest) }, repo.MustAllowPulls) m.Group("", func() { m.Get("/src/*", repo.Home) m.Get("/raw/*", repo.SingleDownload) m.Get("/commits/*", repo.RefCommits) m.Get("/commit/:sha([a-z0-9]{40})$", repo.Diff) m.Get("/forks", repo.Forks) }, context.RepoRef()) m.Get("/commit/:sha([a-z0-9]{40})\\.:ext(patch|diff)", repo.RawDiff) m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.CompareDiff) }, ignSignIn, context.RepoAssignment(), repo.MustBeNotBare) m.Group("/:username/:reponame", func() { m.Get("/stars", repo.Stars) m.Get("/watchers", repo.Watchers) }, ignSignIn, context.RepoAssignment(), context.RepoRef()) m.Group("/:username", func() { m.Group("/:reponame", func() { m.Get("", repo.Home) m.Get("\\.git$", repo.Home) }, ignSignIn, context.RepoAssignment(true), context.RepoRef()) m.Group("/:reponame", func() { m.Any("/*", ignSignInAndCsrf, repo.HTTP) m.Head("/tasks/trigger", repo.TriggerTask) }) }) // ***** END: Repository ***** m.Group("/api", func() { apiv1.RegisterRoutes(m) }, ignSignIn) // robots.txt m.Get("/robots.txt", func(ctx *context.Context) { if setting.HasRobotsTxt { ctx.ServeFileContent(path.Join(setting.CustomPath, "robots.txt")) } else { ctx.Error(404) } }) // Not found handler. m.NotFound(routers.NotFound) // Flag for port number in case first time run conflict. if ctx.IsSet("port") { setting.AppUrl = strings.Replace(setting.AppUrl, setting.HttpPort, ctx.String("port"), 1) setting.HttpPort = ctx.String("port") } var err error 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: server := &http.Server{Addr: listenAddr, TLSConfig: &tls.Config{MinVersion: tls.VersionTLS10}, Handler: m} err = server.ListenAndServeTLS(setting.CertFile, setting.KeyFile) case setting.FCGI: err = fcgi.Serve(nil, m) default: log.Fatal(4, "Invalid protocol: %s", setting.Protocol) } if err != nil { log.Fatal(4, "Fail to start server: %v", err) } }
func newLogService() { log.Info("%s %s", AppName, AppVer) if len(BuildTime) > 0 { log.Info("Build Time: %s", BuildTime) log.Info("Build Git Hash: %s", BuildGitHash) } // Get and check log mode. LogModes = strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",") LogConfigs = make([]string, len(LogModes)) for i, mode := range LogModes { mode = strings.TrimSpace(mode) sec, err := Cfg.GetSection("log." + mode) if err != nil { log.Fatal(4, "Unknown log mode: %s", mode) } validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"} // Log level. levelName := Cfg.Section("log."+mode).Key("LEVEL").In( Cfg.Section("log").Key("LEVEL").In("Trace", validLevels), validLevels) level, ok := logLevels[levelName] if !ok { log.Fatal(4, "Unknown log level: %s", levelName) } // Generate log configuration. switch mode { case "console": LogConfigs[i] = fmt.Sprintf(`{"level":%s}`, level) case "file": logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "gogs.log")) if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil { panic(err.Error()) } LogConfigs[i] = fmt.Sprintf( `{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level, logPath, sec.Key("LOG_ROTATE").MustBool(true), sec.Key("MAX_LINES").MustInt(1000000), 1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)), sec.Key("DAILY_ROTATE").MustBool(true), sec.Key("MAX_DAYS").MustInt(7)) case "conn": LogConfigs[i] = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"}`, level, sec.Key("RECONNECT_ON_MSG").MustBool(), sec.Key("RECONNECT").MustBool(), sec.Key("PROTOCOL").In("tcp", []string{"tcp", "unix", "udp"}), sec.Key("ADDR").MustString(":7020")) case "smtp": LogConfigs[i] = fmt.Sprintf(`{"level":%s,"username":"******","password":"******","host":"%s","sendTos":"%s","subject":"%s"}`, level, sec.Key("USER").MustString("*****@*****.**"), sec.Key("PASSWD").MustString("******"), sec.Key("HOST").MustString("127.0.0.1:25"), sec.Key("RECEIVERS").MustString("[]"), sec.Key("SUBJECT").MustString("Diagnostic message from serve")) case "database": LogConfigs[i] = fmt.Sprintf(`{"level":%s,"driver":"%s","conn":"%s"}`, level, sec.Key("DRIVER").String(), sec.Key("CONN").String()) } log.NewLogger(Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000), mode, LogConfigs[i]) log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName) } }
func InstallPost(ctx *context.Context, form auth.InstallForm) { ctx.Data["CurDbOption"] = form.DbType if ctx.HasError() { if ctx.HasValue("Err_SMTPEmail") { ctx.Data["Err_SMTP"] = true } if ctx.HasValue("Err_AdminName") || ctx.HasValue("Err_AdminPasswd") || ctx.HasValue("Err_AdminEmail") { ctx.Data["Err_Admin"] = true } ctx.HTML(200, INSTALL) return } if _, err := exec.LookPath("git"); err != nil { ctx.RenderWithErr(ctx.Tr("install.test_git_failed", err), INSTALL, &form) return } // Pass basic check, now test configuration. // Test database setting. dbTypes := map[string]string{"MySQL": "mysql", "PostgreSQL": "postgres", "SQLite3": "sqlite3", "TiDB": "tidb"} models.DbCfg.Type = dbTypes[form.DbType] models.DbCfg.Host = form.DbHost models.DbCfg.User = form.DbUser models.DbCfg.Passwd = form.DbPasswd models.DbCfg.Name = form.DbName models.DbCfg.SSLMode = form.SSLMode models.DbCfg.Path = form.DbPath if (models.DbCfg.Type == "sqlite3" || models.DbCfg.Type == "tidb") && len(models.DbCfg.Path) == 0 { ctx.Data["Err_DbPath"] = true ctx.RenderWithErr(ctx.Tr("install.err_empty_db_path"), INSTALL, &form) return } else if models.DbCfg.Type == "tidb" && strings.ContainsAny(path.Base(models.DbCfg.Path), ".-") { ctx.Data["Err_DbPath"] = true ctx.RenderWithErr(ctx.Tr("install.err_invalid_tidb_name"), INSTALL, &form) return } // Set test engine. var x *xorm.Engine if err := models.NewTestEngine(x); err != nil { if strings.Contains(err.Error(), `Unknown database type: sqlite3`) { ctx.Data["Err_DbType"] = true ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "http://gogs.io/docs/installation/install_from_binary.html"), INSTALL, &form) } else { ctx.Data["Err_DbSetting"] = true ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), INSTALL, &form) } return } // Test repository root path. form.RepoRootPath = strings.Replace(form.RepoRootPath, "\\", "/", -1) if err := os.MkdirAll(form.RepoRootPath, os.ModePerm); err != nil { ctx.Data["Err_RepoRootPath"] = true ctx.RenderWithErr(ctx.Tr("install.invalid_repo_path", err), INSTALL, &form) return } // Test log root path. form.LogRootPath = strings.Replace(form.LogRootPath, "\\", "/", -1) if err := os.MkdirAll(form.LogRootPath, os.ModePerm); err != nil { ctx.Data["Err_LogRootPath"] = true ctx.RenderWithErr(ctx.Tr("install.invalid_log_root_path", err), INSTALL, &form) return } // Check run user. curUser := user.CurrentUsername() if form.RunUser != curUser { ctx.Data["Err_RunUser"] = true ctx.RenderWithErr(ctx.Tr("install.run_user_not_match", form.RunUser, curUser), INSTALL, &form) return } // Check logic loophole between disable self-registration and no admin account. if form.DisableRegistration && len(form.AdminName) == 0 { ctx.Data["Err_Services"] = true ctx.Data["Err_Admin"] = true ctx.RenderWithErr(ctx.Tr("install.no_admin_and_disable_registration"), INSTALL, form) return } // Check admin password. if len(form.AdminName) > 0 && len(form.AdminPasswd) == 0 { ctx.Data["Err_Admin"] = true ctx.Data["Err_AdminPasswd"] = true ctx.RenderWithErr(ctx.Tr("install.err_empty_admin_password"), INSTALL, form) return } if form.AdminPasswd != form.AdminConfirmPasswd { ctx.Data["Err_Admin"] = true ctx.Data["Err_AdminPasswd"] = true ctx.RenderWithErr(ctx.Tr("form.password_not_match"), INSTALL, form) return } if form.AppUrl[len(form.AppUrl)-1] != '/' { form.AppUrl += "/" } // Save settings. cfg := ini.Empty() if com.IsFile(setting.CustomConf) { // Keeps custom settings if there is already something. if err := cfg.Append(setting.CustomConf); err != nil { log.Error(4, "Fail to load custom conf '%s': %v", setting.CustomConf, err) } } cfg.Section("database").Key("DB_TYPE").SetValue(models.DbCfg.Type) cfg.Section("database").Key("HOST").SetValue(models.DbCfg.Host) cfg.Section("database").Key("NAME").SetValue(models.DbCfg.Name) cfg.Section("database").Key("USER").SetValue(models.DbCfg.User) cfg.Section("database").Key("PASSWD").SetValue(models.DbCfg.Passwd) cfg.Section("database").Key("SSL_MODE").SetValue(models.DbCfg.SSLMode) cfg.Section("database").Key("PATH").SetValue(models.DbCfg.Path) cfg.Section("").Key("APP_NAME").SetValue(form.AppName) cfg.Section("repository").Key("ROOT").SetValue(form.RepoRootPath) cfg.Section("").Key("RUN_USER").SetValue(form.RunUser) cfg.Section("server").Key("DOMAIN").SetValue(form.Domain) cfg.Section("server").Key("HTTP_PORT").SetValue(form.HTTPPort) cfg.Section("server").Key("ROOT_URL").SetValue(form.AppUrl) if form.SSHPort == 0 { cfg.Section("server").Key("DISABLE_SSH").SetValue("true") } else { cfg.Section("server").Key("DISABLE_SSH").SetValue("false") cfg.Section("server").Key("SSH_PORT").SetValue(com.ToStr(form.SSHPort)) } if len(strings.TrimSpace(form.SMTPHost)) > 0 { cfg.Section("mailer").Key("ENABLED").SetValue("true") cfg.Section("mailer").Key("HOST").SetValue(form.SMTPHost) cfg.Section("mailer").Key("FROM").SetValue(form.SMTPFrom) cfg.Section("mailer").Key("USER").SetValue(form.SMTPEmail) cfg.Section("mailer").Key("PASSWD").SetValue(form.SMTPPasswd) } else { cfg.Section("mailer").Key("ENABLED").SetValue("false") } cfg.Section("service").Key("REGISTER_EMAIL_CONFIRM").SetValue(com.ToStr(form.RegisterConfirm)) cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(com.ToStr(form.MailNotify)) cfg.Section("server").Key("OFFLINE_MODE").SetValue(com.ToStr(form.OfflineMode)) cfg.Section("picture").Key("DISABLE_GRAVATAR").SetValue(com.ToStr(form.DisableGravatar)) cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(com.ToStr(form.DisableRegistration)) cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(com.ToStr(form.EnableCaptcha)) cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(com.ToStr(form.RequireSignInView)) cfg.Section("").Key("RUN_MODE").SetValue("prod") cfg.Section("session").Key("PROVIDER").SetValue("file") cfg.Section("log").Key("MODE").SetValue("file") cfg.Section("log").Key("LEVEL").SetValue("Info") cfg.Section("log").Key("ROOT_PATH").SetValue(form.LogRootPath) cfg.Section("security").Key("INSTALL_LOCK").SetValue("true") cfg.Section("security").Key("SECRET_KEY").SetValue(base.GetRandomString(15)) os.MkdirAll(filepath.Dir(setting.CustomConf), os.ModePerm) if err := cfg.SaveTo(setting.CustomConf); err != nil { ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), INSTALL, &form) return } GlobalInit() // Create admin account if len(form.AdminName) > 0 { u := &models.User{ Name: form.AdminName, Email: form.AdminEmail, Passwd: form.AdminPasswd, IsAdmin: true, IsActive: true, } if err := models.CreateUser(u); err != nil { if !models.IsErrUserAlreadyExist(err) { setting.InstallLock = false ctx.Data["Err_AdminName"] = true ctx.Data["Err_AdminEmail"] = true ctx.RenderWithErr(ctx.Tr("install.invalid_admin_setting", err), INSTALL, &form) return } log.Info("Admin account already exist") u, _ = models.GetUserByName(u.Name) } // Auto-login for admin ctx.Session.Set("uid", u.Id) ctx.Session.Set("uname", u.Name) } log.Info("First-time run install finished!") ctx.Flash.Success(ctx.Tr("install.install_success")) ctx.Redirect(form.AppUrl + "user/login") }
func convertDateToUnix(x *xorm.Engine) (err error) { type Bean struct { ID int64 `xorm:"pk autoincr"` Created time.Time Updated time.Time Merged time.Time Deadline time.Time ClosedDate time.Time NextUpdate time.Time } var tables = []struct { name string cols []string bean interface{} }{ {"action", []string{"created"}, new(TAction)}, {"notice", []string{"created"}, new(TNotice)}, {"comment", []string{"created"}, new(TComment)}, {"issue", []string{"deadline", "created", "updated"}, new(TIssue)}, {"milestone", []string{"deadline", "closed_date"}, new(TMilestone)}, {"attachment", []string{"created"}, new(TAttachment)}, {"login_source", []string{"created", "updated"}, new(TLoginSource)}, {"pull_request", []string{"merged"}, new(TPull)}, {"release", []string{"created"}, new(TRelease)}, {"repository", []string{"created", "updated"}, new(TRepo)}, {"mirror", []string{"updated", "next_update"}, new(TMirror)}, {"public_key", []string{"created", "updated"}, new(TPublicKey)}, {"deploy_key", []string{"created", "updated"}, new(TDeployKey)}, {"access_token", []string{"created", "updated"}, new(TAccessToken)}, {"user", []string{"created", "updated"}, new(TUser)}, {"webhook", []string{"created", "updated"}, new(TWebhook)}, } for _, table := range tables { log.Info("Converting table: %s", table.name) if err = x.Sync2(table.bean); err != nil { return fmt.Errorf("Sync [table: %s]: %v", table.name, err) } offset := 0 for { beans := make([]*Bean, 0, 100) if err = x.Sql(fmt.Sprintf("SELECT * FROM `%s` ORDER BY id ASC LIMIT 100 OFFSET %d", table.name, offset)).Find(&beans); err != nil { return fmt.Errorf("select beans [table: %s, offset: %d]: %v", table.name, offset, err) } log.Trace("Table [%s]: offset: %d, beans: %d", table.name, offset, len(beans)) if len(beans) == 0 { break } offset += 100 baseSQL := "UPDATE `" + table.name + "` SET " for _, bean := range beans { valSQLs := make([]string, 0, len(table.cols)) for _, col := range table.cols { fieldSQL := "" fieldSQL += col + "_unix = " switch col { case "deadline": if bean.Deadline.IsZero() { continue } fieldSQL += com.ToStr(bean.Deadline.UTC().Unix()) case "created": fieldSQL += com.ToStr(bean.Created.UTC().Unix()) case "updated": fieldSQL += com.ToStr(bean.Updated.UTC().Unix()) case "closed_date": fieldSQL += com.ToStr(bean.ClosedDate.UTC().Unix()) case "merged": fieldSQL += com.ToStr(bean.Merged.UTC().Unix()) case "next_update": fieldSQL += com.ToStr(bean.NextUpdate.UTC().Unix()) } valSQLs = append(valSQLs, fieldSQL) } if len(valSQLs) == 0 { continue } if _, err = x.Exec(baseSQL + strings.Join(valSQLs, ",") + " WHERE id = " + com.ToStr(bean.ID)); err != nil { return fmt.Errorf("update bean [table: %s, id: %d]: %v", table.name, bean.ID, err) } } } } return nil }