cpularp-manager-api/gin-cpularp.go
2025-04-23 10:29:40 -07:00

255 lines
6.7 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"example.com/lib/dbcommands"
"github.com/gin-gonic/gin"
"github.com/pelletier/go-toml/v2"
"github.com/ravener/discord-oauth2"
"github.com/xyproto/randomstring"
"golang.org/x/oauth2"
"gorm.io/gorm"
)
type appConfig struct {
API struct {
Domain string
Port string
Https bool
}
OAuth struct {
ClientID string
ClientSecret string
}
}
type discordUser struct {
Id string
Username string
Avatar string
Discriminator string
Public_Flags float64
Flags float64
Banner string
Accent_Color float64
Global_Name string
Avatar_Decoration_Data struct {
Asset string
Sku_Id string
Expires_At string
}
Collectibles string
Banner_Color string
Clan string
Primary_Guild string
Mfa_Eneabled bool
Locale string
Premium_Type float64
}
var db *gorm.DB
var config appConfig
var oauthConfig *oauth2.Config
func parseConfig(configPath string) appConfig {
configFile, err := os.Open(configPath)
if err != nil {
log.Fatal(err)
}
configFileContent, err := io.ReadAll(configFile)
if err != nil {
log.Fatal(err)
}
var configObject appConfig
err = toml.Unmarshal(configFileContent, &configObject)
if err != nil {
log.Fatal(err)
}
return configObject
}
func createDiscordOAuthConfig() *oauth2.Config {
protocolString := ""
if config.API.Https {
protocolString = "https://"
config.API.Port = ""
} else {
protocolString = "http://"
config.API.Port = fmt.Sprintf(":%s", config.API.Port)
}
redirectUrlString := fmt.Sprintf("%s%s%s/auth/callback", protocolString, config.API.Domain, config.API.Port)
config := &oauth2.Config{
ClientID: config.OAuth.ClientID,
ClientSecret: config.OAuth.ClientSecret,
RedirectURL: redirectUrlString,
Scopes: []string{discord.ScopeIdentify},
Endpoint: discord.Endpoint,
}
return config
}
func loginRedirect(context *gin.Context) {
context.Redirect(302, oauthConfig.AuthCodeURL(context.GetString("state")))
}
func logoutRedirect(context *gin.Context) {
oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
if err == nil {
dbcommands.LogoutDatabaseUser(db, oauthTokenJSON)
context.SetCookie("discord-oauthtoken", "", -1, "", config.API.Domain, false, true)
} else {
log.Println(err)
}
context.Redirect(http.StatusTemporaryRedirect, "http://localhost:15995/")
}
func authCallback(context *gin.Context) {
oauthState := randomstring.CookieFriendlyString(32)
context.Set("state", oauthState)
var err error
oauthToken, err := oauthConfig.Exchange(context.Request.Context(), context.Query("code"))
if err != nil {
context.Redirect(http.StatusInternalServerError, "http://localhost:15995/")
}
oauthTokenJSON, _ := json.Marshal(oauthToken)
context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", config.API.Domain, false, false)
user := getDiscordUser(context, oauthToken)
createOrUpdateUser(context, oauthToken, user)
context.Redirect(http.StatusTemporaryRedirect, "http://localhost:15995/dashboard")
}
func getDiscordUser(context *gin.Context, oauthToken *oauth2.Token) discordUser {
log.Println(*oauthToken)
response, err := oauthConfig.Client(context.Request.Context(), oauthToken).Get("https://discord.com/api/users/@me")
if err != nil || response.StatusCode != 200 {
responseMessage := ""
if err != nil {
responseMessage = err.Error()
} else {
responseMessage = response.Status
}
context.JSON(http.StatusInternalServerError, gin.H{
"message": responseMessage,
})
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil {
context.JSON(http.StatusInternalServerError, gin.H{
"message": err.Error(),
})
}
log.Println(string(body))
var user discordUser
json.Unmarshal(body, &user)
return user
}
func createOrUpdateUser(context *gin.Context, oauthToken *oauth2.Token, user discordUser) {
oauthTokenJSON, err := json.Marshal(oauthToken)
if err != nil {
log.Println(err)
}
dbUser := dbcommands.User{
DisplayName: user.Global_Name,
Username: user.Username,
Id: user.Id,
Avatar: user.Avatar,
AvatarDecoration: user.Avatar_Decoration_Data.Asset,
LoginToken: string(oauthTokenJSON),
LoggedIn: true,
}
if dbcommands.DatabaseUserExists(db, user.Id) {
dbOAuthToken := dbcommands.GetDatabaseUserToken(db, user.Id)
if dbOAuthToken == "" {
context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", config.API.Domain, false, false)
err := dbcommands.UpdateDatabaseUser(db, dbUser)
if err != nil {
log.Println(err)
}
} else {
context.SetCookie("discord-oauthtoken", dbOAuthToken, 0, "", config.API.Domain, false, false)
}
} else {
err := dbcommands.CreateDatabaseUser(db, dbUser)
if err != nil {
log.Println(err)
}
}
}
func dashboardDisplay(context *gin.Context) {
oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
log.Println(oauthTokenJSON)
if err == nil {
var oauthToken *oauth2.Token
err := json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
if err == nil {
if oauthToken.Valid() {
user := getDiscordUser(context, oauthToken)
if dbcommands.DatabaseUserLoggedIn(db, user.Id) {
context.JSON(http.StatusOK, user)
return
} else {
context.Redirect(http.StatusTemporaryRedirect, "http://localhost:31337/logout")
}
return
}
} else {
log.Println(err)
}
} else {
log.Println(err)
}
context.Redirect(http.StatusTemporaryRedirect, "/")
}
func isUserAutorized(context *gin.Context) {
oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
log.Printf("Something something: %s", oauthTokenJSON)
if err == nil {
var oauthToken *oauth2.Token
err := json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
if err == nil {
if oauthToken.Valid() {
user := getDiscordUser(context, oauthToken)
log.Printf("What the fuck: %v", user)
is_logged_in := dbcommands.DatabaseUserLoggedIn(db, user.Id)
log.Printf("Whyyyyyy: %v", is_logged_in)
context.JSON(http.StatusOK, gin.H{
"message": is_logged_in,
})
return
} else {
log.Println(err)
}
} else {
log.Println(err)
}
} else {
log.Println(err)
}
context.JSON(http.StatusOK, gin.H{
"message": false,
})
}
func main() {
db = dbcommands.InitializeDatabase()
config = parseConfig("config.toml")
oauthConfig = createDiscordOAuthConfig()
app := gin.Default()
app.Static("/public", "./public")
app.GET("/login", loginRedirect)
app.GET("/auth/callback", authCallback)
app.GET("/logout", logoutRedirect)
app.GET("/dashboard", dashboardDisplay)
app.GET("/authorized", isUserAutorized)
app.Run(":31337")
}