135 lines
2.8 KiB
Go
135 lines
2.8 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
|
|
authservice "update_server/internal/auth"
|
|
"update_server/internal/db"
|
|
"update_server/internal/slug"
|
|
)
|
|
|
|
func (h *handler) basePageData(r *http.Request, title, eyebrow, heading, description string) PageData {
|
|
return PageData{
|
|
Title: title,
|
|
Eyebrow: eyebrow,
|
|
Heading: heading,
|
|
Description: description,
|
|
BaseURL: strings.TrimRight(h.config.BaseURL, "/"),
|
|
CSRFToken: h.csrfToken(r),
|
|
CurrentUser: h.currentUser(r),
|
|
}
|
|
}
|
|
|
|
func (h *handler) currentUser(r *http.Request) *db.User {
|
|
sessionState, ok := authservice.FromContext(r.Context())
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
user := sessionState.User
|
|
return &user
|
|
}
|
|
|
|
func (h *handler) currentUserID(r *http.Request) *int64 {
|
|
user := h.currentUser(r)
|
|
if user == nil {
|
|
return nil
|
|
}
|
|
|
|
return &user.ID
|
|
}
|
|
|
|
func routeID(r *http.Request, key string) (int64, error) {
|
|
raw := strings.TrimSpace(chi.URLParam(r, key))
|
|
if raw == "" {
|
|
return 0, fmt.Errorf("%s is required", key)
|
|
}
|
|
|
|
value, err := strconv.ParseInt(raw, 10, 64)
|
|
if err != nil || value <= 0 {
|
|
return 0, fmt.Errorf("invalid %s", key)
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
func projectFormInput(name, slugValue, description string) (db.CreateProjectParams, string) {
|
|
name = strings.TrimSpace(name)
|
|
slugValue = slug.Make(firstNonEmpty(slugValue, name))
|
|
description = strings.TrimSpace(description)
|
|
|
|
switch {
|
|
case name == "":
|
|
return db.CreateProjectParams{}, "Project name is required."
|
|
case slugValue == "":
|
|
return db.CreateProjectParams{}, "Project slug is required."
|
|
default:
|
|
return db.CreateProjectParams{
|
|
Name: name,
|
|
Slug: slugValue,
|
|
Description: description,
|
|
}, ""
|
|
}
|
|
}
|
|
|
|
func tagFormInput(name, slugValue, description string) (db.CreateTagParams, string) {
|
|
name = strings.TrimSpace(name)
|
|
slugValue = slug.Make(firstNonEmpty(slugValue, name))
|
|
description = strings.TrimSpace(description)
|
|
|
|
switch {
|
|
case name == "":
|
|
return db.CreateTagParams{}, "Tag name is required."
|
|
case slugValue == "":
|
|
return db.CreateTagParams{}, "Tag slug is required."
|
|
default:
|
|
return db.CreateTagParams{
|
|
Name: name,
|
|
Slug: slugValue,
|
|
Description: description,
|
|
}, ""
|
|
}
|
|
}
|
|
|
|
func firstNonEmpty(values ...string) string {
|
|
for _, value := range values {
|
|
if trimmed := strings.TrimSpace(value); trimmed != "" {
|
|
return trimmed
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func maxUploadMegabytes(bytes int64) int64 {
|
|
if bytes <= 0 {
|
|
return 0
|
|
}
|
|
|
|
const mebibyte = 1024 * 1024
|
|
value := bytes / mebibyte
|
|
if bytes%mebibyte != 0 {
|
|
value++
|
|
}
|
|
if value == 0 {
|
|
value = 1
|
|
}
|
|
|
|
return value
|
|
}
|
|
|
|
func maxUploadRequestLimit(fileLimit int64) int64 {
|
|
const multipartOverhead = 1 << 20
|
|
return fileLimit + multipartOverhead
|
|
}
|
|
|
|
func isMaxBytesError(err error) bool {
|
|
var maxErr *http.MaxBytesError
|
|
return errors.As(err, &maxErr)
|
|
}
|