Skip to content

Commit 0b0c819

Browse files
Supabase login
1 parent 83b2f91 commit 0b0c819

File tree

14 files changed

+501
-293
lines changed

14 files changed

+501
-293
lines changed

internal/admin/handlers.go

Lines changed: 79 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@ func NewHandler(templates TemplateRenderer) *Handler {
2929
}
3030

3131
func (h *Handler) AdminHandler(c echo.Context) error {
32+
cookie, err := c.Cookie("session")
33+
if err != nil {
34+
return h.templates.Render(c.Response().Writer, "admin/pages/login.html", map[string]interface{}{
35+
"Title": "Admin Login - Millions of Words",
36+
}, c)
37+
}
38+
39+
user, err := loader.ValidateSession(cookie.Value)
40+
if err != nil || user == nil {
41+
return h.templates.Render(c.Response().Writer, "admin/pages/login.html", map[string]interface{}{
42+
"Title": "Admin Login - Millions of Words",
43+
}, c)
44+
}
45+
3246
allAlbums, err := loader.LoadAllAlbumsData()
3347
if err != nil {
3448
log.Printf("Error loading albums: %v", err)
@@ -37,32 +51,33 @@ func (h *Handler) AdminHandler(c echo.Context) error {
3751

3852
return h.templates.Render(c.Response().Writer, "admin/pages/index.html", map[string]interface{}{
3953
"Title": "Admin - Millions of Words",
40-
"Authenticated": false,
54+
"Authenticated": true,
4155
"Albums": allAlbums,
4256
}, c)
4357
}
4458

4559
func (h *Handler) AdminAuthHandler(c echo.Context) error {
46-
key := c.FormValue("authKey")
47-
valid, err := loader.ValidateAuthKey(key)
48-
if err != nil || !valid {
49-
return c.HTML(http.StatusUnauthorized, `
50-
<div class="text-red-500 text-center p-2">Invalid authentication key</div>
51-
`)
52-
}
60+
email := c.FormValue("email")
61+
password := c.FormValue("password")
5362

54-
allAlbums, err := loader.LoadAllAlbumsData()
63+
user, err := loader.SignInWithEmail(email, password)
5564
if err != nil {
56-
log.Printf("Error loading albums: %v", err)
57-
return err
65+
return c.HTML(http.StatusUnauthorized, `
66+
<div class="text-red-500 text-center p-2">Invalid email or password</div>
67+
`)
5868
}
5969

60-
return h.templates.Render(c.Response().Writer, "admin/pages/index.html", map[string]interface{}{
61-
"Title": "Admin - Millions of Words",
62-
"Authenticated": true,
63-
"AuthKey": key,
64-
"Albums": allAlbums,
65-
}, c)
70+
c.SetCookie(&http.Cookie{
71+
Name: "session",
72+
Value: user.AccessToken,
73+
HttpOnly: true,
74+
Path: "/",
75+
Secure: true,
76+
SameSite: http.SameSiteStrictMode,
77+
MaxAge: 86400, // 24 hours
78+
})
79+
80+
return c.Redirect(http.StatusFound, "/admin")
6681
}
6782

6883
func (h *Handler) AdminEditorHandler(c echo.Context) error {
@@ -76,7 +91,7 @@ func (h *Handler) AdminEditorHandler(c echo.Context) error {
7691
return err
7792
}
7893

79-
return h.templates.Render(c.Response().Writer, "admin/components/album-form", map[string]interface{}{
94+
return h.templates.Render(c.Response().Writer, "admin/components/album-form.html", map[string]interface{}{
8095
"Albums": allAlbums,
8196
}, c)
8297
}
@@ -85,7 +100,8 @@ func (h *Handler) AdminImportHandler(c echo.Context) error {
85100
if err := validateAuth(c); err != nil {
86101
return err
87102
}
88-
return h.templates.Render(c.Response().Writer, "admin/components/import-form", nil, c)
103+
104+
return h.templates.Render(c.Response().Writer, "admin/components/import-form.html", nil, c)
89105
}
90106

91107
func (h *Handler) AdminAlbumEditorHandler(c echo.Context) error {
@@ -98,7 +114,6 @@ func (h *Handler) AdminAlbumEditorHandler(c echo.Context) error {
98114
return echo.NewHTTPError(http.StatusBadRequest, "No album ID provided")
99115
}
100116

101-
authKey := c.QueryParam("authKey")
102117
albums, err := loader.LoadAllAlbumsData()
103118
if err != nil {
104119
return echo.NewHTTPError(http.StatusInternalServerError, "Error loading albums")
@@ -107,8 +122,7 @@ func (h *Handler) AdminAlbumEditorHandler(c echo.Context) error {
107122
for _, album := range albums {
108123
if album.ID == albumID {
109124
return h.templates.Render(c.Response().Writer, "admin/components/album-editor-content.html", map[string]interface{}{
110-
"Album": album,
111-
"AuthKey": authKey,
125+
"Album": album,
112126
}, c)
113127
}
114128
}
@@ -151,14 +165,8 @@ func (h *Handler) UpdateTrackHandler(c echo.Context) error {
151165
}
152166

153167
func (h *Handler) ImportAlbumHandler(c echo.Context) error {
154-
key := c.FormValue("authKey")
155-
valid, err := loader.ValidateAuthKey(key)
156-
if err != nil || !valid {
157-
return c.HTML(http.StatusUnauthorized, `
158-
<div class="bg-red-500/10 border border-red-500 text-red-500 p-4 rounded">
159-
Invalid authentication
160-
</div>
161-
`)
168+
if err := validateAuth(c); err != nil {
169+
return err
162170
}
163171

164172
urls := strings.Split(c.FormValue("bandcampUrls"), "\n")
@@ -177,56 +185,56 @@ func (h *Handler) ImportAlbumHandler(c echo.Context) error {
177185

178186
if !strings.Contains(url, "bandcamp.com") {
179187
results = append(results, fmt.Sprintf(`
180-
<div class="bg-red-500/10 border border-red-500 text-red-500 p-2 rounded text-sm">
181-
Invalid Bandcamp URL: %s
182-
</div>`, url))
188+
<div class="bg-red-500/10 border border-red-500 text-red-500 p-2 rounded text-sm">
189+
Invalid Bandcamp URL: %s
190+
</div>`, url))
183191
continue
184192
}
185193

186194
exists, err := loader.AlbumUrlExists(url)
187195
if err != nil {
188196
results = append(results, fmt.Sprintf(`
189-
<div class="bg-red-500/10 border border-red-500 text-red-500 p-2 rounded text-sm">
190-
Error checking database for %s: %v
191-
</div>`, url, err))
197+
<div class="bg-red-500/10 border border-red-500 text-red-500 p-2 rounded text-sm">
198+
Error checking database for %s: %v
199+
</div>`, url, err))
192200
continue
193201
}
194202

195203
if exists {
196204
results = append(results, fmt.Sprintf(`
197-
<div class="bg-yellow-500/10 border border-yellow-500 text-yellow-500 p-2 rounded text-sm">
198-
%s has already been imported
199-
</div>`, url))
205+
<div class="bg-yellow-500/10 border border-yellow-500 text-yellow-500 p-2 rounded text-sm">
206+
%s has already been imported
207+
</div>`, url))
200208
continue
201209
}
202210

203211
albumData, err := fetch.FetchFromBandcamp(url)
204212
if err != nil {
205213
results = append(results, fmt.Sprintf(`
206-
<div class="bg-red-500/10 border border-red-500 text-red-500 p-2 rounded text-sm">
207-
Error fetching %s: %v
208-
</div>`, url, err))
214+
<div class="bg-red-500/10 border border-red-500 text-red-500 p-2 rounded text-sm">
215+
Error fetching %s: %v
216+
</div>`, url, err))
209217
continue
210218
}
211219

212220
if err := loader.SaveAlbum(albumData); err != nil {
213221
results = append(results, fmt.Sprintf(`
214-
<div class="bg-red-500/10 border border-red-500 text-red-500 p-2 rounded text-sm">
215-
Error saving %s: %v
216-
</div>`, url, err))
222+
<div class="bg-red-500/10 border border-red-500 text-red-500 p-2 rounded text-sm">
223+
Error saving %s: %v
224+
</div>`, url, err))
217225
continue
218226
}
219227

220228
results = append(results, fmt.Sprintf(`
221-
<div class="bg-green-500/10 border border-green-500 text-green-500 p-2 rounded text-sm">
222-
Successfully imported %s - %s
223-
</div>`, albumData.ArtistName, albumData.AlbumName))
229+
<div class="bg-green-500/10 border border-green-500 text-green-500 p-2 rounded text-sm">
230+
Successfully imported %s - %s
231+
</div>`, albumData.ArtistName, albumData.AlbumName))
224232

225233
progressMsg := fmt.Sprintf(`
226-
<div class="text-gray-400 text-sm text-right">
227-
Processed %d of %d
228-
</div>
229-
`, i+1, total)
234+
<div class="text-gray-400 text-sm text-right">
235+
Processed %d of %d
236+
</div>
237+
`, i+1, total)
230238

231239
log.Printf("Writing progress update to response")
232240
_, err = c.Response().Write([]byte(strings.Join(results, "\n") + progressMsg))
@@ -247,49 +255,48 @@ func (h *Handler) FetchMetalArchivesHandler(c echo.Context) error {
247255
return err
248256
}
249257

250-
url := c.FormValue("url")
258+
url := c.FormValue("metalArchivesUrl")
251259
if url == "" {
252-
return echo.NewHTTPError(http.StatusBadRequest, "URL is required")
260+
return echo.NewHTTPError(http.StatusBadRequest, "Metal Archives URL is required")
253261
}
254262

255-
album, err := fetch.FetchFromMetalArchives(url)
263+
data, err := fetch.FetchFromMetalArchives(url)
256264
if err != nil {
257-
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to fetch album: %v", err))
258-
}
259-
260-
if err := loader.SaveAlbum(album); err != nil {
261-
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to save album: %v", err))
265+
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Failed to fetch data: %v", err))
262266
}
263267

264-
return c.JSON(http.StatusOK, album)
268+
return h.templates.Render(c.Response().Writer, "admin/components/metal-archives-preview.html", map[string]interface{}{
269+
"Data": data,
270+
}, c)
265271
}
266272

267273
func (h *Handler) ValidateMetalArchivesUrlHandler(c echo.Context) error {
268274
if err := validateAuth(c); err != nil {
269275
return err
270276
}
271277

272-
url := c.FormValue("url")
278+
url := c.FormValue("metalArchivesUrl")
273279
if url == "" {
274-
return echo.NewHTTPError(http.StatusBadRequest, "URL is required")
280+
return c.HTML(http.StatusOK, "")
275281
}
276282

277-
if !strings.Contains(url, "metal-archives.com") {
278-
return echo.NewHTTPError(http.StatusBadRequest, "Invalid Metal Archives URL")
283+
if !strings.HasPrefix(url, "https://www.metal-archives.com/albums/") {
284+
return c.HTML(http.StatusOK, `<div class="text-red-500">Invalid Metal Archives URL format</div>`)
279285
}
280286

281-
return c.JSON(http.StatusOK, map[string]string{"status": "valid"})
287+
return c.HTML(http.StatusOK, "")
282288
}
283289

284290
func validateAuth(c echo.Context) error {
285-
key := c.QueryParam("authKey")
286-
if key == "" {
287-
key = c.FormValue("authKey")
291+
cookie, err := c.Cookie("session")
292+
if err != nil {
293+
return echo.NewHTTPError(http.StatusUnauthorized, "Not authenticated")
288294
}
289295

290-
valid, err := loader.ValidateAuthKey(key)
291-
if err != nil || !valid {
292-
return echo.NewHTTPError(http.StatusUnauthorized, "Invalid auth key")
296+
user, err := loader.ValidateSession(cookie.Value)
297+
if err != nil || user == nil {
298+
return echo.NewHTTPError(http.StatusUnauthorized, "Invalid session")
293299
}
300+
294301
return nil
295302
}

loaders/sqlite/loader.go

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -162,32 +162,7 @@ func calculateAverage(total, count int) int {
162162
return 0
163163
}
164164

165-
func ValidateAuthKey(key string) (bool, error) {
166-
db, err := sql.Open("sqlite", dbPath)
167-
if err != nil {
168-
return false, fmt.Errorf("error opening database: %w", err)
169-
}
170-
defer db.Close()
171-
172-
var exists bool
173-
err = db.QueryRow("SELECT EXISTS(SELECT 1 FROM auth_keys WHERE key = ?)", key).Scan(&exists)
174-
if err != nil {
175-
log.Printf("Error checking auth key: %v", err)
176-
return false, fmt.Errorf("error checking auth key: %w", err)
177-
}
178-
179-
return exists, nil
180-
}
181-
182165
func UpdateTrackLyrics(req models.UpdateTrackRequest) error {
183-
valid, err := ValidateAuthKey(req.AuthKey)
184-
if err != nil {
185-
return fmt.Errorf("error validating auth: %w", err)
186-
}
187-
if !valid {
188-
return fmt.Errorf("invalid auth key")
189-
}
190-
191166
cleanLyrics := strings.TrimSpace(req.Lyrics)
192167
if strings.HasPrefix(strings.ToLower(cleanLyrics), "lyrics") {
193168
cleanLyrics = ""

0 commit comments

Comments
 (0)