mirror of
https://github.com/go-shiori/shiori.git
synced 2025-11-08 14:21:20 +08:00
* refactor: base http server stdlib * refactor: swagger and frontend routes * fix: use global middlewares * refactor: removed gin from testutils * fix: object references in legacy webserver * refactor: legacy, swagger and system handlers * fix: added verbs to handlers * fix: server handlers ordering * refactor: bookmarks handlers * refactor: system api routes * tests: bookmark handlers * refactor: migrated api auth routes * chore: remove unused middlewares * docs: add swagger docs to refactored system api * chore: remove old auth routes * refactor: account apis * chore: removed old handlers * fix: api v1 handlers missing middlewares * refactor: migrated tag list route * refactor: bookmark routes * refactor: remove gin * chore: make styles * test: fixed tests * test: generate binary file without text * fix: global middleware missing from system api handler * fix: incorrect api handler * chore: avoid logging screenshot contents * tests: bookmarks domain * tests: shortcuts * test: missing tests * tests: server tests * test: remove test using syscall to avoid windows errors * chore: added middlewares
178 lines
5.1 KiB
Go
178 lines
5.1 KiB
Go
package api_v1
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/go-shiori/shiori/internal/http/middleware"
|
|
"github.com/go-shiori/shiori/internal/http/response"
|
|
"github.com/go-shiori/shiori/internal/model"
|
|
)
|
|
|
|
type createAccountPayload struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
Owner bool `json:"owner"`
|
|
}
|
|
|
|
func (p *createAccountPayload) ToAccountDTO() model.AccountDTO {
|
|
return model.AccountDTO{
|
|
Username: p.Username,
|
|
Password: p.Password,
|
|
Owner: &p.Owner,
|
|
}
|
|
}
|
|
|
|
// @Summary List accounts
|
|
// @Description List accounts
|
|
// @Tags accounts
|
|
// @Produce json
|
|
// @Success 200 {array} model.AccountDTO
|
|
// @Failure 500 {string} string "Internal Server Error"
|
|
// @Router /api/v1/accounts [get]
|
|
func HandleListAccounts(deps model.Dependencies, c model.WebContext) {
|
|
if err := middleware.RequireLoggedInAdmin(deps, c); err != nil {
|
|
return
|
|
}
|
|
|
|
accounts, err := deps.Domains().Accounts().ListAccounts(c.Request().Context())
|
|
if err != nil {
|
|
deps.Logger().WithError(err).Error("error getting accounts")
|
|
response.SendInternalServerError(c)
|
|
return
|
|
}
|
|
|
|
response.Send(c, http.StatusOK, accounts)
|
|
}
|
|
|
|
// @Summary Create an account
|
|
// @Tags accounts
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Success 201 {object} model.AccountDTO
|
|
// @Failure 400 {object} nil "Bad Request"
|
|
// @Failure 409 {object} nil "Account already exists"
|
|
// @Failure 500 {object} nil "Internal Server Error"
|
|
// @Router /api/v1/accounts [post]
|
|
func HandleCreateAccount(deps model.Dependencies, c model.WebContext) {
|
|
if err := middleware.RequireLoggedInAdmin(deps, c); err != nil {
|
|
return
|
|
}
|
|
|
|
var payload createAccountPayload
|
|
if err := json.NewDecoder(c.Request().Body).Decode(&payload); err != nil {
|
|
response.SendError(c, http.StatusBadRequest, "invalid json", nil)
|
|
return
|
|
}
|
|
|
|
account, err := deps.Domains().Accounts().CreateAccount(c.Request().Context(), payload.ToAccountDTO())
|
|
if err, isValidationErr := err.(model.ValidationError); isValidationErr {
|
|
response.SendError(c, http.StatusBadRequest, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
if errors.Is(err, model.ErrAlreadyExists) {
|
|
response.SendError(c, http.StatusConflict, "account already exists", nil)
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
deps.Logger().WithError(err).Error("error creating account")
|
|
response.SendInternalServerError(c)
|
|
return
|
|
}
|
|
|
|
response.Send(c, http.StatusCreated, account)
|
|
}
|
|
|
|
// @Summary Delete an account
|
|
// @Tags accounts
|
|
// @Produce json
|
|
// @Param id path int true "Account ID"
|
|
// @Success 204 {object} nil "No content"
|
|
// @Failure 400 {object} nil "Invalid ID"
|
|
// @Failure 404 {object} nil "Account not found"
|
|
// @Failure 500 {object} nil "Internal Server Error"
|
|
// @Router /api/v1/accounts/{id} [delete]
|
|
func HandleDeleteAccount(deps model.Dependencies, c model.WebContext) {
|
|
if err := middleware.RequireLoggedInAdmin(deps, c); err != nil {
|
|
return
|
|
}
|
|
|
|
id, err := strconv.Atoi(c.Request().PathValue("id"))
|
|
if err != nil {
|
|
response.SendError(c, http.StatusBadRequest, "invalid id", nil)
|
|
return
|
|
}
|
|
|
|
err = deps.Domains().Accounts().DeleteAccount(c.Request().Context(), id)
|
|
if errors.Is(err, model.ErrNotFound) {
|
|
response.SendError(c, http.StatusNotFound, "account not found", nil)
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
deps.Logger().WithError(err).Error("error deleting account")
|
|
response.SendInternalServerError(c)
|
|
return
|
|
}
|
|
|
|
response.Send(c, http.StatusNoContent, nil)
|
|
}
|
|
|
|
// @Summary Update an account
|
|
// @Tags accounts
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param id path int true "Account ID"
|
|
// @Param account body updateAccountPayload true "Account data"
|
|
// @Success 200 {object} model.AccountDTO
|
|
// @Failure 400 {object} nil "Invalid ID/data"
|
|
// @Failure 404 {object} nil "Account not found"
|
|
// @Failure 409 {object} nil "Account already exists"
|
|
// @Failure 500 {object} nil "Internal Server Error"
|
|
// @Router /api/v1/accounts/{id} [patch]
|
|
func HandleUpdateAccount(deps model.Dependencies, c model.WebContext) {
|
|
if err := middleware.RequireLoggedInAdmin(deps, c); err != nil {
|
|
return
|
|
}
|
|
|
|
accountID, err := strconv.Atoi(c.Request().PathValue("id"))
|
|
if err != nil {
|
|
response.SendError(c, http.StatusBadRequest, "invalid id", nil)
|
|
return
|
|
}
|
|
|
|
var payload updateAccountPayload
|
|
if err := json.NewDecoder(c.Request().Body).Decode(&payload); err != nil {
|
|
response.SendError(c, http.StatusBadRequest, "invalid json", nil)
|
|
return
|
|
}
|
|
|
|
updatedAccount := payload.ToAccountDTO()
|
|
updatedAccount.ID = model.DBID(accountID)
|
|
|
|
account, err := deps.Domains().Accounts().UpdateAccount(c.Request().Context(), updatedAccount)
|
|
if errors.Is(err, model.ErrNotFound) {
|
|
response.SendError(c, http.StatusNotFound, "account not found", nil)
|
|
return
|
|
}
|
|
if errors.Is(err, model.ErrAlreadyExists) {
|
|
response.SendError(c, http.StatusConflict, "account already exists", nil)
|
|
return
|
|
}
|
|
if err, isValidationErr := err.(model.ValidationError); isValidationErr {
|
|
response.SendError(c, http.StatusBadRequest, err.Error(), nil)
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
deps.Logger().WithError(err).Error("error updating account")
|
|
response.SendInternalServerError(c)
|
|
return
|
|
}
|
|
|
|
response.Send(c, http.StatusOK, account)
|
|
}
|