mirror of
https://github.com/harness/drone.git
synced 2025-05-18 18:09:56 +08:00
Refactored to use Model and Database folders
This commit is contained in:
parent
554276de05
commit
36b01512c0
@ -1,9 +1,7 @@
|
|||||||
package notify
|
package notify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/server/resource/commit"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/drone/drone/server/resource/repo"
|
|
||||||
"github.com/drone/drone/server/resource/user"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Context represents the context of an
|
// Context represents the context of an
|
||||||
@ -13,13 +11,13 @@ type Context struct {
|
|||||||
Host string
|
Host string
|
||||||
|
|
||||||
// User that owns the repository
|
// User that owns the repository
|
||||||
User *user.User
|
User *model.User
|
||||||
|
|
||||||
// Repository being built.
|
// Repository being built.
|
||||||
Repo *repo.Repo
|
Repo *model.Repo
|
||||||
|
|
||||||
// Commit being built
|
// Commit being built
|
||||||
Commit *commit.Commit
|
Commit *model.Commit
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sender interface {
|
type Sender interface {
|
||||||
|
@ -1,20 +1,19 @@
|
|||||||
package notify
|
package notify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/server/resource/commit"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/drone/drone/server/resource/repo"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_getBuildUrl(t *testing.T) {
|
func Test_getBuildUrl(t *testing.T) {
|
||||||
c := &Context{
|
c := &Context{
|
||||||
Host: "http://examplehost.com",
|
Host: "http://examplehost.com",
|
||||||
Repo: &repo.Repo{
|
Repo: &model.Repo{
|
||||||
Host: "examplegit.com",
|
Host: "examplegit.com",
|
||||||
Owner: "owner",
|
Owner: "owner",
|
||||||
Name: "repo",
|
Name: "repo",
|
||||||
},
|
},
|
||||||
Commit: &commit.Commit{
|
Commit: &model.Commit{
|
||||||
Sha: "abc",
|
Sha: "abc",
|
||||||
Branch: "example",
|
Branch: "example",
|
||||||
},
|
},
|
||||||
|
@ -5,9 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/drone/drone/server/resource/commit"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/drone/drone/server/resource/repo"
|
|
||||||
"github.com/drone/drone/server/resource/user"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Webhook struct {
|
type Webhook struct {
|
||||||
@ -31,9 +29,9 @@ func (w *Webhook) Send(context *Context) error {
|
|||||||
func (w *Webhook) send(context *Context) error {
|
func (w *Webhook) send(context *Context) error {
|
||||||
// data will get posted in this format
|
// data will get posted in this format
|
||||||
data := struct {
|
data := struct {
|
||||||
Owner *user.User `json:"owner"`
|
Owner *model.User `json:"owner"`
|
||||||
Repo *repo.Repo `json:"repository"`
|
Repo *model.Repo `json:"repository"`
|
||||||
Commit *commit.Commit `json:"commit"`
|
Commit *model.Commit `json:"commit"`
|
||||||
}{context.User, context.Repo, context.Commit}
|
}{context.User, context.Repo, context.Commit}
|
||||||
|
|
||||||
// data json encoded
|
// data json encoded
|
||||||
|
@ -1,48 +1,49 @@
|
|||||||
package commit
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/russross/meddler"
|
"github.com/russross/meddler"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommitManager interface {
|
type CommitManager interface {
|
||||||
// Find finds the commit by ID.
|
// 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 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 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 finds the commit's output.
|
||||||
FindOutput(commit int64) ([]byte, error)
|
FindOutput(commit int64) ([]byte, error)
|
||||||
|
|
||||||
// List finds recent commits for the repository
|
// 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 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 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 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 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 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 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 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
|
// CancelAll will update the status of all Started or Pending
|
||||||
// builds to a status of Killed (cancelled).
|
// builds to a status of Killed (cancelled).
|
||||||
@ -54,9 +55,9 @@ type commitManager struct {
|
|||||||
*sql.DB
|
*sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager initiales a new CommitManager intended to
|
// NewCommitManager initiales a new CommitManager intended to
|
||||||
// manage and persist commits.
|
// manage and persist commits.
|
||||||
func NewManager(db *sql.DB) CommitManager {
|
func NewCommitManager(db *sql.DB) CommitManager {
|
||||||
return &commitManager{db}
|
return &commitManager{db}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ LIMIT 20
|
|||||||
`
|
`
|
||||||
|
|
||||||
// SQL query to retrieve the latest Commits for a user's repositories.
|
// 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.*
|
SELECT r.repo_remote, r.repo_host, r.repo_owner, r.repo_name, c.*
|
||||||
FROM commits c, repos r, perms p
|
FROM commits c, repos r, perms p
|
||||||
WHERE c.repo_id=r.repo_id
|
WHERE c.repo_id=r.repo_id
|
||||||
@ -96,7 +97,7 @@ LIMIT 20
|
|||||||
`
|
`
|
||||||
|
|
||||||
// SQL query to retrieve the latest Commits across all branches.
|
// SQL query to retrieve the latest Commits across all branches.
|
||||||
const listQuery = `
|
const listCommitsQuery = `
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM commits
|
FROM commits
|
||||||
WHERE repo_id=?
|
WHERE repo_id=?
|
||||||
@ -105,7 +106,7 @@ LIMIT 20
|
|||||||
`
|
`
|
||||||
|
|
||||||
// SQL query to retrieve a Commit by branch and sha.
|
// SQL query to retrieve a Commit by branch and sha.
|
||||||
const findQuery = `
|
const findCommitQuery = `
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM commits
|
FROM commits
|
||||||
WHERE repo_id=?
|
WHERE repo_id=?
|
||||||
@ -115,7 +116,7 @@ LIMIT 1
|
|||||||
`
|
`
|
||||||
|
|
||||||
// SQL query to retrieve the most recent Commit for a branch.
|
// SQL query to retrieve the most recent Commit for a branch.
|
||||||
const findLatestQuery = `
|
const findLatestCommitQuery = `
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM commits
|
FROM commits
|
||||||
WHERE commit_id IN (
|
WHERE commit_id IN (
|
||||||
@ -143,12 +144,12 @@ UPDATE output SET output_raw = ? WHERE commit_id = ?;
|
|||||||
`
|
`
|
||||||
|
|
||||||
// SQL statement to delete a Commit by ID.
|
// SQL statement to delete a Commit by ID.
|
||||||
const deleteStmt = `
|
const deleteCommitStmt = `
|
||||||
DELETE FROM commits WHERE commit_id = ?;
|
DELETE FROM commits WHERE commit_id = ?;
|
||||||
`
|
`
|
||||||
|
|
||||||
// SQL statement to cancel all running Commits.
|
// SQL statement to cancel all running Commits.
|
||||||
const cancelStmt = `
|
const cancelCommitStmt = `
|
||||||
UPDATE commits SET
|
UPDATE commits SET
|
||||||
commit_status = ?,
|
commit_status = ?,
|
||||||
commit_started = ?,
|
commit_started = ?,
|
||||||
@ -156,21 +157,21 @@ commit_finished = ?
|
|||||||
WHERE commit_status IN ('Started', 'Pending');
|
WHERE commit_status IN ('Started', 'Pending');
|
||||||
`
|
`
|
||||||
|
|
||||||
func (db *commitManager) Find(id int64) (*Commit, error) {
|
func (db *commitManager) Find(id int64) (*model.Commit, error) {
|
||||||
dst := Commit{}
|
dst := model.Commit{}
|
||||||
err := meddler.Load(db, "commits", &dst, id)
|
err := meddler.Load(db, "commits", &dst, id)
|
||||||
return &dst, err
|
return &dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) FindSha(repo int64, branch, sha string) (*Commit, error) {
|
func (db *commitManager) FindSha(repo int64, branch, sha string) (*model.Commit, error) {
|
||||||
dst := Commit{}
|
dst := model.Commit{}
|
||||||
err := meddler.QueryRow(db, &dst, findQuery, repo, branch, sha)
|
err := meddler.QueryRow(db, &dst, findCommitQuery, repo, branch, sha)
|
||||||
return &dst, err
|
return &dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) FindLatest(repo int64, branch string) (*Commit, error) {
|
func (db *commitManager) FindLatest(repo int64, branch string) (*model.Commit, error) {
|
||||||
dst := Commit{}
|
dst := model.Commit{}
|
||||||
err := meddler.QueryRow(db, &dst, findLatestQuery, repo, branch)
|
err := meddler.QueryRow(db, &dst, findLatestCommitQuery, repo, branch)
|
||||||
return &dst, err
|
return &dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,42 +181,42 @@ func (db *commitManager) FindOutput(commit int64) ([]byte, error) {
|
|||||||
return []byte(dst), err
|
return []byte(dst), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) List(repo int64) ([]*Commit, error) {
|
func (db *commitManager) List(repo int64) ([]*model.Commit, error) {
|
||||||
var dst []*Commit
|
var dst []*model.Commit
|
||||||
err := meddler.QueryAll(db, &dst, listQuery, repo)
|
err := meddler.QueryAll(db, &dst, listCommitsQuery, repo)
|
||||||
return dst, err
|
return dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) ListBranch(repo int64, branch string) ([]*Commit, error) {
|
func (db *commitManager) ListBranch(repo int64, branch string) ([]*model.Commit, error) {
|
||||||
var dst []*Commit
|
var dst []*model.Commit
|
||||||
err := meddler.QueryAll(db, &dst, listBranchQuery, repo, branch)
|
err := meddler.QueryAll(db, &dst, listBranchQuery, repo, branch)
|
||||||
return dst, err
|
return dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) ListBranches(repo int64) ([]*Commit, error) {
|
func (db *commitManager) ListBranches(repo int64) ([]*model.Commit, error) {
|
||||||
var dst []*Commit
|
var dst []*model.Commit
|
||||||
err := meddler.QueryAll(db, &dst, listBranchesQuery, repo)
|
err := meddler.QueryAll(db, &dst, listBranchesQuery, repo)
|
||||||
return dst, err
|
return dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) ListUser(user int64) ([]*CommitRepo, error) {
|
func (db *commitManager) ListUser(user int64) ([]*model.CommitRepo, error) {
|
||||||
var dst []*CommitRepo
|
var dst []*model.CommitRepo
|
||||||
err := meddler.QueryAll(db, &dst, listUserQuery, user)
|
err := meddler.QueryAll(db, &dst, listUserCommitsQuery, user)
|
||||||
return dst, err
|
return dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) Insert(commit *Commit) error {
|
func (db *commitManager) Insert(commit *model.Commit) error {
|
||||||
commit.Created = time.Now().Unix()
|
commit.Created = time.Now().Unix()
|
||||||
commit.Updated = time.Now().Unix()
|
commit.Updated = time.Now().Unix()
|
||||||
return meddler.Insert(db, "commits", commit)
|
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()
|
commit.Updated = time.Now().Unix()
|
||||||
return meddler.Update(db, "commits", commit)
|
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)
|
_, err := db.Exec(insertOutputStmt, commit.ID, out)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@ -224,12 +225,12 @@ func (db *commitManager) UpdateOutput(commit *Commit, out []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) Delete(commit *Commit) error {
|
func (db *commitManager) Delete(commit *model.Commit) error {
|
||||||
_, err := db.Exec(deleteStmt, commit.ID)
|
_, err := db.Exec(deleteCommitStmt, commit.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *commitManager) CancelAll() error {
|
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
|
return err
|
||||||
}
|
}
|
@ -1,35 +1,18 @@
|
|||||||
package commit
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drone/drone/server/database/schema"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/drone/drone/server/database/testdata"
|
|
||||||
"github.com/drone/drone/server/database/testdatabase"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// in-memory database instance for unit testing
|
func TestCommitFind(t *testing.T) {
|
||||||
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) {
|
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
commit, err := commits.Find(3)
|
commit, err := commits.Find(3)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Commit from ID, got %s", err)
|
t.Errorf("Want Commit from ID, got %s", err)
|
||||||
@ -38,11 +21,11 @@ func TestFind(t *testing.T) {
|
|||||||
testCommit(t, commit)
|
testCommit(t, commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindSha(t *testing.T) {
|
func TestCommitFindSha(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
commit, err := commits.FindSha(2, "master", "7253f6545caed41fb8f5a6fcdb3abc0b81fa9dbf")
|
commit, err := commits.FindSha(2, "master", "7253f6545caed41fb8f5a6fcdb3abc0b81fa9dbf")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Commit from SHA, got %s", err)
|
t.Errorf("Want Commit from SHA, got %s", err)
|
||||||
@ -51,11 +34,11 @@ func TestFindSha(t *testing.T) {
|
|||||||
testCommit(t, commit)
|
testCommit(t, commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindLatest(t *testing.T) {
|
func TestCommitFindLatest(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
commit, err := commits.FindLatest(2, "master")
|
commit, err := commits.FindLatest(2, "master")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Latest Commit, got %s", err)
|
t.Errorf("Want Latest Commit, got %s", err)
|
||||||
@ -64,11 +47,11 @@ func TestFindLatest(t *testing.T) {
|
|||||||
testCommit(t, commit)
|
testCommit(t, commit)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindOutput(t *testing.T) {
|
func TestCommitFindOutput(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
out, err := commits.FindOutput(1)
|
out, err := commits.FindOutput(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Commit stdout, got %s", err)
|
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()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
list, err := commits.List(2)
|
list, err := commits.List(2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want List from RepoID, got %s", err)
|
t.Errorf("Want List from RepoID, got %s", err)
|
||||||
@ -98,11 +81,11 @@ func TestList(t *testing.T) {
|
|||||||
testCommit(t, list[0])
|
testCommit(t, list[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListBranch(t *testing.T) {
|
func TestCommitListBranch(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
list, err := commits.ListBranch(2, "master")
|
list, err := commits.ListBranch(2, "master")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want List from RepoID, got %s", err)
|
t.Errorf("Want List from RepoID, got %s", err)
|
||||||
@ -116,11 +99,11 @@ func TestListBranch(t *testing.T) {
|
|||||||
testCommit(t, list[0])
|
testCommit(t, list[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestListBranches(t *testing.T) {
|
func TestCommitListBranches(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
list, err := commits.ListBranches(2)
|
list, err := commits.ListBranches(2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Branch List from RepoID, got %s", err)
|
t.Errorf("Want Branch List from RepoID, got %s", err)
|
||||||
@ -134,35 +117,35 @@ func TestListBranches(t *testing.T) {
|
|||||||
testCommit(t, list[1])
|
testCommit(t, list[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInsert(t *testing.T) {
|
func TestCommitInsert(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commit := Commit{RepoID: 3, Branch: "foo", Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac"}
|
commit := model.Commit{RepoID: 3, Branch: "foo", Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac"}
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
if err := commits.Insert(&commit); err != nil {
|
if err := commits.Insert(&commit); err != nil {
|
||||||
t.Errorf("Want Commit created, got %s", err)
|
t.Errorf("Want Commit created, got %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify that it is ok to add same sha for different branch
|
// 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 {
|
if err != nil {
|
||||||
t.Errorf("Want Commit created, got %s", err)
|
t.Errorf("Want Commit created, got %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify unique remote + remote id constraint
|
// 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 {
|
if err == nil {
|
||||||
t.Error("Want unique constraint violated")
|
t.Error("Want unique constraint violated")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
func TestCommitUpdate(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
commit, err := commits.Find(5)
|
commit, err := commits.Find(5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Commit from ID, got %s", err)
|
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()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
commits := NewManager(db)
|
commits := NewCommitManager(db)
|
||||||
commit, err := commits.Find(1)
|
commit, err := commits.Find(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Commit from ID, got %s", err)
|
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
|
// testCommit is a helper function that compares the commit
|
||||||
// to an expected set of fixed field values.
|
// 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"
|
var got, want = commit.Status, "Success"
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("Want Status %v, got %v", want, got)
|
t.Errorf("Want Status %v, got %v", want, got)
|
@ -1,33 +1,32 @@
|
|||||||
package perm
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drone/drone/server/resource/repo"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/drone/drone/server/resource/user"
|
|
||||||
"github.com/russross/meddler"
|
"github.com/russross/meddler"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PermManager interface {
|
type PermManager interface {
|
||||||
// Grant will grant the user read, write and admin persmissions
|
// Grant will grant the user read, write and admin persmissions
|
||||||
// to the specified repository.
|
// 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 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
|
// Read returns true if the specified user has read
|
||||||
// access to the repository.
|
// 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
|
// Write returns true if the specified user has write
|
||||||
// access to the repository.
|
// 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
|
// Admin returns true if the specified user is an
|
||||||
// administrator of the repository.
|
// 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.
|
// permManager manages user permissions to access repositories.
|
||||||
@ -37,7 +36,7 @@ type permManager struct {
|
|||||||
|
|
||||||
// SQL query to retrieve a user's permission to
|
// SQL query to retrieve a user's permission to
|
||||||
// access a repository.
|
// access a repository.
|
||||||
const findQuery = `
|
const findPermQuery = `
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM perms
|
FROM perms
|
||||||
WHERE user_id=?
|
WHERE user_id=?
|
||||||
@ -46,19 +45,30 @@ LIMIT 1
|
|||||||
`
|
`
|
||||||
|
|
||||||
// SQL statement to delete a permission.
|
// SQL statement to delete a permission.
|
||||||
const deleteStmt = `
|
const deletePermStmt = `
|
||||||
DELETE FROM perms WHERE user_id=? AND repo_id=?
|
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
|
// NewManager initiales a new PermManager intended to
|
||||||
// manage user permission and access control.
|
// manage user permission and access control.
|
||||||
func NewManager(db *sql.DB) PermManager {
|
func NewPermManager(db *sql.DB) PermManager {
|
||||||
return &permManager{db}
|
return &permManager{db}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grant will grant the user read, write and admin persmissions
|
// Grant will grant the user read, write and admin persmissions
|
||||||
// to the specified repository.
|
// 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
|
// attempt to get existing permissions from the database
|
||||||
perm, err := db.find(u, r)
|
perm, err := db.find(u, r)
|
||||||
if err != nil && err != sql.ErrNoRows {
|
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.
|
// Revoke will revoke all user permissions to the specified repository.
|
||||||
func (db *permManager) Revoke(u *user.User, r *repo.Repo) error {
|
func (db *permManager) Revoke(u *model.User, r *model.Repo) error {
|
||||||
_, err := db.Exec(deleteStmt, u.ID, r.ID)
|
_, err := db.Exec(deletePermStmt, u.ID, r.ID)
|
||||||
return err
|
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 {
|
switch {
|
||||||
// if the repo is public, grant access.
|
// if the repo is public, grant access.
|
||||||
case r.Private == false:
|
case r.Private == false:
|
||||||
@ -107,7 +117,7 @@ func (db *permManager) Read(u *user.User, r *repo.Repo) (bool, error) {
|
|||||||
return perm.Read, err
|
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 {
|
switch {
|
||||||
// if the user is nil, deny access
|
// if the user is nil, deny access
|
||||||
case u == nil:
|
case u == nil:
|
||||||
@ -122,7 +132,7 @@ func (db *permManager) Write(u *user.User, r *repo.Repo) (bool, error) {
|
|||||||
return perm.Write, err
|
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 {
|
switch {
|
||||||
// if the user is nil, deny access
|
// if the user is nil, deny access
|
||||||
case u == nil:
|
case u == nil:
|
||||||
@ -137,8 +147,8 @@ func (db *permManager) Admin(u *user.User, r *repo.Repo) (bool, error) {
|
|||||||
return perm.Admin, err
|
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 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
|
return &dst, err
|
||||||
}
|
}
|
@ -1,37 +1,18 @@
|
|||||||
package perm
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/drone/drone/server/database/schema"
|
"github.com/drone/drone/shared/model"
|
||||||
"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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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) {
|
func Test_find(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
manager := NewManager(db).(*permManager)
|
manager := NewPermManager(db).(*permManager)
|
||||||
perm, err := manager.find(&user.User{ID: 101}, &repo.Repo{ID: 200})
|
perm, err := manager.find(&model.User{ID: 101}, &model.Repo{ID: 200})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want permission, got %s", err)
|
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
|
// test that we get the appropriate error message when
|
||||||
// no permissions are found in the database.
|
// 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 {
|
if err != sql.ErrNoRows {
|
||||||
t.Errorf("Want ErrNoRows, got %s", err)
|
t.Errorf("Want ErrNoRows, got %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRead(t *testing.T) {
|
func TestPermRead(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
var manager = NewManager(db)
|
var manager = NewPermManager(db)
|
||||||
|
|
||||||
// dummy admin and repo
|
// dummy admin and repo
|
||||||
u := user.User{ID: 101, Admin: false}
|
u := model.User{ID: 101, Admin: false}
|
||||||
r := repo.Repo{ID: 201, Private: false}
|
r := model.Repo{ID: 201, Private: false}
|
||||||
|
|
||||||
// public repos should always be accessible
|
// public repos should always be accessible
|
||||||
if read, err := manager.Read(&u, &r); !read || err != nil {
|
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()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
var manager = NewManager(db)
|
var manager = NewPermManager(db)
|
||||||
|
|
||||||
// dummy admin and repo
|
// dummy admin and repo
|
||||||
u := user.User{ID: 101, Admin: false}
|
u := model.User{ID: 101, Admin: false}
|
||||||
r := repo.Repo{ID: 201, Private: false}
|
r := model.Repo{ID: 201, Private: false}
|
||||||
|
|
||||||
// repos should not be accessible to nil users
|
// repos should not be accessible to nil users
|
||||||
r.Private = true
|
r.Private = true
|
||||||
@ -172,14 +153,14 @@ func TestWrite(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdmin(t *testing.T) {
|
func TestPermAdmin(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
var manager = NewManager(db)
|
var manager = NewPermManager(db)
|
||||||
|
|
||||||
// dummy admin and repo
|
// dummy admin and repo
|
||||||
u := user.User{ID: 101, Admin: false}
|
u := model.User{ID: 101, Admin: false}
|
||||||
r := repo.Repo{ID: 201, Private: false}
|
r := model.Repo{ID: 201, Private: false}
|
||||||
|
|
||||||
// repos should not be accessible to nil users
|
// repos should not be accessible to nil users
|
||||||
r.Private = true
|
r.Private = true
|
||||||
@ -213,15 +194,15 @@ func TestAdmin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRevoke(t *testing.T) {
|
func TestPermRevoke(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
// dummy admin and repo
|
// dummy admin and repo
|
||||||
u := user.User{ID: 101}
|
u := model.User{ID: 101}
|
||||||
r := repo.Repo{ID: 200}
|
r := model.Repo{ID: 200}
|
||||||
|
|
||||||
manager := NewManager(db)
|
manager := NewPermManager(db)
|
||||||
admin, err := manager.Admin(&u, &r)
|
admin, err := manager.Admin(&u, &r)
|
||||||
if !admin || err != nil {
|
if !admin || err != nil {
|
||||||
t.Errorf("Want Admin permission, got Admin %v, error %s", admin, err)
|
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()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
// dummy admin and repo
|
// dummy admin and repo
|
||||||
u := user.User{ID: 104}
|
u := model.User{ID: 104}
|
||||||
r := repo.Repo{ID: 200}
|
r := model.Repo{ID: 200}
|
||||||
|
|
||||||
manager := NewManager(db).(*permManager)
|
manager := NewPermManager(db).(*permManager)
|
||||||
if err := manager.Grant(&u, &r, true, true, true); err != nil {
|
if err := manager.Grant(&u, &r, true, true, true); err != nil {
|
||||||
t.Errorf("Want permissions granted, got %s", err)
|
t.Errorf("Want permissions granted, got %s", err)
|
||||||
}
|
}
|
@ -1,36 +1,37 @@
|
|||||||
package repo
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/russross/meddler"
|
"github.com/russross/meddler"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RepoManager interface {
|
type RepoManager interface {
|
||||||
// Find retrieves the Repo by ID.
|
// 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 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 persists a new Repo to the datastore.
|
||||||
Insert(repo *Repo) error
|
Insert(repo *model.Repo) error
|
||||||
|
|
||||||
// Insert persists a modified Repo to the datastore.
|
// 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 removes a Repo from the datastore.
|
||||||
Delete(repo *Repo) error
|
Delete(repo *model.Repo) error
|
||||||
|
|
||||||
// List retrieves all repositories from the datastore.
|
// 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.
|
// List retrieves all public repositories from the datastore.
|
||||||
//ListPublic(user int64) ([]*Repo, error)
|
//ListPublic(user int64) ([]*Repo, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(db *sql.DB) RepoManager {
|
func NewRepoManager(db *sql.DB) RepoManager {
|
||||||
return &repoManager{db}
|
return &repoManager{db}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,46 +39,39 @@ type repoManager struct {
|
|||||||
*sql.DB
|
*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 = ?"
|
const query = "select * from repos where repo_id = ?"
|
||||||
var repo = Repo{}
|
var repo = model.Repo{}
|
||||||
var err = meddler.QueryRow(db, &repo, query, id)
|
var err = meddler.QueryRow(db, &repo, query, id)
|
||||||
return &repo, err
|
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 = ?"
|
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)
|
var err = meddler.QueryRow(db, &repo, query, remote, owner, name)
|
||||||
return &repo, err
|
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 = ?)"
|
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)
|
err := meddler.QueryAll(db, &repos, query, user)
|
||||||
return repos, err
|
return repos, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (db *repoManager) ListPublic(user int64) ([]*Repo, error) {
|
func (db *repoManager) Insert(repo *model.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 {
|
|
||||||
repo.Created = time.Now().Unix()
|
repo.Created = time.Now().Unix()
|
||||||
repo.Updated = time.Now().Unix()
|
repo.Updated = time.Now().Unix()
|
||||||
return meddler.Insert(db, "repos", repo)
|
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()
|
repo.Updated = time.Now().Unix()
|
||||||
return meddler.Update(db, "repos", repo)
|
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 = ?"
|
const stmt = "delete from repos where repo_id = ?"
|
||||||
_, err := db.Exec(stmt, repo.ID)
|
_, err := db.Exec(stmt, repo.ID)
|
||||||
return err
|
return err
|
@ -1,34 +1,17 @@
|
|||||||
package repo
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/drone/drone/server/database/schema"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/drone/drone/server/database/testdata"
|
|
||||||
"github.com/drone/drone/server/database/testdatabase"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// in-memory database instance for unit testing
|
func TestRepoFind(t *testing.T) {
|
||||||
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) {
|
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
repos := NewManager(db)
|
repos := NewRepoManager(db)
|
||||||
repo, err := repos.Find(1)
|
repo, err := repos.Find(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Repo from ID, got %s", err)
|
t.Errorf("Want Repo from ID, got %s", err)
|
||||||
@ -37,11 +20,11 @@ func TestFind(t *testing.T) {
|
|||||||
testRepo(t, repo)
|
testRepo(t, repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestName(t *testing.T) {
|
func TestRepoFindName(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
repos := NewManager(db)
|
repos := NewRepoManager(db)
|
||||||
user, err := repos.FindName("github.com", "lhofstadter", "lenwoloppali")
|
user, err := repos.FindName("github.com", "lhofstadter", "lenwoloppali")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Repo by Name, got %s", err)
|
t.Errorf("Want Repo by Name, got %s", err)
|
||||||
@ -50,11 +33,11 @@ func TestName(t *testing.T) {
|
|||||||
testRepo(t, user)
|
testRepo(t, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
func TestRepoList(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
repos := NewManager(db)
|
repos := NewRepoManager(db)
|
||||||
all, err := repos.List(1)
|
all, err := repos.List(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Repos, got %s", err)
|
t.Errorf("Want Repos, got %s", err)
|
||||||
@ -68,28 +51,28 @@ func TestList(t *testing.T) {
|
|||||||
testRepo(t, all[0])
|
testRepo(t, all[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInsert(t *testing.T) {
|
func TestRepoInsert(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
repo, _ := New("github.com", "mrwolowitz", "lenwoloppali")
|
repo, _ := model.NewRepo("github.com", "mrwolowitz", "lenwoloppali")
|
||||||
repos := NewManager(db)
|
repos := NewRepoManager(db)
|
||||||
if err := repos.Insert(repo); err != nil {
|
if err := repos.Insert(repo); err != nil {
|
||||||
t.Errorf("Want Repo created, got %s", err)
|
t.Errorf("Want Repo created, got %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify unique remote + owner + name login constraint
|
// 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 {
|
if err == nil {
|
||||||
t.Error("Want unique constraint violated")
|
t.Error("Want unique constraint violated")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
func TestRepoUpdate(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
repos := NewManager(db)
|
repos := NewRepoManager(db)
|
||||||
repo, err := repos.Find(1)
|
repo, err := repos.Find(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Repo from ID, got %s", err)
|
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()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
repos := NewManager(db)
|
repos := NewRepoManager(db)
|
||||||
repo, err := repos.Find(1)
|
repo, err := repos.Find(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Repo from ID, got %s", err)
|
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
|
// testRepo is a helper function that compares the repo
|
||||||
// to an expected set of fixed field values.
|
// 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"
|
var got, want = repo.Remote, "github.com"
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("Want Remote %v, got %v", want, got)
|
t.Errorf("Want Remote %v, got %v", want, got)
|
@ -1,33 +1,34 @@
|
|||||||
package user
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/russross/meddler"
|
"github.com/russross/meddler"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserManager interface {
|
type UserManager interface {
|
||||||
// Find finds the User by ID.
|
// 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 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 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 finds all registered users of the system.
|
||||||
List() ([]*User, error)
|
List() ([]*model.User, error)
|
||||||
|
|
||||||
// Insert persists the User to the datastore.
|
// 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 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 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.
|
// 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.
|
// SQL query to retrieve a User by remote login.
|
||||||
const findLoginQuery = `
|
const findUserLoginQuery = `
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM users
|
FROM users
|
||||||
WHERE user_remote=?
|
WHERE user_remote=?
|
||||||
@ -45,7 +46,7 @@ LIMIT 1
|
|||||||
`
|
`
|
||||||
|
|
||||||
// SQL query to retrieve a User by remote login.
|
// SQL query to retrieve a User by remote login.
|
||||||
const findTokenQuery = `
|
const findUserTokenQuery = `
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM users
|
FROM users
|
||||||
WHERE user_token=?
|
WHERE user_token=?
|
||||||
@ -53,59 +54,59 @@ LIMIT 1
|
|||||||
`
|
`
|
||||||
|
|
||||||
// SQL query to retrieve a list of all users.
|
// SQL query to retrieve a list of all users.
|
||||||
const listQuery = `
|
const listUserQuery = `
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM users
|
FROM users
|
||||||
ORDER BY user_name ASC
|
ORDER BY user_name ASC
|
||||||
`
|
`
|
||||||
|
|
||||||
// SQL statement to delete a User by ID.
|
// SQL statement to delete a User by ID.
|
||||||
const deleteStmt = `
|
const deleteUserStmt = `
|
||||||
DELETE FROM users WHERE user_id=?
|
DELETE FROM users WHERE user_id=?
|
||||||
`
|
`
|
||||||
|
|
||||||
// NewManager initiales a new UserManager intended to
|
// NewUserManager initiales a new UserManager intended to
|
||||||
// manage and persist commits.
|
// manage and persist commits.
|
||||||
func NewManager(db *sql.DB) UserManager {
|
func NewUserManager(db *sql.DB) UserManager {
|
||||||
return &userManager{db}
|
return &userManager{db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *userManager) Find(id int64) (*User, error) {
|
func (db *userManager) Find(id int64) (*model.User, error) {
|
||||||
dst := User{}
|
dst := model.User{}
|
||||||
err := meddler.Load(db, "users", &dst, id)
|
err := meddler.Load(db, "users", &dst, id)
|
||||||
return &dst, err
|
return &dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *userManager) FindLogin(remote, login string) (*User, error) {
|
func (db *userManager) FindLogin(remote, login string) (*model.User, error) {
|
||||||
dst := User{}
|
dst := model.User{}
|
||||||
err := meddler.QueryRow(db, &dst, findLoginQuery, remote, login)
|
err := meddler.QueryRow(db, &dst, findUserLoginQuery, remote, login)
|
||||||
return &dst, err
|
return &dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *userManager) FindToken(token string) (*User, error) {
|
func (db *userManager) FindToken(token string) (*model.User, error) {
|
||||||
dst := User{}
|
dst := model.User{}
|
||||||
err := meddler.QueryRow(db, &dst, findTokenQuery, token)
|
err := meddler.QueryRow(db, &dst, findUserTokenQuery, token)
|
||||||
return &dst, err
|
return &dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *userManager) List() ([]*User, error) {
|
func (db *userManager) List() ([]*model.User, error) {
|
||||||
var dst []*User
|
var dst []*model.User
|
||||||
err := meddler.QueryAll(db, &dst, listQuery)
|
err := meddler.QueryAll(db, &dst, listUserQuery)
|
||||||
return dst, err
|
return dst, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *userManager) Insert(user *User) error {
|
func (db *userManager) Insert(user *model.User) error {
|
||||||
user.Created = time.Now().Unix()
|
user.Created = time.Now().Unix()
|
||||||
user.Updated = time.Now().Unix()
|
user.Updated = time.Now().Unix()
|
||||||
return meddler.Insert(db, "users", user)
|
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()
|
user.Updated = time.Now().Unix()
|
||||||
return meddler.Update(db, "users", user)
|
return meddler.Update(db, "users", user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *userManager) Delete(user *User) error {
|
func (db *userManager) Delete(user *model.User) error {
|
||||||
_, err := db.Exec(deleteStmt, user.ID)
|
_, err := db.Exec(deleteUserStmt, user.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package user
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/drone/drone/server/database/schema"
|
"github.com/drone/drone/server/database/schema"
|
||||||
"github.com/drone/drone/server/database/testdata"
|
"github.com/drone/drone/server/database/testdata"
|
||||||
"github.com/drone/drone/server/database/testdatabase"
|
"github.com/drone/drone/server/database/testdatabase"
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// in-memory database instance for unit testing
|
// in-memory database instance for unit testing
|
||||||
@ -24,11 +25,11 @@ func teardown() {
|
|||||||
db.Close()
|
db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFind(t *testing.T) {
|
func TestUserFind(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
users := NewManager(db)
|
users := NewUserManager(db)
|
||||||
user, err := users.Find(1)
|
user, err := users.Find(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want User from ID, got %s", err)
|
t.Errorf("Want User from ID, got %s", err)
|
||||||
@ -37,11 +38,11 @@ func TestFind(t *testing.T) {
|
|||||||
testUser(t, user)
|
testUser(t, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindLogin(t *testing.T) {
|
func TestUserFindLogin(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
users := NewManager(db)
|
users := NewUserManager(db)
|
||||||
user, err := users.FindLogin("github.com", "smellypooper")
|
user, err := users.FindLogin("github.com", "smellypooper")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want User from Login, got %s", err)
|
t.Errorf("Want User from Login, got %s", err)
|
||||||
@ -50,11 +51,11 @@ func TestFindLogin(t *testing.T) {
|
|||||||
testUser(t, user)
|
testUser(t, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindToken(t *testing.T) {
|
func TestUserFindToken(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
users := NewManager(db)
|
users := NewUserManager(db)
|
||||||
user, err := users.FindToken("e42080dddf012c718e476da161d21ad5")
|
user, err := users.FindToken("e42080dddf012c718e476da161d21ad5")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want User from Token, got %s", err)
|
t.Errorf("Want User from Token, got %s", err)
|
||||||
@ -63,11 +64,11 @@ func TestFindToken(t *testing.T) {
|
|||||||
testUser(t, user)
|
testUser(t, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
func TestUserList(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
users := NewManager(db)
|
users := NewUserManager(db)
|
||||||
all, err := users.List()
|
all, err := users.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want Users, got %s", err)
|
t.Errorf("Want Users, got %s", err)
|
||||||
@ -81,12 +82,12 @@ func TestList(t *testing.T) {
|
|||||||
testUser(t, all[0])
|
testUser(t, all[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInsert(t *testing.T) {
|
func TestUserInsert(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
user := New("github.com", "winkle", "winkle@caltech.edu")
|
user := model.NewUser("github.com", "winkle", "winkle@caltech.edu")
|
||||||
users := NewManager(db)
|
users := NewUserManager(db)
|
||||||
if err := users.Insert(user); err != nil {
|
if err := users.Insert(user); err != nil {
|
||||||
t.Errorf("Want User created, got %s", err)
|
t.Errorf("Want User created, got %s", err)
|
||||||
}
|
}
|
||||||
@ -97,23 +98,23 @@ func TestInsert(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// verify unique remote + remote login constraint
|
// 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 {
|
if err == nil {
|
||||||
t.Error("Want Token unique constraint violated")
|
t.Error("Want Token unique constraint violated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify unique token constraint
|
// 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 {
|
if err == nil {
|
||||||
t.Error("Want Token unique constraint violated")
|
t.Error("Want Token unique constraint violated")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
func TestUserUpdate(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
users := NewManager(db)
|
users := NewUserManager(db)
|
||||||
user, err := users.Find(4)
|
user, err := users.Find(4)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want User from ID, got %s", err)
|
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()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
users := NewManager(db)
|
users := NewUserManager(db)
|
||||||
user, err := users.Find(1)
|
user, err := users.Find(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Want User from ID, got %s", err)
|
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
|
// testUser is a helper function that compares the user
|
||||||
// to an expected set of fixed field values.
|
// 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"
|
var got, want = user.Login, "smellypooper"
|
||||||
if got != want {
|
if got != want {
|
||||||
t.Errorf("Want Token %v, got %v", want, got)
|
t.Errorf("Want Token %v, got %v", want, got)
|
@ -4,8 +4,8 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drone/drone/server/resource/commit"
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/resource/repo"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/gorilla/pat"
|
"github.com/gorilla/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,11 +20,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type BadgeHandler struct {
|
type BadgeHandler struct {
|
||||||
commits commit.CommitManager
|
commits database.CommitManager
|
||||||
repos repo.RepoManager
|
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}
|
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 no branch, use the default
|
||||||
if len(branch) == 0 {
|
if len(branch) == 0 {
|
||||||
branch = repo.DefaultBranch
|
branch = model.DefaultBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the latest commit
|
// get the latest commit
|
||||||
@ -69,13 +69,13 @@ func (h *BadgeHandler) GetStatus(w http.ResponseWriter, r *http.Request) error {
|
|||||||
|
|
||||||
// determine which badge to load
|
// determine which badge to load
|
||||||
switch c.Status {
|
switch c.Status {
|
||||||
case commit.StatusSuccess:
|
case model.StatusSuccess:
|
||||||
w.Write(badgeSuccess)
|
w.Write(badgeSuccess)
|
||||||
case commit.StatusFailure:
|
case model.StatusFailure:
|
||||||
w.Write(badgeFailure)
|
w.Write(badgeFailure)
|
||||||
case commit.StatusError:
|
case model.StatusError:
|
||||||
w.Write(badgeError)
|
w.Write(badgeError)
|
||||||
case commit.StatusEnqueue, commit.StatusStarted:
|
case model.StatusEnqueue, model.StatusStarted:
|
||||||
w.Write(badgeStarted)
|
w.Write(badgeStarted)
|
||||||
default:
|
default:
|
||||||
w.Write(badgeNone)
|
w.Write(badgeNone)
|
||||||
|
@ -4,21 +4,19 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/drone/drone/server/resource/commit"
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/resource/perm"
|
|
||||||
"github.com/drone/drone/server/resource/repo"
|
|
||||||
"github.com/drone/drone/server/session"
|
"github.com/drone/drone/server/session"
|
||||||
"github.com/gorilla/pat"
|
"github.com/gorilla/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BranchHandler struct {
|
type BranchHandler struct {
|
||||||
perms perm.PermManager
|
perms database.PermManager
|
||||||
repos repo.RepoManager
|
repos database.RepoManager
|
||||||
commits commit.CommitManager
|
commits database.CommitManager
|
||||||
sess session.Session
|
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}
|
return &BranchHandler{perms, repos, commits, sess}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,23 +4,22 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/queue"
|
"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/server/session"
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/gorilla/pat"
|
"github.com/gorilla/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommitHandler struct {
|
type CommitHandler struct {
|
||||||
perms perm.PermManager
|
perms database.PermManager
|
||||||
repos repo.RepoManager
|
repos database.RepoManager
|
||||||
commits commit.CommitManager
|
commits database.CommitManager
|
||||||
sess session.Session
|
sess session.Session
|
||||||
queue *queue.Queue
|
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}
|
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
|
// 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{}
|
return badRequest{}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Status = commit.StatusEnqueue
|
c.Status = model.StatusEnqueue
|
||||||
c.Started = 0
|
c.Started = 0
|
||||||
c.Finished = 0
|
c.Finished = 0
|
||||||
c.Duration = 0
|
c.Duration = 0
|
||||||
|
@ -3,23 +3,22 @@ package handler
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/queue"
|
"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/config"
|
||||||
"github.com/drone/drone/server/resource/repo"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/drone/drone/server/resource/user"
|
|
||||||
"github.com/gorilla/pat"
|
"github.com/gorilla/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type HookHandler struct {
|
type HookHandler struct {
|
||||||
users user.UserManager
|
users database.UserManager
|
||||||
repos repo.RepoManager
|
repos database.RepoManager
|
||||||
commits commit.CommitManager
|
commits database.CommitManager
|
||||||
queue *queue.Queue
|
queue *queue.Queue
|
||||||
conf *config.Config
|
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}
|
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}
|
return badRequest{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
c := commit.Commit{
|
c := model.Commit{
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
Status: commit.StatusEnqueue,
|
Status: model.StatusEnqueue,
|
||||||
Sha: hook.Sha,
|
Sha: hook.Sha,
|
||||||
Branch: hook.Branch,
|
Branch: hook.Branch,
|
||||||
PullRequest: hook.PullRequest,
|
PullRequest: hook.PullRequest,
|
||||||
|
@ -5,23 +5,22 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/resource/config"
|
"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/server/session"
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/gorilla/pat"
|
"github.com/gorilla/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoginHandler struct {
|
type LoginHandler struct {
|
||||||
users user.UserManager
|
users database.UserManager
|
||||||
repos repo.RepoManager
|
repos database.RepoManager
|
||||||
perms perm.PermManager
|
perms database.PermManager
|
||||||
sess session.Session
|
sess session.Session
|
||||||
conf *config.Config
|
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}
|
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
|
// 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.Name = login.Name
|
||||||
u.SetEmail(login.Email)
|
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
|
// TODO this should move to a server/sync package and
|
||||||
// should be injected into this struct, just like
|
// should be injected into this struct, just like
|
||||||
// the database code.
|
// the database code.
|
||||||
if u.Stale() {
|
if u.IsStale() {
|
||||||
log.Println("sync user account.", u.Login)
|
log.Println("sync user account.", u.Login)
|
||||||
|
|
||||||
// sync inside a goroutine. This should eventually be moved to
|
// 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
|
// insert all repositories
|
||||||
for _, remoteRepo := range repos {
|
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.Private = remoteRepo.Private
|
||||||
repo.Host = remoteRepo.Host
|
repo.Host = remoteRepo.Host
|
||||||
repo.CloneURL = remoteRepo.Clone
|
repo.CloneURL = remoteRepo.Clone
|
||||||
|
@ -5,10 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"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/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/server/session"
|
||||||
"github.com/drone/drone/shared/httputil"
|
"github.com/drone/drone/shared/httputil"
|
||||||
"github.com/drone/drone/shared/sshutil"
|
"github.com/drone/drone/shared/sshutil"
|
||||||
@ -17,14 +15,14 @@ import (
|
|||||||
|
|
||||||
type RepoHandler struct {
|
type RepoHandler struct {
|
||||||
conf *config.Config
|
conf *config.Config
|
||||||
commits commit.CommitManager
|
commits database.CommitManager
|
||||||
perms perm.PermManager
|
perms database.PermManager
|
||||||
repos repo.RepoManager
|
repos database.RepoManager
|
||||||
sess session.Session
|
sess session.Session
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRepoHandler(repos repo.RepoManager, commits commit.CommitManager,
|
func NewRepoHandler(repos database.RepoManager, commits database.CommitManager,
|
||||||
perms perm.PermManager, sess session.Session, conf *config.Config) *RepoHandler {
|
perms database.PermManager, sess session.Session, conf *config.Config) *RepoHandler {
|
||||||
return &RepoHandler{conf, commits, perms, repos, sess}
|
return &RepoHandler{conf, commits, perms, repos, sess}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,27 +5,25 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/drone/drone/server/channel"
|
"github.com/drone/drone/server/channel"
|
||||||
"github.com/drone/drone/server/resource/commit"
|
"github.com/drone/drone/server/database"
|
||||||
"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/server/session"
|
||||||
"github.com/drone/drone/shared/httputil"
|
"github.com/drone/drone/shared/httputil"
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/gorilla/pat"
|
"github.com/gorilla/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Renderer func(wr io.Writer, name string, data interface{}) error
|
type Renderer func(wr io.Writer, name string, data interface{}) error
|
||||||
|
|
||||||
type SiteHandler struct {
|
type SiteHandler struct {
|
||||||
users user.UserManager
|
users database.UserManager
|
||||||
repos repo.RepoManager
|
repos database.RepoManager
|
||||||
commits commit.CommitManager
|
commits database.CommitManager
|
||||||
perms perm.PermManager
|
perms database.PermManager
|
||||||
sess session.Session
|
sess session.Session
|
||||||
render Renderer
|
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}
|
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)
|
feed, _ := s.commits.ListUser(u.ID)
|
||||||
data := struct {
|
data := struct {
|
||||||
User *user.User
|
User *model.User
|
||||||
Feed []*commit.CommitRepo
|
Feed []*model.CommitRepo
|
||||||
}{u, feed}
|
}{u, feed}
|
||||||
return s.render(w, "user_feed.html", &data)
|
return s.render(w, "user_feed.html", &data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogin serves the account login page
|
// GetLogin serves the account login page
|
||||||
func (s *SiteHandler) GetLogin(w http.ResponseWriter, r *http.Request) error {
|
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.
|
// GetUser serves the account settings page.
|
||||||
@ -56,7 +54,7 @@ func (s *SiteHandler) GetUser(w http.ResponseWriter, r *http.Request) error {
|
|||||||
if u == nil {
|
if u == nil {
|
||||||
return s.render(w, "404.html", 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 {
|
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 {
|
if u == nil || u.Admin == false {
|
||||||
return s.render(w, "404.html", nil)
|
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 {
|
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 {
|
if u == nil || u.Admin == false {
|
||||||
return s.render(w, "404.html", nil)
|
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 {
|
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)
|
return s.render(w, "404.html", nil)
|
||||||
}
|
}
|
||||||
data := struct {
|
data := struct {
|
||||||
User *user.User
|
User *model.User
|
||||||
Repo *repo.Repo
|
Repo *model.Repo
|
||||||
Branch string
|
Branch string
|
||||||
Channel string
|
Channel string
|
||||||
Stream string
|
Stream string
|
||||||
Branches []*commit.Commit
|
Branches []*model.Commit
|
||||||
Commits []*commit.Commit
|
Commits []*model.Commit
|
||||||
Commit *commit.Commit
|
Commit *model.Commit
|
||||||
}{User: usr, Repo: arepo}
|
}{User: usr, Repo: arepo}
|
||||||
|
|
||||||
// generate a token for connecting to the streaming server
|
// 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)
|
return s.render(w, "404.html", nil)
|
||||||
}
|
}
|
||||||
data := struct {
|
data := struct {
|
||||||
User *user.User
|
User *model.User
|
||||||
Repo *repo.Repo
|
Repo *model.Repo
|
||||||
Host string
|
Host string
|
||||||
Scheme string
|
Scheme string
|
||||||
}{u, arepo, httputil.GetHost(r), httputil.GetScheme(r)}
|
}{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)
|
s.render(w, "500.html", nil)
|
||||||
}
|
}
|
||||||
data := struct {
|
data := struct {
|
||||||
User *user.User
|
User *model.User
|
||||||
Repos []*repo.Repo
|
Repos []*model.Repo
|
||||||
}{u, repos}
|
}{u, repos}
|
||||||
return s.render(w, "user_repos.html", &data)
|
return s.render(w, "user_repos.html", &data)
|
||||||
}
|
}
|
||||||
|
@ -4,21 +4,20 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/drone/drone/server/resource/commit"
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/resource/repo"
|
|
||||||
"github.com/drone/drone/server/resource/user"
|
|
||||||
"github.com/drone/drone/server/session"
|
"github.com/drone/drone/server/session"
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/gorilla/pat"
|
"github.com/gorilla/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserHandler struct {
|
type UserHandler struct {
|
||||||
commits commit.CommitManager
|
commits database.CommitManager
|
||||||
repos repo.RepoManager
|
repos database.RepoManager
|
||||||
users user.UserManager
|
users database.UserManager
|
||||||
sess session.Session
|
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}
|
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
|
// requesting their own data, and will need to display
|
||||||
// the Token on the website.
|
// the Token on the website.
|
||||||
data := struct {
|
data := struct {
|
||||||
*user.User
|
*model.User
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}{u, u.Token}
|
}{u, u.Token}
|
||||||
return json.NewEncoder(w).Encode(&data)
|
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
|
// unmarshal the repository from the payload
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
in := user.User{}
|
in := model.User{}
|
||||||
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
|
||||||
return badRequest{err}
|
return badRequest{err}
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,17 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/drone/drone/server/resource/user"
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/session"
|
"github.com/drone/drone/server/session"
|
||||||
"github.com/gorilla/pat"
|
"github.com/gorilla/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UsersHandler struct {
|
type UsersHandler struct {
|
||||||
users user.UserManager
|
users database.UserManager
|
||||||
sess session.Session
|
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}
|
return &UsersHandler{users, sess}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,14 +10,11 @@ import (
|
|||||||
|
|
||||||
"code.google.com/p/go.net/websocket"
|
"code.google.com/p/go.net/websocket"
|
||||||
"github.com/drone/drone/server/channel"
|
"github.com/drone/drone/server/channel"
|
||||||
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/database/schema"
|
"github.com/drone/drone/server/database/schema"
|
||||||
"github.com/drone/drone/server/handler"
|
"github.com/drone/drone/server/handler"
|
||||||
"github.com/drone/drone/server/queue"
|
"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/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/server/session"
|
||||||
"github.com/drone/drone/shared/build/docker"
|
"github.com/drone/drone/shared/build/docker"
|
||||||
"github.com/drone/drone/shared/build/log"
|
"github.com/drone/drone/shared/build/log"
|
||||||
@ -95,10 +92,10 @@ func main() {
|
|||||||
schema.Load(db)
|
schema.Load(db)
|
||||||
|
|
||||||
// setup the database managers
|
// setup the database managers
|
||||||
repos := repo.NewManager(db)
|
repos := database.NewRepoManager(db)
|
||||||
users := user.NewManager(db)
|
users := database.NewUserManager(db)
|
||||||
perms := perm.NewManager(db)
|
perms := database.NewPermManager(db)
|
||||||
commits := commit.NewManager(db)
|
commits := database.NewCommitManager(db)
|
||||||
|
|
||||||
// cancel all previously running builds
|
// cancel all previously running builds
|
||||||
go commits.CancelAll()
|
go commits.CancelAll()
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package queue
|
package queue
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/server/resource/commit"
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/server/resource/repo"
|
"github.com/drone/drone/shared/model"
|
||||||
"github.com/drone/drone/server/resource/user"
|
|
||||||
|
|
||||||
"github.com/drone/drone/shared/build/script"
|
"github.com/drone/drone/shared/build/script"
|
||||||
)
|
)
|
||||||
@ -16,9 +15,9 @@ type Queue struct {
|
|||||||
// BuildTasks represents a build that is pending
|
// BuildTasks represents a build that is pending
|
||||||
// execution.
|
// execution.
|
||||||
type BuildTask struct {
|
type BuildTask struct {
|
||||||
User *user.User
|
User *model.User
|
||||||
Repo *repo.Repo
|
Repo *model.Repo
|
||||||
Commit *commit.Commit
|
Commit *model.Commit
|
||||||
|
|
||||||
// Build instructions from the .drone.yml
|
// Build instructions from the .drone.yml
|
||||||
// file, unmarshalled.
|
// file, unmarshalled.
|
||||||
@ -26,7 +25,7 @@ type BuildTask struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start N workers with the given build runner.
|
// 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)
|
tasks := make(chan *BuildTask)
|
||||||
queue := &Queue{tasks: tasks}
|
queue := &Queue{tasks: tasks}
|
||||||
|
|
||||||
|
@ -4,20 +4,19 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/drone/drone/server/channel"
|
"github.com/drone/drone/server/channel"
|
||||||
|
"github.com/drone/drone/server/database"
|
||||||
"github.com/drone/drone/shared/build/git"
|
"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/build/script"
|
||||||
|
"github.com/drone/drone/shared/model"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/drone/drone/server/resource/commit"
|
|
||||||
"github.com/drone/drone/server/resource/repo"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type worker struct {
|
type worker struct {
|
||||||
commits commit.CommitManager
|
commits database.CommitManager
|
||||||
|
|
||||||
runner BuildRunner
|
runner BuildRunner
|
||||||
}
|
}
|
||||||
@ -52,7 +51,7 @@ func (w *worker) execute(task *BuildTask) error {
|
|||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
task.Commit.Finished = time.Now().Unix()
|
task.Commit.Finished = time.Now().Unix()
|
||||||
task.Commit.Duration = task.Commit.Finished - task.Commit.Started
|
task.Commit.Duration = task.Commit.Finished - task.Commit.Started
|
||||||
task.Commit.Status = commit.StatusError
|
task.Commit.Status = model.StatusError
|
||||||
w.commits.Update(task.Commit)
|
w.commits.Update(task.Commit)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -66,7 +65,7 @@ func (w *worker) execute(task *BuildTask) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update commit and build status
|
// update commit and build status
|
||||||
task.Commit.Status = commit.StatusStarted
|
task.Commit.Status = model.StatusStarted
|
||||||
task.Commit.Started = time.Now().Unix()
|
task.Commit.Started = time.Now().Unix()
|
||||||
|
|
||||||
// persist the commit to the database
|
// 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.Finished = time.Now().Unix()
|
||||||
task.Commit.Duration = task.Commit.Finished - task.Commit.Started
|
task.Commit.Duration = task.Commit.Finished - task.Commit.Started
|
||||||
task.Commit.Status = commit.StatusSuccess
|
task.Commit.Status = model.StatusSuccess
|
||||||
|
|
||||||
// capture build output
|
// capture build output
|
||||||
stdout := buf.buf.String()
|
stdout := buf.buf.String()
|
||||||
|
|
||||||
// if exit code != 0 set to failure
|
// if exit code != 0 set to failure
|
||||||
if passed {
|
if passed {
|
||||||
task.Commit.Status = commit.StatusFailure
|
task.Commit.Status = model.StatusFailure
|
||||||
if buildErr != nil && len(stdout) == 0 {
|
if buildErr != nil && len(stdout) == 0 {
|
||||||
// TODO: If you wanted to have very friendly error messages, you could do that here
|
// TODO: If you wanted to have very friendly error messages, you could do that here
|
||||||
stdout = fmt.Sprintf("%s\n", buildErr.Error())
|
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)
|
var path = filepath.Join(task.Repo.Host, task.Repo.Owner, task.Repo.Name)
|
||||||
path = git.GitPath(task.Script.Git, path)
|
path = git.GitPath(task.Script.Git, path)
|
||||||
|
|
||||||
repo := &r.Repo{
|
repo := &repo.Repo{
|
||||||
Name: task.Repo.Host + task.Repo.Owner + task.Repo.Name,
|
Name: task.Repo.Host + task.Repo.Owner + task.Repo.Name,
|
||||||
Path: task.Repo.CloneURL,
|
Path: task.Repo.CloneURL,
|
||||||
Branch: task.Commit.Branch,
|
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
|
// updateGitHubStatus is a helper function that will send
|
||||||
// the build status to GitHub using the Status API.
|
// the build status to GitHub using the Status API.
|
||||||
// see https://github.com/blog/1227-commit-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
|
// convert from drone status to github status
|
||||||
var message, status string
|
var message, status string
|
||||||
|
@ -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"`
|
|
||||||
}
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,8 @@ package session
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"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/securecookie"
|
||||||
"github.com/gorilla/sessions"
|
"github.com/gorilla/sessions"
|
||||||
)
|
)
|
||||||
@ -13,25 +14,25 @@ var cookies = sessions.NewCookieStore(
|
|||||||
securecookie.GenerateRandomKey(64))
|
securecookie.GenerateRandomKey(64))
|
||||||
|
|
||||||
type Session interface {
|
type Session interface {
|
||||||
User(r *http.Request) *user.User
|
User(r *http.Request) *model.User
|
||||||
UserToken(r *http.Request) *user.User
|
UserToken(r *http.Request) *model.User
|
||||||
UserCookie(r *http.Request) *user.User
|
UserCookie(r *http.Request) *model.User
|
||||||
SetUser(w http.ResponseWriter, r *http.Request, u *user.User)
|
SetUser(w http.ResponseWriter, r *http.Request, u *model.User)
|
||||||
Clear(w http.ResponseWriter, r *http.Request)
|
Clear(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
type session struct {
|
type session struct {
|
||||||
users user.UserManager
|
users database.UserManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSession(users user.UserManager) Session {
|
func NewSession(users database.UserManager) Session {
|
||||||
return &session{
|
return &session{
|
||||||
users: users,
|
users: users,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// User gets the currently authenticated user from the secure cookie session.
|
// 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 {
|
//if true {
|
||||||
// user, _ := s.users.Find(1)
|
// user, _ := s.users.Find(1)
|
||||||
// return user
|
// 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.
|
// 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")
|
token := r.FormValue("access_token")
|
||||||
user, _ := s.users.FindToken(token)
|
user, _ := s.users.FindToken(token)
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserCookie gets the currently authenticated user from the secure cookie session.
|
// 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")
|
sess, err := cookies.Get(r, "_sess")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
@ -70,7 +71,7 @@ func (s *session) UserCookie(r *http.Request) *user.User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetUser writes the specified username to the session.
|
// 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, _ := cookies.Get(r, "_sess")
|
||||||
sess.Values["uid"] = u.ID
|
sess.Values["uid"] = u.ID
|
||||||
sess.Save(r, w)
|
sess.Save(r, w)
|
||||||
|
@ -1,20 +1,9 @@
|
|||||||
package commit
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/server/resource/util"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
StatusNone = "None"
|
|
||||||
StatusEnqueue = "Pending"
|
|
||||||
StatusStarted = "Started"
|
|
||||||
StatusSuccess = "Success"
|
|
||||||
StatusFailure = "Failure"
|
|
||||||
StatusError = "Error"
|
|
||||||
StatusKilled = "Killed"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Commit struct {
|
type Commit struct {
|
||||||
ID int64 `meddler:"commit_id,pk" json:"id"`
|
ID int64 `meddler:"commit_id,pk" json:"id"`
|
||||||
RepoID int64 `meddler:"repo_id" json:"-"`
|
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.
|
// SetAuthor sets the author's email address and calculate the Gravatar hash.
|
||||||
func (c *Commit) SetAuthor(email string) {
|
func (c *Commit) SetAuthor(email string) {
|
||||||
c.Author = email
|
c.Author = email
|
||||||
c.Gravatar = util.CreateGravatar(email)
|
c.Gravatar = createGravatar(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the Short (--short) Commit Hash.
|
// Returns the Short (--short) Commit Hash.
|
1
shared/model/config.go
Normal file
1
shared/model/config.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package model
|
@ -1,4 +1,4 @@
|
|||||||
package repo
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"gopkg.in/yaml.v1"
|
"gopkg.in/yaml.v1"
|
||||||
@ -11,12 +11,9 @@ var (
|
|||||||
DefaultTimeout int64 = 7200
|
DefaultTimeout int64 = 7200
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// RepoParams represents a set of private key value parameters
|
||||||
HostGitlab = "gitlab.com"
|
// for each Repository.
|
||||||
HostGithub = "github.com"
|
type RepoParams map[string]string
|
||||||
HostGithubEnterprise = "enterprise.github.com"
|
|
||||||
HostBitbucket = "bitbucket.org"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Repo struct {
|
type Repo struct {
|
||||||
ID int64 `meddler:"repo_id,pk" json:"-"`
|
ID int64 `meddler:"repo_id,pk" json:"-"`
|
||||||
@ -44,23 +41,7 @@ type Repo struct {
|
|||||||
Updated int64 `meddler:"repo_updated" json:"updated_at"`
|
Updated int64 `meddler:"repo_updated" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGithub(owner, name string) (*Repo, error) {
|
func NewRepo(remote, 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) {
|
|
||||||
repo := Repo{}
|
repo := Repo{}
|
||||||
repo.Remote = remote
|
repo.Remote = remote
|
||||||
repo.Owner = owner
|
repo.Owner = owner
|
11
shared/model/status.go
Normal file
11
shared/model/status.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusNone = "None"
|
||||||
|
StatusEnqueue = "Pending"
|
||||||
|
StatusStarted = "Started"
|
||||||
|
StatusSuccess = "Success"
|
||||||
|
StatusFailure = "Failure"
|
||||||
|
StatusError = "Error"
|
||||||
|
StatusKilled = "Killed"
|
||||||
|
)
|
@ -1,7 +1,6 @@
|
|||||||
package user
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/drone/drone/server/resource/util"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,9 +22,9 @@ type User struct {
|
|||||||
Synced int64 `meddler:"user_synced" json:"synced_at"`
|
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 := User{}
|
||||||
user.Token = util.GenerateToken()
|
user.Token = generateToken()
|
||||||
user.Login = login
|
user.Login = login
|
||||||
user.Remote = remote
|
user.Remote = remote
|
||||||
user.Active = true
|
user.Active = true
|
||||||
@ -36,15 +35,15 @@ func New(remote, login, email string) *User {
|
|||||||
// SetEmail sets the email address and calculate the Gravatar hash.
|
// SetEmail sets the email address and calculate the Gravatar hash.
|
||||||
func (u *User) SetEmail(email string) {
|
func (u *User) SetEmail(email string) {
|
||||||
u.Email = email
|
u.Email = email
|
||||||
u.Gravatar = util.CreateGravatar(email)
|
u.Gravatar = createGravatar(email)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) Stale() bool {
|
func (u *User) IsStale() bool {
|
||||||
switch {
|
switch {
|
||||||
case u.Synced == 0:
|
case u.Synced == 0:
|
||||||
return true
|
return true
|
||||||
// refresh every 24 hours
|
// refresh every 24 hours
|
||||||
case u.Synced+expires < time.Now().Unix():
|
case u.Synced+DefaultExpires < time.Now().Unix():
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
@ -53,4 +52,4 @@ func (u *User) Stale() bool {
|
|||||||
|
|
||||||
// by default, let's expire the user
|
// by default, let's expire the user
|
||||||
// cache after 72 hours
|
// 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
48
shared/model/util.go
Normal 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))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user