More work on project permissions

This commit is contained in:
simon987 2019-02-16 11:47:54 -05:00
parent 03153c4d39
commit e079fc8497
18 changed files with 470 additions and 125 deletions

View File

@ -128,6 +128,9 @@ func (api *WebAPI) ProjectCreate(r *Request) {
}, 500)
return
}
api.Database.SetManagerRoleOn(manager.(*storage.Manager), id,
storage.ROLE_MANAGE_ACCESS|storage.ROLE_READ|storage.ROLE_EDIT)
r.OkJson(CreateProjectResponse{
Ok: true,
Id: id,
@ -169,29 +172,7 @@ func (api *WebAPI) ProjectUpdate(r *Request) {
Chain: updateReq.Chain,
}
if isValidProject(project) {
err := api.Database.UpdateProject(project)
if err != nil {
r.Json(CreateProjectResponse{
Ok: false,
Message: err.Error(),
}, 500)
logrus.WithError(err).WithFields(logrus.Fields{
"project": project,
}).Warn("Error during project update")
} else {
r.OkJson(UpdateProjectResponse{
Ok: true,
})
logrus.WithFields(logrus.Fields{
"project": project,
}).Debug("Updated project")
}
} else {
if !isValidProject(project) {
logrus.WithFields(logrus.Fields{
"project": project,
}).Warn("Invalid project")
@ -200,6 +181,41 @@ func (api *WebAPI) ProjectUpdate(r *Request) {
Ok: false,
Message: "Invalid project",
}, 400)
return
}
sess := api.Session.StartFasthttp(r.Ctx)
manager := sess.Get("manager")
if !isProjectUpdateAuthorized(project, manager, api.Database) {
r.Json(CreateProjectResponse{
Ok: false,
Message: "Unauthorized",
}, 403)
logrus.WithError(err).WithFields(logrus.Fields{
"project": project,
}).Warn("Unauthorized project update")
return
}
err = api.Database.UpdateProject(project)
if err != nil {
r.Json(CreateProjectResponse{
Ok: false,
Message: err.Error(),
}, 500)
logrus.WithError(err).WithFields(logrus.Fields{
"project": project,
}).Warn("Error during project update")
} else {
r.OkJson(UpdateProjectResponse{
Ok: true,
})
logrus.WithFields(logrus.Fields{
"project": project,
}).Debug("Updated project")
}
}
@ -210,18 +226,20 @@ func isValidProject(project *storage.Project) bool {
if project.Priority < 0 {
return false
}
if project.Hidden && project.Public {
return false
}
return true
}
func isProjectCreationAuthorized(project *storage.Project, manager interface{}) bool {
return true
if manager == nil {
return false
}
if project.Public && manager.(*storage.Manager).WebsiteAdmin {
if project.Public && !manager.(*storage.Manager).WebsiteAdmin {
return false
}
return true
@ -229,16 +247,15 @@ func isProjectCreationAuthorized(project *storage.Project, manager interface{})
func isProjectUpdateAuthorized(project *storage.Project, manager interface{}, db *storage.Database) bool {
var man storage.Manager
if manager != nil {
man = manager.(storage.Manager)
if manager == nil {
return false
}
if man.WebsiteAdmin {
if manager.(*storage.Manager).WebsiteAdmin {
return true
}
role := db.ManagerHasRoleOn(&man, project.Id)
role := db.GetManagerRoleOn(manager.(*storage.Manager), project.Id)
if role&storage.ROLE_EDIT == 1 {
return true
}
@ -246,36 +263,69 @@ func isProjectUpdateAuthorized(project *storage.Project, manager interface{}, db
return false
}
func isProjectReadAuthorized(project *storage.Project, manager interface{}, db *storage.Database) bool {
if project.Public || !project.Hidden {
return true
}
if manager == nil {
return false
}
if manager.(*storage.Manager).WebsiteAdmin {
return true
}
role := db.GetManagerRoleOn(manager.(*storage.Manager), project.Id)
if role&storage.ROLE_READ == 1 {
return true
}
return false
}
func (api *WebAPI) ProjectGet(r *Request) {
id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
handleErr(err, r) //todo handle invalid id
sess := api.Session.StartFasthttp(r.Ctx)
manager := sess.Get("manager")
project := api.Database.GetProject(id)
if project != nil {
r.OkJson(GetProjectResponse{
Ok: true,
Project: project,
})
} else {
if project == nil {
r.Json(GetProjectResponse{
Ok: false,
Message: "Project not found",
}, 404)
return
}
if !isProjectReadAuthorized(project, manager, api.Database) {
r.Json(GetProjectResponse{
Ok: false,
Message: "Unauthorized",
}, 403)
return
}
r.OkJson(GetProjectResponse{
Ok: true,
Project: project,
})
}
func (api *WebAPI) ProjectGetAllProjects(r *Request) {
worker, _ := api.validateSignature(r)
sess := api.Session.StartFasthttp(r.Ctx)
manager := sess.Get("manager")
var id int64
if worker == nil {
if manager == nil {
id = 0
} else {
id = worker.Id
id = manager.(*storage.Manager).Id
}
projects := api.Database.GetAllProjects(id)
r.OkJson(GetAllProjectsResponse{
@ -314,7 +364,7 @@ func (api *WebAPI) ProjectGetAccessRequests(r *Request) {
}
if !manager.(*storage.Manager).WebsiteAdmin &&
api.Database.ManagerHasRoleOn(manager.(*storage.Manager), 1)&
api.Database.GetManagerRoleOn(manager.(*storage.Manager), 1)&
storage.ROLE_MANAGE_ACCESS == 0 {
r.Json(ProjectGetAccessRequestsResponse{
Ok: false,

View File

@ -126,7 +126,7 @@ func (database *Database) UpdateManagerPassword(manager *Manager, newPassword []
}).Trace("Database.UpdateManagerPassword UPDATE")
}
func (database *Database) ManagerHasRoleOn(manager *Manager, projectId int64) ManagerRole {
func (database *Database) GetManagerRoleOn(manager *Manager, projectId int64) ManagerRole {
db := database.getDB()
@ -142,6 +142,25 @@ func (database *Database) ManagerHasRoleOn(manager *Manager, projectId int64) Ma
return role
}
func (database *Database) SetManagerRoleOn(manager *Manager, projectId int64, role ManagerRole) {
db := database.getDB()
res, err := db.Exec(`INSERT INTO manager_has_role_on_project (manager, role, project)
VALUES ($1,$2,$3) ON CONFLICT (manager, project) DO UPDATE SET role=$2`,
manager.Id, role, projectId)
handleErr(err)
rowsAffected, _ := res.RowsAffected()
logrus.WithFields(logrus.Fields{
"role": role,
"manager": manager.Username,
"rowsAffected": rowsAffected,
"project": projectId,
}).Info("Set manager role on project")
}
func (database *Database) GetAllManagers() *[]Manager {
db := database.getDB()

View File

@ -127,13 +127,13 @@ func (database *Database) UpdateProject(project *Project) error {
return nil
}
func (database Database) GetAllProjects(workerId int64) *[]Project {
func (database Database) GetAllProjects(managerId int64) *[]Project {
projects := make([]Project, 0)
db := database.getDB()
var rows *sql.Rows
var err error
if workerId == 0 {
if managerId == 0 {
rows, err = db.Query(`SELECT
Id, priority, name, clone_url, git_repo, version, motd, public, hidden, COALESCE(chain,0)
FROM project
@ -143,9 +143,9 @@ func (database Database) GetAllProjects(workerId int64) *[]Project {
rows, err = db.Query(`SELECT
Id, priority, name, clone_url, git_repo, version, motd, public, hidden, COALESCE(chain,0)
FROM project
LEFT JOIN worker_has_access_to_project whatp ON whatp.project = id
WHERE NOT hidden OR whatp.worker = $1
ORDER BY name`, workerId)
LEFT JOIN manager_has_role_on_project mhrop ON mhrop.project = id AND mhrop.manager=$1
WHERE NOT hidden OR mhrop.role & 1 = 1 OR (SELECT tracker_admin FROM manager WHERE id=$1)
ORDER BY name`, managerId)
}
handleErr(err)

View File

@ -1,11 +1,14 @@
package test
import (
"bytes"
"encoding/json"
"github.com/simon987/task_tracker/api"
"github.com/simon987/task_tracker/config"
"golang.org/x/net/publicsuffix"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"testing"
)
@ -142,7 +145,7 @@ func TestInvalidCredentialsLogin(t *testing.T) {
func register(request *api.RegisterRequest) *api.RegisterResponse {
r := Post("/register", request, nil)
r := Post("/register", request, nil, nil)
resp := &api.RegisterResponse{}
data, _ := ioutil.ReadAll(r.Body)
@ -154,7 +157,7 @@ func register(request *api.RegisterRequest) *api.RegisterResponse {
func login(request *api.LoginRequest) (*api.LoginResponse, *http.Response) {
r := Post("/login", request, nil)
r := Post("/login", request, nil, nil)
resp := &api.LoginResponse{}
data, _ := ioutil.ReadAll(r.Body)
@ -164,6 +167,34 @@ func login(request *api.LoginRequest) (*api.LoginResponse, *http.Response) {
return resp, r
}
func getSessionCtx(username string, password string, admin bool) {
func getSessionCtx(username string, password string, admin bool) *http.Client {
register(&api.RegisterRequest{
Username: username,
Password: password,
})
if admin {
manager, _ := testApi.Database.ValidateCredentials([]byte(username), []byte(password))
manager.WebsiteAdmin = true
testApi.Database.UpdateManager(manager)
}
body, err := json.Marshal(api.LoginRequest{
Username: username,
Password: password,
})
buf := bytes.NewBuffer(body)
req, err := http.NewRequest("POST", "http://"+config.Cfg.ServerAddr+"/login", buf)
handleErr(err)
jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
client := &http.Client{
Jar: jar,
}
_, err = client.Do(req)
handleErr(err)
return client
}

View File

@ -13,7 +13,7 @@ import (
func TestWebHookNoSignature(t *testing.T) {
r := Post("/git/receivehook", api.GitPayload{}, nil)
r := Post("/git/receivehook", api.GitPayload{}, nil, nil)
if r.StatusCode != 403 {
t.Error()
@ -35,7 +35,7 @@ func TestWebHookInvalidSignature(t *testing.T) {
func TestWebHookDontUpdateVersion(t *testing.T) {
resp := createProject(api.CreateProjectRequest{
resp := createProjectAsAdmin(api.CreateProjectRequest{
Name: "My version should not be updated",
Version: "old",
GitRepo: "username/not_this_one",
@ -59,7 +59,7 @@ func TestWebHookDontUpdateVersion(t *testing.T) {
t.Error()
}
getResp, _ := getProject(resp.Id)
getResp, _ := getProjectAsAdmin(resp.Id)
if getResp.Project.Version != "old" {
t.Error()
@ -67,7 +67,7 @@ func TestWebHookDontUpdateVersion(t *testing.T) {
}
func TestWebHookUpdateVersion(t *testing.T) {
resp := createProject(api.CreateProjectRequest{
resp := createProjectAsAdmin(api.CreateProjectRequest{
Name: "My version should be updated",
Version: "old",
GitRepo: "username/repo_name",
@ -91,7 +91,7 @@ func TestWebHookUpdateVersion(t *testing.T) {
t.Error()
}
getResp, _ := getProject(resp.Id)
getResp, _ := getProjectAsAdmin(resp.Id)
if getResp.Project.Version != "new" {
t.Error()

View File

@ -9,7 +9,7 @@ import (
func TestIndex(t *testing.T) {
r := Get("/", nil)
r := Get("/", nil, nil)
body, _ := ioutil.ReadAll(r.Body)
var info api.Info

View File

@ -18,7 +18,7 @@ func TestTraceValid(t *testing.T) {
Scope: "test",
Message: "This is a test message",
TimeStamp: time.Now().Unix(),
}, w)
}, w, nil)
if r.StatusCode != 200 {
t.Fail()
@ -30,7 +30,7 @@ func TestTraceInvalidScope(t *testing.T) {
r := Post("/log/trace", api.LogRequest{
Message: "this is a test message",
TimeStamp: time.Now().Unix(),
}, w)
}, w, nil)
if r.StatusCode == 200 {
t.Error()
@ -40,7 +40,7 @@ func TestTraceInvalidScope(t *testing.T) {
Scope: "",
Message: "this is a test message",
TimeStamp: time.Now().Unix(),
}, w)
}, w, nil)
if r.StatusCode == 200 {
t.Error()
@ -56,7 +56,7 @@ func TestTraceInvalidMessage(t *testing.T) {
Scope: "test",
Message: "",
TimeStamp: time.Now().Unix(),
}, w)
}, w, nil)
if r.StatusCode == 200 {
t.Error()
@ -71,7 +71,7 @@ func TestTraceInvalidTime(t *testing.T) {
r := Post("/log/trace", api.LogRequest{
Scope: "test",
Message: "test",
}, w)
}, w, nil)
if r.StatusCode == 200 {
t.Error()
}
@ -87,7 +87,7 @@ func TestWarnValid(t *testing.T) {
Scope: "test",
Message: "test",
TimeStamp: time.Now().Unix(),
}, w)
}, w, nil)
if r.StatusCode != 200 {
t.Fail()
}
@ -100,7 +100,7 @@ func TestInfoValid(t *testing.T) {
Scope: "test",
Message: "test",
TimeStamp: time.Now().Unix(),
}, w)
}, w, nil)
if r.StatusCode != 200 {
t.Fail()
}
@ -113,7 +113,7 @@ func TestErrorValid(t *testing.T) {
Scope: "test",
Message: "test",
TimeStamp: time.Now().Unix(),
}, w)
}, w, nil)
if r.StatusCode != 200 {
t.Fail()
}
@ -179,7 +179,7 @@ func getLogs(since int64, level storage.LogLevel) *api.GetLogResponse {
r := Post(fmt.Sprintf("/logs"), api.GetLogRequest{
Since: since,
Level: level,
}, nil)
}, nil, nil)
resp := &api.GetLogResponse{}
data, _ := ioutil.ReadAll(r.Body)

View File

@ -11,7 +11,7 @@ import (
func TestCreateGetProject(t *testing.T) {
resp := createProject(api.CreateProjectRequest{
resp := createProjectAsAdmin(api.CreateProjectRequest{
Name: "Test name",
CloneUrl: "http://github.com/test/test",
GitRepo: "drone/webhooktest",
@ -19,7 +19,7 @@ func TestCreateGetProject(t *testing.T) {
Priority: 123,
Motd: "motd",
Public: true,
Hidden: true,
Hidden: false,
})
id := resp.Id
@ -31,7 +31,7 @@ func TestCreateGetProject(t *testing.T) {
t.Fail()
}
getResp, _ := getProject(id)
getResp, _ := getProjectAsAdmin(id)
if getResp.Project.Id != id {
t.Error()
@ -60,13 +60,13 @@ func TestCreateGetProject(t *testing.T) {
if getResp.Project.Public != true {
t.Error()
}
if getResp.Project.Hidden != true {
if getResp.Project.Hidden != false {
t.Error()
}
}
func TestCreateProjectInvalid(t *testing.T) {
resp := createProject(api.CreateProjectRequest{})
resp := createProjectAsAdmin(api.CreateProjectRequest{})
if resp.Ok != false {
t.Fail()
@ -74,10 +74,10 @@ func TestCreateProjectInvalid(t *testing.T) {
}
func TestCreateDuplicateProjectName(t *testing.T) {
createProject(api.CreateProjectRequest{
createProjectAsAdmin(api.CreateProjectRequest{
Name: "duplicate name",
})
resp := createProject(api.CreateProjectRequest{
resp := createProjectAsAdmin(api.CreateProjectRequest{
Name: "duplicate name",
})
@ -91,11 +91,11 @@ func TestCreateDuplicateProjectName(t *testing.T) {
}
func TestCreateDuplicateProjectRepo(t *testing.T) {
createProject(api.CreateProjectRequest{
createProjectAsAdmin(api.CreateProjectRequest{
Name: "different name",
GitRepo: "user/same",
})
resp := createProject(api.CreateProjectRequest{
resp := createProjectAsAdmin(api.CreateProjectRequest{
Name: "but same repo",
GitRepo: "user/same",
})
@ -111,7 +111,7 @@ func TestCreateDuplicateProjectRepo(t *testing.T) {
func TestGetProjectNotFound(t *testing.T) {
getResp, r := getProject(12345)
getResp, r := getProjectAsAdmin(12345)
if getResp.Ok != false {
t.Fail()
@ -128,7 +128,7 @@ func TestGetProjectNotFound(t *testing.T) {
func TestUpdateProjectValid(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Public: true,
Version: "versionA",
Motd: "MotdA",
@ -146,13 +146,13 @@ func TestUpdateProjectValid(t *testing.T) {
Motd: "MotdB",
Public: false,
Hidden: true,
}, pid)
}, pid, testAdminCtx)
if updateResp.Ok != true {
t.Error()
}
proj, _ := getProject(pid)
proj, _ := getProjectAsAdmin(pid)
if proj.Project.Public != false {
t.Error()
@ -176,7 +176,7 @@ func TestUpdateProjectValid(t *testing.T) {
func TestUpdateProjectInvalid(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Public: true,
Version: "lllllllllllll",
Motd: "2wwwwwwwwwwwwwww",
@ -193,7 +193,7 @@ func TestUpdateProjectInvalid(t *testing.T) {
Name: "NameB-0",
Motd: "MotdB000000",
Public: false,
}, pid)
}, pid, testAdminCtx)
if updateResp.Ok != false {
t.Error()
@ -206,7 +206,7 @@ func TestUpdateProjectInvalid(t *testing.T) {
func TestUpdateProjectConstraintFail(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Public: true,
Version: "testUpdateProjectConstraintFail",
Motd: "testUpdateProjectConstraintFail",
@ -216,7 +216,7 @@ func TestUpdateProjectConstraintFail(t *testing.T) {
Priority: 1,
}).Id
createProject(api.CreateProjectRequest{
createProjectAsAdmin(api.CreateProjectRequest{
Public: true,
Version: "testUpdateProjectConstraintFail_d",
Motd: "testUpdateProjectConstraintFail_d",
@ -232,7 +232,7 @@ func TestUpdateProjectConstraintFail(t *testing.T) {
CloneUrl: "testUpdateProjectConstraintFail_d",
Name: "testUpdateProjectConstraintFail_d",
Motd: "testUpdateProjectConstraintFail_d",
}, pid)
}, pid, testAdminCtx)
if updateResp.Ok != false {
t.Error()
@ -243,9 +243,215 @@ func TestUpdateProjectConstraintFail(t *testing.T) {
}
}
func createProject(req api.CreateProjectRequest) *api.CreateProjectResponse {
func TestNotLoggedProjectCreate(t *testing.T) {
r := Post("/project/create", req, nil)
r := createProject(api.CreateProjectRequest{
Hidden: false,
Name: "testnotlogged",
Priority: 1,
CloneUrl: "testnotlogged",
GitRepo: "testnotlogged",
}, nil)
if r.Ok != false {
t.Error()
}
if len(r.Message) <= 0 {
t.Error()
}
}
func TestUserCanCreatePrivateProject(t *testing.T) {
r := createProject(api.CreateProjectRequest{
Hidden: false,
Name: "testuserprivate",
Priority: 1,
CloneUrl: "testuserprivate",
GitRepo: "testuserprivate",
Public: false,
}, testUserCtx)
if r.Ok != true {
t.Error()
}
}
func TestUserCannotCreatePublicProject(t *testing.T) {
r := createProject(api.CreateProjectRequest{
Hidden: false,
Name: "testuserprivate",
Priority: 1,
CloneUrl: "testuserprivate",
GitRepo: "testuserprivate",
Public: true,
}, testUserCtx)
if r.Ok != false {
t.Error()
}
if len(r.Message) <= 0 {
t.Error()
}
}
func TestHiddenProjectsNotShownInList(t *testing.T) {
r := createProject(api.CreateProjectRequest{
Hidden: true,
Name: "testhiddenprojectlist",
Priority: 1,
CloneUrl: "testhiddenprojectlist",
GitRepo: "testhiddenprojectlist",
Public: false,
}, testUserCtx)
if r.Ok != true {
t.Error()
}
list := getProjectList(nil)
for _, p := range *list.Projects {
if p.Id == r.Id {
t.Error()
}
}
}
func TestHiddenProjectCannotBePublic(t *testing.T) {
r := createProject(api.CreateProjectRequest{
Hidden: true,
Name: "testhiddencannotbepublic",
Priority: 1,
CloneUrl: "testhiddencannotbepublic",
GitRepo: "testhiddencannotbepublic",
Public: true,
}, testAdminCtx)
if r.Ok != false {
t.Error()
}
if len(r.Message) <= 0 {
t.Error()
}
}
func TestHiddenProjectNotAccessible(t *testing.T) {
otherUser := getSessionCtx("otheruser", "otheruser", false)
r := createProject(api.CreateProjectRequest{
Hidden: true,
Name: "testhiddenprojectaccess",
Priority: 1,
CloneUrl: "testhiddenprojectaccess",
GitRepo: "testhiddenprojectaccess",
Public: false,
}, testUserCtx)
if r.Ok != true {
t.Error()
}
pAdmin, _ := getProject(r.Id, testAdminCtx)
pUser, _ := getProject(r.Id, testUserCtx)
pOtherUser, _ := getProject(r.Id, otherUser)
pGuest, _ := getProject(r.Id, nil)
if pAdmin.Ok != true {
t.Error()
}
if pUser.Ok != true {
t.Error()
}
if pOtherUser.Ok != false {
t.Error()
}
if pGuest.Ok != false {
t.Error()
}
}
func TestUpdateProjectPermissions(t *testing.T) {
p := createProjectAsAdmin(api.CreateProjectRequest{
GitRepo: "updateprojectpermissions",
CloneUrl: "updateprojectpermissions",
Name: "updateprojectpermissions",
Version: "updateprojectpermissions",
})
r := updateProject(api.UpdateProjectRequest{
GitRepo: "newupdateprojectpermissions",
CloneUrl: "newupdateprojectpermissions",
Name: "newupdateprojectpermissions",
}, p.Id, nil)
if r.Ok != false {
t.Error()
}
if len(r.Message) <= 0 {
t.Error()
}
}
func TestUserWithReadAccessShouldSeeHiddenProjectInList(t *testing.T) {
pHidden := createProject(api.CreateProjectRequest{
GitRepo: "testUserHidden",
CloneUrl: "testUserHidden",
Name: "testUserHidden",
Version: "testUserHidden",
Hidden: true,
}, testUserCtx)
list := getProjectList(testUserCtx)
found := false
for _, p := range *list.Projects {
if p.Id == pHidden.Id {
found = true
}
}
if !found {
t.Error()
}
}
func TestAdminShouldSeeHiddenProjectInList(t *testing.T) {
pHidden := createProject(api.CreateProjectRequest{
GitRepo: "testAdminHidden",
CloneUrl: "testAdminHidden",
Name: "testAdminHidden",
Version: "testAdminHidden",
Hidden: true,
}, testUserCtx)
list := getProjectList(testAdminCtx)
found := false
for _, p := range *list.Projects {
if p.Id == pHidden.Id {
found = true
}
}
if !found {
t.Error()
}
}
func createProjectAsAdmin(req api.CreateProjectRequest) *api.CreateProjectResponse {
return createProject(req, testAdminCtx)
}
func createProject(req api.CreateProjectRequest, s *http.Client) *api.CreateProjectResponse {
r := Post("/project/create", req, nil, s)
var resp api.CreateProjectResponse
data, _ := ioutil.ReadAll(r.Body)
@ -255,9 +461,13 @@ func createProject(req api.CreateProjectRequest) *api.CreateProjectResponse {
return &resp
}
func getProject(id int64) (*api.GetProjectResponse, *http.Response) {
func getProjectAsAdmin(id int64) (*api.GetProjectResponse, *http.Response) {
return getProject(id, testAdminCtx)
}
r := Get(fmt.Sprintf("/project/get/%d", id), nil)
func getProject(id int64, s *http.Client) (*api.GetProjectResponse, *http.Response) {
r := Get(fmt.Sprintf("/project/get/%d", id), nil, s)
var getResp api.GetProjectResponse
data, _ := ioutil.ReadAll(r.Body)
@ -267,9 +477,9 @@ func getProject(id int64) (*api.GetProjectResponse, *http.Response) {
return &getResp, r
}
func updateProject(request api.UpdateProjectRequest, pid int64) *api.UpdateProjectResponse {
func updateProject(request api.UpdateProjectRequest, pid int64, s *http.Client) *api.UpdateProjectResponse {
r := Post(fmt.Sprintf("/project/update/%d", pid), request, nil)
r := Post(fmt.Sprintf("/project/update/%d", pid), request, nil, s)
var resp api.UpdateProjectResponse
data, _ := ioutil.ReadAll(r.Body)
@ -278,3 +488,14 @@ func updateProject(request api.UpdateProjectRequest, pid int64) *api.UpdateProje
return &resp
}
func getProjectList(s *http.Client) *api.GetAllProjectsResponse {
r := Get("/project/list", nil, s)
var resp api.GetAllProjectsResponse
data, _ := ioutil.ReadAll(r.Body)
err := json.Unmarshal(data, &resp)
handleErr(err)
return &resp
}

View File

@ -10,7 +10,7 @@ import (
func BenchmarkCreateTaskRemote(b *testing.B) {
resp := createProject(api.CreateProjectRequest{
resp := createProjectAsAdmin(api.CreateProjectRequest{
Name: "BenchmarkCreateTask" + strconv.Itoa(b.N),
GitRepo: "benchmark_test" + strconv.Itoa(b.N),
Version: "f09e8c9r0w839x0c43",

View File

@ -12,7 +12,7 @@ import (
func TestCreateTaskValid(t *testing.T) {
//Make sure there is always a project for id:1
createProject(api.CreateProjectRequest{
createProjectAsAdmin(api.CreateProjectRequest{
Name: "Some Test name",
Version: "Test Version",
CloneUrl: "http://github.com/test/test",
@ -133,7 +133,7 @@ func TestCreateTaskInvalidRecipe(t *testing.T) {
func TestCreateGetTask(t *testing.T) {
//Make sure there is always a project for id:1
resp := createProject(api.CreateProjectRequest{
resp := createProjectAsAdmin(api.CreateProjectRequest{
Name: "My project",
Version: "1.0",
CloneUrl: "http://github.com/test/test",
@ -194,7 +194,7 @@ func TestCreateGetTask(t *testing.T) {
func createTasks(prefix string) (int64, int64) {
lowP := createProject(api.CreateProjectRequest{
lowP := createProjectAsAdmin(api.CreateProjectRequest{
Name: prefix + "low",
Version: "1.0",
CloneUrl: "http://github.com/test/test",
@ -202,7 +202,7 @@ func createTasks(prefix string) (int64, int64) {
Priority: 1,
Public: true,
})
highP := createProject(api.CreateProjectRequest{
highP := createProjectAsAdmin(api.CreateProjectRequest{
Name: prefix + "high",
Version: "1.0",
CloneUrl: "http://github.com/test/test",
@ -293,7 +293,7 @@ func TestTaskNoAccess(t *testing.T) {
worker := genWid()
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Name: "This is a private proj",
Motd: "private",
Version: "private",
@ -335,7 +335,7 @@ func TestTaskHasAccess(t *testing.T) {
worker := genWid()
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Name: "This is a private proj1",
Motd: "private1",
Version: "private1",
@ -382,7 +382,7 @@ func TestReleaseTaskSuccess(t *testing.T) {
worker := genWid()
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Priority: 0,
GitRepo: "testreleasetask",
CloneUrl: "lllllllll",
@ -420,7 +420,7 @@ func TestReleaseTaskSuccess(t *testing.T) {
func TestCreateIntCollision(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Priority: 1,
GitRepo: "testcreateintcollision",
CloneUrl: "testcreateintcollision",
@ -460,7 +460,7 @@ func TestCreateIntCollision(t *testing.T) {
func TestCreateStringCollision(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Priority: 1,
GitRepo: "testcreatestringcollision",
CloneUrl: "testcreatestringcollision",
@ -509,7 +509,7 @@ func TestCreateStringCollision(t *testing.T) {
func TestCannotVerifySameTaskTwice(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Priority: 1,
GitRepo: "verifysametasktwice",
CloneUrl: "verifysametasktwice",
@ -547,7 +547,7 @@ func TestCannotVerifySameTaskTwice(t *testing.T) {
func TestVerification2(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Priority: 1,
GitRepo: "verify2",
CloneUrl: "verify2",
@ -603,7 +603,7 @@ func TestVerification2(t *testing.T) {
func TestReleaseTaskFail(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Priority: 1,
GitRepo: "releasefail",
CloneUrl: "releasefail",
@ -643,14 +643,14 @@ func TestTaskChain(t *testing.T) {
w := genWid()
p1 := createProject(api.CreateProjectRequest{
p1 := createProjectAsAdmin(api.CreateProjectRequest{
Name: "testtaskchain1",
Public: true,
GitRepo: "testtaskchain1",
CloneUrl: "testtaskchain1",
}).Id
p2 := createProject(api.CreateProjectRequest{
p2 := createProjectAsAdmin(api.CreateProjectRequest{
Name: "testtaskchain2",
Public: true,
GitRepo: "testtaskchain2",
@ -692,7 +692,7 @@ func TestTaskChain(t *testing.T) {
func createTask(request api.CreateTaskRequest, worker *storage.Worker) *api.CreateTaskResponse {
r := Post("/task/create", request, worker)
r := Post("/task/create", request, worker, nil)
var resp api.CreateTaskResponse
data, _ := ioutil.ReadAll(r.Body)
@ -704,7 +704,7 @@ func createTask(request api.CreateTaskRequest, worker *storage.Worker) *api.Crea
func getTask(worker *storage.Worker) *api.GetTaskResponse {
r := Get(fmt.Sprintf("/task/get"), worker)
r := Get(fmt.Sprintf("/task/get"), worker, nil)
var resp api.GetTaskResponse
data, _ := ioutil.ReadAll(r.Body)
@ -716,7 +716,7 @@ func getTask(worker *storage.Worker) *api.GetTaskResponse {
func getTaskFromProject(project int64, worker *storage.Worker) *api.GetTaskResponse {
r := Get(fmt.Sprintf("/task/get/%d", project), worker)
r := Get(fmt.Sprintf("/task/get/%d", project), worker, nil)
var resp api.GetTaskResponse
data, _ := ioutil.ReadAll(r.Body)
@ -728,7 +728,7 @@ func getTaskFromProject(project int64, worker *storage.Worker) *api.GetTaskRespo
func releaseTask(request api.ReleaseTaskRequest, worker *storage.Worker) *api.ReleaseTaskResponse {
r := Post("/task/release", request, worker)
r := Post("/task/release", request, worker, nil)
var resp api.ReleaseTaskResponse
data, _ := ioutil.ReadAll(r.Body)

View File

@ -95,7 +95,7 @@ func TestRemoveAccessFailedProjectConstraint(t *testing.T) {
func TestRemoveAccessFailedWorkerConstraint(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Priority: 1,
GitRepo: "dfffffffffff",
CloneUrl: "fffffffffff23r",
@ -117,7 +117,7 @@ func TestRemoveAccessFailedWorkerConstraint(t *testing.T) {
func TestGrantAccessFailedWorkerConstraint(t *testing.T) {
pid := createProject(api.CreateProjectRequest{
pid := createProjectAsAdmin(api.CreateProjectRequest{
Priority: 1,
GitRepo: "dfffffffffff1",
CloneUrl: "fffffffffff23r1",
@ -173,7 +173,7 @@ func TestCreateWorkerAliasInvalid(t *testing.T) {
}
func createWorker(req api.CreateWorkerRequest) (*api.CreateWorkerResponse, *http.Response) {
r := Post("/worker/create", req, nil)
r := Post("/worker/create", req, nil, nil)
var resp *api.CreateWorkerResponse
data, _ := ioutil.ReadAll(r.Body)
@ -185,7 +185,7 @@ func createWorker(req api.CreateWorkerRequest) (*api.CreateWorkerResponse, *http
func getWorker(id int64) (*api.GetWorkerResponse, *http.Response) {
r := Get(fmt.Sprintf("/worker/get/%d", id), nil)
r := Get(fmt.Sprintf("/worker/get/%d", id), nil, nil)
var resp *api.GetWorkerResponse
data, _ := ioutil.ReadAll(r.Body)
@ -206,7 +206,7 @@ func grantAccess(wid int64, project int64) *api.WorkerAccessResponse {
r := Post("/access/grant", api.WorkerAccessRequest{
WorkerId: wid,
ProjectId: project,
}, nil)
}, nil, nil)
var resp *api.WorkerAccessResponse
data, _ := ioutil.ReadAll(r.Body)
@ -221,7 +221,7 @@ func removeAccess(wid int64, project int64) *api.WorkerAccessResponse {
r := Post("/access/remove", api.WorkerAccessRequest{
WorkerId: wid,
ProjectId: project,
}, nil)
}, nil, nil)
var resp *api.WorkerAccessResponse
data, _ := ioutil.ReadAll(r.Body)
@ -233,7 +233,7 @@ func removeAccess(wid int64, project int64) *api.WorkerAccessResponse {
func updateWorker(request api.UpdateWorkerRequest, w *storage.Worker) *api.UpdateWorkerResponse {
r := Post("/worker/update", request, w)
r := Post("/worker/update", request, w, nil)
var resp *api.UpdateWorkerResponse
data, _ := ioutil.ReadAll(r.Body)

View File

@ -19,7 +19,11 @@ type SessionContext struct {
SessionCookie *http.Cookie
}
func Post(path string, x interface{}, worker *storage.Worker) *http.Response {
func Post(path string, x interface{}, worker *storage.Worker, s *http.Client) *http.Response {
if s == nil {
s = &http.Client{}
}
body, err := json.Marshal(x)
buf := bytes.NewBuffer(body)
@ -36,14 +40,17 @@ func Post(path string, x interface{}, worker *storage.Worker) *http.Response {
req.Header.Add("X-Signature", sig)
}
client := http.Client{}
r, err := client.Do(req)
r, err := s.Do(req)
handleErr(err)
return r
}
func Get(path string, worker *storage.Worker) *http.Response {
func Get(path string, worker *storage.Worker, s *http.Client) *http.Response {
if s == nil {
s = &http.Client{}
}
url := "http://" + config.Cfg.ServerAddr + path
req, err := http.NewRequest("GET", url, nil)
@ -58,8 +65,7 @@ func Get(path string, worker *storage.Worker) *http.Response {
req.Header.Add("X-Signature", sig)
}
client := http.Client{}
r, err := client.Do(req)
r, err := s.Do(req)
handleErr(err)
return r

View File

@ -3,19 +3,28 @@ package test
import (
"github.com/simon987/task_tracker/api"
"github.com/simon987/task_tracker/config"
"net/http"
"testing"
"time"
)
var testApi *api.WebAPI
var testAdminCtx *http.Client
var testUserCtx *http.Client
func TestMain(m *testing.M) {
config.SetupConfig()
testApi := api.New()
testApi = api.New()
testApi.SetupLogger()
testApi.Database.Reset()
go testApi.Run()
time.Sleep(time.Millisecond * 100)
testAdminCtx = getSessionCtx("testadmin", "testadmin", true)
testUserCtx = getSessionCtx("testuser", "testuser", false)
m.Run()
}

View File

@ -79,8 +79,9 @@ CREATE TABLE manager
CREATE TABLE manager_has_role_on_project
(
manager INTEGER REFERENCES manager (id) NOT NULL,
role SMALLINT NOT NULl,
project INTEGER REFERENCES project (id) NOT NULL
role SMALLINT NOT NULL,
project INTEGER REFERENCES project (id) NOT NULL,
primary key (manager, project)
);
CREATE TABLE project_monitoring_snapshot

View File

@ -8,4 +8,5 @@ export interface Project {
version: string;
public: boolean;
chain: number;
hidden: boolean;
}

View File

@ -13,8 +13,11 @@
<mat-expansion-panel *ngFor="let project of projects" style="margin-top: 1em">
<mat-expansion-panel-header>
<mat-panel-title>
<mat-icon *ngIf="project.public">public</mat-icon>
<mat-icon *ngIf="!project.public">lock</mat-icon>
<mat-icon *ngIf="project.public" [title]="'project.public' | translate">public</mat-icon>
<mat-icon *ngIf="!project.public && !project.hidden" [title]="'project.private'|translate">
lock
</mat-icon>
<mat-icon *ngIf="project.hidden" [title]="'project.hidden'|translate">block</mat-icon>
<span style="width: 3em">{{project.id}}</span>{{project.name}}
</mat-panel-title>
<mat-panel-description>{{project.motd}}</mat-panel-description>

View File

@ -58,6 +58,8 @@
"create_title": "Create new project",
"create_subtitle": "Todo: subtitle",
"public": "Public",
"private": "Private",
"hidden": "Hidden",
"create": "Create",
"git_repo": "Git repository name",
"motd": "Message of the day",

View File

@ -60,6 +60,8 @@
"create_title": "Créer un nouveau projet",
"create_subtitle": "todo: sous-titre",
"public": "Publique",
"private": "Privé",
"hidden": "Caché",
"create": "Créer",
"motd": "Message du jour",
"update": "Mettre à jour",