apps/bookmarks/handlers_web.go 4.8 K raw
1
package main
2
3
import (
4
	"context"
5
	"net/http"
6
	"strings"
7
8
	"github.com/stevedylandev/andromeda/pkg/auth"
9
	"github.com/stevedylandev/andromeda/pkg/web"
10
)
11
12
func (a *App) indexHandler(w http.ResponseWriter, r *http.Request) {
13
	cats, _ := listCategories(a.DB)
14
	links, _ := listLinks(a.DB)
15
	groups := make([]categoryGroup, 0, len(cats))
16
	for _, c := range cats {
17
		group := categoryGroup{Name: c.Name}
18
		for _, l := range links {
19
			if l.CategoryID == c.ID {
20
				group.Links = append(group.Links, l)
21
			}
22
		}
23
		groups = append(groups, group)
24
	}
25
	web.Render(a.Templates, w, "index.html", indexPageData{Groups: groups}, a.Log)
26
}
27
28
func (a *App) loginGetHandler(w http.ResponseWriter, r *http.Request) {
29
	web.Render(a.Templates, w, "login.html", loginPageData{Error: r.URL.Query().Get("error")}, a.Log)
30
}
31
32
func (a *App) loginPostHandler(w http.ResponseWriter, r *http.Request) {
33
	if a.Password == "" {
34
		web.RedirectWithError(w, r, "/login", "No password configured")
35
		return
36
	}
37
	if err := r.ParseForm(); err != nil {
38
		web.RedirectWithError(w, r, "/login", "Bad request")
39
		return
40
	}
41
	if !auth.VerifyPassword(r.FormValue("password"), a.Password) {
42
		web.RedirectWithError(w, r, "/login", "Invalid password")
43
		return
44
	}
45
	token, err := a.Sessions.Create()
46
	if err != nil {
47
		a.Log.Error("create session failed", "err", err)
48
		web.RedirectWithError(w, r, "/login", "Session error")
49
		return
50
	}
51
	a.Sessions.PruneExpired()
52
	http.SetCookie(w, a.Sessions.SessionCookie(token))
53
	http.Redirect(w, r, "/admin", http.StatusSeeOther)
54
}
55
56
func (a *App) logoutHandler(w http.ResponseWriter, r *http.Request) {
57
	if c, err := r.Cookie(a.Sessions.CookieName); err == nil && c.Value != "" {
58
		a.Sessions.Delete(c.Value)
59
	}
60
	http.SetCookie(w, a.Sessions.ClearCookie())
61
	http.Redirect(w, r, "/login", http.StatusSeeOther)
62
}
63
64
func (a *App) adminHandler(w http.ResponseWriter, r *http.Request) {
65
	cats, _ := listCategories(a.DB)
66
	raw, _ := listLinks(a.DB)
67
	catName := map[int64]string{}
68
	for _, c := range cats {
69
		catName[c.ID] = c.Name
70
	}
71
	rows := make([]adminLinkRow, 0, len(raw))
72
	for _, l := range raw {
73
		rows = append(rows, adminLinkRow{ShortID: l.ShortID, Title: l.Title, URL: l.URL, FaviconURL: l.FaviconURL, Category: catName[l.CategoryID]})
74
	}
75
	web.Render(a.Templates, w, "admin.html", adminPageData{Success: r.URL.Query().Get("success"), Error: r.URL.Query().Get("error"), Categories: cats, Links: rows}, a.Log)
76
}
77
78
func (a *App) adminAddCategory(w http.ResponseWriter, r *http.Request) {
79
	if err := r.ParseForm(); err != nil {
80
		web.RedirectWithError(w, r, "/admin", "Bad request")
81
		return
82
	}
83
	name := strings.TrimSpace(r.FormValue("name"))
84
	if name == "" {
85
		web.RedirectWithError(w, r, "/admin", "Name required")
86
		return
87
	}
88
	if _, err := createCategory(a.DB, name); err != nil {
89
		a.Log.Error("create category", "err", err)
90
		web.RedirectWithError(w, r, "/admin", "Failed to add category")
91
		return
92
	}
93
	web.RedirectWithSuccess(w, r, "/admin", "Category added")
94
}
95
96
func (a *App) adminDeleteCategory(w http.ResponseWriter, r *http.Request) {
97
	_, _ = deleteCategoryByShortID(a.DB, r.PathValue("short_id"))
98
	web.RedirectWithSuccess(w, r, "/admin", "Category removed")
99
}
100
101
func (a *App) adminMoveCategory(w http.ResponseWriter, r *http.Request) {
102
	dir := 0
103
	switch r.PathValue("dir") {
104
	case "up":
105
		dir = -1
106
	case "down":
107
		dir = 1
108
	default:
109
		web.RedirectWithError(w, r, "/admin", "Invalid direction")
110
		return
111
	}
112
	if _, err := moveCategory(a.DB, r.PathValue("short_id"), dir); err != nil {
113
		a.Log.Error("move category", "err", err)
114
		web.RedirectWithError(w, r, "/admin", "Failed to reorder")
115
		return
116
	}
117
	web.RedirectWithSuccess(w, r, "/admin", "Category reordered")
118
}
119
120
func (a *App) adminAddLink(w http.ResponseWriter, r *http.Request) {
121
	if err := r.ParseForm(); err != nil {
122
		web.RedirectWithError(w, r, "/admin", "Bad request")
123
		return
124
	}
125
	title := strings.TrimSpace(r.FormValue("title"))
126
	url := strings.TrimSpace(r.FormValue("url"))
127
	if title == "" || url == "" {
128
		web.RedirectWithError(w, r, "/admin", "Title and URL required")
129
		return
130
	}
131
	cat, err := getCategoryByName(a.DB, r.FormValue("category"))
132
	if err != nil || cat == nil {
133
		web.RedirectWithError(w, r, "/admin", "Unknown category")
134
		return
135
	}
136
	link, err := createLink(a.DB, title, url, nil, cat.ID)
137
	if err != nil {
138
		a.Log.Error("create link", "err", err)
139
		web.RedirectWithError(w, r, "/admin", "Failed to add link")
140
		return
141
	}
142
	go func(id int64, u string) {
143
		if fav := discoverFavicon(context.Background(), u); fav != "" {
144
			if err := updateLinkFavicon(a.DB, id, &fav); err != nil {
145
				a.Log.Error("update favicon", "err", err)
146
			}
147
		}
148
	}(link.ID, url)
149
	web.RedirectWithSuccess(w, r, "/admin", "Link added")
150
}
151
152
func (a *App) adminDeleteLink(w http.ResponseWriter, r *http.Request) {
153
	_, _ = deleteLinkByShortID(a.DB, r.PathValue("short_id"))
154
	web.RedirectWithSuccess(w, r, "/admin", "Link removed")
155
}