home to your local SPACEGIRL 💫 arimelody.space
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

admin account/TOTP fixes

+67 -43
+25 -26
admin/accounthttp.go
··· 20 20 21 21 mux.Handle("/account/totp-setup", totpSetupHandler(app)) 22 22 mux.Handle("/account/totp-confirm", totpConfirmHandler(app)) 23 - mux.Handle("/account/totp-delete/", http.StripPrefix("/totp-delete", totpDeleteHandler(app))) 23 + mux.Handle("/account/totp-delete", totpDeleteHandler(app)) 24 24 25 25 mux.Handle("/account/password", changePasswordHandler(app)) 26 26 mux.Handle("/account/delete", deleteAccountHandler(app)) ··· 266 266 http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 267 267 return 268 268 } 269 - code := r.FormValue("totp") 270 - if len(code) != controller.TOTP_CODE_LENGTH { 271 - http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 272 - return 273 - } 274 269 275 270 totp, err := controller.GetTOTP(app.DB, session.Account.ID, name) 276 271 if err != nil { ··· 290 285 fmt.Fprintf(os.Stderr, "WARN: Failed to generate TOTP QR code: %v\n", err) 291 286 } 292 287 288 + code := r.FormValue("totp") 293 289 confirmCode := controller.GenerateTOTP(totp.Secret, 0) 294 - if code != confirmCode { 295 - confirmCodeOffset := controller.GenerateTOTP(totp.Secret, 1) 296 - if code != confirmCodeOffset { 297 - session.Error = sql.NullString{ Valid: true, String: "Incorrect TOTP code. Please try again." } 298 - err = templates.TOTPConfirmTemplate.Execute(w, totpConfirmData{ 299 - adminPageData: adminPageData{ Path: r.URL.Path, Session: session }, 300 - TOTP: totp, 301 - NameEscaped: url.PathEscape(totp.Name), 302 - QRBase64Image: qrBase64Image, 303 - }) 304 - if err != nil { 305 - fmt.Fprintf(os.Stderr, "WARN: Failed to render TOTP setup page: %v\n", err) 306 - http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) 307 - } 308 - return 290 + confirmCodeOffset := controller.GenerateTOTP(totp.Secret, 1) 291 + if len(code) != controller.TOTP_CODE_LENGTH || (code != confirmCode && code != confirmCodeOffset) { 292 + session.Error = sql.NullString{ Valid: true, String: "Incorrect TOTP code. Please try again." } 293 + err = templates.TOTPConfirmTemplate.Execute(w, totpConfirmData{ 294 + adminPageData: adminPageData{ Path: r.URL.Path, Session: session }, 295 + TOTP: totp, 296 + NameEscaped: url.PathEscape(totp.Name), 297 + QRBase64Image: qrBase64Image, 298 + }) 299 + if err != nil { 300 + fmt.Fprintf(os.Stderr, "WARN: Failed to render TOTP setup page: %v\n", err) 301 + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) 309 302 } 303 + return 310 304 } 311 305 312 306 err = controller.ConfirmTOTP(app.DB, session.Account.ID, name) ··· 327 321 328 322 func totpDeleteHandler(app *model.AppState) http.Handler { 329 323 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 330 - if r.Method != http.MethodGet { 324 + if r.Method != http.MethodPost { 331 325 http.NotFound(w, r) 332 326 return 333 327 } 334 328 335 - if len(r.URL.Path) < 2 { 329 + session := r.Context().Value("session").(*model.Session) 330 + 331 + err := r.ParseForm() 332 + if err != nil { 336 333 http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 337 334 return 338 335 } 339 - name := r.URL.Path[1:] 340 - 341 - session := r.Context().Value("session").(*model.Session) 336 + name := r.FormValue("totp-name") 337 + if len(name) == 0 { 338 + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) 339 + return 340 + } 342 341 343 342 totp, err := controller.GetTOTP(app.DB, session.Account.ID, name) 344 343 if err != nil {
+8 -3
admin/static/admin.css
··· 309 309 margin: 0 0 1em 0; 310 310 padding: 1em; 311 311 border-radius: 8px; 312 + color: #101010; 312 313 background: #ffffff; 313 314 } 314 315 #message { ··· 379 380 form { 380 381 width: 100%; 381 382 display: block; 383 + color: var(--fg-0); 382 384 } 383 385 form label { 384 386 width: 100%; 385 387 margin: 1rem 0 .5rem 0; 386 388 display: block; 387 - color: #10101080; 388 389 } 389 390 form input { 390 - margin: .5rem 0; 391 - padding: .3rem .5rem; 391 + min-width: 20rem; 392 + max-width: calc(100% - 1em)); 393 + margin: .5em 0; 394 + padding: .3em .5em; 392 395 display: block; 393 396 border-radius: 4px; 397 + border: 1px solid #808080; 394 398 font-size: inherit; 395 399 font-family: inherit; 396 400 color: inherit; 401 + background-color: var(--bg-0); 397 402 } 398 403 input[disabled] { 399 404 opacity: .5;
+6 -1
admin/static/edit-account.css
··· 11 11 align-items: center; 12 12 color: inherit; 13 13 } 14 - input { 14 + form#change-password input, 15 + form#delete-account input { 15 16 width: min(20rem, calc(100% - 1rem)); 16 17 margin: .5rem 0; 17 18 padding: .3rem .5rem; ··· 48 49 .mfa-device .mfa-device-name { 49 50 font-weight: bold; 50 51 } 52 + 53 + .mfa-device form input { 54 + display: none; 55 + }
-1
admin/templates/html/artists.html
··· 1 1 {{define "head"}} 2 2 <title>Artists - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <link rel="stylesheet" href="/admin/static/artists.css"> 6 5 {{end}} 7 6
+9 -2
admin/templates/html/edit-account.html
··· 28 28 <label for="confirm-password">Confirm Password</label> 29 29 <input type="password" id="confirm-password" value="" autocomplete="new-password" required> 30 30 31 + <br> 32 + 31 33 <button type="submit" class="save">Change Password</button> 32 34 </form> 33 35 </div> ··· 44 46 <p class="mfa-device-date">Added: {{.CreatedAtString}}</p> 45 47 </div> 46 48 <div> 47 - <a class="button delete" href="/admin/account/totp-delete/{{.TOTP.Name}}">Delete</a> 49 + <form method="POST" action="/admin/account/totp-delete"> 50 + <input type="text" name="totp-name" value="{{.TOTP.Name}}" hidden> 51 + <button type="submit" class="delete">Delete</button> 52 + </form> 48 53 </div> 49 54 </div> 50 55 {{end}} ··· 67 72 This action is <strong>irreversible</strong>. 68 73 You will need to enter your password and TOTP below. 69 74 </p> 70 - <form action="/admin/account/delete" method="POST"> 75 + <form action="/admin/account/delete" method="POST" id="delete-account"> 71 76 <label for="password">Password</label> 72 77 <input type="password" name="password" value="" autocomplete="current-password" required> 73 78 74 79 <label for="totp">TOTP</label> 75 80 <input type="text" name="totp" value="" autocomplete="one-time-code" required> 81 + 82 + <br> 76 83 77 84 <button type="submit" class="delete">Delete Account</button> 78 85 </form>
-1
admin/templates/html/index.html
··· 1 1 {{define "head"}} 2 2 <title>Admin - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <link rel="stylesheet" href="/admin/static/releases.css"> 6 5 <link rel="stylesheet" href="/admin/static/artists.css"> 7 6 <link rel="stylesheet" href="/admin/static/tracks.css">
-1
admin/templates/html/login-totp.html
··· 1 1 {{define "head"}} 2 2 <title>Login - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <style> 6 5 form#login-totp { 7 6 width: 100%;
-1
admin/templates/html/login.html
··· 1 1 {{define "head"}} 2 2 <title>Login - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <style> 6 5 form#login { 7 6 width: 100%;
-1
admin/templates/html/logs.html
··· 1 1 {{define "head"}} 2 2 <title>Audit Logs - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <link rel="stylesheet" href="/admin/static/logs.css"> 6 5 {{end}} 7 6
-1
admin/templates/html/register.html
··· 1 1 {{define "head"}} 2 2 <title>Register - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <style> 6 5 p a { 7 6 color: #2a67c8;
-1
admin/templates/html/releases.html
··· 1 1 {{define "head"}} 2 2 <title>Releases - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <link rel="stylesheet" href="/admin/static/releases.css"> 6 5 {{end}} 7 6
+17 -2
admin/templates/html/totp-confirm.html
··· 1 1 {{define "head"}} 2 2 <title>TOTP Confirmation - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <style> 6 5 .qr-code { 7 6 border: 1px solid #8888; ··· 9 8 code { 10 9 user-select: all; 11 10 } 11 + #totp-setup input { 12 + width: 3.8em; 13 + min-width: auto; 14 + font-size: 32px; 15 + font-family: 'Monaspace Argon', monospace; 16 + text-align: center; 17 + } 12 18 </style> 13 19 {{end}} 14 20 15 21 {{define "content"}} 16 22 <main> 23 + <h1>Two-Factor Authentication</h1> 24 + 17 25 {{if .Session.Error.Valid}} 18 26 <p id="error">{{html .Session.Error.String}}</p> 19 27 {{end}} ··· 40 48 <p><code>{{.TOTP.Secret}}</code></p> 41 49 42 50 <label for="totp">TOTP:</label> 43 - <input type="text" name="totp" value="" autocomplete="one-time-code" required autofocus> 51 + <input type="text" 52 + name="totp" 53 + value="" 54 + minlength="6" 55 + maxlength="6" 56 + autocomplete="one-time-code" 57 + required 58 + autofocus> 44 59 45 60 <button type="submit" class="new">Create</button> 46 61 </form>
+2 -1
admin/templates/html/totp-setup.html
··· 1 1 {{define "head"}} 2 2 <title>TOTP Setup - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 {{end}} 6 5 7 6 {{define "content"}} 8 7 <main> 8 + <h1>Two-Factor Authentication</h1> 9 + 9 10 {{if .Session.Error.Valid}} 10 11 <p id="error">{{html .Session.Error.String}}</p> 11 12 {{end}}
-1
admin/templates/html/tracks.html
··· 1 1 {{define "head"}} 2 2 <title>Releases - ari melody 💫</title> 3 3 <link rel="shortcut icon" href="/img/favicon.png" type="image/x-icon"> 4 - <link rel="stylesheet" href="/admin/static/admin.css"> 5 4 <link rel="stylesheet" href="/admin/static/tracks.css"> 6 5 {{end}} 7 6