mirror of
https://github.com/simon987/task_tracker.git
synced 2025-04-20 10:36:46 +00:00
Add project secret & bug fix
This commit is contained in:
parent
94c3ce3267
commit
f235bfb588
@ -91,6 +91,8 @@ func New() *WebAPI {
|
|||||||
api.router.POST("/project/request_access", LogRequestMiddleware(api.CreateWorkerAccess))
|
api.router.POST("/project/request_access", LogRequestMiddleware(api.CreateWorkerAccess))
|
||||||
api.router.POST("/project/accept_request/:id/:wid", LogRequestMiddleware(api.AcceptAccessRequest))
|
api.router.POST("/project/accept_request/:id/:wid", LogRequestMiddleware(api.AcceptAccessRequest))
|
||||||
api.router.POST("/project/reject_request/:id/:wid", LogRequestMiddleware(api.RejectAccessRequest))
|
api.router.POST("/project/reject_request/:id/:wid", LogRequestMiddleware(api.RejectAccessRequest))
|
||||||
|
api.router.GET("/project/secret/:id", LogRequestMiddleware(api.GetSecret))
|
||||||
|
api.router.POST("/project/secret/:id", LogRequestMiddleware(api.SetSecret))
|
||||||
|
|
||||||
api.router.POST("/task/submit", LogRequestMiddleware(api.SubmitTask))
|
api.router.POST("/task/submit", LogRequestMiddleware(api.SubmitTask))
|
||||||
api.router.GET("/task/get/:project", LogRequestMiddleware(api.GetTaskFromProject))
|
api.router.GET("/task/get/:project", LogRequestMiddleware(api.GetTaskFromProject))
|
||||||
|
@ -214,6 +214,10 @@ type ReleaseTaskRequest struct {
|
|||||||
Verification int64 `json:"verification"`
|
Verification int64 `json:"verification"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ReleaseTaskRequest) IsValid() bool {
|
||||||
|
return r.TaskId != 0
|
||||||
|
}
|
||||||
|
|
||||||
type ReleaseTaskResponse struct {
|
type ReleaseTaskResponse struct {
|
||||||
Updated bool `json:"updated"`
|
Updated bool `json:"updated"`
|
||||||
}
|
}
|
||||||
@ -276,3 +280,11 @@ type Info struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SetSecretRequest struct {
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetSecretResponse struct {
|
||||||
|
Secret string `json:"secret"`
|
||||||
|
}
|
||||||
|
156
api/project.go
156
api/project.go
@ -10,7 +10,13 @@ import (
|
|||||||
func (api *WebAPI) GetProject(r *Request) {
|
func (api *WebAPI) GetProject(r *Request) {
|
||||||
|
|
||||||
id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
||||||
handleErr(err, r) //todo handle invalid id
|
if err != nil || id <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid worker id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sess := api.Session.StartFasthttp(r.Ctx)
|
sess := api.Session.StartFasthttp(r.Ctx)
|
||||||
manager := sess.Get("manager")
|
manager := sess.Get("manager")
|
||||||
@ -263,7 +269,13 @@ func (api *WebAPI) GetProjectList(r *Request) {
|
|||||||
func (api *WebAPI) GetAssigneeStatsForProject(r *Request) {
|
func (api *WebAPI) GetAssigneeStatsForProject(r *Request) {
|
||||||
|
|
||||||
id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
||||||
handleErr(err, r) //todo handle invalid id
|
if err != nil || id <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid worker id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
stats := api.Database.GetAssigneeStats(id, 16)
|
stats := api.Database.GetAssigneeStats(id, 16)
|
||||||
|
|
||||||
@ -281,7 +293,13 @@ func (api *WebAPI) GetWorkerAccessListForProject(r *Request) {
|
|||||||
manager := sess.Get("manager")
|
manager := sess.Get("manager")
|
||||||
|
|
||||||
id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
||||||
handleErr(err, r) //todo handle invalid id
|
if err != nil || id <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid worker id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !isActionOnProjectAuthorized(id, manager, storage.ROLE_MANAGE_ACCESS, api.Database) {
|
if !isActionOnProjectAuthorized(id, manager, storage.ROLE_MANAGE_ACCESS, api.Database) {
|
||||||
r.Json(JsonResponse{
|
r.Json(JsonResponse{
|
||||||
@ -352,10 +370,22 @@ func (api *WebAPI) CreateWorkerAccess(r *Request) {
|
|||||||
func (api *WebAPI) AcceptAccessRequest(r *Request) {
|
func (api *WebAPI) AcceptAccessRequest(r *Request) {
|
||||||
|
|
||||||
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
||||||
handleErr(err, r) //todo handle invalid id
|
if err != nil || pid <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid worker id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
wid, err := strconv.ParseInt(r.Ctx.UserValue("wid").(string), 10, 64)
|
wid, err := strconv.ParseInt(r.Ctx.UserValue("wid").(string), 10, 64)
|
||||||
handleErr(err, r) //todo handle invalid id
|
if err != nil || wid <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid worker id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
sess := api.Session.StartFasthttp(r.Ctx)
|
sess := api.Session.StartFasthttp(r.Ctx)
|
||||||
manager := sess.Get("manager")
|
manager := sess.Get("manager")
|
||||||
@ -385,10 +415,22 @@ func (api *WebAPI) AcceptAccessRequest(r *Request) {
|
|||||||
func (api *WebAPI) RejectAccessRequest(r *Request) {
|
func (api *WebAPI) RejectAccessRequest(r *Request) {
|
||||||
|
|
||||||
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
||||||
handleErr(err, r) //todo handle invalid id
|
if err != nil || pid <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid project id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
wid, err := strconv.ParseInt(r.Ctx.UserValue("wid").(string), 10, 64)
|
wid, err := strconv.ParseInt(r.Ctx.UserValue("wid").(string), 10, 64)
|
||||||
handleErr(err, r) //todo handle invalid id
|
if err != nil || wid <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid worker id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ok := api.Database.RejectAccessRequest(wid, pid)
|
ok := api.Database.RejectAccessRequest(wid, pid)
|
||||||
|
|
||||||
@ -407,7 +449,13 @@ func (api *WebAPI) RejectAccessRequest(r *Request) {
|
|||||||
func (api *WebAPI) SetManagerRoleOnProject(r *Request) {
|
func (api *WebAPI) SetManagerRoleOnProject(r *Request) {
|
||||||
|
|
||||||
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
||||||
handleErr(err, r) //todo handle invalid id
|
if err != nil || pid <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid project id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
req := &SetManagerRoleOnProjectRequest{}
|
req := &SetManagerRoleOnProjectRequest{}
|
||||||
err = json.Unmarshal(r.Ctx.Request.Body(), req)
|
err = json.Unmarshal(r.Ctx.Request.Body(), req)
|
||||||
@ -435,3 +483,95 @@ func (api *WebAPI) SetManagerRoleOnProject(r *Request) {
|
|||||||
Ok: true,
|
Ok: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *WebAPI) SetSecret(r *Request) {
|
||||||
|
|
||||||
|
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
||||||
|
handleErr(err, r) //todo handle invalid id
|
||||||
|
if err != nil || pid <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid project id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sess := api.Session.StartFasthttp(r.Ctx)
|
||||||
|
manager := sess.Get("manager")
|
||||||
|
|
||||||
|
if !isActionOnProjectAuthorized(pid, manager, storage.ROLE_EDIT, api.Database) {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Unauthorized",
|
||||||
|
}, 403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &SetSecretRequest{}
|
||||||
|
err = json.Unmarshal(r.Ctx.Request.Body(), req)
|
||||||
|
if err != nil {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Could not parse request",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
api.Database.SetSecret(pid, req.Secret)
|
||||||
|
|
||||||
|
r.OkJson(JsonResponse{
|
||||||
|
Ok: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (api *WebAPI) GetSecret(r *Request) {
|
||||||
|
|
||||||
|
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
|
||||||
|
if err != nil || pid <= 0 {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid project id",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var secret string
|
||||||
|
|
||||||
|
worker, err := api.validateSignature(r)
|
||||||
|
if err == nil {
|
||||||
|
secret, err = api.Database.GetSecret(pid, worker.Id)
|
||||||
|
if err != nil {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Unauthorized",
|
||||||
|
}, 403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.OkJson(JsonResponse{
|
||||||
|
Ok: true,
|
||||||
|
Content: GetSecretResponse{
|
||||||
|
Secret: secret,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sess := api.Session.StartFasthttp(r.Ctx)
|
||||||
|
manager := sess.Get("manager")
|
||||||
|
|
||||||
|
if !isActionOnProjectAuthorized(pid, manager, storage.ROLE_EDIT, api.Database) {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Unauthorized",
|
||||||
|
}, 403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
secret, _ = api.Database.GetSecret(pid, 0)
|
||||||
|
r.OkJson(JsonResponse{
|
||||||
|
Ok: true,
|
||||||
|
Content: GetSecretResponse{
|
||||||
|
Secret: secret,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
10
api/task.go
10
api/task.go
@ -209,7 +209,17 @@ func (api *WebAPI) ReleaseTask(r *Request) {
|
|||||||
Ok: false,
|
Ok: false,
|
||||||
Message: "Could not parse request",
|
Message: "Could not parse request",
|
||||||
}, 400)
|
}, 400)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !req.IsValid() {
|
||||||
|
r.Json(JsonResponse{
|
||||||
|
Ok: false,
|
||||||
|
Message: "Invalid request",
|
||||||
|
}, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
res := api.Database.ReleaseTask(req.TaskId, worker.Id, req.Result, req.Verification)
|
res := api.Database.ReleaseTask(req.TaskId, worker.Id, req.Result, req.Verification)
|
||||||
|
|
||||||
response := JsonResponse{
|
response := JsonResponse{
|
||||||
|
@ -3,7 +3,8 @@ server:
|
|||||||
|
|
||||||
database:
|
database:
|
||||||
conn_str: "user=task_tracker dbname=task_tracker_test sslmode=disable"
|
conn_str: "user=task_tracker dbname=task_tracker_test sslmode=disable"
|
||||||
log_levels: ["debug", "error", "trace", "info", "warn"]
|
# log_levels: ["debug", "error", "trace", "info", "warn"]
|
||||||
|
log_levels: ["error", "info", "warn"]
|
||||||
|
|
||||||
git:
|
git:
|
||||||
webhook_secret: "very_secret_secret"
|
webhook_secret: "very_secret_secret"
|
||||||
|
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"github.com/simon987/task_tracker/api"
|
"github.com/simon987/task_tracker/api"
|
||||||
"github.com/simon987/task_tracker/config"
|
"github.com/simon987/task_tracker/config"
|
||||||
|
//"github.com/simon987/task_tracker/storage"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
16
schema.sql
16
schema.sql
@ -1,8 +1,6 @@
|
|||||||
DROP TABLE IF EXISTS worker, project, task, log_entry,
|
DROP TABLE IF EXISTS worker, project, task, log_entry,
|
||||||
worker_access, manager, manager_has_role_on_project, project_monitoring_snapshot,
|
worker_access, manager, manager_has_role_on_project, project_monitoring_snapshot,
|
||||||
worker_verifies_task;
|
worker_verifies_task;
|
||||||
DROP TYPE IF EXISTS status;
|
|
||||||
DROP TYPE IF EXISTS log_level;
|
|
||||||
|
|
||||||
CREATE TABLE worker
|
CREATE TABLE worker
|
||||||
(
|
(
|
||||||
@ -25,7 +23,8 @@ CREATE TABLE project
|
|||||||
clone_url TEXT NOT NULL,
|
clone_url TEXT NOT NULL,
|
||||||
git_repo TEXT UNIQUE NOT NULL,
|
git_repo TEXT UNIQUE NOT NULL,
|
||||||
version TEXT NOT NULL,
|
version TEXT NOT NULL,
|
||||||
motd TEXT NOT NULL
|
motd TEXT NOT NULL,
|
||||||
|
secret TEXT NOT NULL DEFAULT '{}'
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE worker_access
|
CREATE TABLE worker_access
|
||||||
@ -83,7 +82,8 @@ CREATE TABLE manager_has_role_on_project
|
|||||||
(
|
(
|
||||||
manager INTEGER REFERENCES manager (id) NOT NULL,
|
manager INTEGER REFERENCES manager (id) NOT NULL,
|
||||||
role SMALLINT NOT NULL,
|
role SMALLINT NOT NULL,
|
||||||
project INTEGER REFERENCES project (id) NOT NULL
|
project INTEGER REFERENCES project (id) NOT NULL,
|
||||||
|
PRIMARY KEY (manager, project)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE project_monitoring_snapshot
|
CREATE TABLE project_monitoring_snapshot
|
||||||
@ -102,7 +102,10 @@ $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
chain INTEGER;
|
chain INTEGER;
|
||||||
BEGIN
|
BEGIN
|
||||||
UPDATE project SET closed_task_count=closed_task_count + 1 WHERE id = OLD.project returning project.chain into chain;
|
if OLD.assignee IS NOT NULL THEN
|
||||||
|
UPDATE project
|
||||||
|
SET closed_task_count=closed_task_count + 1
|
||||||
|
WHERE id = OLD.project returning project.chain into chain;
|
||||||
UPDATE worker SET closed_task_count=closed_task_count + 1 WHERE id = OLD.assignee;
|
UPDATE worker SET closed_task_count=closed_task_count + 1 WHERE id = OLD.assignee;
|
||||||
IF chain != 0 THEN
|
IF chain != 0 THEN
|
||||||
INSERT into task (hash64, project, assignee, max_assign_time, assign_time, verification_count,
|
INSERT into task (hash64, project, assignee, max_assign_time, assign_time, verification_count,
|
||||||
@ -111,6 +114,7 @@ BEGIN
|
|||||||
old.verification_count, old.priority, 0, old.max_retries, 1,
|
old.verification_count, old.priority, 0, old.max_retries, 1,
|
||||||
old.recipe);
|
old.recipe);
|
||||||
end if;
|
end if;
|
||||||
|
end if;
|
||||||
RETURN OLD;
|
RETURN OLD;
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE 'plpgsql';
|
$$ LANGUAGE 'plpgsql';
|
||||||
@ -135,7 +139,7 @@ CREATE TRIGGER on_manager_insert
|
|||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
EXECUTE PROCEDURE on_manager_insert();
|
EXECUTE PROCEDURE on_manager_insert();
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION release_task_ok(wid INT, tid INT, ver INT) RETURNS BOOLEAN AS
|
CREATE OR REPLACE FUNCTION release_task_ok(wid INT, tid INT, ver BIGINT) RETURNS BOOLEAN AS
|
||||||
$$
|
$$
|
||||||
DECLARE
|
DECLARE
|
||||||
res INT = NULL;
|
res INT = NULL;
|
||||||
|
@ -39,6 +39,8 @@ func (database *Database) getDB() *sql.DB {
|
|||||||
logrus.Fatal(err)
|
logrus.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.SetMaxOpenConns(50)
|
||||||
|
|
||||||
database.db = db
|
database.db = db
|
||||||
} else {
|
} else {
|
||||||
err := database.db.Ping()
|
err := database.db.Ping()
|
||||||
|
@ -192,3 +192,36 @@ func (database *Database) GetAssigneeStats(pid int64, count int64) *[]AssignedTa
|
|||||||
|
|
||||||
return &assignees
|
return &assignees
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (database *Database) GetSecret(pid int64, workerId int64) (secret string, err error) {
|
||||||
|
|
||||||
|
db := database.getDB()
|
||||||
|
|
||||||
|
var row *sql.Row
|
||||||
|
if workerId == 0 {
|
||||||
|
row = db.QueryRow(`SELECT secret FROM project WHERE id=$1`, pid)
|
||||||
|
} else {
|
||||||
|
row = db.QueryRow(`SELECT secret FROM project
|
||||||
|
WHERE id =$1 AND (
|
||||||
|
SELECT a.role_assign FROM worker_access a WHERE a.worker=$2 AND a.project=$1
|
||||||
|
)`, pid, workerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = row.Scan(&secret)
|
||||||
|
handleErr(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (database *Database) SetSecret(pid int64, secret string) {
|
||||||
|
|
||||||
|
db := database.getDB()
|
||||||
|
|
||||||
|
res, err := db.Exec(`UPDATE project SET secret=$1 WHERE id=$2`, secret, pid)
|
||||||
|
handleErr(err)
|
||||||
|
|
||||||
|
rowsAffected, _ := res.RowsAffected()
|
||||||
|
logrus.WithFields(logrus.Fields{
|
||||||
|
"rowsAffected": rowsAffected,
|
||||||
|
"project": pid,
|
||||||
|
}).Info("Set secret")
|
||||||
|
}
|
||||||
|
@ -83,7 +83,7 @@ func (database *Database) GetTask(worker *Worker) *Task {
|
|||||||
INNER JOIN project project on task.project = project.id
|
INNER JOIN project project on task.project = project.id
|
||||||
LEFT JOIN worker_verifies_task wvt on task.id = wvt.task AND wvt.worker=$1
|
LEFT JOIN worker_verifies_task wvt on task.id = wvt.task AND wvt.worker=$1
|
||||||
WHERE assignee IS NULL AND task.status=1
|
WHERE assignee IS NULL AND task.status=1
|
||||||
AND (project.public OR EXISTS (
|
AND (project.public OR (
|
||||||
SELECT a.role_assign FROM worker_access a WHERE a.worker=$1 AND a.project=project.id
|
SELECT a.role_assign FROM worker_access a WHERE a.worker=$1 AND a.project=project.id
|
||||||
))
|
))
|
||||||
AND wvt.task IS NULL
|
AND wvt.task IS NULL
|
||||||
@ -144,9 +144,10 @@ func (database Database) ReleaseTask(id int64, workerId int64, result TaskResult
|
|||||||
|
|
||||||
var taskUpdated bool
|
var taskUpdated bool
|
||||||
if result == TR_OK {
|
if result == TR_OK {
|
||||||
row := db.QueryRow(`SELECT release_task_ok($1,$2,$3)`, workerId, id, verification)
|
row := db.QueryRow(fmt.Sprintf(`SELECT release_task_ok(%d,%d,%d)`, workerId, id, verification))
|
||||||
|
|
||||||
_ = row.Scan(&taskUpdated)
|
err := row.Scan(&taskUpdated)
|
||||||
|
handleErr(err)
|
||||||
} else if result == TR_FAIL {
|
} else if result == TR_FAIL {
|
||||||
res, err := db.Exec(`UPDATE task SET (status, assignee, retries) =
|
res, err := db.Exec(`UPDATE task SET (status, assignee, retries) =
|
||||||
(CASE WHEN retries+1 >= max_retries THEN 2 ELSE 1 END, NULL, retries+1)
|
(CASE WHEN retries+1 >= max_retries THEN 2 ELSE 1 END, NULL, retries+1)
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/simon987/task_tracker/api"
|
"github.com/simon987/task_tracker/api"
|
||||||
"github.com/simon987/task_tracker/storage"
|
"github.com/simon987/task_tracker/storage"
|
||||||
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -780,6 +781,42 @@ func TestTaskChain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTaskReleaseBigInt(t *testing.T) {
|
||||||
|
|
||||||
|
createTask(api.SubmitTaskRequest{
|
||||||
|
Project: testProject,
|
||||||
|
VerificationCount: 1,
|
||||||
|
Recipe: "bigint",
|
||||||
|
}, testWorker)
|
||||||
|
createTask(api.SubmitTaskRequest{
|
||||||
|
Project: testProject,
|
||||||
|
VerificationCount: 1,
|
||||||
|
Recipe: "smallint",
|
||||||
|
}, testWorker)
|
||||||
|
|
||||||
|
tid := getTaskFromProject(testProject, testWorker).Content.Task.Id
|
||||||
|
tid2 := getTaskFromProject(testProject, testWorker).Content.Task.Id
|
||||||
|
|
||||||
|
r := releaseTask(api.ReleaseTaskRequest{
|
||||||
|
Verification: math.MaxInt64,
|
||||||
|
Result: storage.TR_OK,
|
||||||
|
TaskId: tid,
|
||||||
|
}, testWorker)
|
||||||
|
|
||||||
|
r2 := releaseTask(api.ReleaseTaskRequest{
|
||||||
|
Verification: math.MinInt64,
|
||||||
|
Result: storage.TR_OK,
|
||||||
|
TaskId: tid2,
|
||||||
|
}, testWorker)
|
||||||
|
|
||||||
|
if r.Content.Updated != true {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
if r2.Content.Updated != true {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func createTask(request api.SubmitTaskRequest, worker *storage.Worker) (ar api.JsonResponse) {
|
func createTask(request api.SubmitTaskRequest, worker *storage.Worker) (ar api.JsonResponse) {
|
||||||
r := Post("/task/submit", request, worker, nil)
|
r := Post("/task/submit", request, worker, nil)
|
||||||
UnmarshalResponse(r, &ar)
|
UnmarshalResponse(r, &ar)
|
||||||
|
@ -3,6 +3,7 @@ package test
|
|||||||
import (
|
import (
|
||||||
"github.com/simon987/task_tracker/api"
|
"github.com/simon987/task_tracker/api"
|
||||||
"github.com/simon987/task_tracker/config"
|
"github.com/simon987/task_tracker/config"
|
||||||
|
"github.com/simon987/task_tracker/storage"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -12,6 +13,9 @@ var testApi *api.WebAPI
|
|||||||
var testAdminCtx *http.Client
|
var testAdminCtx *http.Client
|
||||||
var testUserCtx *http.Client
|
var testUserCtx *http.Client
|
||||||
|
|
||||||
|
var testProject int64
|
||||||
|
var testWorker *storage.Worker
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
||||||
config.SetupConfig()
|
config.SetupConfig()
|
||||||
@ -25,6 +29,19 @@ func TestMain(m *testing.M) {
|
|||||||
|
|
||||||
testAdminCtx = getSessionCtx("testadmin", "testadmin", true)
|
testAdminCtx = getSessionCtx("testadmin", "testadmin", true)
|
||||||
testUserCtx = getSessionCtx("testuser", "testuser", false)
|
testUserCtx = getSessionCtx("testuser", "testuser", false)
|
||||||
|
testProject = createProjectAsAdmin(api.CreateProjectRequest{
|
||||||
|
Name: "generictestproject",
|
||||||
|
Public: false,
|
||||||
|
}).Content.Id
|
||||||
|
testWorker = createWorker(api.CreateWorkerRequest{
|
||||||
|
Alias: "generictestworker",
|
||||||
|
}).Content.Worker
|
||||||
|
requestAccess(api.CreateWorkerAccessRequest{
|
||||||
|
Project: testProject,
|
||||||
|
Assign: true,
|
||||||
|
Submit: true,
|
||||||
|
}, testWorker)
|
||||||
|
acceptAccessRequest(testProject, testWorker.Id, testAdminCtx)
|
||||||
|
|
||||||
m.Run()
|
m.Run()
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
DROP TABLE IF EXISTS worker, project, task, log_entry,
|
DROP TABLE IF EXISTS worker, project, task, log_entry,
|
||||||
worker_access, manager, manager_has_role_on_project, project_monitoring_snapshot,
|
worker_access, manager, manager_has_role_on_project, project_monitoring_snapshot,
|
||||||
worker_verifies_task;
|
worker_verifies_task;
|
||||||
DROP TYPE IF EXISTS status;
|
|
||||||
DROP TYPE IF EXISTS log_level;
|
|
||||||
|
|
||||||
CREATE TABLE worker
|
CREATE TABLE worker
|
||||||
(
|
(
|
||||||
@ -25,7 +23,8 @@ CREATE TABLE project
|
|||||||
clone_url TEXT NOT NULL,
|
clone_url TEXT NOT NULL,
|
||||||
git_repo TEXT UNIQUE NOT NULL,
|
git_repo TEXT UNIQUE NOT NULL,
|
||||||
version TEXT NOT NULL,
|
version TEXT NOT NULL,
|
||||||
motd TEXT NOT NULL
|
motd TEXT NOT NULL,
|
||||||
|
secret TEXT NOT NULL DEFAULT '{}'
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE worker_access
|
CREATE TABLE worker_access
|
||||||
@ -103,7 +102,10 @@ $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
chain INTEGER;
|
chain INTEGER;
|
||||||
BEGIN
|
BEGIN
|
||||||
UPDATE project SET closed_task_count=closed_task_count + 1 WHERE id = OLD.project returning project.chain into chain;
|
if OLD.assignee IS NOT NULL THEN
|
||||||
|
UPDATE project
|
||||||
|
SET closed_task_count=closed_task_count + 1
|
||||||
|
WHERE id = OLD.project returning project.chain into chain;
|
||||||
UPDATE worker SET closed_task_count=closed_task_count + 1 WHERE id = OLD.assignee;
|
UPDATE worker SET closed_task_count=closed_task_count + 1 WHERE id = OLD.assignee;
|
||||||
IF chain != 0 THEN
|
IF chain != 0 THEN
|
||||||
INSERT into task (hash64, project, assignee, max_assign_time, assign_time, verification_count,
|
INSERT into task (hash64, project, assignee, max_assign_time, assign_time, verification_count,
|
||||||
@ -112,6 +114,7 @@ BEGIN
|
|||||||
old.verification_count, old.priority, 0, old.max_retries, 1,
|
old.verification_count, old.priority, 0, old.max_retries, 1,
|
||||||
old.recipe);
|
old.recipe);
|
||||||
end if;
|
end if;
|
||||||
|
end if;
|
||||||
RETURN OLD;
|
RETURN OLD;
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE 'plpgsql';
|
$$ LANGUAGE 'plpgsql';
|
||||||
@ -136,7 +139,7 @@ CREATE TRIGGER on_manager_insert
|
|||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
EXECUTE PROCEDURE on_manager_insert();
|
EXECUTE PROCEDURE on_manager_insert();
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION release_task_ok(wid INT, tid INT, ver INT) RETURNS BOOLEAN AS
|
CREATE OR REPLACE FUNCTION release_task_ok(wid INT, tid INT, ver BIGINT) RETURNS BOOLEAN AS
|
||||||
$$
|
$$
|
||||||
DECLARE
|
DECLARE
|
||||||
res INT = NULL;
|
res INT = NULL;
|
||||||
|
@ -6,7 +6,7 @@ import {Credentials} from "./models/credentials";
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class ApiService {
|
export class ApiService {
|
||||||
|
|
||||||
private url: string = "http://localhost/api";
|
public url: string = "http://localhost/api";
|
||||||
private options: {
|
private options: {
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
responseType: "json"
|
responseType: "json"
|
||||||
@ -66,36 +66,44 @@ export class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getProjectAccess(project: number) {
|
getProjectAccess(project: number) {
|
||||||
return this.http.get(this.url + `/project/access_list/${project}`)
|
return this.http.get(this.url + `/project/access_list/${project}`, this.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
getManagerList() {
|
getManagerList() {
|
||||||
return this.http.get(this.url + "/manager/list")
|
return this.http.get(this.url + "/manager/list", this.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
getManagerListWithRoleOn(project: number) {
|
getManagerListWithRoleOn(project: number) {
|
||||||
return this.http.get(this.url + "/manager/list_for_project/" + project)
|
return this.http.get(this.url + "/manager/list_for_project/" + project, this.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
promote(managerId: number) {
|
promote(managerId: number) {
|
||||||
return this.http.get(this.url + `/manager/promote/${managerId}`)
|
return this.http.get(this.url + `/manager/promote/${managerId}`, this.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
demote(managerId: number) {
|
demote(managerId: number) {
|
||||||
return this.http.get(this.url + `/manager/demote/${managerId}`)
|
return this.http.get(this.url + `/manager/demote/${managerId}`, this.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptWorkerAccessRequest(wid: number, pid: number) {
|
acceptWorkerAccessRequest(wid: number, pid: number) {
|
||||||
return this.http.post(this.url + `/project/accept_request/${pid}/${wid}`, null)
|
return this.http.post(this.url + `/project/accept_request/${pid}/${wid}`, null, this.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
rejectWorkerAccessRequest(wid: number, pid: number) {
|
rejectWorkerAccessRequest(wid: number, pid: number) {
|
||||||
return this.http.post(this.url + `/project/reject_request/${pid}/${wid}`, null)
|
return this.http.post(this.url + `/project/reject_request/${pid}/${wid}`, null, this.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
setManagerRoleOnProject(pid: number, role: number, manager: number) {
|
setManagerRoleOnProject(pid: number, role: number, manager: number) {
|
||||||
return this.http.post(this.url + `/manager/set_role_for_project/${pid}`,
|
return this.http.post(this.url + `/manager/set_role_for_project/${pid}`,
|
||||||
{"role": role, "manager": manager})
|
{"role": role, "manager": manager}, this.options)
|
||||||
|
}
|
||||||
|
|
||||||
|
getSecret(pid: number) {
|
||||||
|
return this.http.get(this.url + `/project/secret/${pid}`,)
|
||||||
|
}
|
||||||
|
|
||||||
|
setSecret(pid: number, secret: string) {
|
||||||
|
return this.http.post(this.url + `/project/secret/${pid}`, {"secret": secret})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,11 @@ import {AccountDetailsComponent} from "./account-details/account-details.compone
|
|||||||
import {WorkerDashboardComponent} from "./worker-dashboard/worker-dashboard.component";
|
import {WorkerDashboardComponent} from "./worker-dashboard/worker-dashboard.component";
|
||||||
import {ProjectPermsComponent} from "./project-perms/project-perms.component";
|
import {ProjectPermsComponent} from "./project-perms/project-perms.component";
|
||||||
import {ManagerListComponent} from "./manager-list/manager-list.component";
|
import {ManagerListComponent} from "./manager-list/manager-list.component";
|
||||||
|
import {IndexComponent} from "./index/index.component";
|
||||||
|
import {ProjectSecretComponent} from "./project-secret/project-secret.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
{path: "", component: IndexComponent},
|
||||||
{path: "log", component: LogsComponent},
|
{path: "log", component: LogsComponent},
|
||||||
{path: "login", component: LoginComponent},
|
{path: "login", component: LoginComponent},
|
||||||
{path: "account", component: AccountDetailsComponent},
|
{path: "account", component: AccountDetailsComponent},
|
||||||
@ -22,9 +25,10 @@ const routes: Routes = [
|
|||||||
{path: "project/:id", component: ProjectDashboardComponent},
|
{path: "project/:id", component: ProjectDashboardComponent},
|
||||||
{path: "project/:id/update", component: UpdateProjectComponent},
|
{path: "project/:id/update", component: UpdateProjectComponent},
|
||||||
{path: "project/:id/perms", component: ProjectPermsComponent},
|
{path: "project/:id/perms", component: ProjectPermsComponent},
|
||||||
|
{path: "project/:id/secret", component: ProjectSecretComponent},
|
||||||
{path: "new_project", component: CreateProjectComponent},
|
{path: "new_project", component: CreateProjectComponent},
|
||||||
{path: "workers", component: WorkerDashboardComponent},
|
{path: "workers", component: WorkerDashboardComponent},
|
||||||
{path: "manager_list", component: ManagerListComponent}
|
{path: "manager_list", component: ManagerListComponent},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -27,6 +27,7 @@ import {
|
|||||||
MatSlideToggleModule,
|
MatSlideToggleModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
MatSortModule,
|
MatSortModule,
|
||||||
|
MatStepperModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
MatToolbarModule,
|
MatToolbarModule,
|
||||||
@ -52,6 +53,8 @@ import {ManagerListComponent} from './manager-list/manager-list.component';
|
|||||||
import {ProjectSelectComponent} from './project-select/project-select.component';
|
import {ProjectSelectComponent} from './project-select/project-select.component';
|
||||||
import {ManagerSelectComponent} from './manager-select/manager-select.component';
|
import {ManagerSelectComponent} from './manager-select/manager-select.component';
|
||||||
import {ProjectIconComponent} from './project-icon/project-icon.component';
|
import {ProjectIconComponent} from './project-icon/project-icon.component';
|
||||||
|
import {IndexComponent} from './index/index.component';
|
||||||
|
import {ProjectSecretComponent} from './project-secret/project-secret.component';
|
||||||
|
|
||||||
|
|
||||||
export function createTranslateLoader(http: HttpClient) {
|
export function createTranslateLoader(http: HttpClient) {
|
||||||
@ -76,6 +79,8 @@ export function createTranslateLoader(http: HttpClient) {
|
|||||||
ProjectSelectComponent,
|
ProjectSelectComponent,
|
||||||
ManagerSelectComponent,
|
ManagerSelectComponent,
|
||||||
ProjectIconComponent,
|
ProjectIconComponent,
|
||||||
|
IndexComponent,
|
||||||
|
ProjectSecretComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@ -114,7 +119,8 @@ export function createTranslateLoader(http: HttpClient) {
|
|||||||
MatProgressBarModule,
|
MatProgressBarModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
MatListModule,
|
MatListModule,
|
||||||
MatButtonToggleModule
|
MatButtonToggleModule,
|
||||||
|
MatStepperModule
|
||||||
|
|
||||||
],
|
],
|
||||||
exports: [],
|
exports: [],
|
||||||
|
@ -6,6 +6,7 @@ import {MatPaginator, MatSort, MatTableDataSource} from "@angular/material";
|
|||||||
|
|
||||||
import * as moment from "moment"
|
import * as moment from "moment"
|
||||||
import {AuthService} from "../auth.service";
|
import {AuthService} from "../auth.service";
|
||||||
|
import {Manager} from "../models/manager";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-manager-list',
|
selector: 'app-manager-list',
|
||||||
|
@ -56,11 +56,13 @@
|
|||||||
|
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
<!--TODO: auth-->
|
<button mat-raised-button [routerLink]="'/projects'">Back</button>
|
||||||
<button mat-raised-button color="primary" *ngIf="project"
|
<button mat-raised-button color="primary" *ngIf="project && auth.logged"
|
||||||
[routerLink]="'/project/' + project.id + '/update'">{{"project.update" | translate}}</button>
|
[routerLink]="'/project/' + project.id + '/update'">{{"project.update" | translate}}</button>
|
||||||
<button mat-raised-button color="primary" *ngIf="project"
|
<button mat-raised-button color="primary" *ngIf="project && auth.logged"
|
||||||
[routerLink]="'/project/' + project.id + '/perms'">{{"project.perms" | translate}}</button>
|
[routerLink]="'/project/' + project.id + '/perms'">{{"project.perms" | translate}}</button>
|
||||||
|
<button mat-raised-button color="primary" *ngIf="project && auth.logged"
|
||||||
|
[routerLink]="'/project/' + project.id + '/secret'">{{"project.secret" | translate}}</button>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,6 +7,7 @@ import {Chart} from "chart.js";
|
|||||||
import {AssignedTasks, MonitoringSnapshot} from "../models/monitoring";
|
import {AssignedTasks, MonitoringSnapshot} from "../models/monitoring";
|
||||||
import {TranslateService} from "@ngx-translate/core";
|
import {TranslateService} from "@ngx-translate/core";
|
||||||
import {MessengerService} from "../messenger.service";
|
import {MessengerService} from "../messenger.service";
|
||||||
|
import {AuthService} from "../auth.service";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -46,6 +47,7 @@ export class ProjectDashboardComponent implements OnInit {
|
|||||||
constructor(private apiService: ApiService,
|
constructor(private apiService: ApiService,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
|
public auth: AuthService,
|
||||||
private messenger: MessengerService) {
|
private messenger: MessengerService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@
|
|||||||
*ngIf="authService.logged">
|
*ngIf="authService.logged">
|
||||||
<mat-icon>perm_identity</mat-icon>
|
<mat-icon>perm_identity</mat-icon>
|
||||||
{{"project.perms" | translate}}</button>
|
{{"project.perms" | translate}}</button>
|
||||||
|
<button mat-raised-button color="primary"
|
||||||
|
*ngIf="authService.logged"
|
||||||
|
[routerLink]="'/project/' + project.id + '/secret'">
|
||||||
|
{{"project.secret" | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
</mat-expansion-panel>
|
</mat-expansion-panel>
|
||||||
<span *ngIf="projects && projects.length == 0">
|
<span *ngIf="projects && projects.length == 0">
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<mat-card-subtitle>{{"perms.subtitle" | translate}}</mat-card-subtitle>
|
<mat-card-subtitle>{{"perms.subtitle" | translate}}</mat-card-subtitle>
|
||||||
</mat-card-header>
|
</mat-card-header>
|
||||||
|
|
||||||
<mat-card-content *ngIf="!unauthorized || !auth.account">
|
<mat-card-content *ngIf="!(unauthorized || !auth.account)">
|
||||||
<h3>{{"perms.workers" | translate}}</h3>
|
<h3>{{"perms.workers" | translate}}</h3>
|
||||||
<mat-list *ngIf="accesses && accesses.length>0">
|
<mat-list *ngIf="accesses && accesses.length>0">
|
||||||
<mat-list-item *ngFor="let wa of accesses" [class.request]="wa.request">
|
<mat-list-item *ngFor="let wa of accesses" [class.request]="wa.request">
|
||||||
@ -65,5 +65,8 @@
|
|||||||
</p>
|
</p>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
|
|
||||||
|
<mat-card-actions>
|
||||||
|
<button mat-raised-button [routerLink]="'../'">Back</button>
|
||||||
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
.mat-form-field {
|
||||||
|
width: 100%;
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
<div class="container">
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>{{"secret.title" | translate}}</mat-card-title>
|
||||||
|
<mat-card-subtitle>{{"secret.subtitle" | translate}}</mat-card-subtitle>
|
||||||
|
</mat-card-header>
|
||||||
|
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline">
|
||||||
|
<mat-label>{{"secret.secret" | translate}}</mat-label>
|
||||||
|
<textarea matInput [(ngModel)]="secret"
|
||||||
|
[placeholder]="'secret.secret'|translate"
|
||||||
|
name="secret"></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-card-actions>
|
||||||
|
<button mat-raised-button [routerLink]="'../'">Back</button>
|
||||||
|
<button mat-raised-button color="primary"
|
||||||
|
(click)="onUpdate()">{{"secret.update" | translate}}</button>
|
||||||
|
</mat-card-actions>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
@ -0,0 +1,46 @@
|
|||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {AuthService} from "../auth.service";
|
||||||
|
import {ApiService} from "../api.service";
|
||||||
|
import {ActivatedRoute} from "@angular/router";
|
||||||
|
import {TranslateService} from "@ngx-translate/core";
|
||||||
|
import {MessengerService} from "../messenger.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-project-secret',
|
||||||
|
templateUrl: './project-secret.component.html',
|
||||||
|
styleUrls: ['./project-secret.component.css']
|
||||||
|
})
|
||||||
|
export class ProjectSecretComponent implements OnInit {
|
||||||
|
|
||||||
|
secret: string;
|
||||||
|
projectId: number;
|
||||||
|
|
||||||
|
constructor(private auth: AuthService,
|
||||||
|
private apiService: ApiService,
|
||||||
|
private translate: TranslateService,
|
||||||
|
private messenger: MessengerService,
|
||||||
|
private route: ActivatedRoute) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.route.params.subscribe(params => {
|
||||||
|
this.projectId = params["id"];
|
||||||
|
this.getSecret();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSecret() {
|
||||||
|
this.apiService.getSecret(this.projectId).subscribe(data => {
|
||||||
|
this.secret = data["content"]["secret"]
|
||||||
|
}, error => {
|
||||||
|
this.translate.get("messenger.unauthorized").subscribe(t => this.messenger.show(t))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onUpdate() {
|
||||||
|
this.apiService.setSecret(this.projectId, this.secret).subscribe(data => {
|
||||||
|
this.translate.get("secret.ok").subscribe(t => this.messenger.show(t))
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
<mat-card-actions>
|
<mat-card-actions>
|
||||||
|
<button mat-raised-button [routerLink]="'../'">Back</button>
|
||||||
<button type="submit" form="uf" mat-raised-button color="primary">{{"project.update" | translate}}</button>
|
<button type="submit" form="uf" mat-raised-button color="primary">{{"project.update" | translate}}</button>
|
||||||
</mat-card-actions>
|
</mat-card-actions>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
@ -67,7 +67,8 @@
|
|||||||
"perms": "Permissions",
|
"perms": "Permissions",
|
||||||
"chain": "Chain tasks to",
|
"chain": "Chain tasks to",
|
||||||
"manager_select": "Give access to manager",
|
"manager_select": "Give access to manager",
|
||||||
"version": "Git version (commit hash)"
|
"version": "Git version (commit hash)",
|
||||||
|
"secret": "Secret"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"title": "Dashboard for",
|
"title": "Dashboard for",
|
||||||
@ -137,5 +138,16 @@
|
|||||||
"project_select": {
|
"project_select": {
|
||||||
"list_loading": "Loading project list...",
|
"list_loading": "Loading project list...",
|
||||||
"none": "None"
|
"none": "None"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"version": "Latest commit hash here",
|
||||||
|
"alias": "Relevent alias"
|
||||||
|
},
|
||||||
|
"secret": {
|
||||||
|
"title": "Project secret",
|
||||||
|
"subtitle": "You can set project configuration here. It is only accessible by workers with ASSIGN access to this project",
|
||||||
|
"secret": "Secret",
|
||||||
|
"update": "Update",
|
||||||
|
"ok": "Updated"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,8 @@
|
|||||||
"set": "Changements enregistrés",
|
"set": "Changements enregistrés",
|
||||||
"workers": "Workers",
|
"workers": "Workers",
|
||||||
"no_workers": "Aucun Worker n'a explicitement accès à ce projet",
|
"no_workers": "Aucun Worker n'a explicitement accès à ce projet",
|
||||||
"managers": "Managers"
|
"managers": "Managers",
|
||||||
|
"secret": "Secret"
|
||||||
},
|
},
|
||||||
"messenger": {
|
"messenger": {
|
||||||
"close": "Fermer",
|
"close": "Fermer",
|
||||||
@ -139,6 +140,17 @@
|
|||||||
"project_select": {
|
"project_select": {
|
||||||
"list_loading": "Chargement de la liste de projets...",
|
"list_loading": "Chargement de la liste de projets...",
|
||||||
"none": "Aucun"
|
"none": "Aucun"
|
||||||
|
},
|
||||||
|
"index": {
|
||||||
|
"version": "Le dernier hash de commit",
|
||||||
|
"alias": "Alias pertinent"
|
||||||
|
},
|
||||||
|
"secret": {
|
||||||
|
"title": "Secret",
|
||||||
|
"subtitle": "Vous pouvez définir la configuration du projet ici. Ce n'est accessible que par les Workers ayant accès au projet",
|
||||||
|
"secret": "Secret",
|
||||||
|
"update": "Mettre à jour",
|
||||||
|
"ok": "Mis à jour"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user