Refactored to use Model and Database folders

This commit is contained in:
Brad Rydzewski 2014-06-12 16:41:04 -07:00
parent 554276de05
commit 36b01512c0
32 changed files with 407 additions and 477 deletions

View file

@ -1,9 +1,7 @@
package notify
import (
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/shared/model"
)
// Context represents the context of an
@ -13,13 +11,13 @@ type Context struct {
Host string
// User that owns the repository
User *user.User
User *model.User
// Repository being built.
Repo *repo.Repo
Repo *model.Repo
// Commit being built
Commit *commit.Commit
Commit *model.Commit
}
type Sender interface {

View file

@ -1,20 +1,19 @@
package notify
import (
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/shared/model"
"testing"
)
func Test_getBuildUrl(t *testing.T) {
c := &Context{
Host: "http://examplehost.com",
Repo: &repo.Repo{
Repo: &model.Repo{
Host: "examplegit.com",
Owner: "owner",
Name: "repo",
},
Commit: &commit.Commit{
Commit: &model.Commit{
Sha: "abc",
Branch: "example",
},

View file

@ -5,9 +5,7 @@ import (
"encoding/json"
"net/http"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/shared/model"
)
type Webhook struct {
@ -31,9 +29,9 @@ func (w *Webhook) Send(context *Context) error {
func (w *Webhook) send(context *Context) error {
// data will get posted in this format
data := struct {
Owner *user.User `json:"owner"`
Repo *repo.Repo `json:"repository"`
Commit *commit.Commit `json:"commit"`
Owner *model.User `json:"owner"`
Repo *model.Repo `json:"repository"`
Commit *model.Commit `json:"commit"`
}{context.User, context.Repo, context.Commit}
// data json encoded

View file

@ -1,48 +1,49 @@
package commit
package database
import (
"database/sql"
"time"
"github.com/drone/drone/shared/model"
"github.com/russross/meddler"
)
type CommitManager interface {
// Find finds the commit by ID.
Find(id int64) (*Commit, error)
Find(id int64) (*model.Commit, error)
// FindSha finds the commit for the branch and sha.
FindSha(repo int64, branch, sha string) (*Commit, error)
FindSha(repo int64, branch, sha string) (*model.Commit, error)
// FindLatest finds the most recent commit for the branch.
FindLatest(repo int64, branch string) (*Commit, error)
FindLatest(repo int64, branch string) (*model.Commit, error)
// FindOutput finds the commit's output.
FindOutput(commit int64) ([]byte, error)
// List finds recent commits for the repository
List(repo int64) ([]*Commit, error)
List(repo int64) ([]*model.Commit, error)
// ListBranch finds recent commits for the repository and branch.
ListBranch(repo int64, branch string) ([]*Commit, error)
ListBranch(repo int64, branch string) ([]*model.Commit, error)
// ListBranches finds most recent commit for each branch.
ListBranches(repo int64) ([]*Commit, error)
ListBranches(repo int64) ([]*model.Commit, error)
// ListUser finds most recent commits for a user.
ListUser(repo int64) ([]*CommitRepo, error)
ListUser(repo int64) ([]*model.CommitRepo, error)
// Insert persists the commit to the datastore.
Insert(commit *Commit) error
Insert(commit *model.Commit) error
// Update persists changes to the commit to the datastore.
Update(commit *Commit) error
Update(commit *model.Commit) error
// UpdateOutput persists a commit's stdout to the datastore.
UpdateOutput(commit *Commit, out []byte) error
UpdateOutput(commit *model.Commit, out []byte) error
// Delete removes the commit from the datastore.
Delete(commit *Commit) error
Delete(commit *model.Commit) error
// CancelAll will update the status of all Started or Pending
// builds to a status of Killed (cancelled).
@ -54,9 +55,9 @@ type commitManager struct {
*sql.DB
}
// NewManager initiales a new CommitManager intended to
// NewCommitManager initiales a new CommitManager intended to
// manage and persist commits.
func NewManager(db *sql.DB) CommitManager {
func NewCommitManager(db *sql.DB) CommitManager {
return &commitManager{db}
}
@ -84,7 +85,7 @@ LIMIT 20
`
// SQL query to retrieve the latest Commits for a user's repositories.
const listUserQuery = `
const listUserCommitsQuery = `
SELECT r.repo_remote, r.repo_host, r.repo_owner, r.repo_name, c.*
FROM commits c, repos r, perms p
WHERE c.repo_id=r.repo_id
@ -96,7 +97,7 @@ LIMIT 20
`
// SQL query to retrieve the latest Commits across all branches.
const listQuery = `
const listCommitsQuery = `
SELECT *
FROM commits
WHERE repo_id=?
@ -105,7 +106,7 @@ LIMIT 20
`
// SQL query to retrieve a Commit by branch and sha.
const findQuery = `
const findCommitQuery = `
SELECT *
FROM commits
WHERE repo_id=?
@ -115,7 +116,7 @@ LIMIT 1
`
// SQL query to retrieve the most recent Commit for a branch.
const findLatestQuery = `
const findLatestCommitQuery = `
SELECT *
FROM commits
WHERE commit_id IN (
@ -143,12 +144,12 @@ UPDATE output SET output_raw = ? WHERE commit_id = ?;
`
// SQL statement to delete a Commit by ID.
const deleteStmt = `
const deleteCommitStmt = `
DELETE FROM commits WHERE commit_id = ?;
`
// SQL statement to cancel all running Commits.
const cancelStmt = `
const cancelCommitStmt = `
UPDATE commits SET
commit_status = ?,
commit_started = ?,
@ -156,21 +157,21 @@ commit_finished = ?
WHERE commit_status IN ('Started', 'Pending');
`
func (db *commitManager) Find(id int64) (*Commit, error) {
dst := Commit{}
func (db *commitManager) Find(id int64) (*model.Commit, error) {
dst := model.Commit{}
err := meddler.Load(db, "commits", &dst, id)
return &dst, err
}
func (db *commitManager) FindSha(repo int64, branch, sha string) (*Commit, error) {
dst := Commit{}
err := meddler.QueryRow(db, &dst, findQuery, repo, branch, sha)
func (db *commitManager) FindSha(repo int64, branch, sha string) (*model.Commit, error) {
dst := model.Commit{}
err := meddler.QueryRow(db, &dst, findCommitQuery, repo, branch, sha)
return &dst, err
}
func (db *commitManager) FindLatest(repo int64, branch string) (*Commit, error) {
dst := Commit{}
err := meddler.QueryRow(db, &dst, findLatestQuery, repo, branch)
func (db *commitManager) FindLatest(repo int64, branch string) (*model.Commit, error) {
dst := model.Commit{}
err := meddler.QueryRow(db, &dst, findLatestCommitQuery, repo, branch)
return &dst, err
}
@ -180,42 +181,42 @@ func (db *commitManager) FindOutput(commit int64) ([]byte, error) {
return []byte(dst), err
}
func (db *commitManager) List(repo int64) ([]*Commit, error) {
var dst []*Commit
err := meddler.QueryAll(db, &dst, listQuery, repo)
func (db *commitManager) List(repo int64) ([]*model.Commit, error) {
var dst []*model.Commit
err := meddler.QueryAll(db, &dst, listCommitsQuery, repo)
return dst, err
}
func (db *commitManager) ListBranch(repo int64, branch string) ([]*Commit, error) {
var dst []*Commit
func (db *commitManager) ListBranch(repo int64, branch string) ([]*model.Commit, error) {
var dst []*model.Commit
err := meddler.QueryAll(db, &dst, listBranchQuery, repo, branch)
return dst, err
}
func (db *commitManager) ListBranches(repo int64) ([]*Commit, error) {
var dst []*Commit
func (db *commitManager) ListBranches(repo int64) ([]*model.Commit, error) {
var dst []*model.Commit
err := meddler.QueryAll(db, &dst, listBranchesQuery, repo)
return dst, err
}
func (db *commitManager) ListUser(user int64) ([]*CommitRepo, error) {
var dst []*CommitRepo
err := meddler.QueryAll(db, &dst, listUserQuery, user)
func (db *commitManager) ListUser(user int64) ([]*model.CommitRepo, error) {
var dst []*model.CommitRepo
err := meddler.QueryAll(db, &dst, listUserCommitsQuery, user)
return dst, err
}
func (db *commitManager) Insert(commit *Commit) error {
func (db *commitManager) Insert(commit *model.Commit) error {
commit.Created = time.Now().Unix()
commit.Updated = time.Now().Unix()
return meddler.Insert(db, "commits", commit)
}
func (db *commitManager) Update(commit *Commit) error {
func (db *commitManager) Update(commit *model.Commit) error {
commit.Updated = time.Now().Unix()
return meddler.Update(db, "commits", commit)
}
func (db *commitManager) UpdateOutput(commit *Commit, out []byte) error {
func (db *commitManager) UpdateOutput(commit *model.Commit, out []byte) error {
_, err := db.Exec(insertOutputStmt, commit.ID, out)
if err != nil {
return nil
@ -224,12 +225,12 @@ func (db *commitManager) UpdateOutput(commit *Commit, out []byte) error {
return err
}
func (db *commitManager) Delete(commit *Commit) error {
_, err := db.Exec(deleteStmt, commit.ID)
func (db *commitManager) Delete(commit *model.Commit) error {
_, err := db.Exec(deleteCommitStmt, commit.ID)
return err
}
func (db *commitManager) CancelAll() error {
_, err := db.Exec(cancelStmt, StatusKilled, time.Now().Unix(), time.Now().Unix())
_, err := db.Exec(cancelCommitStmt, model.StatusKilled, time.Now().Unix(), time.Now().Unix())
return err
}

View file

@ -1,35 +1,18 @@
package commit
package database
import (
"database/sql"
"testing"
"time"
"github.com/drone/drone/server/database/schema"
"github.com/drone/drone/server/database/testdata"
"github.com/drone/drone/server/database/testdatabase"
"github.com/drone/drone/shared/model"
)
// in-memory database instance for unit testing
var db *sql.DB
// setup the test database and test fixtures
func setup() {
db, _ = testdatabase.Open()
schema.Load(db)
testdata.Load(db)
}
// teardown the test database
func teardown() {
db.Close()
}
func TestFind(t *testing.T) {
func TestCommitFind(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
commit, err := commits.Find(3)
if err != nil {
t.Errorf("Want Commit from ID, got %s", err)
@ -38,11 +21,11 @@ func TestFind(t *testing.T) {
testCommit(t, commit)
}
func TestFindSha(t *testing.T) {
func TestCommitFindSha(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
commit, err := commits.FindSha(2, "master", "7253f6545caed41fb8f5a6fcdb3abc0b81fa9dbf")
if err != nil {
t.Errorf("Want Commit from SHA, got %s", err)
@ -51,11 +34,11 @@ func TestFindSha(t *testing.T) {
testCommit(t, commit)
}
func TestFindLatest(t *testing.T) {
func TestCommitFindLatest(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
commit, err := commits.FindLatest(2, "master")
if err != nil {
t.Errorf("Want Latest Commit, got %s", err)
@ -64,11 +47,11 @@ func TestFindLatest(t *testing.T) {
testCommit(t, commit)
}
func TestFindOutput(t *testing.T) {
func TestCommitFindOutput(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
out, err := commits.FindOutput(1)
if err != nil {
t.Errorf("Want Commit stdout, got %s", err)
@ -80,11 +63,11 @@ func TestFindOutput(t *testing.T) {
}
}
func TestList(t *testing.T) {
func TestCommitList(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
list, err := commits.List(2)
if err != nil {
t.Errorf("Want List from RepoID, got %s", err)
@ -98,11 +81,11 @@ func TestList(t *testing.T) {
testCommit(t, list[0])
}
func TestListBranch(t *testing.T) {
func TestCommitListBranch(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
list, err := commits.ListBranch(2, "master")
if err != nil {
t.Errorf("Want List from RepoID, got %s", err)
@ -116,11 +99,11 @@ func TestListBranch(t *testing.T) {
testCommit(t, list[0])
}
func TestListBranches(t *testing.T) {
func TestCommitListBranches(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
list, err := commits.ListBranches(2)
if err != nil {
t.Errorf("Want Branch List from RepoID, got %s", err)
@ -134,35 +117,35 @@ func TestListBranches(t *testing.T) {
testCommit(t, list[1])
}
func TestInsert(t *testing.T) {
func TestCommitInsert(t *testing.T) {
setup()
defer teardown()
commit := Commit{RepoID: 3, Branch: "foo", Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac"}
commits := NewManager(db)
commit := model.Commit{RepoID: 3, Branch: "foo", Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac"}
commits := NewCommitManager(db)
if err := commits.Insert(&commit); err != nil {
t.Errorf("Want Commit created, got %s", err)
}
// verify that it is ok to add same sha for different branch
var err = commits.Insert(&Commit{RepoID: 3, Branch: "bar", Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac"})
var err = commits.Insert(&model.Commit{RepoID: 3, Branch: "bar", Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac"})
if err != nil {
t.Errorf("Want Commit created, got %s", err)
}
// verify unique remote + remote id constraint
err = commits.Insert(&Commit{RepoID: 3, Branch: "bar", Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac"})
err = commits.Insert(&model.Commit{RepoID: 3, Branch: "bar", Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac"})
if err == nil {
t.Error("Want unique constraint violated")
}
}
func TestUpdate(t *testing.T) {
func TestCommitUpdate(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
commit, err := commits.Find(5)
if err != nil {
t.Errorf("Want Commit from ID, got %s", err)
@ -198,11 +181,11 @@ func TestUpdate(t *testing.T) {
}
}
func TestDelete(t *testing.T) {
func TestCommitDelete(t *testing.T) {
setup()
defer teardown()
commits := NewManager(db)
commits := NewCommitManager(db)
commit, err := commits.Find(1)
if err != nil {
t.Errorf("Want Commit from ID, got %s", err)
@ -221,7 +204,7 @@ func TestDelete(t *testing.T) {
// testCommit is a helper function that compares the commit
// to an expected set of fixed field values.
func testCommit(t *testing.T, commit *Commit) {
func testCommit(t *testing.T, commit *model.Commit) {
var got, want = commit.Status, "Success"
if got != want {
t.Errorf("Want Status %v, got %v", want, got)

View file

@ -1,33 +1,32 @@
package perm
package database
import (
"database/sql"
"time"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/shared/model"
"github.com/russross/meddler"
)
type PermManager interface {
// Grant will grant the user read, write and admin persmissions
// to the specified repository.
Grant(u *user.User, r *repo.Repo, read, write, admin bool) error
Grant(u *model.User, r *model.Repo, read, write, admin bool) error
// Revoke will revoke all user permissions to the specified repository.
Revoke(u *user.User, r *repo.Repo) error
Revoke(u *model.User, r *model.Repo) error
// Read returns true if the specified user has read
// access to the repository.
Read(u *user.User, r *repo.Repo) (bool, error)
Read(u *model.User, r *model.Repo) (bool, error)
// Write returns true if the specified user has write
// access to the repository.
Write(u *user.User, r *repo.Repo) (bool, error)
Write(u *model.User, r *model.Repo) (bool, error)
// Admin returns true if the specified user is an
// administrator of the repository.
Admin(u *user.User, r *repo.Repo) (bool, error)
Admin(u *model.User, r *model.Repo) (bool, error)
}
// permManager manages user permissions to access repositories.
@ -37,7 +36,7 @@ type permManager struct {
// SQL query to retrieve a user's permission to
// access a repository.
const findQuery = `
const findPermQuery = `
SELECT *
FROM perms
WHERE user_id=?
@ -46,19 +45,30 @@ LIMIT 1
`
// SQL statement to delete a permission.
const deleteStmt = `
const deletePermStmt = `
DELETE FROM perms WHERE user_id=? AND repo_id=?
`
type perm struct {
ID int64 `meddler:"perm_id,pk"`
UserID int64 `meddler:"user_id"`
RepoID int64 `meddler:"repo_id"`
Read bool `meddler:"perm_read"`
Write bool `meddler:"perm_write"`
Admin bool `meddler:"perm_admin"`
Created int64 `meddler:"perm_created"`
Updated int64 `meddler:"perm_updated"`
}
// NewManager initiales a new PermManager intended to
// manage user permission and access control.
func NewManager(db *sql.DB) PermManager {
func NewPermManager(db *sql.DB) PermManager {
return &permManager{db}
}
// Grant will grant the user read, write and admin persmissions
// to the specified repository.
func (db *permManager) Grant(u *user.User, r *repo.Repo, read, write, admin bool) error {
func (db *permManager) Grant(u *model.User, r *model.Repo, read, write, admin bool) error {
// attempt to get existing permissions from the database
perm, err := db.find(u, r)
if err != nil && err != sql.ErrNoRows {
@ -84,12 +94,12 @@ func (db *permManager) Grant(u *user.User, r *repo.Repo, read, write, admin bool
}
// Revoke will revoke all user permissions to the specified repository.
func (db *permManager) Revoke(u *user.User, r *repo.Repo) error {
_, err := db.Exec(deleteStmt, u.ID, r.ID)
func (db *permManager) Revoke(u *model.User, r *model.Repo) error {
_, err := db.Exec(deletePermStmt, u.ID, r.ID)
return err
}
func (db *permManager) Read(u *user.User, r *repo.Repo) (bool, error) {
func (db *permManager) Read(u *model.User, r *model.Repo) (bool, error) {
switch {
// if the repo is public, grant access.
case r.Private == false:
@ -107,7 +117,7 @@ func (db *permManager) Read(u *user.User, r *repo.Repo) (bool, error) {
return perm.Read, err
}
func (db *permManager) Write(u *user.User, r *repo.Repo) (bool, error) {
func (db *permManager) Write(u *model.User, r *model.Repo) (bool, error) {
switch {
// if the user is nil, deny access
case u == nil:
@ -122,7 +132,7 @@ func (db *permManager) Write(u *user.User, r *repo.Repo) (bool, error) {
return perm.Write, err
}
func (db *permManager) Admin(u *user.User, r *repo.Repo) (bool, error) {
func (db *permManager) Admin(u *model.User, r *model.Repo) (bool, error) {
switch {
// if the user is nil, deny access
case u == nil:
@ -137,8 +147,8 @@ func (db *permManager) Admin(u *user.User, r *repo.Repo) (bool, error) {
return perm.Admin, err
}
func (db *permManager) find(u *user.User, r *repo.Repo) (*perm, error) {
func (db *permManager) find(u *model.User, r *model.Repo) (*perm, error) {
var dst = perm{}
var err = meddler.QueryRow(db, &dst, findQuery, u.ID, r.ID)
var err = meddler.QueryRow(db, &dst, findPermQuery, u.ID, r.ID)
return &dst, err
}

View file

@ -1,37 +1,18 @@
package perm
package database
import (
"database/sql"
"testing"
"github.com/drone/drone/server/database/schema"
"github.com/drone/drone/server/database/testdata"
"github.com/drone/drone/server/database/testdatabase"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/shared/model"
)
// in-memory database instance for unit testing
var db *sql.DB
// setup the test database and test fixtures
func setup() {
db, _ = testdatabase.Open()
schema.Load(db)
testdata.Load(db)
}
// teardown the test database
func teardown() {
db.Close()
}
func Test_find(t *testing.T) {
setup()
defer teardown()
manager := NewManager(db).(*permManager)
perm, err := manager.find(&user.User{ID: 101}, &repo.Repo{ID: 200})
manager := NewPermManager(db).(*permManager)
perm, err := manager.find(&model.User{ID: 101}, &model.Repo{ID: 200})
if err != nil {
t.Errorf("Want permission, got %s", err)
}
@ -78,20 +59,20 @@ func Test_find(t *testing.T) {
// test that we get the appropriate error message when
// no permissions are found in the database.
_, err = manager.find(&user.User{ID: 102}, &repo.Repo{ID: 201})
_, err = manager.find(&model.User{ID: 102}, &model.Repo{ID: 201})
if err != sql.ErrNoRows {
t.Errorf("Want ErrNoRows, got %s", err)
}
}
func TestRead(t *testing.T) {
func TestPermRead(t *testing.T) {
setup()
defer teardown()
var manager = NewManager(db)
var manager = NewPermManager(db)
// dummy admin and repo
u := user.User{ID: 101, Admin: false}
r := repo.Repo{ID: 201, Private: false}
u := model.User{ID: 101, Admin: false}
r := model.Repo{ID: 201, Private: false}
// public repos should always be accessible
if read, err := manager.Read(&u, &r); !read || err != nil {
@ -131,14 +112,14 @@ func TestRead(t *testing.T) {
}
}
func TestWrite(t *testing.T) {
func TestPermWrite(t *testing.T) {
setup()
defer teardown()
var manager = NewManager(db)
var manager = NewPermManager(db)
// dummy admin and repo
u := user.User{ID: 101, Admin: false}
r := repo.Repo{ID: 201, Private: false}
u := model.User{ID: 101, Admin: false}
r := model.Repo{ID: 201, Private: false}
// repos should not be accessible to nil users
r.Private = true
@ -172,14 +153,14 @@ func TestWrite(t *testing.T) {
}
}
func TestAdmin(t *testing.T) {
func TestPermAdmin(t *testing.T) {
setup()
defer teardown()
var manager = NewManager(db)
var manager = NewPermManager(db)
// dummy admin and repo
u := user.User{ID: 101, Admin: false}
r := repo.Repo{ID: 201, Private: false}
u := model.User{ID: 101, Admin: false}
r := model.Repo{ID: 201, Private: false}
// repos should not be accessible to nil users
r.Private = true
@ -213,15 +194,15 @@ func TestAdmin(t *testing.T) {
}
}
func TestRevoke(t *testing.T) {
func TestPermRevoke(t *testing.T) {
setup()
defer teardown()
// dummy admin and repo
u := user.User{ID: 101}
r := repo.Repo{ID: 200}
u := model.User{ID: 101}
r := model.Repo{ID: 200}
manager := NewManager(db)
manager := NewPermManager(db)
admin, err := manager.Admin(&u, &r)
if !admin || err != nil {
t.Errorf("Want Admin permission, got Admin %v, error %s", admin, err)
@ -238,15 +219,15 @@ func TestRevoke(t *testing.T) {
}
}
func TestGrant(t *testing.T) {
func TestPermGrant(t *testing.T) {
setup()
defer teardown()
// dummy admin and repo
u := user.User{ID: 104}
r := repo.Repo{ID: 200}
u := model.User{ID: 104}
r := model.Repo{ID: 200}
manager := NewManager(db).(*permManager)
manager := NewPermManager(db).(*permManager)
if err := manager.Grant(&u, &r, true, true, true); err != nil {
t.Errorf("Want permissions granted, got %s", err)
}

View file

@ -1,36 +1,37 @@
package repo
package database
import (
"database/sql"
"time"
"github.com/drone/drone/shared/model"
"github.com/russross/meddler"
)
type RepoManager interface {
// Find retrieves the Repo by ID.
Find(id int64) (*Repo, error)
Find(id int64) (*model.Repo, error)
// FindName retrieves the Repo by the remote, owner and name.
FindName(remote, owner, name string) (*Repo, error)
FindName(remote, owner, name string) (*model.Repo, error)
// Insert persists a new Repo to the datastore.
Insert(repo *Repo) error
Insert(repo *model.Repo) error
// Insert persists a modified Repo to the datastore.
Update(repo *Repo) error
Update(repo *model.Repo) error
// Delete removes a Repo from the datastore.
Delete(repo *Repo) error
Delete(repo *model.Repo) error
// List retrieves all repositories from the datastore.
List(user int64) ([]*Repo, error)
List(user int64) ([]*model.Repo, error)
// List retrieves all public repositories from the datastore.
//ListPublic(user int64) ([]*Repo, error)
}
func NewManager(db *sql.DB) RepoManager {
func NewRepoManager(db *sql.DB) RepoManager {
return &repoManager{db}
}
@ -38,46 +39,39 @@ type repoManager struct {
*sql.DB
}
func (db *repoManager) Find(id int64) (*Repo, error) {
func (db *repoManager) Find(id int64) (*model.Repo, error) {
const query = "select * from repos where repo_id = ?"
var repo = Repo{}
var repo = model.Repo{}
var err = meddler.QueryRow(db, &repo, query, id)
return &repo, err
}
func (db *repoManager) FindName(remote, owner, name string) (*Repo, error) {
func (db *repoManager) FindName(remote, owner, name string) (*model.Repo, error) {
const query = "select * from repos where repo_host = ? and repo_owner = ? and repo_name = ?"
var repo = Repo{}
var repo = model.Repo{}
var err = meddler.QueryRow(db, &repo, query, remote, owner, name)
return &repo, err
}
func (db *repoManager) List(user int64) ([]*Repo, error) {
func (db *repoManager) List(user int64) ([]*model.Repo, error) {
const query = "select * from repos where repo_id IN (select repo_id from perms where user_id = ?)"
var repos []*Repo
var repos []*model.Repo
err := meddler.QueryAll(db, &repos, query, user)
return repos, err
}
//func (db *repoManager) ListPublic(user int64) ([]*Repo, error) {
// const query = "select * from repos where repo_id IN (select repo_id from perms where user_id = ?) AND repo_private=0"
// var repos []*Repo
// err := meddler.QueryAll(db, &repos, query, user)
// return repos, err
//}
func (db *repoManager) Insert(repo *Repo) error {
func (db *repoManager) Insert(repo *model.Repo) error {
repo.Created = time.Now().Unix()
repo.Updated = time.Now().Unix()
return meddler.Insert(db, "repos", repo)
}
func (db *repoManager) Update(repo *Repo) error {
func (db *repoManager) Update(repo *model.Repo) error {
repo.Updated = time.Now().Unix()
return meddler.Update(db, "repos", repo)
}
func (db *repoManager) Delete(repo *Repo) error {
func (db *repoManager) Delete(repo *model.Repo) error {
const stmt = "delete from repos where repo_id = ?"
_, err := db.Exec(stmt, repo.ID)
return err

View file

@ -1,34 +1,17 @@
package repo
package database
import (
"database/sql"
"testing"
"github.com/drone/drone/server/database/schema"
"github.com/drone/drone/server/database/testdata"
"github.com/drone/drone/server/database/testdatabase"
"github.com/drone/drone/shared/model"
)
// in-memory database instance for unit testing
var db *sql.DB
// setup the test database and test fixtures
func setup() {
db, _ = testdatabase.Open()
schema.Load(db)
testdata.Load(db)
}
// teardown the test database
func teardown() {
db.Close()
}
func TestFind(t *testing.T) {
func TestRepoFind(t *testing.T) {
setup()
defer teardown()
repos := NewManager(db)
repos := NewRepoManager(db)
repo, err := repos.Find(1)
if err != nil {
t.Errorf("Want Repo from ID, got %s", err)
@ -37,11 +20,11 @@ func TestFind(t *testing.T) {
testRepo(t, repo)
}
func TestName(t *testing.T) {
func TestRepoFindName(t *testing.T) {
setup()
defer teardown()
repos := NewManager(db)
repos := NewRepoManager(db)
user, err := repos.FindName("github.com", "lhofstadter", "lenwoloppali")
if err != nil {
t.Errorf("Want Repo by Name, got %s", err)
@ -50,11 +33,11 @@ func TestName(t *testing.T) {
testRepo(t, user)
}
func TestList(t *testing.T) {
func TestRepoList(t *testing.T) {
setup()
defer teardown()
repos := NewManager(db)
repos := NewRepoManager(db)
all, err := repos.List(1)
if err != nil {
t.Errorf("Want Repos, got %s", err)
@ -68,28 +51,28 @@ func TestList(t *testing.T) {
testRepo(t, all[0])
}
func TestInsert(t *testing.T) {
func TestRepoInsert(t *testing.T) {
setup()
defer teardown()
repo, _ := New("github.com", "mrwolowitz", "lenwoloppali")
repos := NewManager(db)
repo, _ := model.NewRepo("github.com", "mrwolowitz", "lenwoloppali")
repos := NewRepoManager(db)
if err := repos.Insert(repo); err != nil {
t.Errorf("Want Repo created, got %s", err)
}
// verify unique remote + owner + name login constraint
var err = repos.Insert(&Repo{Host: repo.Host, Owner: repo.Owner, Name: repo.Name})
var err = repos.Insert(&model.Repo{Host: repo.Host, Owner: repo.Owner, Name: repo.Name})
if err == nil {
t.Error("Want unique constraint violated")
}
}
func TestUpdate(t *testing.T) {
func TestRepoUpdate(t *testing.T) {
setup()
defer teardown()
repos := NewManager(db)
repos := NewRepoManager(db)
repo, err := repos.Find(1)
if err != nil {
t.Errorf("Want Repo from ID, got %s", err)
@ -132,11 +115,11 @@ func TestUpdate(t *testing.T) {
}
}
func TestDelete(t *testing.T) {
func TestRepoDelete(t *testing.T) {
setup()
defer teardown()
repos := NewManager(db)
repos := NewRepoManager(db)
repo, err := repos.Find(1)
if err != nil {
t.Errorf("Want Repo from ID, got %s", err)
@ -155,7 +138,7 @@ func TestDelete(t *testing.T) {
// testRepo is a helper function that compares the repo
// to an expected set of fixed field values.
func testRepo(t *testing.T, repo *Repo) {
func testRepo(t *testing.T, repo *model.Repo) {
var got, want = repo.Remote, "github.com"
if got != want {
t.Errorf("Want Remote %v, got %v", want, got)

View file

@ -1,33 +1,34 @@
package user
package database
import (
"database/sql"
"time"
"github.com/drone/drone/shared/model"
"github.com/russross/meddler"
)
type UserManager interface {
// Find finds the User by ID.
Find(id int64) (*User, error)
Find(id int64) (*model.User, error)
// FindLogin finds the User by remote login.
FindLogin(remote, login string) (*User, error)
FindLogin(remote, login string) (*model.User, error)
// FindToken finds the User by token.
FindToken(token string) (*User, error)
FindToken(token string) (*model.User, error)
// List finds all registered users of the system.
List() ([]*User, error)
List() ([]*model.User, error)
// Insert persists the User to the datastore.
Insert(user *User) error
Insert(user *model.User) error
// Update persists changes to the User to the datastore.
Update(user *User) error
Update(user *model.User) error
// Delete removes the User from the datastore.
Delete(user *User) error
Delete(user *model.User) error
}
// userManager manages a list of users in a SQL database.
@ -36,7 +37,7 @@ type userManager struct {
}
// SQL query to retrieve a User by remote login.
const findLoginQuery = `
const findUserLoginQuery = `
SELECT *
FROM users
WHERE user_remote=?
@ -45,7 +46,7 @@ LIMIT 1
`
// SQL query to retrieve a User by remote login.
const findTokenQuery = `
const findUserTokenQuery = `
SELECT *
FROM users
WHERE user_token=?
@ -53,59 +54,59 @@ LIMIT 1
`
// SQL query to retrieve a list of all users.
const listQuery = `
const listUserQuery = `
SELECT *
FROM users
ORDER BY user_name ASC
`
// SQL statement to delete a User by ID.
const deleteStmt = `
const deleteUserStmt = `
DELETE FROM users WHERE user_id=?
`
// NewManager initiales a new UserManager intended to
// NewUserManager initiales a new UserManager intended to
// manage and persist commits.
func NewManager(db *sql.DB) UserManager {
func NewUserManager(db *sql.DB) UserManager {
return &userManager{db}
}
func (db *userManager) Find(id int64) (*User, error) {
dst := User{}
func (db *userManager) Find(id int64) (*model.User, error) {
dst := model.User{}
err := meddler.Load(db, "users", &dst, id)
return &dst, err
}
func (db *userManager) FindLogin(remote, login string) (*User, error) {
dst := User{}
err := meddler.QueryRow(db, &dst, findLoginQuery, remote, login)
func (db *userManager) FindLogin(remote, login string) (*model.User, error) {
dst := model.User{}
err := meddler.QueryRow(db, &dst, findUserLoginQuery, remote, login)
return &dst, err
}
func (db *userManager) FindToken(token string) (*User, error) {
dst := User{}
err := meddler.QueryRow(db, &dst, findTokenQuery, token)
func (db *userManager) FindToken(token string) (*model.User, error) {
dst := model.User{}
err := meddler.QueryRow(db, &dst, findUserTokenQuery, token)
return &dst, err
}
func (db *userManager) List() ([]*User, error) {
var dst []*User
err := meddler.QueryAll(db, &dst, listQuery)
func (db *userManager) List() ([]*model.User, error) {
var dst []*model.User
err := meddler.QueryAll(db, &dst, listUserQuery)
return dst, err
}
func (db *userManager) Insert(user *User) error {
func (db *userManager) Insert(user *model.User) error {
user.Created = time.Now().Unix()
user.Updated = time.Now().Unix()
return meddler.Insert(db, "users", user)
}
func (db *userManager) Update(user *User) error {
func (db *userManager) Update(user *model.User) error {
user.Updated = time.Now().Unix()
return meddler.Update(db, "users", user)
}
func (db *userManager) Delete(user *User) error {
_, err := db.Exec(deleteStmt, user.ID)
func (db *userManager) Delete(user *model.User) error {
_, err := db.Exec(deleteUserStmt, user.ID)
return err
}

View file

@ -1,4 +1,4 @@
package user
package database
import (
"database/sql"
@ -7,6 +7,7 @@ import (
"github.com/drone/drone/server/database/schema"
"github.com/drone/drone/server/database/testdata"
"github.com/drone/drone/server/database/testdatabase"
"github.com/drone/drone/shared/model"
)
// in-memory database instance for unit testing
@ -24,11 +25,11 @@ func teardown() {
db.Close()
}
func TestFind(t *testing.T) {
func TestUserFind(t *testing.T) {
setup()
defer teardown()
users := NewManager(db)
users := NewUserManager(db)
user, err := users.Find(1)
if err != nil {
t.Errorf("Want User from ID, got %s", err)
@ -37,11 +38,11 @@ func TestFind(t *testing.T) {
testUser(t, user)
}
func TestFindLogin(t *testing.T) {
func TestUserFindLogin(t *testing.T) {
setup()
defer teardown()
users := NewManager(db)
users := NewUserManager(db)
user, err := users.FindLogin("github.com", "smellypooper")
if err != nil {
t.Errorf("Want User from Login, got %s", err)
@ -50,11 +51,11 @@ func TestFindLogin(t *testing.T) {
testUser(t, user)
}
func TestFindToken(t *testing.T) {
func TestUserFindToken(t *testing.T) {
setup()
defer teardown()
users := NewManager(db)
users := NewUserManager(db)
user, err := users.FindToken("e42080dddf012c718e476da161d21ad5")
if err != nil {
t.Errorf("Want User from Token, got %s", err)
@ -63,11 +64,11 @@ func TestFindToken(t *testing.T) {
testUser(t, user)
}
func TestList(t *testing.T) {
func TestUserList(t *testing.T) {
setup()
defer teardown()
users := NewManager(db)
users := NewUserManager(db)
all, err := users.List()
if err != nil {
t.Errorf("Want Users, got %s", err)
@ -81,12 +82,12 @@ func TestList(t *testing.T) {
testUser(t, all[0])
}
func TestInsert(t *testing.T) {
func TestUserInsert(t *testing.T) {
setup()
defer teardown()
user := New("github.com", "winkle", "winkle@caltech.edu")
users := NewManager(db)
user := model.NewUser("github.com", "winkle", "winkle@caltech.edu")
users := NewUserManager(db)
if err := users.Insert(user); err != nil {
t.Errorf("Want User created, got %s", err)
}
@ -97,23 +98,23 @@ func TestInsert(t *testing.T) {
}
// verify unique remote + remote login constraint
var err = users.Insert(&User{Remote: user.Remote, Login: user.Login, Token: "f71eb4a81a2cca56035dd7f6f2942e41"})
var err = users.Insert(&model.User{Remote: user.Remote, Login: user.Login, Token: "f71eb4a81a2cca56035dd7f6f2942e41"})
if err == nil {
t.Error("Want Token unique constraint violated")
}
// verify unique token constraint
err = users.Insert(&User{Remote: "gitlab.com", Login: user.Login, Token: user.Token})
err = users.Insert(&model.User{Remote: "gitlab.com", Login: user.Login, Token: user.Token})
if err == nil {
t.Error("Want Token unique constraint violated")
}
}
func TestUpdate(t *testing.T) {
func TestUserUpdate(t *testing.T) {
setup()
defer teardown()
users := NewManager(db)
users := NewUserManager(db)
user, err := users.Find(4)
if err != nil {
t.Errorf("Want User from ID, got %s", err)
@ -138,11 +139,11 @@ func TestUpdate(t *testing.T) {
}
}
func TestDelete(t *testing.T) {
func TestUserDelete(t *testing.T) {
setup()
defer teardown()
users := NewManager(db)
users := NewUserManager(db)
user, err := users.Find(1)
if err != nil {
t.Errorf("Want User from ID, got %s", err)
@ -161,7 +162,7 @@ func TestDelete(t *testing.T) {
// testUser is a helper function that compares the user
// to an expected set of fixed field values.
func testUser(t *testing.T, user *User) {
func testUser(t *testing.T, user *model.User) {
var got, want = user.Login, "smellypooper"
if got != want {
t.Errorf("Want Token %v, got %v", want, got)

View file

@ -4,8 +4,8 @@ import (
"net/http"
"time"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/database"
"github.com/drone/drone/shared/model"
"github.com/gorilla/pat"
)
@ -20,11 +20,11 @@ var (
)
type BadgeHandler struct {
commits commit.CommitManager
repos repo.RepoManager
commits database.CommitManager
repos database.RepoManager
}
func NewBadgeHandler(repos repo.RepoManager, commits commit.CommitManager) *BadgeHandler {
func NewBadgeHandler(repos database.RepoManager, commits database.CommitManager) *BadgeHandler {
return &BadgeHandler{commits, repos}
}
@ -54,7 +54,7 @@ func (h *BadgeHandler) GetStatus(w http.ResponseWriter, r *http.Request) error {
// if no branch, use the default
if len(branch) == 0 {
branch = repo.DefaultBranch
branch = model.DefaultBranch
}
// get the latest commit
@ -69,13 +69,13 @@ func (h *BadgeHandler) GetStatus(w http.ResponseWriter, r *http.Request) error {
// determine which badge to load
switch c.Status {
case commit.StatusSuccess:
case model.StatusSuccess:
w.Write(badgeSuccess)
case commit.StatusFailure:
case model.StatusFailure:
w.Write(badgeFailure)
case commit.StatusError:
case model.StatusError:
w.Write(badgeError)
case commit.StatusEnqueue, commit.StatusStarted:
case model.StatusEnqueue, model.StatusStarted:
w.Write(badgeStarted)
default:
w.Write(badgeNone)

View file

@ -4,21 +4,19 @@ import (
"encoding/json"
"net/http"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/perm"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/session"
"github.com/gorilla/pat"
)
type BranchHandler struct {
perms perm.PermManager
repos repo.RepoManager
commits commit.CommitManager
perms database.PermManager
repos database.RepoManager
commits database.CommitManager
sess session.Session
}
func NewBranchHandler(repos repo.RepoManager, commits commit.CommitManager, perms perm.PermManager, sess session.Session) *BranchHandler {
func NewBranchHandler(repos database.RepoManager, commits database.CommitManager, perms database.PermManager, sess session.Session) *BranchHandler {
return &BranchHandler{perms, repos, commits, sess}
}

View file

@ -4,23 +4,22 @@ import (
"encoding/json"
"net/http"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/queue"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/perm"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/session"
"github.com/drone/drone/shared/model"
"github.com/gorilla/pat"
)
type CommitHandler struct {
perms perm.PermManager
repos repo.RepoManager
commits commit.CommitManager
perms database.PermManager
repos database.RepoManager
commits database.CommitManager
sess session.Session
queue *queue.Queue
}
func NewCommitHandler(repos repo.RepoManager, commits commit.CommitManager, perms perm.PermManager, sess session.Session, queue *queue.Queue) *CommitHandler {
func NewCommitHandler(repos database.RepoManager, commits database.CommitManager, perms database.PermManager, sess session.Session, queue *queue.Queue) *CommitHandler {
return &CommitHandler{perms, repos, commits, sess, queue}
}
@ -146,11 +145,11 @@ func (h *CommitHandler) PostCommit(w http.ResponseWriter, r *http.Request) error
}
// we can't start an already started build
if c.Status == commit.StatusStarted || c.Status == commit.StatusEnqueue {
if c.Status == model.StatusStarted || c.Status == model.StatusEnqueue {
return badRequest{}
}
c.Status = commit.StatusEnqueue
c.Status = model.StatusEnqueue
c.Started = 0
c.Finished = 0
c.Duration = 0

View file

@ -3,23 +3,22 @@ package handler
import (
"net/http"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/queue"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/config"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/shared/model"
"github.com/gorilla/pat"
)
type HookHandler struct {
users user.UserManager
repos repo.RepoManager
commits commit.CommitManager
users database.UserManager
repos database.RepoManager
commits database.CommitManager
queue *queue.Queue
conf *config.Config
}
func NewHookHandler(users user.UserManager, repos repo.RepoManager, commits commit.CommitManager, conf *config.Config, queue *queue.Queue) *HookHandler {
func NewHookHandler(users database.UserManager, repos database.RepoManager, commits database.CommitManager, conf *config.Config, queue *queue.Queue) *HookHandler {
return &HookHandler{users, repos, commits, queue, conf}
}
@ -76,9 +75,9 @@ func (h *HookHandler) PostHook(w http.ResponseWriter, r *http.Request) error {
return badRequest{err}
}
c := commit.Commit{
c := model.Commit{
RepoID: repo.ID,
Status: commit.StatusEnqueue,
Status: model.StatusEnqueue,
Sha: hook.Sha,
Branch: hook.Branch,
PullRequest: hook.PullRequest,

View file

@ -5,23 +5,22 @@ import (
"net/http"
"time"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/resource/config"
"github.com/drone/drone/server/resource/perm"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/server/session"
"github.com/drone/drone/shared/model"
"github.com/gorilla/pat"
)
type LoginHandler struct {
users user.UserManager
repos repo.RepoManager
perms perm.PermManager
users database.UserManager
repos database.RepoManager
perms database.PermManager
sess session.Session
conf *config.Config
}
func NewLoginHandler(users user.UserManager, repos repo.RepoManager, perms perm.PermManager, sess session.Session, conf *config.Config) *LoginHandler {
func NewLoginHandler(users database.UserManager, repos database.RepoManager, perms database.PermManager, sess session.Session, conf *config.Config) *LoginHandler {
return &LoginHandler{users, repos, perms, sess, conf}
}
@ -56,7 +55,7 @@ func (h *LoginHandler) GetLogin(w http.ResponseWriter, r *http.Request) error {
}
// create the user account
u = user.New(remote.GetName(), login.Login, login.Email)
u = model.NewUser(remote.GetName(), login.Login, login.Email)
u.Name = login.Name
u.SetEmail(login.Email)
@ -86,7 +85,7 @@ func (h *LoginHandler) GetLogin(w http.ResponseWriter, r *http.Request) error {
// TODO this should move to a server/sync package and
// should be injected into this struct, just like
// the database code.
if u.Stale() {
if u.IsStale() {
log.Println("sync user account.", u.Login)
// sync inside a goroutine. This should eventually be moved to
@ -109,7 +108,7 @@ func (h *LoginHandler) GetLogin(w http.ResponseWriter, r *http.Request) error {
// insert all repositories
for _, remoteRepo := range repos {
repo, _ := repo.New(remote.GetName(), remoteRepo.Owner, remoteRepo.Name)
repo, _ := model.NewRepo(remote.GetName(), remoteRepo.Owner, remoteRepo.Name)
repo.Private = remoteRepo.Private
repo.Host = remoteRepo.Host
repo.CloneURL = remoteRepo.Clone

View file

@ -5,10 +5,8 @@ import (
"fmt"
"net/http"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/resource/config"
"github.com/drone/drone/server/resource/perm"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/session"
"github.com/drone/drone/shared/httputil"
"github.com/drone/drone/shared/sshutil"
@ -17,14 +15,14 @@ import (
type RepoHandler struct {
conf *config.Config
commits commit.CommitManager
perms perm.PermManager
repos repo.RepoManager
commits database.CommitManager
perms database.PermManager
repos database.RepoManager
sess session.Session
}
func NewRepoHandler(repos repo.RepoManager, commits commit.CommitManager,
perms perm.PermManager, sess session.Session, conf *config.Config) *RepoHandler {
func NewRepoHandler(repos database.RepoManager, commits database.CommitManager,
perms database.PermManager, sess session.Session, conf *config.Config) *RepoHandler {
return &RepoHandler{conf, commits, perms, repos, sess}
}

View file

@ -5,27 +5,25 @@ import (
"net/http"
"github.com/drone/drone/server/channel"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/perm"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/session"
"github.com/drone/drone/shared/httputil"
"github.com/drone/drone/shared/model"
"github.com/gorilla/pat"
)
type Renderer func(wr io.Writer, name string, data interface{}) error
type SiteHandler struct {
users user.UserManager
repos repo.RepoManager
commits commit.CommitManager
perms perm.PermManager
users database.UserManager
repos database.RepoManager
commits database.CommitManager
perms database.PermManager
sess session.Session
render Renderer
}
func NewSiteHandler(users user.UserManager, repos repo.RepoManager, commits commit.CommitManager, perms perm.PermManager, sess session.Session, render Renderer) *SiteHandler {
func NewSiteHandler(users database.UserManager, repos database.RepoManager, commits database.CommitManager, perms database.PermManager, sess session.Session, render Renderer) *SiteHandler {
return &SiteHandler{users, repos, commits, perms, sess, render}
}
@ -39,15 +37,15 @@ func (s *SiteHandler) GetIndex(w http.ResponseWriter, r *http.Request) error {
}
feed, _ := s.commits.ListUser(u.ID)
data := struct {
User *user.User
Feed []*commit.CommitRepo
User *model.User
Feed []*model.CommitRepo
}{u, feed}
return s.render(w, "user_feed.html", &data)
}
// GetLogin serves the account login page
func (s *SiteHandler) GetLogin(w http.ResponseWriter, r *http.Request) error {
return s.render(w, "login.html", struct{ User *user.User }{nil})
return s.render(w, "login.html", struct{ User *model.User }{nil})
}
// GetUser serves the account settings page.
@ -56,7 +54,7 @@ func (s *SiteHandler) GetUser(w http.ResponseWriter, r *http.Request) error {
if u == nil {
return s.render(w, "404.html", nil)
}
return s.render(w, "user_conf.html", struct{ User *user.User }{u})
return s.render(w, "user_conf.html", struct{ User *model.User }{u})
}
func (s *SiteHandler) GetUsers(w http.ResponseWriter, r *http.Request) error {
@ -64,7 +62,7 @@ func (s *SiteHandler) GetUsers(w http.ResponseWriter, r *http.Request) error {
if u == nil || u.Admin == false {
return s.render(w, "404.html", nil)
}
return s.render(w, "admin_users.html", struct{ User *user.User }{u})
return s.render(w, "admin_users.html", struct{ User *model.User }{u})
}
func (s *SiteHandler) GetConfig(w http.ResponseWriter, r *http.Request) error {
@ -72,7 +70,7 @@ func (s *SiteHandler) GetConfig(w http.ResponseWriter, r *http.Request) error {
if u == nil || u.Admin == false {
return s.render(w, "404.html", nil)
}
return s.render(w, "admin_conf.html", struct{ User *user.User }{u})
return s.render(w, "admin_conf.html", struct{ User *model.User }{u})
}
func (s *SiteHandler) GetRepo(w http.ResponseWriter, r *http.Request) error {
@ -89,14 +87,14 @@ func (s *SiteHandler) GetRepo(w http.ResponseWriter, r *http.Request) error {
return s.render(w, "404.html", nil)
}
data := struct {
User *user.User
Repo *repo.Repo
User *model.User
Repo *model.Repo
Branch string
Channel string
Stream string
Branches []*commit.Commit
Commits []*commit.Commit
Commit *commit.Commit
Branches []*model.Commit
Commits []*model.Commit
Commit *model.Commit
}{User: usr, Repo: arepo}
// generate a token for connecting to the streaming server
@ -148,8 +146,8 @@ func (s *SiteHandler) GetRepoAdmin(w http.ResponseWriter, r *http.Request) error
return s.render(w, "404.html", nil)
}
data := struct {
User *user.User
Repo *repo.Repo
User *model.User
Repo *model.Repo
Host string
Scheme string
}{u, arepo, httputil.GetHost(r), httputil.GetScheme(r)}
@ -167,8 +165,8 @@ func (s *SiteHandler) GetRepos(w http.ResponseWriter, r *http.Request) error {
s.render(w, "500.html", nil)
}
data := struct {
User *user.User
Repos []*repo.Repo
User *model.User
Repos []*model.Repo
}{u, repos}
return s.render(w, "user_repos.html", &data)
}

View file

@ -4,21 +4,20 @@ import (
"encoding/json"
"net/http"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/session"
"github.com/drone/drone/shared/model"
"github.com/gorilla/pat"
)
type UserHandler struct {
commits commit.CommitManager
repos repo.RepoManager
users user.UserManager
commits database.CommitManager
repos database.RepoManager
users database.UserManager
sess session.Session
}
func NewUserHandler(users user.UserManager, repos repo.RepoManager, commits commit.CommitManager, sess session.Session) *UserHandler {
func NewUserHandler(users database.UserManager, repos database.RepoManager, commits database.CommitManager, sess session.Session) *UserHandler {
return &UserHandler{commits, repos, users, sess}
}
@ -35,7 +34,7 @@ func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) error {
// requesting their own data, and will need to display
// the Token on the website.
data := struct {
*user.User
*model.User
Token string `json:"token"`
}{u, u.Token}
return json.NewEncoder(w).Encode(&data)
@ -52,7 +51,7 @@ func (h *UserHandler) PutUser(w http.ResponseWriter, r *http.Request) error {
// unmarshal the repository from the payload
defer r.Body.Close()
in := user.User{}
in := model.User{}
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
return badRequest{err}
}

View file

@ -4,17 +4,17 @@ import (
"encoding/json"
"net/http"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/session"
"github.com/gorilla/pat"
)
type UsersHandler struct {
users user.UserManager
users database.UserManager
sess session.Session
}
func NewUsersHandler(users user.UserManager, sess session.Session) *UsersHandler {
func NewUsersHandler(users database.UserManager, sess session.Session) *UsersHandler {
return &UsersHandler{users, sess}
}

View file

@ -10,14 +10,11 @@ import (
"code.google.com/p/go.net/websocket"
"github.com/drone/drone/server/channel"
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/database/schema"
"github.com/drone/drone/server/handler"
"github.com/drone/drone/server/queue"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/config"
"github.com/drone/drone/server/resource/perm"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/server/session"
"github.com/drone/drone/shared/build/docker"
"github.com/drone/drone/shared/build/log"
@ -95,10 +92,10 @@ func main() {
schema.Load(db)
// setup the database managers
repos := repo.NewManager(db)
users := user.NewManager(db)
perms := perm.NewManager(db)
commits := commit.NewManager(db)
repos := database.NewRepoManager(db)
users := database.NewUserManager(db)
perms := database.NewPermManager(db)
commits := database.NewCommitManager(db)
// cancel all previously running builds
go commits.CancelAll()

View file

@ -1,9 +1,8 @@
package queue
import (
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/repo"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/server/database"
"github.com/drone/drone/shared/model"
"github.com/drone/drone/shared/build/script"
)
@ -16,9 +15,9 @@ type Queue struct {
// BuildTasks represents a build that is pending
// execution.
type BuildTask struct {
User *user.User
Repo *repo.Repo
Commit *commit.Commit
User *model.User
Repo *model.Repo
Commit *model.Commit
// Build instructions from the .drone.yml
// file, unmarshalled.
@ -26,7 +25,7 @@ type BuildTask struct {
}
// Start N workers with the given build runner.
func Start(workers int, commits commit.CommitManager, runner BuildRunner) *Queue {
func Start(workers int, commits database.CommitManager, runner BuildRunner) *Queue {
tasks := make(chan *BuildTask)
queue := &Queue{tasks: tasks}

View file

@ -4,20 +4,19 @@ import (
"bytes"
"fmt"
"github.com/drone/drone/server/channel"
"github.com/drone/drone/server/database"
"github.com/drone/drone/shared/build/git"
r "github.com/drone/drone/shared/build/repo"
"github.com/drone/drone/shared/build/repo"
"github.com/drone/drone/shared/build/script"
"github.com/drone/drone/shared/model"
"io"
"log"
"path/filepath"
"time"
"github.com/drone/drone/server/resource/commit"
"github.com/drone/drone/server/resource/repo"
)
type worker struct {
commits commit.CommitManager
commits database.CommitManager
runner BuildRunner
}
@ -52,7 +51,7 @@ func (w *worker) execute(task *BuildTask) error {
if e := recover(); e != nil {
task.Commit.Finished = time.Now().Unix()
task.Commit.Duration = task.Commit.Finished - task.Commit.Started
task.Commit.Status = commit.StatusError
task.Commit.Status = model.StatusError
w.commits.Update(task.Commit)
}
}()
@ -66,7 +65,7 @@ func (w *worker) execute(task *BuildTask) error {
}
// update commit and build status
task.Commit.Status = commit.StatusStarted
task.Commit.Status = model.StatusStarted
task.Commit.Started = time.Now().Unix()
// persist the commit to the database
@ -132,14 +131,14 @@ func (w *worker) execute(task *BuildTask) error {
task.Commit.Finished = time.Now().Unix()
task.Commit.Duration = task.Commit.Finished - task.Commit.Started
task.Commit.Status = commit.StatusSuccess
task.Commit.Status = model.StatusSuccess
// capture build output
stdout := buf.buf.String()
// if exit code != 0 set to failure
if passed {
task.Commit.Status = commit.StatusFailure
task.Commit.Status = model.StatusFailure
if buildErr != nil && len(stdout) == 0 {
// TODO: If you wanted to have very friendly error messages, you could do that here
stdout = fmt.Sprintf("%s\n", buildErr.Error())
@ -173,7 +172,7 @@ func (w *worker) runBuild(task *BuildTask, buf io.Writer) (bool, error) {
var path = filepath.Join(task.Repo.Host, task.Repo.Owner, task.Repo.Name)
path = git.GitPath(task.Script.Git, path)
repo := &r.Repo{
repo := &repo.Repo{
Name: task.Repo.Host + task.Repo.Owner + task.Repo.Name,
Path: task.Repo.CloneURL,
Branch: task.Commit.Branch,
@ -200,7 +199,7 @@ func (w *worker) runBuild(task *BuildTask, buf io.Writer) (bool, error) {
// updateGitHubStatus is a helper function that will send
// the build status to GitHub using the Status API.
// see https://github.com/blog/1227-commit-status-api
func updateGitHubStatus(repo *repo.Repo, commit *commit.Commit) error {
func updateGitHubStatus(repo *repo.Repo, commit *model.Commit) error {
/*
// convert from drone status to github status
var message, status string

View file

@ -1,12 +0,0 @@
package perm
type perm struct {
ID int64 `meddler:"perm_id,pk"`
UserID int64 `meddler:"user_id"`
RepoID int64 `meddler:"repo_id"`
Read bool `meddler:"perm_read"`
Write bool `meddler:"perm_write"`
Admin bool `meddler:"perm_admin"`
Created int64 `meddler:"perm_created"`
Updated int64 `meddler:"perm_updated"`
}

View file

@ -1,22 +0,0 @@
package user
import (
"testing"
)
func TestSetEmail(t *testing.T) {
user := User{}
user.SetEmail("winkle@caltech.edu")
// make sure the email was correctly set
var got, want = user.Email, "winkle@caltech.edu"
if got != want {
t.Errorf("Want Email %s, got %s", want, got)
}
// make sure the gravatar hash was correctly calculated
got, want = user.Gravatar, "ab23a88a3ed77ecdfeb894c0eaf2817a"
if got != want {
t.Errorf("Want Gravatar %s, got %s", want, got)
}
}

View file

@ -3,7 +3,8 @@ package session
import (
"net/http"
"github.com/drone/drone/server/resource/user"
"github.com/drone/drone/server/database"
"github.com/drone/drone/shared/model"
"github.com/gorilla/securecookie"
"github.com/gorilla/sessions"
)
@ -13,25 +14,25 @@ var cookies = sessions.NewCookieStore(
securecookie.GenerateRandomKey(64))
type Session interface {
User(r *http.Request) *user.User
UserToken(r *http.Request) *user.User
UserCookie(r *http.Request) *user.User
SetUser(w http.ResponseWriter, r *http.Request, u *user.User)
User(r *http.Request) *model.User
UserToken(r *http.Request) *model.User
UserCookie(r *http.Request) *model.User
SetUser(w http.ResponseWriter, r *http.Request, u *model.User)
Clear(w http.ResponseWriter, r *http.Request)
}
type session struct {
users user.UserManager
users database.UserManager
}
func NewSession(users user.UserManager) Session {
func NewSession(users database.UserManager) Session {
return &session{
users: users,
}
}
// User gets the currently authenticated user from the secure cookie session.
func (s *session) User(r *http.Request) *user.User {
func (s *session) User(r *http.Request) *model.User {
//if true {
// user, _ := s.users.Find(1)
// return user
@ -47,14 +48,14 @@ func (s *session) User(r *http.Request) *user.User {
}
// UserToken gets the currently authenticated user for the given auth token.
func (s *session) UserToken(r *http.Request) *user.User {
func (s *session) UserToken(r *http.Request) *model.User {
token := r.FormValue("access_token")
user, _ := s.users.FindToken(token)
return user
}
// UserCookie gets the currently authenticated user from the secure cookie session.
func (s *session) UserCookie(r *http.Request) *user.User {
func (s *session) UserCookie(r *http.Request) *model.User {
sess, err := cookies.Get(r, "_sess")
if err != nil {
return nil
@ -70,7 +71,7 @@ func (s *session) UserCookie(r *http.Request) *user.User {
}
// SetUser writes the specified username to the session.
func (s *session) SetUser(w http.ResponseWriter, r *http.Request, u *user.User) {
func (s *session) SetUser(w http.ResponseWriter, r *http.Request, u *model.User) {
sess, _ := cookies.Get(r, "_sess")
sess.Values["uid"] = u.ID
sess.Save(r, w)

View file

@ -1,20 +1,9 @@
package commit
package model
import (
"github.com/drone/drone/server/resource/util"
"time"
)
const (
StatusNone = "None"
StatusEnqueue = "Pending"
StatusStarted = "Started"
StatusSuccess = "Success"
StatusFailure = "Failure"
StatusError = "Error"
StatusKilled = "Killed"
)
type Commit struct {
ID int64 `meddler:"commit_id,pk" json:"id"`
RepoID int64 `meddler:"repo_id" json:"-"`
@ -37,7 +26,7 @@ type Commit struct {
// SetAuthor sets the author's email address and calculate the Gravatar hash.
func (c *Commit) SetAuthor(email string) {
c.Author = email
c.Gravatar = util.CreateGravatar(email)
c.Gravatar = createGravatar(email)
}
// Returns the Short (--short) Commit Hash.

1
shared/model/config.go Normal file
View file

@ -0,0 +1 @@
package model

View file

@ -1,4 +1,4 @@
package repo
package model
import (
"gopkg.in/yaml.v1"
@ -11,12 +11,9 @@ var (
DefaultTimeout int64 = 7200
)
const (
HostGitlab = "gitlab.com"
HostGithub = "github.com"
HostGithubEnterprise = "enterprise.github.com"
HostBitbucket = "bitbucket.org"
)
// RepoParams represents a set of private key value parameters
// for each Repository.
type RepoParams map[string]string
type Repo struct {
ID int64 `meddler:"repo_id,pk" json:"-"`
@ -44,23 +41,7 @@ type Repo struct {
Updated int64 `meddler:"repo_updated" json:"updated_at"`
}
func NewGithub(owner, name string) (*Repo, error) {
return New(HostGithub, owner, name)
}
func NewGithubEnterprise(owner, name string) (*Repo, error) {
return New(HostGithubEnterprise, owner, name)
}
func NewGitlab(owner, name string) (*Repo, error) {
return New(HostGitlab, owner, name)
}
func NewBitbucket(owner, name string) (*Repo, error) {
return New(HostBitbucket, owner, name)
}
func New(remote, owner, name string) (*Repo, error) {
func NewRepo(remote, owner, name string) (*Repo, error) {
repo := Repo{}
repo.Remote = remote
repo.Owner = owner

11
shared/model/status.go Normal file
View file

@ -0,0 +1,11 @@
package model
const (
StatusNone = "None"
StatusEnqueue = "Pending"
StatusStarted = "Started"
StatusSuccess = "Success"
StatusFailure = "Failure"
StatusError = "Error"
StatusKilled = "Killed"
)

View file

@ -1,7 +1,6 @@
package user
package model
import (
"github.com/drone/drone/server/resource/util"
"time"
)
@ -23,9 +22,9 @@ type User struct {
Synced int64 `meddler:"user_synced" json:"synced_at"`
}
func New(remote, login, email string) *User {
func NewUser(remote, login, email string) *User {
user := User{}
user.Token = util.GenerateToken()
user.Token = generateToken()
user.Login = login
user.Remote = remote
user.Active = true
@ -36,15 +35,15 @@ func New(remote, login, email string) *User {
// SetEmail sets the email address and calculate the Gravatar hash.
func (u *User) SetEmail(email string) {
u.Email = email
u.Gravatar = util.CreateGravatar(email)
u.Gravatar = createGravatar(email)
}
func (u *User) Stale() bool {
func (u *User) IsStale() bool {
switch {
case u.Synced == 0:
return true
// refresh every 24 hours
case u.Synced+expires < time.Now().Unix():
case u.Synced+DefaultExpires < time.Now().Unix():
return true
default:
return false
@ -53,4 +52,4 @@ func (u *User) Stale() bool {
// by default, let's expire the user
// cache after 72 hours
var expires = int64(time.Hour.Seconds() * 72)
var DefaultExpires = int64(time.Hour.Seconds() * 72)

48
shared/model/util.go Normal file
View file

@ -0,0 +1,48 @@
package model
import (
"crypto/md5"
"crypto/rand"
"fmt"
"io"
"strings"
)
// standard characters allowed in token string.
var chars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
// default token length
var length = 40
// generateToken generates random strings good for use in URIs to
// identify unique objects.
func generateToken() string {
b := make([]byte, length)
r := make([]byte, length+(length/4)) // storage for random bytes.
clen := byte(len(chars))
maxrb := byte(256 - (256 % len(chars)))
i := 0
for {
io.ReadFull(rand.Reader, r)
for _, c := range r {
if c >= maxrb {
// Skip this number to avoid modulo bias.
continue
}
b[i] = chars[c%clen]
i++
if i == length {
return string(b)
}
}
}
}
// helper function to create a Gravatar Hash
// for the given Email address.
func createGravatar(email string) string {
email = strings.ToLower(strings.TrimSpace(email))
hash := md5.New()
hash.Write([]byte(email))
return fmt.Sprintf("%x", hash.Sum(nil))
}