6 files changed,
119 insertions(+),
1 deletions(-)
Author:
Smirnov Oleksandr
ss2316544@gmail.com
Committed by:
GitHub
noreply@github.com
Committed at:
2025-06-25 16:06:29 +0300
Parent:
e4abd99
M
e2e/apiv1_notes_test.go
··· 222 222 ) 223 223 e.Equal(httpResp.Code, http.StatusNotFound) 224 224 } 225 + 226 +type apiv1NoteMetadataResponse struct { 227 + CreatedAt time.Time `json:"created_at"` 228 + HasPassword bool `json:"has_password"` 229 +} 230 + 231 +func (e *AppTestSuite) TestNoteV1_GetMetadata() { 232 + // create note 233 + httpResp := e.httpRequest( 234 + http.MethodPost, 235 + "/api/v1/note", 236 + e.jsonify(apiv1NoteCreateRequest{Content: "content"}), //nolint:exhaustruct 237 + ) 238 + e.Equal(http.StatusCreated, httpResp.Code) 239 + 240 + var bodyCreated apiv1NoteCreateResponse 241 + e.readBodyAndUnjsonify(httpResp.Body, &bodyCreated) 242 + 243 + // get metadata 244 + metaResp := e.httpRequest(http.MethodGet, "/api/v1/note/"+bodyCreated.Slug+"/meta", []byte{}) 245 + e.Equal(metaResp.Code, http.StatusOK) 246 + 247 + var metadata apiv1NoteMetadataResponse 248 + e.readBodyAndUnjsonify(metaResp.Body, &metadata) 249 + 250 + e.False(metadata.HasPassword) 251 + e.NotEmpty(metadata.CreatedAt) 252 +} 253 + 254 +func (e *AppTestSuite) TestNoteV1_GetMetadata_withPassword() { 255 + // create note 256 + httpResp := e.httpRequest( 257 + http.MethodPost, 258 + "/api/v1/note", 259 + e.jsonify(apiv1NoteCreateRequest{ //nolint:exhaustruct 260 + Content: "content", 261 + Password: "pass", 262 + }), 263 + ) 264 + e.Equal(http.StatusCreated, httpResp.Code) 265 + 266 + var bodyCreated apiv1NoteCreateResponse 267 + e.readBodyAndUnjsonify(httpResp.Body, &bodyCreated) 268 + 269 + // get metadata 270 + metaResp := e.httpRequest(http.MethodGet, "/api/v1/note/"+bodyCreated.Slug+"/meta", []byte{}) 271 + e.Equal(metaResp.Code, http.StatusOK) 272 + 273 + var metadata apiv1NoteMetadataResponse 274 + e.readBodyAndUnjsonify(metaResp.Body, &metadata) 275 + 276 + e.True(metadata.HasPassword) 277 + e.NotEmpty(metadata.CreatedAt) 278 +} 279 + 280 +func (e *AppTestSuite) TestNoteV1_GetMetadata_notFound() { 281 + metaResp := e.httpRequest(http.MethodGet, "/api/v1/note/"+e.uuid()+"/meta", []byte{}) 282 + e.Equal(http.StatusNotFound, metaResp.Code) 283 +}
M
internal/service/notesrv/notesrv.go
··· 23 23 Create(ctx context.Context, note dtos.CreateNote, userID uuid.UUID) (dtos.NoteSlug, error) 24 24 25 25 // GetBySlugAndRemoveIfNeeded returns note by slug, and removes if if needed. 26 - // If notes is not found returns [models.ErrNoteNotFound]. 26 + // If note is not found returns [models.ErrNoteNotFound]. 27 27 GetBySlugAndRemoveIfNeeded( 28 28 ctx context.Context, 29 29 input GetNoteBySlugInput, 30 30 ) (dtos.GetNote, error) 31 + 32 + // GetNoteMetadataBySlug returns note metadata by slug. 33 + // If note is not found returns [models.ErrNoteNotFound]. 34 + GetNoteMetadataBySlug(ctx context.Context, slug dtos.NoteSlug) (dtos.NoteMetadata, error) 31 35 32 36 // GetAllByAuthorID returns all notes by author id. 33 37 GetAllByAuthorID( ··· 140 144 } 141 145 142 146 return respNote, n.noterepo.RemoveBySlug(ctx, inp.Slug, time.Now()) 147 +} 148 + 149 +func (n *NoteSrv) GetNoteMetadataBySlug( 150 + ctx context.Context, 151 + slug dtos.NoteSlug, 152 +) (dtos.NoteMetadata, error) { 153 + note, err := n.noterepo.GetMetadataBySlug(ctx, slug) 154 + return note, err 143 155 } 144 156 145 157 func (n *NoteSrv) GetAllByAuthorID(
M
internal/store/psql/noterepo/noterepo.go
··· 21 21 // Returns [models.ErrNoteNotFound] if note is not found. 22 22 GetBySlug(ctx context.Context, slug dtos.NoteSlug) (models.Note, error) 23 23 24 + // GetMetadataBySlug gets note's metadata by its slug. 25 + // Returns [models.ErrNoteNotFound] if note is not found. 26 + GetMetadataBySlug(ctx context.Context, slug dtos.NoteSlug) (dtos.NoteMetadata, error) 27 + 24 28 // GetAllByAuthorID returns all notes with specified author. 25 29 GetAllByAuthorID(ctx context.Context, authorID uuid.UUID) ([]models.Note, error) 26 30 ··· 112 116 } 113 117 114 118 return note, err 119 +} 120 + 121 +func (s *NoteRepo) GetMetadataBySlug( 122 + ctx context.Context, 123 + slug dtos.NoteSlug, 124 +) (dtos.NoteMetadata, error) { 125 + query := `--sql 126 + select n.created_at, (n.password is not null and n.password <> '') has_password 127 + from notes n 128 + where slug = $1 129 + ` 130 + 131 + var metadata dtos.NoteMetadata 132 + err := s.db.QueryRow(ctx, query, slug).Scan(&metadata.CreatedAt, &metadata.HasPassword) 133 + if errors.Is(err, pgx.ErrNoRows) { 134 + return dtos.NoteMetadata{}, models.ErrNoteNotFound 135 + } 136 + 137 + return metadata, err 115 138 } 116 139 117 140 func (s *NoteRepo) GetAllByAuthorID(
M
internal/transport/http/apiv1/note.go
··· 92 92 }) 93 93 } 94 94 95 +type getNoteMetadataBySlugResponse struct { 96 + CreatedAt time.Time `json:"created_at"` 97 + HasPassword bool `json:"has_password"` 98 +} 99 + 100 +func (a *APIV1) getNoteMetadataByIDHandler(c *gin.Context) { 101 + meta, err := a.notesrv.GetNoteMetadataBySlug(c.Request.Context(), c.Param("slug")) 102 + if err != nil { 103 + errorResponse(c, err) 104 + return 105 + } 106 + 107 + c.JSON(http.StatusOK, getNoteMetadataBySlugResponse{ 108 + CreatedAt: meta.CreatedAt, 109 + HasPassword: meta.HasPassword, 110 + }) 111 +} 112 + 95 113 type getNotesResponse struct { 96 114 Content string `json:"content"` 97 115 Slug string `json:"slug"`