diff --git a/cmd/web-api/docs/docs.go b/cmd/web-api/docs/docs.go index 71058df..ee7f0de 100644 --- a/cmd/web-api/docs/docs.go +++ b/cmd/web-api/docs/docs.go @@ -220,7 +220,7 @@ var doc = `{ "application/json" ], "tags": [ - "project" + "checklist" ], "summary": "List projects", "parameters": [ @@ -261,7 +261,7 @@ var doc = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/project.ProjectResponse" + "$ref": "#/definitions/checklist.ProjectResponse" } } }, @@ -291,7 +291,7 @@ var doc = `{ "OAuth2Password": [] } ], - "description": "Create inserts a new project into the system.", + "description": "Create inserts a new checklist into the system.", "consumes": [ "application/json" ], @@ -299,9 +299,9 @@ var doc = `{ "application/json" ], "tags": [ - "project" + "checklist" ], - "summary": "Create new project.", + "summary": "Create new checklist.", "parameters": [ { "description": "Project details", @@ -310,7 +310,7 @@ var doc = `{ "required": true, "schema": { "type": "object", - "$ref": "#/definitions/project.ProjectCreateRequest" + "$ref": "#/definitions/checklist.ProjectCreateRequest" } } ], @@ -318,7 +318,7 @@ var doc = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/project.ProjectResponse" + "$ref": "#/definitions/checklist.ProjectResponse" } }, "400": { @@ -353,7 +353,7 @@ var doc = `{ "OAuth2Password": [] } ], - "description": "Update updates the specified project in the system.", + "description": "Update updates the specified checklist in the system.", "consumes": [ "application/json" ], @@ -361,9 +361,9 @@ var doc = `{ "application/json" ], "tags": [ - "project" + "checklist" ], - "summary": "Update project by ID", + "summary": "Update checklist by ID", "parameters": [ { "description": "Update fields", @@ -372,7 +372,7 @@ var doc = `{ "required": true, "schema": { "type": "object", - "$ref": "#/definitions/project.ProjectUpdateRequest" + "$ref": "#/definitions/checklist.ProjectUpdateRequest" } } ], @@ -406,7 +406,7 @@ var doc = `{ "OAuth2Password": [] } ], - "description": "Archive soft-deletes the specified project from the system.", + "description": "Archive soft-deletes the specified checklist from the system.", "consumes": [ "application/json" ], @@ -414,9 +414,9 @@ var doc = `{ "application/json" ], "tags": [ - "project" + "checklist" ], - "summary": "Archive project by ID", + "summary": "Archive checklist by ID", "parameters": [ { "description": "Update fields", @@ -425,7 +425,7 @@ var doc = `{ "required": true, "schema": { "type": "object", - "$ref": "#/definitions/project.ProjectArchiveRequest" + "$ref": "#/definitions/checklist.ProjectArchiveRequest" } } ], @@ -459,7 +459,7 @@ var doc = `{ "OAuth2Password": [] } ], - "description": "Read returns the specified project from the system.", + "description": "Read returns the specified checklist from the system.", "consumes": [ "application/json" ], @@ -467,9 +467,9 @@ var doc = `{ "application/json" ], "tags": [ - "project" + "checklist" ], - "summary": "Get project by ID.", + "summary": "Get checklist by ID.", "parameters": [ { "type": "string", @@ -483,7 +483,7 @@ var doc = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/project.ProjectResponse" + "$ref": "#/definitions/checklist.ProjectResponse" } }, "400": { @@ -512,7 +512,7 @@ var doc = `{ "OAuth2Password": [] } ], - "description": "Delete removes the specified project from the system.", + "description": "Delete removes the specified checklist from the system.", "consumes": [ "application/json" ], @@ -520,9 +520,9 @@ var doc = `{ "application/json" ], "tags": [ - "project" + "checklist" ], - "summary": "Delete project by ID", + "summary": "Delete checklist by ID", "parameters": [ { "type": "string", @@ -1512,7 +1512,7 @@ var doc = `{ } } }, - "project.ProjectArchiveRequest": { + "checklist.ProjectArchiveRequest": { "type": "object", "required": [ "id" @@ -1524,7 +1524,7 @@ var doc = `{ } } }, - "project.ProjectCreateRequest": { + "checklist.ProjectCreateRequest": { "type": "object", "required": [ "account_id", @@ -1541,7 +1541,7 @@ var doc = `{ } } }, - "project.ProjectResponse": { + "checklist.ProjectResponse": { "type": "object", "required": [ "account_id", @@ -1579,7 +1579,7 @@ var doc = `{ } } }, - "project.ProjectUpdateRequest": { + "checklist.ProjectUpdateRequest": { "type": "object", "required": [ "id" diff --git a/cmd/web-api/docs/swagger.yaml b/cmd/web-api/docs/swagger.yaml index 5ee5fdf..f200200 100644 --- a/cmd/web-api/docs/swagger.yaml +++ b/cmd/web-api/docs/swagger.yaml @@ -673,7 +673,7 @@ paths: description: OK schema: items: - $ref: '#/definitions/project.ProjectResponse' + $ref: '#/definitions/checklist.ProjectResponse' type: array "400": description: Bad Request @@ -691,18 +691,18 @@ paths: - OAuth2Password: [] summary: List projects tags: - - project + - checklist patch: consumes: - application/json - description: Update updates the specified project in the system. + description: Update updates the specified checklist in the system. parameters: - description: Update fields in: body name: data required: true schema: - $ref: '#/definitions/project.ProjectUpdateRequest' + $ref: '#/definitions/checklist.ProjectUpdateRequest' type: object produces: - application/json @@ -722,20 +722,20 @@ paths: $ref: '#/definitions/weberror.ErrorResponse' security: - OAuth2Password: [] - summary: Update project by ID + summary: Update checklist by ID tags: - - project + - checklist post: consumes: - application/json - description: Create inserts a new project into the system. + description: Create inserts a new checklist into the system. parameters: - description: Project details in: body name: data required: true schema: - $ref: '#/definitions/project.ProjectCreateRequest' + $ref: '#/definitions/checklist.ProjectCreateRequest' type: object produces: - application/json @@ -743,7 +743,7 @@ paths: "201": description: Created schema: - $ref: '#/definitions/project.ProjectResponse' + $ref: '#/definitions/checklist.ProjectResponse' "400": description: Bad Request schema: @@ -762,14 +762,14 @@ paths: $ref: '#/definitions/weberror.ErrorResponse' security: - OAuth2Password: [] - summary: Create new project. + summary: Create new checklist. tags: - - project + - checklist /projects/{id}: delete: consumes: - application/json - description: Delete removes the specified project from the system. + description: Delete removes the specified checklist from the system. parameters: - description: Project ID in: path @@ -794,13 +794,13 @@ paths: $ref: '#/definitions/weberror.ErrorResponse' security: - OAuth2Password: [] - summary: Delete project by ID + summary: Delete checklist by ID tags: - - project + - checklist get: consumes: - application/json - description: Read returns the specified project from the system. + description: Read returns the specified checklist from the system. parameters: - description: Project ID in: path @@ -813,7 +813,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/project.ProjectResponse' + $ref: '#/definitions/checklist.ProjectResponse' "400": description: Bad Request schema: @@ -828,21 +828,21 @@ paths: $ref: '#/definitions/weberror.ErrorResponse' security: - OAuth2Password: [] - summary: Get project by ID. + summary: Get checklist by ID. tags: - - project + - checklist /projects/archive: patch: consumes: - application/json - description: Archive soft-deletes the specified project from the system. + description: Archive soft-deletes the specified checklist from the system. parameters: - description: Update fields in: body name: data required: true schema: - $ref: '#/definitions/project.ProjectArchiveRequest' + $ref: '#/definitions/checklist.ProjectArchiveRequest' type: object produces: - application/json @@ -862,9 +862,9 @@ paths: $ref: '#/definitions/weberror.ErrorResponse' security: - OAuth2Password: [] - summary: Archive project by ID + summary: Archive checklist by ID tags: - - project + - checklist /signup: post: consumes: diff --git a/cmd/web-api/handlers/project.go b/cmd/web-api/handlers/checklist.go similarity index 75% rename from cmd/web-api/handlers/project.go rename to cmd/web-api/handlers/checklist.go index ba892f8..81a6f1d 100644 --- a/cmd/web-api/handlers/project.go +++ b/cmd/web-api/handlers/checklist.go @@ -6,28 +6,28 @@ import ( "strconv" "strings" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" - "geeks-accelerator/oss/saas-starter-kit/internal/project" "github.com/pkg/errors" "gopkg.in/go-playground/validator.v9" ) -// Project represents the Project API method handler set. -type Projects struct { - Repository *project.Repository +// Checklist represents the Checklist API method handler set. +type Checklists struct { + Repository *checklist.Repository // ADD OTHER STATE LIKE THE LOGGER IF NEEDED. } // Find godoc -// TODO: Need to implement unittests on projects/find endpoint. There are none. -// @Summary List projects -// @Description Find returns the existing projects in the system. -// @Tags project +// TODO: Need to implement unittests on checklists/find endpoint. There are none. +// @Summary List checklists +// @Description Find returns the existing checklists in the system. +// @Tags checklist // @Accept json // @Produce json // @Security OAuth2Password @@ -36,18 +36,18 @@ type Projects struct { // @Param limit query integer false "Limit, example: 10" // @Param offset query integer false "Offset, example: 20" // @Param include-archived query boolean false "Included Archived, example: false" -// @Success 200 {array} project.ProjectResponse +// @Success 200 {array} checklist.ChecklistResponse // @Failure 400 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse -// @Router /projects [get] -func (h *Projects) Find(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// @Router /checklists [get] +func (h *Checklists) Find(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { claims, ok := ctx.Value(auth.Key).(auth.Claims) if !ok { return errors.New("claims missing from context") } - var req project.ProjectFindRequest + var req checklist.ChecklistFindRequest // Handle where query value if set. if v := r.URL.Query().Get("where"); v != "" { @@ -113,7 +113,7 @@ func (h *Projects) Find(ctx context.Context, w http.ResponseWriter, r *http.Requ return err } - var resp []*project.ProjectResponse + var resp []*checklist.ChecklistResponse for _, m := range res { resp = append(resp, m.Response(ctx)) } @@ -122,19 +122,19 @@ func (h *Projects) Find(ctx context.Context, w http.ResponseWriter, r *http.Requ } // Read godoc -// @Summary Get project by ID. -// @Description Read returns the specified project from the system. -// @Tags project +// @Summary Get checklist by ID. +// @Description Read returns the specified checklist from the system. +// @Tags checklist // @Accept json // @Produce json // @Security OAuth2Password -// @Param id path string true "Project ID" -// @Success 200 {object} project.ProjectResponse +// @Param id path string true "Checklist ID" +// @Success 200 {object} checklist.ChecklistResponse // @Failure 400 {object} weberror.ErrorResponse // @Failure 404 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse -// @Router /projects/{id} [get] -func (h *Projects) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// @Router /checklists/{id} [get] +func (h *Checklists) Read(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { claims, ok := ctx.Value(auth.Key).(auth.Claims) if !ok { return errors.New("claims missing from context") @@ -151,14 +151,14 @@ func (h *Projects) Read(ctx context.Context, w http.ResponseWriter, r *http.Requ includeArchived = b } - res, err := h.Repository.Read(ctx, claims, project.ProjectReadRequest{ + res, err := h.Repository.Read(ctx, claims, checklist.ChecklistReadRequest{ ID: params["id"], IncludeArchived: includeArchived, }) if err != nil { cause := errors.Cause(err) switch cause { - case project.ErrNotFound: + case checklist.ErrNotFound: return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusNotFound)) default: return errors.Wrapf(err, "ID: %s", params["id"]) @@ -169,20 +169,20 @@ func (h *Projects) Read(ctx context.Context, w http.ResponseWriter, r *http.Requ } // Create godoc -// @Summary Create new project. -// @Description Create inserts a new project into the system. -// @Tags project +// @Summary Create new checklist. +// @Description Create inserts a new checklist into the system. +// @Tags checklist // @Accept json // @Produce json // @Security OAuth2Password -// @Param data body project.ProjectCreateRequest true "Project details" -// @Success 201 {object} project.ProjectResponse +// @Param data body checklist.ChecklistCreateRequest true "Checklist details" +// @Success 201 {object} checklist.ChecklistResponse // @Failure 400 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse // @Failure 404 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse -// @Router /projects [post] -func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// @Router /checklists [post] +func (h *Checklists) Create(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { v, err := webcontext.ContextValues(ctx) if err != nil { return err @@ -193,7 +193,7 @@ func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Re return err } - var req project.ProjectCreateRequest + var req checklist.ChecklistCreateRequest if err := web.Decode(ctx, r, &req); err != nil { if _, ok := errors.Cause(err).(*weberror.Error); !ok { err = weberror.NewError(ctx, err, http.StatusBadRequest) @@ -205,14 +205,14 @@ func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Re if err != nil { cause := errors.Cause(err) switch cause { - case project.ErrForbidden: + case checklist.ErrForbidden: return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusForbidden)) default: _, ok := cause.(validator.ValidationErrors) if ok { return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusBadRequest)) } - return errors.Wrapf(err, "Project: %+v", &req) + return errors.Wrapf(err, "Checklist: %+v", &req) } } @@ -220,19 +220,19 @@ func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Re } // Read godoc -// @Summary Update project by ID -// @Description Update updates the specified project in the system. -// @Tags project +// @Summary Update checklist by ID +// @Description Update updates the specified checklist in the system. +// @Tags checklist // @Accept json // @Produce json // @Security OAuth2Password -// @Param data body project.ProjectUpdateRequest true "Update fields" +// @Param data body checklist.ChecklistUpdateRequest true "Update fields" // @Success 204 // @Failure 400 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse -// @Router /projects [patch] -func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// @Router /checklists [patch] +func (h *Checklists) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { v, err := webcontext.ContextValues(ctx) if err != nil { return err @@ -243,7 +243,7 @@ func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Re return err } - var req project.ProjectUpdateRequest + var req checklist.ChecklistUpdateRequest if err := web.Decode(ctx, r, &req); err != nil { if _, ok := errors.Cause(err).(*weberror.Error); !ok { err = weberror.NewError(ctx, err, http.StatusBadRequest) @@ -255,7 +255,7 @@ func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Re if err != nil { cause := errors.Cause(err) switch cause { - case project.ErrForbidden: + case checklist.ErrForbidden: return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusForbidden)) default: _, ok := cause.(validator.ValidationErrors) @@ -271,19 +271,19 @@ func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Re } // Read godoc -// @Summary Archive project by ID -// @Description Archive soft-deletes the specified project from the system. -// @Tags project +// @Summary Archive checklist by ID +// @Description Archive soft-deletes the specified checklist from the system. +// @Tags checklist // @Accept json // @Produce json // @Security OAuth2Password -// @Param data body project.ProjectArchiveRequest true "Update fields" +// @Param data body checklist.ChecklistArchiveRequest true "Update fields" // @Success 204 // @Failure 400 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse -// @Router /projects/archive [patch] -func (h *Projects) Archive(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// @Router /checklists/archive [patch] +func (h *Checklists) Archive(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { v, err := webcontext.ContextValues(ctx) if err != nil { return err @@ -294,7 +294,7 @@ func (h *Projects) Archive(ctx context.Context, w http.ResponseWriter, r *http.R return err } - var req project.ProjectArchiveRequest + var req checklist.ChecklistArchiveRequest if err := web.Decode(ctx, r, &req); err != nil { if _, ok := errors.Cause(err).(*weberror.Error); !ok { err = weberror.NewError(ctx, err, http.StatusBadRequest) @@ -306,7 +306,7 @@ func (h *Projects) Archive(ctx context.Context, w http.ResponseWriter, r *http.R if err != nil { cause := errors.Cause(err) switch cause { - case project.ErrForbidden: + case checklist.ErrForbidden: return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusForbidden)) default: _, ok := cause.(validator.ValidationErrors) @@ -322,30 +322,30 @@ func (h *Projects) Archive(ctx context.Context, w http.ResponseWriter, r *http.R } // Delete godoc -// @Summary Delete project by ID -// @Description Delete removes the specified project from the system. -// @Tags project +// @Summary Delete checklist by ID +// @Description Delete removes the specified checklist from the system. +// @Tags checklist // @Accept json // @Produce json // @Security OAuth2Password -// @Param id path string true "Project ID" +// @Param id path string true "Checklist ID" // @Success 204 // @Failure 400 {object} weberror.ErrorResponse // @Failure 403 {object} weberror.ErrorResponse // @Failure 500 {object} weberror.ErrorResponse -// @Router /projects/{id} [delete] -func (h *Projects) Delete(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// @Router /checklists/{id} [delete] +func (h *Checklists) Delete(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { claims, err := auth.ClaimsFromContext(ctx) if err != nil { return err } err = h.Repository.Delete(ctx, claims, - project.ProjectDeleteRequest{ID: params["id"]}) + checklist.ChecklistDeleteRequest{ID: params["id"]}) if err != nil { cause := errors.Cause(err) switch cause { - case project.ErrForbidden: + case checklist.ErrForbidden: return web.RespondJsonError(ctx, w, weberror.NewError(ctx, err, http.StatusForbidden)) default: _, ok := cause.(validator.ValidationErrors) diff --git a/cmd/web-api/handlers/example.go b/cmd/web-api/handlers/example.go index b448de5..b160231 100644 --- a/cmd/web-api/handlers/example.go +++ b/cmd/web-api/handlers/example.go @@ -4,18 +4,18 @@ import ( "context" "net/http" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" - "geeks-accelerator/oss/saas-starter-kit/internal/project" "github.com/pkg/errors" ) // Example represents the Example API method handler set. type Example struct { - Project *project.Repository + Checklist *checklist.Repository // ADD OTHER STATE LIKE THE LOGGER AND CONFIG HERE. } @@ -28,7 +28,7 @@ func (h *Example) ErrorResponse(ctx context.Context, w http.ResponseWriter, r *h } if qv := r.URL.Query().Get("test-validation-error"); qv != "" { - _, err := h.Project.Create(ctx, auth.Claims{}, project.ProjectCreateRequest{}, v.Now) + _, err := h.Checklist.Create(ctx, auth.Claims{}, checklist.ChecklistCreateRequest{}, v.Now) return web.RespondJsonError(ctx, w, err) } diff --git a/cmd/web-api/handlers/routes.go b/cmd/web-api/handlers/routes.go index 6088083..07ce923 100644 --- a/cmd/web-api/handlers/routes.go +++ b/cmd/web-api/handlers/routes.go @@ -7,13 +7,13 @@ import ( "geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/mid" saasSwagger "geeks-accelerator/oss/saas-starter-kit/internal/mid/saas-swagger" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" _ "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" - "geeks-accelerator/oss/saas-starter-kit/internal/project" "geeks-accelerator/oss/saas-starter-kit/internal/signup" "geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user_account" @@ -36,7 +36,7 @@ type AppContext struct { AuthRepo *user_auth.Repository SignupRepo *signup.Repository InviteRepo *invite.Repository - ProjectRepo *project.Repository + ChecklistRepo *checklist.Repository Authenticator *auth.Authenticator PreAppMiddleware []web.Middleware PostAppMiddleware []web.Middleware @@ -74,7 +74,7 @@ func API(shutdown chan os.Signal, appCtx *AppContext) http.Handler { // Register example endpoints. ex := Example{ - Project: appCtx.ProjectRepo, + Checklist: appCtx.ChecklistRepo, } app.Handle("GET", "/v1/examples/error-response", ex.ErrorResponse) @@ -119,16 +119,16 @@ func API(shutdown chan os.Signal, appCtx *AppContext) http.Handler { } app.Handle("POST", "/v1/signup", s.Signup) - // Register project. - p := Projects{ - Repository: appCtx.ProjectRepo, + // Register checklist. + p := Checklists{ + Repository: appCtx.ChecklistRepo, } - app.Handle("GET", "/v1/projects", p.Find, mid.AuthenticateHeader(appCtx.Authenticator)) - app.Handle("POST", "/v1/projects", p.Create, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) - app.Handle("GET", "/v1/projects/:id", p.Read, mid.AuthenticateHeader(appCtx.Authenticator)) - app.Handle("PATCH", "/v1/projects", p.Update, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) - app.Handle("PATCH", "/v1/projects/archive", p.Archive, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) - app.Handle("DELETE", "/v1/projects/:id", p.Delete, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("GET", "/v1/checklists", p.Find, mid.AuthenticateHeader(appCtx.Authenticator)) + app.Handle("POST", "/v1/checklists", p.Create, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("GET", "/v1/checklists/:id", p.Read, mid.AuthenticateHeader(appCtx.Authenticator)) + app.Handle("PATCH", "/v1/checklists", p.Update, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("PATCH", "/v1/checklists/archive", p.Archive, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("DELETE", "/v1/checklists/:id", p.Delete, mid.AuthenticateHeader(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) // Register swagger documentation. // TODO: Add authentication. Current authenticator requires an Authorization header diff --git a/cmd/web-api/main.go b/cmd/web-api/main.go index 649d86c..b9c9ede 100644 --- a/cmd/web-api/main.go +++ b/cmd/web-api/main.go @@ -22,18 +22,18 @@ import ( "geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers" "geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/mid" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/flag" "geeks-accelerator/oss/saas-starter-kit/internal/platform/notify" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" - "geeks-accelerator/oss/saas-starter-kit/internal/project" - "geeks-accelerator/oss/saas-starter-kit/internal/project_route" "geeks-accelerator/oss/saas-starter-kit/internal/signup" "geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth" + "geeks-accelerator/oss/saas-starter-kit/internal/webroute" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" @@ -437,19 +437,19 @@ func main() { // ========================================================================= // Init repositories and AppContext - projectRoute, err := project_route.New(cfg.Service.BaseUrl, cfg.Project.WebAppBaseUrl) + webRoute, err := webroute.New(cfg.Service.BaseUrl, cfg.Project.WebAppBaseUrl) if err != nil { - log.Fatalf("main : project routes : %s: %+v", cfg.Service.BaseUrl, err) + log.Fatalf("main : checklist routes : %s: %+v", cfg.Service.BaseUrl, err) } - usrRepo := user.NewRepository(masterDb, projectRoute.UserResetPassword, notifyEmail, cfg.Project.SharedSecretKey) + usrRepo := user.NewRepository(masterDb, webRoute.UserResetPassword, notifyEmail, cfg.Project.SharedSecretKey) usrAccRepo := user_account.NewRepository(masterDb) accRepo := account.NewRepository(masterDb) accPrefRepo := account_preference.NewRepository(masterDb) authRepo := user_auth.NewRepository(masterDb, authenticator, usrRepo, usrAccRepo, accPrefRepo) signupRepo := signup.NewRepository(masterDb, usrRepo, usrAccRepo, accRepo) - inviteRepo := invite.NewRepository(masterDb, usrRepo, usrAccRepo, accRepo, projectRoute.UserInviteAccept, notifyEmail, cfg.Project.SharedSecretKey) - prjRepo := project.NewRepository(masterDb) + inviteRepo := invite.NewRepository(masterDb, usrRepo, usrAccRepo, accRepo, webRoute.UserInviteAccept, notifyEmail, cfg.Project.SharedSecretKey) + chklstRepo := checklist.NewRepository(masterDb) appCtx := &handlers.AppContext{ Log: log, @@ -463,7 +463,7 @@ func main() { AuthRepo: authRepo, SignupRepo: signupRepo, InviteRepo: inviteRepo, - ProjectRepo: prjRepo, + ChecklistRepo: chklstRepo, Authenticator: authenticator, } diff --git a/cmd/web-api/tests/project_test.go b/cmd/web-api/tests/checklist_test.go similarity index 84% rename from cmd/web-api/tests/project_test.go rename to cmd/web-api/tests/checklist_test.go index 504cdd4..b4d57ab 100644 --- a/cmd/web-api/tests/project_test.go +++ b/cmd/web-api/tests/checklist_test.go @@ -8,26 +8,26 @@ import ( "testing" "time" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/mid" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/tests" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" - "geeks-accelerator/oss/saas-starter-kit/internal/project" "github.com/pborman/uuid" ) -func mockProjectCreateRequest(accountID string) project.ProjectCreateRequest { - return project.ProjectCreateRequest{ +func mockChecklistCreateRequest(accountID string) checklist.ChecklistCreateRequest { + return checklist.ChecklistCreateRequest{ Name: fmt.Sprintf("Moon Launch %s", uuid.NewRandom().String()), AccountID: accountID, } } -// mockProject creates a new project for testing and associates it with the supplied account ID. -func newMockProject(accountID string) *project.Project { - req := mockProjectCreateRequest(accountID) - p, err := appCtx.ProjectRepo.Create(tests.Context(), auth.Claims{}, req, time.Now().UTC().AddDate(-1, -1, -1)) +// mockChecklist creates a new checklist for testing and associates it with the supplied account ID. +func newMockChecklist(accountID string) *checklist.Checklist { + req := mockChecklistCreateRequest(accountID) + p, err := appCtx.ChecklistRepo.Create(tests.Context(), auth.Claims{}, req, time.Now().UTC().AddDate(-1, -1, -1)) if err != nil { panic(err) } @@ -35,25 +35,25 @@ func newMockProject(accountID string) *project.Project { return p } -// TestProjectCRUDAdmin tests all the project CRUD endpoints using an user with role admin. -func TestProjectCRUDAdmin(t *testing.T) { +// TestChecklistCRUDAdmin tests all the checklist CRUD endpoints using an user with role admin. +func TestChecklistCRUDAdmin(t *testing.T) { defer tests.Recover(t) tr := roleTests[auth.RoleAdmin] - // Add claims to the context for the project. + // Add claims to the context for the checklist. ctx := context.WithValue(tests.Context(), auth.Key, tr.Claims) // Test create. - var created project.ProjectResponse + var created checklist.ChecklistResponse { expectedStatus := http.StatusCreated - req := mockProjectCreateRequest(tr.Account.ID) + req := mockChecklistCreateRequest(tr.Account.ID) rt := requestTest{ fmt.Sprintf("Create %d w/role %s", expectedStatus, tr.Role), http.MethodPost, - "/v1/projects", + "/v1/checklists", req, tr.Token, tr.Claims, @@ -68,7 +68,7 @@ func TestProjectCRUDAdmin(t *testing.T) { } t.Logf("\t%s\tReceived valid status code of %d.", tests.Success, w.Code) - var actual project.ProjectResponse + var actual checklist.ChecklistResponse if err := json.Unmarshal(w.Body.Bytes(), &actual); err != nil { t.Logf("\t\tGot error : %+v", err) t.Fatalf("\t%s\tDecode response body failed.", tests.Failed) @@ -79,12 +79,12 @@ func TestProjectCRUDAdmin(t *testing.T) { "updated_at": web.NewTimeResponse(ctx, actual.UpdatedAt.Value), "id": actual.ID, "account_id": req.AccountID, - "status": web.NewEnumResponse(ctx, "active", project.ProjectStatus_ValuesInterface()...), + "status": web.NewEnumResponse(ctx, "active", checklist.ChecklistStatus_ValuesInterface()...), "created_at": web.NewTimeResponse(ctx, actual.CreatedAt.Value), "name": req.Name, } - var expected project.ProjectResponse + var expected checklist.ChecklistResponse if err := decodeMapToStruct(expectedMap, &expected); err != nil { t.Logf("\t\tGot error : %+v\nActual results to format expected : \n", err) printResultMap(ctx, w.Body.Bytes()) // used to help format expectedMap @@ -107,7 +107,7 @@ func TestProjectCRUDAdmin(t *testing.T) { rt := requestTest{ fmt.Sprintf("Read %d w/role %s", expectedStatus, tr.Role), http.MethodGet, - fmt.Sprintf("/v1/projects/%s", created.ID), + fmt.Sprintf("/v1/checklists/%s", created.ID), nil, tr.Token, tr.Claims, @@ -122,7 +122,7 @@ func TestProjectCRUDAdmin(t *testing.T) { } t.Logf("\t%s\tReceived valid status code of %d.", tests.Success, w.Code) - var actual project.ProjectResponse + var actual checklist.ChecklistResponse if err := json.Unmarshal(w.Body.Bytes(), &actual); err != nil { t.Logf("\t\tGot error : %+v", err) t.Fatalf("\t%s\tDecode response body failed.", tests.Failed) @@ -142,7 +142,7 @@ func TestProjectCRUDAdmin(t *testing.T) { rt := requestTest{ fmt.Sprintf("Read %d w/role %s using random ID", expectedStatus, tr.Role), http.MethodGet, - fmt.Sprintf("/v1/projects/%s", randID), + fmt.Sprintf("/v1/checklists/%s", randID), nil, tr.Token, tr.Claims, @@ -166,7 +166,7 @@ func TestProjectCRUDAdmin(t *testing.T) { expected := weberror.ErrorResponse{ StatusCode: expectedStatus, Error: http.StatusText(expectedStatus), - Details: fmt.Sprintf("project %s not found: Entity not found", randID), + Details: fmt.Sprintf("checklist %s not found: Entity not found", randID), StackTrace: actual.StackTrace, } @@ -177,14 +177,14 @@ func TestProjectCRUDAdmin(t *testing.T) { } // Test Read with forbidden ID. - forbiddenProject := newMockProject(newMockSignup().account.ID) + forbiddenChecklist := newMockChecklist(newMockSignup().account.ID) { expectedStatus := http.StatusNotFound rt := requestTest{ fmt.Sprintf("Read %d w/role %s using forbidden ID", expectedStatus, tr.Role), http.MethodGet, - fmt.Sprintf("/v1/projects/%s", forbiddenProject.ID), + fmt.Sprintf("/v1/checklists/%s", forbiddenChecklist.ID), nil, tr.Token, tr.Claims, @@ -208,7 +208,7 @@ func TestProjectCRUDAdmin(t *testing.T) { expected := weberror.ErrorResponse{ StatusCode: expectedStatus, Error: http.StatusText(expectedStatus), - Details: fmt.Sprintf("project %s not found: Entity not found", forbiddenProject.ID), + Details: fmt.Sprintf("checklist %s not found: Entity not found", forbiddenChecklist.ID), StackTrace: actual.StackTrace, } @@ -226,8 +226,8 @@ func TestProjectCRUDAdmin(t *testing.T) { rt := requestTest{ fmt.Sprintf("Update %d w/role %s", expectedStatus, tr.Role), http.MethodPatch, - "/v1/projects", - project.ProjectUpdateRequest{ + "/v1/checklists", + checklist.ChecklistUpdateRequest{ ID: created.ID, Name: &newName, }, @@ -259,8 +259,8 @@ func TestProjectCRUDAdmin(t *testing.T) { rt := requestTest{ fmt.Sprintf("Archive %d w/role %s", expectedStatus, tr.Role), http.MethodPatch, - "/v1/projects/archive", - project.ProjectArchiveRequest{ + "/v1/checklists/archive", + checklist.ChecklistArchiveRequest{ ID: created.ID, }, tr.Token, @@ -291,7 +291,7 @@ func TestProjectCRUDAdmin(t *testing.T) { rt := requestTest{ fmt.Sprintf("Delete %d w/role %s", expectedStatus, tr.Role), http.MethodDelete, - fmt.Sprintf("/v1/projects/%s", created.ID), + fmt.Sprintf("/v1/checklists/%s", created.ID), nil, tr.Token, tr.Claims, @@ -315,24 +315,24 @@ func TestProjectCRUDAdmin(t *testing.T) { } } -// TestProjectCRUDUser tests all the project CRUD endpoints using an user with role project. -func TestProjectCRUDUser(t *testing.T) { +// TestChecklistCRUDUser tests all the checklist CRUD endpoints using an user with role checklist. +func TestChecklistCRUDUser(t *testing.T) { defer tests.Recover(t) tr := roleTests[auth.RoleUser] - // Add claims to the context for the project. + // Add claims to the context for the checklist. ctx := context.WithValue(tests.Context(), auth.Key, tr.Claims) // Test create. { expectedStatus := http.StatusForbidden - req := mockProjectCreateRequest(tr.Account.ID) + req := mockChecklistCreateRequest(tr.Account.ID) rt := requestTest{ fmt.Sprintf("Create %d w/role %s", expectedStatus, tr.Role), http.MethodPost, - "/v1/projects", + "/v1/checklists", req, tr.Token, tr.Claims, @@ -363,7 +363,7 @@ func TestProjectCRUDUser(t *testing.T) { } // Since role doesn't support create, bypass auth to test other endpoints. - created := newMockProject(tr.Account.ID).Response(ctx) + created := newMockChecklist(tr.Account.ID).Response(ctx) // Test read. { @@ -372,7 +372,7 @@ func TestProjectCRUDUser(t *testing.T) { rt := requestTest{ fmt.Sprintf("Read %d w/role %s", expectedStatus, tr.Role), http.MethodGet, - fmt.Sprintf("/v1/projects/%s", created.ID), + fmt.Sprintf("/v1/checklists/%s", created.ID), nil, tr.Token, tr.Claims, @@ -387,7 +387,7 @@ func TestProjectCRUDUser(t *testing.T) { } t.Logf("\t%s\tReceived valid status code of %d.", tests.Success, w.Code) - var actual *project.ProjectResponse + var actual *checklist.ChecklistResponse if err := json.Unmarshal(w.Body.Bytes(), &actual); err != nil { t.Logf("\t\tGot error : %+v", err) t.Fatalf("\t%s\tDecode response body failed.", tests.Failed) @@ -407,7 +407,7 @@ func TestProjectCRUDUser(t *testing.T) { rt := requestTest{ fmt.Sprintf("Read %d w/role %s using random ID", expectedStatus, tr.Role), http.MethodGet, - fmt.Sprintf("/v1/projects/%s", randID), + fmt.Sprintf("/v1/checklists/%s", randID), nil, tr.Token, tr.Claims, @@ -431,7 +431,7 @@ func TestProjectCRUDUser(t *testing.T) { expected := weberror.ErrorResponse{ StatusCode: expectedStatus, Error: http.StatusText(expectedStatus), - Details: fmt.Sprintf("project %s not found: Entity not found", randID), + Details: fmt.Sprintf("checklist %s not found: Entity not found", randID), StackTrace: actual.StackTrace, } @@ -442,14 +442,14 @@ func TestProjectCRUDUser(t *testing.T) { } // Test Read with forbidden ID. - forbiddenProject := newMockProject(newMockSignup().account.ID) + forbiddenChecklist := newMockChecklist(newMockSignup().account.ID) { expectedStatus := http.StatusNotFound rt := requestTest{ fmt.Sprintf("Read %d w/role %s using forbidden ID", expectedStatus, tr.Role), http.MethodGet, - fmt.Sprintf("/v1/projects/%s", forbiddenProject.ID), + fmt.Sprintf("/v1/checklists/%s", forbiddenChecklist.ID), nil, tr.Token, tr.Claims, @@ -473,7 +473,7 @@ func TestProjectCRUDUser(t *testing.T) { expected := weberror.ErrorResponse{ StatusCode: expectedStatus, Error: http.StatusText(expectedStatus), - Details: fmt.Sprintf("project %s not found: Entity not found", forbiddenProject.ID), + Details: fmt.Sprintf("checklist %s not found: Entity not found", forbiddenChecklist.ID), StackTrace: actual.StackTrace, } @@ -491,8 +491,8 @@ func TestProjectCRUDUser(t *testing.T) { rt := requestTest{ fmt.Sprintf("Update %d w/role %s", expectedStatus, tr.Role), http.MethodPatch, - "/v1/projects", - project.ProjectUpdateRequest{ + "/v1/checklists", + checklist.ChecklistUpdateRequest{ ID: created.ID, Name: &newName, }, @@ -531,8 +531,8 @@ func TestProjectCRUDUser(t *testing.T) { rt := requestTest{ fmt.Sprintf("Archive %d w/role %s", expectedStatus, tr.Role), http.MethodPatch, - "/v1/projects/archive", - project.ProjectArchiveRequest{ + "/v1/checklists/archive", + checklist.ChecklistArchiveRequest{ ID: created.ID, }, tr.Token, @@ -570,7 +570,7 @@ func TestProjectCRUDUser(t *testing.T) { rt := requestTest{ fmt.Sprintf("Delete %d w/role %s", expectedStatus, tr.Role), http.MethodDelete, - fmt.Sprintf("/v1/projects/%s", created.ID), + fmt.Sprintf("/v1/checklists/%s", created.ID), nil, tr.Token, tr.Claims, @@ -601,26 +601,26 @@ func TestProjectCRUDUser(t *testing.T) { } } -// TestProjectCreate validates create project endpoint. -func TestProjectCreate(t *testing.T) { +// TestChecklistCreate validates create checklist endpoint. +func TestChecklistCreate(t *testing.T) { defer tests.Recover(t) tr := roleTests[auth.RoleAdmin] - // Add claims to the context for the project. + // Add claims to the context for the checklist. ctx := context.WithValue(tests.Context(), auth.Key, tr.Claims) // Test create with invalid data. { expectedStatus := http.StatusBadRequest - req := mockProjectCreateRequest(tr.Account.ID) - invalidStatus := project.ProjectStatus("invalid status") + req := mockChecklistCreateRequest(tr.Account.ID) + invalidStatus := checklist.ChecklistStatus("invalid status") req.Status = &invalidStatus rt := requestTest{ fmt.Sprintf("Create %d w/role %s using invalid data", expectedStatus, tr.Role), http.MethodPost, - "/v1/projects", + "/v1/checklists", req, tr.Token, tr.Claims, @@ -646,7 +646,7 @@ func TestProjectCreate(t *testing.T) { Details: actual.Details, Error: "Field validation error", Fields: []weberror.FieldError{ - //{Field: "status", Error: "Key: 'ProjectCreateRequest.status' Error:Field validation for 'status' failed on the 'oneof' tag"}, + //{Field: "status", Error: "Key: 'ChecklistCreateRequest.status' Error:Field validation for 'status' failed on the 'oneof' tag"}, { Field: "status", Value: invalidStatus.String(), @@ -665,25 +665,25 @@ func TestProjectCreate(t *testing.T) { } } -// TestProjectUpdate validates update project endpoint. -func TestProjectUpdate(t *testing.T) { +// TestChecklistUpdate validates update checklist endpoint. +func TestChecklistUpdate(t *testing.T) { defer tests.Recover(t) tr := roleTests[auth.RoleAdmin] - // Add claims to the context for the project. + // Add claims to the context for the checklist. ctx := context.WithValue(tests.Context(), auth.Key, tr.Claims) // Test update with invalid data. { expectedStatus := http.StatusBadRequest - invalidStatus := project.ProjectStatus("invalid status") + invalidStatus := checklist.ChecklistStatus("invalid status") rt := requestTest{ fmt.Sprintf("Update %d w/role %s using invalid data", expectedStatus, tr.Role), http.MethodPatch, - "/v1/projects", - project.ProjectUpdateRequest{ + "/v1/checklists", + checklist.ChecklistUpdateRequest{ ID: uuid.NewRandom().String(), Status: &invalidStatus, }, @@ -711,7 +711,7 @@ func TestProjectUpdate(t *testing.T) { Details: actual.Details, Error: "Field validation error", Fields: []weberror.FieldError{ - //{Field: "status", Error: "Key: 'ProjectUpdateRequest.status' Error:Field validation for 'status' failed on the 'oneof' tag"}, + //{Field: "status", Error: "Key: 'ChecklistUpdateRequest.status' Error:Field validation for 'status' failed on the 'oneof' tag"}, { Field: "status", Value: invalidStatus.String(), @@ -730,16 +730,16 @@ func TestProjectUpdate(t *testing.T) { } } -// TestProjectArchive validates archive project endpoint. -func TestProjectArchive(t *testing.T) { +// TestChecklistArchive validates archive checklist endpoint. +func TestChecklistArchive(t *testing.T) { defer tests.Recover(t) tr := roleTests[auth.RoleAdmin] - // Add claims to the context for the project. + // Add claims to the context for the checklist. ctx := context.WithValue(tests.Context(), auth.Key, tr.Claims) - forbiddenProject := newMockProject(newMockSignup().account.ID) + forbiddenChecklist := newMockChecklist(newMockSignup().account.ID) // Test archive with invalid data. { @@ -750,8 +750,8 @@ func TestProjectArchive(t *testing.T) { rt := requestTest{ fmt.Sprintf("Archive %d w/role %s using invalid data", expectedStatus, tr.Role), http.MethodPatch, - "/v1/projects/archive", - project.ProjectArchiveRequest{ + "/v1/checklists/archive", + checklist.ChecklistArchiveRequest{ ID: invalidId, }, tr.Token, @@ -778,7 +778,7 @@ func TestProjectArchive(t *testing.T) { Details: actual.Details, Error: "Field validation error", Fields: []weberror.FieldError{ - //{Field: "id", Error: "Key: 'ProjectArchiveRequest.id' Error:Field validation for 'id' failed on the 'uuid' tag"}, + //{Field: "id", Error: "Key: 'ChecklistArchiveRequest.id' Error:Field validation for 'id' failed on the 'uuid' tag"}, { Field: "id", Value: invalidId, @@ -803,9 +803,9 @@ func TestProjectArchive(t *testing.T) { rt := requestTest{ fmt.Sprintf("Archive %d w/role %s using forbidden ID", expectedStatus, tr.Role), http.MethodPatch, - "/v1/projects/archive", - project.ProjectArchiveRequest{ - ID: forbiddenProject.ID, + "/v1/checklists/archive", + checklist.ChecklistArchiveRequest{ + ID: forbiddenChecklist.ID, }, tr.Token, tr.Claims, @@ -829,7 +829,7 @@ func TestProjectArchive(t *testing.T) { expected := weberror.ErrorResponse{ StatusCode: expectedStatus, Error: http.StatusText(expectedStatus), - Details: project.ErrForbidden.Error(), + Details: checklist.ErrForbidden.Error(), StackTrace: actual.StackTrace, } @@ -840,16 +840,16 @@ func TestProjectArchive(t *testing.T) { } } -// TestProjectDelete validates delete project endpoint. -func TestProjectDelete(t *testing.T) { +// TestChecklistDelete validates delete checklist endpoint. +func TestChecklistDelete(t *testing.T) { defer tests.Recover(t) tr := roleTests[auth.RoleAdmin] - // Add claims to the context for the project. + // Add claims to the context for the checklist. ctx := context.WithValue(tests.Context(), auth.Key, tr.Claims) - forbiddenProject := newMockProject(newMockSignup().account.ID) + forbiddenChecklist := newMockChecklist(newMockSignup().account.ID) // Test delete with invalid data. { @@ -860,7 +860,7 @@ func TestProjectDelete(t *testing.T) { rt := requestTest{ fmt.Sprintf("Delete %d w/role %s using invalid data", expectedStatus, tr.Role), http.MethodDelete, - "/v1/projects/" + invalidId, + "/v1/checklists/" + invalidId, nil, tr.Token, tr.Claims, @@ -911,7 +911,7 @@ func TestProjectDelete(t *testing.T) { rt := requestTest{ fmt.Sprintf("Delete %d w/role %s using forbidden ID", expectedStatus, tr.Role), http.MethodDelete, - fmt.Sprintf("/v1/projects/%s", forbiddenProject.ID), + fmt.Sprintf("/v1/checklists/%s", forbiddenChecklist.ID), nil, tr.Token, tr.Claims, @@ -935,7 +935,7 @@ func TestProjectDelete(t *testing.T) { expected := weberror.ErrorResponse{ StatusCode: expectedStatus, Error: http.StatusText(expectedStatus), - Details: project.ErrForbidden.Error(), + Details: checklist.ErrForbidden.Error(), StackTrace: actual.StackTrace, } diff --git a/cmd/web-api/tests/tests_test.go b/cmd/web-api/tests/tests_test.go index 4defad9..1d1fff3 100644 --- a/cmd/web-api/tests/tests_test.go +++ b/cmd/web-api/tests/tests_test.go @@ -17,19 +17,19 @@ import ( "geeks-accelerator/oss/saas-starter-kit/cmd/web-api/handlers" "geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/notify" "geeks-accelerator/oss/saas-starter-kit/internal/platform/tests" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" - "geeks-accelerator/oss/saas-starter-kit/internal/project" - "geeks-accelerator/oss/saas-starter-kit/internal/project_route" "geeks-accelerator/oss/saas-starter-kit/internal/signup" "geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth" + "geeks-accelerator/oss/saas-starter-kit/internal/webroute" "github.com/google/go-cmp/cmp" "github.com/iancoleman/strcase" "github.com/pborman/uuid" @@ -93,7 +93,7 @@ func testMain(m *testing.M) int { log := test.Log log.SetOutput(ioutil.Discard) - projectRoute, err := project_route.New("http://web-api.com", "http://web-app.com") + projectRoute, err := webroute.New("http://web-api.com", "http://web-app.com") if err != nil { panic(err) } @@ -107,7 +107,7 @@ func testMain(m *testing.M) int { authRepo := user_auth.NewRepository(test.MasterDB, authenticator, usrRepo, usrAccRepo, accPrefRepo) signupRepo := signup.NewRepository(test.MasterDB, usrRepo, usrAccRepo, accRepo) inviteRepo := invite.NewRepository(test.MasterDB, usrRepo, usrAccRepo, accRepo, projectRoute.UserInviteAccept, notifyEmail, "6368616e676520746869732070613434") - prjRepo := project.NewRepository(test.MasterDB) + prjRepo := checklist.NewRepository(test.MasterDB) appCtx = &handlers.AppContext{ Log: log, diff --git a/cmd/web-app/handlers/projects.go b/cmd/web-app/handlers/checklists.go similarity index 61% rename from cmd/web-app/handlers/projects.go rename to cmd/web-app/handlers/checklists.go index 3075e9a..1c1ac7d 100644 --- a/cmd/web-app/handlers/projects.go +++ b/cmd/web-app/handlers/checklists.go @@ -6,50 +6,50 @@ import ( "net/http" "strings" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/datatable" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" - "geeks-accelerator/oss/saas-starter-kit/internal/project" "github.com/gorilla/schema" "github.com/pkg/errors" "gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis" ) -// Projects represents the Projects API method handler set. -type Projects struct { - ProjectRepo *project.Repository - Redis *redis.Client - Renderer web.Renderer +// Checklists represents the Checklists API method handler set. +type Checklists struct { + ChecklistRepo *checklist.Repository + Redis *redis.Client + Renderer web.Renderer } -func urlProjectsIndex() string { - return fmt.Sprintf("/projects") +func urlChecklistsIndex() string { + return fmt.Sprintf("/checklists") } -func urlProjectsCreate() string { - return fmt.Sprintf("/projects/create") +func urlChecklistsCreate() string { + return fmt.Sprintf("/checklists/create") } -func urlProjectsView(projectID string) string { - return fmt.Sprintf("/projects/%s", projectID) +func urlChecklistsView(checklistID string) string { + return fmt.Sprintf("/checklists/%s", checklistID) } -func urlProjectsUpdate(projectID string) string { - return fmt.Sprintf("/projects/%s/update", projectID) +func urlChecklistsUpdate(checklistID string) string { + return fmt.Sprintf("/checklists/%s/update", checklistID) } -// Index handles listing all the projects for the current account. -func (h *Projects) Index(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// Index handles listing all the checklists for the current account. +func (h *Checklists) Index(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { claims, err := auth.ClaimsFromContext(ctx) if err != nil { return err } - statusOpts := web.NewEnumResponse(ctx, nil, project.ProjectStatus_ValuesInterface()...) + statusOpts := web.NewEnumResponse(ctx, nil, checklist.ChecklistStatus_ValuesInterface()...) statusFilterItems := []datatable.FilterOptionItem{} for _, opt := range statusOpts.Options { @@ -61,13 +61,13 @@ func (h *Projects) Index(ctx context.Context, w http.ResponseWriter, r *http.Req fields := []datatable.DisplayField{ datatable.DisplayField{Field: "id", Title: "ID", Visible: false, Searchable: true, Orderable: true, Filterable: false}, - datatable.DisplayField{Field: "name", Title: "Project", Visible: true, Searchable: true, Orderable: true, Filterable: true, FilterPlaceholder: "filter Name"}, + datatable.DisplayField{Field: "name", Title: "Checklist", Visible: true, Searchable: true, Orderable: true, Filterable: true, FilterPlaceholder: "filter Name"}, datatable.DisplayField{Field: "status", Title: "Status", Visible: true, Searchable: true, Orderable: true, Filterable: true, FilterPlaceholder: "All Statuses", FilterItems: statusFilterItems}, datatable.DisplayField{Field: "updated_at", Title: "Last Updated", Visible: true, Searchable: true, Orderable: true, Filterable: false}, datatable.DisplayField{Field: "created_at", Title: "Created", Visible: true, Searchable: true, Orderable: true, Filterable: false}, } - mapFunc := func(q *project.Project, cols []datatable.DisplayField) (resp []datatable.ColumnValue, err error) { + mapFunc := func(q *checklist.Checklist, cols []datatable.DisplayField) (resp []datatable.ColumnValue, err error) { for i := 0; i < len(cols); i++ { col := cols[i] var v datatable.ColumnValue @@ -76,17 +76,17 @@ func (h *Projects) Index(ctx context.Context, w http.ResponseWriter, r *http.Req v.Value = fmt.Sprintf("%s", q.ID) case "name": v.Value = q.Name - v.Formatted = fmt.Sprintf("%s", urlProjectsView(q.ID), v.Value) + v.Formatted = fmt.Sprintf("%s", urlChecklistsView(q.ID), v.Value) case "status": v.Value = q.Status.String() var subStatusClass string var subStatusIcon string switch q.Status { - case project.ProjectStatus_Active: + case checklist.ChecklistStatus_Active: subStatusClass = "text-green" subStatusIcon = "far fa-dot-circle" - case project.ProjectStatus_Disabled: + case checklist.ChecklistStatus_Disabled: subStatusClass = "text-orange" subStatusIcon = "far fa-circle" } @@ -110,7 +110,7 @@ func (h *Projects) Index(ctx context.Context, w http.ResponseWriter, r *http.Req } loadFunc := func(ctx context.Context, sorting string, fields []datatable.DisplayField) (resp [][]datatable.ColumnValue, err error) { - res, err := h.ProjectRepo.Find(ctx, claims, project.ProjectFindRequest{ + res, err := h.ChecklistRepo.Find(ctx, claims, checklist.ChecklistFindRequest{ Where: "account_id = ?", Args: []interface{}{claims.Audience}, Order: strings.Split(sorting, ","), @@ -122,7 +122,7 @@ func (h *Projects) Index(ctx context.Context, w http.ResponseWriter, r *http.Req for _, a := range res { l, err := mapFunc(a, fields) if err != nil { - return resp, errors.Wrapf(err, "Failed to map project for display.") + return resp, errors.Wrapf(err, "Failed to map checklist for display.") } resp = append(resp, l) @@ -148,15 +148,15 @@ func (h *Projects) Index(ctx context.Context, w http.ResponseWriter, r *http.Req } data := map[string]interface{}{ - "datatable": dt.Response(), - "urlProjectsCreate": urlProjectsCreate(), + "datatable": dt.Response(), + "urlChecklistsCreate": urlChecklistsCreate(), } - return h.Renderer.Render(ctx, w, r, TmplLayoutBase, "projects-index.gohtml", web.MIMETextHTMLCharsetUTF8, http.StatusOK, data) + return h.Renderer.Render(ctx, w, r, TmplLayoutBase, "checklists-index.gohtml", web.MIMETextHTMLCharsetUTF8, http.StatusOK, data) } -// Create handles creating a new project for the account. -func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// Create handles creating a new checklist for the account. +func (h *Checklists) Create(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { ctxValues, err := webcontext.ContextValues(ctx) if err != nil { @@ -169,7 +169,7 @@ func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Re } // - req := new(project.ProjectCreateRequest) + req := new(checklist.ChecklistCreateRequest) data := make(map[string]interface{}) f := func() (bool, error) { if r.Method == http.MethodPost { @@ -186,7 +186,7 @@ func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Re } req.AccountID = claims.Audience - usr, err := h.ProjectRepo.Create(ctx, claims, *req, ctxValues.Now) + usr, err := h.ChecklistRepo.Create(ctx, claims, *req, ctxValues.Now) if err != nil { switch errors.Cause(err) { default: @@ -199,12 +199,12 @@ func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Re } } - // Display a success message to the project. + // Display a success message to the checklist. webcontext.SessionFlashSuccess(ctx, - "Project Created", - "Project successfully created.") + "Checklist Created", + "Checklist successfully created.") - return true, web.Redirect(ctx, w, r, urlProjectsView(usr.ID), http.StatusFound) + return true, web.Redirect(ctx, w, r, urlChecklistsView(usr.ID), http.StatusFound) } return false, nil @@ -219,17 +219,17 @@ func (h *Projects) Create(ctx context.Context, w http.ResponseWriter, r *http.Re data["form"] = req - if verr, ok := weberror.NewValidationError(ctx, webcontext.Validator().Struct(project.ProjectCreateRequest{})); ok { + if verr, ok := weberror.NewValidationError(ctx, webcontext.Validator().Struct(checklist.ChecklistCreateRequest{})); ok { data["validationDefaults"] = verr.(*weberror.Error) } - return h.Renderer.Render(ctx, w, r, TmplLayoutBase, "projects-create.gohtml", web.MIMETextHTMLCharsetUTF8, http.StatusOK, data) + return h.Renderer.Render(ctx, w, r, TmplLayoutBase, "checklists-create.gohtml", web.MIMETextHTMLCharsetUTF8, http.StatusOK, data) } -// View handles displaying a project. -func (h *Projects) View(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// View handles displaying a checklist. +func (h *Checklists) View(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { - projectID := params["project_id"] + checklistID := params["checklist_id"] ctxValues, err := webcontext.ContextValues(ctx) if err != nil { @@ -251,18 +251,18 @@ func (h *Projects) View(ctx context.Context, w http.ResponseWriter, r *http.Requ switch r.PostForm.Get("action") { case "archive": - err = h.ProjectRepo.Archive(ctx, claims, project.ProjectArchiveRequest{ - ID: projectID, + err = h.ChecklistRepo.Archive(ctx, claims, checklist.ChecklistArchiveRequest{ + ID: checklistID, }, ctxValues.Now) if err != nil { return false, err } webcontext.SessionFlashSuccess(ctx, - "Project Archive", - "Project successfully archive.") + "Checklist Archive", + "Checklist successfully archive.") - return true, web.Redirect(ctx, w, r, urlProjectsIndex(), http.StatusFound) + return true, web.Redirect(ctx, w, r, urlChecklistsIndex(), http.StatusFound) } } @@ -276,21 +276,21 @@ func (h *Projects) View(ctx context.Context, w http.ResponseWriter, r *http.Requ return nil } - prj, err := h.ProjectRepo.ReadByID(ctx, claims, projectID) + prj, err := h.ChecklistRepo.ReadByID(ctx, claims, checklistID) if err != nil { return err } - data["project"] = prj.Response(ctx) - data["urlProjectsView"] = urlProjectsView(projectID) - data["urlProjectsUpdate"] = urlProjectsUpdate(projectID) + data["checklist"] = prj.Response(ctx) + data["urlChecklistsView"] = urlChecklistsView(checklistID) + data["urlChecklistsUpdate"] = urlChecklistsUpdate(checklistID) - return h.Renderer.Render(ctx, w, r, TmplLayoutBase, "projects-view.gohtml", web.MIMETextHTMLCharsetUTF8, http.StatusOK, data) + return h.Renderer.Render(ctx, w, r, TmplLayoutBase, "checklists-view.gohtml", web.MIMETextHTMLCharsetUTF8, http.StatusOK, data) } -// Update handles updating a project for the account. -func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { +// Update handles updating a checklist for the account. +func (h *Checklists) Update(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error { - projectID := params["project_id"] + checklistID := params["checklist_id"] ctxValues, err := webcontext.ContextValues(ctx) if err != nil { @@ -303,7 +303,7 @@ func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Re } // - req := new(project.ProjectUpdateRequest) + req := new(checklist.ChecklistUpdateRequest) data := make(map[string]interface{}) f := func() (bool, error) { if r.Method == http.MethodPost { @@ -318,9 +318,9 @@ func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Re if err := decoder.Decode(req, r.PostForm); err != nil { return false, err } - req.ID = projectID + req.ID = checklistID - err = h.ProjectRepo.Update(ctx, claims, *req, ctxValues.Now) + err = h.ChecklistRepo.Update(ctx, claims, *req, ctxValues.Now) if err != nil { switch errors.Cause(err) { default: @@ -333,12 +333,12 @@ func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Re } } - // Display a success message to the project. + // Display a success message to the checklist. webcontext.SessionFlashSuccess(ctx, - "Project Updated", - "Project successfully updated.") + "Checklist Updated", + "Checklist successfully updated.") - return true, web.Redirect(ctx, w, r, urlProjectsView(req.ID), http.StatusFound) + return true, web.Redirect(ctx, w, r, urlChecklistsView(req.ID), http.StatusFound) } return false, nil @@ -351,13 +351,13 @@ func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Re return nil } - prj, err := h.ProjectRepo.ReadByID(ctx, claims, projectID) + prj, err := h.ChecklistRepo.ReadByID(ctx, claims, checklistID) if err != nil { return err } - data["project"] = prj.Response(ctx) + data["checklist"] = prj.Response(ctx) - data["urlProjectsView"] = urlProjectsView(projectID) + data["urlChecklistsView"] = urlChecklistsView(checklistID) if req.ID == "" { req.Name = &prj.Name @@ -365,9 +365,9 @@ func (h *Projects) Update(ctx context.Context, w http.ResponseWriter, r *http.Re } data["form"] = req - if verr, ok := weberror.NewValidationError(ctx, webcontext.Validator().Struct(project.ProjectUpdateRequest{})); ok { + if verr, ok := weberror.NewValidationError(ctx, webcontext.Validator().Struct(checklist.ChecklistUpdateRequest{})); ok { data["validationDefaults"] = verr.(*weberror.Error) } - return h.Renderer.Render(ctx, w, r, TmplLayoutBase, "projects-update.gohtml", web.MIMETextHTMLCharsetUTF8, http.StatusOK, data) + return h.Renderer.Render(ctx, w, r, TmplLayoutBase, "checklists-update.gohtml", web.MIMETextHTMLCharsetUTF8, http.StatusOK, data) } diff --git a/cmd/web-app/handlers/root.go b/cmd/web-app/handlers/root.go index d31b6c7..9940dab 100644 --- a/cmd/web-app/handlers/root.go +++ b/cmd/web-app/handlers/root.go @@ -8,7 +8,7 @@ import ( "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" - "geeks-accelerator/oss/saas-starter-kit/internal/project_route" + "geeks-accelerator/oss/saas-starter-kit/internal/webroute" "github.com/ikeikeikeike/go-sitemap-generator/v2/stm" "github.com/pkg/errors" @@ -19,9 +19,9 @@ import ( // Root represents the Root API method handler set. type Root struct { - Renderer web.Renderer - Sitemap *stm.Sitemap - ProjectRoute project_route.ProjectRoute + Renderer web.Renderer + Sitemap *stm.Sitemap + WebRoute webroute.WebRoute } // Index determines if the user has authentication and loads the associated page. @@ -56,7 +56,7 @@ func (h *Root) SitePage(ctx context.Context, w http.ResponseWriter, r *http.Requ tmpName = "site-api.gohtml" // http://127.0.0.1:3001/docs/doc.json - swaggerJsonUrl := h.ProjectRoute.ApiDocsJson(true) + swaggerJsonUrl := h.WebRoute.ApiDocsJson(true) // Load the json file from the API service. res, err := pester.Get(swaggerJsonUrl) @@ -92,8 +92,8 @@ func (h *Root) SitePage(ctx context.Context, w http.ResponseWriter, r *http.Requ return errors.WithStack(err) } - data["urlApiBaseUri"] = h.ProjectRoute.WebApiUrl(doc.BasePath) - data["urlApiDocs"] = h.ProjectRoute.ApiDocs() + data["urlApiBaseUri"] = h.WebRoute.WebApiUrl(doc.BasePath) + data["urlApiDocs"] = h.WebRoute.ApiDocs() case "/pricing": tmpName = "site-pricing.gohtml" @@ -122,7 +122,7 @@ func (h *Root) RobotTxt(ctx context.Context, w http.ResponseWriter, r *http.Requ return web.RespondText(ctx, w, txt, http.StatusOK) } - sitemapUrl := h.ProjectRoute.WebAppUrl("/sitemap.xml") + sitemapUrl := h.WebRoute.WebAppUrl("/sitemap.xml") txt := fmt.Sprintf("User-agent: *\nDisallow: /ping\nDisallow: /status\nDisallow: /debug/\nSitemap: %s", sitemapUrl) return web.RespondText(ctx, w, txt, http.StatusOK) diff --git a/cmd/web-app/handlers/routes.go b/cmd/web-app/handlers/routes.go index b0df47b..75158ed 100644 --- a/cmd/web-app/handlers/routes.go +++ b/cmd/web-app/handlers/routes.go @@ -11,19 +11,19 @@ import ( "geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/geonames" "geeks-accelerator/oss/saas-starter-kit/internal/mid" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" - "geeks-accelerator/oss/saas-starter-kit/internal/project" - "geeks-accelerator/oss/saas-starter-kit/internal/project_route" "geeks-accelerator/oss/saas-starter-kit/internal/signup" "geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth" + "geeks-accelerator/oss/saas-starter-kit/internal/webroute" "github.com/aws/aws-sdk-go/aws/session" "github.com/ikeikeikeike/go-sitemap-generator/v2/stm" @@ -50,13 +50,13 @@ type AppContext struct { AuthRepo *user_auth.Repository SignupRepo *signup.Repository InviteRepo *invite.Repository - ProjectRepo *project.Repository + ChecklistRepo *checklist.Repository GeoRepo *geonames.Repository Authenticator *auth.Authenticator StaticDir string TemplateDir string Renderer web.Renderer - ProjectRoute project_route.ProjectRoute + WebRoute webroute.WebRoute PreAppMiddleware []web.Middleware PostAppMiddleware []web.Middleware AwsSession *session.Session @@ -105,7 +105,7 @@ func APP(shutdown chan os.Signal, appCtx *AppContext) http.Handler { // Build a sitemap. sm := stm.NewSitemap(1) sm.SetVerbose(false) - sm.SetDefaultHost(appCtx.ProjectRoute.WebAppUrl("")) + sm.SetDefaultHost(appCtx.WebRoute.WebAppUrl("")) sm.Create() smLocAddModified := func(loc stm.URL, filename string) { @@ -121,19 +121,19 @@ func APP(shutdown chan os.Signal, appCtx *AppContext) http.Handler { sm.Add(loc) } - // Register project management pages. - p := Projects{ - ProjectRepo: appCtx.ProjectRepo, - Redis: appCtx.Redis, - Renderer: appCtx.Renderer, + // Register checklist management pages. + p := Checklists{ + ChecklistRepo: appCtx.ChecklistRepo, + Redis: appCtx.Redis, + Renderer: appCtx.Renderer, } - app.Handle("POST", "/projects/:project_id/update", p.Update, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) - app.Handle("GET", "/projects/:project_id/update", p.Update, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) - app.Handle("POST", "/projects/:project_id", p.View, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) - app.Handle("GET", "/projects/:project_id", p.View, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasAuth()) - app.Handle("POST", "/projects/create", p.Create, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) - app.Handle("GET", "/projects/create", p.Create, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) - app.Handle("GET", "/projects", p.Index, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasAuth()) + app.Handle("POST", "/checklists/:checklist_id/update", p.Update, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("GET", "/checklists/:checklist_id/update", p.Update, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("POST", "/checklists/:checklist_id", p.View, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("GET", "/checklists/:checklist_id", p.View, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasAuth()) + app.Handle("POST", "/checklists/create", p.Create, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("GET", "/checklists/create", p.Create, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasRole(auth.RoleAdmin)) + app.Handle("GET", "/checklists", p.Index, mid.AuthenticateSessionRequired(appCtx.Authenticator), mid.HasAuth()) // Register user management pages. us := Users{ @@ -231,9 +231,9 @@ func APP(shutdown chan os.Signal, appCtx *AppContext) http.Handler { // Register root r := Root{ - Renderer: appCtx.Renderer, - ProjectRoute: appCtx.ProjectRoute, - Sitemap: sm, + Renderer: appCtx.Renderer, + WebRoute: appCtx.WebRoute, + Sitemap: sm, } app.Handle("GET", "/api", r.SitePage) app.Handle("GET", "/pricing", r.SitePage) diff --git a/cmd/web-app/main.go b/cmd/web-app/main.go index 31674d5..219ab63 100644 --- a/cmd/web-app/main.go +++ b/cmd/web-app/main.go @@ -23,6 +23,7 @@ import ( "geeks-accelerator/oss/saas-starter-kit/cmd/web-app/handlers" "geeks-accelerator/oss/saas-starter-kit/internal/account" "geeks-accelerator/oss/saas-starter-kit/internal/account/account_preference" + "geeks-accelerator/oss/saas-starter-kit/internal/checklist" "geeks-accelerator/oss/saas-starter-kit/internal/geonames" "geeks-accelerator/oss/saas-starter-kit/internal/mid" "geeks-accelerator/oss/saas-starter-kit/internal/platform/auth" @@ -30,16 +31,15 @@ import ( img_resize "geeks-accelerator/oss/saas-starter-kit/internal/platform/img-resize" "geeks-accelerator/oss/saas-starter-kit/internal/platform/notify" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web" - template_renderer "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/template-renderer" + template_renderer "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/tmplrender" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/webcontext" "geeks-accelerator/oss/saas-starter-kit/internal/platform/web/weberror" - "geeks-accelerator/oss/saas-starter-kit/internal/project" - "geeks-accelerator/oss/saas-starter-kit/internal/project_route" "geeks-accelerator/oss/saas-starter-kit/internal/signup" "geeks-accelerator/oss/saas-starter-kit/internal/user" "geeks-accelerator/oss/saas-starter-kit/internal/user_account" "geeks-accelerator/oss/saas-starter-kit/internal/user_account/invite" "geeks-accelerator/oss/saas-starter-kit/internal/user_auth" + "geeks-accelerator/oss/saas-starter-kit/internal/webroute" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" @@ -440,20 +440,20 @@ func main() { // ========================================================================= // Init repositories and AppContext - projectRoute, err := project_route.New(cfg.Project.WebApiBaseUrl, cfg.Service.BaseUrl) + webRoute, err := webroute.New(cfg.Project.WebApiBaseUrl, cfg.Service.BaseUrl) if err != nil { - log.Fatalf("main : project routes : %+v", cfg.Service.BaseUrl, err) + log.Fatalf("main : checklist routes : %+v", cfg.Service.BaseUrl, err) } - usrRepo := user.NewRepository(masterDb, projectRoute.UserResetPassword, notifyEmail, cfg.Project.SharedSecretKey) + usrRepo := user.NewRepository(masterDb, webRoute.UserResetPassword, notifyEmail, cfg.Project.SharedSecretKey) usrAccRepo := user_account.NewRepository(masterDb) accRepo := account.NewRepository(masterDb) geoRepo := geonames.NewRepository(masterDb) accPrefRepo := account_preference.NewRepository(masterDb) authRepo := user_auth.NewRepository(masterDb, authenticator, usrRepo, usrAccRepo, accPrefRepo) signupRepo := signup.NewRepository(masterDb, usrRepo, usrAccRepo, accRepo) - inviteRepo := invite.NewRepository(masterDb, usrRepo, usrAccRepo, accRepo, projectRoute.UserInviteAccept, notifyEmail, cfg.Project.SharedSecretKey) - prjRepo := project.NewRepository(masterDb) + inviteRepo := invite.NewRepository(masterDb, usrRepo, usrAccRepo, accRepo, webRoute.UserInviteAccept, notifyEmail, cfg.Project.SharedSecretKey) + chklstRepo := checklist.NewRepository(masterDb) appCtx := &handlers.AppContext{ Log: log, @@ -463,7 +463,7 @@ func main() { Redis: redisClient, TemplateDir: cfg.Service.TemplateDir, StaticDir: cfg.Service.StaticFiles.Dir, - ProjectRoute: projectRoute, + WebRoute: webRoute, UserRepo: usrRepo, UserAccountRepo: usrAccRepo, AccountRepo: accRepo, @@ -472,7 +472,7 @@ func main() { GeoRepo: geoRepo, SignupRepo: signupRepo, InviteRepo: inviteRepo, - ProjectRepo: prjRepo, + ChecklistRepo: chklstRepo, Authenticator: authenticator, AwsSession: awsSession, } @@ -525,13 +525,14 @@ func main() { staticS3UrlFormatter = func(p string) string { // When the path starts with a forward slash its referencing a local file, // make sure the static file prefix is included - if strings.HasPrefix(p, "/") || !strings.HasPrefix(p, "://") { + if (strings.HasPrefix(p, "/") || !strings.HasPrefix(p, "://")) && !strings.HasPrefix(p, cfg.Service.StaticFiles.S3Prefix) { p = filepath.Join(cfg.Service.StaticFiles.S3Prefix, p) } + return s3UrlFormatter(p) } } else { - staticS3UrlFormatter = projectRoute.WebAppUrl + staticS3UrlFormatter = webRoute.WebAppUrl } // staticUrlFormatter is a help function used by template functions defined below. @@ -920,11 +921,12 @@ func main() { tmplFuncs["S3ImgUrl"] = func(ctx context.Context, p string, size int) string { imgUrl := imgUrlFormatter(p) if cfg.Service.StaticFiles.ImgResizeEnabled { + var rerr error imgUrl, rerr = img_resize.S3ImgUrl(ctx, redisClient, staticS3UrlFormatter, awsSession, cfg.Aws.S3BucketPublic, imgResizeS3KeyPrefix, imgUrl, size) if rerr != nil { imgUrl = "error" - log.Printf("main : S3ImgUrl : %s - %s\n", p, rerr) + log.Printf("main : S3ImgUrl : %s - %+v\n", p, rerr) } } return imgUrl diff --git a/cmd/web-app/templates/content/projects-create.gohtml b/cmd/web-app/templates/content/checklists-create.gohtml similarity index 76% rename from cmd/web-app/templates/content/projects-create.gohtml rename to cmd/web-app/templates/content/checklists-create.gohtml index 3b498fc..1250a51 100644 --- a/cmd/web-app/templates/content/projects-create.gohtml +++ b/cmd/web-app/templates/content/checklists-create.gohtml @@ -1,4 +1,4 @@ -{{define "title"}}Create Project{{end}} +{{define "title"}}Create Checklist{{end}} {{define "style"}} {{end}} @@ -6,13 +6,13 @@