diff options
-rw-r--r-- | cmd/web.go | 2 | ||||
-rw-r--r-- | models/org.go | 41 | ||||
-rw-r--r-- | models/user.go | 9 | ||||
-rw-r--r-- | routers/org/org.go | 38 | ||||
-rw-r--r-- | routers/repo/repo.go | 20 | ||||
-rw-r--r-- | routers/user/home.go | 6 | ||||
-rw-r--r-- | templates/org/home.tmpl | 70 | ||||
-rw-r--r-- | templates/org/org.tmpl | 85 | ||||
-rw-r--r-- | templates/repo/create.tmpl | 17 |
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}}"> |