diff options
author | zhsso <zhssoge@gmail.com> | 2014-04-10 14:20:01 -0400 |
---|---|---|
committer | zhsso <zhssoge@gmail.com> | 2014-04-10 14:20:01 -0400 |
commit | f3ed11d177d76bcb1850c6670c1516d25a66eb2c (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /models | |
parent | fde5b16332d5c4dc8246b899cd42d58b058f2bed (diff) | |
download | gitea-f3ed11d177d76bcb1850c6670c1516d25a66eb2c.tar.gz gitea-f3ed11d177d76bcb1850c6670c1516d25a66eb2c.zip |
mistakes
Diffstat (limited to 'models')
-rw-r--r-- | models/access.go | 62 | ||||
-rw-r--r-- | models/action.go | 135 | ||||
-rw-r--r-- | models/git.go | 411 | ||||
-rw-r--r-- | models/issue.go | 234 | ||||
-rw-r--r-- | models/models.go | 131 | ||||
-rw-r--r-- | models/models_test.go | 55 | ||||
-rw-r--r-- | models/oauth2.go | 49 | ||||
-rw-r--r-- | models/publickey.go | 228 | ||||
-rw-r--r-- | models/repo.go | 647 | ||||
-rw-r--r-- | models/user.go | 479 |
10 files changed, 0 insertions, 2431 deletions
diff --git a/models/access.go b/models/access.go deleted file mode 100644 index 2c0900151f..0000000000 --- a/models/access.go +++ /dev/null @@ -1,62 +0,0 @@ -// 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" - "time" - - "github.com/lunny/xorm" -) - -// Access types. -const ( - AU_READABLE = iota + 1 - AU_WRITABLE -) - -// Access represents the accessibility of user to repository. -type Access struct { - Id int64 - UserName string `xorm:"unique(s)"` - RepoName string `xorm:"unique(s)"` - Mode int `xorm:"unique(s)"` - Created time.Time `xorm:"created"` -} - -// AddAccess adds new access record. -func AddAccess(access *Access) error { - access.UserName = strings.ToLower(access.UserName) - access.RepoName = strings.ToLower(access.RepoName) - _, err := orm.Insert(access) - return err -} - -// UpdateAccess updates access information. -func UpdateAccess(access *Access) error { - access.UserName = strings.ToLower(access.UserName) - access.RepoName = strings.ToLower(access.RepoName) - _, err := orm.Id(access.Id).Update(access) - return err -} - -// UpdateAccess updates access information with session for rolling back. -func UpdateAccessWithSession(sess *xorm.Session, access *Access) error { - if _, err := sess.Id(access.Id).Update(access); err != nil { - sess.Rollback() - return err - } - return nil -} - -// HasAccess returns true if someone can read or write to given repository. -func HasAccess(userName, repoName string, mode int) (bool, error) { - return orm.Get(&Access{ - Id: 0, - UserName: strings.ToLower(userName), - RepoName: strings.ToLower(repoName), - Mode: mode, - }) -} diff --git a/models/action.go b/models/action.go deleted file mode 100644 index a642a82c98..0000000000 --- a/models/action.go +++ /dev/null @@ -1,135 +0,0 @@ -// 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 ( - "encoding/json" - "time" - - "github.com/gogits/gogs/modules/base" - "github.com/gogits/gogs/modules/log" -) - -// Operation types of user action. -const ( - OP_CREATE_REPO = iota + 1 - OP_DELETE_REPO - OP_STAR_REPO - OP_FOLLOW_REPO - OP_COMMIT_REPO - OP_CREATE_ISSUE - OP_PULL_REQUEST - OP_TRANSFER_REPO -) - -// Action represents user operation type and other information to repository., -// it implemented interface base.Actioner so that can be used in template render. -type Action struct { - Id int64 - UserId int64 // Receiver user id. - OpType int // Operations: CREATE DELETE STAR ... - ActUserId int64 // Action user id. - ActUserName string // Action user name. - ActEmail string - RepoId int64 - RepoName string - RefName string - Content string `xorm:"TEXT"` - Created time.Time `xorm:"created"` -} - -func (a Action) GetOpType() int { - return a.OpType -} - -func (a Action) GetActUserName() string { - return a.ActUserName -} - -func (a Action) GetActEmail() string { - return a.ActEmail -} - -func (a Action) GetRepoName() string { - return a.RepoName -} - -func (a Action) GetBranch() string { - return a.RefName -} - -func (a Action) GetContent() string { - return a.Content -} - -// CommitRepoAction adds new action for committing repository. -func CommitRepoAction(userId int64, userName, actEmail string, - repoId int64, repoName string, refName string, commit *base.PushCommits) error { - log.Trace("action.CommitRepoAction(start): %d/%s", userId, repoName) - - bs, err := json.Marshal(commit) - if err != nil { - log.Error("action.CommitRepoAction(json): %d/%s", userId, repoName) - return err - } - - if err = NotifyWatchers(&Action{ActUserId: userId, ActUserName: userName, ActEmail: actEmail, - OpType: OP_COMMIT_REPO, Content: string(bs), RepoId: repoId, RepoName: repoName, RefName: refName}); err != nil { - log.Error("action.CommitRepoAction(notify watchers): %d/%s", userId, repoName) - return err - } - - // Change repository bare status and update last updated time. - repo, err := GetRepositoryByName(userId, repoName) - if err != nil { - log.Error("action.CommitRepoAction(GetRepositoryByName): %d/%s", userId, repoName) - return err - } - repo.IsBare = false - if err = UpdateRepository(repo); err != nil { - log.Error("action.CommitRepoAction(UpdateRepository): %d/%s", userId, repoName) - return err - } - - log.Trace("action.CommitRepoAction(end): %d/%s", userId, repoName) - return nil -} - -// 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}); err != nil { - log.Error("action.NewRepoAction(notify watchers): %d/%s", user.Id, repo.Name) - return err - } - - log.Trace("action.NewRepoAction: %s/%s", user.LowerName, repo.LowerName) - return err -} - -// TransferRepoAction adds new action for transfering repository. -func TransferRepoAction(user, newUser *User, repo *Repository) (err error) { - if err = NotifyWatchers(&Action{ActUserId: user.Id, ActUserName: user.Name, ActEmail: user.Email, - OpType: OP_TRANSFER_REPO, RepoId: repo.Id, RepoName: repo.Name, Content: newUser.Name}); err != nil { - log.Error("action.TransferRepoAction(notify watchers): %d/%s", user.Id, repo.Name) - return err - } - - log.Trace("action.TransferRepoAction: %s/%s", user.LowerName, repo.LowerName) - return err -} - -// GetFeeds returns action list of given user in given context. -func GetFeeds(userid, offset int64, isProfile bool) ([]Action, error) { - actions := make([]Action, 0, 20) - sess := orm.Limit(20, int(offset)).Desc("id").Where("user_id=?", userid) - if isProfile { - sess.And("act_user_id=?", userid) - } else { - sess.And("act_user_id!=?", userid) - } - err := sess.Find(&actions) - return actions, err -} diff --git a/models/git.go b/models/git.go deleted file mode 100644 index 77b7ef2d7e..0000000000 --- a/models/git.go +++ /dev/null @@ -1,411 +0,0 @@ -// 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 ( - "bufio" - "container/list" - "fmt" - "io" - "os" - "os/exec" - "path" - "strings" - - "github.com/gogits/git" - - "github.com/gogits/gogs/modules/base" -) - -// RepoFile represents a file object in git repository. -type RepoFile struct { - *git.TreeEntry - Path string - Size int64 - Repo *git.Repository - Commit *git.Commit -} - -// LookupBlob returns the content of an object. -func (file *RepoFile) LookupBlob() (*git.Blob, error) { - if file.Repo == nil { - return nil, ErrRepoFileNotLoaded - } - - return file.Repo.LookupBlob(file.Id) -} - -// GetBranches returns all branches of given repository. -func GetBranches(userName, repoName string) ([]string, error) { - repo, err := git.OpenRepository(RepoPath(userName, repoName)) - if err != nil { - return nil, err - } - - refs, err := repo.AllReferences() - if err != nil { - return nil, err - } - - brs := make([]string, len(refs)) - for i, ref := range refs { - brs[i] = ref.BranchName() - } - return brs, nil -} - -// GetTags returns all tags of given repository. -func GetTags(userName, repoName string) ([]string, error) { - repo, err := git.OpenRepository(RepoPath(userName, repoName)) - if err != nil { - return nil, err - } - - refs, err := repo.AllTags() - if err != nil { - return nil, err - } - - tags := make([]string, len(refs)) - for i, ref := range refs { - tags[i] = ref.Name - } - return tags, nil -} - -func IsBranchExist(userName, repoName, branchName string) bool { - repo, err := git.OpenRepository(RepoPath(userName, repoName)) - if err != nil { - return false - } - return repo.IsBranchExist(branchName) -} - -func GetTargetFile(userName, repoName, branchName, commitId, rpath string) (*RepoFile, error) { - repo, err := git.OpenRepository(RepoPath(userName, repoName)) - if err != nil { - return nil, err - } - - commit, err := repo.GetCommitOfBranch(branchName) - if err != nil { - commit, err = repo.GetCommit(commitId) - if err != nil { - return nil, err - } - } - - parts := strings.Split(path.Clean(rpath), "/") - - var entry *git.TreeEntry - tree := commit.Tree - for i, part := range parts { - if i == len(parts)-1 { - entry = tree.EntryByName(part) - if entry == nil { - return nil, ErrRepoFileNotExist - } - } else { - tree, err = repo.SubTree(tree, part) - if err != nil { - return nil, err - } - } - } - - size, err := repo.ObjectSize(entry.Id) - if err != nil { - return nil, err - } - - repoFile := &RepoFile{ - entry, - rpath, - size, - repo, - commit, - } - - return repoFile, nil -} - -// GetReposFiles returns a list of file object in given directory of repository. -// func GetReposFilesOfBranch(userName, repoName, branchName, rpath string) ([]*RepoFile, error) { -// return getReposFiles(userName, repoName, commitId, rpath) -// } - -// GetReposFiles returns a list of file object in given directory of repository. -func GetReposFiles(userName, repoName, commitId, rpath string) ([]*RepoFile, error) { - return getReposFiles(userName, repoName, commitId, rpath) -} - -func getReposFiles(userName, repoName, commitId string, rpath string) ([]*RepoFile, error) { - repopath := RepoPath(userName, repoName) - repo, err := git.OpenRepository(repopath) - if err != nil { - return nil, err - } - - commit, err := repo.GetCommit(commitId) - if err != nil { - return nil, err - } - - var repodirs []*RepoFile - var repofiles []*RepoFile - commit.Tree.Walk(func(dirname string, entry *git.TreeEntry) int { - if dirname == rpath { - // TODO: size get method shoule be improved - size, err := repo.ObjectSize(entry.Id) - if err != nil { - return 0 - } - - cmd := exec.Command("git", "log", "-1", "--pretty=format:%H", commitId, "--", path.Join(dirname, entry.Name)) - cmd.Dir = repopath - out, err := cmd.Output() - if err != nil { - return 0 - } - filecm, err := repo.GetCommit(string(out)) - if err != nil { - return 0 - } - - rp := &RepoFile{ - entry, - path.Join(dirname, entry.Name), - size, - repo, - filecm, - } - - if entry.IsFile() { - repofiles = append(repofiles, rp) - } else if entry.IsDir() { - repodirs = append(repodirs, rp) - } - } - return 0 - }) - - return append(repodirs, repofiles...), nil -} - -func GetCommit(userName, repoName, commitId string) (*git.Commit, error) { - repo, err := git.OpenRepository(RepoPath(userName, repoName)) - if err != nil { - return nil, err - } - - return repo.GetCommit(commitId) -} - -// GetCommitsByBranch returns all commits of given branch of repository. -func GetCommitsByBranch(userName, repoName, branchName string) (*list.List, error) { - repo, err := git.OpenRepository(RepoPath(userName, repoName)) - if err != nil { - return nil, err - } - r, err := repo.LookupReference(fmt.Sprintf("refs/heads/%s", branchName)) - if err != nil { - return nil, err - } - return r.AllCommits() -} - -// GetCommitsByCommitId returns all commits of given commitId of repository. -func GetCommitsByCommitId(userName, repoName, commitId string) (*list.List, error) { - repo, err := git.OpenRepository(RepoPath(userName, repoName)) - if err != nil { - return nil, err - } - oid, err := git.NewOidFromString(commitId) - if err != nil { - return nil, err - } - return repo.CommitsBefore(oid) -} - -// Diff line types. -const ( - DIFF_LINE_PLAIN = iota + 1 - DIFF_LINE_ADD - DIFF_LINE_DEL - DIFF_LINE_SECTION -) - -const ( - DIFF_FILE_ADD = iota + 1 - DIFF_FILE_CHANGE - DIFF_FILE_DEL -) - -type DiffLine struct { - LeftIdx int - RightIdx int - Type int - Content string -} - -func (d DiffLine) GetType() int { - return d.Type -} - -type DiffSection struct { - Name string - Lines []*DiffLine -} - -type DiffFile struct { - Name string - Addition, Deletion int - Type int - Sections []*DiffSection -} - -type Diff struct { - TotalAddition, TotalDeletion int - Files []*DiffFile -} - -func (diff *Diff) NumFiles() int { - return len(diff.Files) -} - -const DIFF_HEAD = "diff --git " - -func ParsePatch(reader io.Reader) (*Diff, error) { - scanner := bufio.NewScanner(reader) - var ( - curFile *DiffFile - curSection = &DiffSection{ - Lines: make([]*DiffLine, 0, 10), - } - - leftLine, rightLine int - ) - - diff := &Diff{Files: make([]*DiffFile, 0)} - var i int - for scanner.Scan() { - line := scanner.Text() - // fmt.Println(i, line) - if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") { - continue - } - - i = i + 1 - if line == "" { - continue - } - if line[0] == ' ' { - diffLine := &DiffLine{Type: DIFF_LINE_PLAIN, Content: line, LeftIdx: leftLine, RightIdx: rightLine} - leftLine++ - rightLine++ - curSection.Lines = append(curSection.Lines, diffLine) - continue - } else if line[0] == '@' { - curSection = &DiffSection{} - curFile.Sections = append(curFile.Sections, curSection) - ss := strings.Split(line, "@@") - diffLine := &DiffLine{Type: DIFF_LINE_SECTION, Content: line} - curSection.Lines = append(curSection.Lines, diffLine) - - // Parse line number. - ranges := strings.Split(ss[len(ss)-2][1:], " ") - leftLine, _ = base.StrTo(strings.Split(ranges[0], ",")[0][1:]).Int() - rightLine, _ = base.StrTo(strings.Split(ranges[1], ",")[0]).Int() - continue - } else if line[0] == '+' { - curFile.Addition++ - diff.TotalAddition++ - diffLine := &DiffLine{Type: DIFF_LINE_ADD, Content: line, RightIdx: rightLine} - rightLine++ - curSection.Lines = append(curSection.Lines, diffLine) - continue - } else if line[0] == '-' { - curFile.Deletion++ - diff.TotalDeletion++ - diffLine := &DiffLine{Type: DIFF_LINE_DEL, Content: line, LeftIdx: leftLine} - if leftLine > 0 { - leftLine++ - } - curSection.Lines = append(curSection.Lines, diffLine) - continue - } - - // Get new file. - if strings.HasPrefix(line, DIFF_HEAD) { - fs := strings.Split(line[len(DIFF_HEAD):], " ") - a := fs[0] - - curFile = &DiffFile{ - Name: a[strings.Index(a, "/")+1:], - Type: DIFF_FILE_CHANGE, - Sections: make([]*DiffSection, 0, 10), - } - diff.Files = append(diff.Files, curFile) - - // Check file diff type. - for scanner.Scan() { - switch { - case strings.HasPrefix(scanner.Text(), "new file"): - curFile.Type = DIFF_FILE_ADD - case strings.HasPrefix(scanner.Text(), "deleted"): - curFile.Type = DIFF_FILE_DEL - case strings.HasPrefix(scanner.Text(), "index"): - curFile.Type = DIFF_FILE_CHANGE - } - if curFile.Type > 0 { - break - } - } - } - } - - return diff, nil -} - -func GetDiff(repoPath, commitid string) (*Diff, error) { - repo, err := git.OpenRepository(repoPath) - if err != nil { - return nil, err - } - - commit, err := repo.GetCommit(commitid) - if err != nil { - return nil, err - } - - // First commit of repository. - if commit.ParentCount() == 0 { - rd, wr := io.Pipe() - go func() { - cmd := exec.Command("git", "show", commitid) - cmd.Dir = repoPath - cmd.Stdout = wr - cmd.Stdin = os.Stdin - cmd.Stderr = os.Stderr - cmd.Run() - wr.Close() - }() - defer rd.Close() - return ParsePatch(rd) - } - - rd, wr := io.Pipe() - go func() { - cmd := exec.Command("git", "diff", commit.Parent(0).Oid.String(), commitid) - cmd.Dir = repoPath - cmd.Stdout = wr - cmd.Stdin = os.Stdin - cmd.Stderr = os.Stderr - cmd.Run() - wr.Close() - }() - defer rd.Close() - return ParsePatch(rd) -} diff --git a/models/issue.go b/models/issue.go deleted file mode 100644 index f14030df5e..0000000000 --- a/models/issue.go +++ /dev/null @@ -1,234 +0,0 @@ -// 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 ( - "errors" - "strings" - "time" - - "github.com/gogits/gogs/modules/base" -) - -var ( - ErrIssueNotExist = errors.New("Issue does not exist") -) - -// Issue represents an issue or pull request of repository. -type Issue struct { - Id int64 - Index int64 // Index in one repository. - Name string - RepoId int64 `xorm:"index"` - Repo *Repository `xorm:"-"` - PosterId int64 - Poster *User `xorm:"-"` - MilestoneId int64 - AssigneeId int64 - IsPull bool // Indicates whether is a pull request or not. - IsClosed bool - Labels string `xorm:"TEXT"` - Mentions string `xorm:"TEXT"` - Content string `xorm:"TEXT"` - RenderedContent string `xorm:"-"` - NumComments int - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` -} - -// CreateIssue creates new issue for repository. -func CreateIssue(userId, repoId, milestoneId, assigneeId int64, issueCount int, name, labels, content string, isPull bool) (issue *Issue, err error) { - // TODO: find out mentions - mentions := "" - - sess := orm.NewSession() - defer sess.Close() - sess.Begin() - - issue = &Issue{ - Index: int64(issueCount) + 1, - Name: name, - RepoId: repoId, - PosterId: userId, - MilestoneId: milestoneId, - AssigneeId: assigneeId, - IsPull: isPull, - Labels: labels, - Mentions: mentions, - Content: content, - } - if _, err = sess.Insert(issue); err != nil { - sess.Rollback() - return nil, err - } - - rawSql := "UPDATE `repository` SET num_issues = num_issues + 1 WHERE id = ?" - if _, err = sess.Exec(rawSql, repoId); err != nil { - sess.Rollback() - return nil, err - } - - if err = sess.Commit(); err != nil { - sess.Rollback() - return nil, err - } - - return issue, nil -} - -// GetIssueById returns issue object by given id. -func GetIssueByIndex(repoId, index int64) (*Issue, error) { - issue := &Issue{RepoId: repoId, Index: index} - has, err := orm.Get(issue) - if err != nil { - return nil, err - } else if !has { - return nil, ErrIssueNotExist - } - return issue, nil -} - -// GetIssues returns a list of issues by given conditions. -func GetIssues(userId, repoId, posterId, milestoneId int64, page int, isClosed, isMention bool, labels, sortType string) ([]Issue, error) { - sess := orm.Limit(20, (page-1)*20) - - if repoId > 0 { - sess.Where("repo_id=?", repoId).And("is_closed=?", isClosed) - } else { - sess.Where("is_closed=?", isClosed) - } - - if userId > 0 { - sess.And("assignee_id=?", userId) - } else if posterId > 0 { - sess.And("poster_id=?", posterId) - } else if isMention { - sess.And("mentions like '%$" + base.ToStr(userId) + "|%'") - } - - if milestoneId > 0 { - sess.And("milestone_id=?", milestoneId) - } - - if len(labels) > 0 { - for _, label := range strings.Split(labels, ",") { - sess.And("mentions like '%$" + label + "|%'") - } - } - - switch sortType { - case "oldest": - sess.Asc("created") - case "recentupdate": - sess.Desc("updated") - case "leastupdate": - sess.Asc("updated") - case "mostcomment": - sess.Desc("num_comments") - case "leastcomment": - sess.Asc("num_comments") - default: - sess.Desc("created") - } - - var issues []Issue - err := sess.Find(&issues) - return issues, err -} - -// GetUserIssueCount returns the number of issues that were created by given user in repository. -func GetUserIssueCount(userId, repoId int64) int64 { - count, _ := orm.Where("poster_id=?", userId).And("repo_id=?", repoId).Count(new(Issue)) - return count -} - -// UpdateIssue updates information of issue. -func UpdateIssue(issue *Issue) error { - _, err := orm.Id(issue.Id).AllCols().Update(issue) - return err -} - -// Label represents a list of labels of repository for issues. -type Label struct { - Id int64 - RepoId int64 `xorm:"index"` - Names string - Colors string -} - -// Milestone represents a milestone of repository. -type Milestone struct { - Id int64 - Name string - RepoId int64 `xorm:"index"` - IsClosed bool - Content string - NumIssues int - DueDate time.Time - Created time.Time `xorm:"created"` -} - -// Issue types. -const ( - IT_PLAIN = iota // Pure comment. - IT_REOPEN // Issue reopen status change prompt. - IT_CLOSE // Issue close status change prompt. -) - -// Comment represents a comment in commit and issue page. -type Comment struct { - Id int64 - Type int - PosterId int64 - Poster *User `xorm:"-"` - IssueId int64 - CommitId int64 - Line int64 - Content string - Created time.Time `xorm:"created"` -} - -// CreateComment creates comment of issue or commit. -func CreateComment(userId, repoId, issueId, commitId, line int64, cmtType int, content string) error { - sess := orm.NewSession() - defer sess.Close() - sess.Begin() - - if _, err := orm.Insert(&Comment{PosterId: userId, Type: cmtType, IssueId: issueId, - CommitId: commitId, Line: line, Content: content}); err != nil { - sess.Rollback() - return err - } - - // Check comment type. - switch cmtType { - case IT_PLAIN: - rawSql := "UPDATE `issue` SET num_comments = num_comments + 1 WHERE id = ?" - if _, err := sess.Exec(rawSql, issueId); err != nil { - sess.Rollback() - return err - } - case IT_REOPEN: - rawSql := "UPDATE `repository` SET num_closed_issues = num_closed_issues - 1 WHERE id = ?" - if _, err := sess.Exec(rawSql, repoId); err != nil { - sess.Rollback() - return err - } - case IT_CLOSE: - rawSql := "UPDATE `repository` SET num_closed_issues = num_closed_issues + 1 WHERE id = ?" - if _, err := sess.Exec(rawSql, repoId); err != nil { - sess.Rollback() - return err - } - } - return sess.Commit() -} - -// GetIssueComments returns list of comment by given issue id. -func GetIssueComments(issueId int64) ([]Comment, error) { - comments := make([]Comment, 0, 10) - err := orm.Asc("created").Find(&comments, &Comment{IssueId: issueId}) - return comments, err -} diff --git a/models/models.go b/models/models.go deleted file mode 100644 index ee96207d10..0000000000 --- a/models/models.go +++ /dev/null @@ -1,131 +0,0 @@ -// 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 ( - "fmt" - "os" - "path" - - _ "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" - "github.com/lunny/xorm" - // _ "github.com/mattn/go-sqlite3" - - "github.com/gogits/gogs/modules/base" -) - -var ( - orm *xorm.Engine - tables []interface{} - - HasEngine bool - - DbCfg struct { - Type, Host, Name, User, Pwd, Path, SslMode string - } - - UseSQLite3 bool -) - -func init() { - tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch), - new(Action), new(Access), new(Issue), new(Comment), new(Oauth2)) -} - -func LoadModelsConfig() { - DbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE") - if DbCfg.Type == "sqlite3" { - UseSQLite3 = true - } - DbCfg.Host = base.Cfg.MustValue("database", "HOST") - DbCfg.Name = base.Cfg.MustValue("database", "NAME") - DbCfg.User = base.Cfg.MustValue("database", "USER") - DbCfg.Pwd = base.Cfg.MustValue("database", "PASSWD") - DbCfg.SslMode = base.Cfg.MustValue("database", "SSL_MODE") - DbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db") -} - -func NewTestEngine(x *xorm.Engine) (err error) { - switch DbCfg.Type { - case "mysql": - x, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8", - DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name)) - case "postgres": - x, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", - DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode)) - // case "sqlite3": - // os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) - // x, err = xorm.NewEngine("sqlite3", DbCfg.Path) - default: - return fmt.Errorf("Unknown database type: %s", DbCfg.Type) - } - if err != nil { - return fmt.Errorf("models.init(fail to conntect database): %v", err) - } - return x.Sync(tables...) -} - -func SetEngine() (err error) { - switch DbCfg.Type { - case "mysql": - orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8", - DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name)) - case "postgres": - orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s", - DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode)) - case "sqlite3": - os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm) - orm, err = xorm.NewEngine("sqlite3", DbCfg.Path) - default: - return fmt.Errorf("Unknown database type: %s", DbCfg.Type) - } - if err != nil { - return fmt.Errorf("models.init(fail to conntect database): %v", err) - } - - // WARNNING: for serv command, MUST remove the output to os.stdout, - // so use log file to instead print to stdout. - execDir, _ := base.ExecDir() - logPath := execDir + "/log/xorm.log" - os.MkdirAll(path.Dir(logPath), os.ModePerm) - - f, err := os.Create(logPath) - if err != nil { - return fmt.Errorf("models.init(fail to create xorm.log): %v", err) - } - orm.Logger = f - - orm.ShowSQL = true - orm.ShowDebug = true - orm.ShowErr = true - return nil -} - -func NewEngine() (err error) { - if err = SetEngine(); err != nil { - return err - } - if err = orm.Sync(tables...); err != nil { - return fmt.Errorf("sync database struct error: %v\n", err) - } - return nil -} - -type Statistic struct { - Counter struct { - User, PublicKey, Repo, Watch, Action, Access int64 - } -} - -func GetStatistic() (stats Statistic) { - stats.Counter.User, _ = orm.Count(new(User)) - stats.Counter.PublicKey, _ = orm.Count(new(PublicKey)) - stats.Counter.Repo, _ = orm.Count(new(Repository)) - stats.Counter.Watch, _ = orm.Count(new(Watch)) - stats.Counter.Action, _ = orm.Count(new(Action)) - stats.Counter.Access, _ = orm.Count(new(Access)) - return -} diff --git a/models/models_test.go b/models/models_test.go deleted file mode 100644 index b808f41d21..0000000000 --- a/models/models_test.go +++ /dev/null @@ -1,55 +0,0 @@ -// 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 ( - "fmt" - "testing" - - "github.com/lunny/xorm" - _ "github.com/mattn/go-sqlite3" - . "github.com/smartystreets/goconvey/convey" - - "github.com/gogits/gogs/modules/base" -) - -func init() { - var err error - orm, err = xorm.NewEngine("sqlite3", "./test.db") - if err != nil { - fmt.Println(err) - } - - orm.ShowSQL = true - orm.ShowDebug = true - - err = orm.Sync(&User{}, &Repository{}) - if err != nil { - fmt.Println(err) - } - - base.RepoRootPath = "test" -} - -func TestCreateRepository(t *testing.T) { - user := User{Id: 1, Name: "foobar", Type: UT_INDIVIDUAL} - _, err := CreateRepository(&user, "test", "", "", "test repo desc", false, false) - if err != nil { - t.Error(err) - } -} - -func TestDeleteRepository(t *testing.T) { - err := DeleteRepository(1, 1, "foobar") - if err != nil { - t.Error(err) - } -} - -func TestCommitRepoAction(t *testing.T) { - Convey("Create a commit repository action", t, func() { - - }) -} diff --git a/models/oauth2.go b/models/oauth2.go deleted file mode 100644 index 45728b0d51..0000000000 --- a/models/oauth2.go +++ /dev/null @@ -1,49 +0,0 @@ -// 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 "errors" - -// OT: Oauth2 Type -const ( - OT_GITHUB = iota + 1 - OT_GOOGLE - OT_TWITTER -) - -var ( - ErrOauth2RecordNotExists = errors.New("not exists oauth2 record") - ErrOauth2NotAssociatedWithUser = errors.New("not associated with user") -) - -type Oauth2 struct { - Id int64 - Uid int64 // userId - User *User `xorm:"-"` - Type int `xorm:"pk unique(oauth)"` // twitter,github,google... - Identity string `xorm:"pk unique(oauth)"` // id.. - Token string `xorm:"VARCHAR(200) not null"` -} - -func AddOauth2(oa *Oauth2) (err error) { - if _, err = orm.Insert(oa); err != nil { - return err - } - return nil -} - -func GetOauth2(identity string) (oa *Oauth2, err error) { - oa = &Oauth2{Identity: identity} - isExist, err := orm.Get(oa) - if err != nil { - return - } else if !isExist { - return nil, ErrOauth2RecordNotExists - } else if oa.Uid == 0 { - return oa, ErrOauth2NotAssociatedWithUser - } - oa.User, err = GetUserById(oa.Uid) - return oa, err -} diff --git a/models/publickey.go b/models/publickey.go deleted file mode 100644 index ed47ff209d..0000000000 --- a/models/publickey.go +++ /dev/null @@ -1,228 +0,0 @@ -// 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 ( - "bufio" - "errors" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "strings" - "sync" - "time" - - "github.com/Unknwon/com" - - "github.com/gogits/gogs/modules/log" -) - -const ( - // "### autogenerated by gitgos, DO NOT EDIT\n" - TPL_PUBLICK_KEY = `command="%s serv key-%d",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` -) - -var ( - ErrKeyAlreadyExist = errors.New("Public key already exist") -) - -var sshOpLocker = sync.Mutex{} - -var ( - sshPath string - appPath string -) - -// exePath returns the executable path. -func exePath() (string, error) { - file, err := exec.LookPath(os.Args[0]) - if err != nil { - return "", err - } - return filepath.Abs(file) -} - -// homeDir returns the home directory of current user. -func homeDir() string { - home, err := com.HomeDir() - if err != nil { - return "/" - } - return home -} - -func init() { - var err error - - appPath, err = exePath() - if err != nil { - fmt.Printf("publickey.init(fail to get app path): %v\n", err) - os.Exit(2) - } - - // Determine and create .ssh path. - sshPath = filepath.Join(homeDir(), ".ssh") - if err = os.MkdirAll(sshPath, os.ModePerm); err != nil { - fmt.Printf("publickey.init(fail to create sshPath(%s)): %v\n", sshPath, err) - os.Exit(2) - } -} - -// PublicKey represents a SSH key of user. -type PublicKey struct { - Id int64 - OwnerId int64 `xorm:"unique(s) index not null"` - Name string `xorm:"unique(s) not null"` - Fingerprint string - Content string `xorm:"TEXT not null"` - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` -} - -// GenAuthorizedKey returns formatted public key string. -func GenAuthorizedKey(keyId int64, key string) string { - return fmt.Sprintf(TPL_PUBLICK_KEY+"\n", appPath, keyId, key) -} - -// AddPublicKey adds new public key to database and SSH key file. -func AddPublicKey(key *PublicKey) (err error) { - // Check if public key name has been used. - has, err := orm.Get(key) - if err != nil { - return err - } else if has { - return ErrKeyAlreadyExist - } - - // Calculate fingerprint. - tmpPath := strings.Replace(filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()), - "id_rsa.pub"), "\\", "/", -1) - os.MkdirAll(path.Dir(tmpPath), os.ModePerm) - if err = ioutil.WriteFile(tmpPath, []byte(key.Content), os.ModePerm); err != nil { - return err - } - stdout, _, err := com.ExecCmd("ssh-keygen", "-l", "-f", tmpPath) - if err != nil { - return err - } else if len(stdout) < 2 { - return errors.New("Not enough output for calculating fingerprint") - } - key.Fingerprint = strings.Split(stdout, " ")[1] - - // Save SSH key. - if _, err = orm.Insert(key); err != nil { - return err - } - if err = SaveAuthorizedKeyFile(key); err != nil { - if _, err2 := orm.Delete(key); err2 != nil { - return err2 - } - return err - } - - return nil -} - -func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error { - // Delete SSH key in SSH key file. - sshOpLocker.Lock() - defer sshOpLocker.Unlock() - - fr, err := os.Open(p) - if err != nil { - return err - } - defer fr.Close() - - fw, err := os.Create(tmpP) - if err != nil { - return err - } - defer fw.Close() - - buf := bufio.NewReader(fr) - for { - line, errRead := buf.ReadString('\n') - line = strings.TrimSpace(line) - - if errRead != nil { - if errRead != io.EOF { - return errRead - } - - // Reached end of file, if nothing to read then break, - // otherwise handle the last line. - if len(line) == 0 { - break - } - } - - // Found the line and copy rest of file. - if strings.Contains(line, fmt.Sprintf("key-%d", key.Id)) && strings.Contains(line, key.Content) { - continue - } - // Still finding the line, copy the line that currently read. - if _, err = fw.WriteString(line + "\n"); err != nil { - return err - } - - if errRead == io.EOF { - break - } - } - return nil -} - -// DeletePublicKey deletes SSH key information both in database and authorized_keys file. -func DeletePublicKey(key *PublicKey) (err error) { - // Delete SSH key in database. - has, err := orm.Id(key.Id).Get(key) - if err != nil { - return err - } else if !has { - return errors.New("Public key does not exist") - } - if _, err = orm.Delete(key); err != nil { - return err - } - - p := filepath.Join(sshPath, "authorized_keys") - tmpP := filepath.Join(sshPath, "authorized_keys.tmp") - log.Trace("ssh.DeletePublicKey(authorized_keys): %s", p) - - if err = rewriteAuthorizedKeys(key, p, tmpP); err != nil { - return err - } else if err = os.Remove(p); err != nil { - return err - } - return os.Rename(tmpP, p) -} - -// ListPublicKey returns a list of public keys that user has. -func ListPublicKey(userId int64) ([]PublicKey, error) { - keys := make([]PublicKey, 0) - err := orm.Find(&keys, &PublicKey{OwnerId: userId}) - return keys, err -} - -// SaveAuthorizedKeyFile writes SSH key content to SSH key file. -func SaveAuthorizedKeyFile(key *PublicKey) error { - sshOpLocker.Lock() - defer sshOpLocker.Unlock() - - p := filepath.Join(sshPath, "authorized_keys") - f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) - if err != nil { - return err - } - defer f.Close() - - _, err = f.WriteString(GenAuthorizedKey(key.Id, key.Content)) - return err -} diff --git a/models/repo.go b/models/repo.go deleted file mode 100644 index 573e0f4e6f..0000000000 --- a/models/repo.go +++ /dev/null @@ -1,647 +0,0 @@ -// 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 ( - "errors" - "fmt" - "io/ioutil" - "os" - "os/exec" - "path" - "path/filepath" - "strings" - "time" - "unicode/utf8" - - "github.com/Unknwon/cae/zip" - "github.com/Unknwon/com" - - "github.com/gogits/git" - - "github.com/gogits/gogs/modules/base" - "github.com/gogits/gogs/modules/log" -) - -var ( - ErrRepoAlreadyExist = errors.New("Repository already exist") - ErrRepoNotExist = errors.New("Repository does not exist") - ErrRepoFileNotExist = errors.New("Target Repo file does not exist") - ErrRepoNameIllegal = errors.New("Repository name contains illegal characters") - ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded") -) - -var ( - LanguageIgns, Licenses []string -) - -func LoadRepoConfig() { - LanguageIgns = strings.Split(base.Cfg.MustValue("repository", "LANG_IGNS"), "|") - Licenses = strings.Split(base.Cfg.MustValue("repository", "LICENSES"), "|") -} - -func NewRepoContext() { - zip.Verbose = false - - // Check if server has basic git setting. - stdout, _, err := com.ExecCmd("git", "config", "--get", "user.name") - if err != nil { - fmt.Printf("repo.init(fail to get git user.name): %v", err) - os.Exit(2) - } else if len(stdout) == 0 { - if _, _, err = com.ExecCmd("git", "config", "--global", "user.email", "gogitservice@gmail.com"); err != nil { - fmt.Printf("repo.init(fail to set git user.email): %v", err) - os.Exit(2) - } else if _, _, err = com.ExecCmd("git", "config", "--global", "user.name", "Gogs"); err != nil { - fmt.Printf("repo.init(fail to set git user.name): %v", err) - os.Exit(2) - } - } -} - -// Repository represents a git repository. -type Repository struct { - Id int64 - OwnerId int64 `xorm:"unique(s)"` - ForkId int64 - LowerName string `xorm:"unique(s) index not null"` - Name string `xorm:"index not null"` - Description string - Website string - NumWatches int - NumStars int - NumForks int - NumIssues int - NumReleases int `xorm:"NOT NULL"` - NumClosedIssues int - NumOpenIssues int `xorm:"-"` - IsPrivate bool - IsBare bool - IsGoget bool - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` -} - -// IsRepositoryExist returns true if the repository with given name under user has already existed. -func IsRepositoryExist(user *User, repoName string) (bool, error) { - repo := Repository{OwnerId: user.Id} - has, err := orm.Where("lower_name = ?", strings.ToLower(repoName)).Get(&repo) - if err != nil { - return has, err - } else if !has { - return false, nil - } - - return com.IsDir(RepoPath(user.Name, repoName)), nil -} - -var ( - illegalEquals = []string{"raw", "install", "api", "avatar", "user", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"} - illegalSuffixs = []string{".git"} -) - -// IsLegalName returns false if name contains illegal characters. -func IsLegalName(repoName string) bool { - repoName = strings.ToLower(repoName) - for _, char := range illegalEquals { - if repoName == char { - return false - } - } - for _, char := range illegalSuffixs { - if strings.HasSuffix(repoName, char) { - return false - } - } - return true -} - -// CreateRepository creates a repository for given user or orgnaziation. -func CreateRepository(user *User, repoName, desc, repoLang, license string, private bool, initReadme bool) (*Repository, error) { - if !IsLegalName(repoName) { - return nil, ErrRepoNameIllegal - } - - isExist, err := IsRepositoryExist(user, repoName) - if err != nil { - return nil, err - } else if isExist { - return nil, ErrRepoAlreadyExist - } - - repo := &Repository{ - OwnerId: user.Id, - Name: repoName, - LowerName: strings.ToLower(repoName), - Description: desc, - IsPrivate: private, - IsBare: repoLang == "" && license == "" && !initReadme, - } - repoPath := RepoPath(user.Name, repoName) - - sess := orm.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, repoName, err2)) - } - sess.Rollback() - return nil, err - } - - access := Access{ - UserName: user.LowerName, - RepoName: strings.ToLower(path.Join(user.Name, repo.Name)), - Mode: AU_WRITABLE, - } - 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, repoName, err2)) - } - return nil, err - } - - rawSql := "UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?" - if _, err = sess.Exec(rawSql, user.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, repoName, 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, repoName, err2)) - } - return nil, err - } - - c := exec.Command("git", "update-server-info") - c.Dir = repoPath - if err = c.Run(); err != nil { - log.Error("repo.CreateRepository(exec update-server-info): %v", err) - } - - if err = NewRepoAction(user, repo); err != nil { - log.Error("repo.CreateRepository(NewRepoAction): %v", err) - } - - if err = WatchRepo(user.Id, repo.Id, true); err != nil { - log.Error("repo.CreateRepository(WatchRepo): %v", err) - } - - if err = initRepository(repoPath, user, repo, initReadme, repoLang, license); err != nil { - return nil, err - } - - return repo, nil -} - -// extractGitBareZip extracts git-bare.zip to repository path. -func extractGitBareZip(repoPath string) error { - z, err := zip.Open("conf/content/git-bare.zip") - if err != nil { - fmt.Println("shi?") - return err - } - defer z.Close() - - return z.ExtractTo(repoPath) -} - -// initRepoCommit temporarily changes with work directory. -func initRepoCommit(tmpPath string, sig *git.Signature) (err error) { - var stderr string - if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "add", "--all"); err != nil { - return err - } - if len(stderr) > 0 { - log.Trace("stderr(1): %s", stderr) - } - - if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), - "-m", "Init commit"); err != nil { - return err - } - if len(stderr) > 0 { - log.Trace("stderr(2): %s", stderr) - } - - if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "push", "origin", "master"); err != nil { - return err - } - if len(stderr) > 0 { - log.Trace("stderr(3): %s", stderr) - } - return nil -} - -func createHookUpdate(hookPath, content string) error { - pu, err := os.OpenFile(hookPath, os.O_CREATE|os.O_WRONLY, 0777) - if err != nil { - return err - } - defer pu.Close() - - _, err = pu.WriteString(content) - return err -} - -// SetRepoEnvs sets environment variables for command update. -func SetRepoEnvs(userId int64, userName, repoName string) { - os.Setenv("userId", base.ToStr(userId)) - os.Setenv("userName", userName) - os.Setenv("repoName", repoName) -} - -// InitRepository initializes README and .gitignore if needed. -func initRepository(f string, user *User, repo *Repository, initReadme bool, repoLang, license string) error { - repoPath := RepoPath(user.Name, repo.Name) - - // Create bare new repository. - if err := extractGitBareZip(repoPath); err != nil { - return err - } - - // hook/post-update - if err := createHookUpdate(filepath.Join(repoPath, "hooks", "update"), - fmt.Sprintf("#!/usr/bin/env bash\n%s update $1 $2 $3\n", - strings.Replace(appPath, "\\", "/", -1))); err != nil { - return err - } - - // Initialize repository according to user's choice. - fileName := map[string]string{} - if initReadme { - fileName["readme"] = "README.md" - } - if repoLang != "" { - fileName["gitign"] = ".gitignore" - } - if license != "" { - fileName["license"] = "LICENSE" - } - - // Clone to temprory path and do the init commit. - tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond())) - os.MkdirAll(tmpDir, os.ModePerm) - - if _, _, err := com.ExecCmd("git", "clone", repoPath, tmpDir); err != nil { - return err - } - - // README - if initReadme { - defaultReadme := repo.Name + "\n" + strings.Repeat("=", - utf8.RuneCountInString(repo.Name)) + "\n\n" + repo.Description - if err := ioutil.WriteFile(filepath.Join(tmpDir, fileName["readme"]), - []byte(defaultReadme), 0644); err != nil { - return err - } - } - - // .gitignore - if repoLang != "" { - filePath := "conf/gitignore/" + repoLang - if com.IsFile(filePath) { - if _, err := com.Copy(filePath, - filepath.Join(tmpDir, fileName["gitign"])); err != nil { - return err - } - } - } - - // LICENSE - if license != "" { - filePath := "conf/license/" + license - if com.IsFile(filePath) { - if _, err := com.Copy(filePath, - filepath.Join(tmpDir, fileName["license"])); err != nil { - return err - } - } - } - - if len(fileName) == 0 { - return nil - } - - SetRepoEnvs(user.Id, user.Name, repo.Name) - - // Apply changes and commit. - return initRepoCommit(tmpDir, user.NewGitSig()) -} - -// UserRepo reporesents a repository with user name. -type UserRepo struct { - *Repository - UserName string -} - -// GetRepos returns given number of repository objects with offset. -func GetRepos(num, offset int) ([]UserRepo, error) { - repos := make([]Repository, 0, num) - if err := orm.Limit(num, offset).Asc("id").Find(&repos); err != nil { - return nil, err - } - - urepos := make([]UserRepo, len(repos)) - for i := range repos { - urepos[i].Repository = &repos[i] - u := new(User) - has, err := orm.Id(urepos[i].Repository.OwnerId).Get(u) - if err != nil { - return nil, err - } else if !has { - return nil, ErrUserNotExist - } - urepos[i].UserName = u.Name - } - - return urepos, nil -} - -func RepoPath(userName, repoName string) string { - return filepath.Join(UserPath(userName), strings.ToLower(repoName)+".git") -} - -// TransferOwnership transfers all corresponding setting from old user to new one. -func TransferOwnership(user *User, newOwner string, repo *Repository) (err error) { - newUser, err := GetUserByName(newOwner) - if err != nil { - return err - } - - // Update accesses. - accesses := make([]Access, 0, 10) - if err = orm.Find(&accesses, &Access{RepoName: user.LowerName + "/" + repo.LowerName}); err != nil { - return err - } - - sess := orm.NewSession() - defer sess.Close() - if err = sess.Begin(); err != nil { - return err - } - - for i := range accesses { - accesses[i].RepoName = newUser.LowerName + "/" + repo.LowerName - if accesses[i].UserName == user.LowerName { - accesses[i].UserName = newUser.LowerName - } - if err = UpdateAccessWithSession(sess, &accesses[i]); err != nil { - return err - } - } - - // Update repository. - repo.OwnerId = newUser.Id - if _, err := sess.Id(repo.Id).Update(repo); err != nil { - sess.Rollback() - return err - } - - // Update user repository number. - rawSql := "UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?" - if _, err = sess.Exec(rawSql, newUser.Id); err != nil { - sess.Rollback() - return err - } - rawSql = "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?" - if _, err = sess.Exec(rawSql, user.Id); err != nil { - sess.Rollback() - return err - } - - // Add watch of new owner to repository. - if !IsWatching(newUser.Id, repo.Id) { - if err = WatchRepo(newUser.Id, repo.Id, true); err != nil { - sess.Rollback() - return err - } - } - - if err = TransferRepoAction(user, newUser, repo); err != nil { - sess.Rollback() - return err - } - - // Change repository directory name. - if err = os.Rename(RepoPath(user.Name, repo.Name), RepoPath(newUser.Name, repo.Name)); err != nil { - sess.Rollback() - return err - } - - return sess.Commit() -} - -// ChangeRepositoryName changes all corresponding setting from old repository name to new one. -func ChangeRepositoryName(userName, oldRepoName, newRepoName string) (err error) { - // Update accesses. - accesses := make([]Access, 0, 10) - if err = orm.Find(&accesses, &Access{RepoName: strings.ToLower(userName + "/" + oldRepoName)}); err != nil { - return err - } - - sess := orm.NewSession() - defer sess.Close() - if err = sess.Begin(); err != nil { - return err - } - - for i := range accesses { - accesses[i].RepoName = userName + "/" + newRepoName - if err = UpdateAccessWithSession(sess, &accesses[i]); err != nil { - return err - } - } - - // Change repository directory name. - if err = os.Rename(RepoPath(userName, oldRepoName), RepoPath(userName, newRepoName)); err != nil { - sess.Rollback() - return err - } - - return sess.Commit() -} - -func UpdateRepository(repo *Repository) error { - repo.LowerName = strings.ToLower(repo.Name) - - if len(repo.Description) > 255 { - repo.Description = repo.Description[:255] - } - if len(repo.Website) > 255 { - repo.Website = repo.Website[:255] - } - _, err := orm.Id(repo.Id).AllCols().Update(repo) - return err -} - -// DeleteRepository deletes a repository for a user or orgnaztion. -func DeleteRepository(userId, repoId int64, userName string) (err error) { - repo := &Repository{Id: repoId, OwnerId: userId} - has, err := orm.Get(repo) - if err != nil { - return err - } else if !has { - return ErrRepoNotExist - } - - sess := orm.NewSession() - defer sess.Close() - if err = sess.Begin(); err != nil { - return err - } - if _, err = sess.Delete(&Repository{Id: repoId}); err != nil { - sess.Rollback() - return err - } - if _, err := sess.Delete(&Access{RepoName: strings.ToLower(path.Join(userName, repo.Name))}); err != nil { - sess.Rollback() - return err - } - rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?" - if _, err = sess.Exec(rawSql, userId); err != nil { - sess.Rollback() - return err - } - if _, err = sess.Delete(&Watch{RepoId: repoId}); err != nil { - sess.Rollback() - return err - } - if err = sess.Commit(); err != nil { - sess.Rollback() - return err - } - if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { - // TODO: log and delete manully - log.Error("delete repo %s/%s failed: %v", userName, repo.Name, err) - return err - } - return nil -} - -// GetRepositoryByName returns the repository by given name under user if exists. -func GetRepositoryByName(userId int64, repoName string) (*Repository, error) { - repo := &Repository{ - OwnerId: userId, - LowerName: strings.ToLower(repoName), - } - has, err := orm.Get(repo) - if err != nil { - return nil, err - } else if !has { - return nil, ErrRepoNotExist - } - return repo, err -} - -// GetRepositoryById returns the repository by given id if exists. -func GetRepositoryById(id int64) (*Repository, error) { - repo := &Repository{} - has, err := orm.Id(id).Get(repo) - if err != nil { - return nil, err - } else if !has { - return nil, ErrRepoNotExist - } - return repo, err -} - -// GetRepositories returns the list of repositories of given user. -func GetRepositories(user *User) ([]Repository, error) { - repos := make([]Repository, 0, 10) - err := orm.Desc("updated").Find(&repos, &Repository{OwnerId: user.Id}) - return repos, err -} - -func GetRepositoryCount(user *User) (int64, error) { - return orm.Count(&Repository{OwnerId: user.Id}) -} - -// Watch is connection request for receiving repository notifycation. -type Watch struct { - Id int64 - RepoId int64 `xorm:"UNIQUE(watch)"` - UserId int64 `xorm:"UNIQUE(watch)"` -} - -// Watch or unwatch repository. -func WatchRepo(userId, repoId int64, watch bool) (err error) { - if watch { - if _, err = orm.Insert(&Watch{RepoId: repoId, UserId: userId}); err != nil { - return err - } - - rawSql := "UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?" - _, err = orm.Exec(rawSql, repoId) - } else { - if _, err = orm.Delete(&Watch{0, repoId, userId}); err != nil { - return err - } - rawSql := "UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?" - _, err = orm.Exec(rawSql, repoId) - } - return err -} - -// GetWatches returns all watches of given repository. -func GetWatches(repoId int64) ([]Watch, error) { - watches := make([]Watch, 0, 10) - err := orm.Find(&watches, &Watch{RepoId: repoId}) - return watches, err -} - -// NotifyWatchers creates batch of actions for every watcher. -func NotifyWatchers(act *Action) error { - // Add feeds for user self and all watchers. - watches, err := GetWatches(act.RepoId) - if err != nil { - return errors.New("repo.NotifyWatchers(get watches): " + err.Error()) - } - - // Add feed for actioner. - act.UserId = act.ActUserId - if _, err = orm.InsertOne(act); err != nil { - return errors.New("repo.NotifyWatchers(create action): " + err.Error()) - } - - for i := range watches { - if act.ActUserId == watches[i].UserId { - continue - } - - act.Id = 0 - act.UserId = watches[i].UserId - if _, err = orm.InsertOne(act); err != nil { - return errors.New("repo.NotifyWatchers(create action): " + err.Error()) - } - } - return nil -} - -// IsWatching checks if user has watched given repository. -func IsWatching(userId, repoId int64) bool { - has, _ := orm.Get(&Watch{0, repoId, userId}) - return has -} - -func ForkRepository(reposName string, userId int64) { - -} diff --git a/models/user.go b/models/user.go deleted file mode 100644 index b2fddd0a1d..0000000000 --- a/models/user.go +++ /dev/null @@ -1,479 +0,0 @@ -// 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 ( - "crypto/sha256" - "encoding/hex" - "errors" - "fmt" - "os" - "path/filepath" - "strings" - "time" - - "github.com/gogits/git" - - "github.com/gogits/gogs/modules/base" - "github.com/gogits/gogs/modules/log" -) - -// User types. -const ( - UT_INDIVIDUAL = iota + 1 - UT_ORGANIZATION -) - -// Login types. -const ( - LT_PLAIN = iota + 1 - LT_LDAP -) - -var ( - ErrUserOwnRepos = errors.New("User still have ownership of repositories") - ErrUserAlreadyExist = errors.New("User already exist") - ErrUserNotExist = errors.New("User does not exist") - ErrEmailAlreadyUsed = errors.New("E-mail already used") - ErrUserNameIllegal = errors.New("User name contains illegal characters") - ErrKeyNotExist = errors.New("Public key does not exist") -) - -// User represents the object of individual and member of organization. -type User struct { - Id int64 - LowerName string `xorm:"unique not null"` - Name string `xorm:"unique not null"` - Email string `xorm:"unique not null"` - Passwd string `xorm:"not null"` - LoginType int - Type int - NumFollowers int - NumFollowings int - NumStars int - NumRepos int - Avatar string `xorm:"varchar(2048) not null"` - AvatarEmail string `xorm:"not null"` - Location string - Website string - IsActive bool - IsAdmin bool - Rands string `xorm:"VARCHAR(10)"` - Salt string `xorm:"VARCHAR(10)"` - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` -} - -// HomeLink returns the user home page link. -func (user *User) HomeLink() string { - return "/user/" + user.Name -} - -// AvatarLink returns the user gravatar link. -func (user *User) AvatarLink() string { - if base.Service.EnableCacheAvatar { - return "/avatar/" + user.Avatar - } - return "http://1.gravatar.com/avatar/" + user.Avatar -} - -// NewGitSig generates and returns the signature of given user. -func (user *User) NewGitSig() *git.Signature { - return &git.Signature{ - Name: user.Name, - Email: user.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) -} - -// Member represents user is member of organization. -type Member struct { - Id int64 - OrgId int64 `xorm:"unique(member) index"` - UserId int64 `xorm:"unique(member)"` -} - -// IsUserExist checks if given user name exist, -// the user name should be noncased unique. -func IsUserExist(name string) (bool, error) { - if len(name) == 0 { - return false, nil - } - return orm.Get(&User{LowerName: strings.ToLower(name)}) -} - -// IsEmailUsed returns true if the e-mail has been used. -func IsEmailUsed(email string) (bool, error) { - if len(email) == 0 { - return false, nil - } - return orm.Get(&User{Email: email}) -} - -// return a user salt token -func GetUserSalt() string { - return base.GetRandomString(10) -} - -// RegisterUser creates record of a new user. -func RegisterUser(user *User) (*User, error) { - if !IsLegalName(user.Name) { - return nil, ErrUserNameIllegal - } - - isExist, err := IsUserExist(user.Name) - if err != nil { - return nil, err - } else if isExist { - return nil, ErrUserAlreadyExist - } - - isExist, err = IsEmailUsed(user.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 = orm.Insert(user); err != nil { - return nil, err - } else if err = os.MkdirAll(UserPath(user.Name), os.ModePerm); err != nil { - if _, err := orm.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)) - } - return nil, err - } - - if user.Id == 1 { - user.IsAdmin = true - user.IsActive = true - _, err = orm.Id(user.Id).UseBool().Update(user) - } - return user, err -} - -// GetUsers returns given number of user objects with offset. -func GetUsers(num, offset int) ([]User, error) { - users := make([]User, 0, num) - err := orm.Limit(num, offset).Asc("id").Find(&users) - return users, err -} - -// get user by erify code -func getVerifyUser(code string) (user *User) { - if len(code) <= base.TimeLimitCodeLength { - return nil - } - - // use tail hex username query user - hexStr := code[base.TimeLimitCodeLength:] - if b, err := hex.DecodeString(hexStr); err == nil { - if user, err = GetUserByName(string(b)); user != nil { - return user - } - log.Error("user.getVerifyUser: %v", err) - } - - return nil -} - -// verify active code when active account -func VerifyUserActiveCode(code string) (user *User) { - minutes := base.Service.ActiveCodeLives - - if user = getVerifyUser(code); user != nil { - // time limit code - prefix := code[:base.TimeLimitCodeLength] - data := base.ToStr(user.Id) + user.Email + user.LowerName + user.Passwd + user.Rands - - if base.VerifyTimeLimitCode(data, minutes, prefix) { - return user - } - } - return nil -} - -// ChangeUserName changes all corresponding setting from old user name to new one. -func ChangeUserName(user *User, newUserName string) (err error) { - newUserName = strings.ToLower(newUserName) - - // Update accesses of user. - accesses := make([]Access, 0, 10) - if err = orm.Find(&accesses, &Access{UserName: user.LowerName}); err != nil { - return err - } - - sess := orm.NewSession() - defer sess.Close() - if err = sess.Begin(); err != nil { - return err - } - - for i := range accesses { - accesses[i].UserName = newUserName - if strings.HasPrefix(accesses[i].RepoName, user.LowerName+"/") { - accesses[i].RepoName = strings.Replace(accesses[i].RepoName, user.LowerName, newUserName, 1) - if err = UpdateAccessWithSession(sess, &accesses[i]); err != nil { - return err - } - } - } - - repos, err := GetRepositories(user) - if err != nil { - return err - } - for i := range repos { - accesses = make([]Access, 0, 10) - // Update accesses of user repository. - if err = orm.Find(&accesses, &Access{RepoName: user.LowerName + "/" + repos[i].LowerName}); err != nil { - return err - } - - for j := range accesses { - accesses[j].RepoName = newUserName + "/" + repos[i].LowerName - if err = UpdateAccessWithSession(sess, &accesses[j]); err != nil { - return err - } - } - } - - // Change user directory name. - if err = os.Rename(UserPath(user.LowerName), UserPath(newUserName)); err != nil { - sess.Rollback() - return err - } - - return sess.Commit() -} - -// UpdateUser updates user's information. -func UpdateUser(user *User) (err error) { - user.LowerName = strings.ToLower(user.Name) - - if len(user.Location) > 255 { - user.Location = user.Location[:255] - } - if len(user.Website) > 255 { - user.Website = user.Website[:255] - } - - _, err = orm.Id(user.Id).AllCols().Update(user) - return err -} - -// DeleteUser completely deletes everything of the user. -func DeleteUser(user *User) error { - // Check ownership of repository. - count, err := GetRepositoryCount(user) - if err != nil { - return errors.New("modesl.GetRepositories: " + err.Error()) - } else if count > 0 { - return ErrUserOwnRepos - } - - // TODO: check issues, other repos' commits - - // Delete all followers. - if _, err = orm.Delete(&Follow{FollowId: user.Id}); err != nil { - return err - } - - // Delete all feeds. - if _, err = orm.Delete(&Action{UserId: user.Id}); err != nil { - return err - } - - // Delete all watches. - if _, err = orm.Delete(&Watch{UserId: user.Id}); err != nil { - return err - } - - // Delete all accesses. - if _, err = orm.Delete(&Access{UserName: user.LowerName}); err != nil { - return err - } - - // Delete all SSH keys. - keys := make([]PublicKey, 0, 10) - if err = orm.Find(&keys, &PublicKey{OwnerId: user.Id}); err != nil { - return err - } - for _, key := range keys { - if err = DeletePublicKey(&key); err != nil { - return err - } - } - - // Delete user directory. - if err = os.RemoveAll(UserPath(user.Name)); err != nil { - return err - } - - _, err = orm.Delete(user) - return err -} - -// UserPath returns the path absolute path of user repositories. -func UserPath(userName string) string { - return filepath.Join(base.RepoRootPath, strings.ToLower(userName)) -} - -func GetUserByKeyId(keyId int64) (*User, error) { - user := new(User) - rawSql := "SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?" - has, err := orm.Sql(rawSql, keyId).Get(user) - if err != nil { - return nil, err - } else if !has { - err = errors.New("not exist key owner") - return nil, err - } - return user, nil -} - -// GetUserById returns the user object by given id if exists. -func GetUserById(id int64) (*User, error) { - user := new(User) - has, err := orm.Id(id).Get(user) - if err != nil { - return nil, err - } - if !has { - return nil, ErrUserNotExist - } - return user, nil -} - -// GetUserByName returns the user object by given name if exists. -func GetUserByName(name string) (*User, error) { - if len(name) == 0 { - return nil, ErrUserNotExist - } - user := &User{LowerName: strings.ToLower(name)} - has, err := orm.Get(user) - if err != nil { - return nil, err - } else if !has { - return nil, ErrUserNotExist - } - return user, nil -} - -// GetUserEmailsByNames returns a slice of e-mails corresponds to names. -func GetUserEmailsByNames(names []string) []string { - mails := make([]string, 0, len(names)) - for _, name := range names { - u, err := GetUserByName(name) - if err != nil { - continue - } - mails = append(mails, u.Email) - } - return mails -} - -// GetUserByEmail returns the user object by given e-mail if exists. -func GetUserByEmail(email string) (*User, error) { - if len(email) == 0 { - return nil, ErrUserNotExist - } - user := &User{Email: strings.ToLower(email)} - has, err := orm.Get(user) - if err != nil { - return nil, err - } else if !has { - return nil, ErrUserNotExist - } - return user, nil -} - -// LoginUserPlain validates user by raw user name and password. -func LoginUserPlain(name, passwd string) (*User, error) { - user := User{LowerName: strings.ToLower(name)} - has, err := orm.Get(&user) - if err != nil { - return nil, err - } else if !has { - return nil, ErrUserNotExist - } - - newUser := &User{Passwd: passwd, Salt: user.Salt} - newUser.EncodePasswd() - if user.Passwd != newUser.Passwd { - return nil, ErrUserNotExist - } - return &user, nil -} - -// Follow is connection request for receiving user notifycation. -type Follow struct { - Id int64 - UserId int64 `xorm:"unique(follow)"` - FollowId int64 `xorm:"unique(follow)"` -} - -// FollowUser marks someone be another's follower. -func FollowUser(userId int64, followId int64) (err error) { - session := orm.NewSession() - defer session.Close() - session.Begin() - - if _, err = session.Insert(&Follow{UserId: userId, FollowId: followId}); err != nil { - session.Rollback() - return err - } - - rawSql := "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?" - if _, err = session.Exec(rawSql, followId); err != nil { - session.Rollback() - return err - } - - rawSql = "UPDATE `user` SET num_followings = num_followings + 1 WHERE id = ?" - if _, err = session.Exec(rawSql, userId); err != nil { - session.Rollback() - return err - } - return session.Commit() -} - -// UnFollowUser unmarks someone be another's follower. -func UnFollowUser(userId int64, unFollowId int64) (err error) { - session := orm.NewSession() - defer session.Close() - session.Begin() - - if _, err = session.Delete(&Follow{UserId: userId, FollowId: unFollowId}); err != nil { - session.Rollback() - return err - } - - rawSql := "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?" - if _, err = session.Exec(rawSql, unFollowId); err != nil { - session.Rollback() - return err - } - - rawSql = "UPDATE `user` SET num_followings = num_followings - 1 WHERE id = ?" - if _, err = session.Exec(rawSql, userId); err != nil { - session.Rollback() - return err - } - return session.Commit() -} |