Fixes #38. Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
parent
f721e56371
commit
de24146991
7 changed files with 42 additions and 20 deletions
|
@ -38,7 +38,6 @@ type NotePayload struct {
|
||||||
type NoteResponse struct {
|
type NoteResponse struct {
|
||||||
ID int64 `json:"id"`
|
ID int64 `json:"id"`
|
||||||
Message string `json:"message,omitempty"`
|
Message string `json:"message,omitempty"`
|
||||||
Error string `json:"error,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -192,8 +191,12 @@ func handleMain() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("encoding content")
|
logger.Debug("encoding content")
|
||||||
encoded := internal.Encode(content)
|
encodedContent := internal.Encode(content)
|
||||||
p.Content = encoded
|
p.Content = encodedContent
|
||||||
|
|
||||||
|
logger.Debug("encoding password")
|
||||||
|
encodedPassword := internal.Encode([]byte(*password))
|
||||||
|
p.Password = encodedPassword
|
||||||
|
|
||||||
payload, err := json.Marshal(p)
|
payload, err := json.Marshal(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -241,7 +244,7 @@ func handleMain() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.StatusCode != http.StatusOK {
|
if r.StatusCode != http.StatusOK {
|
||||||
return internal.ReturnError(logger, jsonBody.Message, fmt.Errorf("%s", jsonBody.Error))
|
return internal.ReturnError(logger, jsonBody.Message, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("finding note location")
|
logger.Debug("finding note location")
|
||||||
|
|
|
@ -82,7 +82,7 @@ Return content of a note encrypted by the given encryption key.
|
||||||
Return content of a protected note encrypted by the given encryption key.
|
Return content of a protected note encrypted by the given encryption key.
|
||||||
|
|
||||||
Body (JSON):
|
Body (JSON):
|
||||||
* **password** (string): password used to protect the note (required)
|
* **password** (string): base64 encoded password used to protect the note (required)
|
||||||
|
|
||||||
### GET /api/note/\<id\>
|
### GET /api/note/\<id\>
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ Return content of a protected note.
|
||||||
If the note is encrypted, the encrypted value is returned (application/octet-stream). Otherwise, the text is returned (text/plain).
|
If the note is encrypted, the encrypted value is returned (application/octet-stream). Otherwise, the text is returned (text/plain).
|
||||||
|
|
||||||
Body (JSON):
|
Body (JSON):
|
||||||
* **password** (string): password used to protect the note (required)
|
* **password** (string): base64 encoded password used to protect the note (required)
|
||||||
|
|
||||||
### Errors
|
### Errors
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,11 @@ type NotePayload struct {
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type NoteResponse struct {
|
||||||
|
ID int64 `json:"id"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
func handleMain() int {
|
func handleMain() int {
|
||||||
|
|
||||||
flag.Usage = usage
|
flag.Usage = usage
|
||||||
|
@ -134,16 +139,21 @@ func handleMain() int {
|
||||||
return internal.ReturnError(logger, "could not retreive note", err)
|
return internal.ReturnError(logger, "could not retreive note", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.StatusCode >= 300 {
|
|
||||||
return internal.ReturnError(logger, "could not retreive note", fmt.Errorf("status code %d", r.StatusCode))
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Debug("decoding body")
|
logger.Debug("decoding body")
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return internal.ReturnError(logger, "could not read response", err)
|
return internal.ReturnError(logger, "could not read response", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.StatusCode != http.StatusOK {
|
||||||
|
jsonBody := &NoteResponse{}
|
||||||
|
err = json.Unmarshal(body, jsonBody)
|
||||||
|
if err != nil {
|
||||||
|
return internal.ReturnError(logger, "could not decode response", err)
|
||||||
|
}
|
||||||
|
return internal.ReturnError(logger, jsonBody.Message, nil)
|
||||||
|
}
|
||||||
|
|
||||||
var content []byte
|
var content []byte
|
||||||
if *encryptionKey != "" {
|
if *encryptionKey != "" {
|
||||||
logger.Debug("decrypting note")
|
logger.Debug("decrypting note")
|
||||||
|
|
|
@ -123,7 +123,7 @@ func (d *Database) Get(id string) (*Note, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Database) Create(content []byte, password string, encryptionKey string, encrypted bool, expiration int, deleteAfterRead bool, language string) (note *Note, err error) {
|
func (d *Database) Create(content []byte, password []byte, encryptionKey string, encrypted bool, expiration int, deleteAfterRead bool, language string) (note *Note, err error) {
|
||||||
if expiration == 0 {
|
if expiration == 0 {
|
||||||
expiration = d.expiration
|
expiration = d.expiration
|
||||||
}
|
}
|
||||||
|
@ -161,8 +161,8 @@ func (d *Database) Create(content []byte, password string, encryptionKey string,
|
||||||
note.Encrypted = true
|
note.Encrypted = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if password != "" {
|
if password != nil {
|
||||||
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
hash, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@ var (
|
||||||
ErrEncryptionKeyNotFound = errors.New("encryption key not found")
|
ErrEncryptionKeyNotFound = errors.New("encryption key not found")
|
||||||
ErrCouldNotDecryptNote = errors.New("could not decrypt note")
|
ErrCouldNotDecryptNote = errors.New("could not decrypt note")
|
||||||
ErrInvalidPassword = errors.New("invalid password")
|
ErrInvalidPassword = errors.New("invalid password")
|
||||||
|
ErrInvalidExpiration = errors.New("invalid expiration")
|
||||||
|
ErrInvalidLanguage = errors.New("invalid language")
|
||||||
ErrCouldNotParseFile = errors.New("could not parse file")
|
ErrCouldNotParseFile = errors.New("could not parse file")
|
||||||
ErrFileTooLarge = errors.New("file too large")
|
ErrFileTooLarge = errors.New("file too large")
|
||||||
ErrTextFileExpected = errors.New("text file expected")
|
ErrTextFileExpected = errors.New("text file expected")
|
||||||
|
@ -16,9 +18,9 @@ var (
|
||||||
ErrEmptyNote = errors.New("empty note")
|
ErrEmptyNote = errors.New("empty note")
|
||||||
ErrEncryptionRequired = errors.New("encryption is required")
|
ErrEncryptionRequired = errors.New("encryption is required")
|
||||||
ErrClientEncryptionKeyNotAllowed = errors.New("client encryption key is not allowed")
|
ErrClientEncryptionKeyNotAllowed = errors.New("client encryption key is not allowed")
|
||||||
ErrInvalidExpiration = errors.New("invalid expiration")
|
|
||||||
ErrCouldNotCreateNote = errors.New("could not create note")
|
ErrCouldNotCreateNote = errors.New("could not create note")
|
||||||
ErrCouldNotDecodePayload = errors.New("could not decode payload")
|
ErrCouldNotDecodePayload = errors.New("could not decode payload")
|
||||||
ErrCouldNotDecodeContent = errors.New("could not decode content")
|
ErrCouldNotDecodeContent = errors.New("could not decode content")
|
||||||
|
ErrCouldNotDecodePassword = errors.New("could not decode password")
|
||||||
ErrNoteIsPasswordProtected = errors.New("note is password protected")
|
ErrNoteIsPasswordProtected = errors.New("note is password protected")
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,6 +28,8 @@ func apiError(level int, w http.ResponseWriter, logger *slog.Logger, topLevelErr
|
||||||
// Wrap error for logging
|
// Wrap error for logging
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("%v: %w", topLevelErr, err)
|
err = fmt.Errorf("%v: %w", topLevelErr, err)
|
||||||
|
} else {
|
||||||
|
err = topLevelErr
|
||||||
}
|
}
|
||||||
logger.Error(fmt.Sprintf("%v", err))
|
logger.Error(fmt.Sprintf("%v", err))
|
||||||
|
|
||||||
|
@ -106,13 +108,18 @@ func (h *CreateNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
content, err := internal.Decode(body.Content)
|
content, err := internal.Decode(body.Content)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
APIError(w, logger, ErrCouldNotDecodeContent, err)
|
APIError(w, logger, ErrCouldNotDecodeContent, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
note, err := h.db.Create(content, body.Password, body.EncryptionKey, body.Encrypted, body.Expiration, body.DeleteAfterRead, body.Language)
|
password, err := internal.Decode(body.Password)
|
||||||
|
if err != nil {
|
||||||
|
APIError(w, logger, ErrCouldNotDecodePassword, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
note, err := h.db.Create(content, password, body.EncryptionKey, body.Encrypted, body.Expiration, body.DeleteAfterRead, body.Language)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
APIError(w, logger, ErrCouldNotCreateNote, err)
|
APIError(w, logger, ErrCouldNotCreateNote, err)
|
||||||
return
|
return
|
||||||
|
@ -143,9 +150,9 @@ func (h *GetNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
APIError(w, logger, ErrCouldNotFindNote, err)
|
APIError(w, logger, ErrCouldNotFindNote, err)
|
||||||
} else if note == nil {
|
} else if note == nil {
|
||||||
APIErrorNotFound(w, logger, ErrNoteDoesNotExist, err)
|
APIErrorNotFound(w, logger, ErrNoteDoesNotExist, nil)
|
||||||
} else if note.PasswordHash != nil {
|
} else if note.PasswordHash != nil {
|
||||||
APIErrorBadRequest(w, logger, ErrNoteIsPasswordProtected, err)
|
APIErrorBadRequest(w, logger, ErrNoteIsPasswordProtected, nil)
|
||||||
} else {
|
} else {
|
||||||
if note.Encrypted {
|
if note.Encrypted {
|
||||||
w.Header().Set("Content-Type", "application/octet-stream")
|
w.Header().Set("Content-Type", "application/octet-stream")
|
||||||
|
@ -209,7 +216,7 @@ func (h *GetProtectedNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
|
||||||
if len(note.PasswordHash) > 0 {
|
if len(note.PasswordHash) > 0 {
|
||||||
err := bcrypt.CompareHashAndPassword(note.PasswordHash, []byte(body.Password))
|
err := bcrypt.CompareHashAndPassword(note.PasswordHash, []byte(body.Password))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
APIError(w, logger, ErrInvalidPassword, err)
|
APIErrorBadRequest(w, logger, ErrInvalidPassword, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ func (h *CreateNoteWithFormHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("saving note to the database")
|
logger.Debug("saving note to the database")
|
||||||
note, err := h.db.Create(content, password, encryptionKey, encryptionKey != "", expirationInt, deleteAfterRead != "", language)
|
note, err := h.db.Create(content, []byte(password), encryptionKey, encryptionKey != "", expirationInt, deleteAfterRead != "", language)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.WebError(w, logger, ErrCouldNotCreateNote, err)
|
h.WebError(w, logger, ErrCouldNotCreateNote, err)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue