forked from jriou/coller
149 lines
3.4 KiB
Go
149 lines
3.4 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
"git.riou.xyz/jriou/coller/internal"
|
|
)
|
|
|
|
func HealthHandler(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprintf(w, "OK")
|
|
}
|
|
|
|
type CreateNoteHandler struct {
|
|
logger *slog.Logger
|
|
db *Database
|
|
maxUploadSize int64
|
|
}
|
|
|
|
type CreateNotePayload struct {
|
|
Content string `json:"content"`
|
|
EncryptionKey string `json:"encryption_key"`
|
|
Encrypted bool `json:"encrypted"`
|
|
Expiration int `json:"expiration"`
|
|
DeleteAfterRead bool `json:"delete_after_read"`
|
|
Language string `json:"language"`
|
|
}
|
|
|
|
type CreateNoteResponse struct {
|
|
ID string `json:"id"`
|
|
}
|
|
|
|
func (h *CreateNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
bodyReader := http.MaxBytesReader(w, r.Body, h.maxUploadSize)
|
|
defer r.Body.Close()
|
|
|
|
var body CreateNotePayload
|
|
err := json.NewDecoder(bodyReader).Decode(&body)
|
|
if err != nil {
|
|
WriteError(w, "could not decode payload to create note", err)
|
|
return
|
|
}
|
|
|
|
content, err := internal.Decode(body.Content)
|
|
|
|
if err != nil {
|
|
WriteError(w, "could not decode content", err)
|
|
return
|
|
}
|
|
|
|
note, err := h.db.Create(content, body.EncryptionKey, body.Encrypted, body.Expiration, body.DeleteAfterRead, body.Language)
|
|
if err != nil {
|
|
WriteError(w, "could not create note", err)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(CreateNoteResponse{ID: note.ID})
|
|
}
|
|
|
|
type GetNoteHandler struct {
|
|
logger *slog.Logger
|
|
db *Database
|
|
}
|
|
|
|
func (h *GetNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
|
|
|
id := mux.Vars(r)["id"]
|
|
|
|
note, err := h.db.Get(id)
|
|
|
|
if err != nil {
|
|
WriteError(w, "could not get note", err)
|
|
} else if note == nil {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
} else {
|
|
if note.Encrypted {
|
|
w.Header().Set("Content-Type", "application/octet-stream")
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
fmt.Fprint(w, string(note.Content))
|
|
}
|
|
}
|
|
|
|
type GetEncryptedNoteHandler struct {
|
|
logger *slog.Logger
|
|
db *Database
|
|
}
|
|
|
|
func (h *GetEncryptedNoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
|
|
|
vars := mux.Vars(r)
|
|
id := vars["id"]
|
|
encryptionKey := vars["encryptionKey"]
|
|
|
|
note, err := h.db.Get(id)
|
|
|
|
if err != nil {
|
|
WriteError(w, "could not get note", err)
|
|
return
|
|
} else if note == nil {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
if encryptionKey != "" && note.Encrypted {
|
|
note.Content, err = internal.Decrypt(note.Content, encryptionKey)
|
|
if err != nil {
|
|
WriteError(w, "could not decrypt note", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
fmt.Fprint(w, string(note.Content))
|
|
}
|
|
|
|
type ClientHandler struct {
|
|
logger *slog.Logger
|
|
version string
|
|
}
|
|
|
|
func (h *ClientHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
h.logger.Debug("rendering client redirection")
|
|
vars := mux.Vars(r)
|
|
os := vars["os"]
|
|
arch := vars["arch"]
|
|
clientName := vars["clientName"]
|
|
|
|
if !internal.InSlice(supportedOSes, os) || !internal.InSlice(supportedArches, arch) || !internal.InSlice(supportedClients, clientName) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
version := h.version
|
|
if version == "" {
|
|
version = "latest"
|
|
}
|
|
|
|
http.Redirect(w, r, fmt.Sprintf("https://git.riou.xyz/jriou/%s/releases/download/%s/%s-%s-%s", clientName, version, clientName, os, arch), http.StatusMovedPermanently)
|
|
}
|