Merge branch 'master' of github.com:gogits/gogs

Conflicts:
	models/update.go
	routers/repo/http.go
This commit is contained in:
Lunny Xiao 2014-06-28 14:58:59 +08:00
commit 86e2627175
75 changed files with 2034 additions and 661 deletions

View file

@ -11,19 +11,20 @@ import (
"github.com/go-xorm/xorm"
)
// Access types.
type AccessType int
const (
AU_READABLE = iota + 1
AU_WRITABLE
READABLE AccessType = iota + 1
WRITABLE
)
// Access represents the accessibility of user to repository.
type Access struct {
Id int64
UserName string `xorm:"unique(s)"`
RepoName string `xorm:"unique(s)"` // <user name>/<repo name>
Mode int `xorm:"unique(s)"`
Created time.Time `xorm:"created"`
UserName string `xorm:"unique(s)"`
RepoName string `xorm:"unique(s)"` // <user name>/<repo name>
Mode AccessType `xorm:"unique(s)"`
Created time.Time `xorm:"created"`
}
// AddAccess adds new access record.
@ -59,7 +60,7 @@ func UpdateAccessWithSession(sess *xorm.Session, access *Access) error {
// HasAccess returns true if someone can read or write to given repository.
// The repoName should be in format <username>/<reponame>.
func HasAccess(uname, repoName string, mode int) (bool, error) {
func HasAccess(uname, repoName string, mode AccessType) (bool, error) {
if len(repoName) == 0 {
return false, nil
}

View file

@ -182,14 +182,15 @@ 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,
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)
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, RepoUserName: repo.Owner.Name, RepoName: repo.Name,
IsPrivate: repo.IsPrivate}); err != nil {
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
}

View file

@ -213,9 +213,9 @@ func GetIssueCountByPoster(uid, rid int64, isClosed bool) int64 {
// IssueUser represents an issue-user relation.
type IssueUser struct {
Id int64
Uid int64 // User ID.
Uid int64 `xorm:"INDEX"` // User ID.
IssueId int64
RepoId int64
RepoId int64 `xorm:"INDEX"`
MilestoneId int64
IsRead bool
IsAssigned bool

View file

@ -255,7 +255,7 @@ func LoginUserLdapSource(user *User, name, passwd string, sourceId int64, cfg *L
Email: mail,
}
return RegisterUser(user)
return CreateUser(user)
}
type loginAuth struct {
@ -359,5 +359,5 @@ func LoginUserSMTPSource(user *User, name, passwd string, sourceId int64, cfg *S
Passwd: passwd,
Email: name,
}
return RegisterUser(user)
return CreateUser(user)
}

View file

@ -35,7 +35,7 @@ func init() {
tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch),
new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow),
new(Mirror), new(Release), new(LoginSource), new(Webhook), new(IssueUser),
new(Milestone), new(Label), new(HookTask))
new(Milestone), new(Label), new(HookTask), new(Team), new(OrgUser), new(TeamUser))
}
func LoadModelsConfig() {

192
models/org.go Normal file
View file

@ -0,0 +1,192 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
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 (
ORG_READABLE AuthorizeType = iota + 1
ORG_WRITABLE
ORG_ADMIN
)
const OWNER_TEAM = "Owner"
// Team represents a organization team.
type Team struct {
Id int64
OrgId int64 `xorm:"INDEX"`
Name string
Description string
Authorize AuthorizeType
RepoIds string `xorm:"TEXT"`
NumMembers int
NumRepos int
}
// NewTeam creates a record of new team.
func NewTeam(t *Team) error {
_, err := x.Insert(t)
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
}
// ________ ____ ___
// \_____ \_______ ____ | | \______ ___________
// / | \_ __ \/ ___\| | / ___// __ \_ __ \
// / | \ | \/ /_/ > | /\___ \\ ___/| | \/
// \_______ /__| \___ /|______//____ >\___ >__|
// \/ /_____/ \/ \/
// OrgUser represents an organization-user relation.
type OrgUser struct {
Id int64
Uid int64 `xorm:"INDEX"`
OrgId int64 `xorm:"INDEX"`
IsPublic bool
IsOwner bool
NumTeam int
}
// GetOrgUsersByUserId returns all organization-user relations by user ID.
func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) {
ous := make([]*OrgUser, 0, 10)
err := x.Where("uid=?", uid).Find(&ous)
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
}
func GetOrganizationCount(u *User) (int64, error) {
return x.Where("uid=?", u.Id).Count(new(OrgUser))
}
// ___________ ____ ___
// \__ ___/___ _____ _____ | | \______ ___________
// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
// | |\ ___/ / __ \| Y Y \ | /\___ \\ ___/| | \/
// |____| \___ >____ /__|_| /______//____ >\___ >__|
// \/ \/ \/ \/ \/
// TeamUser represents an team-user relation.
type TeamUser struct {
Id int64
Uid int64
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
}

View file

@ -158,7 +158,7 @@ func IsRepositoryExist(u *User, repoName string) (bool, error) {
}
var (
illegalEquals = []string{"raw", "install", "api", "avatar", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
illegalEquals = []string{"raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
illegalSuffixs = []string{".git"}
)
@ -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)
@ -251,8 +251,8 @@ func MirrorUpdate() {
}
// MigrateRepository migrates a existing repository from other project hosting.
func MigrateRepository(user *User, name, desc string, private, mirror bool, url string) (*Repository, error) {
repo, err := CreateRepository(user, name, desc, "", "", private, mirror, false)
func MigrateRepository(u *User, name, desc string, private, mirror bool, url string) (*Repository, error) {
repo, err := CreateRepository(u, name, desc, "", "", private, mirror, false)
if err != nil {
return nil, err
}
@ -261,11 +261,11 @@ func MigrateRepository(user *User, name, desc string, private, mirror bool, url
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()))
os.MkdirAll(tmpDir, os.ModePerm)
repoPath := RepoPath(user.Name, name)
repoPath := RepoPath(u.Name, name)
repo.IsBare = false
if mirror {
if err = MirrorRepository(repo.Id, user.Name, repo.Name, repoPath, url); err != nil {
if err = MirrorRepository(repo.Id, u.Name, repo.Name, repoPath, url); err != nil {
return repo, err
}
repo.IsMirror = true
@ -454,21 +454,28 @@ 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,
Owner: u,
Name: name,
LowerName: strings.ToLower(name),
Description: desc,
@ -479,67 +486,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()
sess.Begin()
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
}
mode := AU_WRITABLE
var t *Team // Owner team.
mode := WRITABLE
if mirror {
mode = AU_READABLE
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
}
// 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 {
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))
}
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)
}
@ -548,7 +573,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
}

View file

@ -6,6 +6,7 @@ package models
import (
"container/list"
"fmt"
"os/exec"
"strings"
@ -15,13 +16,13 @@ import (
"github.com/gogits/gogs/modules/log"
)
func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName string, userId int64) {
func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName string, userId int64) error {
//fmt.Println(refName, oldCommitId, newCommitId)
//fmt.Println(userName, repoUserName, repoName)
isNew := strings.HasPrefix(oldCommitId, "0000000")
if isNew &&
strings.HasPrefix(newCommitId, "0000000") {
log.GitLogger.Fatal("old rev and new rev both 000000")
return fmt.Errorf("old rev and new rev both 000000")
}
f := RepoPath(repoUserName, repoName)
@ -33,18 +34,17 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
isDel := strings.HasPrefix(newCommitId, "0000000")
if isDel {
log.GitLogger.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userId)
return
return nil
}
repo, err := git.OpenRepository(f)
if err != nil {
log.GitLogger.Fatal("runUpdate.Open repoId: %v", err)
return fmt.Errorf("runUpdate.Open repoId: %v", err)
}
newCommit, err := repo.GetCommit(newCommitId)
if err != nil {
log.GitLogger.Fatal("runUpdate GetCommit of newCommitId: %v", err)
return
return fmt.Errorf("runUpdate GetCommit of newCommitId: %v", err)
}
var l *list.List
@ -52,28 +52,27 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
if isNew {
l, err = newCommit.CommitsBefore()
if err != nil {
log.GitLogger.Fatal("Find CommitsBefore erro: %v", err)
return fmt.Errorf("Find CommitsBefore erro: %v", err)
}
} else {
l, err = newCommit.CommitsBeforeUntil(oldCommitId)
if err != nil {
log.GitLogger.Fatal("Find CommitsBeforeUntil erro: %v", err)
return
return fmt.Errorf("Find CommitsBeforeUntil erro: %v", err)
}
}
if err != nil {
log.GitLogger.Fatal("runUpdate.Commit repoId: %v", err)
return fmt.Errorf("runUpdate.Commit repoId: %v", err)
}
ru, err := GetUserByName(repoUserName)
if err != nil {
log.GitLogger.Fatal("runUpdate.GetUserByName: %v", err)
return fmt.Errorf("runUpdate.GetUserByName: %v", err)
}
repos, err := GetRepositoryByName(ru.Id, repoName)
if err != nil {
log.GitLogger.Fatal("runUpdate.GetRepositoryByName userId: %v", err)
return fmt.Errorf("runUpdate.GetRepositoryByName userId: %v", err)
}
// if tags push
@ -104,6 +103,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
return
}
// if commits push
commits := make([]*base.PushCommit, 0)
var maxCommits = 3
var actEmail string
@ -126,6 +126,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName
//commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()})
if err = CommitRepoAction(userId, ru.Id, userName, actEmail,
repos.Id, repoUserName, repoName, refName, &base.PushCommits{l.Len(), commits}); err != nil {
log.GitLogger.Fatal("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err)
}
return nil
}

View file

