streamline response handling and logging
Signed-off-by: Tobias Erbshäußer <tobias@tesoft.dev>
This commit is contained in:
+27
-20
@@ -23,7 +23,7 @@ func (h *ApiHandler) ServeLoginPost(writer http.ResponseWriter, request *http.Re
|
|||||||
body, err := io.ReadAll(bodyReader)
|
body, err := io.ReadAll(bodyReader)
|
||||||
_ = bodyReader.Close()
|
_ = bodyReader.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(writer, err.Error(), http.StatusBadRequest)
|
WriteError(writer, http.StatusBadRequest, "failed to read body", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,19 +34,19 @@ func (h *ApiHandler) ServeLoginPost(writer http.ResponseWriter, request *http.Re
|
|||||||
loginBody := LoginBody{}
|
loginBody := LoginBody{}
|
||||||
err = json.Unmarshal(body, &loginBody)
|
err = json.Unmarshal(body, &loginBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(writer, err.Error(), http.StatusBadRequest)
|
WriteError(writer, http.StatusBadRequest, "failed to read body", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
success, err := h.db.ValidateRootPassword(loginBody.Password)
|
success, err := h.db.ValidateRootPassword(loginBody.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error logging in:", err)
|
WriteError(writer, http.StatusInternalServerError, "failed to read database", err)
|
||||||
http.Error(writer, "failed to read database", http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !success {
|
if !success {
|
||||||
http.Error(writer, "invalid password", http.StatusUnauthorized)
|
log.Printf("failed login from '%s'", request.RemoteAddr)
|
||||||
|
WriteError(writer, http.StatusUnauthorized, "invalid password", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,14 +62,9 @@ func (h *ApiHandler) ServeLoginPost(writer http.ResponseWriter, request *http.Re
|
|||||||
cookie.HttpOnly = true
|
cookie.HttpOnly = true
|
||||||
http.SetCookie(writer, &cookie)
|
http.SetCookie(writer, &cookie)
|
||||||
|
|
||||||
writer.Header().Set("Content-Type", "application/json")
|
WriteResponse(writer, http.StatusOK, map[string]interface{}{})
|
||||||
writer.WriteHeader(http.StatusOK)
|
|
||||||
err = json.NewEncoder(writer).Encode(map[string]interface{}{})
|
|
||||||
if err != nil {
|
|
||||||
http.Error(writer, "failed to serialize results", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
log.Printf("successful login from '%s'", request.RemoteAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ApiHandler) ServeLogoutPost(writer http.ResponseWriter, request *http.Request) {
|
func (h *ApiHandler) ServeLogoutPost(writer http.ResponseWriter, request *http.Request) {
|
||||||
@@ -85,13 +80,9 @@ func (h *ApiHandler) ServeLogoutPost(writer http.ResponseWriter, request *http.R
|
|||||||
|
|
||||||
h.authToken = nil
|
h.authToken = nil
|
||||||
|
|
||||||
writer.Header().Set("Content-Type", "application/json")
|
WriteResponse(writer, http.StatusOK, map[string]interface{}{})
|
||||||
writer.WriteHeader(http.StatusOK)
|
|
||||||
err := json.NewEncoder(writer).Encode(map[string]interface{}{})
|
log.Printf("successful logout from '%s'", request.RemoteAddr)
|
||||||
if err != nil {
|
|
||||||
http.Error(writer, "failed to serialize results", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ApiHandler) ProcessAuth(next http.Handler, required bool) http.Handler {
|
func (h *ApiHandler) ProcessAuth(next http.Handler, required bool) http.Handler {
|
||||||
@@ -103,7 +94,7 @@ func (h *ApiHandler) ProcessAuth(next http.Handler, required bool) http.Handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !isAuthorized && required {
|
if !isAuthorized && required {
|
||||||
http.Error(writer, "authentication required", http.StatusUnauthorized)
|
WriteError(writer, http.StatusUnauthorized, "authentication required", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,3 +106,19 @@ func IsAuthorized(request *http.Request) bool {
|
|||||||
value := request.Context().Value(isAuthorizedContextKey)
|
value := request.Context().Value(isAuthorizedContextKey)
|
||||||
return value != nil && value.(bool)
|
return value != nil && value.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WriteResponse(writer http.ResponseWriter, code int, body any) {
|
||||||
|
writer.Header().Set("Content-Type", "application/json")
|
||||||
|
writer.WriteHeader(code)
|
||||||
|
_ = json.NewEncoder(writer).Encode(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteError(writer http.ResponseWriter, code int, message string, err error) {
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteResponse(writer, code, map[string]interface{}{
|
||||||
|
"message": message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
+11
-25
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"backend/md"
|
"backend/md"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -63,7 +62,7 @@ func ParseArticle(reader io.Reader, filePrefix string) (*Article, error) {
|
|||||||
|
|
||||||
readmeBytes, found := tarFiles["README.md"]
|
readmeBytes, found := tarFiles["README.md"]
|
||||||
if !found {
|
if !found {
|
||||||
return nil, errors.New("README.md not found")
|
return nil, errors.New("file 'README.md' not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
usedFiles := make(map[string]ArticleFile)
|
usedFiles := make(map[string]ArticleFile)
|
||||||
@@ -163,7 +162,7 @@ func (h *ApiHandler) ServeBlogGet(writer http.ResponseWriter, request *http.Requ
|
|||||||
} else {
|
} else {
|
||||||
offset, err = strconv.Atoi(offsetStr)
|
offset, err = strconv.Atoi(offsetStr)
|
||||||
if err != nil || offset < 0 {
|
if err != nil || offset < 0 {
|
||||||
http.Error(writer, "invalid offset", http.StatusBadRequest)
|
WriteError(writer, http.StatusBadRequest, "invalid offset", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,69 +173,56 @@ func (h *ApiHandler) ServeBlogGet(writer http.ResponseWriter, request *http.Requ
|
|||||||
} else {
|
} else {
|
||||||
limit, err = strconv.Atoi(limitStr)
|
limit, err = strconv.Atoi(limitStr)
|
||||||
if err != nil || limit <= 0 || limit > 100 {
|
if err != nil || limit <= 0 || limit > 100 {
|
||||||
http.Error(writer, "invalid limit", http.StatusBadRequest)
|
WriteError(writer, http.StatusBadRequest, "invalid limit", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
articles, err := h.db.GetBlogArticles(IsAuthorized(request), offset, limit)
|
articles, err := h.db.GetBlogArticles(IsAuthorized(request), offset, limit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error getting articles:", err)
|
WriteError(writer, http.StatusInternalServerError, "failed to query database", err)
|
||||||
http.Error(writer, "failed to query database", http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.Header().Set("Content-Type", "application/json")
|
WriteResponse(writer, http.StatusOK, articles)
|
||||||
writer.WriteHeader(http.StatusOK)
|
|
||||||
err = json.NewEncoder(writer).Encode(articles)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(writer, "failed to serialize results", http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ApiHandler) ServeBlogPut(writer http.ResponseWriter, request *http.Request) {
|
func (h *ApiHandler) ServeBlogPut(writer http.ResponseWriter, request *http.Request) {
|
||||||
err := request.ParseMultipartForm(10 * 1024 * 1024)
|
err := request.ParseMultipartForm(10 * 1024 * 1024)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(writer, "failed to parse multipart form", http.StatusBadRequest)
|
WriteError(writer, http.StatusBadRequest, "failed to parse multipart form", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
file, _, err := request.FormFile("file")
|
file, _, err := request.FormFile("file")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(writer, "failed to parse file", http.StatusBadRequest)
|
WriteError(writer, http.StatusBadRequest, "failed to parse file", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = file.Close()
|
_ = file.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.Println("Creating new blog article")
|
log.Println("creating new blog article ...")
|
||||||
|
|
||||||
id, commit, err := h.db.CreateBlogArticle()
|
id, commit, err := h.db.CreateBlogArticle()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error creating new blog article:", err)
|
WriteError(writer, http.StatusInternalServerError, "failed to write database", err)
|
||||||
http.Error(writer, "failed to add article to database", http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
article, err := ParseArticle(file, "/api/blog/"+strconv.FormatInt(id, 10)+"/file/")
|
article, err := ParseArticle(file, "/api/blog/"+strconv.FormatInt(id, 10)+"/file/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = commit(nil)
|
_ = commit(nil)
|
||||||
log.Println("Error creating new blog article:", err)
|
WriteError(writer, http.StatusInternalServerError, "failed to parse article: "+err.Error(), nil)
|
||||||
http.Error(writer, "failed to add article to database", http.StatusInternalServerError)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = commit(article)
|
err = commit(article)
|
||||||
|
|
||||||
writer.Header().Set("Content-Type", "application/json")
|
WriteResponse(writer, http.StatusOK, map[string]interface{}{
|
||||||
writer.WriteHeader(http.StatusOK)
|
|
||||||
err = json.NewEncoder(writer).Encode(map[string]interface{}{
|
|
||||||
"id": id,
|
"id": id,
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
http.Error(writer, "failed to serialize results", http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ApiHandler) ServeBlogGetSingle(writer http.ResponseWriter, request *http.Request) {
|
func (h *ApiHandler) ServeBlogGetSingle(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
|||||||
+6
-6
@@ -18,7 +18,7 @@ type Database struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewDatabase(path string, rootPassword string) (*Database, error) {
|
func NewDatabase(path string, rootPassword string) (*Database, error) {
|
||||||
log.Println("Opening database '" + path + "'")
|
log.Println("opening database '" + path + "'")
|
||||||
|
|
||||||
db, err := sql.Open("sqlite3", path)
|
db, err := sql.Open("sqlite3", path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -37,7 +37,7 @@ func NewDatabase(path string, rootPassword string) (*Database, error) {
|
|||||||
func (db *Database) Close() {
|
func (db *Database) Close() {
|
||||||
err := db.db.Close()
|
err := db.db.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Error closing database:", err.Error())
|
log.Println("error closing database:", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ func migrate(db *sql.DB, rootPassword string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Checking database schema version")
|
log.Println("checking database schema version")
|
||||||
var curVersion int
|
var curVersion int
|
||||||
err = tx.QueryRow("SELECT version FROM schema_info").Scan(&curVersion)
|
err = tx.QueryRow("SELECT version FROM schema_info").Scan(&curVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -217,7 +217,7 @@ func migrate(db *sql.DB, rootPassword string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if curVersion == -1 {
|
if curVersion == -1 {
|
||||||
log.Println("Database is empty")
|
log.Println("database is empty")
|
||||||
|
|
||||||
err = createV1Tables(tx, rootPassword)
|
err = createV1Tables(tx, rootPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -225,7 +225,7 @@ func migrate(db *sql.DB, rootPassword string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Println("Database schema version is", curVersion)
|
log.Println("database schema version is", curVersion)
|
||||||
|
|
||||||
if curVersion != 1 {
|
if curVersion != 1 {
|
||||||
return errors.New("unsupported database schema version")
|
return errors.New("unsupported database schema version")
|
||||||
@@ -236,7 +236,7 @@ func migrate(db *sql.DB, rootPassword string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createV1Tables(tx *sql.Tx, rootPassword string) error {
|
func createV1Tables(tx *sql.Tx, rootPassword string) error {
|
||||||
log.Println("Creating tables for schema version 1")
|
log.Println("creating tables for schema version 1")
|
||||||
|
|
||||||
salt := make([]byte, 32)
|
salt := make([]byte, 32)
|
||||||
_, _ = rand.Read(salt)
|
_, _ = rand.Read(salt)
|
||||||
|
|||||||
Reference in New Issue
Block a user