Skip to content

Commit

Permalink
feat(notes): store author_id if user authorized
Browse files Browse the repository at this point in the history
  • Loading branch information
olexsmir committed Jul 25, 2024
1 parent 6408609 commit 30fbeb5
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
1 change: 0 additions & 1 deletion internal/dtos/note.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ func (n NoteSlugDTO) String() string { return string(n) }

type NoteDTO struct {
Content string
UserID uuid.UUID
Slug string
BurnBeforeExpiration bool
CreatedAt time.Time
Expand Down
27 changes: 22 additions & 5 deletions internal/service/notesrv/notesrv.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ package notesrv
import (
"context"

"github.com/google/uuid"
"github.com/gofrs/uuid/v5"
"github.com/olexsmir/onasty/internal/dtos"
"github.com/olexsmir/onasty/internal/models"
"github.com/olexsmir/onasty/internal/store/psql/noterepo"
)

type NoteServicer interface {
Create(ctx context.Context, note dtos.CreateNoteDTO) (dtos.NoteSlugDTO, error)
// Create create note
// if slug is empty it will be generated, otherwise used as is
// if userID is empty it means user isn't authorized so it will be used
Create(ctx context.Context, note dtos.CreateNoteDTO, userID uuid.UUID) (dtos.NoteSlugDTO, error)
GetBySlugAndRemoveIfNeeded(ctx context.Context, slug dtos.NoteSlugDTO) (dtos.NoteDTO, error)
}

Expand All @@ -26,13 +29,27 @@ func New(noterepo noterepo.NoteStorer) NoteServicer {
}
}

func (n *NoteSrv) Create(ctx context.Context, inp dtos.CreateNoteDTO) (dtos.NoteSlugDTO, error) {
func (n *NoteSrv) Create(
ctx context.Context,
inp dtos.CreateNoteDTO,
userID uuid.UUID,
) (dtos.NoteSlugDTO, error) {
if inp.Slug == "" {
inp.Slug = uuid.New().String()
inp.Slug = uuid.Must(uuid.NewV4()).String()
}

err := n.noterepo.Create(ctx, inp)
return dtos.NoteSlugDTO(inp.Slug), err
if err != nil {
return "", err
}

if !userID.IsNil() {
if err := n.noterepo.SetAuthorIDBySlug(ctx, dtos.NoteSlugDTO(inp.Slug), userID); err != nil {
return "", err
}
}

return dtos.NoteSlugDTO(inp.Slug), nil
}

func (n *NoteSrv) GetBySlugAndRemoveIfNeeded(
Expand Down
40 changes: 38 additions & 2 deletions internal/store/psql/noterepo/noterepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"

"github.com/gofrs/uuid/v5"
"github.com/henvic/pgq"
"github.com/jackc/pgx/v5"
"github.com/olexsmir/onasty/internal/dtos"
Expand All @@ -15,6 +16,8 @@ type NoteStorer interface {
Create(ctx context.Context, inp dtos.CreateNoteDTO) error
GetBySlug(ctx context.Context, slug dtos.NoteSlugDTO) (dtos.NoteDTO, error)
DeleteBySlug(ctx context.Context, slug dtos.NoteSlugDTO) error

SetAuthorIDBySlug(ctx context.Context, slug dtos.NoteSlugDTO, authorID uuid.UUID) error
}

var _ NoteStorer = (*NoteRepo)(nil)
Expand All @@ -30,8 +33,8 @@ func New(db *psqlutil.DB) NoteStorer {
func (s *NoteRepo) Create(ctx context.Context, inp dtos.CreateNoteDTO) error {
query, args, err := pgq.
Insert("notes").
Columns("content", "user_id", "slug", "burn_before_expiration ", "created_at", "expires_at").
Values(inp.Content, inp.UserID, inp.Slug, inp.BurnBeforeExpiration, inp.CreatedAt, inp.ExpiresAt).
Columns("content", "slug", "burn_before_expiration ", "created_at", "expires_at").
Values(inp.Content, inp.Slug, inp.BurnBeforeExpiration, inp.CreatedAt, inp.ExpiresAt).
SQL()
if err != nil {
return err
Expand Down Expand Up @@ -82,3 +85,36 @@ func (s *NoteRepo) DeleteBySlug(ctx context.Context, slug dtos.NoteSlugDTO) erro

return err
}

func (s *NoteRepo) SetAuthorIDBySlug(
ctx context.Context,
slug dtos.NoteSlugDTO,
authorID uuid.UUID,
) error {
tx, err := s.db.Begin(ctx)
if err != nil {
return err
}
defer tx.Rollback(ctx) //nolint:errcheck

var noteID uuid.UUID
err = tx.QueryRow(ctx, "select id from notes where slug = $1", slug.String()).Scan(&noteID)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return models.ErrNoteNotFound
}
return err
}

_, err = tx.Exec(
ctx,
"insert into notes_authors (note_id, user_id) values ($1, $2)",
noteID,
authorID,
)
if err != nil {
return err
}

return tx.Commit(ctx)
}
6 changes: 5 additions & 1 deletion internal/transport/http/apiv1/note.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package apiv1

import (
"log/slog"
"net/http"
"time"

Expand Down Expand Up @@ -38,16 +39,19 @@ func (a *APIV1) createNoteHandler(c *gin.Context) {
if err := note.Validate(); err != nil {
newErrorStatus(c, http.StatusBadRequest, err.Error())
return

}

Check failure on line 43 in internal/transport/http/apiv1/note.go

View workflow job for this annotation

GitHub Actions / golang

unnecessary trailing newline (whitespace)

Check failure on line 43 in internal/transport/http/apiv1/note.go

View workflow job for this annotation

GitHub Actions / golang

unnecessary trailing newline (whitespace)

slog.Debug("userid", "a", a.getUserID(c))

slug, err := a.notesrv.Create(c.Request.Context(), dtos.CreateNoteDTO{
Content: note.Content,
UserID: a.getUserID(c),
Slug: note.Slug,
BurnBeforeExpiration: note.BurnBeforeExpiration,
CreatedAt: note.CreatedAt,
ExpiresAt: note.ExpiresAt,
})
}, a.getUserID(c))
if err != nil {
errorResponse(c, err)
return
Expand Down

0 comments on commit 30fbeb5

Please sign in to comment.