From 9f9cd6bfc61d82ee0a3d31cee112be7975b8ca86 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 20 Mar 2014 07:50:26 -0400 Subject: Work on admin --- routers/admin/admin.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 routers/admin/admin.go (limited to 'routers/admin/admin.go') diff --git a/routers/admin/admin.go b/routers/admin/admin.go new file mode 100644 index 00000000..c7523b7f --- /dev/null +++ b/routers/admin/admin.go @@ -0,0 +1,24 @@ +// Copyright 2014 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package admin + +import ( + "github.com/gogits/gogs/modules/middleware" +) + +func Dashboard(ctx *middleware.Context) { + ctx.Data["Title"] = "Admin Dashboard" + ctx.HTML(200, "admin/dashboard") +} + +func Users(ctx *middleware.Context) { + ctx.Data["Title"] = "User Management" + ctx.HTML(200, "admin/users") +} + +func Repositories(ctx *middleware.Context) { + ctx.Data["Title"] = "Repository Management" + ctx.HTML(200, "admin/repos") +} -- cgit v1.2.3 From 06631ab91f5d84b48d6f71ac8eaf4df740ba0282 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 20 Mar 2014 16:04:56 -0400 Subject: Basic admin data table, models changes --- README.md | 2 +- gogs.go | 8 +- models/issue.go | 19 ++++ models/models.go | 56 ++++------- models/publickey.go | 10 +- models/repo.go | 216 +++++++++++++++++++++-------------------- models/user.go | 97 +++++++++--------- modules/base/conf.go | 21 ++-- routers/admin/admin.go | 15 +++ serve.go | 4 +- templates/admin/dashboard.tmpl | 2 +- templates/admin/repos.tmpl | 24 +++++ templates/admin/users.tmpl | 26 +++++ 13 files changed, 291 insertions(+), 209 deletions(-) create mode 100644 models/issue.go (limited to 'routers/admin/admin.go') diff --git a/README.md b/README.md index 4219e4ed..8c971fdb 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ There are some very good products in this category such as [gitlab](http://gitla - Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, develop specification, change log and road map. - See [Trello Broad](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team. -- Try it before anything? Go down to **Installation -> Install from binary** section!. +- Try it before anything? Do it [online](http://try.gogits.org/Unknown/gogs) or go down to **Installation -> Install from binary** section! - Having troubles? Get help from [Troubleshooting](https://github.com/gogits/gogs/wiki/Troubleshooting). ## Features diff --git a/gogs.go b/gogs.go index a600c53d..a9f7e6b5 100644 --- a/gogs.go +++ b/gogs.go @@ -15,12 +15,12 @@ import ( "github.com/gogits/gogs/modules/base" ) -// +build go1.1 +// +build go1.2 -// Test that go1.1 tag above is included in builds. main.go refers to this definition. -const go11tag = true +// Test that go1.2 tag above is included in builds. main.go refers to this definition. +const go12tag = true -const APP_VER = "0.1.3.0320.1" +const APP_VER = "0.1.4.0321" func init() { base.AppVer = APP_VER diff --git a/models/issue.go b/models/issue.go new file mode 100644 index 00000000..c669d201 --- /dev/null +++ b/models/issue.go @@ -0,0 +1,19 @@ +// Copyright 2014 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +type Issue struct { + Id int64 + RepoId int64 `xorm:"index"` + PosterId int64 +} + +type PullRequest struct { + Id int64 +} + +type Comment struct { + Id int64 +} diff --git a/models/models.go b/models/models.go index 2e0bb759..214d1c76 100644 --- a/models/models.go +++ b/models/models.go @@ -15,30 +15,7 @@ import ( "github.com/gogits/gogs/modules/base" ) -var ( - orm *xorm.Engine - RepoRootPath string -) - -type Members struct { - Id int64 - OrgId int64 `xorm:"unique(s) index"` - UserId int64 `xorm:"unique(s)"` -} - -type Issue struct { - Id int64 - RepoId int64 `xorm:"index"` - PosterId int64 -} - -type PullRequest struct { - Id int64 -} - -type Comment struct { - Id int64 -} +var orm *xorm.Engine func setEngine() { dbType := base.Cfg.MustValue("database", "DB_TYPE") @@ -65,8 +42,8 @@ func setEngine() { os.Exit(2) } - // TODO: for serv command, MUST remove the output to os.stdout, so - // use log file to instead print to stdout + // WARNNING: for serv command, MUST remove the output to os.stdout, + // so use log file to instead print to stdout. //x.ShowDebug = true //orm.ShowErr = true @@ -77,20 +54,29 @@ func setEngine() { } orm.Logger = f orm.ShowSQL = true - - // Determine and create root git reposiroty path. - RepoRootPath = base.Cfg.MustValue("repository", "ROOT") - if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil { - fmt.Printf("models.init(fail to create RepoRootPath(%s)): %v\n", RepoRootPath, err) - os.Exit(2) - } } func init() { setEngine() - if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Access), - new(Action), new(Watch)); err != nil { + if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch), + new(Action), new(Access)); err != nil { fmt.Printf("sync database struct error: %v\n", err) os.Exit(2) } } + +type Statistic struct { + Counter struct { + User, PublicKey, Repo, Watch, Action, Access int64 + } +} + +func GetStatistic() (stats Statistic) { + stats.Counter.User, _ = orm.Count(new(User)) + stats.Counter.PublicKey, _ = orm.Count(new(PublicKey)) + stats.Counter.Repo, _ = orm.Count(new(Repository)) + stats.Counter.Watch, _ = orm.Count(new(Watch)) + stats.Counter.Action, _ = orm.Count(new(Action)) + stats.Counter.Access, _ = orm.Count(new(Access)) + return stats +} diff --git a/models/publickey.go b/models/publickey.go index 092436d5..c69bca68 100644 --- a/models/publickey.go +++ b/models/publickey.go @@ -27,8 +27,12 @@ const ( ) var ( - sshOpLocker = sync.Mutex{} + ErrKeyAlreadyExist = errors.New("Public key already exist") +) +var sshOpLocker = sync.Mutex{} + +var ( sshPath string appPath string ) @@ -79,10 +83,6 @@ type PublicKey struct { Updated time.Time `xorm:"updated"` } -var ( - ErrKeyAlreadyExist = errors.New("Public key already exist") -) - // GenAuthorizedKey returns formatted public key string. func GenAuthorizedKey(keyId int64, key string) string { return fmt.Sprintf(TPL_PUBLICK_KEY+"\n", appPath, keyId, key) diff --git a/models/repo.go b/models/repo.go index bcbc5867..f7173d76 100644 --- a/models/repo.go +++ b/models/repo.go @@ -27,63 +27,18 @@ import ( "github.com/gogits/gogs/modules/log" ) -// Repository represents a git repository. -type Repository struct { - Id int64 - OwnerId int64 `xorm:"unique(s)"` - ForkId int64 - LowerName string `xorm:"unique(s) index not null"` - Name string `xorm:"index not null"` - Description string - Website string - Private bool - NumWatchs int - NumStars int - NumForks int - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` -} - -// Watch is connection request for receiving repository notifycation. -type Watch struct { - Id int64 - RepoId int64 `xorm:"UNIQUE(watch)"` - UserId int64 `xorm:"UNIQUE(watch)"` -} - -// Watch or unwatch repository. -func WatchRepo(userId, repoId int64, watch bool) (err error) { - if watch { - _, err = orm.Insert(&Watch{RepoId: repoId, UserId: userId}) - } else { - _, err = orm.Delete(&Watch{0, repoId, userId}) - } - return err -} - -// GetWatches returns all watches of given repository. -func GetWatches(repoId int64) ([]Watch, error) { - watches := make([]Watch, 0, 10) - err := orm.Find(&watches, &Watch{RepoId: repoId}) - return watches, err -} - -// IsWatching checks if user has watched given repository. -func IsWatching(userId, repoId int64) bool { - has, _ := orm.Get(&Watch{0, repoId, userId}) - return has -} - var ( - gitInitLocker = sync.Mutex{} - LanguageIgns, Licenses []string + ErrRepoAlreadyExist = errors.New("Repository already exist") + ErrRepoNotExist = errors.New("Repository does not exist") + ErrRepoFileNotExist = errors.New("Target Repo file does not exist") + ErrRepoNameIllegal = errors.New("Repository name contains illegal characters") + ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded") ) +var gitInitLocker = sync.Mutex{} + var ( - ErrRepoAlreadyExist = errors.New("Repository already exist") - ErrRepoNotExist = errors.New("Repository does not exist") - ErrRepoFileNotExist = errors.New("Target Repo file does not exist") - ErrRepoNameIllegal = errors.New("Repository name contains illegal characters") + LanguageIgns, Licenses []string ) func init() { @@ -117,6 +72,23 @@ func init() { } } +// Repository represents a git repository. +type Repository struct { + Id int64 + OwnerId int64 `xorm:"unique(s)"` + ForkId int64 + LowerName string `xorm:"unique(s) index not null"` + Name string `xorm:"index not null"` + Description string + Website string + Private bool + NumWatches int + NumStars int + NumForks int + Created time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` +} + // IsRepositoryExist returns true if the repository with given name under user has already existed. func IsRepositoryExist(user *User, repoName string) (bool, error) { repo := Repository{OwnerId: user.Id} @@ -351,6 +323,60 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep return nil } +// GetRepos returns given number of repository objects with offset. +func GetRepos(num, offset int) ([]Repository, error) { + repos := make([]Repository, 0, num) + err := orm.Limit(num, offset).Asc("id").Find(&repos) + return repos, err +} + +func RepoPath(userName, repoName string) string { + return filepath.Join(UserPath(userName), repoName+".git") +} + +// DeleteRepository deletes a repository for a user or orgnaztion. +func DeleteRepository(userId, repoId int64, userName string) (err error) { + repo := &Repository{Id: repoId, OwnerId: userId} + has, err := orm.Get(repo) + if err != nil { + return err + } else if !has { + return ErrRepoNotExist + } + + session := orm.NewSession() + if err = session.Begin(); err != nil { + return err + } + if _, err = session.Delete(&Repository{Id: repoId}); err != nil { + session.Rollback() + return err + } + if _, err := session.Delete(&Access{UserName: userName, RepoName: repo.Name}); err != nil { + session.Rollback() + return err + } + rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?" + if _, err = session.Exec(rawSql, userId); err != nil { + session.Rollback() + return err + } + if _, err = session.Delete(&Watch{RepoId: repoId}); err != nil { + session.Rollback() + return err + } + if err = session.Commit(); err != nil { + session.Rollback() + return err + } + if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { + // TODO: log and delete manully + log.Error("delete repo %s/%s failed: %v", userName, repo.Name, err) + return err + } + return nil +} + // GetRepositoryByName returns the repository by given name under user if exists. func GetRepositoryByName(user *User, repoName string) (*Repository, error) { repo := &Repository{ @@ -388,6 +414,36 @@ func GetRepositoryCount(user *User) (int64, error) { return orm.Count(&Repository{OwnerId: user.Id}) } +// Watch is connection request for receiving repository notifycation. +type Watch struct { + Id int64 + RepoId int64 `xorm:"UNIQUE(watch)"` + UserId int64 `xorm:"UNIQUE(watch)"` +} + +// Watch or unwatch repository. +func WatchRepo(userId, repoId int64, watch bool) (err error) { + if watch { + _, err = orm.Insert(&Watch{RepoId: repoId, UserId: userId}) + } else { + _, err = orm.Delete(&Watch{0, repoId, userId}) + } + return err +} + +// GetWatches returns all watches of given repository. +func GetWatches(repoId int64) ([]Watch, error) { + watches := make([]Watch, 0, 10) + err := orm.Find(&watches, &Watch{RepoId: repoId}) + return watches, err +} + +// IsWatching checks if user has watched given repository. +func IsWatching(userId, repoId int64) bool { + has, _ := orm.Get(&Watch{0, repoId, userId}) + return has +} + func StarReposiory(user *User, repoName string) error { return nil } @@ -408,60 +464,6 @@ func ForkRepository(reposName string, userId int64) { } -func RepoPath(userName, repoName string) string { - return filepath.Join(UserPath(userName), repoName+".git") -} - -// DeleteRepository deletes a repository for a user or orgnaztion. -func DeleteRepository(userId, repoId int64, userName string) (err error) { - repo := &Repository{Id: repoId, OwnerId: userId} - has, err := orm.Get(repo) - if err != nil { - return err - } else if !has { - return ErrRepoNotExist - } - - session := orm.NewSession() - if err = session.Begin(); err != nil { - return err - } - if _, err = session.Delete(&Repository{Id: repoId}); err != nil { - session.Rollback() - return err - } - if _, err := session.Delete(&Access{UserName: userName, RepoName: repo.Name}); err != nil { - session.Rollback() - return err - } - rawSql := "UPDATE user SET num_repos = num_repos - 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_repos = num_repos - 1 WHERE id = ?" - } - if _, err = session.Exec(rawSql, userId); err != nil { - session.Rollback() - return err - } - if _, err = session.Delete(&Watch{RepoId: repoId}); err != nil { - session.Rollback() - return err - } - if err = session.Commit(); err != nil { - session.Rollback() - return err - } - if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { - // TODO: log and delete manully - log.Error("delete repo %s/%s failed: %v", userName, repo.Name, err) - return err - } - return nil -} - -var ( - ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded") -) - // RepoFile represents a file object in git repository. type RepoFile struct { *git.TreeEntry diff --git a/models/user.go b/models/user.go index 990e1954..3c110912 100644 --- a/models/user.go +++ b/models/user.go @@ -33,6 +33,14 @@ const ( LT_LDAP ) +var ( + ErrUserOwnRepos = errors.New("User still have ownership of repositories") + ErrUserAlreadyExist = errors.New("User already exist") + ErrUserNotExist = errors.New("User does not exist") + ErrEmailAlreadyUsed = errors.New("E-mail already used") + ErrUserNameIllegal = errors.New("User name contains illegal characters") +) + // User represents the object of individual and member of organization. type User struct { Id int64 @@ -67,20 +75,28 @@ func (user *User) AvatarLink() string { return "http://1.gravatar.com/avatar/" + user.Avatar } -type Follow struct { - Id int64 - UserId int64 `xorm:"unique(s)"` - FollowId int64 `xorm:"unique(s)"` - Created time.Time `xorm:"created"` +// NewGitSig generates and returns the signature of given user. +func (user *User) NewGitSig() *git.Signature { + return &git.Signature{ + Name: user.Name, + Email: user.Email, + When: time.Now(), + } } -var ( - ErrUserOwnRepos = errors.New("User still have ownership of repositories") - ErrUserAlreadyExist = errors.New("User already exist") - ErrUserNotExist = errors.New("User does not exist") - ErrEmailAlreadyUsed = errors.New("E-mail already used") - ErrUserNameIllegal = errors.New("User name contains illegal characters") -) +// EncodePasswd encodes password to safe format. +func (user *User) EncodePasswd() error { + newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64) + user.Passwd = fmt.Sprintf("%x", newPasswd) + return err +} + +// Member represents user is member of organization. +type Member struct { + Id int64 + OrgId int64 `xorm:"unique(member) index"` + UserId int64 `xorm:"unique(member)"` +} // IsUserExist checks if given user name exist, // the user name should be noncased unique. @@ -93,15 +109,6 @@ func IsEmailUsed(email string) (bool, error) { return orm.Get(&User{Email: email}) } -// NewGitSig generates and returns the signature of given user. -func (user *User) NewGitSig() *git.Signature { - return &git.Signature{ - Name: user.Name, - Email: user.Email, - When: time.Now(), - } -} - // return a user salt token func GetUserSalt() string { return base.GetRandomString(10) @@ -151,6 +158,13 @@ func RegisterUser(user *User) (*User, error) { return user, err } +// GetUsers returns given number of user objects with offset. +func GetUsers(num, offset int) ([]User, error) { + users := make([]User, 0, num) + err := orm.Limit(num, offset).Asc("id").Find(&users) + return users, err +} + // get user by erify code func getVerifyUser(code string) (user *User) { if len(code) <= base.TimeLimitCodeLength { @@ -229,24 +243,14 @@ func DeleteUser(user *User) error { return err } -// EncodePasswd encodes password to safe format. -func (user *User) EncodePasswd() error { - newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64) - user.Passwd = fmt.Sprintf("%x", newPasswd) - return err -} - // UserPath returns the path absolute path of user repositories. func UserPath(userName string) string { - return filepath.Join(RepoRootPath, strings.ToLower(userName)) + return filepath.Join(base.RepoRootPath, strings.ToLower(userName)) } func GetUserByKeyId(keyId int64) (*User, error) { user := new(User) - rawSql := "SELECT a.* FROM user AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "SELECT a.* FROM \"user\" AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?" - } + rawSql := "SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?" has, err := orm.Sql(rawSql, keyId).Get(user) if err != nil { return nil, err @@ -303,6 +307,13 @@ func LoginUserPlain(name, passwd string) (*User, error) { return &user, err } +// Follow is connection request for receiving user notifycation. +type Follow struct { + Id int64 + UserId int64 `xorm:"unique(follow)"` + FollowId int64 `xorm:"unique(follow)"` +} + // FollowUser marks someone be another's follower. func FollowUser(userId int64, followId int64) (err error) { session := orm.NewSession() @@ -314,19 +325,13 @@ func FollowUser(userId int64, followId int64) (err error) { return err } - rawSql := "UPDATE user SET num_followers = num_followers + 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_followers = num_followers + 1 WHERE id = ?" - } + rawSql := "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?" if _, err = session.Exec(rawSql, followId); err != nil { session.Rollback() return err } - rawSql = "UPDATE user SET num_followings = num_followings + 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_followings = num_followings + 1 WHERE id = ?" - } + rawSql = "UPDATE `user` SET num_followings = num_followings + 1 WHERE id = ?" if _, err = session.Exec(rawSql, userId); err != nil { session.Rollback() return err @@ -345,19 +350,13 @@ func UnFollowUser(userId int64, unFollowId int64) (err error) { return err } - rawSql := "UPDATE user SET num_followers = num_followers - 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_followers = num_followers - 1 WHERE id = ?" - } + rawSql := "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?" if _, err = session.Exec(rawSql, unFollowId); err != nil { session.Rollback() return err } - rawSql = "UPDATE user SET num_followings = num_followings - 1 WHERE id = ?" - if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" { - rawSql = "UPDATE \"user\" SET num_followings = num_followings - 1 WHERE id = ?" - } + rawSql = "UPDATE `user` SET num_followings = num_followings - 1 WHERE id = ?" if _, err = session.Exec(rawSql, userId); err != nil { session.Rollback() return err diff --git a/modules/base/conf.go b/modules/base/conf.go index fdbf3ad3..81f32bd5 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -26,12 +26,14 @@ type Mailer struct { } var ( - AppVer string - AppName string - AppLogo string - AppUrl string - Domain string - SecretKey string + AppVer string + AppName string + AppLogo string + AppUrl string + Domain string + SecretKey string + RepoRootPath string + Cfg *goconfig.ConfigFile MailService *Mailer ) @@ -173,6 +175,13 @@ func init() { AppUrl = Cfg.MustValue("server", "ROOT_URL") Domain = Cfg.MustValue("server", "DOMAIN") SecretKey = Cfg.MustValue("security", "SECRET_KEY") + + // Determine and create root git reposiroty path. + RepoRootPath = Cfg.MustValue("repository", "ROOT") + if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil { + fmt.Printf("models.init(fail to create RepoRootPath(%s)): %v\n", RepoRootPath, err) + os.Exit(2) + } } func NewServices() { diff --git a/routers/admin/admin.go b/routers/admin/admin.go index c7523b7f..a37f1207 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -5,20 +5,35 @@ package admin import ( + "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/middleware" ) func Dashboard(ctx *middleware.Context) { ctx.Data["Title"] = "Admin Dashboard" + ctx.Data["Stats"] = models.GetStatistic() ctx.HTML(200, "admin/dashboard") } func Users(ctx *middleware.Context) { ctx.Data["Title"] = "User Management" + + var err error + ctx.Data["Users"], err = models.GetUsers(100, 0) + if err != nil { + ctx.Handle(200, "admin.Users", err) + return + } ctx.HTML(200, "admin/users") } func Repositories(ctx *middleware.Context) { ctx.Data["Title"] = "Repository Management" + var err error + ctx.Data["Repos"], err = models.GetRepos(100, 0) + if err != nil { + ctx.Handle(200, "admin.Repositories", err) + return + } ctx.HTML(200, "admin/repos") } diff --git a/serve.go b/serve.go index ddc67023..2a17a334 100644 --- a/serve.go +++ b/serve.go @@ -12,7 +12,9 @@ import ( "strings" "github.com/codegangsta/cli" + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/base" ) var ( @@ -144,7 +146,7 @@ func runServ(*cli.Context) { } gitcmd := exec.Command(verb, rRepo) - gitcmd.Dir = models.RepoRootPath + gitcmd.Dir = base.RepoRootPath gitcmd.Stdout = os.Stdout gitcmd.Stdin = os.Stdin gitcmd.Stderr = os.Stderr diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 84456c85..6a914b65 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -16,7 +16,7 @@
- Gogs database has 4 users, 3 repositories, 4 SSH keys. + Gogs database has {{.Stats.Counter.User}} users, {{.Stats.Counter.PublicKey}} SSH keys, {{.Stats.Counter.Repo}} repositories, {{.Stats.Counter.Watch}} watches, {{.Stats.Counter.Action}} actions, and {{.Stats.Counter.Access}} accesses.
diff --git a/templates/admin/repos.tmpl b/templates/admin/repos.tmpl index ec7f47e0..4522c667 100644 --- a/templates/admin/repos.tmpl +++ b/templates/admin/repos.tmpl @@ -16,6 +16,30 @@
+ + + + + + + + + + + + + {{range .Repos}} + + + + + + + + + {{end}} + +
IdNamePrivateWatchesForksCreated
{{.Id}}{{.Name}}{{.NumWatches}}{{.NumForks}}{{DateFormat .Created "M d, Y"}}
diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl index 8acf256d..c087f268 100644 --- a/templates/admin/users.tmpl +++ b/templates/admin/users.tmpl @@ -16,6 +16,32 @@
+ + + + + + + + + + + + + + {{range .Users}} + + + + + + + + + + {{end}} + +
IdNameE-mailActivedAdminReposJoin
{{.Id}}{{.Name}}{{.Email}}{{.NumRepos}}{{DateFormat .Created "M d, Y"}}
-- cgit v1.2.3 From f6596f11c4aacd3c7c30098f7ffe79e936d21583 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 01:48:10 -0400 Subject: All configuration reload-able --- README.md | 1 + models/models.go | 39 ++++++++++++++++++++++++--------------- models/models_test.go | 3 +++ models/repo.go | 4 +++- modules/base/conf.go | 2 +- modules/mailer/mailer.go | 2 +- routers/admin/admin.go | 10 ++++++++++ templates/admin/config.tmpl | 17 +++++++++++++++++ templates/admin/dashboard.tmpl | 9 +-------- templates/admin/nav.tmpl | 8 ++++++++ templates/admin/repos.tmpl | 9 +-------- templates/admin/users.tmpl | 9 +-------- web.go | 20 +++++++++++++++++--- 13 files changed, 88 insertions(+), 45 deletions(-) create mode 100644 templates/admin/config.tmpl create mode 100644 templates/admin/nav.tmpl (limited to 'routers/admin/admin.go') diff --git a/README.md b/README.md index 3668ae89..e78ce8fe 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ There are some very good products in this category such as [gitlab](http://gitla - Repository viewer. - Gravatar support. - Mail service(register). +- Administration panel. - Supports MySQL, PostgreSQL and SQLite3(binary release only). ## Installation diff --git a/models/models.go b/models/models.go index 8df23097..bb0015d3 100644 --- a/models/models.go +++ b/models/models.go @@ -16,30 +16,39 @@ import ( "github.com/gogits/gogs/modules/base" ) -var orm *xorm.Engine +var ( + orm *xorm.Engine + + dbCfg struct { + Type, Host, Name, User, Pwd, Path, SslMode string + } +) + +func LoadModelsConfig() { + dbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE") + dbCfg.Host = base.Cfg.MustValue("database", "HOST") + dbCfg.Name = base.Cfg.MustValue("database", "NAME") + dbCfg.User = base.Cfg.MustValue("database", "USER") + dbCfg.Pwd = base.Cfg.MustValue("database", "PASSWD") + dbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db") + dbCfg.SslMode = base.Cfg.MustValue("database", "SSL_MODE") +} func setEngine() { - dbType := base.Cfg.MustValue("database", "DB_TYPE") - dbHost := base.Cfg.MustValue("database", "HOST") - dbName := base.Cfg.MustValue("database", "NAME") - dbUser := base.Cfg.MustValue("database", "USER") - dbPwd := base.Cfg.MustValue("database", "PASSWD") - dbPath := base.Cfg.MustValue("database", "PATH", "data/gogs.db") - sslMode := base.Cfg.MustValue("database", "SSL_MODE") var err error - switch dbType { + switch dbCfg.Type { case "mysql": orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@%s/%s?charset=utf8", - dbUser, dbPwd, dbHost, dbName)) + dbCfg.User, dbCfg.Pwd, dbCfg.Host, dbCfg.Name)) case "postgres": orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", - dbUser, dbPwd, dbName, sslMode)) + dbCfg.User, dbCfg.Pwd, dbCfg.Name, dbCfg.SslMode)) case "sqlite3": - os.MkdirAll(path.Dir(dbPath), os.ModePerm) - orm, err = xorm.NewEngine("sqlite3", dbPath) + os.MkdirAll(path.Dir(dbCfg.Path), os.ModePerm) + orm, err = xorm.NewEngine("sqlite3", dbCfg.Path) default: - fmt.Printf("Unknown database type: %s\n", dbType) + fmt.Printf("Unknown database type: %s\n", dbCfg.Type) os.Exit(2) } if err != nil { @@ -61,7 +70,7 @@ func setEngine() { orm.ShowSQL = true } -func init() { +func NewEngine() { setEngine() if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch), new(Action), new(Access)); err != nil { diff --git a/models/models_test.go b/models/models_test.go index c44ef476..d0f734d6 100644 --- a/models/models_test.go +++ b/models/models_test.go @@ -13,6 +13,9 @@ import ( ) func init() { + LoadModelsConfig() + NewEngine() + var err error orm, err = xorm.NewEngine("sqlite3", "./test.db") if err != nil { diff --git a/models/repo.go b/models/repo.go index 93f68ced..f2520047 100644 --- a/models/repo.go +++ b/models/repo.go @@ -41,10 +41,12 @@ var ( LanguageIgns, Licenses []string ) -func init() { +func LoadRepoConfig() { LanguageIgns = strings.Split(base.Cfg.MustValue("repository", "LANG_IGNS"), "|") Licenses = strings.Split(base.Cfg.MustValue("repository", "LICENSES"), "|") +} +func NewRepoContext() { zip.Verbose = false // Check if server has basic git setting. diff --git a/modules/base/conf.go b/modules/base/conf.go index 41b66b69..42d50da4 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -148,7 +148,7 @@ func newRegisterMailService() { log.Info("Register Mail Service Enabled") } -func init() { +func NewConfigContext() { var err error workDir, err := exeDir() if err != nil { diff --git a/modules/mailer/mailer.go b/modules/mailer/mailer.go index 150607f8..da63e01d 100644 --- a/modules/mailer/mailer.go +++ b/modules/mailer/mailer.go @@ -40,7 +40,7 @@ func (m Message) Content() string { var mailQueue chan *Message -func init() { +func NewMailerContext() { mailQueue = make(chan *Message, base.Cfg.MustInt("mailer", "SEND_BUFFER_LEN", 10)) go processMailQueue() } diff --git a/routers/admin/admin.go b/routers/admin/admin.go index a37f1207..1095a599 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -11,12 +11,14 @@ import ( func Dashboard(ctx *middleware.Context) { ctx.Data["Title"] = "Admin Dashboard" + ctx.Data["PageIsDashboard"] = true ctx.Data["Stats"] = models.GetStatistic() ctx.HTML(200, "admin/dashboard") } func Users(ctx *middleware.Context) { ctx.Data["Title"] = "User Management" + ctx.Data["PageIsUsers"] = true var err error ctx.Data["Users"], err = models.GetUsers(100, 0) @@ -29,6 +31,8 @@ func Users(ctx *middleware.Context) { func Repositories(ctx *middleware.Context) { ctx.Data["Title"] = "Repository Management" + ctx.Data["PageIsRepos"] = true + var err error ctx.Data["Repos"], err = models.GetRepos(100, 0) if err != nil { @@ -37,3 +41,9 @@ func Repositories(ctx *middleware.Context) { } ctx.HTML(200, "admin/repos") } + +func Config(ctx *middleware.Context) { + ctx.Data["Title"] = "Server Configuration" + ctx.Data["PageIsConfig"] = true + ctx.HTML(200, "admin/config") +} diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl new file mode 100644 index 00000000..d209bcdf --- /dev/null +++ b/templates/admin/config.tmpl @@ -0,0 +1,17 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
+ {{template "admin/nav" .}} +
+
+
+ Server Configuration +
+ +
+ +
+
+
+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 6a914b65..8950f50c 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -1,14 +1,7 @@ {{template "base/head" .}} {{template "base/navbar" .}}
- - + {{template "admin/nav" .}}
diff --git a/templates/admin/nav.tmpl b/templates/admin/nav.tmpl new file mode 100644 index 00000000..bb704ee3 --- /dev/null +++ b/templates/admin/nav.tmpl @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/templates/admin/repos.tmpl b/templates/admin/repos.tmpl index f4834c90..a1f41d83 100644 --- a/templates/admin/repos.tmpl +++ b/templates/admin/repos.tmpl @@ -1,14 +1,7 @@ {{template "base/head" .}} {{template "base/navbar" .}}
- - + {{template "admin/nav" .}}
diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl index b690e177..ae2b5bbb 100644 --- a/templates/admin/users.tmpl +++ b/templates/admin/users.tmpl @@ -1,14 +1,7 @@ {{template "base/head" .}} {{template "base/navbar" .}}
- - + {{template "admin/nav" .}}
diff --git a/web.go b/web.go index a5a8305a..648cb9d7 100644 --- a/web.go +++ b/web.go @@ -16,9 +16,11 @@ import ( "github.com/gogits/binding" + "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/log" + "github.com/gogits/gogs/modules/mailer" "github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/routers" "github.com/gogits/gogs/routers/admin" @@ -36,6 +38,16 @@ gogs web`, Flags: []cli.Flag{}, } +// globalInit is for global configuration reload-able. +func globalInit() { + base.NewConfigContext() + mailer.NewMailerContext() + models.LoadModelsConfig() + models.LoadRepoConfig() + models.NewRepoContext() + models.NewEngine() +} + // Check run mode(Default of martini is Dev). func checkRunMode() { switch base.Cfg.MustValue("", "RUN_MODE") { @@ -59,6 +71,7 @@ func newMartini() *martini.ClassicMartini { } func runWeb(*cli.Context) { + globalInit() base.NewServices() checkRunMode() log.Info("%s %s", base.AppName, base.AppVer) @@ -101,9 +114,10 @@ func runWeb(*cli.Context) { m.Get("/help", routers.Help) adminReq := middleware.AdminRequire() - m.Any("/admin", reqSignIn, adminReq, admin.Dashboard) - m.Any("/admin/users", reqSignIn, adminReq, admin.Users) - m.Any("/admin/repos", reqSignIn, adminReq, admin.Repositories) + m.Get("/admin", reqSignIn, adminReq, admin.Dashboard) + m.Get("/admin/users", reqSignIn, adminReq, admin.Users) + m.Get("/admin/repos", reqSignIn, adminReq, admin.Repositories) + m.Get("/admin/config", reqSignIn, adminReq, admin.Config) m.Post("/:username/:reponame/settings", reqSignIn, middleware.RepoAssignment(true), repo.SettingPost) m.Get("/:username/:reponame/settings", reqSignIn, middleware.RepoAssignment(true), repo.Setting) -- cgit v1.2.3 From c1576b4c400376f22ec25012a6ca66e9c5539ee4 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 03:27:59 -0400 Subject: Add admin add user --- models/models.go | 28 +++++++++---------- models/repo.go | 2 +- modules/base/conf.go | 2 ++ routers/admin/admin.go | 18 ++++++++++++ routers/admin/user.go | 63 ++++++++++++++++++++++++++++++++++++++++++ templates/admin/config.tmpl | 50 +++++++++++++++++++++++++++++++++ templates/admin/users.tmpl | 1 + templates/admin/users/new.tmpl | 54 ++++++++++++++++++++++++++++++++++++ web.go | 1 + 9 files changed, 204 insertions(+), 15 deletions(-) create mode 100644 routers/admin/user.go create mode 100644 templates/admin/users/new.tmpl (limited to 'routers/admin/admin.go') diff --git a/models/models.go b/models/models.go index bb0015d3..a4550d72 100644 --- a/models/models.go +++ b/models/models.go @@ -19,36 +19,36 @@ import ( var ( orm *xorm.Engine - dbCfg struct { + DbCfg struct { Type, Host, Name, User, Pwd, Path, SslMode string } ) func LoadModelsConfig() { - dbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE") - dbCfg.Host = base.Cfg.MustValue("database", "HOST") - dbCfg.Name = base.Cfg.MustValue("database", "NAME") - dbCfg.User = base.Cfg.MustValue("database", "USER") - dbCfg.Pwd = base.Cfg.MustValue("database", "PASSWD") - dbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db") - dbCfg.SslMode = base.Cfg.MustValue("database", "SSL_MODE") + DbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE") + DbCfg.Host = base.Cfg.MustValue("database", "HOST") + DbCfg.Name = base.Cfg.MustValue("database", "NAME") + DbCfg.User = base.Cfg.MustValue("database", "USER") + DbCfg.Pwd = base.Cfg.MustValue("database", "PASSWD") + DbCfg.SslMode = base.Cfg.MustValue("database", "SSL_MODE") + DbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db") } func setEngine() { var err error - switch dbCfg.Type { + switch DbCfg.Type { case "mysql": orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@%s/%s?charset=utf8", - dbCfg.User, dbCfg.Pwd, dbCfg.Host, dbCfg.Name)) + DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name)) case "postgres": orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", - dbCfg.User, dbCfg.Pwd, dbCfg.Name, dbCfg.SslMode)) + DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode)) case "sqlite3": - os.MkdirAll(path.Dir(dbCfg.Path), os.ModePerm) - orm, err = xorm.NewEngine("sqlite3", dbCfg.Path) + os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) + orm, err = xorm.NewEngine("sqlite3", DbCfg.Path) default: - fmt.Printf("Unknown database type: %s\n", dbCfg.Type) + fmt.Printf("Unknown database type: %s\n", DbCfg.Type) os.Exit(2) } if err != nil { diff --git a/models/repo.go b/models/repo.go index f2520047..918e5dc8 100644 --- a/models/repo.go +++ b/models/repo.go @@ -107,7 +107,7 @@ func IsRepositoryExist(user *User, repoName string) (bool, error) { var ( // Define as all lower case!! - illegalPatterns = []string{"[.][Gg][Ii][Tt]", "user", "help", "stars", "issues", "pulls", "commits", "admin", "repo", "template"} + illegalPatterns = []string{"[.][Gg][Ii][Tt]", "user", "help", "stars", "issues", "pulls", "commits", "admin", "repo", "template", "admin"} ) // IsLegalName returns false if name contains illegal characters. diff --git a/modules/base/conf.go b/modules/base/conf.go index 3050b915..bf054ec3 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -32,6 +32,7 @@ var ( AppUrl string Domain string SecretKey string + RunUser string RepoRootPath string Cfg *goconfig.ConfigFile @@ -179,6 +180,7 @@ func NewConfigContext() { AppUrl = Cfg.MustValue("server", "ROOT_URL") Domain = Cfg.MustValue("server", "DOMAIN") SecretKey = Cfg.MustValue("security", "SECRET_KEY") + RunUser = Cfg.MustValue("", "RUN_USER") // Determine and create root git reposiroty path. RepoRootPath = Cfg.MustValue("repository", "ROOT") diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 1095a599..547883f7 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -5,7 +5,12 @@ package admin import ( + "strings" + + "github.com/codegangsta/martini" + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/middleware" ) @@ -45,5 +50,18 @@ func Repositories(ctx *middleware.Context) { func Config(ctx *middleware.Context) { ctx.Data["Title"] = "Server Configuration" ctx.Data["PageIsConfig"] = true + + ctx.Data["AppUrl"] = base.AppUrl + ctx.Data["Domain"] = base.Domain + ctx.Data["RunUser"] = base.RunUser + ctx.Data["RunMode"] = strings.Title(martini.Env) + ctx.Data["RepoRootPath"] = base.RepoRootPath + + ctx.Data["Service"] = base.Service + + ctx.Data["DbCfg"] = models.DbCfg + + ctx.Data["Mailer"] = base.MailService + ctx.HTML(200, "admin/config") } diff --git a/routers/admin/user.go b/routers/admin/user.go new file mode 100644 index 00000000..9dcc1499 --- /dev/null +++ b/routers/admin/user.go @@ -0,0 +1,63 @@ +// Copyright 2014 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package admin + +import ( + "strings" + + "github.com/gogits/gogs/models" + "github.com/gogits/gogs/modules/auth" + "github.com/gogits/gogs/modules/log" + "github.com/gogits/gogs/modules/middleware" +) + +func NewUser(ctx *middleware.Context, form auth.RegisterForm) { + ctx.Data["Title"] = "New Account" + + if ctx.Req.Method == "GET" { + ctx.HTML(200, "admin/users/new") + return + } + + if form.Password != form.RetypePasswd { + ctx.Data["HasError"] = true + ctx.Data["Err_Password"] = true + ctx.Data["Err_RetypePasswd"] = true + ctx.Data["ErrorMsg"] = "Password and re-type password are not same" + auth.AssignForm(form, ctx.Data) + } + + if ctx.HasError() { + ctx.HTML(200, "admin/users/new") + return + } + + u := &models.User{ + Name: form.UserName, + Email: form.Email, + Passwd: form.Password, + IsActive: true, + } + + var err error + if u, err = models.RegisterUser(u); err != nil { + switch err { + case models.ErrUserAlreadyExist: + ctx.RenderWithErr("Username has been already taken", "admin/users/new", &form) + case models.ErrEmailAlreadyUsed: + ctx.RenderWithErr("E-mail address has been already used", "admin/users/new", &form) + case models.ErrUserNameIllegal: + ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "admin/users/new", &form) + default: + ctx.Handle(200, "admin.user.NewUser", err) + } + return + } + + log.Trace("%s User created by admin(%s): %s", ctx.Req.RequestURI, + ctx.User.LowerName, strings.ToLower(form.UserName)) + + ctx.Redirect("/admin/users") +} diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index d209bcdf..9593a545 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -9,7 +9,57 @@
+
Application Name: {{AppName}}
+
Application Version: {{AppVer}}
+
Application URL: {{.AppUrl}}
+
Domain: {{.Domain}}
+
+
Run User: {{.RunUser}}
+
Run Mode: {{.RunMode}}
+
+
Repository Root Path: {{.RepoRootPath}}
+
+
+ +
+
+ Database Configuration +
+
+
Type: {{.DbCfg.Type}}
+
Host: {{.DbCfg.Host}}
+
Name: {{.DbCfg.Name}}
+
User: {{.DbCfg.User}}
+
SslMode: {{.DbCfg.SslMode}} (for "postgres" only)
+
Path: {{.DbCfg.Path}} (for "sqlite3" only)
+
+
+ +
+
+ Service Configuration +
+ +
+
Register Email Confirmation:
+
Disenable Registeration:
+
Require Sign In View:
+
+
Active Code Lives: {{.Service.ActiveCodeLives}} minutes
+
Reset Password Code Lives: {{.Service.ResetPwdCodeLives}} minutes
+
+
+ +
+
+ Mailer Configuration +
+ +
+
Name: {{.Mailer.Name}}
+
Host: {{.Mailer.Host}}
+
User: {{.Mailer.User}}
diff --git a/templates/admin/users.tmpl b/templates/admin/users.tmpl index ae2b5bbb..d82f04b8 100644 --- a/templates/admin/users.tmpl +++ b/templates/admin/users.tmpl @@ -9,6 +9,7 @@
+ New Account diff --git a/templates/admin/users/new.tmpl b/templates/admin/users/new.tmpl new file mode 100644 index 00000000..bf59b16a --- /dev/null +++ b/templates/admin/users/new.tmpl @@ -0,0 +1,54 @@ +{{template "base/head" .}} +{{template "base/navbar" .}} +
+ {{template "admin/nav" .}} +
+
+
+ New Account +
+ +
+
+
+
{{.ErrorMsg}}
+
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/web.go b/web.go index 6fe838aa..d6d78afa 100644 --- a/web.go +++ b/web.go @@ -117,6 +117,7 @@ func runWeb(*cli.Context) { adminReq := middleware.AdminRequire() m.Get("/admin", reqSignIn, adminReq, admin.Dashboard) m.Get("/admin/users", reqSignIn, adminReq, admin.Users) + m.Any("/admin/users/new", reqSignIn, adminReq, binding.BindIgnErr(auth.RegisterForm{}), admin.NewUser) m.Get("/admin/repos", reqSignIn, adminReq, admin.Repositories) m.Get("/admin/config", reqSignIn, adminReq, admin.Config) -- cgit v1.2.3 From e67653cf13857f671de9bf6279453f99cdd60d11 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 04:13:32 -0400 Subject: Bug fix --- CONTRIBUTING.md | 49 ++++++++++++++++++++++++++++++++++++++++++ routers/admin/admin.go | 6 +++++- templates/admin/config.tmpl | 1 + templates/admin/dashboard.tmpl | 9 ++++++++ templates/repo/nav.tmpl | 6 +++--- 5 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 CONTRIBUTING.md (limited to 'routers/admin/admin.go') diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..08013d37 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,49 @@ +# Contributing to Gogs + +Want to hack on Gogs? Awesome! Here are instructions to get you +started. They are probably not perfect, please let us know if anything +feels wrong or incomplete. + +## Contribution guidelines + +### Pull requests are always welcome + +We are always thrilled to receive pull requests, and do our best to +process them as fast as possible. Not sure if that typo is worth a pull +request? Do it! We will appreciate it. + +If your pull request is not accepted on the first try, don't be +discouraged! If there's a problem with the implementation, hopefully you +received feedback on what to improve. + +We're trying very hard to keep Gogs lean and focused. We don't want it +to do everything for everybody. This means that we might decide against +incorporating a new feature. + +### Discuss your design on the mailing list + +We recommend discussing your plans [on the mailing +list](https://groups.google.com/forum/#!forum/gogits) +before starting to code - especially for more ambitious contributions. +This gives other contributors a chance to point you in the right +direction, give feedback on your design, and maybe point out if someone +else is working on the same thing. + +We may close your pull request if not first discussed on the mailing +list. We aren't doing this to be jerks. We are doing this to prevent +people from spending large amounts of time on changes that may need +to be designed or architected in a specific way, or may not align with +the vision of the project. + +### Create issues... + +Any significant improvement should be documented as [a GitHub +issue](https://github.com/gogits/gogs/issues) before anybody +starts working on it. + +### ...but check for existing issues first! + +Please take a moment to check that an issue doesn't already exist +documenting your bug report or improvement proposal. If it does, it +never hurts to add a quick "+1" or "I have this problem too". This will +help prioritize the most common problems and requests. \ No newline at end of file diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 547883f7..6d3831a9 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -61,7 +61,11 @@ func Config(ctx *middleware.Context) { ctx.Data["DbCfg"] = models.DbCfg - ctx.Data["Mailer"] = base.MailService + ctx.Data["MailerEnabled"] = false + if base.MailService != nil { + ctx.Data["MailerEnabled"] = true + ctx.Data["Mailer"] = base.MailService + } ctx.HTML(200, "admin/config") } diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 9593a545..7013c201 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -57,6 +57,7 @@
+
Enabled:
Name: {{.Mailer.Name}}
Host: {{.Mailer.Host}}
User: {{.Mailer.User}}
diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 8950f50c..6088487d 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -12,6 +12,15 @@ Gogs database has {{.Stats.Counter.User}} users, {{.Stats.Counter.PublicKey}} SSH keys, {{.Stats.Counter.Repo}} repositories, {{.Stats.Counter.Watch}} watches, {{.Stats.Counter.Action}} actions, and {{.Stats.Counter.Access}} accesses.
+ +
+
+ System Status +
+ +
+
+
{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/repo/nav.tmpl b/templates/repo/nav.tmpl index 718c429a..c61051af 100644 --- a/templates/repo/nav.tmpl +++ b/templates/repo/nav.tmpl @@ -5,8 +5,8 @@

{{.Owner.Name}} / {{.Repository.Name}}

{{.Repository.Description}}{{if .Repository.Website}}{{.Repository.Website}}{{end}}

- {{if not .IsBareRepo}}
+ {{if not .IsBareRepo}}
+ {{end}}
- + Fork  {{.Repository.NumForks}}
- {{end}} \ No newline at end of file -- cgit v1.2.3 From d40499e7fa3d62655431f160b6909d9751dabe11 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 10:09:57 -0400 Subject: Finsih mail resend limit --- README.md | 2 +- conf/app.ini | 8 +++++++- gogs.go | 2 +- models/models.go | 1 - modules/base/conf.go | 35 +++++++++++++++++++++++++---------- routers/admin/admin.go | 3 +++ routers/user/user.go | 12 ++++++++++-- templates/admin/config.tmpl | 11 +++++++++++ templates/user/active.tmpl | 2 ++ 9 files changed, 60 insertions(+), 16 deletions(-) (limited to 'routers/admin/admin.go') diff --git a/README.md b/README.md index e78ce8fe..cbd1f588 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Gogs(Go Git Service) is a GitHub-like clone in the Go Programming Language. Since we choose to use pure Go implementation of Git manipulation, Gogs certainly supports **ALL platforms** that Go supports, including Linux, Max OS X, and Windows with **ZERO** dependency. -##### Current version: 0.1.4 Alpha +##### Current version: 0.1.5 Alpha ## Purpose diff --git a/conf/app.ini b/conf/app.ini index 71fe81e8..ecb0d251 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -61,8 +61,14 @@ USER = PASSWD = [cache] +; Either "memory", "redis", or "memcache", default is "memory" ADAPTER = memory -CONFIG = +; For "memory" only, GC interval in seconds, default is 60 +INTERVAL = 60 +; For "redis" and "memcache", connection host address +; redis: ":6039" +; memcache: "127.0.0.1:11211" +HOST = [log] ; Either "console", "file", "conn" or "smtp", default is "console" diff --git a/gogs.go b/gogs.go index a9f7e6b5..41df7928 100644 --- a/gogs.go +++ b/gogs.go @@ -20,7 +20,7 @@ import ( // Test that go1.2 tag above is included in builds. main.go refers to this definition. const go12tag = true -const APP_VER = "0.1.4.0321" +const APP_VER = "0.1.5.0321" func init() { base.AppVer = APP_VER diff --git a/models/models.go b/models/models.go index a4550d72..8713ff28 100644 --- a/models/models.go +++ b/models/models.go @@ -35,7 +35,6 @@ func LoadModelsConfig() { } func setEngine() { - var err error switch DbCfg.Type { case "mysql": diff --git a/modules/base/conf.go b/modules/base/conf.go index 3962972c..2c3ecd72 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -133,6 +133,30 @@ func newLogService() { log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName) } +func newCacheService() { + CacheAdapter = Cfg.MustValue("cache", "ADAPTER", "memory") + + switch CacheAdapter { + case "memory": + CacheConfig = fmt.Sprintf(`{"interval":%d}`, Cfg.MustInt("cache", "INTERVAL", 60)) + case "redis", "memcache": + CacheConfig = fmt.Sprintf(`{"conn":"%s"}`, Cfg.MustValue("cache", "HOST")) + default: + fmt.Printf("Unknown cache adapter: %s\n", CacheAdapter) + os.Exit(2) + } + + var err error + Cache, err = cache.NewCache(CacheAdapter, CacheConfig) + if err != nil { + fmt.Printf("Init cache system failed, adapter: %s, config: %s, %v\n", + CacheAdapter, CacheConfig, err) + os.Exit(2) + } + + log.Info("Cache Service Enabled") +} + func newMailService() { // Check mailer setting. if Cfg.MustBool("mailer", "ENABLED") { @@ -188,16 +212,6 @@ func NewConfigContext() { SecretKey = Cfg.MustValue("security", "SECRET_KEY") RunUser = Cfg.MustValue("", "RUN_USER") - CacheAdapter = Cfg.MustValue("cache", "ADAPTER") - CacheConfig = Cfg.MustValue("cache", "CONFIG") - - Cache, err = cache.NewCache(CacheAdapter, CacheConfig) - if err != nil { - fmt.Printf("Init cache system failed, adapter: %s, config: %s, %v\n", - CacheAdapter, CacheConfig, err) - os.Exit(2) - } - // Determine and create root git reposiroty path. RepoRootPath = Cfg.MustValue("repository", "ROOT") if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil { @@ -209,6 +223,7 @@ func NewConfigContext() { func NewServices() { newService() newLogService() + newCacheService() newMailService() newRegisterMailService() } diff --git a/routers/admin/admin.go b/routers/admin/admin.go index 6d3831a9..d70af3c5 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -67,5 +67,8 @@ func Config(ctx *middleware.Context) { ctx.Data["Mailer"] = base.MailService } + ctx.Data["CacheAdapter"] = base.CacheAdapter + ctx.Data["CacheConfig"] = base.CacheConfig + ctx.HTML(200, "admin/config") } diff --git a/routers/user/user.go b/routers/user/user.go index 40b594ab..d38eb1ce 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -167,6 +167,10 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) { ctx.Data["Email"] = u.Email ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60 ctx.HTML(200, "user/active") + + if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil { + log.Error("Set cache(MailResendLimit) fail: %v", err) + } return } ctx.Redirect("/user/login") @@ -247,8 +251,12 @@ func Activate(ctx *middleware.Context) { } // Resend confirmation e-mail. if base.Service.RegisterEmailConfirm { - ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60 - mailer.SendActiveMail(ctx.Render, ctx.User) + if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) { + ctx.Data["ResendLimited"] = true + } else { + ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60 + mailer.SendActiveMail(ctx.Render, ctx.User) + } } else { ctx.Data["ServiceNotEnabled"] = true } diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 7013c201..ad32ec3f 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -63,6 +63,17 @@
User: {{.Mailer.User}}
+ +
+
+ Cache Configuration +
+ +
+
Cache Adapter: {{.CacheAdapter}}
+
Cache Config: {{.CacheConfig}}
+
+
{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/user/active.tmpl b/templates/user/active.tmpl index fefd7d3a..47c87a59 100644 --- a/templates/user/active.tmpl +++ b/templates/user/active.tmpl @@ -6,6 +6,8 @@ {{if .IsActivatePage}} {{if .ServiceNotEnabled}}

Sorry, Register Mail Confirmation has been disabled.

+ {{else if .ResendLimited}} +

Sorry, you are sending activation e-mail too frequently, please wait 3 minutes.

{{else}}

New confirmation e-mail has been sent to {{.SignedUser.Email}}, please check your inbox within {{.Hours}} hours to complete your registeration.


-- cgit v1.2.3 From f219ddcf4ef13b9d5de129da4eb2b56dbc899d61 Mon Sep 17 00:00:00 2001 From: Unknown Date: Fri, 21 Mar 2014 12:13:13 -0400 Subject: Add log config panel in admin --- .gopmfile | 3 +-- modules/base/conf.go | 26 ++++++++++++++------------ routers/admin/admin.go | 3 +++ templates/admin/config.tmpl | 16 +++++++++++++++- 4 files changed, 33 insertions(+), 15 deletions(-) (limited to 'routers/admin/admin.go') diff --git a/.gopmfile b/.gopmfile index 9e2440f3..5b690a06 100644 --- a/.gopmfile +++ b/.gopmfile @@ -9,13 +9,12 @@ github.com/Unknwon/com= github.com/Unknwon/cae= github.com/Unknwon/goconfig= github.com/dchest/scrypt= -github.com/go-sql-driver/mysql= -github.com/lib/pq= github.com/lunny/xorm= github.com/gogits/logs= github.com/gogits/binding= github.com/gogits/git= github.com/gogits/gfm= +github.com/gogits/cache= [res] include=templates|public|conf diff --git a/modules/base/conf.go b/modules/base/conf.go index 2c3ecd72..863daca6 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -43,6 +43,9 @@ var ( Cache cache.Cache CacheAdapter string CacheConfig string + + LogMode string + LogConfig string ) var Service struct { @@ -83,15 +86,15 @@ func newService() { func newLogService() { // Get and check log mode. - mode := Cfg.MustValue("log", "MODE", "console") - modeSec := "log." + mode + LogMode = Cfg.MustValue("log", "MODE", "console") + modeSec := "log." + LogMode if _, err := Cfg.GetSection(modeSec); err != nil { - fmt.Printf("Unknown log mode: %s\n", mode) + fmt.Printf("Unknown log mode: %s\n", LogMode) os.Exit(2) } // Log level. - levelName := Cfg.MustValue("log."+mode, "LEVEL", "Trace") + levelName := Cfg.MustValue("log."+LogMode, "LEVEL", "Trace") level, ok := logLevels[levelName] if !ok { fmt.Printf("Unknown log level: %s\n", levelName) @@ -99,14 +102,13 @@ func newLogService() { } // Generate log configuration. - var config string - switch mode { + switch LogMode { case "console": - config = fmt.Sprintf(`{"level":%s}`, level) + LogConfig = fmt.Sprintf(`{"level":%s}`, level) case "file": logPath := Cfg.MustValue(modeSec, "FILE_NAME", "log/gogs.log") os.MkdirAll(path.Dir(logPath), os.ModePerm) - config = fmt.Sprintf( + LogConfig = fmt.Sprintf( `{"level":%s,"filename":%s,"rotate":%v,"maxlines":%d,"maxsize",%d,"daily":%v,"maxdays":%d}`, level, logPath, Cfg.MustBool(modeSec, "LOG_ROTATE", true), @@ -115,13 +117,13 @@ func newLogService() { Cfg.MustBool(modeSec, "DAILY_ROTATE", true), Cfg.MustInt(modeSec, "MAX_DAYS", 7)) case "conn": - config = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":%s,"addr":%s}`, level, + LogConfig = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":%s,"addr":%s}`, level, Cfg.MustBool(modeSec, "RECONNECT_ON_MSG", false), Cfg.MustBool(modeSec, "RECONNECT", false), Cfg.MustValue(modeSec, "PROTOCOL", "tcp"), Cfg.MustValue(modeSec, "ADDR", ":7020")) case "smtp": - config = fmt.Sprintf(`{"level":%s,"username":%s,"password":%s,"host":%s,"sendTos":%s,"subject":%s}`, level, + LogConfig = fmt.Sprintf(`{"level":%s,"username":%s,"password":%s,"host":%s,"sendTos":%s,"subject":%s}`, level, Cfg.MustValue(modeSec, "USER", "example@example.com"), Cfg.MustValue(modeSec, "PASSWD", "******"), Cfg.MustValue(modeSec, "HOST", "127.0.0.1:25"), @@ -129,8 +131,8 @@ func newLogService() { Cfg.MustValue(modeSec, "SUBJECT", "Diagnostic message from serve")) } - log.NewLogger(Cfg.MustInt64("log", "BUFFER_LEN", 10000), mode, config) - log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName) + log.NewLogger(Cfg.MustInt64("log", "BUFFER_LEN", 10000), LogMode, LogConfig) + log.Info("Log Mode: %s(%s)", strings.Title(LogMode), levelName) } func newCacheService() { diff --git a/routers/admin/admin.go b/routers/admin/admin.go index d70af3c5..2e19b99c 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -70,5 +70,8 @@ func Config(ctx *middleware.Context) { ctx.Data["CacheAdapter"] = base.CacheAdapter ctx.Data["CacheConfig"] = base.CacheConfig + ctx.Data["LogMode"] = base.LogMode + ctx.Data["LogConfig"] = base.LogConfig + ctx.HTML(200, "admin/config") } diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index ad32ec3f..6906f240 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -71,7 +71,21 @@
Cache Adapter: {{.CacheAdapter}}
-
Cache Config: {{.CacheConfig}}
+
Cache Config:
+
{{.CacheConfig}}
+
+ + +
+
+ Log Configuration +
+ +
+
Log Mode: {{.LogMode}}
+
Log Config:
+
{{.LogConfig}}
+
-- cgit v1.2.3