summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/serve.go20
-rw-r--r--cmd/web.go5
-rw-r--r--gogs.go2
-rw-r--r--models/access.go17
-rw-r--r--models/issue.go4
-rw-r--r--models/login.go4
-rw-r--r--models/models.go2
-rw-r--r--models/org.go69
-rw-r--r--models/repo.go10
-rw-r--r--models/user.go186
-rw-r--r--modules/auth/org.go33
-rw-r--r--modules/middleware/repo.go4
-rw-r--r--routers/admin/user.go4
-rw-r--r--routers/install.go2
-rw-r--r--routers/org/org.go96
-rw-r--r--routers/repo/http.go8
-rw-r--r--routers/repo/setting.go4
-rw-r--r--routers/user/home.go13
-rw-r--r--routers/user/user.go7
-rw-r--r--templates/VERSION2
-rw-r--r--templates/org/dashboard.tmpl73
-rw-r--r--templates/org/new.tmpl24
-rw-r--r--templates/user/dashboard.tmpl39
-rw-r--r--templates/user/issues.tmpl3
24 files changed, 436 insertions, 195 deletions
diff --git a/cmd/serve.go b/cmd/serve.go
index 62e290d82a..2a76da7937 100644
--- a/cmd/serve.go
+++ b/cmd/serve.go
@@ -56,19 +56,19 @@ func parseCmd(cmd string) (string, string) {
}
var (
- COMMANDS_READONLY = map[string]int{
- "git-upload-pack": models.AU_WRITABLE,
- "git upload-pack": models.AU_WRITABLE,
- "git-upload-archive": models.AU_WRITABLE,
+ COMMANDS_READONLY = map[string]models.AccessType{
+ "git-upload-pack": models.WRITABLE,
+ "git upload-pack": models.WRITABLE,
+ "git-upload-archive": models.WRITABLE,
}
- COMMANDS_WRITE = map[string]int{
- "git-receive-pack": models.AU_READABLE,
- "git receive-pack": models.AU_READABLE,
+ COMMANDS_WRITE = map[string]models.AccessType{
+ "git-receive-pack": models.READABLE,
+ "git receive-pack": models.READABLE,
}
)
-func In(b string, sl map[string]int) bool {
+func In(b string, sl map[string]models.AccessType) bool {
_, e := sl[b]
return e
}
@@ -129,7 +129,7 @@ func runServ(k *cli.Context) {
// Access check.
switch {
case isWrite:
- has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.AU_WRITABLE)
+ has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.WRITABLE)
if err != nil {
println("Gogs: internal error:", err)
log.GitLogger.Fatal("Fail to check write access:", err)
@@ -152,7 +152,7 @@ func runServ(k *cli.Context) {
break
}
- has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.AU_READABLE)
+ has, err := models.HasAccess(user.Name, path.Join(repoUserName, repoName), models.READABLE)
if err != nil {
println("Gogs: internal error:", err)
log.GitLogger.Fatal("Fail to check read access:", err)
diff --git a/cmd/web.go b/cmd/web.go
index d29183a9dc..878fdeac70 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -188,14 +188,15 @@ func runWeb(*cli.Context) {
reqOwner := middleware.RequireOwner()
- m.Group("/o", func(r martini.Router) {
+ m.Group("/org", func(r martini.Router) {
r.Get("/create", org.New)
+ r.Post("/create", bindIgnErr(auth.CreateOrganizationForm{}), org.NewPost)
r.Get("/:org", org.Organization)
r.Get("/:org/dashboard", org.Dashboard)
r.Get("/:org/members", org.Members)
r.Get("/:org/teams", org.Teams)
r.Get("/:org/setting", org.Setting)
- })
+ }, reqSignIn)
m.Group("/:username/:reponame", func(r martini.Router) {
r.Get("/settings", repo.Setting)
diff --git a/gogs.go b/gogs.go
index 75d3eb4b8d..5c2c6ed943 100644
--- a/gogs.go
+++ b/gogs.go
@@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-const APP_VER = "0.4.5.0624 Alpha"
+const APP_VER = "0.4.5.0625 Alpha"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
diff --git a/models/access.go b/models/access.go
index cf31fc137b..5238daba32 100644
--- a/models/access.go
+++ b/models/access.go
@@ -11,19 +11,20 @@ import (
"github.com/go-xorm/xorm"
)
-// Access types.
+type AccessType int
+
const (
- AU_READABLE = iota + 1
- AU_WRITABLE
+ READABLE AccessType = iota + 1
+ WRITABLE
)
// Access represents the accessibility of user to repository.
type Access struct {
Id int64
- UserName string `xorm:"unique(s)"`
- RepoName string `xorm:"unique(s)"` // <user name>/<repo name>
- Mode int `xorm:"unique(s)"`
- Created time.Time `xorm:"created"`
+ UserName string `xorm:"unique(s)"`
+ RepoName string `xorm:"unique(s)"` // <user name>/<repo name>
+ Mode AccessType `xorm:"unique(s)"`
+ Created time.Time `xorm:"created"`
}
// AddAccess adds new access record.
@@ -59,7 +60,7 @@ func UpdateAccessWithSession(sess *xorm.Session, access *Access) error {
// HasAccess returns true if someone can read or write to given repository.
// The repoName should be in format <username>/<reponame>.
-func HasAccess(uname, repoName string, mode int) (bool, error) {
+func HasAccess(uname, repoName string, mode AccessType) (bool, error) {
if len(repoName) == 0 {
return false, nil
}
diff --git a/models/issue.go b/models/issue.go
index 11f6dd4ef9..6d67a72bc4 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -213,9 +213,9 @@ func GetIssueCountByPoster(uid, rid int64, isClosed bool) int64 {
// IssueUser represents an issue-user relation.
type IssueUser struct {
Id int64
- Uid int64 // User ID.
+ Uid int64 `xorm:"INDEX"` // User ID.
IssueId int64
- RepoId int64
+ RepoId int64 `xorm:"INDEX"`
MilestoneId int64
IsRead bool
IsAssigned bool
diff --git a/models/login.go b/models/login.go
index 98c5c64e40..e99b61e779 100644
--- a/models/login.go
+++ b/models/login.go
@@ -255,7 +255,7 @@ func LoginUserLdapSource(user *User, name, passwd string, sourceId int64, cfg *L
Email: mail,
}
- return RegisterUser(user)
+ return CreateUser(user)
}
type loginAuth struct {
@@ -359,5 +359,5 @@ func LoginUserSMTPSource(user *User, name, passwd string, sourceId int64, cfg *S
Passwd: passwd,
Email: name,
}
- return RegisterUser(user)
+ return CreateUser(user)
}
diff --git a/models/models.go b/models/models.go
index d6273d7f98..4e65c00bcb 100644
--- a/models/models.go
+++ b/models/models.go
@@ -35,7 +35,7 @@ func init() {
tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch),
new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow),
new(Mirror), new(Release), new(LoginSource), new(Webhook), new(IssueUser),
- new(Milestone), new(Label), new(HookTask))
+ new(Milestone), new(Label), new(HookTask), new(Team), new(OrgUser), new(TeamUser))
}
func LoadModelsConfig() {
diff --git a/models/org.go b/models/org.go
new file mode 100644
index 0000000000..1cfe179846
--- /dev/null
+++ b/models/org.go
@@ -0,0 +1,69 @@
+// 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 AuthorizeType int
+
+const (
+ ORG_READABLE AuthorizeType = iota + 1
+ ORG_WRITABLE
+ ORG_ADMIN
+)
+
+// Team represents a organization team.
+type Team struct {
+ Id int64
+ OrgId int64 `xorm:"INDEX"`
+ Name string
+ Description string
+ Authorize AuthorizeType
+ NumMembers int
+ NumRepos int
+}
+
+// NewTeam creates a record of new team.
+func NewTeam(t *Team) error {
+ _, err := x.Insert(t)
+ return err
+}
+
+// ________ ____ ___
+// \_____ \_______ ____ | | \______ ___________
+// / | \_ __ \/ ___\| | / ___// __ \_ __ \
+// / | \ | \/ /_/ > | /\___ \\ ___/| | \/
+// \_______ /__| \___ /|______//____ >\___ >__|
+// \/ /_____/ \/ \/
+
+// OrgUser represents an organization-user relation.
+type OrgUser struct {
+ Id int64
+ Uid int64 `xorm:"INDEX"`
+ OrgId int64 `xorm:"INDEX"`
+ IsPublic bool
+ IsOwner bool
+ NumTeam int
+}
+
+// GetOrgUsersByUserId returns all organization-user relations by user ID.
+func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) {
+ ous := make([]*OrgUser, 0, 10)
+ err := x.Where("uid=?", uid).Find(&ous)
+ return ous, err
+}
+
+// ___________ ____ ___
+// \__ ___/___ _____ _____ | | \______ ___________
+// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
+// | |\ ___/ / __ \| Y Y \ | /\___ \\ ___/| | \/
+// |____| \___ >____ /__|_| /______//____ >\___ >__|
+// \/ \/ \/ \/ \/
+
+// TeamUser represents an team-user relation.
+type TeamUser struct {
+ Id int64
+ Uid int64
+ OrgId int64 `xorm:"INDEX"`
+ TeamId int64
+}
diff --git a/models/repo.go b/models/repo.go
index 4ccaccbf81..f0e46c713e 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -158,7 +158,7 @@ func IsRepositoryExist(u *User, repoName string) (bool, error) {
}
var (
- illegalEquals = []string{"raw", "install", "api", "avatar", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
+ illegalEquals = []string{"raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
illegalSuffixs = []string{".git"}
)
@@ -483,7 +483,9 @@ func CreateRepository(user *User, name, desc, lang, license string, private, mir
sess := x.NewSession()
defer sess.Close()
- sess.Begin()
+ if err = sess.Begin(); err != nil {
+ return nil, err
+ }
if _, err = sess.Insert(repo); err != nil {
if err2 := os.RemoveAll(repoPath); err2 != nil {
@@ -495,9 +497,9 @@ func CreateRepository(user *User, name, desc, lang, license string, private, mir
return nil, err
}
- mode := AU_WRITABLE
+ mode := WRITABLE
if mirror {
- mode = AU_READABLE
+ mode = READABLE
}
access := Access{
UserName: user.LowerName,
diff --git a/models/user.go b/models/user.go
index 50d81c942d..2388be9a9c 100644
--- a/models/user.go
+++ b/models/user.go
@@ -21,10 +21,11 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-// User types.
+type UserType int
+
const (
- UT_INDIVIDUAL = iota + 1
- UT_ORGANIZATION
+ INDIVIDUAL UserType = iota // Historic reason to make it starts at 0.
+ ORGANIZATION
)
var (
@@ -50,7 +51,8 @@ type User struct {
LoginType LoginType
LoginSource int64 `xorm:"not null default 0"`
LoginName string
- Type int
+ Type UserType
+ Orgs []*User `xorm:"-"`
NumFollowers int
NumFollowings int
NumStars int
@@ -65,36 +67,60 @@ type User struct {
Salt string `xorm:"VARCHAR(10)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
+
+ // For organization.
+ NumTeams int
+ NumMembers int
}
// HomeLink returns the user home page link.
-func (user *User) HomeLink() string {
- return "/user/" + user.Name
+func (u *User) HomeLink() string {
+ return "/user/" + u.Name
}
// AvatarLink returns user gravatar link.
-func (user *User) AvatarLink() string {
+func (u *User) AvatarLink() string {
if setting.DisableGravatar {
return "/img/avatar_default.jpg"
} else if setting.Service.EnableCacheAvatar {
- return "/avatar/" + user.Avatar
+ return "/avatar/" + u.Avatar
}
- return "//1.gravatar.com/avatar/" + user.Avatar
+ return "//1.gravatar.com/avatar/" + u.Avatar
}
// NewGitSig generates and returns the signature of given user.
-func (user *User) NewGitSig() *git.Signature {
+func (u *User) NewGitSig() *git.Signature {
return &git.Signature{
- Name: user.Name,
- Email: user.Email,
+ Name: u.Name,
+ Email: u.Email,
When: time.Now(),
}
}
// EncodePasswd encodes password to safe format.
-func (user *User) EncodePasswd() {
- newPasswd := base.PBKDF2([]byte(user.Passwd), []byte(user.Salt), 10000, 50, sha256.New)
- user.Passwd = fmt.Sprintf("%x", newPasswd)
+func (u *User) EncodePasswd() {
+ newPasswd := base.PBKDF2([]byte(u.Passwd), []byte(u.Salt), 10000, 50, sha256.New)
+ u.Passwd = fmt.Sprintf("%x", newPasswd)
+}
+
+func (u *User) IsOrganization() bool {
+ return u.Type == ORGANIZATION
+}
+
+func (u *User) GetOrganizations() error {
+ ous, err := GetOrgUsersByUserId(u.Id)
+ if err != nil {
+ return err
+ }
+
+ u.Orgs = make([]*User, len(ous))
+ for i, ou := range ous {
+ u.Orgs[i], err = GetUserById(ou.OrgId)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
}
// Member represents user is member of organization.
@@ -126,49 +152,135 @@ func GetUserSalt() string {
return base.GetRandomString(10)
}
-// RegisterUser creates record of a new user.
-func RegisterUser(user *User) (*User, error) {
+// CreateUser creates record of a new user.
+func CreateUser(u *User) (*User, error) {
+ if !IsLegalName(u.Name) {
+ return nil, ErrUserNameIllegal
+ }
+
+ isExist, err := IsUserExist(u.Name)
+ if err != nil {
+ return nil, err
+ } else if isExist {
+ return nil, ErrUserAlreadyExist
+ }
+
+ isExist, err = IsEmailUsed(u.Email)
+ if err != nil {
+ return nil, err
+ } else if isExist {
+ return nil, ErrEmailAlreadyUsed
+ }
+
+ u.LowerName = strings.ToLower(u.Name)
+ u.Avatar = base.EncodeMd5(u.Email)
+ u.AvatarEmail = u.Email
+ u.Rands = GetUserSalt()
+ u.Salt = GetUserSalt()
+ u.EncodePasswd()
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
+ return nil, err
+ }
- if !IsLegalName(user.Name) {
+ if _, err = sess.Insert(u); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ if err = os.MkdirAll(UserPath(u.Name), os.ModePerm); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ if err = sess.Commit(); err != nil {
+ return nil, err
+ }
+
+ // Auto-set admin for user whose ID is 1.
+ if u.Id == 1 {
+ u.IsAdmin = true
+ u.IsActive = true
+ _, err = x.Id(u.Id).UseBool().Update(u)
+ }
+ return u, err
+}
+
+// CreateOrganization creates record of a new organization.
+func CreateOrganization(org, owner *User) (*User, error) {
+ if !IsLegalName(org.Name) {
return nil, ErrUserNameIllegal
}
- isExist, err := IsUserExist(user.Name)
+ isExist, err := IsUserExist(org.Name)
if err != nil {
return nil, err
} else if isExist {
return nil, ErrUserAlreadyExist
}
- isExist, err = IsEmailUsed(user.Email)
+ isExist, err = IsEmailUsed(org.Email)
if err != nil {
return nil, err
} else if isExist {
return nil, ErrEmailAlreadyUsed
}
- user.LowerName = strings.ToLower(user.Name)
- user.Avatar = base.EncodeMd5(user.Email)
- user.AvatarEmail = user.Email
- user.Rands = GetUserSalt()
- user.Salt = GetUserSalt()
- user.EncodePasswd()
- if _, err = x.Insert(user); err != nil {
+ org.LowerName = strings.ToLower(org.Name)
+ org.Avatar = base.EncodeMd5(org.Email)
+ org.AvatarEmail = org.Email
+ // No password for organization.
+ org.NumTeams = 1
+ org.NumMembers = 1
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err = sess.Begin(); err != nil {
+ return nil, err
+ }
+
+ if _, err = sess.Insert(org); err != nil {
+ sess.Rollback()
return nil, err
- } else if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil {
- if _, err := x.Id(user.Id).Delete(&User{}); err != nil {
- return nil, errors.New(fmt.Sprintf(
- "both create userpath %s and delete table record faild: %v", user.Name, err))
- }
+ }
+
+ // Create default owner team.
+ t := &Team{
+ OrgId: org.Id,
+ Name: "Owner",
+ Authorize: ORG_ADMIN,
+ NumMembers: 1,
+ }
+ if _, err = sess.Insert(t); err != nil {
+ sess.Rollback()
return nil, err
}
- if user.Id == 1 {
- user.IsAdmin = true
- user.IsActive = true
- _, err = x.Id(user.Id).UseBool().Update(user)
+ // Add initial creator to organization and owner team.
+ ou := &OrgUser{
+ Uid: owner.Id,
+ OrgId: org.Id,
+ IsOwner: true,
+ NumTeam: 1,
}
- return user, err
+ if _, err = sess.Insert(ou); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ tu := &TeamUser{
+ Uid: owner.Id,
+ OrgId: org.Id,
+ TeamId: t.Id,
+ }
+ if _, err = sess.Insert(tu); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ return org, sess.Commit()
}
// GetUsers returns given number of user objects with offset.
diff --git a/modules/auth/org.go b/modules/auth/org.go
new file mode 100644
index 0000000000..a60fbb851e
--- /dev/null
+++ b/modules/auth/org.go
@@ -0,0 +1,33 @@
+// 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 auth
+
+import (
+ "net/http"
+ "reflect"
+
+ "github.com/go-martini/martini"
+
+ "github.com/gogits/gogs/modules/base"
+ "github.com/gogits/gogs/modules/middleware/binding"
+)
+
+type CreateOrganizationForm struct {
+ OrgName string `form:"orgname" binding:"Required;AlphaDashDot;MaxSize(30)"`
+ Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
+}
+
+func (f *CreateOrganizationForm) Name(field string) string {
+ names := map[string]string{
+ "OrgName": "Organization name",
+ "Email": "E-mail address",
+ }
+ return names[field]
+}
+
+func (f *CreateOrganizationForm) Validate(errs *binding.Errors, req *http.Request, ctx martini.Context) {
+ data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
+ validate(errs, data, f)
+}
diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go
index 6c77ed2a77..43ba1e8c5a 100644
--- a/modules/middleware/repo.go
+++ b/modules/middleware/repo.go
@@ -46,7 +46,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
// Collaborators who have write access can be seen as owners.
if ctx.IsSigned {
- ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.AU_WRITABLE)
+ ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.WRITABLE)
if err != nil {
ctx.Handle(500, "RepoAssignment(HasAccess)", err)
return
@@ -107,7 +107,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
return
}
- hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.AU_READABLE)
+ hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.READABLE)
if err != nil {
ctx.Handle(500, "RepoAssignment(HasAccess)", err)
return
diff --git a/routers/admin/user.go b/routers/admin/user.go
index d1bbb48068..cf99db2bf7 100644
--- a/routers/admin/user.go
+++ b/routers/admin/user.go
@@ -67,7 +67,7 @@ func NewUserPost(ctx *middleware.Context, form auth.RegisterForm) {
}
var err error
- if u, err = models.RegisterUser(u); err != nil {
+ if u, err = models.CreateUser(u); err != nil {
switch err {
case models.ErrUserAlreadyExist:
ctx.RenderWithErr("Username has been already taken", USER_NEW, &form)
@@ -76,7 +76,7 @@ func NewUserPost(ctx *middleware.Context, form auth.RegisterForm) {
case models.ErrUserNameIllegal:
ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), USER_NEW, &form)
default:
- ctx.Handle(500, "admin.user.NewUser(RegisterUser)", err)
+ ctx.Handle(500, "admin.user.NewUser(CreateUser)", err)
}
return
}
diff --git a/routers/install.go b/routers/install.go
index 6ce7c98026..bb3c16eae4 100644
--- a/routers/install.go
+++ b/routers/install.go
@@ -227,7 +227,7 @@ func InstallPost(ctx *middleware.Context, form auth.InstallForm) {
GlobalInit()
// Create admin account.
- if _, err := models.RegisterUser(&models.User{Name: form.AdminName, Email: form.AdminEmail, Passwd: form.AdminPasswd,
+ if _, err := models.CreateUser(&models.User{Name: form.AdminName, Email: form.AdminEmail, Passwd: form.AdminPasswd,
IsAdmin: true, IsActive: true}); err != nil {
if err != models.ErrUserAlreadyExist {
setting.InstallLock = false
diff --git a/routers/org/org.go b/routers/org/org.go
index ff97402ebc..0595a81b3d 100644
--- a/routers/org/org.go
+++ b/routers/org/org.go
@@ -1,33 +1,117 @@
+// 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 org
import (
"github.com/go-martini/martini"
+
+ "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/middleware"
+ "github.com/gogits/gogs/routers/user"
+)
+
+const (
+ NEW base.TplName = "org/new"
)
func Organization(ctx *middleware.Context, params martini.Params) {
- ctx.Data["Title"] = "Organization "+params["org"]
+ ctx.Data["Title"] = "Organization " + params["org"]
ctx.HTML(200, "org/org")
}
func Members(ctx *middleware.Context, params martini.Params) {
- ctx.Data["Title"] = "Organization "+params["org"]+" Members"
+ ctx.Data["Title"] = "Organization " + params["org"] + " Members"
ctx.HTML(200, "org/members")
}
func Teams(ctx *middleware.Context, params martini.Params) {
- ctx.Data["Title"] = "Organization "+params["org"]+" Teams"
+ ctx.Data["Title"] = "Organization " + params["org"] + " Teams"
ctx.HTML(200, "org/teams")
}
func New(ctx *middleware.Context) {
- ctx.Data["Title"] = "Create an Organization"
- ctx.HTML(200, "org/new")
+ ctx.Data["Title"] = "Create An Organization"
+ ctx.HTML(200, NEW)
+}
+
+func NewPost(ctx *middleware.Context, form auth.CreateOrganizationForm) {
+ ctx.Data["Title"] = "Create An Organization"
+
+ if ctx.HasError() {
+ ctx.HTML(200, NEW)
+ return
+ }
+
+ org := &models.User{
+ Name: form.OrgName,
+ Email: form.Email,
+ IsActive: true, // NOTE: may need to set false when require e-mail confirmation.
+ Type: models.ORGANIZATION,
+ }
+
+ var err error
+ if org, err = models.CreateOrganization(org, ctx.User); err != nil {
+ switch err {
+ case models.ErrUserAlreadyExist:
+ ctx.Data["Err_OrgName"] = true
+ ctx.RenderWithErr("Organization name has been already taken", NEW, &form)
+ case models.ErrEmailAlreadyUsed:
+ ctx.Data["Err_Email"] = true
+ ctx.RenderWithErr("E-mail address has been already used", NEW, &form)
+ case models.ErrUserNameIllegal:
+ ctx.Data["Err_OrgName"] = true
+ ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), NEW, &form)
+ default:
+ ctx.Handle(500, "user.NewPost(CreateUser)", err)
+ }
+ return
+ }
+ log.Trace("%s Organization created: %s", ctx.Req.RequestURI, org.Name)
+
+ ctx.Redirect("/org/" + form.OrgName + "/dashboard")
}
func Dashboard(ctx *middleware.Context, params martini.Params) {
ctx.Data["Title"] = "Dashboard"
- ctx.HTML(200, "org/dashboard")
+ ctx.Data["PageIsUserDashboard"] = true
+ ctx.Data["PageIsOrgDashboard"] = true
+
+ org, err := models.GetUserByName(params["org"])
+ if err != nil {
+ if err == models.ErrUserNotExist {
+ ctx.Handle(404, "org.Dashboard(GetUserByName)", err)
+ } else {
+ ctx.Handle(500, "org.Dashboard(GetUserByName)", err)
+ }
+ return
+ }
+
+ if err := ctx.User.GetOrganizations(); err != nil {
+ ctx.Handle(500, "home.Dashboard(GetOrganizations)", err)
+ return
+ }
+ ctx.Data["Orgs"] = ctx.User.Orgs
+ ctx.Data["ContextUser"] = org
+
+ ctx.Data["MyRepos"], err = models.GetRepositories(org.Id, true)
+ if err != nil {
+ ctx.Handle(500, "org.Dashboard(GetRepositories)", err)
+ return
+ }
+
+ actions, err := models.GetFeeds(org.Id, 0, false)
+ if err != nil {
+ ctx.Handle(500, "org.Dashboard(GetFeeds)", err)
+ return
+ }
+ ctx.Data["Feeds"] = actions
+
+ ctx.HTML(200, user.DASHBOARD)
}
func Setting(ctx *middleware.Context, param martini.Params) {
diff --git a/routers/repo/http.go b/routers/repo/http.go
index d2bff29973..981266d548 100644
--- a/routers/repo/http.go
+++ b/routers/repo/http.go
@@ -107,9 +107,9 @@ func Http(ctx *middleware.Context, params martini.Params) {
}
if !isPublicPull {
- var tp = models.AU_WRITABLE
+ var tp = models.WRITABLE
if isPull {
- tp = models.AU_READABLE
+ tp = models.READABLE
}
has, err := models.HasAccess(authUsername, username+"/"+reponame, tp)
@@ -117,8 +117,8 @@ func Http(ctx *middleware.Context, params martini.Params) {
ctx.Handle(401, "no basic auth and digit auth", nil)
return
} else if !has {
- if tp == models.AU_READABLE {
- has, err = models.HasAccess(authUsername, username+"/"+reponame, models.AU_WRITABLE)
+ if tp == models.READABLE {
+ has, err = models.HasAccess(authUsername, username+"/"+reponame, models.WRITABLE)
if err != nil || !has {
ctx.Handle(401, "no basic auth and digit auth", nil)
return
diff --git a/routers/repo/setting.go b/routers/repo/setting.go
index 6479cb3041..3d48e79c3d 100644
--- a/routers/repo/setting.go
+++ b/routers/repo/setting.go
@@ -175,7 +175,7 @@ func CollaborationPost(ctx *middleware.Context) {
ctx.Redirect(ctx.Req.RequestURI)
return
}
- has, err := models.HasAccess(name, repoLink, models.AU_WRITABLE)
+ has, err := models.HasAccess(name, repoLink, models.WRITABLE)
if err != nil {
ctx.Handle(500, "setting.CollaborationPost(HasAccess)", err)
return
@@ -196,7 +196,7 @@ func CollaborationPost(ctx *middleware.Context) {
}
if err = models.AddAccess(&models.Access{UserName: name, RepoName: repoLink,
- Mode: models.AU_WRITABLE}); err != nil {
+ Mode: models.WRITABLE}); err != nil {
ctx.Handle(500, "setting.CollaborationPost(AddAccess)", err)
return
}
diff --git a/routers/user/home.go b/routers/user/home.go
index 0f2cee2565..86907b5a90 100644
--- a/routers/user/home.go
+++ b/routers/user/home.go
@@ -20,7 +20,7 @@ import (
const (
DASHBOARD base.TplName = "user/dashboard"
PROFILE base.TplName = "user/profile"
- ISSUES base.TplName = "user/issue"
+ ISSUES base.TplName = "user/issues"
PULLS base.TplName = "user/pulls"
STARS base.TplName = "user/stars"
)
@@ -29,6 +29,13 @@ func Dashboard(ctx *middleware.Context) {
ctx.Data["Title"] = "Dashboard"
ctx.Data["PageIsUserDashboard"] = true
+ if err := ctx.User.GetOrganizations(); err != nil {
+ ctx.Handle(500, "home.Dashboard(GetOrganizations)", err)
+ return
+ }
+ ctx.Data["Orgs"] = ctx.User.Orgs
+ ctx.Data["ContextUser"] = ctx.User
+
var err error
ctx.Data["MyRepos"], err = models.GetRepositories(ctx.User.Id, true)
if err != nil {
@@ -53,7 +60,7 @@ func Dashboard(ctx *middleware.Context) {
for _, act := range actions {
if act.IsPrivate {
if has, _ := models.HasAccess(ctx.User.Name, act.RepoUserName+"/"+act.RepoName,
- models.AU_READABLE); !has {
+ models.READABLE); !has {
continue
}
}
@@ -131,7 +138,7 @@ func Feeds(ctx *middleware.Context, form auth.FeedsForm) {
for _, act := range actions {
if act.IsPrivate {
if has, _ := models.HasAccess(ctx.User.Name, act.RepoUserName+"/"+act.RepoName,
- models.AU_READABLE); !has {
+ models.READABLE); !has {
continue
}
}
diff --git a/routers/user/user.go b/routers/user/user.go
index 8144730e09..a50f126c0c 100644
--- a/routers/user/user.go
+++ b/routers/user/user.go
@@ -226,7 +226,7 @@ func SignUpPost(ctx *middleware.Context, form auth.RegisterForm) {
}
var err error
- if u, err = models.RegisterUser(u); err != nil {
+ if u, err = models.CreateUser(u); err != nil {
switch err {
case models.ErrUserAlreadyExist:
ctx.Data["Err_UserName"] = true
@@ -235,13 +235,14 @@ func SignUpPost(ctx *middleware.Context, form auth.RegisterForm) {
ctx.Data["Err_Email"] = true
ctx.RenderWithErr("E-mail address has been already used", SIGNUP, &form)
case models.ErrUserNameIllegal:
+ ctx.Data["Err_UserName"] = true
ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), SIGNUP, &form)
default:
- ctx.Handle(500, "user.SignUpPost(RegisterUser)", err)
+ ctx.Handle(500, "user.SignUpPost(CreateUser)", err)
}
return
}
- log.Trace("%s User created: %s", ctx.Req.RequestURI, form.UserName)
+ log.Trace("%s User created: %s", ctx.Req.RequestURI, u.Name)
// Bind social account.
if isOauth {
diff --git a/templates/VERSION b/templates/VERSION
index 8c2be60bbf..b5cda695b5 100644
--- a/templates/VERSION
+++ b/templates/VERSION
@@ -1 +1 @@
-0.4.5.0624 Alpha \ No newline at end of file
+0.4.5.0625 Alpha \ No newline at end of file
diff --git a/templates/org/dashboard.tmpl b/templates/org/dashboard.tmpl
deleted file mode 100644
index f86de1f42b..0000000000
--- a/templates/org/dashboard.tmpl
+++ /dev/null
@@ -1,73 +0,0 @@
-{{template "base/head" .}}
-{{template "base/navbar" .}}
-<div id="body-nav">
- <div class="container">
- <div class="btn-group pull-left" id="dashboard-switch">
- <button type="button" class="btn btn-default">
- <img src="//1.gravatar.com/avatar/f72f7454ce9d710baa506394f68f4132?s=28" alt="user-avatar" title="username">
- gogits
- </button>
- <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
- <span class="caret"></span>
- </button>
- <div class="dropdown-menu clone-group-btn no-propagation">
- <ul id="dashboard-switch-menu" class="list-unstyled">
- <li class="checked"><a href="#"><i class="fa fa-check"></i>
- <img src="//1.gravatar.com/avatar/f72f7454ce9d710baa506394f68f4132?s=28" alt="user-avatar" title="username">
- gogits/gogs</a>
- </li>
- </ul>
- </div>
- </div>
- <ul class="nav nav-pills pull-right">
- <li class="active"><a href="/">Feed</a></li>
- <li><a href="/issues">Issues</a></li>
- <li><a href="#">Setting</a></li>
- <!-- <li><a href="/pulls">Pull Requests</a></li>
- <li><a href="/stars">Stars</a></li> -->
- </ul>
- <h3>News Feed</h3>
- </div>
-</div>
-<div id="body" class="container" data-page="user">
- {{if .HasInfo}}<div class="alert alert-info">{{.InfoMsg}}</div>{{end}}
- <div id="feed-left" class="col-md-8">
- <ul class="list-unstyled activity-list">
- {{range .Feeds}}
- <li>
- <i class="icon fa fa-{{ActionIcon .OpType}}"></i>
- <div class="info"><span class="meta">{{TimeSince .Created}}</span><br>{{ActionDesc . | str2html}}</div>
- <span class="clearfix"></span>
- </li>
- {{else}}
- <li>Oh. Looks like there isn't any activity here yet. Get Busy!</li>
- {{end}}
- </ul>
- </div>
- <div id="feed-right" class="col-md-4">
- <div class="panel panel-default repo-panel">
- <div class="panel-heading">Repositories
- <div class="btn-group pull-right" id="user-dashboard-repo-new">
- <button type="button" class="btn btn-success btn-sm dropdown-toggle" data-toggle="dropdown"><i class="fa fa-plus-square"></i>New</button>
- <div class="dropdown-menu dropdown-menu-right">
- <ul class="list-unstyled">
- <li><a href="/repo/create"><i class="fa fa-book"></i>Repository</a></li>
- <li><a href="/repo/migrate"><i class="fa fa-clipboard"></i>Migration</a></li>
- <!-- <li><a href="#"><i class="fa fa-users"></i>Organization</a></li> -->
- </ul>
- </div>
- </div>
- </div>
-
- <div class="panel-body">
- <ul class="list-group">{{range .MyRepos}}
- <li class="list-group-item"><a href="/{{$.SignedUserName}}/{{.Name}}">
- <!-- <span class="stars pull-right"><i class="fa fa-star"></i>{{.NumStars}}</span> -->
- <i class="fa fa-book"></i>{{.Name}}{{if .IsPrivate}} <span class="label label-default">Private</span>{{end}}</a>
- </li>{{end}}
- </ul>
- </div>
- </div>
- </div>
-</div>
-{{template "base/footer" .}}
diff --git a/templates/org/new.tmpl b/templates/org/new.tmpl
index baa9c9dfa0..bb46db4ac3 100644
--- a/templates/org/new.tmpl
+++ b/templates/org/new.tmpl
@@ -1,22 +1,14 @@
{{template "base/head" .}}
{{template "base/navbar" .}}
<div class="container" id="body">
- <form action="/repo/create" method="post" class="form-horizontal card" id="org-create">
+ <form action="/org/create" method="post" class="form-horizontal card" id="org-create">
{{.CsrfTokenHtml}}
<h3>Create New Organization</h3>
{{template "base/alert" .}}
- <div class="form-group">
- <label class="col-md-2 control-label">Owner<strong class="text-danger">*</strong></label>
- <div class="col-md-8">
- <p class="form-control-static">{{.SignedUserName}}</p>
- <input type="hidden" value="{{.SignedUserId}}" name="userId"/>
- </div>
- </div>
-
- <div class="form-group {{if .Err_RepoName}}has-error has-feedback{{end}}">
+ <div class="form-group {{if .Err_OrgName}}has-error has-feedback{{end}}">
<label class="col-md-2 control-label">Organization<strong class="text-danger">*</strong></label>
<div class="col-md-8">
- <input name="repo" type="text" class="form-control" placeholder="Type your repository name" value="{{.repo}}" required="required">
+ <input name="orgname" type="text" class="form-control" placeholder="Type your organization name" value="{{.orgname}}" required="required">
<span class="help-block">Great organization names are short and memorable. </span>
</div>
</div>
@@ -24,18 +16,10 @@
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}">
<label class="col-md-2 control-label">Email<strong class="text-danger">*</strong></label>
<div class="col-md-8">
- <input name="email" type="text" class="form-control" placeholder="Type organization's email" value="" required="required">
+ <input name="email" type="text" class="form-control" placeholder="Type organization's email" value="{{.email}}" required="required">
<span class="help-block">Organization's Email receives all notifications and confirmations.</span>
</div>
</div>
-<!--
- <div class="form-group">
- <label class="col-md-2 control-label">Owners<strong class="text-danger">*</strong></label>
- <div class="col-md-8">
- owners
- </div>
- </div>-->
-
<div class="form-group">
<div class="col-md-offset-2 col-md-8">
diff --git a/templates/user/dashboard.tmpl b/templates/user/dashboard.tmpl
index 12018ad891..e1b43e1597 100644
--- a/templates/user/dashboard.tmpl
+++ b/templates/user/dashboard.tmpl
@@ -4,29 +4,46 @@
<div class="container">
<div class="btn-group pull-left" id="dashboard-switch">
<button type="button" class="btn btn-default">
- <img src="//1.gravatar.com/avatar/f72f7454ce9d710baa506394f68f4132?s=28" alt="user-avatar" title="username">
- fuxiaohei
+ <img src="{{.ContextUser.AvatarLink}}?s=28" alt="user-avatar" title="username">
+ {{.ContextUser.Name}}
</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<div class="dropdown-menu clone-group-btn no-propagation">
<ul id="dashboard-switch-menu" class="list-unstyled">
- <li class="checked"><a href="#"><i class="fa fa-check"></i>
- <img src="//1.gravatar.com/avatar/f72f7454ce9d710baa506394f68f4132?s=28" alt="user-avatar" title="username">
- gogits/gogs</a></li>
+ <li{{if not .PageIsOrgDashboard}} class="checked"{{end}}>
+ <a href="/">
+ <i class="fa fa-check"></i>
+ <img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username">
+ {{.SignedUser.Name}}
+ </a>
+ </li>
+ {{range .Orgs}}
+ <li{{if eq $.ContextUser.Id .Id}} class="checked"{{end}}>
+ <a href="/org/{{.Name}}/dashboard">
+ <i class="fa fa-check"></i>
+ <img src="{{.AvatarLink}}?s=28" alt="user-avatar" title="username">
+ {{.Name}}
+ </a>
+ </li>
+ {{end}}
+ <li>
+ <a href="/org/create">Create organization</a>
+ </li>
</ul>
</div>
</div>
<ul class="nav nav-pills pull-right">
- <li class="active"><a href="/">Feed</a></li>
- <li><a href="/issues">Issues</a></li>
+ <li class="active"><a href="/{{if .PageIsOrgDashboard}}org/{{.ContextUser.Name}}/dashboard{{end}}">News Feed</a></li>
+ <li><a href="/{{if .PageIsOrgDashboard}}org/{{.ContextUser.Name}}/dashboard/{{end}}issues">Issues</a></li>
+ {{if .PageIsOrgDashboard}}<li><a href="/org/{{.ContextUser.Name}}/settings">Settings</a></li>{{end}}
<!-- <li><a href="/pulls">Pull Requests</a></li>
<li><a href="/stars">Stars</a></li> -->
</ul>
- <h3>News Feed</h3>
</div>
</div>
+
<div id="body" class="container" data-page="user">
{{if .HasInfo}}<div class="alert alert-info">{{.InfoMsg}}</div>{{end}}
<div id="feed-left" class="col-md-8">
@@ -44,7 +61,7 @@
</div>
<div id="feed-right" class="col-md-4">
<div class="panel panel-default repo-panel">
- <div class="panel-heading">Your Repositories
+ <div class="panel-heading">{{if not .PageIsOrgDashboard}}Your {{end}}Repositories
<div class="btn-group pull-right" id="user-dashboard-repo-new">
<button type="button" class="btn btn-success btn-sm dropdown-toggle" data-toggle="dropdown"><i class="fa fa-plus-square"></i>New</button>
<div class="dropdown-menu dropdown-menu-right">
@@ -66,7 +83,8 @@
</ul>
</div>
</div>
-
+
+ {{if not .PageIsOrgDashboard}}
<div class="panel panel-default repo-panel">
<div class="panel-heading">Collaborative Repositories</div>
<div class="panel-body">
@@ -78,6 +96,7 @@
</ul>
</div>
</div>
+ {{end}}
</div>
</div>
{{template "base/footer" .}}
diff --git a/templates/user/issues.tmpl b/templates/user/issues.tmpl
index d1c2bd9941..c4ad64a4cf 100644
--- a/templates/user/issues.tmpl
+++ b/templates/user/issues.tmpl
@@ -3,7 +3,7 @@
<div id="body-nav">
<div class="container">
<ul class="nav nav-pills pull-right">
- <li><a href="/">Feed</a></li>
+ <li><a href="/">News Feed</a></li>
<li class="active"><a href="/issues">Issues</a></li>
<!-- <li><a href="/pulls">Pull Requests</a></li>
<li><a href="/stars">Stars</a></li> -->
@@ -11,6 +11,7 @@
<h3>Your Issues</h3>
</div>
</div>
+
<div id="body" class="container" data-page="user">
{{if .HasInfo}}<div class="alert alert-info">{{.InfoMsg}}</div>{{end}}
<div id="issue">