summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUnknown <joe2010xtmf@163.com>2014-06-27 03:37:01 -0400
committerUnknown <joe2010xtmf@163.com>2014-06-27 03:37:01 -0400
commit19e910428951135b9a341554dad54a6546d2ad50 (patch)
treefde86e17d1cfccd3fb42b1f57f0f1eb9f0f9b9be
parent32b09681b2da96afe9a44790e7944c4ac51e696c (diff)
downloadgitea-19e910428951135b9a341554dad54a6546d2ad50.tar.gz
gitea-19e910428951135b9a341554dad54a6546d2ad50.zip
Organization settings page
-rw-r--r--cmd/web.go5
-rw-r--r--gogs.go2
-rw-r--r--models/org.go86
-rw-r--r--models/repo.go2
-rw-r--r--models/user.go114
-rw-r--r--modules/auth/org.go30
-rw-r--r--modules/auth/repo.go2
-rw-r--r--modules/auth/user.go2
-rw-r--r--routers/org/org.go56
-rw-r--r--templates/VERSION2
-rw-r--r--templates/org/settings.tmpl (renamed from templates/org/setting.tmpl)56
11 files changed, 217 insertions, 140 deletions
diff --git a/cmd/web.go b/cmd/web.go
index 878fdeac70..729a1ba28f 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -190,12 +190,13 @@ func runWeb(*cli.Context) {
m.Group("/org", func(r martini.Router) {
r.Get("/create", org.New)
- r.Post("/create", bindIgnErr(auth.CreateOrganizationForm{}), org.NewPost)
+ r.Post("/create", bindIgnErr(auth.CreateOrgForm{}), 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)
+ r.Get("/:org/settings", org.Settings)
+ r.Post("/:org/settings", bindIgnErr(auth.OrgSettingForm{}), org.SettingsPost)
}, reqSignIn)
m.Group("/:username/:reponame", func(r martini.Router) {
diff --git a/gogs.go b/gogs.go
index 5c2c6ed943..d56760ab24 100644
--- a/gogs.go
+++ b/gogs.go
@@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-const APP_VER = "0.4.5.0625 Alpha"
+const APP_VER = "0.4.5.0627 Alpha"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
diff --git a/models/org.go b/models/org.go
index 227151ab02..553a46aa0b 100644
--- a/models/org.go
+++ b/models/org.go
@@ -4,6 +4,88 @@
package models
+import (
+ "strings"
+
+ "github.com/gogits/gogs/modules/base"
+)
+
+// CreateOrganization creates record of a new organization.
+func CreateOrganization(org, owner *User) (*User, error) {
+ if !IsLegalName(org.Name) {
+ return nil, ErrUserNameIllegal
+ }
+
+ isExist, err := IsUserExist(org.Name)
+ if err != nil {
+ return nil, err
+ } else if isExist {
+ return nil, ErrUserAlreadyExist
+ }
+
+ isExist, err = IsEmailUsed(org.Email)
+ if err != nil {
+ return nil, err
+ } else if isExist {
+ return nil, ErrEmailAlreadyUsed
+ }
+
+ org.LowerName = strings.ToLower(org.Name)
+ org.FullName = 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
+ }
+
+ // Create default owner team.
+ t := &Team{
+ OrgId: org.Id,
+ Name: OWNER_TEAM,
+ Authorize: ORG_ADMIN,
+ NumMembers: 1,
+ }
+ if _, err = sess.Insert(t); err != nil {
+ sess.Rollback()
+ return nil, err
+ }
+
+ // Add initial creator to organization and owner team.
+ ou := &OrgUser{
+ Uid: owner.Id,
+ OrgId: org.Id,
+ IsOwner: true,
+ NumTeam: 1,
+ }
+ 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()
+}
+
type AuthorizeType int
const (
@@ -72,6 +154,10 @@ func GetOrgUsersByOrgId(orgId int64) ([]*OrgUser, error) {
return ous, err
}
+func GetOrganizationCount(u *User) (int64, error) {
+ return x.Where("uid=?", u.Id).Count(new(OrgUser))
+}
+
// ___________ ____ ___
// \__ ___/___ _____ _____ | | \______ ___________
// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
diff --git a/models/repo.go b/models/repo.go
index 840529b959..85f2a913d3 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -240,7 +240,7 @@ func MirrorUpdate() {
"git", "remote", "update"); err != nil {
return errors.New("git remote update: " + stderr)
} else if err = git.UnpackRefs(repoPath); err != nil {
- return err
+ return errors.New("UnpackRefs: " + err.Error())
}
m.NextUpdate = time.Now().Add(time.Duration(m.Interval) * time.Hour)
diff --git a/models/user.go b/models/user.go
index f67911ca6c..8ffad26632 100644
--- a/models/user.go
+++ b/models/user.go
@@ -30,6 +30,7 @@ const (
var (
ErrUserOwnRepos = errors.New("User still have ownership of repositories")
+ ErrUserHasOrgs = errors.New("User still have membership of organization")
ErrUserAlreadyExist = errors.New("User already exist")
ErrUserNotExist = errors.New("User does not exist")
ErrUserNotKeyOwner = errors.New("User does not the owner of public key")
@@ -69,8 +70,9 @@ type User struct {
Updated time.Time `xorm:"updated"`
// For organization.
- NumTeams int
- NumMembers int
+ Description string
+ NumTeams int
+ NumMembers int
}
// HomeLink returns the user home page link.
@@ -211,81 +213,6 @@ func CreateUser(u *User) (*User, error) {
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(org.Name)
- if err != nil {
- return nil, err
- } else if isExist {
- return nil, ErrUserAlreadyExist
- }
-
- isExist, err = IsEmailUsed(org.Email)
- if err != nil {
- return nil, err
- } else if isExist {
- return nil, ErrEmailAlreadyUsed
- }
-
- 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
- }
-
- // Create default owner team.
- t := &Team{
- OrgId: org.Id,
- Name: OWNER_TEAM,
- Authorize: ORG_ADMIN,
- NumMembers: 1,
- }
- if _, err = sess.Insert(t); err != nil {
- sess.Rollback()
- return nil, err
- }
-
- // Add initial creator to organization and owner team.
- ou := &OrgUser{
- Uid: owner.Id,
- OrgId: org.Id,
- IsOwner: true,
- NumTeam: 1,
- }
- 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.
func GetUsers(num, offset int) ([]User, error) {
users := make([]User, 0, num)
@@ -392,51 +319,62 @@ func UpdateUser(u *User) (err error) {
if len(u.Website) > 255 {
u.Website = u.Website[:255]
}
+ if len(u.Description) > 255 {
+ u.Description = u.Description[:255]
+ }
_, err = x.Id(u.Id).AllCols().Update(u)
return err
}
// DeleteUser completely deletes everything of the user.
-func DeleteUser(user *User) error {
+func DeleteUser(u *User) error {
// Check ownership of repository.
- count, err := GetRepositoryCount(user)
+ count, err := GetRepositoryCount(u)
if err != nil {
- return errors.New("modesl.GetRepositories: " + err.Error())
+ return errors.New("modesl.GetRepositories(GetRepositoryCount): " + err.Error())
} else if count > 0 {
return ErrUserOwnRepos
}
+ // Check membership of organization.
+ count, err = GetOrganizationCount(u)
+ if err != nil {
+ return errors.New("modesl.GetRepositories(GetOrganizationCount): " + err.Error())
+ } else if count > 0 {
+ return ErrUserHasOrgs
+ }
+
// TODO: check issues, other repos' commits
// Delete all followers.
- if _, err = x.Delete(&Follow{FollowId: user.Id}); err != nil {
+ if _, err = x.Delete(&Follow{FollowId: u.Id}); err != nil {
return err
}
// Delete oauth2.
- if _, err = x.Delete(&Oauth2{Uid: user.Id}); err != nil {
+ if _, err = x.Delete(&Oauth2{Uid: u.Id}); err != nil {
return err
}
// Delete all feeds.
- if _, err = x.Delete(&Action{UserId: user.Id}); err != nil {
+ if _, err = x.Delete(&Action{UserId: u.Id}); err != nil {
return err
}
// Delete all watches.
- if _, err = x.Delete(&Watch{UserId: user.Id}); err != nil {
+ if _, err = x.Delete(&Watch{UserId: u.Id}); err != nil {
return err
}
// Delete all accesses.
- if _, err = x.Delete(&Access{UserName: user.LowerName}); err != nil {
+ if _, err = x.Delete(&Access{UserName: u.LowerName}); err != nil {
return err
}
// Delete all SSH keys.
keys := make([]*PublicKey, 0, 10)
- if err = x.Find(&keys, &PublicKey{OwnerId: user.Id}); err != nil {
+ if err = x.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil {
return err
}
for _, key := range keys {
@@ -446,11 +384,11 @@ func DeleteUser(user *User) error {
}
// Delete user directory.
- if err = os.RemoveAll(UserPath(user.Name)); err != nil {
+ if err = os.RemoveAll(UserPath(u.Name)); err != nil {
return err
}
- _, err = x.Delete(user)
+ _, err = x.Delete(u)
return err
}
diff --git a/modules/auth/org.go b/modules/auth/org.go
index a60fbb851e..f87d10a707 100644
--- a/modules/auth/org.go
+++ b/modules/auth/org.go
@@ -14,12 +14,12 @@ import (
"github.com/gogits/gogs/modules/middleware/binding"
)
-type CreateOrganizationForm struct {
+type CreateOrgForm 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 {
+func (f *CreateOrgForm) Name(field string) string {
names := map[string]string{
"OrgName": "Organization name",
"Email": "E-mail address",
@@ -27,7 +27,31 @@ func (f *CreateOrganizationForm) Name(field string) string {
return names[field]
}
-func (f *CreateOrganizationForm) Validate(errs *binding.Errors, req *http.Request, ctx martini.Context) {
+func (f *CreateOrgForm) Validate(errs *binding.Errors, req *http.Request, ctx martini.Context) {
data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
validate(errs, data, f)
}
+
+type OrgSettingForm struct {
+ DisplayName string `form:"display_name" binding:"Required;MaxSize(100)"`
+ Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
+ Description string `form:"desc" binding:"MaxSize(255)"`
+ Website string `form:"site" binding:"Url;MaxSize(100)"`
+ Location string `form:"location" binding:"MaxSize(50)"`
+}
+
+func (f *OrgSettingForm) Name(field string) string {
+ names := map[string]string{
+ "DisplayName": "Display name",
+ "Email": "E-mail address",
+ "Description": "Description",
+ "Website": "Website address",
+ "Location": "Location",
+ }
+ return names[field]
+}
+
+func (f *OrgSettingForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) {
+ data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
+ validate(errors, data, f)
+}
diff --git a/modules/auth/repo.go b/modules/auth/repo.go
index db13743de8..d3d215322a 100644
--- a/modules/auth/repo.go
+++ b/modules/auth/repo.go
@@ -71,7 +71,7 @@ func (f *MigrateRepoForm) Validate(errors *binding.Errors, req *http.Request, co
type RepoSettingForm struct {
RepoName string `form:"name" binding:"Required;AlphaDash;MaxSize(100)"`
- Description string `form:"desc" binding:"MaxSize(100)"`
+ Description string `form:"desc" binding:"MaxSize(255)"`
Website string `form:"site" binding:"Url;MaxSize(100)"`
Branch string `form:"branch"`
Interval int `form:"interval"`
diff --git a/modules/auth/user.go b/modules/auth/user.go
index 20f9933626..4a781acfa5 100644
--- a/modules/auth/user.go
+++ b/modules/auth/user.go
@@ -93,7 +93,7 @@ func (f *UpdateProfileForm) Name(field string) string {
names := map[string]string{
"UserName": "Username",
"Email": "E-mail address",
- "Website": "Website",
+ "Website": "Website address",
"Location": "Location",
"Avatar": "Gravatar Email",
}
diff --git a/routers/org/org.go b/routers/org/org.go
index 0595a81b3d..4f57b9a963 100644
--- a/routers/org/org.go
+++ b/routers/org/org.go
@@ -16,7 +16,8 @@ import (
)
const (
- NEW base.TplName = "org/new"
+ NEW base.TplName = "org/new"
+ SETTINGS base.TplName = "org/settings"
)
func Organization(ctx *middleware.Context, params martini.Params) {
@@ -39,7 +40,7 @@ func New(ctx *middleware.Context) {
ctx.HTML(200, NEW)
}
-func NewPost(ctx *middleware.Context, form auth.CreateOrganizationForm) {
+func NewPost(ctx *middleware.Context, form auth.CreateOrgForm) {
ctx.Data["Title"] = "Create An Organization"
if ctx.HasError() {
@@ -114,7 +115,52 @@ func Dashboard(ctx *middleware.Context, params martini.Params) {
ctx.HTML(200, user.DASHBOARD)
}
-func Setting(ctx *middleware.Context, param martini.Params) {
- ctx.Data["Title"] = "Setting"
- ctx.HTML(200, "org/setting")
+func Settings(ctx *middleware.Context, params martini.Params) {
+ ctx.Data["Title"] = "Settings"
+
+ org, err := models.GetUserByName(params["org"])
+ if err != nil {
+ if err == models.ErrUserNotExist {
+ ctx.Handle(404, "org.Settings(GetUserByName)", err)
+ } else {
+ ctx.Handle(500, "org.Settings(GetUserByName)", err)
+ }
+ return
+ }
+ ctx.Data["Org"] = org
+
+ ctx.HTML(200, SETTINGS)
+}
+
+func SettingsPost(ctx *middleware.Context, params martini.Params, form auth.OrgSettingForm) {
+ ctx.Data["Title"] = "Settings"
+
+ org, err := models.GetUserByName(params["org"])
+ if err != nil {
+ if err == models.ErrUserNotExist {
+ ctx.Handle(404, "org.SettingsPost(GetUserByName)", err)
+ } else {
+ ctx.Handle(500, "org.SettingsPost(GetUserByName)", err)
+ }
+ return
+ }
+ ctx.Data["Org"] = org
+
+ if ctx.HasError() {
+ ctx.HTML(200, SETTINGS)
+ return
+ }
+
+ org.FullName = form.DisplayName
+ org.Email = form.Email
+ org.Description = form.Description
+ org.Website = form.Website
+ org.Location = form.Location
+ if err = models.UpdateUser(org); err != nil {
+ ctx.Handle(500, "org.SettingsPost(UpdateUser)", err)
+ return
+ }
+ log.Trace("%s Organization setting updated: %s", ctx.Req.RequestURI, org.LowerName)
+ ctx.Flash.Success("Organization profile has been successfully updated.")
+ ctx.Redirect("/org/" + org.Name + "/settings")
}
diff --git a/templates/VERSION b/templates/VERSION
index b5cda695b5..be0ebee0f5 100644
--- a/templates/VERSION
+++ b/templates/VERSION
@@ -1 +1 @@
-0.4.5.0625 Alpha \ No newline at end of file
+0.4.5.0627 Alpha \ No newline at end of file
diff --git a/templates/org/setting.tmpl b/templates/org/settings.tmpl
index 1be9707a1a..e19c027d44 100644
--- a/templates/org/setting.tmpl
+++ b/templates/org/settings.tmpl
@@ -4,32 +4,20 @@
<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
+ <img src="{{.Org.AvatarLink}}?s=28" alt="user-avatar" title="username">
+ {{.Org.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>
- </ul>
- </div>-->
</div>
<ul class="nav nav-pills pull-right">
- <li><a href="/">Feed</a></li>
- <li><a href="/issues">Issues</a></li>
- <li class="active"><a href="#">Setting</a></li>
+ <li><a href="/org/{{.Org.Name}}/dashboard/">News Feed</a></li>
+ <li><a href="/org/{{.Org.Name}}/dashboard/issues">Issues</a></li>
+ <li class="active"><a href="/org/{{.Org.Name}}/settings">Settings</a></li>
<!-- <li><a href="/pulls">Pull Requests</a></li>
<li><a href="/stars">Stars</a></li> -->
</ul>
</div>
</div>
+
<div id="body" class="container" data-page="org">
<div id="user-setting-nav" class="col-md-2 repo-setting-nav">
<ul class="list-group">
@@ -40,52 +28,46 @@
{{template "base/alert" .}}
<div class="panel panel-default">
<div class="panel-heading">
- Repository Options
+ Organization Options
</div>
<div class="panel-body">
- <form action="/{{.Owner.Name}}/{{.Repository.Name}}/settings" method="post" class="form-horizontal">
+ <form action="/org/{{.Org.Name}}/settings" method="post" class="form-horizontal">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="update">
- <div class="form-group">
- <label class="col-md-3 text-right" for="org-setting-name">Name</label>
-
+ <div class="form-group{{if .Err_DisplayName}} has-error has-feedback{{end}}">
+ <label class="col-md-3 text-right" for="org-setting-name">Display Name</label>
<div class="col-md-9">
- <input class="form-control" name="name" value="" title="" id="org-setting-name"/>
+ <input class="form-control" name="display_name" value="{{.Org.FullName}}" title="" id="org-setting-name"/>
</div>
</div>
- <div class="form-group">
+ <div class="form-group{{if .Err_Email}} has-error has-feedback{{end}}">
<label class="col-md-3 text-right" for="org-email">Email</label>
-
<div class="col-md-9">
- <input class="form-control" name="email" value="" title="" id="org-email" type="email"/>
+ <input class="form-control" name="email" value="{{.Org.Email}}" title="" id="org-email" type="email"/>
</div>
</div>
- <div class="form-group">
+ <div class="form-group{{if .Err_Description}} has-error has-feedback{{end}}">
<label class="col-md-3 text-right" for="org-desc">Description</label>
-
<div class="col-md-9">
- <textarea class="form-control" name="desc" id="org-desc" rows="3">{{.Repository.Description}}</textarea>
+ <textarea class="form-control" name="desc" id="org-desc" rows="3">{{.Org.Description}}</textarea>
</div>
</div>
- <div class="form-group">
+ <div class="form-group{{if .Err_Website}} has-error has-feedback{{end}}">
<label class="col-md-3 text-right" for="org-site">Official Site</label>
-
<div class="col-md-9">
- <input type="url" class="form-control" name="site" value="{{.Repository.Website}}"
- id="org-site"/>
+ <input type="url" class="form-control" name="site" value="{{.Org.Website}}" id="org-site"/>
</div>
</div>
- <div class="form-group">
+ <div class="form-group{{if .Err_Location}} has-error has-feedback{{end}}">
<label class="col-md-3 text-right" for="org-location">Location</label>
-
<div class="col-md-9">
- <input class="form-control" name="email" value="" title="" id="org-location"/>
+ <input class="form-control" name="location" value="{{.Org.Location}}" title="" id="org-location"/>
</div>
</div>