r.Get("/:org", org.Organization) | r.Get("/:org", org.Organization) | ||||
r.Get("/:org/dashboard", org.Dashboard) | r.Get("/:org/dashboard", org.Dashboard) | ||||
r.Get("/:org/members", org.Members) | r.Get("/:org/members", org.Members) | ||||
// organization teams | |||||
r.Get("/:org/teams/:team/edit", org.EditTeam) | r.Get("/:org/teams/:team/edit", org.EditTeam) | ||||
r.Get("/:org/teams/new", org.NewTeam) | r.Get("/:org/teams/new", org.NewTeam) | ||||
r.Get("/:org/teams", org.Teams) | r.Get("/:org/teams", org.Teams) | ||||
r.Get("/:org/settings", org.Settings) | r.Get("/:org/settings", org.Settings) | ||||
r.Post("/:org/settings", bindIgnErr(auth.OrgSettingForm{}), org.SettingsPost) | r.Post("/:org/settings", bindIgnErr(auth.OrgSettingForm{}), org.SettingsPost) | ||||
r.Post("/:org/settings/delete", org.DeletePost) | |||||
}, reqSignIn) | }, reqSignIn) | ||||
m.Group("/:username/:reponame", func(r martini.Router) { | m.Group("/:username/:reponame", func(r martini.Router) { |
"github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
) | ) | ||||
const APP_VER = "0.4.5.0627 Alpha" | |||||
const APP_VER = "0.4.5.0628 Alpha" | |||||
func init() { | func init() { | ||||
runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) |
"github.com/gogits/gogs/modules/base" | "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. | // CreateOrganization creates record of a new organization. | ||||
func CreateOrganization(org, owner *User) (*User, error) { | func CreateOrganization(org, owner *User) (*User, error) { | ||||
if !IsLegalName(org.Name) { | if !IsLegalName(org.Name) { | ||||
return org, sess.Commit() | 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 | type AuthorizeType int | ||||
const ( | const ( | ||||
return x.Where("uid=?", u.Id).Count(new(OrgUser)) | 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 | |||||
} | |||||
// ___________ ____ ___ | // ___________ ____ ___ | ||||
// \__ ___/___ _____ _____ | | \______ ___________ | // \__ ___/___ _____ _____ | | \______ ___________ | ||||
// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \ | // | |_/ __ \\__ \ / \| | / ___// __ \_ __ \ |
} | } | ||||
// DeleteRepository deletes a repository for a user or orgnaztion. | // 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} | repo := &Repository{Id: repoId, OwnerId: userId} | ||||
has, err := x.Get(repo) | has, err := x.Get(repo) | ||||
if err != nil { | if err != nil { | ||||
if err = sess.Begin(); err != nil { | if err = sess.Begin(); err != nil { | ||||
return err | return err | ||||
} | } | ||||
if _, err = sess.Delete(&Repository{Id: repoId}); err != nil { | if _, err = sess.Delete(&Repository{Id: repoId}); err != nil { | ||||
sess.Rollback() | sess.Rollback() | ||||
return err | return err |
u.Passwd = fmt.Sprintf("%x", newPasswd) | u.Passwd = fmt.Sprintf("%x", newPasswd) | ||||
} | } | ||||
// IsOrganization returns true if user is actually a organization. | |||||
func (u *User) IsOrganization() bool { | func (u *User) IsOrganization() bool { | ||||
return u.Type == ORGANIZATION | return u.Type == ORGANIZATION | ||||
} | } | ||||
// GetOrganizations returns all organizations that user belongs to. | |||||
func (u *User) GetOrganizations() error { | func (u *User) GetOrganizations() error { | ||||
ous, err := GetOrgUsersByUserId(u.Id) | ous, err := GetOrgUsersByUserId(u.Id) | ||||
if err != nil { | if err != nil { | ||||
return nil | 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, | // IsUserExist checks if given user name exist, | ||||
// the user name should be noncased unique. | // the user name should be noncased unique. | ||||
func IsUserExist(name string) (bool, error) { | func IsUserExist(name string) (bool, error) { | ||||
return err | 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 { | func DeleteUser(u *User) error { | ||||
// Check ownership of repository. | // Check ownership of repository. | ||||
count, err := GetRepositoryCount(u) | count, err := GetRepositoryCount(u) | ||||
} | } | ||||
// TODO: check issues, other repos' commits | // TODO: check issues, other repos' commits | ||||
// TODO: roll backable in some point. | |||||
// Delete all followers. | // Delete all followers. | ||||
if _, err = x.Delete(&Follow{FollowId: u.Id}); err != nil { | if _, err = x.Delete(&Follow{FollowId: u.Id}); err != nil { | ||||
return err | return err | ||||
} | } | ||||
// Delete oauth2. | // Delete oauth2. | ||||
if _, err = x.Delete(&Oauth2{Uid: u.Id}); err != nil { | if _, err = x.Delete(&Oauth2{Uid: u.Id}); err != nil { | ||||
return err | return err | ||||
} | } | ||||
// Delete all feeds. | // Delete all feeds. | ||||
if _, err = x.Delete(&Action{UserId: u.Id}); err != nil { | if _, err = x.Delete(&Action{UserId: u.Id}); err != nil { | ||||
return err | return err | ||||
} | } | ||||
// Delete all watches. | // Delete all watches. | ||||
if _, err = x.Delete(&Watch{UserId: u.Id}); err != nil { | if _, err = x.Delete(&Watch{UserId: u.Id}); err != nil { | ||||
return err | return err | ||||
} | } | ||||
// Delete all accesses. | // Delete all accesses. | ||||
if _, err = x.Delete(&Access{UserName: u.LowerName}); err != nil { | if _, err = x.Delete(&Access{UserName: u.LowerName}); err != nil { | ||||
return err | return err | ||||
} | } | ||||
// Delete all SSH keys. | // Delete all SSH keys. | ||||
keys := make([]*PublicKey, 0, 10) | keys := make([]*PublicKey, 0, 10) | ||||
if err = x.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil { | if err = x.Find(&keys, &PublicKey{OwnerId: u.Id}); err != nil { |
repoName := params["reponame"] | repoName := params["reponame"] | ||||
refName := params["branchname"] | refName := params["branchname"] | ||||
// TODO: need more advanced onwership and access level check. | |||||
// Collaborators who have write access can be seen as owners. | // Collaborators who have write access can be seen as owners. | ||||
if ctx.IsSigned { | if ctx.IsSigned { | ||||
ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.WRITABLE) | ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.WRITABLE) |
ctx.HTML(200, "org/members") | ctx.HTML(200, "org/members") | ||||
} | } | ||||
func New(ctx *middleware.Context) { | func New(ctx *middleware.Context) { | ||||
ctx.Data["Title"] = "Create An Organization" | ctx.Data["Title"] = "Create An Organization" | ||||
ctx.HTML(200, NEW) | ctx.HTML(200, NEW) | ||||
ctx.Flash.Success("Organization profile has been successfully updated.") | ctx.Flash.Success("Organization profile has been successfully updated.") | ||||
ctx.Redirect("/org/" + org.Name + "/settings") | 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") | |||||
} |
return | 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 | 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("/") | |||||
} | |||||
} | } | ||||
} | } | ||||
case models.ErrUserOwnRepos: | case models.ErrUserOwnRepos: | ||||
ctx.Flash.Error("Your account still have ownership of repository, you have to delete or transfer them first.") | ctx.Flash.Error("Your account still have ownership of repository, you have to delete or transfer them first.") | ||||
default: | default: | ||||
ctx.Handle(500, "user.Delete(DeleteUser)", err) | |||||
ctx.Handle(500, "user.DeletePost(DeleteUser)", err) | |||||
return | return | ||||
} | } | ||||
} else { | } else { |
0.4.5.0627 Alpha | |||||
0.4.5.0628 Alpha |
<div class="panel-body"> | <div class="panel-body"> | ||||
<ul class="list-group">{{range .MyRepos}} | <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> --> | <!-- <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> | <i class="fa fa-book"></i>{{.Name}}{{if .IsPrivate}} <span class="label label-default">Private</span>{{end}}</a> | ||||
</li>{{end}} | </li>{{end}} |