diff --git a/.gitignore b/.gitignore index 92b579f2..07372407 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ gogs *.exe *.exe~ -.DS_Store \ No newline at end of file +.DS_Store +*.db diff --git a/models/models.go b/models/models.go index d5a8c8cf..bddece47 100644 --- a/models/models.go +++ b/models/models.go @@ -5,67 +5,42 @@ package models import ( - "os" - "path/filepath" + "time" + "github.com/lunny/xorm" - - git "github.com/libgit2/git2go" ) -const ( - UserRepo = iota - OrgRepo +var ( + // orm + orm *xorm.Engine + // repository root path + root string ) -type User struct { - Id int64 - Name string `xorm:"unique"` +type PublicKey struct { + Id int64 + Name string `xorm:"unique not null"` + Content string `xorm:"text not null"` + Created time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` } -type Org struct { +type Members struct { + Id int64 + OrgId int64 `xorm:"unique(s) index"` + UserId int64 `xorm:"unique(s)"` +} + +type Issue struct { + Id int64 + RepoId int64 `xorm:"index"` + PosterId int64 +} + +type PullRequest struct { Id int64 } -type Repo struct { - Id int64 - OwnerId int64 `xorm:"unique(s)"` - Type int `xorm:"unique(s)"` - Name string `xorm:"unique(s)"` -} - -var ( - orm *xorm.Engine -) - -// -// create a repository for a user or orgnaziation -// -func CreateUserRepository(root string, user *User, reposName string) error { - p := filepath.Join(root, user.Name) - os.MkdirAll(p, os.ModePerm) - f := filepath.Join(p, reposName) - _, err := git.InitRepository(f, false) - if err != nil { - return err - } - - repo := Repo{OwnerId: user.Id, Type: UserRepo, Name: reposName} - _, err = orm.Insert(&repo) - if err != nil { - os.RemoveAll(f) - } - return err -} - -// -// delete a repository for a user or orgnaztion -// -func DeleteUserRepository(root string, user *User, reposName string) error { - err := os.RemoveAll(filepath.Join(root, user.Name, reposName)) - if err != nil { - return err - } - - _, err = orm.Delete(&Repo{OwnerId: user.Id, Type: UserRepo, Name: reposName}) - return err +type Comment struct { + Id int64 } diff --git a/models/models_test.go b/models/models_test.go index 80653d57..f4a40ff3 100644 --- a/models/models_test.go +++ b/models/models_test.go @@ -15,15 +15,28 @@ func init() { fmt.Println(err) } - err = orm.Sync(&User{}, &Org{}, &Repo{}) + orm.ShowSQL = true + orm.ShowDebug = true + + err = orm.Sync(&User{}, &Repo{}) if err != nil { fmt.Println(err) } + + root = "test" } func TestCreateRepository(t *testing.T) { - user := User{Id: 1} - err := CreateUserRepository("test", &user, "test") + user := User{Id: 1, Type: Individual} + _, err := CreateRepository(&user, "test") + if err != nil { + t.Error(err) + } +} + +func TestDeleteRepository(t *testing.T) { + user := User{Id: 1, Type: Individual} + err := DeleteRepository(&user, "test") if err != nil { t.Error(err) } diff --git a/models/repo.go b/models/repo.go new file mode 100644 index 00000000..8e3aae9a --- /dev/null +++ b/models/repo.go @@ -0,0 +1,119 @@ +package models + +import ( + "os" + "path/filepath" + "strings" + "time" + + git "github.com/libgit2/git2go" +) + +type Repo struct { + Id int64 + OwnerId int64 `xorm:"unique(s)"` + ForkId int64 + LowerName string `xorm:"unique(s) index not null"` + Name string `xorm:"index not null"` + NumWatchs int + NumStars int + NumForks int + Created time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` +} + +// check if repository is exist +func IsRepositoryExist(user *User, reposName string) (bool, error) { + repo := Repo{OwnerId: user.Id} + // TODO: get repository by nocase name + return orm.Where("lower_name = ?", strings.ToLower(reposName)).Get(&repo) +} + +// +// create a repository for a user or orgnaziation +// +func CreateRepository(user *User, reposName string) (*Repo, error) { + p := filepath.Join(root, user.Name) + os.MkdirAll(p, os.ModePerm) + f := filepath.Join(p, reposName) + _, err := git.InitRepository(f, false) + if err != nil { + return nil, err + } + + repo := Repo{OwnerId: user.Id, Name: reposName} + session := orm.NewSession() + defer session.Close() + session.Begin() + _, err = session.Insert(&repo) + if err != nil { + os.RemoveAll(f) + session.Rollback() + return nil, err + } + _, err = session.Exec("update user set num_repos = num_repos + 1 where id = ?", user.Id) + if err != nil { + os.RemoveAll(f) + session.Rollback() + return nil, err + } + err = session.Commit() + if err != nil { + os.RemoveAll(f) + session.Rollback() + return nil, err + } + return &repo, nil +} + +// list one user's repository +func GetRepositories(user *User) ([]Repo, error) { + repos := make([]Repo, 0) + err := orm.Find(&repos, &Repo{OwnerId: user.Id}) + return repos, err +} + +func StarReposiory(user *User, repoName string) error { + return nil +} + +func UnStarRepository() { + +} + +func WatchRepository() { + +} + +func UnWatchRepository() { + +} + +// +// delete a repository for a user or orgnaztion +// +func DeleteRepository(user *User, reposName string) error { + session := orm.NewSession() + _, err := session.Delete(&Repo{OwnerId: user.Id, Name: reposName}) + if err != nil { + session.Rollback() + return err + } + _, err = session.Exec("update user set num_repos = num_repos - 1 where id = ?", user.Id) + if err != nil { + session.Rollback() + return err + } + err = session.Commit() + if err != nil { + session.Rollback() + return err + } + + err = os.RemoveAll(filepath.Join(root, user.Name, reposName)) + if err != nil { + // TODO: log and delete manully + return err + } + return nil +} diff --git a/models/user.go b/models/user.go new file mode 100644 index 00000000..4093c5cc --- /dev/null +++ b/models/user.go @@ -0,0 +1,148 @@ +package models + +import ( + "errors" + "fmt" + "strings" + "time" + + "github.com/dchest/scrypt" +) // user type +const ( + Individual = iota + 1 + Organization +) + +// login type +const ( + Plain = iota + 1 + LDAP +) + +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"` + Created time.Time `xorm:"created"` + Updated time.Time `xorm:"updated"` +} + +type Follow struct { + Id int64 + UserId int64 `xorm:"unique(s)"` + FollowId int64 `xorm:"unique(s)"` + Created time.Time `xorm:"created"` +} + +const ( + OpCreateRepo = iota + 1 + OpDeleteRepo + OpStarRepo + OpFollowRepo + OpCommitRepo + OpPullRequest +) + +type Action struct { + Id int64 + UserId int64 + OpType int + RepoId int64 + Content string + Created time.Time `xorm:"created"` +} + +var ( + ErrUserNotExist = errors.New("User not exist") +) + +// user's name should be noncased unique +func IsUserExist(name string) (bool, error) { + return orm.Get(&User{LowerName: strings.ToLower(name)}) +} + +func RegisterUser(user *User) error { + _, err := orm.Insert(user) + return err +} + +func UpdateUser(user *User) error { + _, err := orm.Id(user.Id).Update(user) + return err +} + +func (user *User) EncodePasswd(pass string) error { + newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte("!#@FDEWREWR&*("), 16384, 8, 1, 64) + user.Passwd = fmt.Sprintf("%x", newPasswd) + return err +} + +func LoginUserPlain(name, passwd string) (*User, error) { + user := User{Name: name} + err := user.EncodePasswd(passwd) + if err != nil { + return nil, err + } + + has, err := orm.Get(&user) + if !has { + err = ErrUserNotExist + } + if err != nil { + return nil, err + } + return &user, nil +} + +func FollowUser(userId int64, followId int64) error { + session := orm.NewSession() + defer session.Close() + session.Begin() + _, err := session.Insert(&Follow{UserId: userId, FollowId: followId}) + if err != nil { + session.Rollback() + return err + } + _, err = session.Exec("update user set num_followers = num_followers + 1 where id = ?", followId) + if err != nil { + session.Rollback() + return err + } + _, err = session.Exec("update user set num_followings = num_followings + 1 where id = ?", userId) + if err != nil { + session.Rollback() + return err + } + return session.Commit() +} + +func UnFollowUser(userId int64, unFollowId int64) error { + session := orm.NewSession() + defer session.Close() + session.Begin() + _, err := session.Delete(&Follow{UserId: userId, FollowId: unFollowId}) + if err != nil { + session.Rollback() + return err + } + _, err = session.Exec("update user set num_followers = num_followers - 1 where id = ?", unFollowId) + if err != nil { + session.Rollback() + return err + } + _, err = session.Exec("update user set num_followings = num_followings - 1 where id = ?", userId) + if err != nil { + session.Rollback() + return err + } + return session.Commit() +}