@@ -182,14 +182,14 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string, | |||
} | |||
// NewRepoAction adds new action for creating repository. | |||
func NewRepoAction(user *User, repo *Repository) (err error) { | |||
if err = NotifyWatchers(&Action{ActUserId: user.Id, ActUserName: user.Name, ActEmail: user.Email, | |||
func NewRepoAction(u *User, repo *Repository) (err error) { | |||
if err = NotifyWatchers(&Action{ActUserId: u.Id, ActUserName: u.Name, ActEmail: u.Email, | |||
OpType: OP_CREATE_REPO, RepoId: repo.Id, RepoName: repo.Name, IsPrivate: repo.IsPrivate}); err != nil { | |||
log.Error("action.NewRepoAction(notify watchers): %d/%s", user.Id, repo.Name) | |||
log.Error("action.NewRepoAction(notify watchers): %d/%s", u.Id, repo.Name) | |||
return err | |||
} | |||
log.Trace("action.NewRepoAction: %s/%s", user.LowerName, repo.LowerName) | |||
log.Trace("action.NewRepoAction: %s/%s", u.LowerName, repo.LowerName) | |||
return err | |||
} | |||
@@ -12,6 +12,8 @@ const ( | |||
ORG_ADMIN | |||
) | |||
const OWNER_TEAM = "Owner" | |||
// Team represents a organization team. | |||
type Team struct { | |||
Id int64 | |||
@@ -19,6 +21,7 @@ type Team struct { | |||
Name string | |||
Description string | |||
Authorize AuthorizeType | |||
RepoIds string `xorm:"TEXT"` | |||
NumMembers int | |||
NumRepos int | |||
} | |||
@@ -29,6 +32,15 @@ func NewTeam(t *Team) error { | |||
return err | |||
} | |||
func UpdateTeam(t *Team) error { | |||
if len(t.Description) > 255 { | |||
t.Description = t.Description[:255] | |||
} | |||
_, err := x.Id(t.Id).AllCols().Update(t) | |||
return err | |||
} | |||
// ________ ____ ___ | |||
// \_____ \_______ ____ | | \______ ___________ | |||
// / | \_ __ \/ ___\| | / ___// __ \_ __ \ | |||
@@ -53,6 +65,13 @@ func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) { | |||
return ous, err | |||
} | |||
// GetOrgUsersByOrgId returns all organization-user relations by organization ID. | |||
func GetOrgUsersByOrgId(orgId int64) ([]*OrgUser, error) { | |||
ous := make([]*OrgUser, 0, 10) | |||
err := x.Where("org_id=?", orgId).Find(&ous) | |||
return ous, err | |||
} | |||
// ___________ ____ ___ | |||
// \__ ___/___ _____ _____ | | \______ ___________ | |||
// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \ | |||
@@ -67,3 +86,21 @@ type TeamUser struct { | |||
OrgId int64 `xorm:"INDEX"` | |||
TeamId int64 | |||
} | |||
// GetTeamMembers returns all members in given team of organization. | |||
func GetTeamMembers(orgId, teamId int64) ([]*User, error) { | |||
tus := make([]*TeamUser, 0, 10) | |||
err := x.Where("org_id=?", orgId).And("team_id=?", teamId).Find(&tus) | |||
if err != nil { | |||
return nil, err | |||
} | |||
us := make([]*User, len(tus)) | |||
for i, tu := range tus { | |||
us[i], err = GetUserById(tu.Uid) | |||
if err != nil { | |||
return nil, err | |||
} | |||
} | |||
return us, nil | |||
} |
@@ -454,21 +454,27 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep | |||
return initRepoCommit(tmpDir, user.NewGitSig()) | |||
} | |||
// CreateRepository creates a repository for given user or orgnaziation. | |||
func CreateRepository(user *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) { | |||
// CreateRepository creates a repository for given user or organization. | |||
func CreateRepository(u *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) { | |||
if !IsLegalName(name) { | |||
return nil, ErrRepoNameIllegal | |||
} | |||
isExist, err := IsRepositoryExist(user, name) | |||
isExist, err := IsRepositoryExist(u, name) | |||
if err != nil { | |||
return nil, err | |||
} else if isExist { | |||
return nil, ErrRepoAlreadyExist | |||
} | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
if err = sess.Begin(); err != nil { | |||
return nil, err | |||
} | |||
repo := &Repository{ | |||
OwnerId: user.Id, | |||
OwnerId: u.Id, | |||
Name: name, | |||
LowerName: strings.ToLower(name), | |||
Description: desc, | |||
@@ -479,69 +485,85 @@ func CreateRepository(user *User, name, desc, lang, license string, private, mir | |||
repo.DefaultBranch = "master" | |||
} | |||
repoPath := RepoPath(user.Name, repo.Name) | |||
sess := x.NewSession() | |||
defer sess.Close() | |||
if err = sess.Begin(); err != nil { | |||
return nil, err | |||
} | |||
if _, err = sess.Insert(repo); err != nil { | |||
if err2 := os.RemoveAll(repoPath); err2 != nil { | |||
log.Error("repo.CreateRepository(repo): %v", err) | |||
return nil, errors.New(fmt.Sprintf( | |||
"delete repo directory %s/%s failed(1): %v", user.Name, repo.Name, err2)) | |||
} | |||
sess.Rollback() | |||
return nil, err | |||
} | |||
var t *Team // Owner team. | |||
mode := WRITABLE | |||
if mirror { | |||
mode = READABLE | |||
} | |||
access := Access{ | |||
UserName: user.LowerName, | |||
RepoName: strings.ToLower(path.Join(user.Name, repo.Name)), | |||
access := &Access{ | |||
UserName: u.LowerName, | |||
RepoName: strings.ToLower(path.Join(u.Name, repo.Name)), | |||
Mode: mode, | |||
} | |||
if _, err = sess.Insert(&access); err != nil { | |||
sess.Rollback() | |||
if err2 := os.RemoveAll(repoPath); err2 != nil { | |||
log.Error("repo.CreateRepository(access): %v", err) | |||
return nil, errors.New(fmt.Sprintf( | |||
"delete repo directory %s/%s failed(2): %v", user.Name, repo.Name, err2)) | |||
// Give access to all members in owner team. | |||
if u.IsOrganization() { | |||
t, err = u.GetOwnerTeam() | |||
if err != nil { | |||
sess.Rollback() | |||
return nil, err | |||
} | |||
us, err := GetTeamMembers(u.Id, t.Id) | |||
if err != nil { | |||
sess.Rollback() | |||
return nil, err | |||
} | |||
for _, u := range us { | |||
access.UserName = u.LowerName | |||
if _, err = sess.Insert(access); err != nil { | |||
sess.Rollback() | |||
return nil, err | |||
} | |||
} | |||
} else { | |||
if _, err = sess.Insert(access); err != nil { | |||
sess.Rollback() | |||
return nil, err | |||
} | |||
return nil, err | |||
} | |||
rawSql := "UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?" | |||
if _, err = sess.Exec(rawSql, user.Id); err != nil { | |||
if _, err = sess.Exec(rawSql, u.Id); err != nil { | |||
sess.Rollback() | |||
if err2 := os.RemoveAll(repoPath); err2 != nil { | |||
log.Error("repo.CreateRepository(repo count): %v", err) | |||
return nil, errors.New(fmt.Sprintf( | |||
"delete repo directory %s/%s failed(3): %v", user.Name, repo.Name, err2)) | |||
} | |||
return nil, err | |||
} | |||
if err = sess.Commit(); err != nil { | |||
sess.Rollback() | |||
if err2 := os.RemoveAll(repoPath); err2 != nil { | |||
log.Error("repo.CreateRepository(commit): %v", err) | |||
return nil, errors.New(fmt.Sprintf( | |||
"delete repo directory %s/%s failed(3): %v", user.Name, repo.Name, err2)) | |||
// Update owner team info and count. | |||
if u.IsOrganization() { | |||
t.RepoIds += "$" + base.ToStr(repo.Id) + "|" | |||
t.NumRepos++ | |||
if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { | |||
sess.Rollback() | |||
return nil, err | |||
} | |||
} | |||
if err = sess.Commit(); err != nil { | |||
return nil, err | |||
} | |||
if err = WatchRepo(user.Id, repo.Id, true); err != nil { | |||
log.Error("repo.CreateRepository(WatchRepo): %v", err) | |||
if u.IsOrganization() { | |||
ous, err := GetOrgUsersByOrgId(u.Id) | |||
if err != nil { | |||
log.Error("repo.CreateRepository(GetOrgUsersByOrgId): %v", err) | |||
} else { | |||
for _, ou := range ous { | |||
if err = WatchRepo(ou.Uid, repo.Id, true); err != nil { | |||
log.Error("repo.CreateRepository(WatchRepo): %v", err) | |||
} | |||
} | |||
} | |||
} | |||
if err = WatchRepo(u.Id, repo.Id, true); err != nil { | |||
log.Error("repo.CreateRepository(WatchRepo2): %v", err) | |||
} | |||
if err = NewRepoAction(user, repo); err != nil { | |||
if err = NewRepoAction(u, repo); err != nil { | |||
log.Error("repo.CreateRepository(NewRepoAction): %v", err) | |||
} | |||
@@ -550,7 +572,13 @@ func CreateRepository(user *User, name, desc, lang, license string, private, mir | |||
return repo, nil | |||
} | |||
if err = initRepository(repoPath, user, repo, initReadme, lang, license); err != nil { | |||
repoPath := RepoPath(u.Name, repo.Name) | |||
if err = initRepository(repoPath, u, repo, initReadme, lang, license); err != nil { | |||
if err2 := os.RemoveAll(repoPath); err2 != nil { | |||
log.Error("repo.CreateRepository(initRepository): %v", err) | |||
return nil, errors.New(fmt.Sprintf( | |||
"delete repo directory %s/%s failed(2): %v", u.Name, repo.Name, err2)) | |||
} | |||
return nil, err | |||
} | |||
@@ -123,11 +123,14 @@ func (u *User) GetOrganizations() error { | |||
return nil | |||
} | |||
// Member represents user is member of organization. | |||
type Member struct { | |||
Id int64 | |||
OrgId int64 `xorm:"unique(member) index"` | |||
UserId int64 `xorm:"unique(member)"` | |||
// 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, | |||
@@ -249,7 +252,7 @@ func CreateOrganization(org, owner *User) (*User, error) { | |||
// Create default owner team. | |||
t := &Team{ | |||
OrgId: org.Id, | |||
Name: "Owner", | |||
Name: OWNER_TEAM, | |||
Authorize: ORG_ADMIN, | |||
NumMembers: 1, | |||
} |
@@ -22,9 +22,10 @@ import ( | |||
// \/ \/|__| \/ \/ | |||
type CreateRepoForm struct { | |||
Uid int64 `form:"uid" binding:"Required"` | |||
RepoName string `form:"repo" binding:"Required;AlphaDash;MaxSize(100)"` | |||
Private bool `form:"private"` | |||
Description string `form:"desc" binding:"MaxSize(100)"` | |||
Description string `form:"desc" binding:"MaxSize(255)"` | |||
Language string `form:"language"` | |||
License string `form:"license"` | |||
InitReadme bool `form:"initReadme"` | |||
@@ -50,7 +51,7 @@ type MigrateRepoForm struct { | |||
RepoName string `form:"repo" binding:"Required;AlphaDash;MaxSize(100)"` | |||
Mirror bool `form:"mirror"` | |||
Private bool `form:"private"` | |||
Description string `form:"desc" binding:"MaxSize(100)"` | |||
Description string `form:"desc" binding:"MaxSize(255)"` | |||
} | |||
func (f *MigrateRepoForm) Name(field string) string { |
@@ -63,11 +63,26 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) { | |||
return | |||
} | |||
repo, err := models.CreateRepository(ctx.User, form.RepoName, form.Description, | |||
u := ctx.User | |||
// Not equal means current user is an organization. | |||
if u.Id != form.Uid { | |||
var err error | |||
u, err = models.GetUserById(form.Uid) | |||
if err != nil { | |||
if err == models.ErrUserNotExist { | |||
ctx.Handle(404, "home.Dashboard(GetUserById)", err) | |||
} else { | |||
ctx.Handle(500, "home.Dashboard(GetUserById)", err) | |||
} | |||
return | |||
} | |||
} | |||
repo, err := models.CreateRepository(u, form.RepoName, form.Description, | |||
form.Language, form.License, form.Private, false, form.InitReadme) | |||
if err == nil { | |||
log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, ctx.User.LowerName, form.RepoName) | |||
ctx.Redirect("/" + ctx.User.Name + "/" + form.RepoName) | |||
log.Trace("%s Repository created: %s/%s", ctx.Req.RequestURI, u.LowerName, form.RepoName) | |||
ctx.Redirect("/" + u.Name + "/" + form.RepoName) | |||
return | |||
} else if err == models.ErrRepoAlreadyExist { | |||
ctx.RenderWithErr("Repository name has already been used", CREATE, &form) | |||
@@ -78,7 +93,7 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) { | |||
} | |||
if repo != nil { | |||
if errDelete := models.DeleteRepository(ctx.User.Id, repo.Id, ctx.User.Name); errDelete != nil { | |||
if errDelete := models.DeleteRepository(u.Id, repo.Id, u.Name); errDelete != nil { | |||
log.Error("repo.CreatePost(DeleteRepository): %v", errDelete) | |||
} | |||
} |
@@ -38,12 +38,7 @@ | |||
</div> | |||
</div> | |||
</div> | |||
<input type="hidden" value="{{.SignedUserId}}" name="userId" id="repo-owner-id"/> | |||
<!--<div class="col-md-8"> | |||
<p class="form-control-static">{{.SignedUserName}}</p> | |||
<input type="hidden" value="{{.SignedUserId}}" name="userId"/> | |||
</div>--> | |||
<input type="hidden" value="{{.SignedUserId}}" name="uid" id="repo-owner-id"/> | |||
</div> | |||
<div class="form-group {{if .Err_RepoName}}has-error has-feedback{{end}}"> |