We have database table associations!

This commit is contained in:
Ada Werefox 2025-04-25 15:39:40 -07:00
parent fc074d83c3
commit 98a53d6590
4 changed files with 289 additions and 90 deletions

View file

@ -21,11 +21,17 @@ func main() {
// Create & Update // Create & Update
app.POST("/post/user/update", api.CreateOrUpdateUser) app.POST("/post/user/update", api.CreateOrUpdateUser)
app.POST("/post/group", api.CreateDatabaseGroup) app.POST("/post/group", api.CreateDatabaseGroup)
app.POST("/post/function", api.CreateDatabaseFunction)
app.POST("/post/function-tag", api.CreateDatabaseFunctionTag)
// Read // Read
app.GET("/get/user/info", api.GetUserInfo) app.GET("/get/user/info", api.GetUserInfo)
app.GET("/get/user/authorized", api.GetIsUserAuthorized) app.GET("/get/user/authorized", api.GetIsUserAuthorized)
app.GET("/get/group", api.GetDatabaseGroup) app.GET("/get/group", api.GetDatabaseGroup)
app.GET("/get/groups", api.GetDatabaseGroups) app.GET("/get/groups", api.GetDatabaseGroups)
app.GET("/get/function", api.GetDatabaseFunction)
app.GET("/get/functions", api.GetDatabaseFunctions)
app.GET("/get/function-tag", api.GetDatabaseFunctionTag)
app.GET("/get/function-tags", api.GetDatabaseFunctionTags)
// Delete // Delete
app.Run(":31337") app.Run(":31337")
} }

View file

