5 files changed,
73 insertions(+),
24 deletions(-)
Author:
Olexandr Smirnov
ss2316544@gmail.com
Committed by:
GitHub
noreply@github.com
Committed at:
2025-07-15 14:36:15 +0300
Parent:
36f59cd
M
e2e/apiv1_notes_test.go
··· 139 139 e.Equal(dbNote.ReadAt.IsZero(), false) 140 140 } 141 141 142 +type apiv1NoteGetWithPasswordRequest struct { 143 + Password string `json:"password"` 144 +} 145 + 142 146 func (e *AppTestSuite) TestNoteV1_GetWithPassword() { 143 147 content := e.uuid() 144 148 passwd := e.uuid() ··· 156 160 e.readBodyAndUnjsonify(httpResp.Body, &bodyCreated) 157 161 158 162 httpResp = e.httpRequest( 159 - http.MethodGet, 160 - "/api/v1/note/"+bodyCreated.Slug+"?password="+passwd, 161 - nil, 163 + http.MethodPost, 164 + "/api/v1/note/"+bodyCreated.Slug+"/view", 165 + e.jsonify(apiv1NoteGetWithPasswordRequest{ 166 + Password: passwd, 167 + }), 162 168 ) 163 169 e.Equal(httpResp.Code, http.StatusOK) 164 170 ··· 208 214 e.readBodyAndUnjsonify(httpResp.Body, &bodyCreated) 209 215 210 216 httpResp = e.httpRequest( 211 - http.MethodGet, 212 - "/api/v1/note/"+bodyCreated.Slug+"?password="+e.uuid(), 213 - nil, 217 + http.MethodPost, 218 + "/api/v1/note/"+bodyCreated.Slug+"/view", 219 + e.jsonify(apiv1NoteGetWithPasswordRequest{ 220 + Password: e.uuid(), 221 + }), 214 222 ) 215 223 e.Equal(httpResp.Code, http.StatusNotFound) 216 224 }
M
internal/service/notesrv/input.go
··· 2 2 3 3 import "github.com/olexsmir/onasty/internal/dtos" 4 4 5 +const EmptyPassword = "" 6 + 5 7 // GetNoteBySlugInput used as input for [GetBySlugAndRemoveIfNeeded] 6 8 type GetNoteBySlugInput struct { 7 9 // Slug is a note's slug :) *Required* ··· 13 15 } 14 16 15 17 func (i GetNoteBySlugInput) HasPassword() bool { 16 - return i.Password != "" 18 + return i.Password != EmptyPassword 17 19 }
M
internal/transport/http/apiv1/apiv1.go
··· 63 63 note := r.Group("/note") 64 64 { 65 65 note.GET("/:slug", a.getNoteBySlugHandler) 66 + note.POST("/:slug/view", a.getNoteBySlugAndPasswordHandler) 66 67 note.GET("/:slug/meta", a.getNoteMetadataByIDHandler) 67 68 68 69 possiblyAuthorized := note.Group("", a.couldBeAuthorizedMiddleware)
M
internal/transport/http/apiv1/note.go
··· 60 60 c.Request.Context(), 61 61 notesrv.GetNoteBySlugInput{ 62 62 Slug: c.Param("slug"), 63 - Password: c.Query("password"), 63 + Password: notesrv.EmptyPassword, 64 + }, 65 + ) 66 + if err != nil { 67 + errorResponse(c, err) 68 + return 69 + } 70 + 71 + status := http.StatusOK 72 + if !note.ReadAt.IsZero() { 73 + status = http.StatusNotFound 74 + } 75 + 76 + c.JSON(status, getNoteBySlugResponse{ 77 + Content: note.Content, 78 + ReadAt: note.ReadAt, 79 + CreatedAt: note.CreatedAt, 80 + ExpiresAt: note.ExpiresAt, 81 + BurnBeforeExpiration: note.BurnBeforeExpiration, 82 + }) 83 +} 84 + 85 +type getNoteBuySlugAndPasswordRequest struct { 86 + Password string `json:"password"` 87 +} 88 + 89 +func (a *APIV1) getNoteBySlugAndPasswordHandler(c *gin.Context) { 90 + var req getNoteBuySlugAndPasswordRequest 91 + if err := c.ShouldBindJSON(&req); err != nil { 92 + newError(c, http.StatusBadRequest, "invalid request") 93 + return 94 + } 95 + 96 + note, err := a.notesrv.GetBySlugAndRemoveIfNeeded( 97 + c.Request.Context(), 98 + notesrv.GetNoteBySlugInput{ 99 + Slug: c.Param("slug"), 100 + Password: req.Password, 64 101 }, 65 102 ) 66 103 if err != nil {
M
web/src/Api/Note.elm
··· 7 7 import Iso8601 8 8 import Json.Encode as E 9 9 import Time exposing (Posix) 10 -import Url 11 10 12 11 13 12 create : ··· 59 58 } 60 59 -> Effect msg 61 60 get options = 62 - Effect.sendApiRequest 63 - { endpoint = 64 - "/api/v1/note/" 65 - ++ options.slug 66 - ++ (case options.password of 67 - Just p -> 68 - "?password=" ++ Url.percentEncode p 61 + case options.password of 62 + Just passwd -> 63 + Effect.sendApiRequest 64 + { endpoint = "/api/v1/note/" ++ options.slug ++ "/view" 65 + , method = "POST" 66 + , body = E.object [ ( "password", E.string passwd ) ] |> Http.jsonBody 67 + , onResponse = options.onResponse 68 + , decoder = Note.decode 69 + } 69 70 70 - Nothing -> 71 - "" 72 - ) 73 - , method = "GET" 74 - , body = Http.emptyBody 75 - , onResponse = options.onResponse 76 - , decoder = Note.decode 77 - } 71 + Nothing -> 72 + Effect.sendApiRequest 73 + { endpoint = "/api/v1/note/" ++ options.slug 74 + , method = "GET" 75 + , body = Http.emptyBody 76 + , onResponse = options.onResponse 77 + , decoder = Note.decode 78 + } 78 79 79 80 80 81 getMetadata :