- Repository viewer.
- Gravatar support.
- Mail service(register).
-- Supports MySQL and PostgreSQL.
+- Supports MySQL, PostgreSQL and SQLite3(binary release only).
## Installation
HTTP_PORT = 3000
[database]
-; Either "mysql" or "postgres", it's your choice
+; Either "mysql", "postgres" or "sqlite3"(binary release only), it's your choice
DB_TYPE = mysql
HOST =
NAME = gogs
PASSWD =
; For "postgres" only, either "disable", "require" or "verify-full"
SSL_MODE = disable
+; For "sqlite3" only
+PATH = data/gogs.db
+
+[admin]
[security]
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
RESET_PASSWD_CODE_LIVE_MINUTES = 180
; User need to confirm e-mail for registration
REGISTER_EMAIL_CONFIRM = false
+; Does not allow register and admin create account only
+DISENABLE_REGISTERATION = false
[mailer]
ENABLED = false
watches = append(watches, Watch{UserId: userId})
for i := range watches {
+ if userId == watches[i].UserId && i > 0 {
+ continue // Do not add twice in case author watches his/her repository.
+ }
+
_, err = orm.InsertOne(&Action{
UserId: watches[i].UserId,
ActUserId: userId,
import (
"fmt"
"os"
+ "path"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
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
case "postgres":
orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s",
dbUser, dbPwd, dbName, sslMode))
+ case "sqlite3":
+ os.MkdirAll(path.Dir(dbPath), os.ModePerm)
+ orm, err = xorm.NewEngine("sqlite3", dbPath)
default:
fmt.Printf("Unknown database type: %s\n", dbType)
os.Exit(2)
return nil
}
+// UserRepo reporesents a repository with user name.
+type UserRepo struct {
+ *Repository
+ UserName string
+}
+
// GetRepos returns given number of repository objects with offset.
-func GetRepos(num, offset int) ([]Repository, error) {
+func GetRepos(num, offset int) ([]UserRepo, error) {
repos := make([]Repository, 0, num)
- err := orm.Limit(num, offset).Asc("id").Find(&repos)
- return repos, err
+ if err := orm.Limit(num, offset).Asc("id").Find(&repos); err != nil {
+ return nil, err
+ }
+
+ urepos := make([]UserRepo, len(repos))
+ for i := range repos {
+ urepos[i].Repository = &repos[i]
+ u := new(User)
+ has, err := orm.Id(urepos[i].Repository.OwnerId).Get(u)
+ if err != nil {
+ return nil, err
+ } else if !has {
+ return nil, ErrUserNotExist
+ }
+ urepos[i].UserName = u.Name
+ }
+
+ return urepos, nil
}
func RepoPath(userName, repoName string) string {
)
var Service struct {
- RegisterEmailConfirm bool
- ActiveCodeLives int
- ResetPwdCodeLives int
+ RegisterEmailConfirm bool
+ DisenableRegisteration bool
+ ActiveCodeLives int
+ ResetPwdCodeLives int
}
func exeDir() (string, error) {
func newService() {
Service.ActiveCodeLives = Cfg.MustInt("service", "ACTIVE_CODE_LIVE_MINUTES", 180)
Service.ResetPwdCodeLives = Cfg.MustInt("service", "RESET_PASSWD_CODE_LIVE_MINUTES", 180)
+ Service.DisenableRegisteration = Cfg.MustBool("service", "DISENABLE_REGISTERATION", false)
}
func newLogService() {
return c
}
+var mailDomains = map[string]string{
+ "gmail.com": "gmail.com",
+}
+
var TemplateFuncs template.FuncMap = map[string]interface{}{
"AppName": func() string {
return AppName
"DateFormat": DateFormat,
"List": List,
"Mail2Domain": func(mail string) string {
- return "mail." + strings.Split(mail, "@")[1]
+ suffix := strings.SplitN(mail, "@", 2)[1]
+ domain, ok := mailDomains[suffix]
+ if !ok {
+ return "mail." + suffix
+ }
+ return domain
},
"SubStr": func(str string, start, length int) string {
return str[start : start+length]
ctx.Data["Title"] = "Sign Up"
ctx.Data["PageIsSignUp"] = true
+ if base.Service.DisenableRegisteration {
+ ctx.Data["DisenableRegisteration"] = true
+ ctx.HTML(200, "user/signup")
+ return
+ }
+
if ctx.Req.Method == "GET" {
ctx.HTML(200, "user/signup")
return
<thead>
<tr>
<th>Id</th>
+ <th>Owner</th>
<th>Name</th>
<th>Private</th>
<th>Watches</th>
{{range .Repos}}
<tr>
<td>{{.Id}}</td>
- <td>{{.Name}}</td>
+ <th>{{.UserName}}</th>
+ <td><a href="/{{.UserName}}/{{.Name}}">{{.Name}}</a></td>
<td><i class="fa fa{{if .Private}}-check{{end}}-square-o"></i></td>
<td>{{.NumWatches}}</td>
<td>{{.NumForks}}</td>
{{range .Users}}
<tr>
<td>{{.Id}}</td>
- <td>{{.Name}}</td>
+ <td><a href="/user/{{.Name}}">{{.Name}}</a></td>
<td>{{.Email}}</td>
<td><i class="fa fa{{if .IsActive}}-check{{end}}-square-o"></i></td>
<td><i class="fa fa{{if .IsAdmin}}-check{{end}}-square-o"></i></td>
<a class="navbar-right gogs-nav-item{{if .PageIsNewRepo}} active{{end}}" href="/repo/create" data-toggle="tooltip" data-placement="bottom" title="New Repository"><i class="fa fa-plus fa-lg"></i></a>
<a class="navbar-right gogs-nav-item{{if .PageIsUserSetting}} active{{end}}" href="/user/setting" data-toggle="tooltip" data-placement="bottom" title="Setting"><i class="fa fa-cogs fa-lg"></i></a>
{{if .IsAdmin}}<a class="navbar-right gogs-nav-item{{if .PageIsAdmin}} active{{end}}" href="/admin" data-toggle="tooltip" data-placement="bottom" title="Admin"><i class="fa fa-gear fa-lg"></i></a>{{end}}
- {{else}}<a id="gogs-nav-signin" class="gogs-nav-item navbar-right navbar-btn btn btn-danger" href="/user/login/">Sign in</a>{{end}}
+ {{else}}<a id="gogs-nav-signin" class="gogs-nav-item navbar-right navbar-btn btn btn-success" href="/user/login/">Sign In</a>
+ <a id="gogs-nav-signup" class="gogs-nav-item navbar-right navbar-btn btn btn-info" href="/user/sign_up/">Sign Up</a>{{end}}
</nav>
</div>
</div>
<b class="caret"></b></a>
<ul class="dropdown-menu">
{{range .Branches}}
- <li><a {{if eq . $.Branchname}}class="current" {{end}}href="{{$.BranchLink}}">{{.}}</a></li>
+ <li><a {{if eq . $.Branchname}}class="current" {{end}}href="/{{$.Username}}/{{$.Reponame}}/src/{{.}}">{{.}}</a></li>
{{end}}
</ul>
</div>
</div>
<div class="form-group text-center" id="gogs-social-login">
- <a class="btn btn-default btn-lg">Social Login</a>
+ <a class="btn btn-danger btn-lg">Register new account</a>
</div>
</form>
</div>
{{template "base/navbar" .}}
<div class="container" id="gogs-body" data-page="user-signup">
<form action="/user/sign_up" method="post" class="form-horizontal gogs-card" id="gogs-login-card">
+ {{if .DisenableRegisteration}}
+ Sorry, registeration has been disenabled, you can only get account from administrator.
+ {{else}}
<h3>Sign Up</h3>
<div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div>
<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}">
<a href="/user/login">Already have an account? Sign in now!</a>
</div>
</div>
+ {{end}}
</form>
</div>
{{template "base/footer" .}}
\ No newline at end of file