summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/web.go2
-rw-r--r--models/org.go41
-rw-r--r--models/user.go9
-rw-r--r--routers/org/org.go38
-rw-r--r--routers/repo/repo.go20
-rw-r--r--routers/user/home.go6
-rw-r--r--templates/org/home.tmpl70
-rw-r--r--templates/org/org.tmpl85
-rw-r--r--templates/repo/create.tmpl17
9 files changed, 179 insertions, 109 deletions
diff --git a/cmd/web.go b/cmd/web.go
index 7387d445e4..af92b71384 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -191,7 +191,7 @@ func runWeb(*cli.Context) {
m.Group("/org", func(r martini.Router) {
r.Get("/create", org.New)
r.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.NewPost)
- r.Get("/:org", org.Organization)
+ r.Get("/:org", org.Home)
r.Get("/:org/dashboard", org.Dashboard)
r.Get("/:org/members", org.Members)
diff --git a/models/org.go b/models/org.go
index 025759b001..29a5ac3cab 100644
--- a/models/org.go
+++ b/models/org.go
@@ -20,6 +20,28 @@ func (org *User) GetOwnerTeam() (*Team, error) {
return t, err
}
+// GetTeams returns all teams that belong to organization.
+func (org *User) GetTeams() error {
+ return x.Where("org_id=?", org.Id).Find(&org.Teams)
+}
+
+// GetMembers returns all members of organization.
+func (org *User) GetMembers() error {
+ ous, err := GetOrgUsersByOrgId(org.Id)
+ if err != nil {
+ return err
+ }
+
+ org.Members = make([]*User, len(ous))
+ for i, ou := range ous {
+ org.Members[i], err = GetUserById(ou.Uid)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
// CreateOrganization creates record of a new organization.
func CreateOrganization(org, owner *User) (*User, error) {
if !IsLegalName(org.Name) {
@@ -132,12 +154,13 @@ const (
ORG_ADMIN
)
-const OWNER_TEAM = "Owner"
+const OWNER_TEAM = "Owners"
// Team represents a organization team.
type Team struct {
Id int64
OrgId int64 `xorm:"INDEX"`
+ LowerName string
Name string
Description string
Authorize AuthorizeType
@@ -148,15 +171,19 @@ type Team struct {
// NewTeam creates a record of new team.
func NewTeam(t *Team) error {
+ // TODO: check if same name team of organization exists.
+ t.LowerName = strings.ToLower(t.Name)
_, err := x.Insert(t)
return err
}
+// UpdateTeam updates information of team.
func UpdateTeam(t *Team) error {
if len(t.Description) > 255 {
t.Description = t.Description[:255]
}
+ t.LowerName = strings.ToLower(t.Name)
_, err := x.Id(t.Id).AllCols().Update(t)
return err
}
@@ -192,16 +219,18 @@ func GetOrgUsersByOrgId(orgId int64) ([]*OrgUser, error) {
return ous, err
}
-func GetOrganizationCount(u *User) (int64, error) {
- return x.Where("uid=?", u.Id).Count(new(OrgUser))
-}
-
-// IsOrganizationOwner returns true if given user ID is in the owner team.
+// IsOrganizationOwner returns true if given user is in the owner team.
func IsOrganizationOwner(orgId, uid int64) bool {
has, _ := x.Where("is_owner=?", true).Get(&OrgUser{Uid: uid, OrgId: orgId})
return has
}
+// IsOrganizationMember returns true if given user is member of organization.
+func IsOrganizationMember(orgId, uid int64) bool {
+ has, _ := x.Get(&OrgUser{Uid: uid, OrgId: orgId})
+ return has
+}
+
// ___________ ____ ___
// \__ ___/___ _____ _____ | | \______ ___________
// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
diff --git a/models/user.go b/models/user.go
index 9b0bdebe6b..d273d57f9f 100644
--- a/models/user.go
+++ b/models/user.go
@@ -73,6 +73,8 @@ type User struct {
Description string
NumTeams int
NumMembers int
+ Teams []*Team `xorm:"-"`
+ Members []*User `xorm:"-"`
}
// HomeLink returns the user home page link.
@@ -110,6 +112,11 @@ func (u *User) IsOrganization() bool {
return u.Type == ORGANIZATION
}
+// GetOrganizationCount returns count of membership of organization of user.
+func (u *User) GetOrganizationCount() (int64, error) {
+ return x.Where("uid=?", u.Id).Count(new(OrgUser))
+}
+
// GetOrganizations returns all organizations that user belongs to.
func (u *User) GetOrganizations() error {
ous, err := GetOrgUsersByUserId(u.Id)
@@ -331,7 +338,7 @@ func DeleteUser(u *User) error {
}
// Check membership of organization.
- count, err = GetOrganizationCount(u)
+ count, err = u.GetOrganizationCount()
if err != nil {
return errors.New("modesl.GetRepositories(GetOrganizationCount): " + err.Error())
} else if count > 0 {
diff --git a/routers/org/org.go b/routers/org/org.go
index 7b2c4d7320..ba4adc5b5a 100644
--- a/routers/org/org.go
+++ b/routers/org/org.go
@@ -16,13 +16,45 @@ import (
)
const (
+ HOME base.TplName = "org/home"
NEW base.TplName = "org/new"
SETTINGS base.TplName = "org/settings"
)
-func Organization(ctx *middleware.Context, params martini.Params) {
+func Home(ctx *middleware.Context, params martini.Params) {
ctx.Data["Title"] = "Organization " + params["org"]
- ctx.HTML(200, "org/org")
+
+ org, err := models.GetUserByName(params["org"])
+ if err != nil {
+ if err == models.ErrUserNotExist {
+ ctx.Handle(404, "org.Home(GetUserByName)", err)
+ } else {
+ ctx.Handle(500, "org.Home(GetUserByName)", err)
+ }
+ return
+ }
+ ctx.Data["Org"] = org
+
+ ctx.Data["Repos"], err = models.GetRepositories(org.Id,
+ ctx.IsSigned && models.IsOrganizationMember(org.Id, ctx.User.Id))
+ if err != nil {
+ ctx.Handle(500, "org.Home(GetRepositories)", err)
+ return
+ }
+
+ if err = org.GetMembers(); err != nil {
+ ctx.Handle(500, "org.Home(GetMembers)", err)
+ return
+ }
+ ctx.Data["Members"] = org.Members
+
+ if err = org.GetTeams(); err != nil {
+ ctx.Handle(500, "org.Home(GetTeams)", err)
+ return
+ }
+ ctx.Data["Teams"] = org.Teams
+
+ ctx.HTML(200, HOME)
}
func Members(ctx *middleware.Context, params martini.Params) {
@@ -63,7 +95,7 @@ func NewPost(ctx *middleware.Context, form auth.CreateOrgForm) {
ctx.Data["Err_OrgName"] = true
ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), NEW, &form)
default:
- ctx.Handle(500, "user.NewPost(CreateUser)", err)
+ ctx.Handle(500, "org.NewPost(CreateUser)", err)
}
return
}
diff --git a/routers/repo/repo.go b/routers/repo/repo.go
index 6cb6c0660e..54e5fcfb20 100644
--- a/routers/repo/repo.go
+++ b/routers/repo/repo.go
@@ -37,11 +37,23 @@ func Create(ctx *middleware.Context) {
ctx.Data["LanguageIgns"] = models.LanguageIgns
ctx.Data["Licenses"] = models.Licenses
+ ctxUser := ctx.User
+ orgId, _ := base.StrTo(ctx.Query("org")).Int64()
+ if orgId > 0 {
+ org, err := models.GetUserById(orgId)
+ if err != nil && err != models.ErrUserNotExist {
+ ctx.Handle(500, "home.Dashboard(GetUserById)", err)
+ return
+ }
+ ctxUser = org
+ }
+ ctx.Data["ContextUser"] = ctxUser
+
if err := ctx.User.GetOrganizations(); err != nil {
ctx.Handle(500, "home.Dashboard(GetOrganizations)", err)
return
}
- ctx.Data["Orgs"] = ctx.User.Orgs
+ ctx.Data["AllUsers"] = append([]*models.User{ctx.User}, ctx.User.Orgs...)
ctx.HTML(200, CREATE)
}
@@ -76,6 +88,12 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) {
}
return
}
+
+ // Check ownership of organization.
+ if !models.IsOrganizationOwner(u.Id, ctx.User.Id) {
+ ctx.Error(403)
+ return
+ }
}
repo, err := models.CreateRepository(u, form.RepoName, form.Description,
diff --git a/routers/user/home.go b/routers/user/home.go
index 86907b5a90..02dc1de154 100644
--- a/routers/user/home.go
+++ b/routers/user/home.go
@@ -83,6 +83,12 @@ func Profile(ctx *middleware.Context, params martini.Params) {
}
return
}
+
+ if u.IsOrganization() {
+ ctx.Redirect("/org/" + u.Name)
+ return
+ }
+
// For security reason, hide e-mail address for anonymous visitors.
if !ctx.IsSigned {
u.Email = ""
diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl
new file mode 100644
index 0000000000..a3c2326230
--- /dev/null
+++ b/templates/org/home.tmpl
@@ -0,0 +1,70 @@
+{{template "base/head" .}}
+{{template "base/navbar" .}}
+<div id="body-nav" class="org-nav">
+ <div class="container clearfix">
+ <div class="col-md-8" id="org-nav-wrapper">
+ <img class="pull-left org-logo" src="{{.Org.AvatarLink}}?s=140" alt="" width="100"/>
+ <div id="org-nav-info">
+ <h2 class="org-name">{{.Org.FullName}}</h2>
+ {{if .Org.Description}}<p class="org-description">{{.Org.Description}}</p>{{end}}
+ <ul class="org-meta list-inline">
+ {{if .Org.Website}}<li><i class="fa fa-link"></i><a target="_blank" href="{{.Org.Website}}">{{.Org.Website}}</a></li>{{end}}
+ <li><i class="fa fa-envelope"></i><a href="mailto:{{.Org.Email}}">{{.Org.Email}}</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+</div>
+<div id="body" class="container">
+ <div id="org">
+ <div class="org-main col-md-8">
+ <div class="org-toolbar clearfix">
+ <a class="btn pull-right btn-success" href="/repo/create?org={{.Org.Id}}"><i class="fa fa-plus"></i> New Repository</a>
+ </div>
+ <hr style="width: 100%;border-color: #DDD"/>
+ <div class="org-repo-list" id="org-repo-list">
+ {{range .Repos}}
+ <div class="org-repo-item">
+ <div class="org-repo-status pull-right">
+ <!-- <ul class="list-inline">
+ <li><strong>Go</strong></li>
+ <li><i class="i fa fa-star"></i><strong>6</strong></li>
+ <li><i class="fa fa-code-fork"></i><strong>2</strong></li>
+ </ul> -->
+ </div>
+ <h3 class="org-repo-name"><a href="/{{$.Org.Name}}/{{.Name}}">{{.Name}}</a></h3>
+ <p class="org-repo-description">{{.Description}}</p>
+ <p class="org-repo-update">Updated {{TimeSince .Updated}}</p>
+ </div>
+ {{end}}
+ </div>
+ </div>
+
+ <div class="org-sidebar col-md-4">
+ <div class="org-panel panel panel-default" id="org-sidebar-members">
+ <div class="panel-heading"><strong><a href="/org/{{$.Org.Name}}/members">Members</a></strong></div>
+ <div class="panel-body">
+ {{range .Members}}
+ <a class="org-member" href="/user/{{.Name}}" data-toggle="tooltip" title="{{.Name}}" data-placement="bottom"><img src="{{.AvatarLink}}?s=140" alt=""/></a>
+ {{end}}
+ </div>
+ </div>
+ <div class="org-panel panel panel-default" id="org-sidebar-teams">
+ <div class="panel-heading"><strong><a href="/org/{{$.Org.Name}}/teams">Teams</a></strong></div>
+ <div class="panel-body">
+ {{range .Teams}}
+ <div class="org-team">
+ <a href="/org/{{$.Org.Name}}/teams/{{.LowerName}}">
+ <p class="org-team-name"><strong>{{.Name}}</strong></p>
+ <p class="org-team-meta">
+ {{.NumMembers}} members · {{.NumRepos}} repositories
+ </p>
+ </a>
+ </div>
+ {{end}}
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+{{template "base/footer" .}}
diff --git a/templates/org/org.tmpl b/templates/org/org.tmpl
deleted file mode 100644
index 872e50be86..0000000000
--- a/templates/org/org.tmpl
+++ /dev/null
@@ -1,85 +0,0 @@
-{{template "base/head" .}}
-{{template "base/navbar" .}}
-<div id="body-nav" class="org-nav">
- <div class="container clearfix">
- <div class="col-md-8" id="org-nav-wrapper">
- <img class="pull-left org-logo" src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt="" width="100"/>
- <div id="org-nav-info">
- <h2 class="org-name">Organization Name</h2>
- <p class="org-description">Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language.</p>
- <ul class="org-meta list-inline">
- <li><i class="fa fa-link"></i><a href="#">http://gogs.io</a></li>
- <li><i class="fa fa-envelope"></i><a href="#">info@gogs.io</a></li>
- </ul>
- </div>
- </div>
- </div>
-</div>
-<div id="body" class="container">
- <div id="org">
- <div class="org-main col-md-8">
- <div class="org-toolbar clearfix">
- <button class="btn pull-right btn-success"><i class="fa fa-plus"></i> New Repository</button>
- </div>
- <hr style="width: 100%;border-color: #DDD"/>
- <div class="org-repo-list" id="org-repo-list">
- <div class="org-repo-item">
- <div class="org-repo-status pull-right">
- <ul class="list-inline">
- <li><strong>Go</strong></li>
- <li><i class="i fa fa-star"></i><strong>6</strong></li>
- <li><i class="fa fa-code-fork"></i><strong>2</strong></li>
- </ul>
- </div>
- <h3 class="org-repo-name"><a href="#">gogs</a></h3>
- <p class="org-repo-description">Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language.</p>
- <p class="org-repo-update">Updated 17 hours ago</p>
- </div>
- <div class="org-repo-item">
- <div class="org-repo-status pull-right">
- <ul class="list-inline">
- <li><strong>Go</strong></li>
- <li><i class="i fa fa-star"></i><strong>6</strong></li>
- <li><i class="fa fa-code-fork"></i><strong>2</strong></li>
- </ul>
- </div>
- <h3 class="org-repo-name"><a href="#">gogs</a></h3>
- <p class="org-repo-description">Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language.</p>
- <p class="org-repo-update">Updated 17 hours ago</p>
- </div>
- </div>
- </div>
- <div class="org-sidebar col-md-4">
- <div class="org-panel panel panel-default" id="org-sidebar-members">
- <div class="panel-heading"><strong>Members</strong></div>
- <div class="panel-body">
- <a class="org-member" href="#" data-toggle="tooltip" title="username" data-placement="bottom"><img src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt=""/></a>
- <a class="org-member" href="#" data-toggle="tooltip" title="username" data-placement="bottom"><img src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt=""/></a>
- <a class="org-member" href="#" data-toggle="tooltip" title="username" data-placement="bottom"><img src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt=""/></a>
- </div>
- </div>
- <div class="org-panel panel panel-default" id="org-sidebar-teams">
- <div class="panel-heading"><strong>Teams</strong></div>
- <div class="panel-body">
- <div class="org-team">
- <a href="#">
- <p class="org-team-name"><strong>Team name</strong></p>
- <p class="org-team-meta">
- 4 members · 10 repositories
- </p>
- </a>
- </div>
- <div class="org-team">
- <a href="#">
- <p class="org-team-name"><strong>Team name</strong></p>
- <p class="org-team-meta">
- 4 members · 10 repositories
- </p>
- </a>
- </div>
- </div>
- </div>
- </div>
- </div>
-</div>
-{{template "base/footer" .}}
diff --git a/templates/repo/create.tmpl b/templates/repo/create.tmpl
index 38b32a3bfc..ed01d9772b 100644
--- a/templates/repo/create.tmpl
+++ b/templates/repo/create.tmpl
@@ -10,23 +10,16 @@
<div class="col-md-8">
<div class="btn-group" id="repo-owner-switch">
<button type="button" class="btn btn-default" id="repo-owner-current">
- <img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username" id="repo-owner-avatar">
- <span id="repo-owner-name">{{.SignedUser.Name}}</span>
+ <img src="{{.ContextUser.AvatarLink}}?s=28" alt="user-avatar" title="username" id="repo-owner-avatar">
+ <span id="repo-owner-name">{{.ContextUser.Name}}</span>
</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 data-uid="{{.SignedUser.Id}}" class="checked">
- <a>
- <i class="fa fa-check"></i>
- <img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username">
- {{.SignedUser.Name}}
- </a>
- </li>
- {{range .Orgs}}
- <li data-uid="{{.Id}}">
+ {{range .AllUsers}}
+ <li data-uid="{{.Id}}"{{if eq .Id $.ContextUser.Id}}class="checked"{{end}}>
<a>
<i class="fa fa-check"></i>
<img src="{{.AvatarLink}}?s=28" alt="user-avatar" title="username">
@@ -38,7 +31,7 @@
</div>
</div>
</div>
- <input type="hidden" value="{{.SignedUserId}}" name="uid" id="repo-owner-id"/>
+ <input type="hidden" value="{{.ContextUser.Id}}" name="uid" id="repo-owner-id"/>
</div>
<div class="form-group {{if .Err_RepoName}}has-error has-feedback{{end}}">