Updated config samplle, moved around user methods.

This commit is contained in:
Ada Werefox 2025-04-29 22:45:40 -07:00
parent dcbe844c41
commit be9702d716
5 changed files with 257 additions and 227 deletions

View file

@ -3,6 +3,11 @@ domain = "localhost"
port = "31337"
https = false
[frontend]
domain = "localhost"
port = "15995"
https = false
[oauth]
# You can get all of this from https://discord.com/developers/applications
clientid = "[CHANGE ME]"

View file

@ -18,7 +18,6 @@ func main() {
router.GET("/auth/login", api.AuthLoginRedirect)
router.GET("/auth/logout", api.AuthLogoutRedirect)
// Create
router.POST("/user/update", api.CreateOrUpdateUser)
router.POST("/group", api.CreateGroup)
router.POST("/function", api.CreateFunction)
router.POST("/function-tag", api.CreateFunctionTag)

View file

@ -36,6 +36,97 @@ var GlobalOAuth *oauth2.Config
// Private Functions
func createOrUpdateUser(context *gin.Context) {
oauthTokenJSON := context.GetString("discord-oauthtoken")
err := error(nil)
if oauthTokenJSON == "" {
oauthTokenJSON, err = context.Cookie("discord-oauthtoken")
if err != nil {
log.Printf("This really shouldn't happen. %s", err)
context.AbortWithStatus(http.StatusInternalServerError)
}
}
var oauthToken *oauth2.Token
err = json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
if err != nil {
log.Println(err)
context.AbortWithStatus(http.StatusBadRequest)
}
var currentDiscordUser authdiscord.DiscordUser
result := currentDiscordUser.Get(context, oauthToken, GlobalOAuth)
if result == "" {
if user.Exists(GlobalDatabase, currentDiscordUser.Id) {
currentUser := (*user.Get(GlobalDatabase, []string{currentDiscordUser.Id}))[0]
err := error(nil)
if currentUser.LoggedIn {
context.SetCookie("discord-oauthtoken", currentUser.LoginToken, 0, "", GlobalConfig.API.Domain, false, false)
err = user.Update(
GlobalDatabase,
currentDiscordUser.Id,
currentDiscordUser.Global_Name,
currentDiscordUser.Username,
currentDiscordUser.Avatar,
currentDiscordUser.Avatar_Decoration_Data.Asset,
currentUser.LoginToken,
true,
)
} else {
// context.SetCookie("discord-oauthtoken", oauthTokenJSON, 0, "", GlobalConfig.API.Domain, false, false)
err = user.Update(
GlobalDatabase,
currentDiscordUser.Id,
currentDiscordUser.Global_Name,
currentDiscordUser.Username,
currentDiscordUser.Avatar,
currentDiscordUser.Avatar_Decoration_Data.Asset,
oauthTokenJSON,
true,
)
}
if err != nil {
log.Println(err)
context.AbortWithStatus(http.StatusInternalServerError)
}
} else {
// context.SetCookie("discord-oauthtoken", oauthTokenJSON, 0, "", GlobalConfig.API.Domain, false, false)
err := user.Create(
GlobalDatabase,
currentDiscordUser.Id,
currentDiscordUser.Global_Name,
currentDiscordUser.Username,
currentDiscordUser.Avatar,
currentDiscordUser.Avatar_Decoration_Data.Asset,
oauthTokenJSON,
true,
)
if err != nil {
log.Println(err)
context.AbortWithStatus(http.StatusInternalServerError)
}
}
} else {
log.Printf("This also really shouldn't happen. %s", result)
context.AbortWithStatus(http.StatusInternalServerError)
}
}
func checkAuthentication(context *gin.Context) *oauth2.Token {
oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
if err == nil {
var oauthToken *oauth2.Token
err := json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
if err == nil {
if oauthToken.Valid() {
if (*user.Get(GlobalDatabase, []string{oauthTokenJSON}))[0].LoggedIn {
return oauthToken
}
}
}
}
context.Redirect(http.StatusTemporaryRedirect, GlobalConfig.GetFrontendRootDomain())
return nil
}
func objectIDStringsToInts(context *gin.Context, objectIDs []string) *[]int {
var objectIDInts []int
for _, objectID := range objectIDs {
@ -62,12 +153,13 @@ func AuthCallback(context *gin.Context) {
oauthTokenJSON, _ := json.Marshal(oauthToken)
context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false)
context.Set("discord-oauthtoken", string(oauthTokenJSON))
CreateOrUpdateUser(context)
createOrUpdateUser(context)
log.Println(GlobalConfig.GetFrontendRootDomain())
context.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%sdashboard", GlobalConfig.GetFrontendRootDomain()))
}
func AuthLoginRedirect(context *gin.Context) {
context.Redirect(302, GlobalOAuth.AuthCodeURL(context.GetString("state")))
context.Redirect(http.StatusTemporaryRedirect, GlobalOAuth.AuthCodeURL(context.GetString("state")))
}
func AuthLogoutRedirect(context *gin.Context) {
@ -78,65 +170,14 @@ func AuthLogoutRedirect(context *gin.Context) {
} else {
log.Println(err)
}
log.Println(GlobalConfig.GetFrontendRootDomain())
context.Redirect(http.StatusTemporaryRedirect, GlobalConfig.GetFrontendRootDomain())
}
func CreateOrUpdateUser(context *gin.Context) {
oauthTokenJSON := context.GetString("discord-oauthtoken")
err := error(nil)
if oauthTokenJSON == "" {
oauthTokenJSON, err = context.Cookie("discord-oauthtoken")
if err != nil {
log.Printf("This really shouldn't happen. %s", err)
context.AbortWithStatus(http.StatusInternalServerError)
}
}
var oauthToken *oauth2.Token
err = json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
if err != nil {
log.Println(err)
context.AbortWithStatus(http.StatusBadRequest)
}
var currentDiscordUser authdiscord.DiscordUser
currentDiscordUser.GetDiscordUser(context, oauthToken, GlobalConfig, GlobalOAuth)
updatedDatabaseUser := user.User{
DisplayName: currentDiscordUser.Global_Name,
Username: currentDiscordUser.Username,
Id: currentDiscordUser.Id,
Avatar: currentDiscordUser.Avatar,
AvatarDecoration: currentDiscordUser.Avatar_Decoration_Data.Asset,
LoginToken: string(oauthTokenJSON),
LoggedIn: true,
ApiKey: nil,
}
if user.Exists(GlobalDatabase, currentDiscordUser.Id) {
dbOAuthToken := user.GetTokenFromUserId(GlobalDatabase, currentDiscordUser.Id)
if user.GetLoggedInFromDiscordId(GlobalDatabase, currentDiscordUser.Id) {
context.SetCookie("discord-oauthtoken", dbOAuthToken, 0, "", GlobalConfig.API.Domain, false, false)
updatedDatabaseUser.LoginToken = string(dbOAuthToken)
} else {
context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false)
}
err := updatedDatabaseUser.Update(GlobalDatabase)
if err != nil {
log.Println(err)
context.AbortWithStatus(http.StatusInternalServerError)
}
} else {
err := updatedDatabaseUser.Create(GlobalDatabase)
if err != nil {
log.Println(err)
context.Copy().AbortWithStatus(http.StatusInternalServerError)
}
}
}
// Create Endpoints (post/)
// Create Endpoints (POST)
func CreateGroup(context *gin.Context) {
GetUserLoggedIn(context)
isAuthorized := context.GetBool("is-authorized")
if isAuthorized {
checkAuthentication(context)
name, nameOk := context.GetQuery("name")
if nameOk {
group.Create(GlobalDatabase, name)
@ -144,15 +185,10 @@ func CreateGroup(context *gin.Context) {
} else {
context.AbortWithStatus(http.StatusBadRequest)
}
} else {
context.AbortWithStatus(http.StatusUnauthorized)
}
}
func CreateFunction(context *gin.Context) {
GetUserLoggedIn(context)
isAuthorized := context.GetBool("is-authorized")
if isAuthorized {
checkAuthentication(context)
name, nameOk := context.GetQuery("name")
tags := context.QueryArray("tags")
requirements := context.QueryArray("requirements")
@ -162,15 +198,10 @@ func CreateFunction(context *gin.Context) {
} else {
context.AbortWithStatus(http.StatusBadRequest)
}
} else {
context.AbortWithStatus(http.StatusUnauthorized)
}
}
func CreateFunctionTag(context *gin.Context) {
GetUserLoggedIn(context)
isAuthorized := context.GetBool("is-authorized")
if isAuthorized {
checkAuthentication(context)
name := context.Query("name")
if name != "" {
functiontag.Create(GlobalDatabase, name)
@ -178,17 +209,12 @@ func CreateFunctionTag(context *gin.Context) {
} else {
context.AbortWithStatus(http.StatusBadRequest)
}
} else {
context.AbortWithStatus(http.StatusUnauthorized)
}
}
// Update Endpoints (put/)
// Update Endpoints (PUT)
func UpdateFunction(context *gin.Context) {
GetUserLoggedIn(context)
isAuthorized := context.GetBool("is-authorized")
if isAuthorized {
checkAuthentication(context)
name, nameOk := context.GetQuery("name")
tags := context.QueryArray("tags")
requirements := context.QueryArray("requirements")
@ -198,70 +224,42 @@ func UpdateFunction(context *gin.Context) {
} else {
context.AbortWithStatus(http.StatusBadRequest)
}
} else {
context.AbortWithStatus(http.StatusUnauthorized)
}
}
// Read Endpoints (get/)
// Read Endpoints (GET)
func GetDiscordUser(context *gin.Context) {
oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
if err == nil {
var oauthToken *oauth2.Token
err := json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
if err == nil {
if oauthToken.Valid() {
oauthToken := checkAuthentication(context)
if oauthToken != nil {
var discordUser authdiscord.DiscordUser
discordUser.GetDiscordUser(context, oauthToken, GlobalConfig, GlobalOAuth)
if user.GetLoggedInFromDiscordId(GlobalDatabase, discordUser.Id) {
result := discordUser.Get(context, oauthToken, GlobalOAuth)
if result != "" {
log.Println(result)
log.Println("Assuming the Discord OAuth Key has expired.")
context.Redirect(http.StatusUnauthorized, fmt.Sprintf("%slogout", GlobalConfig.GetFrontendRootDomain()))
} else {
if (*user.Get(GlobalDatabase, []string{discordUser.Id}))[0].LoggedIn {
context.JSON(http.StatusOK, discordUser)
} else {
context.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%slogout", GlobalConfig.GetAPIRootDomain()))
context.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%slogout", GlobalConfig.GetFrontendRootDomain()))
}
return
} else {
log.Println(err)
context.AbortWithStatus(http.StatusBadRequest)
}
} else {
log.Println(err)
context.AbortWithStatus(http.StatusBadRequest)
}
} else {
log.Println(err)
context.AbortWithStatus(http.StatusBadRequest)
}
context.Redirect(http.StatusTemporaryRedirect, GlobalConfig.GetFrontendRootDomain())
}
func GetUserLoggedIn(context *gin.Context) {
oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
if err == nil {
var oauthToken *oauth2.Token
err := json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
if err == nil {
if oauthToken.Valid() {
if user.GetLoggedInFromOAuthToken(GlobalDatabase, oauthTokenJSON) {
context.JSON(http.StatusOK, gin.H{
"message": true,
"message": (checkAuthentication(context) != nil),
})
context.Set("is-authorized", true)
return
}
}
}
}
context.JSON(http.StatusUnauthorized, gin.H{
"message": false,
})
context.Set("is-authorized", false)
}
func GetObjects(context *gin.Context) {
objectIDs, idOk := context.GetQueryArray("id")
if idOk {
switch objectType := context.Param("object"); objectType {
case "user":
context.JSON(http.StatusOK, gin.H{
"user": user.Get(GlobalDatabase, objectIDs)})
case "persons":
context.JSON(http.StatusOK, gin.H{
"persons": person.Get(GlobalDatabase, objectIDs),
@ -381,12 +379,10 @@ func GetAllObjects(context *gin.Context) {
}
}
// Delete Endpoints (delete/)
// Delete Endpoints (DELETE)
func DeleteFunction(context *gin.Context) {
GetUserLoggedIn(context)
isAuthorized := context.GetBool("is-authorized")
if isAuthorized {
checkAuthentication(context)
functionNames, ok := context.GetQueryArray("name")
if ok {
function.Delete(GlobalDatabase, functionNames)
@ -394,7 +390,4 @@ func DeleteFunction(context *gin.Context) {
} else {
context.AbortWithStatus(http.StatusBadRequest)
}
} else {
context.AbortWithStatus(http.StatusUnauthorized)
}
}

View file

@ -4,8 +4,6 @@ import (
"encoding/json"
"fmt"
"io"
"log"
"net/http"
configserver "example.com/config/server"
@ -38,25 +36,22 @@ type DiscordUser struct {
Premium_Type float64 `json:"premium_type"`
}
func (discordUser *DiscordUser) GetDiscordUser(context *gin.Context, oauthToken *oauth2.Token, appConfig configserver.AppConfig, oauthConfig *oauth2.Config) {
func (discordUser *DiscordUser) Get(context *gin.Context, oauthToken *oauth2.Token, oauthConfig *oauth2.Config) string {
response, err := oauthConfig.Client(context, oauthToken).Get("https://discord.com/api/users/@me")
if err != nil || response.StatusCode != 200 {
responseMessage := ""
if err != nil {
responseMessage = err.Error()
return err.Error()
} else {
responseMessage = response.Status
return response.Status
}
log.Println(responseMessage)
log.Println("Assuming the Discord OAuth Key has expired.")
context.Redirect(http.StatusUnauthorized, fmt.Sprintf("%slogout", appConfig.GetFrontendRootDomain()))
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil {
log.Println(err)
return err.Error()
}
json.Unmarshal(body, &discordUser)
return ""
}
func CreateDiscordOAuthConfig(config configserver.AppConfig) *oauth2.Config {

View file

@ -1,38 +1,26 @@
package user
import (
"errors"
"log"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Id string `json:"id"`
Id string `gorm:"primaryKey uniqueIndex" json:"id"`
DisplayName string `json:"display_name"`
Username string `json:"user_name"`
Avatar string `json:"avatar"`
AvatarDecoration string `json:"avatar_decoration"`
LoginToken string `json:"login_token"`
LoggedIn bool `json:"logged_in"`
ApiKey []struct {
Name string `gorm:"primaryKey uniqueIndex" json:"name"`
ApiKeys []struct {
Name string `json:"name"`
Key string `json:"key"`
} `gorm:"foreignKey:Name" json:"api_key"`
}
func (user *User) Get(db *gorm.DB, id string) {
db.Where("id = ?", id).Take(&user)
}
func (user User) Update(db *gorm.DB) error {
result := db.Save(&user)
if result.Error != nil {
return result.Error
}
return nil
}
func (user User) Create(db *gorm.DB) error {
result := db.Create(&user)
if result.Error != nil {
@ -41,46 +29,96 @@ func (user User) Create(db *gorm.DB) error {
return nil
}
func Logout(db *gorm.DB, oauthToken string) {
db.Model(&User{}).Where("login_token = ?", oauthToken).Update("logged_in", false)
func (user *User) Get(db *gorm.DB, id string) error {
result := db.Where("id = ?", id).Take(&user)
if result.Error == gorm.ErrRecordNotFound {
result := db.Where("login_token = ?", id).Take(&user)
if result.Error != nil {
return result.Error
}
}
return nil
}
func (user User) Update(db *gorm.DB) error {
var originalUser User
originalUser.Get(db, user.Id)
result := db.Model(&originalUser).Updates(&user)
if result.Error != nil {
return result.Error
}
return nil
}
func (user User) Delete(db *gorm.DB) error {
result := db.Delete(&user)
if result.Error != nil {
return result.Error
}
return nil
}
func (user User) Logout(db *gorm.DB) error {
result := db.Model(&user).Update("logged_in", false)
if result.Error != nil {
return result.Error
}
return nil
}
func Logout(db *gorm.DB, oauthToken string) error {
var user User
user.Get(db, oauthToken)
return user.Logout(db)
}
func Exists(db *gorm.DB, id string) bool {
var queryUser User
result := db.Where("id = ?", id).Take(&queryUser)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return false
} else {
return true
}
err := queryUser.Get(db, id)
return (err == nil)
}
func GetTokenFromUserId(db *gorm.DB, id string) string {
var dbUser User
result := db.Where("id = ?", id).Select("login_token").Take(&dbUser)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return ""
} else {
return dbUser.LoginToken
}
func Create(db *gorm.DB, id string, displayName string, username string, avatar string, avatarDecoration string, loginToken string, loggedIn bool) error {
return User{
Id: id,
DisplayName: displayName,
Username: username,
Avatar: avatar,
AvatarDecoration: avatarDecoration,
LoginToken: loginToken,
LoggedIn: loggedIn,
ApiKeys: nil,
}.Create(db)
}
func GetLoggedInFromOAuthToken(db *gorm.DB, oauthTokenJSON string) bool {
var queryUser User
result := db.Where("login_token = ?", oauthTokenJSON).Take(&queryUser)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return false
} else {
return queryUser.LoggedIn
func Get(db *gorm.DB, inputUsers []string) *[]User {
var outputUsers []User
for _, inputUser := range inputUsers {
var outputUser User
outputUser.Get(db, inputUser)
outputUsers = append(outputUsers, outputUser)
}
return &outputUsers
}
func GetLoggedInFromDiscordId(db *gorm.DB, discordId string) bool {
var queryUser User
result := db.Where("id = ?", discordId).Take(&queryUser)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return false
} else {
return queryUser.LoggedIn
func GetAll(db *gorm.DB) *[]User {
var outputUserIDs []string
result := db.Model(&User{}).Select("id").Find(&outputUserIDs)
if result.Error != nil {
log.Println(result.Error)
}
return Get(db, outputUserIDs)
}
func Update(db *gorm.DB, id string, displayName string, username string, avatar string, avatarDecoration string, loginToken string, loggedIn bool) error {
return User{
Id: id,
DisplayName: displayName,
Username: username,
Avatar: avatar,
AvatarDecoration: avatarDecoration,
LoginToken: loginToken,
LoggedIn: loggedIn,
ApiKeys: nil,
}.Update(db)
}