diff --git a/api/project.go b/api/project.go index 88c4049..0947169 100644 --- a/api/project.go +++ b/api/project.go @@ -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, diff --git a/storage/auth.go b/storage/auth.go index 1a5f3f4..7d0722f 100644 --- a/storage/auth.go +++ b/storage/auth.go @@ -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() diff --git a/storage/project.go b/storage/project.go index 84e9d73..b35d600 100644 --- a/storage/project.go +++ b/storage/project.go @@ -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) diff --git a/test/api_auth_test.go b/test/api_auth_test.go index a2da173..1b64ba2 100644 --- a/test/api_auth_test.go +++ b/test/api_auth_test.go @@ -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 } diff --git a/test/api_git_test.go b/test/api_git_test.go index 3eb6730..5d8fe49 100644 --- a/test/api_git_test.go +++ b/test/api_git_test.go @@ -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() diff --git a/test/api_index_test.go b/test/api_index_test.go index 720e294..0f51113 100644 --- a/test/api_index_test.go +++ b/test/api_index_test.go @@ -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 diff --git a/test/api_log_test.go b/test/api_log_test.go index 1d63078..ced4183 100644 --- a/test/api_log_test.go +++ b/test/api_log_test.go @@ -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) diff --git a/test/api_project_test.go b/test/api_project_test.go index cac4703..8e40495 100644 --- a/test/api_project_test.go +++ b/test/api_project_test.go @@ -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 +} diff --git a/test/api_task_bench_test.go b/test/api_task_bench_test.go index 5fe23c9..f13d509 100644 --- a/test/api_task_bench_test.go +++ b/test/api_task_bench_test.go @@ -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", diff --git a/test/api_task_test.go b/test/api_task_test.go index 9e5b04f..71d9147 100644 --- a/test/api_task_test.go +++ b/test/api_task_test.go @@ -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) diff --git a/test/api_worker_test.go b/test/api_worker_test.go index 4ba1fdc..fd8e8c7 100644 --- a/test/api_worker_test.go +++ b/test/api_worker_test.go @@ -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) diff --git a/test/common.go b/test/common.go index 62b4f9d..f74780a 100644 --- a/test/common.go +++ b/test/common.go @@ -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 diff --git a/test/main_test.go b/test/main_test.go index a47bd06..c36c9d7 100644 --- a/test/main_test.go +++ b/test/main_test.go @@ -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() } diff --git a/test/schema.sql b/test/schema.sql index b7fbafe..b0344d4 100755 --- a/test/schema.sql +++ b/test/schema.sql @@ -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 diff --git a/web/angular/src/app/models/project.ts b/web/angular/src/app/models/project.ts index 3c687f8..4d77415 100644 --- a/web/angular/src/app/models/project.ts +++ b/web/angular/src/app/models/project.ts @@ -8,4 +8,5 @@ export interface Project { version: string; public: boolean; chain: number; + hidden: boolean; } diff --git a/web/angular/src/app/project-list/project-list.component.html b/web/angular/src/app/project-list/project-list.component.html index f0c4937..a1f3afe 100755 --- a/web/angular/src/app/project-list/project-list.component.html +++ b/web/angular/src/app/project-list/project-list.component.html @@ -13,8 +13,11 @@ - public - lock + public + + lock + + block {{project.id}}{{project.name}} {{project.motd}} diff --git a/web/angular/src/assets/i18n/en.json b/web/angular/src/assets/i18n/en.json index 9a1feed..3b245af 100644 --- a/web/angular/src/assets/i18n/en.json +++ b/web/angular/src/assets/i18n/en.json @@ -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", diff --git a/web/angular/src/assets/i18n/fr.json b/web/angular/src/assets/i18n/fr.json index 1eae8be..ca6cd99 100644 --- a/web/angular/src/assets/i18n/fr.json +++ b/web/angular/src/assets/i18n/fr.json @@ -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",