merge main into dev

This commit is contained in:
ari melody 2025-01-20 11:47:38 +00:00
commit 35d3ce5c5d
Signed by: ari
GPG key ID: CF99829C92678188
31 changed files with 423 additions and 174 deletions

View file

@ -3,7 +3,6 @@ package admin
import (
"fmt"
"math/rand"
"os"
"time"
"arimelody-web/global"
@ -28,20 +27,12 @@ var ADMIN_BYPASS = func() bool {
return false
}()
var ADMIN_ID_DISCORD = func() string {
id := os.Getenv("DISCORD_ADMIN")
if id == "" {
// fmt.Printf("WARN: Discord admin ID (DISCORD_ADMIN) was not provided.\n")
}
return id
}()
var sessions []*Session
func createSession(username string, expires time.Time) Session {
func createSession(userID string, expires time.Time) Session {
return Session{
Token: string(generateToken()),
UserID: username,
UserID: userID,
Expires: expires,
}
}

View file

@ -8,11 +8,13 @@ import (
"path/filepath"
"strings"
"time"
"encoding/json"
"arimelody-web/discord"
"arimelody-web/global"
"arimelody-web/controller"
"arimelody-web/model"
"golang.org/x/crypto/bcrypt"
)
type loginData struct {
@ -149,52 +151,57 @@ func GetSession(r *http.Request) *Session {
func LoginHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !discord.CREDENTIALS_PROVIDED || ADMIN_ID_DISCORD == "" {
http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable)
if r.Method == http.MethodGet {
err := pages["login"].Execute(w, nil)
if err != nil {
fmt.Printf("Error rendering admin login page: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
return
}
fmt.Println(discord.CLIENT_ID)
fmt.Println(discord.API_ENDPOINT)
fmt.Println(discord.REDIRECT_URI)
code := r.URL.Query().Get("code")
if code == "" {
pages["login"].Execute(w, loginData{DiscordURI: discord.REDIRECT_URI})
if r.Method != http.MethodPost {
http.NotFound(w, r);
return
}
auth_token, err := discord.GetOAuthTokenFromCode(code)
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
TOTP string `json:"totp"`
}
data := LoginRequest{}
err := json.NewDecoder(r.Body).Decode(&data)
if err != nil {
fmt.Printf("Failed to retrieve discord access token: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
discord_user, err := discord.GetDiscordUserFromAuth(auth_token)
account, err := controller.GetAccount(global.DB, data.Username)
if err != nil {
fmt.Printf("Failed to retrieve discord user information: %s\n", err)
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
http.Error(w, "No account exists with this username and password.", http.StatusBadRequest)
return
}
if discord_user.ID != ADMIN_ID_DISCORD {
// TODO: unauthorized user; revoke the token
fmt.Printf("Unauthorized login attempted: %s\n", discord_user.ID)
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
err = bcrypt.CompareHashAndPassword(account.Password, []byte(data.Password))
if err != nil {
http.Error(w, "No account exists with this username and password.", http.StatusBadRequest)
return
}
// TODO: check TOTP
// login success!
session := createSession(discord_user.Username, time.Now().Add(24 * time.Hour))
session := createSession(account.ID, time.Now().Add(24 * time.Hour))
sessions = append(sessions, &session)
cookie := http.Cookie{}
cookie.Name = "token"
cookie.Value = session.Token
cookie.Expires = time.Now().Add(24 * time.Hour)
if strings.HasPrefix(global.HTTP_DOMAIN, "https") {
if strings.HasPrefix(global.Config.BaseUrl, "https") {
cookie.Secure = true
}
cookie.HttpOnly = true