Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions services/nexus/internal/http/controllers/v1/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ func NewController(logger *zap.Logger, db *sqlx.DB) *Controller {
TemplatesController: NewTemplatesController(logger, db),
AdminsController: NewAdminsController(logger, db),
UsersController: NewUsersController(logger, db),
TagsController: NewTagsController(logger, db),
}
}

Expand All @@ -19,4 +20,5 @@ type Controller struct {
*TemplatesController
*AdminsController
*UsersController
*TagsController
}
158 changes: 158 additions & 0 deletions services/nexus/internal/http/controllers/v1/tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package v1

import (
"errors"
"net/http"

"github.com/google/uuid"
"github.com/jmoiron/sqlx"
"github.com/lunogram/platform/pkg/http/json"
"github.com/lunogram/platform/pkg/http/problem"
"github.com/lunogram/platform/services/nexus/internal/store"
"github.com/lunogram/platform/services/nexus/oapi"
"go.uber.org/zap"
)

func NewTagsController(logger *zap.Logger, db *sqlx.DB) *TagsController {
return &TagsController{
logger: logger,
db: db,
store: store.NewStores(db),
}
}

type TagsController struct {
logger *zap.Logger
db *sqlx.DB
store *store.Stores
}

func (srv *TagsController) CreateTag(w http.ResponseWriter, r *http.Request, projectID uuid.UUID) {
ctx := r.Context()
body := oapi.CreateTagJSONRequestBody{}
err := json.Decode(r.Body, &body)
if err != nil {
oapi.WriteProblem(w, err)
return
}

logger := srv.logger.With(zap.Stringer("project_id", projectID), zap.String("name", body.Name))
logger.Info("creating tag")

tagID, err := srv.store.TagsStore.CreateTag(ctx, projectID, body.Name)
if err != nil {
logger.Error("failed to create tag", zap.Error(err))
oapi.WriteProblem(w, err)
return
}

tag, err := srv.store.TagsStore.GetTag(ctx, projectID, tagID)
if err != nil {
logger.Error("failed to fetch created tag", zap.Error(err))
oapi.WriteProblem(w, err)
return
}

logger.Info("tag created", zap.Stringer("tag_id", tagID))
json.Write(w, http.StatusCreated, tag.OAPI())
}

func (srv *TagsController) ListTags(w http.ResponseWriter, r *http.Request, projectID uuid.UUID, params oapi.ListTagsParams) {
ctx := r.Context()
logger := srv.logger.With(zap.Stringer("project_id", projectID))
logger.Info("listing tags")

pagination := store.Pagination{
Limit: params.Limit.ToInt(),
Offset: params.Offset.ToInt(),
}

result, total, err := srv.store.TagsStore.ListTags(ctx, projectID, pagination, params.Search.ToString())
if err != nil {
logger.Error("failed to list tags", zap.Error(err))
oapi.WriteProblem(w, err)
return
}

logger.Info("listed tags", zap.Int("count", len(result)))
json.Write(w, http.StatusOK, oapi.TagListResponse{
Total: total,
Limit: pagination.Limit,
Offset: pagination.Offset,
Results: result.OAPI(),
})
}

func (srv *TagsController) GetTag(w http.ResponseWriter, r *http.Request, projectID uuid.UUID, tagID uuid.UUID) {
ctx := r.Context()
logger := srv.logger.With(zap.Stringer("project_id", projectID), zap.Stringer("tag_id", tagID))
logger.Info("getting tag")

tag, err := srv.store.TagsStore.GetTag(ctx, projectID, tagID)
if errors.Is(err, store.ErrNoRows) {
logger.Error("tag not found", zap.Stringer("tag_id", tagID))
oapi.WriteProblem(w, problem.ErrNotFound(problem.Describe("tag not found")))
return
}

if err != nil {
logger.Error("failed to fetch tag", zap.Error(err))
oapi.WriteProblem(w, err)
return
}

logger.Info("tag retrieved")
json.Write(w, http.StatusOK, tag.OAPI())
}

func (srv *TagsController) UpdateTag(w http.ResponseWriter, r *http.Request, projectID uuid.UUID, tagID uuid.UUID) {
logger := srv.logger.With(zap.Stringer("project_id", projectID), zap.Stringer("tag_id", tagID))
logger.Info("updating tag")

ctx := r.Context()
body := oapi.UpdateTagJSONRequestBody{}
err := json.Decode(r.Body, &body)
if err != nil {
oapi.WriteProblem(w, err)
return
}

err = srv.store.TagsStore.UpdateTag(ctx, projectID, tagID, body.Name)
if err != nil {
logger.Error("failed to update tag", zap.Error(err))
oapi.WriteProblem(w, err)
return
}

tag, err := srv.store.TagsStore.GetTag(ctx, projectID, tagID)
if errors.Is(err, store.ErrNoRows) {
logger.Error("tag not found", zap.Stringer("tag_id", tagID))
oapi.WriteProblem(w, problem.ErrNotFound(problem.Describe("tag not found")))
return
}

if err != nil {
logger.Error("failed to fetch updated tag", zap.Error(err))
oapi.WriteProblem(w, err)
return
}

logger.Info("tag updated")
json.Write(w, http.StatusOK, tag.OAPI())
}

func (srv *TagsController) DeleteTag(w http.ResponseWriter, r *http.Request, projectID uuid.UUID, tagID uuid.UUID) {
ctx := r.Context()
logger := srv.logger.With(zap.Stringer("project_id", projectID), zap.Stringer("tag_id", tagID))
logger.Info("deleting tag")

err := srv.store.TagsStore.DeleteTag(ctx, projectID, tagID)
if err != nil {
logger.Error("failed to delete tag", zap.Error(err))
oapi.WriteProblem(w, err)
return
}

logger.Info("tag deleted")
w.WriteHeader(http.StatusNoContent)
}
Loading