2025-04-24 13:58:05 -05:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
2025-04-27 23:14:37 -05:00
|
|
|
"fmt"
|
2025-04-24 13:58:05 -05:00
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
authdiscord "example.com/auth/discord"
|
|
|
|
configserver "example.com/config/server"
|
|
|
|
databasecommands "example.com/database/commands"
|
2025-04-27 23:14:37 -05:00
|
|
|
create "example.com/database/commands/create"
|
|
|
|
get "example.com/database/commands/get"
|
|
|
|
update "example.com/database/commands/update"
|
|
|
|
function "example.com/database/function"
|
|
|
|
functiontag "example.com/database/functiontag"
|
|
|
|
group "example.com/database/group"
|
2025-04-24 13:58:05 -05:00
|
|
|
databasemodels "example.com/database/models"
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/xyproto/randomstring"
|
|
|
|
"golang.org/x/oauth2"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
)
|
|
|
|
|
|
|
|
var GlobalDatabase *gorm.DB
|
|
|
|
var GlobalConfig configserver.AppConfig
|
|
|
|
var GlobalOAuth *oauth2.Config
|
|
|
|
|
2025-04-24 20:17:30 -05:00
|
|
|
// Private Functions
|
|
|
|
|
2025-04-24 17:08:09 -05:00
|
|
|
// Authentication Workflow
|
|
|
|
|
|
|
|
func AuthCallback(context *gin.Context) {
|
|
|
|
oauthState := randomstring.CookieFriendlyString(32)
|
|
|
|
context.Set("state", oauthState)
|
|
|
|
var err error
|
|
|
|
oauthToken, err := GlobalOAuth.Exchange(context.Request.Context(), context.Query("code"))
|
|
|
|
if err != nil {
|
2025-04-27 23:14:37 -05:00
|
|
|
context.Redirect(http.StatusInternalServerError, GlobalConfig.GetFrontendRootDomain())
|
2025-04-24 17:08:09 -05:00
|
|
|
}
|
|
|
|
oauthTokenJSON, _ := json.Marshal(oauthToken)
|
|
|
|
context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false)
|
|
|
|
context.Set("discord-oauthtoken", string(oauthTokenJSON))
|
|
|
|
CreateOrUpdateUser(context)
|
2025-04-27 23:14:37 -05:00
|
|
|
context.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%sdashboard", GlobalConfig.GetFrontendRootDomain()))
|
2025-04-24 17:08:09 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func AuthLoginRedirect(context *gin.Context) {
|
2025-04-27 23:14:37 -05:00
|
|
|
log.Println(GlobalOAuth.AuthCodeURL(context.GetString("state")))
|
2025-04-24 13:58:05 -05:00
|
|
|
context.Redirect(302, GlobalOAuth.AuthCodeURL(context.GetString("state")))
|
|
|
|
}
|
|
|
|
|
2025-04-24 17:08:09 -05:00
|
|
|
func AuthLogoutRedirect(context *gin.Context) {
|
2025-04-24 13:58:05 -05:00
|
|
|
oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
|
|
|
|
if err == nil {
|
|
|
|
databasecommands.LogoutDatabaseUser(GlobalDatabase, oauthTokenJSON)
|
|
|
|
context.SetCookie("discord-oauthtoken", "", -1, "", GlobalConfig.API.Domain, false, true)
|
|
|
|
} else {
|
|
|
|
log.Println(err)
|
|
|
|
}
|
2025-04-27 23:14:37 -05:00
|
|
|
context.Redirect(http.StatusTemporaryRedirect, GlobalConfig.GetFrontendRootDomain())
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
|
|
|
|
2025-04-24 17:08:09 -05:00
|
|
|
// Create & Update Endpoints (post/, put/, patch)
|
|
|
|
|
|
|
|
func CreateOrUpdateUser(context *gin.Context) {
|
2025-04-25 17:39:40 -05:00
|
|
|
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)
|
|
|
|
}
|
2025-04-24 17:08:09 -05:00
|
|
|
}
|
|
|
|
var oauthToken *oauth2.Token
|
|
|
|
err = json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
context.AbortWithStatus(http.StatusBadRequest)
|
|
|
|
}
|
2025-04-27 23:14:37 -05:00
|
|
|
var currentDiscordUser authdiscord.DiscordUser
|
|
|
|
currentDiscordUser.GetDiscordUser(context, oauthToken, GlobalConfig, GlobalOAuth)
|
2025-04-24 17:08:09 -05:00
|
|
|
updatedDatabaseUser := databasemodels.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,
|
2025-04-25 20:14:46 -05:00
|
|
|
ApiKey: nil,
|
2025-04-24 17:08:09 -05:00
|
|
|
}
|
2025-04-27 23:14:37 -05:00
|
|
|
if get.GetDatabaseUserExists(GlobalDatabase, currentDiscordUser.Id) {
|
|
|
|
dbOAuthToken := get.GetDatabaseUserToken(GlobalDatabase, currentDiscordUser.Id)
|
|
|
|
if get.GetDatabaseUserLoggedInFromDiscordId(GlobalDatabase, currentDiscordUser.Id) {
|
2025-04-24 17:08:09 -05:00
|
|
|
context.SetCookie("discord-oauthtoken", dbOAuthToken, 0, "", GlobalConfig.API.Domain, false, false)
|
2025-04-25 17:39:40 -05:00
|
|
|
updatedDatabaseUser.LoginToken = string(dbOAuthToken)
|
2025-04-25 00:25:58 -05:00
|
|
|
} else {
|
|
|
|
context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false)
|
|
|
|
}
|
2025-04-27 23:14:37 -05:00
|
|
|
err := update.UpdateDatabaseUser(GlobalDatabase, updatedDatabaseUser)
|
2025-04-25 00:25:58 -05:00
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
context.AbortWithStatus(http.StatusInternalServerError)
|
2025-04-24 17:08:09 -05:00
|
|
|
}
|
|
|
|
} else {
|
2025-04-27 23:14:37 -05:00
|
|
|
err := create.CreateDatabaseUser(GlobalDatabase, updatedDatabaseUser)
|
2025-04-24 17:08:09 -05:00
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
context.Copy().AbortWithStatus(http.StatusInternalServerError)
|
|
|
|
}
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-24 20:17:30 -05:00
|
|
|
func CreateDatabaseGroup(context *gin.Context) {
|
2025-04-25 00:25:58 -05:00
|
|
|
GetIsUserAuthorized(context)
|
|
|
|
isAuthorized := context.GetBool("is-authorized")
|
|
|
|
if isAuthorized {
|
|
|
|
name := context.Query("name")
|
|
|
|
if name != "" {
|
2025-04-27 23:14:37 -05:00
|
|
|
group.Group{Name: name}.Create(GlobalDatabase)
|
2025-04-25 00:25:58 -05:00
|
|
|
context.Status(http.StatusOK)
|
|
|
|
} else {
|
|
|
|
context.AbortWithStatus(http.StatusBadRequest)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
context.AbortWithStatus(http.StatusUnauthorized)
|
|
|
|
}
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
|
|
|
|
2025-04-25 17:39:40 -05:00
|
|
|
func CreateDatabaseFunction(context *gin.Context) {
|
|
|
|
GetIsUserAuthorized(context)
|
|
|
|
isAuthorized := context.GetBool("is-authorized")
|
|
|
|
if isAuthorized {
|
2025-04-27 23:14:37 -05:00
|
|
|
name, nameOk := context.GetQuery("name")
|
|
|
|
tags, tagsOk := context.GetQueryArray("tags")
|
|
|
|
requirements, requirementsOk := context.GetQueryArray("requirements")
|
|
|
|
if nameOk {
|
|
|
|
var newTags *[]functiontag.FunctionTag
|
|
|
|
var newRequirements *[]function.Function
|
|
|
|
if tagsOk {
|
|
|
|
newTags = functiontag.Get(GlobalDatabase, tags)
|
2025-04-25 17:39:40 -05:00
|
|
|
}
|
2025-04-27 23:14:37 -05:00
|
|
|
if requirementsOk {
|
|
|
|
newRequirements = function.Get(GlobalDatabase, requirements)
|
2025-04-25 17:39:40 -05:00
|
|
|
}
|
2025-04-27 23:14:37 -05:00
|
|
|
log.Printf("OKAY\nName: %s\nTags: %v\nRequirements: %v", name, *newTags, *newRequirements)
|
|
|
|
function.Function{
|
2025-04-25 17:39:40 -05:00
|
|
|
Name: name,
|
2025-04-27 23:14:37 -05:00
|
|
|
Tags: *newTags,
|
|
|
|
Requirements: *newRequirements,
|
|
|
|
}.Create(GlobalDatabase)
|
2025-04-25 17:39:40 -05:00
|
|
|
context.Status(http.StatusOK)
|
|
|
|
} else {
|
|
|
|
context.AbortWithStatus(http.StatusBadRequest)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
context.AbortWithStatus(http.StatusUnauthorized)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func CreateDatabaseFunctionTag(context *gin.Context) {
|
|
|
|
GetIsUserAuthorized(context)
|
|
|
|
isAuthorized := context.GetBool("is-authorized")
|
|
|
|
log.Println(isAuthorized)
|
|
|
|
if isAuthorized {
|
|
|
|
name := context.Query("name")
|
|
|
|
if name != "" {
|
2025-04-27 23:14:37 -05:00
|
|
|
functiontag.FunctionTag{
|
2025-04-25 17:39:40 -05:00
|
|
|
Name: name,
|
2025-04-27 23:14:37 -05:00
|
|
|
}.Create(GlobalDatabase)
|
2025-04-25 17:39:40 -05:00
|
|
|
context.Status(http.StatusOK)
|
|
|
|
} else {
|
|
|
|
context.AbortWithStatus(http.StatusBadRequest)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
context.AbortWithStatus(http.StatusUnauthorized)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-24 20:17:30 -05:00
|
|
|
// Read Endpoints (get/)
|
|
|
|
|
2025-04-24 17:08:09 -05:00
|
|
|
func GetUserInfo(context *gin.Context) {
|
2025-04-24 13:58:05 -05:00
|
|
|
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() {
|
2025-04-27 23:14:37 -05:00
|
|
|
var user authdiscord.DiscordUser
|
|
|
|
user.GetDiscordUser(context, oauthToken, GlobalConfig, GlobalOAuth)
|
|
|
|
if get.GetDatabaseUserLoggedInFromDiscordId(GlobalDatabase, user.Id) {
|
2025-04-24 13:58:05 -05:00
|
|
|
context.JSON(http.StatusOK, user)
|
|
|
|
} else {
|
2025-04-27 23:14:37 -05:00
|
|
|
context.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%slogout", GlobalConfig.GetAPIRootDomain()))
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
|
|
|
return
|
2025-04-24 17:08:09 -05:00
|
|
|
} else {
|
|
|
|
log.Println(err)
|
|
|
|
context.AbortWithStatus(http.StatusBadRequest)
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Println(err)
|
2025-04-24 17:08:09 -05:00
|
|
|
context.AbortWithStatus(http.StatusBadRequest)
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
log.Println(err)
|
2025-04-24 17:08:09 -05:00
|
|
|
context.AbortWithStatus(http.StatusBadRequest)
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
2025-04-27 23:14:37 -05:00
|
|
|
context.Redirect(http.StatusTemporaryRedirect, GlobalConfig.GetFrontendRootDomain())
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
|
|
|
|
2025-04-24 17:08:09 -05:00
|
|
|
func GetIsUserAuthorized(context *gin.Context) {
|
2025-04-24 13:58:05 -05:00
|
|
|
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() {
|
2025-04-27 23:14:37 -05:00
|
|
|
if get.GetDatabaseUserLoggedIn(GlobalDatabase, oauthTokenJSON) {
|
2025-04-24 13:58:05 -05:00
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"message": true,
|
|
|
|
})
|
2025-04-25 00:25:58 -05:00
|
|
|
context.Set("is-authorized", true)
|
|
|
|
return
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
context.JSON(http.StatusUnauthorized, gin.H{
|
|
|
|
"message": false,
|
|
|
|
})
|
2025-04-25 00:25:58 -05:00
|
|
|
context.Set("is-authorized", false)
|
2025-04-24 13:58:05 -05:00
|
|
|
}
|
2025-04-24 17:08:09 -05:00
|
|
|
|
2025-04-27 23:14:37 -05:00
|
|
|
func GetDatabaseGroups(context *gin.Context) {
|
|
|
|
groupNames, ok := context.GetQueryArray("groups")
|
|
|
|
if ok {
|
|
|
|
groups := group.Get(GlobalDatabase, groupNames)
|
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"groups": groups,
|
|
|
|
})
|
2025-04-24 20:17:30 -05:00
|
|
|
} else {
|
2025-04-27 23:14:37 -05:00
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"groups": []group.Group{},
|
2025-04-24 20:17:30 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-27 03:22:42 -05:00
|
|
|
func GetAllDatabaseGroups(context *gin.Context) {
|
2025-04-27 23:14:37 -05:00
|
|
|
groups := group.GetAll(GlobalDatabase)
|
2025-04-24 20:17:30 -05:00
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"groups": groups,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-04-27 23:14:37 -05:00
|
|
|
func GetDatabaseFunctions(context *gin.Context) {
|
|
|
|
functionNames, ok := context.GetQueryArray("functions")
|
|
|
|
if ok {
|
|
|
|
functions := function.Get(GlobalDatabase, functionNames)
|
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"functions": functions,
|
|
|
|
})
|
2025-04-25 17:39:40 -05:00
|
|
|
} else {
|
2025-04-27 23:14:37 -05:00
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"functions": function.Function{},
|
2025-04-25 17:39:40 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-27 03:22:42 -05:00
|
|
|
func GetAllDatabaseFunctions(context *gin.Context) {
|
2025-04-27 23:14:37 -05:00
|
|
|
functions := function.GetAll(GlobalDatabase)
|
2025-04-25 17:39:40 -05:00
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"functions": functions,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-04-27 23:14:37 -05:00
|
|
|
func GetDatabaseFunctionTags(context *gin.Context) {
|
|
|
|
functionTagNames, ok := context.GetQueryArray("functiontags")
|
|
|
|
if ok {
|
|
|
|
functionTags := functiontag.Get(GlobalDatabase, functionTagNames)
|
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"function_tags": functionTags,
|
|
|
|
})
|
2025-04-25 17:39:40 -05:00
|
|
|
} else {
|
2025-04-27 23:14:37 -05:00
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"function_tags": []functiontag.FunctionTag{},
|
2025-04-25 17:39:40 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-27 03:22:42 -05:00
|
|
|
func GetAllDatabaseFunctionTags(context *gin.Context) {
|
2025-04-27 23:14:37 -05:00
|
|
|
functionTags := functiontag.GetAll(GlobalDatabase)
|
2025-04-25 17:39:40 -05:00
|
|
|
context.JSON(http.StatusOK, gin.H{
|
|
|
|
"function_tags": functionTags,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-04-24 17:08:09 -05:00
|
|
|
// Delete Endpoints (delete/)
|