@ -81,9 +81,14 @@ func AuthLogoutRedirect(context *gin.Context) {
// Create & Update Endpoints (post/, put/, patch) // Create & Update Endpoints (post/, put/, patch)
func CreateOrUpdateUser(context *gin.Context) { func CreateOrUpdateUser(context *gin.Context) {
oauthTokenJSON, err := context.Cookie("discord-oauthtoken") oauthTokenJSON := context.GetString("discord-oauthtoken")
if err != nil { err := error(nil)
oauthTokenJSON = context.GetString("discord-oauthtoken") 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 var oauthToken *oauth2.Token
err = json.Unmarshal([]byte(oauthTokenJSON), &oauthToken) err = json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
@ -103,9 +108,9 @@ func CreateOrUpdateUser(context *gin.Context) {
} }
if databasecommands.GetDatabaseUserExists(GlobalDatabase, currentDiscordUser.Id) { if databasecommands.GetDatabaseUserExists(GlobalDatabase, currentDiscordUser.Id) {
dbOAuthToken := databasecommands.GetDatabaseUserToken(GlobalDatabase, currentDiscordUser.Id) dbOAuthToken := databasecommands.GetDatabaseUserToken(GlobalDatabase, currentDiscordUser.Id)
if databasecommands.GetDatabaseUserLoggedIn(GlobalDatabase, dbOAuthToken) { if databasecommands.GetDatabaseUserLoggedInFromDiscordId(GlobalDatabase, currentDiscordUser.Id) {
context.SetCookie("discord-oauthtoken", dbOAuthToken, 0, "", GlobalConfig.API.Domain, false, false) context.SetCookie("discord-oauthtoken", dbOAuthToken, 0, "", GlobalConfig.API.Domain, false, false)
updatedDatabaseUser.LoginToken = string(oauthTokenJSON) updatedDatabaseUser.LoginToken = string(dbOAuthToken)
} else { } else {
context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false) context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false)
} }
@ -126,7 +131,6 @@ func CreateOrUpdateUser(context *gin.Context) {
func CreateDatabaseGroup(context *gin.Context) { func CreateDatabaseGroup(context *gin.Context) {
GetIsUserAuthorized(context) GetIsUserAuthorized(context)
isAuthorized := context.GetBool("is-authorized") isAuthorized := context.GetBool("is-authorized")
log.Println(isAuthorized)
if isAuthorized { if isAuthorized {
name := context.Query("name") name := context.Query("name")
if name != "" { if name != "" {
@ -142,6 +146,59 @@ func CreateDatabaseGroup(context *gin.Context) {
} }
} }
func CreateDatabaseFunction(context *gin.Context) {
GetIsUserAuthorized(context)
isAuthorized := context.GetBool("is-authorized")
log.Println(isAuthorized)
if isAuthorized {
name := context.Query("name")
tags := context.QueryArray("tags")
requirements := context.QueryArray("requirements")
if name != "" {
newTags := []databasemodels.FunctionTag{}
log.Println(tags)
for _, tag := range tags {
newTags = append(newTags, databasecommands.GetDatabaseFunctionTag(GlobalDatabase, tag))
}
log.Println(newTags)
newRequirements := []databasemodels.Function{}
for _, requirement := range requirements {
newRequirement := databasecommands.GetDatabaseFunction(GlobalDatabase, requirement)
newRequirements = append(newRequirements, newRequirement)
}
databasecommands.CreateDatabaseFunction(GlobalDatabase, databasemodels.Function{
Name: name,
Tags: newTags,
Requirements: newRequirements,
})
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 != "" {
databasecommands.CreateDatabaseFunctionTag(GlobalDatabase, databasemodels.FunctionTag{
Name: name,
})
context.Status(http.StatusOK)
} else {
context.AbortWithStatus(http.StatusBadRequest)
}
} else {
context.AbortWithStatus(http.StatusUnauthorized)
}
}
// Read Endpoints (get/) // Read Endpoints (get/)
func GetUserInfo(context *gin.Context) { func GetUserInfo(context *gin.Context) {
@ -152,7 +209,7 @@ func GetUserInfo(context *gin.Context) {
if err == nil { if err == nil {
if oauthToken.Valid() { if oauthToken.Valid() {
user := getDiscordUser(context, oauthToken) user := getDiscordUser(context, oauthToken)
if databasecommands.GetDatabaseUserLoggedIn(GlobalDatabase, oauthTokenJSON) { if databasecommands.GetDatabaseUserLoggedInFromDiscordId(GlobalDatabase, user.Id) {
context.JSON(http.StatusOK, user) context.JSON(http.StatusOK, user)
} else { } else {
context.Redirect(http.StatusTemporaryRedirect, "http://localhost:31337/auth/logout") context.Redirect(http.StatusTemporaryRedirect, "http://localhost:31337/auth/logout")
@ -175,7 +232,6 @@ func GetUserInfo(context *gin.Context) {
func GetIsUserAuthorized(context *gin.Context) { func GetIsUserAuthorized(context *gin.Context) {
oauthTokenJSON, err := context.Cookie("discord-oauthtoken") oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
log.Println(oauthTokenJSON)
if err == nil { if err == nil {
var oauthToken *oauth2.Token var oauthToken *oauth2.Token
err := json.Unmarshal([]byte(oauthTokenJSON), &oauthToken) err := json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
@ -186,7 +242,6 @@ func GetIsUserAuthorized(context *gin.Context) {
"message": true, "message": true,
}) })
context.Set("is-authorized", true) context.Set("is-authorized", true)
log.Println("yessss")
return return
} }
} }
@ -217,4 +272,42 @@ func GetDatabaseGroups(context *gin.Context) {
}) })
} }
func GetDatabaseFunction(context *gin.Context) {
functionName := context.Query("function")
if functionName != "" {
group := databasecommands.GetDatabaseFunction(GlobalDatabase, functionName)
context.JSON(http.StatusOK, group)
} else {
context.JSON(http.StatusBadRequest, gin.H{
"name": "",
})
}
}
func GetDatabaseFunctions(context *gin.Context) {
functions := databasecommands.GetDatabaseFunctions(GlobalDatabase)
context.JSON(http.StatusOK, gin.H{
"functions": functions,
})
}
func GetDatabaseFunctionTag(context *gin.Context) {
functionTagName := context.Query("name")
if functionTagName != "" {
functionTag := databasecommands.GetDatabaseFunctionTag(GlobalDatabase, functionTagName)
context.JSON(http.StatusOK, functionTag)
} else {
context.JSON(http.StatusBadRequest, gin.H{
"name": "",
})
}
}
func GetDatabaseFunctionTags(context *gin.Context) {
functionTags := databasecommands.GetDatabaseFunctionTags(GlobalDatabase)
context.JSON(http.StatusOK, gin.H{
"function_tags": functionTags,
})
}
// Delete Endpoints (delete/) // Delete Endpoints (delete/)

View file

@ -15,11 +15,62 @@ func InitializeDatabase() *gorm.DB {
if err != nil { if err != nil {
log.Fatal("Failed to connect to database.") log.Fatal("Failed to connect to database.")
} }
db.AutoMigrate(&databasemodels.User{}) db.AutoMigrate(
db.AutoMigrate(&databasemodels.Group{}) &databasemodels.User{},
&databasemodels.Group{},
&databasemodels.FunctionTag{},
&databasemodels.ItemTag{},
&databasemodels.Function{},
&databasemodels.FunctionSet{},
&databasemodels.Tier{},
&databasemodels.Role{},
&databasemodels.Person{},
&databasemodels.Item{},
&databasemodels.InventorySlot{},
&databasemodels.Character{},
&databasemodels.Customization{},
&databasemodels.Schematic{},
)
return db return db
} }
// Create Functions
func CreateDatabaseUser(db *gorm.DB, user databasemodels.User) error {
result := db.Create(&user)
if result.Error != nil {
return result.Error
}
return nil
}
func CreateDatabaseGroup(db *gorm.DB, group databasemodels.Group) error {
result := db.Create(&group)
if result.Error != nil {
return result.Error
}
return nil
}
func CreateDatabaseFunction(db *gorm.DB, function databasemodels.Function) error {
log.Println(function)
result := db.Create(&function)
if result.Error != nil {
return result.Error
}
return nil
}
func CreateDatabaseFunctionTag(db *gorm.DB, functionTag databasemodels.FunctionTag) error {
result := db.Create(&functionTag)
if result.Error != nil {
return result.Error
}
return nil
}
// Read Functions
func GetDatabaseUserToken(db *gorm.DB, id string) string { func GetDatabaseUserToken(db *gorm.DB, id string) string {
var dbUser databasemodels.User var dbUser databasemodels.User
result := db.Where("id = ?", id).Select("login_token").Take(&dbUser) result := db.Where("id = ?", id).Select("login_token").Take(&dbUser)
@ -46,38 +97,19 @@ func GetDatabaseUserLoggedIn(db *gorm.DB, oauthTokenJSON string) bool {
if errors.Is(result.Error, gorm.ErrRecordNotFound) { if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return false return false
} else { } else {
log.Println(queryUser)
return queryUser.LoggedIn return queryUser.LoggedIn
} }
} }
func UpdateDatabaseUser(db *gorm.DB, user databasemodels.User) error { func GetDatabaseUserLoggedInFromDiscordId(db *gorm.DB, discordId string) bool {
result := db.Save(&user) var queryUser databasemodels.User
if result.Error != nil { var result *gorm.DB
return result.Error result = db.Where("id = ?", discordId).Take(&queryUser)
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return false
} else {
return queryUser.LoggedIn
} }
return nil
}
func CreateDatabaseUser(db *gorm.DB, user databasemodels.User) error {
result := db.Create(&user)
if result.Error != nil {
return result.Error
}
return nil
}
func LogoutDatabaseUser(db *gorm.DB, oauthToken string) {
db.Model(&databasemodels.User{}).Where("login_token = ?", oauthToken).Update("logged_in", false)
}
func CreateDatabaseGroup(db *gorm.DB, group databasemodels.Group) error {
result := db.Create(&group)
log.Println(group)
if result.Error != nil {
return result.Error
}
return nil
} }
func GetDatabaseGroup(db *gorm.DB, inputGroup string) databasemodels.Group { func GetDatabaseGroup(db *gorm.DB, inputGroup string) databasemodels.Group {
@ -89,11 +121,79 @@ func GetDatabaseGroup(db *gorm.DB, inputGroup string) databasemodels.Group {
return outputGroup return outputGroup
} }
func GetDatabaseGroups(db *gorm.DB) []databasemodels.Group { func GetDatabaseGroups(db *gorm.DB) []string {
var outputGroup []databasemodels.Group var outputGroups []databasemodels.Group
result := db.Find(&outputGroup) var outputGroupsList []string
result := db.Find(&outputGroups)
if result.Error != nil { if result.Error != nil {
return []databasemodels.Group{} return outputGroupsList
} else {
for _, group := range outputGroups {
outputGroupsList = append(outputGroupsList, group.Name)
}
return outputGroupsList
} }
return outputGroup
} }
func GetDatabaseFunction(db *gorm.DB, inputFunction string) databasemodels.Function {
var outputFunction databasemodels.Function
result := db.Model(&databasemodels.Function{}).Where("name = ?", inputFunction).Take(&outputFunction)
if result.Error != nil {
return databasemodels.Function{}
}
return outputFunction
}
func GetDatabaseFunctions(db *gorm.DB) []databasemodels.Function {
var outputFunctions []databasemodels.Function
db.Find(&outputFunctions)
for outputFunctionId, outputFunction := range outputFunctions {
var outputFunctionTags []databasemodels.FunctionTag
db.Model(&outputFunction).Association("Tags").Find(&outputFunctionTags)
var outputFunctionRequirements []databasemodels.Function
db.Model(&outputFunction).Association("Requirements").Find(&outputFunctionRequirements)
outputFunctions[outputFunctionId].Tags = outputFunctionTags
outputFunctions[outputFunctionId].Requirements = outputFunctionRequirements
}
log.Printf("Functions: %v", outputFunctions)
return outputFunctions
}
func GetDatabaseFunctionTag(db *gorm.DB, inputFunctionTag string) databasemodels.FunctionTag {
var outputFunctionTag databasemodels.FunctionTag
result := db.Model(&databasemodels.FunctionTag{}).Where("name = ?", inputFunctionTag).Take(&outputFunctionTag)
if result.Error != nil {
return databasemodels.FunctionTag{}
}
return outputFunctionTag
}
func GetDatabaseFunctionTags(db *gorm.DB) []string {
var outputFunctionTags []databasemodels.FunctionTag
var outputFunctionTagsList []string
result := db.Find(&outputFunctionTags)
if result.Error != nil {
return outputFunctionTagsList
} else {
for _, functionTag := range outputFunctionTags {
outputFunctionTagsList = append(outputFunctionTagsList, functionTag.Name)
}
return outputFunctionTagsList
}
}
// Update Functions
func LogoutDatabaseUser(db *gorm.DB, oauthToken string) {
db.Model(&databasemodels.User{}).Where("login_token = ?", oauthToken).Update("logged_in", false)
}
func UpdateDatabaseUser(db *gorm.DB, user databasemodels.User) error {
result := db.Save(&user)
if result.Error != nil {
return result.Error
}
return nil
}
// Delete Functions

View file

@ -4,19 +4,19 @@ import "gorm.io/gorm"
type User struct { type User struct {
gorm.Model gorm.Model
Id string Id string `json:"id"`
DisplayName string DisplayName string `json:"display_name"`
Username string Username string `json:"user_name"`
Avatar string Avatar string `json:"avatar"`
AvatarDecoration string AvatarDecoration string `json:"avatar_decoration"`
LoginToken string LoginToken string `json:"login_token"`
LoggedIn bool LoggedIn bool `json:"logged_in"`
} }
type Person struct { type Person struct {
gorm.Model gorm.Model
Name string Name string `json:"name"`
Groups []Group // Unique Groups []Group `gorm:"many2many:person_group_associations" json:"groups"` // Unique
} }
type Group struct { type Group struct {
@ -26,82 +26,82 @@ type Group struct {
type Character struct { type Character struct {
gorm.Model gorm.Model
Name string Name string `gorm:"uniqueIndex" json:"name"`
Owners []Person // Unique Owners []Person `gorm:"many2many:character_owner_associations" json:"owners"` // Unique
Roles []Role // Unique Roles []Role `gorm:"many2many:character_role_associations" json:"roles"` // Unique
FunctionSets []FunctionSet FunctionSets []FunctionSet `gorm:"foreignkey:id; references:Name" json:"function_sets"`
Inventory []InventorySlot Inventory []InventorySlot `gorm:"foreignkey:id; references:Name" json:"inventory"`
} }
type Role struct { type Role struct {
gorm.Model gorm.Model
Name string Name string `json:"name"`
Tiers []Tier Tiers []Tier `gorm:"foreignkey:id; references:Name" json:"tiers"`
Visibility []Group // Unique Visibility []Group `gorm:"foreignkey:Name" json:"visibility"` // Unique
} }
type Tier struct { type Tier struct {
gorm.Model gorm.Model
FunctionSets []FunctionSet FunctionSets []FunctionSet `gorm:"foreignkey:id; references:id" json:"function_sets"`
} }
type FunctionSet struct { type FunctionSet struct {
gorm.Model gorm.Model
Functions []Function Functions []Function `gorm:"foreignkey:Name" json:"functions"`
} }
type Function struct { type Function struct {
gorm.Model gorm.Model
Name string Name string `gorm:"primaryKey" gorm:"uniqueIndex" json:"name"`
Tags FunctionTag Tags []FunctionTag `gorm:"many2many:function_tag_associations" json:"tags"`
Requirements []Function Requirements []Function `gorm:"many2many:function_requirement_associations" json:"requirements"`
} }
type FunctionTag struct { type FunctionTag struct {
gorm.Model gorm.Model
Name string Name string `gorm:"primaryKey" gorm:"uniqueIndex" json:"name"`
} }
type InventorySlot struct { type InventorySlot struct {
gorm.Model gorm.Model
Item Item Item Item `gorm:"foreignkey:Name" json:"item"`
Quantity int64 // Positive Quantity int64 `json:"quantity"` // Positive
} }
type Item struct { type Item struct {
gorm.Model gorm.Model
Name string Name string `json:"name"`
Functions []Function Functions []Function `gorm:"foreignkey:Name" json:"functions"`
FlavorText string FlavorText string `json:"flavor_text"`
RulesDescription string RulesDescription string `json:"rules_description"`
PhysrepRequirements string PhysrepRequirements string `json:"physrep_requirements"`
Tags []ItemTag // Unique Tags []ItemTag `gorm:"foreignkey:Name" json:"tags"` // Unique
Customizations []Customization Customizations []Customization `gorm:"foreignkey:Name" json:"customizations"`
Visibility []Group // Unique Visibility []Group `gorm:"foreignkey:Name" json:"visibility"` // Unique
} }
type ItemTag struct { type ItemTag struct {
gorm.Model gorm.Model
Naem string Name string `gorm:"primaryKey" json:"name"`
} }
type Customization struct { type Customization struct {
gorm.Model gorm.Model
Name string Name string `json:"name"`
Functions []Function Functions []Function `gorm:"foreignkey:Name" json:"functions"`
FlavorText string FlavorText string `json:"flavor_text"`
RulesDescription string RulesDescription string `json:"rules_description"`
PhysrepRequirements string PhysrepRequirements string `json:"physrep_requirements"`
Tags []ItemTag // Unique Tags []ItemTag `gorm:"foreignkey:Name" json:"tags"` // Unique
Visibility []Group // Unique Visibility []Group `gorm:"foreignkey:Name" json:"visibility"` // Unique
} }
type Schematic struct { type Schematic struct {
gorm.Model gorm.Model
Material []InventorySlot Material []InventorySlot `gorm:"many2many:schematic_material_associations" json:"material"`
Tools []InventorySlot Tools []InventorySlot `gorm:"many2many:schematic_tool_associations" json:"tools"`
Requirements []Function Requirements []Function `gorm:"many2many:schematic_requirement_associations" json:"requirements"`
TimeUnits int64 // Positive TimeUnits int64 `json:"time_units"` // Positive
Result InventorySlot Result InventorySlot `gorm:"many2many:schematic_result_associations" json:"result"`
Visibility []Group // Unique Visibility []Group `gorm:"many2many:schematic_group_associations" json:"visibility"` // Unique
} }