diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/action.go | 23 | ||||
-rw-r--r-- | models/login.go | 83 | ||||
-rw-r--r-- | models/models.go | 7 | ||||
-rw-r--r-- | models/publickey.go | 14 | ||||
-rw-r--r-- | models/repo.go | 69 | ||||
-rw-r--r-- | models/user.go | 2 | ||||
-rw-r--r-- | models/webhook.go | 133 |
7 files changed, 219 insertions, 112 deletions
diff --git a/models/action.go b/models/action.go index 9fc9d89b..e39b04a1 100644 --- a/models/action.go +++ b/models/action.go @@ -15,7 +15,6 @@ import ( qlog "github.com/qiniu/log" "github.com/gogits/gogs/modules/base" - "github.com/gogits/gogs/modules/hooks" "github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/setting" ) @@ -131,35 +130,35 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string, } repoLink := fmt.Sprintf("%s%s/%s", setting.AppUrl, repoUserName, repoName) - commits := make([]*hooks.PayloadCommit, len(commit.Commits)) + commits := make([]*PayloadCommit, len(commit.Commits)) for i, cmt := range commit.Commits { - commits[i] = &hooks.PayloadCommit{ + commits[i] = &PayloadCommit{ Id: cmt.Sha1, Message: cmt.Message, Url: fmt.Sprintf("%s/commit/%s", repoLink, cmt.Sha1), - Author: &hooks.PayloadAuthor{ + Author: &PayloadAuthor{ Name: cmt.AuthorName, Email: cmt.AuthorEmail, }, } } - p := &hooks.Payload{ + p := &Payload{ Ref: refFullName, Commits: commits, - Repo: &hooks.PayloadRepo{ + Repo: &PayloadRepo{ Id: repo.Id, Name: repo.LowerName, Url: repoLink, Description: repo.Description, Website: repo.Website, Watchers: repo.NumWatches, - Owner: &hooks.PayloadAuthor{ + Owner: &PayloadAuthor{ Name: repoUserName, Email: actEmail, }, Private: repo.IsPrivate, }, - Pusher: &hooks.PayloadAuthor{ + Pusher: &PayloadAuthor{ Name: repo.Owner.LowerName, Email: repo.Owner.Email, }, @@ -172,7 +171,13 @@ func CommitRepoAction(userId, repoUserId int64, userName, actEmail string, } p.Secret = w.Secret - hooks.AddHookTask(&hooks.HookTask{hooks.HTT_WEBHOOK, w.Url, p, w.ContentType, w.IsSsl}) + CreateHookTask(&HookTask{ + Type: WEBHOOK, + Url: w.Url, + Payload: p, + ContentType: w.ContentType, + IsSsl: w.IsSsl, + }) } return nil } diff --git a/models/login.go b/models/login.go index 984a9f8c..863ba44e 100644 --- a/models/login.go +++ b/models/login.go @@ -1,4 +1,4 @@ -// Copyright github.com/juju2013. All rights reserved. +// 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. @@ -20,12 +20,13 @@ import ( "github.com/gogits/gogs/modules/log" ) -// Login types. +type LoginType int + const ( - LT_NOTYPE = iota - LT_PLAIN - LT_LDAP - LT_SMTP + NOTYPE LoginType = iota + PLAIN + LDAP + SMTP ) var ( @@ -34,9 +35,9 @@ var ( ErrAuthenticationUserUsed = errors.New("Authentication has been used by some users") ) -var LoginTypes = map[int]string{ - LT_LDAP: "LDAP", - LT_SMTP: "SMTP", +var LoginTypes = map[LoginType]string{ + LDAP: "LDAP", + SMTP: "SMTP", } // Ensure structs implmented interface. @@ -49,7 +50,6 @@ type LDAPConfig struct { ldap.Ldapsource } -// implement func (cfg *LDAPConfig) FromDB(bs []byte) error { return json.Unmarshal(bs, &cfg.Ldapsource) } @@ -65,7 +65,6 @@ type SMTPConfig struct { TLS bool } -// implement func (cfg *SMTPConfig) FromDB(bs []byte) error { return json.Unmarshal(bs, cfg) } @@ -76,13 +75,13 @@ func (cfg *SMTPConfig) ToDB() ([]byte, error) { type LoginSource struct { Id int64 - Type int - Name string `xorm:"unique"` - IsActived bool `xorm:"not null default false"` + Type LoginType + Name string `xorm:"UNIQUE"` + IsActived bool `xorm:"NOT NULL DEFAULT false"` Cfg core.Conversion `xorm:"TEXT"` - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` - AllowAutoRegister bool `xorm:"not null default false"` + AllowAutoRegister bool `xorm:"NOT NULL DEFAULT false"` + Created time.Time `xorm:"CREATED"` + Updated time.Time `xorm:"UPDATED"` } func (source *LoginSource) TypeString() string { @@ -97,21 +96,25 @@ func (source *LoginSource) SMTP() *SMTPConfig { return source.Cfg.(*SMTPConfig) } -// for xorm callback func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { if colName == "type" { ty := (*val).(int64) - switch ty { - case LT_LDAP: + switch LoginType(ty) { + case LDAP: source.Cfg = new(LDAPConfig) - case LT_SMTP: + case SMTP: source.Cfg = new(SMTPConfig) } } } +func CreateSource(source *LoginSource) error { + _, err := orm.Insert(source) + return err +} + func GetAuths() ([]*LoginSource, error) { - var auths = make([]*LoginSource, 0) + var auths = make([]*LoginSource, 0, 5) err := orm.Find(&auths) return auths, err } @@ -121,18 +124,12 @@ func GetLoginSourceById(id int64) (*LoginSource, error) { has, err := orm.Id(id).Get(source) if err != nil { return nil, err - } - if !has { + } else if !has { return nil, ErrAuthenticationNotExist } return source, nil } -func AddSource(source *LoginSource) error { - _, err := orm.Insert(source) - return err -} - func UpdateSource(source *LoginSource) error { _, err := orm.Id(source.Id).AllCols().Update(source) return err @@ -164,14 +161,14 @@ func UserSignIn(uname, passwd string) (*User, error) { return nil, err } - if u.LoginType == LT_NOTYPE { + if u.LoginType == NOTYPE { if has { - u.LoginType = LT_PLAIN + u.LoginType = PLAIN } } // for plain login, user must have existed. - if u.LoginType == LT_PLAIN { + if u.LoginType == PLAIN { if !has { return nil, ErrUserNotExist } @@ -191,22 +188,20 @@ func UserSignIn(uname, passwd string) (*User, error) { } for _, source := range sources { - if source.Type == LT_LDAP { + if source.Type == LDAP { u, err := LoginUserLdapSource(nil, uname, passwd, source.Id, source.Cfg.(*LDAPConfig), true) if err == nil { return u, nil - } else { - log.Warn("Fail to login(%s) by LDAP(%s): %v", uname, source.Name, err) } - } else if source.Type == LT_SMTP { + log.Warn("Fail to login(%s) by LDAP(%s): %v", uname, source.Name, err) + } else if source.Type == SMTP { u, err := LoginUserSMTPSource(nil, uname, passwd, source.Id, source.Cfg.(*SMTPConfig), true) if err == nil { return u, nil - } else { - log.Warn("Fail to login(%s) by SMTP(%s): %v", uname, source.Name, err) } + log.Warn("Fail to login(%s) by SMTP(%s): %v", uname, source.Name, err) } } @@ -224,10 +219,10 @@ func UserSignIn(uname, passwd string) (*User, error) { } switch u.LoginType { - case LT_LDAP: + case LDAP: return LoginUserLdapSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*LDAPConfig), false) - case LT_SMTP: + case SMTP: return LoginUserSMTPSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*SMTPConfig), false) } @@ -252,7 +247,7 @@ func LoginUserLdapSource(user *User, name, passwd string, sourceId int64, cfg *L user = &User{ LowerName: strings.ToLower(name), Name: strings.ToLower(name), - LoginType: LT_LDAP, + LoginType: LDAP, LoginSource: sourceId, LoginName: name, IsActive: true, @@ -320,9 +315,8 @@ func SmtpAuth(host string, port int, a smtp.Auth, useTls bool) error { return err } return nil - } else { - return ErrUnsupportedLoginType } + return ErrUnsupportedLoginType } // Query if name/passwd can login against the LDAP direcotry pool @@ -358,13 +352,12 @@ func LoginUserSMTPSource(user *User, name, passwd string, sourceId int64, cfg *S user = &User{ LowerName: strings.ToLower(loginName), Name: strings.ToLower(loginName), - LoginType: LT_SMTP, + LoginType: SMTP, LoginSource: sourceId, LoginName: name, IsActive: true, Passwd: passwd, Email: name, } - return RegisterUser(user) } diff --git a/models/models.go b/models/models.go index fa65ef30..a59c0517 100644 --- a/models/models.go +++ b/models/models.go @@ -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(Milestone), new(Label), new(HookTask)) } func LoadModelsConfig() { @@ -46,7 +46,9 @@ func LoadModelsConfig() { DbCfg.Host = setting.Cfg.MustValue("database", "HOST") DbCfg.Name = setting.Cfg.MustValue("database", "NAME") DbCfg.User = setting.Cfg.MustValue("database", "USER") - DbCfg.Pwd = setting.Cfg.MustValue("database", "PASSWD") + if len(DbCfg.Pwd) == 0 { + DbCfg.Pwd = setting.Cfg.MustValue("database", "PASSWD") + } DbCfg.SslMode = setting.Cfg.MustValue("database", "SSL_MODE") DbCfg.Path = setting.Cfg.MustValue("database", "PATH", "data/gogs.db") } @@ -67,7 +69,6 @@ func NewTestEngine(x *xorm.Engine) (err error) { } cnnstr := fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s", DbCfg.User, DbCfg.Pwd, host, port, DbCfg.Name, DbCfg.SslMode) - //fmt.Println(cnnstr) x, err = xorm.NewEngine("postgres", cnnstr) case "sqlite3": if !EnableSQLite3 { diff --git a/models/publickey.go b/models/publickey.go index 556db964..76dc0cc7 100644 --- a/models/publickey.go +++ b/models/publickey.go @@ -37,7 +37,7 @@ var ( var sshOpLocker = sync.Mutex{} var ( - sshPath string // SSH directory. + SshPath string // SSH directory. appPath string // Execution(binary) path. ) @@ -67,9 +67,9 @@ func init() { } // Determine and create .ssh path. - sshPath = filepath.Join(homeDir(), ".ssh") - if err = os.MkdirAll(sshPath, os.ModePerm); err != nil { - qlog.Fatalf("publickey.init(fail to create sshPath(%s)): %v\n", sshPath, err) + SshPath = filepath.Join(homeDir(), ".ssh") + if err = os.MkdirAll(SshPath, os.ModePerm); err != nil { + qlog.Fatalf("publickey.init(fail to create SshPath(%s)): %v\n", SshPath, err) } } @@ -94,7 +94,7 @@ func saveAuthorizedKeyFile(key *PublicKey) error { sshOpLocker.Lock() defer sshOpLocker.Unlock() - fpath := filepath.Join(sshPath, "authorized_keys") + fpath := filepath.Join(SshPath, "authorized_keys") f, err := os.OpenFile(fpath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) if err != nil { return err @@ -216,8 +216,8 @@ func DeletePublicKey(key *PublicKey) error { return err } - fpath := filepath.Join(sshPath, "authorized_keys") - tmpPath := filepath.Join(sshPath, "authorized_keys.tmp") + fpath := filepath.Join(SshPath, "authorized_keys") + tmpPath := filepath.Join(SshPath, "authorized_keys.tmp") log.Trace("publickey.DeletePublicKey(authorized_keys): %s", fpath) if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil { diff --git a/models/repo.go b/models/repo.go index 869059fa..7eab83c2 100644 --- a/models/repo.go +++ b/models/repo.go @@ -28,6 +28,10 @@ import ( "github.com/gogits/gogs/modules/setting" ) +const ( + TPL_UPDATE_HOOK = "#!/usr/bin/env %s\n%s update $1 $2 $3\n" +) + var ( ErrRepoAlreadyExist = errors.New("Repository already exist") ErrRepoNotExist = errors.New("Repository does not exist") @@ -109,11 +113,11 @@ func NewRepoContext() { // Repository represents a git repository. type Repository struct { Id int64 - OwnerId int64 `xorm:"unique(s)"` + OwnerId int64 `xorm:"UNIQUE(s)"` Owner *User `xorm:"-"` ForkId int64 - LowerName string `xorm:"unique(s) index not null"` - Name string `xorm:"index not null"` + LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"` + Name string `xorm:"INDEX NOT NULL"` Description string Website string NumWatches int @@ -131,8 +135,8 @@ type Repository struct { IsBare bool IsGoget bool DefaultBranch string - Created time.Time `xorm:"created"` - Updated time.Time `xorm:"updated"` + Created time.Time `xorm:"CREATED"` + Updated time.Time `xorm:"UPDATED"` } func (repo *Repository) GetOwner() (err error) { @@ -184,6 +188,25 @@ type Mirror struct { NextUpdate time.Time } +// MirrorRepository creates a mirror repository from source. +func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error { + _, stderr, err := com.ExecCmd("git", "clone", "--mirror", url, repoPath) + if err != nil { + return errors.New("git clone --mirror: " + stderr) + } + + if _, err = orm.InsertOne(&Mirror{ + RepoId: repoId, + RepoName: strings.ToLower(userName + "/" + repoName), + Interval: 24, + NextUpdate: time.Now().Add(24 * time.Hour), + }); err != nil { + return err + } + + return git.UnpackRefs(repoPath) +} + func GetMirror(repoId int64) (*Mirror, error) { m := &Mirror{RepoId: repoId} has, err := orm.Get(m) @@ -223,25 +246,6 @@ func MirrorUpdate() { } } -// MirrorRepository creates a mirror repository from source. -func MirrorRepository(repoId int64, userName, repoName, repoPath, url string) error { - _, stderr, err := com.ExecCmd("git", "clone", "--mirror", url, repoPath) - if err != nil { - return errors.New("git clone --mirror: " + stderr) - } - - if _, err = orm.InsertOne(&Mirror{ - RepoId: repoId, - RepoName: strings.ToLower(userName + "/" + repoName), - Interval: 24, - NextUpdate: time.Now().Add(24 * time.Hour), - }); err != nil { - return err - } - - return git.UnpackRefs(repoPath) -} - // 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) @@ -450,7 +454,7 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep rp := strings.NewReplacer("\\", "/", " ", "\\ ") // hook/post-update if err := createHookUpdate(filepath.Join(repoPath, "hooks", "update"), - fmt.Sprintf("#!/usr/bin/env %s\n%s update $1 $2 $3\n", setting.ScriptType, + fmt.Sprintf(TPL_UPDATE_HOOK, setting.ScriptType, rp.Replace(appPath))); err != nil { return err } @@ -746,16 +750,11 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) { 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) + sess.Rollback() return err } - return nil + return sess.Commit() } // GetRepositoryByName returns the repository by given name under user if exists. @@ -832,11 +831,11 @@ func GetCollaborativeRepos(uname string) ([]*Repository, error) { repos := make([]*Repository, 0, 10) for _, access := range accesses { - if strings.HasPrefix(access.RepoName, uname) { + infos := strings.Split(access.RepoName, "/") + if infos[0] == uname { continue } - - infos := strings.Split(access.RepoName, "/") + u, err := GetUserByName(infos[0]) if err != nil { return nil, err diff --git a/models/user.go b/models/user.go index 78ab4642..04ea1fd6 100644 --- a/models/user.go +++ b/models/user.go @@ -47,7 +47,7 @@ type User struct { FullName string Email string `xorm:"unique not null"` Passwd string `xorm:"not null"` - LoginType int + LoginType LoginType LoginSource int64 `xorm:"not null default 0"` LoginName string Type int diff --git a/models/webhook.go b/models/webhook.go index f10fa213..ffd47c8f 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -7,29 +7,35 @@ package models import ( "encoding/json" "errors" + "time" + "github.com/gogits/gogs/modules/httplib" "github.com/gogits/gogs/modules/log" + "github.com/gogits/gogs/modules/setting" ) var ( ErrWebhookNotExist = errors.New("Webhook does not exist") ) -// Content types. +type HookContentType int + const ( - CT_JSON = iota + 1 - CT_FORM + JSON HookContentType = iota + 1 + FORM ) +// HookEvent represents events that will delivery hook. type HookEvent struct { PushOnly bool `json:"push_only"` } +// Webhook represents a web hook object. type Webhook struct { Id int64 RepoId int64 Url string `xorm:"TEXT"` - ContentType int + ContentType HookContentType Secret string `xorm:"TEXT"` Events string `xorm:"TEXT"` *HookEvent `xorm:"-"` @@ -37,6 +43,7 @@ type Webhook struct { IsActive bool } +// GetEvent handles conversion from Events to HookEvent. func (w *Webhook) GetEvent() { w.HookEvent = &HookEvent{} if err := json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil { @@ -44,12 +51,14 @@ func (w *Webhook) GetEvent() { } } -func (w *Webhook) SaveEvent() error { +// UpdateEvent handles conversion from HookEvent to Events. +func (w *Webhook) UpdateEvent() error { data, err := json.Marshal(w.HookEvent) w.Events = string(data) return err } +// HasPushEvent returns true if hook enbaled push event. func (w *Webhook) HasPushEvent() bool { if w.PushOnly { return true @@ -57,18 +66,12 @@ func (w *Webhook) HasPushEvent() bool { return false } -// CreateWebhook creates new webhook. +// CreateWebhook creates a new web hook. func CreateWebhook(w *Webhook) error { _, err := orm.Insert(w) return err } -// UpdateWebhook updates information of webhook. -func UpdateWebhook(w *Webhook) error { - _, err := orm.AllCols().Update(w) - return err -} - // GetWebhookById returns webhook by given ID. func GetWebhookById(hookId int64) (*Webhook, error) { w := &Webhook{Id: hookId} @@ -93,8 +96,114 @@ func GetWebhooksByRepoId(repoId int64) (ws []*Webhook, err error) { return ws, err } +// UpdateWebhook updates information of webhook. +func UpdateWebhook(w *Webhook) error { + _, err := orm.AllCols().Update(w) + return err +} + // DeleteWebhook deletes webhook of repository. func DeleteWebhook(hookId int64) error { _, err := orm.Delete(&Webhook{Id: hookId}) return err } + +// ___ ___ __ ___________ __ +// / | \ ____ ____ | | _\__ ___/____ _____| | __ +// / ~ \/ _ \ / _ \| |/ / | | \__ \ / ___/ |/ / +// \ Y ( <_> | <_> ) < | | / __ \_\___ \| < +// \___|_ / \____/ \____/|__|_ \ |____| (____ /____ >__|_ \ +// \/ \/ \/ \/ \/ + +type HookTaskType int + +const ( + WEBHOOK HookTaskType = iota + 1 + SERVICE +) + +type PayloadAuthor struct { + Name string `json:"name"` + Email string `json:"email"` +} + +type PayloadCommit struct { + Id string `json:"id"` + Message string `json:"message"` + Url string `json:"url"` + Author *PayloadAuthor `json:"author"` +} + +type PayloadRepo struct { + Id int64 `json:"id"` + Name string `json:"name"` + Url string `json:"url"` + Description string `json:"description"` + Website string `json:"website"` + Watchers int `json:"watchers"` + Owner *PayloadAuthor `json:"author"` + Private bool `json:"private"` +} + +// Payload represents a payload information of hook. +type Payload struct { + Secret string `json:"secret"` + Ref string `json:"ref"` + Commits []*PayloadCommit `json:"commits"` + Repo *PayloadRepo `json:"repository"` + Pusher *PayloadAuthor `json:"pusher"` +} + +// HookTask represents a hook task. +type HookTask struct { + Id int64 + Type HookTaskType + Url string + *Payload `xorm:"-"` + PayloadContent string `xorm:"TEXT"` + ContentType HookContentType + IsSsl bool + IsDeliveried bool +} + +// CreateHookTask creates a new hook task, +// it handles conversion from Payload to PayloadContent. +func CreateHookTask(t *HookTask) error { + data, err := json.Marshal(t.Payload) + if err != nil { + return err + } + t.PayloadContent = string(data) + _, err = orm.Insert(t) + return err +} + +// UpdateHookTask updates information of hook task. +func UpdateHookTask(t *HookTask) error { + _, err := orm.AllCols().Update(t) + return err +} + +// DeliverHooks checks and delivers undelivered hooks. +func DeliverHooks() { + timeout := time.Duration(setting.WebhookDeliverTimeout) * time.Second + orm.Where("is_deliveried=?", false).Iterate(new(HookTask), + func(idx int, bean interface{}) error { + t := bean.(*HookTask) + // Only support JSON now. + if _, err := httplib.Post(t.Url).SetTimeout(timeout, timeout). + Body([]byte(t.PayloadContent)).Response(); err != nil { + log.Error("webhook.DeliverHooks(Delivery): %v", err) + return nil + } + + t.IsDeliveried = true + if err := UpdateHookTask(t); err != nil { + log.Error("webhook.DeliverHooks(UpdateHookTask): %v", err) + return nil + } + + log.Trace("Hook delivered: %s", t.PayloadContent) + return nil + }) +} |