@@ -194,13 +194,14 @@ func runWeb(*cli.Context) { | |||
r.Get("/:org", org.Organization) | |||
r.Get("/:org/dashboard", org.Dashboard) | |||
r.Get("/:org/members", org.Members) | |||
// organization teams | |||
r.Get("/:org/teams/:team/edit", org.EditTeam) | |||
r.Get("/:org/teams/new", org.NewTeam) | |||
r.Get("/:org/teams", org.Teams) | |||
r.Get("/:org/settings", org.Settings) | |||
r.Post("/:org/settings", bindIgnErr(auth.OrgSettingForm{}), org.SettingsPost) | |||
r.Post("/:org/settings/delete", org.DeletePost) | |||
}, reqSignIn) | |||
m.Group("/:username/:reponame", func(r martini.Router) { |
@@ -17,7 +17,7 @@ import ( | |||
"github.com/gogits/gogs/modules/setting" | |||
) | |||
const APP_VER = "0.4.5.0627 Alpha" | |||
const APP_VER = "0.4.5.0628 Alpha" | |||
func init() { | |||
runtime.GOMAXPROCS(runtime.NumCPU()) |
@@ -10,6 +10,16 @@ import ( | |||
"github.com/gogits/gogs/modules/base" | |||
) | |||
// GetOwnerTeam returns owner team of organization. | |||
func (org *User) GetOwnerTeam() (*Team, error) { | |||
t := &Team{ | |||
OrgId: org.Id, | |||
Name: OWNER_TEAM, | |||
} | |||
_, err := x.Get(t) | |||
return t, err | |||
} | |||
// CreateOrganization creates record of a new organization. | |||
func CreateOrganization(org, owner *User) (*User, error) { | |||
if !IsLegalName(org.Name) { | |||
@@ -86,6 +96,34 @@ func CreateOrganization(org, owner *User) (*User, error) { | |||
return org, sess.Commit() | |||
} | |||
// TODO: need some kind of mechanism to record failure. | |||
// DeleteOrganization completely and permanently deletes everything of organization. | |||
func DeleteOrganization(org *User) (err error) { | |||
if err := DeleteUser(org); err != nil { | |||
return err | |||
} | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
if err = sess.Begin(); err != nil { | |||
return err | |||
} | |||
if _, err = sess.Delete(&Team{OrgId: org.Id}); err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
if _, err = sess.Delete(&OrgUser{OrgId: org.Id}); err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
if _, err = sess.Delete(&TeamUser{OrgId: org.Id}); err != nil { | |||
sess.Rollback() | |||
return err | |||
} | |||
return sess.Commit() | |||
} | |||
type AuthorizeType int | |||
const ( | |||
@@ -158,6 +196,12 @@ 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. | |||
func IsOrganizationOwner(orgId, uid int64) bool { | |||
has, _ := x.Where("is_owner=?", true).Get(&OrgUser{Uid: uid, OrgId: orgId}) | |||
return has | |||
} | |||
// ___________ ____ ___ | |||
// \__ ___/___ _____ _____ | | \______ ___________ | |||
// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \ |
@@ -733,7 +733,7 @@ func UpdateRepository(repo *Repository) error { | |||
} | |||
// DeleteRepository deletes a repository for a user or orgnaztion. | |||
func DeleteRepository(userId, repoId int64, userName string) (err error) { | |||
func DeleteRepository(userId, repoId int64, userName string) error { | |||
repo := &Repository{Id: repoId, OwnerId: userId} | |||
has, err := x.Get(repo) | |||
if err != nil { | |||
@@ -747,6 +747,7 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) { | |||
if err = sess.Begin(); err != nil { | |||
return err | |||
} | |||
if _, err = sess.Delete(&Repository{Id: repoId}); err != nil { | |||
sess.Rollback() | |||
return err |
@@ -105,10 +105,12 @@ func (u *User) EncodePasswd() { | |||
u.Passwd = fmt.Sprintf("%x", newPasswd) | |||
} | |||
// IsOrganization returns true if user is actually a organization. | |||
func (u *User) IsOrganization() bool { | |||
return u.Type == ORGANIZATION | |||
} | |||
// GetOrganizations returns all organizations that user belongs to. | |||
func (u *User) GetOrganizations() error { | |||
ous, err := GetOrgUsersByUserId(u.Id) | |||
if err != nil { | |||
@@ -125,16 +127,6 @@ func (u *User) GetOrganizations() error { | |||
return nil | |||
} | |||
// GetOwnerTeam returns owner team of organization. | |||
func (org *User) GetOwnerTeam() (*Team, error) { | |||
t := &Team{ | |||
OrgId: org.Id, | |||
Name: OWNER_TEAM, | |||
} | |||
_, err := x.Get(t) | |||
return t, err | |||
} | |||
// IsUserExist checks if given user name exist, | |||
// the user name should be noncased unique. | |||
func IsUserExist(name string) (bool, error) { | |||
@@ -327,7 +319,8 @@ func UpdateUser(u *User) (err error) { | |||
return err | |||
} | |||
// DeleteUser completely deletes everything of the user. | |||
// TODO: need some kind of mechanism to record failure. | |||
// DeleteUser completely and permanently deletes everything of user. | |||
func DeleteUser(u *User) error { | |||
// Check ownership of repository. | |||
count, err := GetRepositoryCount(u) | |||
@@ -346,32 +339,28 @@ func DeleteUser(u *User) error { | |||
} | |||
// TODO: check issues, other repos' commits | |||
// TODO: roll backable in some point. | |||
// Delete all followers. | |||
if _, err = x.Delete(&Follow{FollowId: u.Id}); err != nil { | |||
return err | |||
} | |||
// Delete oauth2. | |||
if _, err = x.Delete(&Oauth2{Uid: u.Id}); err != nil { | |||
return err | |||
} | |||
// Delete all feeds. | |||
if _, err = x.Delete(&Action{UserId: u.Id}); err != nil { | |||
return err | |||
} | |||
// Delete all watches. | |||
if _, err = x.Delete(&Watch{UserId: u.Id}); err != nil { | |||
return err | |||
} | |||
// Delete all accesses. | |||
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: u.Id}); err != nil { |
@@ -44,6 +44,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler { | |||
repoName := params["reponame"] | |||
refName := params["branchname"] | |||
// TODO: need more advanced onwership and access level check. | |||
// 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.WRITABLE) |
@@ -30,7 +30,6 @@ func Members(ctx *middleware.Context, params martini.Params) { | |||
ctx.HTML(200, "org/members") | |||
} | |||
func New(ctx *middleware.Context) { | |||
ctx.Data["Title"] = "Create An Organization" | |||
ctx.HTML(200, NEW) | |||
@@ -160,3 +159,47 @@ func SettingsPost(ctx *middleware.Context, params martini.Params, form auth.OrgS | |||
ctx.Flash.Success("Organization profile has been successfully updated.") | |||
ctx.Redirect("/org/" + org.Name + "/settings") | |||
} | |||
func DeletePost(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.DeletePost(GetUserByName)", err) | |||
} else { | |||
ctx.Handle(500, "org.DeletePost(GetUserByName)", err) | |||
} | |||
return | |||
} | |||
ctx.Data["Org"] = org | |||
if !models.IsOrganizationOwner(org.Id, ctx.User.Id) { | |||
ctx.Error(403) | |||
return | |||
} | |||
tmpUser := models.User{ | |||
Passwd: ctx.Query("password"), | |||
Salt: ctx.User.Salt, | |||
} | |||
tmpUser.EncodePasswd() | |||
if tmpUser.Passwd != ctx.User.Passwd { | |||
ctx.Flash.Error("Password is not correct. Make sure you are owner of this account.") | |||
} else { | |||
if err := models.DeleteOrganization(org); err != nil { | |||
switch err { | |||
case models.ErrUserOwnRepos: | |||
ctx.Flash.Error("This organization still have ownership of repository, you have to delete or transfer them first.") | |||
default: | |||
ctx.Handle(500, "org.DeletePost(DeleteOrganization)", err) | |||
return | |||
} | |||
} else { | |||
ctx.Redirect("/") | |||
return | |||
} | |||
} | |||
ctx.Redirect("/org/" + org.Name + "/settings") | |||
} |
@@ -122,13 +122,23 @@ func SettingPost(ctx *middleware.Context, form auth.RepoSettingForm) { | |||
return | |||
} | |||
if err := models.DeleteRepository(ctx.User.Id, ctx.Repo.Repository.Id, ctx.User.LowerName); err != nil { | |||
ctx.Handle(500, "setting.Delete", err) | |||
if ctx.Repo.Owner.IsOrganization() && | |||
!models.IsOrganizationOwner(ctx.Repo.Owner.Id, ctx.User.Id) { | |||
ctx.Error(403) | |||
return | |||
} | |||
log.Trace("%s Repository deleted: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, ctx.Repo.Repository.LowerName) | |||
ctx.Redirect("/") | |||
if err := models.DeleteRepository(ctx.Repo.Owner.Id, ctx.Repo.Repository.Id, ctx.Repo.Owner.Name); err != nil { | |||
ctx.Handle(500, "setting.Delete(DeleteRepository)", err) | |||
return | |||
} | |||
log.Trace("%s Repository deleted: %s/%s", ctx.Req.RequestURI, ctx.Repo.Owner.LowerName, ctx.Repo.Repository.LowerName) | |||
if ctx.Repo.Owner.IsOrganization() { | |||
ctx.Redirect("/org/" + ctx.Repo.Owner.Name + "/dashboard") | |||
} else { | |||
ctx.Redirect("/") | |||
} | |||
} | |||
} | |||
@@ -296,7 +296,7 @@ func DeletePost(ctx *middleware.Context) { | |||
case models.ErrUserOwnRepos: | |||
ctx.Flash.Error("Your account still have ownership of repository, you have to delete or transfer them first.") | |||
default: | |||
ctx.Handle(500, "user.Delete(DeleteUser)", err) | |||
ctx.Handle(500, "user.DeletePost(DeleteUser)", err) | |||
return | |||
} | |||
} else { |
@@ -1 +1 @@ | |||
0.4.5.0627 Alpha | |||
0.4.5.0628 Alpha |
@@ -76,7 +76,7 @@ | |||
<div class="panel-body"> | |||
<ul class="list-group">{{range .MyRepos}} | |||
<li class="list-group-item"><a href="/{{$.SignedUserName}}/{{.Name}}"> | |||
<li class="list-group-item"><a href="/{{$.ContextUser.Name}}/{{.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}} |