Add Go rewrite with Postgres 17 and Dokploy Docker Compose
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"amnezia-share/internal/models"
|
||||
"amnezia-share/internal/share"
|
||||
"amnezia-share/internal/web"
|
||||
)
|
||||
|
||||
func flashFromQuery(r *http.Request) (ok, errText string) {
|
||||
return r.URL.Query().Get("ok"), r.URL.Query().Get("err")
|
||||
}
|
||||
|
||||
func redirectWithFlash(w http.ResponseWriter, r *http.Request, a *web.App, path string, ok, errText string) {
|
||||
u, _ := url.Parse(a.Cfg.AppURL(path))
|
||||
q := u.Query()
|
||||
if ok != "" {
|
||||
q.Set("ok", ok)
|
||||
}
|
||||
if errText != "" {
|
||||
q.Set("err", errText)
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
http.Redirect(w, r, u.String(), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
const adminPerPage = 20
|
||||
|
||||
type linkRow struct {
|
||||
models.ShareLink
|
||||
Status share.LinkStatus
|
||||
ActiveConfigs int
|
||||
}
|
||||
|
||||
type adminLinksView struct {
|
||||
adminLayout
|
||||
Links []linkRow
|
||||
StatusFilter string
|
||||
Page int
|
||||
Total int
|
||||
PerPage int
|
||||
Detail *models.ShareLink
|
||||
DetailStatus share.LinkStatus
|
||||
Creations []models.ShareCreation
|
||||
DeletedCreations []models.ShareCreation
|
||||
AllowedDurations []int
|
||||
AllowedServerIDs []int
|
||||
AllServers []models.ServerInfo
|
||||
}
|
||||
|
||||
// AdminLinksGet lists share links (paginated, filterable by status) and, when
|
||||
// ?id= is present, shows one link's detail with its creations (share_links.php).
|
||||
func AdminLinksGet(a *web.App) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
ok, errText := flashFromQuery(r)
|
||||
view := adminLinksView{
|
||||
adminLayout: newAdminLayout(a, r, "links"),
|
||||
StatusFilter: r.URL.Query().Get("status"),
|
||||
Page: queryInt(r, "page", 1),
|
||||
PerPage: adminPerPage,
|
||||
AllowedDurations: share.AllowedDurations,
|
||||
}
|
||||
view.OK, view.Error = ok, errText
|
||||
if view.Page < 1 {
|
||||
view.Page = 1
|
||||
}
|
||||
|
||||
links, err := a.Share.ListLinks(ctx, view.Page, view.PerPage, view.StatusFilter)
|
||||
if err != nil {
|
||||
view.Error = err.Error()
|
||||
}
|
||||
view.Total, _ = a.Share.CountLinks(ctx, view.StatusFilter)
|
||||
for _, l := range links {
|
||||
creations, _ := a.Share.ListCreationsForLink(ctx, l.ID)
|
||||
view.Links = append(view.Links, linkRow{
|
||||
ShareLink: l,
|
||||
Status: share.ClassifyLinkStatus(l, len(creations) > 0),
|
||||
ActiveConfigs: len(creations),
|
||||
})
|
||||
}
|
||||
|
||||
if id := queryInt(r, "id", 0); id > 0 {
|
||||
if link, err := a.Share.LinkByID(ctx, id); err == nil && link != nil {
|
||||
view.Detail = link
|
||||
creations, _ := a.Share.ListCreationsForLink(ctx, id)
|
||||
view.DetailStatus = share.ClassifyLinkStatus(*link, len(creations) > 0)
|
||||
view.Creations = creations
|
||||
view.DeletedCreations, _ = a.Share.ListDeletedCreationsForLink(ctx, id)
|
||||
view.AllowedServerIDs = share.ParseAllowedServerIDs(link.AllowedServerIDs)
|
||||
view.AllServers = share.BuildGuestServers(ctx, a.Settings, a.Settings.ServerLabels(ctx))
|
||||
}
|
||||
}
|
||||
|
||||
a.Render(w, r, "page_admin_links", view)
|
||||
}
|
||||
}
|
||||
|
||||
func parseFormDate(v string) *time.Time {
|
||||
v = strings.TrimSpace(v)
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
layouts := []string{"2006-01-02T15:04", "2006-01-02", time.RFC3339}
|
||||
for _, layout := range layouts {
|
||||
if t, err := time.Parse(layout, v); err == nil {
|
||||
return &t
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AdminLinksPost handles link create/update/delete/extend/allowed-servers and
|
||||
// per-creation deletion.
|
||||
func AdminLinksPost(a *web.App) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
action := r.FormValue("action")
|
||||
back := "admin/links"
|
||||
if id := r.FormValue("back_id"); id != "" {
|
||||
back += "?id=" + url.QueryEscape(id)
|
||||
}
|
||||
|
||||
var err error
|
||||
var okMsg string
|
||||
|
||||
switch action {
|
||||
case "create":
|
||||
days := formInt(r, "days", 30)
|
||||
maxUses := formInt(r, "max_uses", 5)
|
||||
subUntil := parseFormDate(r.FormValue("subscription_until"))
|
||||
link, cerr := a.Share.CreateLink(ctx, days, maxUses, subUntil)
|
||||
err = cerr
|
||||
if err == nil {
|
||||
okMsg = "Ссылка создана: #" + itoaHelper(link.ID)
|
||||
}
|
||||
|
||||
case "update":
|
||||
linkID := formInt(r, "link_id", 0)
|
||||
validityDays := formInt(r, "validity_days", 30)
|
||||
floating := r.FormValue("floating_expiry") == "1"
|
||||
expiresAt := parseFormDate(r.FormValue("expires_at"))
|
||||
subUntil := parseFormDate(r.FormValue("subscription_until"))
|
||||
maxUses := formInt(r, "max_uses", 5)
|
||||
err = a.Share.UpdateLink(ctx, linkID, validityDays, floating, expiresAt, subUntil, maxUses)
|
||||
if err == nil {
|
||||
okMsg = "Срок ссылки обновлён."
|
||||
}
|
||||
|
||||
case "delete":
|
||||
linkID := formInt(r, "link_id", 0)
|
||||
err = a.Share.DeleteLink(ctx, linkID)
|
||||
back = "admin/links"
|
||||
if err == nil {
|
||||
okMsg = "Ссылка удалена."
|
||||
}
|
||||
|
||||
case "extend":
|
||||
linkID := formInt(r, "link_id", 0)
|
||||
days := formInt(r, "days", 30)
|
||||
err = a.Share.ExtendLinkByDays(ctx, linkID, days)
|
||||
if err == nil {
|
||||
okMsg = "Ссылка продлена."
|
||||
}
|
||||
|
||||
case "set_allowed_servers":
|
||||
linkID := formInt(r, "link_id", 0)
|
||||
_ = r.ParseForm()
|
||||
var ids []int
|
||||
for _, v := range r.Form["server_ids[]"] {
|
||||
if n := formIntFromString(v, -1); n >= 0 {
|
||||
ids = append(ids, n)
|
||||
}
|
||||
}
|
||||
err = a.Share.SetAllowedServerIDs(ctx, linkID, ids)
|
||||
if err == nil {
|
||||
okMsg = "Список серверов обновлён."
|
||||
}
|
||||
|
||||
case "delete_creation":
|
||||
linkID := formInt(r, "link_id", 0)
|
||||
creationID := formInt64(r, "creation_id", 0)
|
||||
err = a.Share.SoftDeleteCreation(ctx, a.Panel, a.Settings, linkID, creationID)
|
||||
if err == nil {
|
||||
okMsg = "Конфигурация удалена."
|
||||
}
|
||||
|
||||
default:
|
||||
err = errUnknownAction
|
||||
}
|
||||
|
||||
errText := ""
|
||||
if err != nil {
|
||||
errText = err.Error()
|
||||
}
|
||||
redirectWithFlash(w, r, a, back, okMsg, errText)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user