@ -21,14 +21,16 @@ import (
"github.com/gogits/gogs/modules/setting"
)
// User types.
type UserType int
const (
UT_INDIVIDUAL = iota + 1
UT_ORGANIZATION
INDIVIDUAL UserType = iota // Historic reason to make it starts at 0.
ORGANIZATION
)
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")
@ -50,7 +52,8 @@ type User struct {
LoginType LoginType
LoginSource int64 `xorm:"not null default 0"`
LoginName string
Type int
Type UserType
Orgs []*User `xorm:"-"`
NumFollowers int
NumFollowings int
NumStars int
@ -65,43 +68,71 @@ type User struct {
Salt string `xorm:"VARCHAR(10)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
// For organization.
Description string
NumTeams int
NumMembers int
}
// HomeLink returns the user home page link.
func (user *User) HomeLink() string {
return "/user/" + user.Name
func (u *User) HomeLink() string {
return "/user/" + u.Name
}
// AvatarLink returns user gravatar link.
func (user *User) AvatarLink() string {
func (u *User) AvatarLink() string {
if setting.DisableGravatar {
return "/img/avatar_default.jpg"
} else if setting.Service.EnableCacheAvatar {
return "/avatar/" + user.Avatar
return "/avatar/" + u.Avatar
}
return "//1.gravatar.com/avatar/" + user.Avatar
return "//1.gravatar.com/avatar/" + u.Avatar
}
// NewGitSig generates and returns the signature of given user.
func (user *User) NewGitSig() *git.Signature {
func (u *User) NewGitSig() *git.Signature {
return &git.Signature{
Name: user.Name,
Email: user.Email,
Name: u.Name,
Email: u.Email,
When: time.Now(),
}
}
// EncodePasswd encodes password to safe format.
func (user *User) EncodePasswd() {
newPasswd := base.PBKDF2([]byte(user.Passwd), []byte(user.Salt), 10000, 50, sha256.New)
user.Passwd = fmt.Sprintf("%x", newPasswd)
func (u *User) EncodePasswd() {
newPasswd := base.PBKDF2([]byte(u.Passwd), []byte(u.Salt), 10000, 50, sha256.New)
u.Passwd = fmt.Sprintf("%x", newPasswd)
}
// Member represents user is member of organization.
type Member struct {
Id int64
OrgId int64 `xorm:"unique(member) index"`
UserId int64 `xorm:"unique(member)"`
func (u *User) IsOrganization() bool {
return u.Type == ORGANIZATION
}
func (u *User) GetOrganizations() error {
ous, err := GetOrgUsersByUserId(u.Id)
if err != nil {
return err
}
u.Orgs = make([]*User, len(ous))
for i, ou := range ous {
u.Orgs[i], err = GetUserById(ou.OrgId)
if err != nil {
return err
}
}
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,
@ -126,49 +157,60 @@ func GetUserSalt() string {
return base.GetRandomString(10)
}
// RegisterUser creates record of a new user.
func RegisterUser(user *User) (*User, error) {
if !IsLegalName(user.Name) {
// CreateUser creates record of a new user.
func CreateUser(u *User) (*User, error) {
if !IsLegalName(u.Name) {
return nil, ErrUserNameIllegal
}
isExist, err := IsUserExist(user.Name)
isExist, err := IsUserExist(u.Name)
if err != nil {
return nil, err
} else if isExist {
return nil, ErrUserAlreadyExist
}
isExist, err = IsEmailUsed(user.Email)
isExist, err = IsEmailUsed(u.Email)
if err != nil {
return nil, err
} else if isExist {
return nil, ErrEmailAlreadyUsed
}
user.LowerName = strings.ToLower(user.Name)
user.Avatar = base.EncodeMd5(user.Email)
user.AvatarEmail = user.Email
user.Rands = GetUserSalt()
user.Salt = GetUserSalt()
user.EncodePasswd()
if _, err = x.Insert(user); err != nil {
return nil, err
} else if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil {
if _, err := x.Id(user.Id).Delete(&User{}); err != nil {
return nil, errors.New(fmt.Sprintf(
"both create userpath %s and delete table record faild: %v", user.Name, err))
}
u.LowerName = strings.ToLower(u.Name)
u.Avatar = base.EncodeMd5(u.Email)
u.AvatarEmail = u.Email
u.Rands = GetUserSalt()
u.Salt = GetUserSalt()
u.EncodePasswd()
sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return nil, err
}
if user.Id == 1 {
user.IsAdmin = true
user.IsActive = true
_, err = x.Id(user.Id).UseBool().Update(user)
if _, err = sess.Insert(u); err != nil {
sess.Rollback()
return nil, err
}
return user, err
if err = os.MkdirAll(UserPath(u.Name), os.ModePerm); err != nil {
sess.Rollback()
return nil, err
}
if err = sess.Commit(); err != nil {
return nil, err
}
// Auto-set admin for user whose ID is 1.
if u.Id == 1 {
u.IsAdmin = true
u.IsActive = true
_, err = x.Id(u.Id).UseBool().Update(u)
}
return u, err
}
// GetUsers returns given number of user objects with offset.
@ -277,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 {
@ -331,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
}