Standardizing the API endpoints.
This commit is contained in:
		
							parent
							
								
									326fbe79a3
								
							
						
					
					
						commit
						10db069eea
					
				
					 3 changed files with 166 additions and 66 deletions
				
			
		| 
						 | 
				
			
			@ -14,10 +14,15 @@ func main() {
 | 
			
		|||
	api.GlobalConfig = configserver.ParseConfig("../config.toml")
 | 
			
		||||
	api.GlobalOAuth = authdiscord.CreateDiscordOAuthConfig(api.GlobalConfig)
 | 
			
		||||
	app := gin.Default()
 | 
			
		||||
	app.GET("/login", api.LoginRedirect)
 | 
			
		||||
	// Authentication Workflow
 | 
			
		||||
	app.GET("/auth/callback", api.AuthCallback)
 | 
			
		||||
	app.GET("/logout", api.LogoutRedirect)
 | 
			
		||||
	app.GET("/dashboard", api.GetDashboardInfo)
 | 
			
		||||
	app.GET("/authorized", api.IsUserAuthorized)
 | 
			
		||||
	app.GET("/auth/login", api.AuthLoginRedirect)
 | 
			
		||||
	app.GET("/auth/logout", api.AuthLogoutRedirect)
 | 
			
		||||
	// Create & Update
 | 
			
		||||
	app.POST("/post/user/update", api.CreateOrUpdateUser)
 | 
			
		||||
	// Read
 | 
			
		||||
	app.GET("/get/user/info", api.GetUserInfo)
 | 
			
		||||
	app.GET("/get/user/authorized", api.GetIsUserAuthorized)
 | 
			
		||||
	// Delete
 | 
			
		||||
	app.Run(":31337")
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,20 +21,7 @@ var GlobalDatabase *gorm.DB
 | 
			
		|||
var GlobalConfig configserver.AppConfig
 | 
			
		||||
var GlobalOAuth *oauth2.Config
 | 
			
		||||
 | 
			
		||||
func LoginRedirect(context *gin.Context) {
 | 
			
		||||
	context.Redirect(302, GlobalOAuth.AuthCodeURL(context.GetString("state")))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func LogoutRedirect(context *gin.Context) {
 | 
			
		||||
	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)
 | 
			
		||||
	}
 | 
			
		||||
	context.Redirect(http.StatusTemporaryRedirect, "http://localhost:15995/")
 | 
			
		||||
}
 | 
			
		||||
// Authentication Workflow
 | 
			
		||||
 | 
			
		||||
func AuthCallback(context *gin.Context) {
 | 
			
		||||
	oauthState := randomstring.CookieFriendlyString(32)
 | 
			
		||||
| 
						 | 
				
			
			@ -46,12 +33,73 @@ func AuthCallback(context *gin.Context) {
 | 
			
		|||
	}
 | 
			
		||||
	oauthTokenJSON, _ := json.Marshal(oauthToken)
 | 
			
		||||
	context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false)
 | 
			
		||||
	user := GetDiscordUser(context, oauthToken)
 | 
			
		||||
	CreateOrUpdateUser(context, oauthToken, user)
 | 
			
		||||
	context.Set("discord-oauthtoken", string(oauthTokenJSON))
 | 
			
		||||
	CreateOrUpdateUser(context)
 | 
			
		||||
	context.Redirect(http.StatusTemporaryRedirect, "http://localhost:15995/dashboard")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetDiscordUser(context *gin.Context, oauthToken *oauth2.Token) authdiscord.DiscordUser {
 | 
			
		||||
func AuthLoginRedirect(context *gin.Context) {
 | 
			
		||||
	context.Redirect(302, GlobalOAuth.AuthCodeURL(context.GetString("state")))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func AuthLogoutRedirect(context *gin.Context) {
 | 
			
		||||
	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)
 | 
			
		||||
	}
 | 
			
		||||
	context.Redirect(http.StatusTemporaryRedirect, "http://localhost:15995/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create & Update Endpoints (post/, put/, patch)
 | 
			
		||||
 | 
			
		||||
func CreateOrUpdateUser(context *gin.Context) {
 | 
			
		||||
	oauthTokenJSON, err := context.Cookie("discord-oauthtoken")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		oauthTokenJSON = context.GetString("discord-oauthtoken")
 | 
			
		||||
	}
 | 
			
		||||
	var oauthToken *oauth2.Token
 | 
			
		||||
	err = json.Unmarshal([]byte(oauthTokenJSON), &oauthToken)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
		context.AbortWithStatus(http.StatusBadRequest)
 | 
			
		||||
	}
 | 
			
		||||
	currentDiscordUser := getDiscordUser(context, oauthToken)
 | 
			
		||||
	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,
 | 
			
		||||
	}
 | 
			
		||||
	if databasecommands.DatabaseUserExists(GlobalDatabase, currentDiscordUser.Id) {
 | 
			
		||||
		dbOAuthToken := databasecommands.GetDatabaseUserToken(GlobalDatabase, currentDiscordUser.Id)
 | 
			
		||||
		if dbOAuthToken == "" {
 | 
			
		||||
			context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false)
 | 
			
		||||
			err := databasecommands.UpdateDatabaseUser(GlobalDatabase, updatedDatabaseUser)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println(err)
 | 
			
		||||
				context.AbortWithStatus(http.StatusInternalServerError)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			context.SetCookie("discord-oauthtoken", dbOAuthToken, 0, "", GlobalConfig.API.Domain, false, false)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		err := databasecommands.CreateDatabaseUser(GlobalDatabase, updatedDatabaseUser)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println(err)
 | 
			
		||||
			context.Copy().AbortWithStatus(http.StatusInternalServerError)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Read Endpoints (get/)
 | 
			
		||||
 | 
			
		||||
func getDiscordUser(context *gin.Context, oauthToken *oauth2.Token) authdiscord.DiscordUser {
 | 
			
		||||
	response, err := GlobalOAuth.Client(context.Request.Context(), oauthToken).Get("https://discord.com/api/users/@me")
 | 
			
		||||
	if err != nil || response.StatusCode != 200 {
 | 
			
		||||
		responseMessage := ""
 | 
			
		||||
| 
						 | 
				
			
			@ -76,72 +124,43 @@ func GetDiscordUser(context *gin.Context, oauthToken *oauth2.Token) authdiscord.
 | 
			
		|||
	return user
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CreateOrUpdateUser(context *gin.Context, oauthToken *oauth2.Token, user authdiscord.DiscordUser) {
 | 
			
		||||
	oauthTokenJSON, err := json.Marshal(oauthToken)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
	}
 | 
			
		||||
	dbUser := databasemodels.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 databasecommands.DatabaseUserExists(GlobalDatabase, user.Id) {
 | 
			
		||||
		dbOAuthToken := databasecommands.GetDatabaseUserToken(GlobalDatabase, user.Id)
 | 
			
		||||
		if dbOAuthToken == "" {
 | 
			
		||||
			context.SetCookie("discord-oauthtoken", string(oauthTokenJSON), 0, "", GlobalConfig.API.Domain, false, false)
 | 
			
		||||
			err := databasecommands.UpdateDatabaseUser(GlobalDatabase, dbUser)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Println(err)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			context.SetCookie("discord-oauthtoken", dbOAuthToken, 0, "", GlobalConfig.API.Domain, false, false)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		err := databasecommands.CreateDatabaseUser(GlobalDatabase, dbUser)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println(err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetDashboardInfo(context *gin.Context) {
 | 
			
		||||
func GetUserInfo(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() {
 | 
			
		||||
				user := GetDiscordUser(context, oauthToken)
 | 
			
		||||
				user := getDiscordUser(context, oauthToken)
 | 
			
		||||
				if databasecommands.DatabaseUserLoggedIn(GlobalDatabase, user.Id) {
 | 
			
		||||
					context.JSON(http.StatusOK, user)
 | 
			
		||||
					return
 | 
			
		||||
				} else {
 | 
			
		||||
					context.Redirect(http.StatusTemporaryRedirect, "http://localhost:31337/logout")
 | 
			
		||||
					context.Redirect(http.StatusTemporaryRedirect, "http://localhost:31337/auth/logout")
 | 
			
		||||
				}
 | 
			
		||||
				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, "http://localhost:15995/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsUserAuthorized(context *gin.Context) {
 | 
			
		||||
func GetIsUserAuthorized(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() {
 | 
			
		||||
				user := GetDiscordUser(context, oauthToken)
 | 
			
		||||
				user := getDiscordUser(context, oauthToken)
 | 
			
		||||
				if databasecommands.DatabaseUserLoggedIn(GlobalDatabase, user.Id) {
 | 
			
		||||
					context.JSON(http.StatusOK, gin.H{
 | 
			
		||||
						"message": true,
 | 
			
		||||
| 
						 | 
				
			
			@ -152,16 +171,12 @@ func IsUserAuthorized(context *gin.Context) {
 | 
			
		|||
					})
 | 
			
		||||
				}
 | 
			
		||||
				return
 | 
			
		||||
			} else {
 | 
			
		||||
				log.Println(err)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			log.Println(err)
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Println(err)
 | 
			
		||||
	}
 | 
			
		||||
	context.JSON(http.StatusUnauthorized, gin.H{
 | 
			
		||||
		"message": false,
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete Endpoints (delete/)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,3 +12,83 @@ type User struct {
 | 
			
		|||
	LoginToken       string
 | 
			
		||||
	LoggedIn         bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Person struct {
 | 
			
		||||
	Name   string
 | 
			
		||||
	Groups []Group // Unique
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Group struct {
 | 
			
		||||
	Name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Character struct {
 | 
			
		||||
	Name         string
 | 
			
		||||
	Owners       []Person // Unique
 | 
			
		||||
	Roles        []Role   // Unique
 | 
			
		||||
	FunctionSets []FunctionSet
 | 
			
		||||
	Inventory    []InventorySlot
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Role struct {
 | 
			
		||||
	Name       string
 | 
			
		||||
	Tiers      []Tier
 | 
			
		||||
	Visibility []Group // Unique
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Tier struct {
 | 
			
		||||
	FunctionSets []FunctionSet
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FunctionSet struct {
 | 
			
		||||
	Functions []Function
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Function struct {
 | 
			
		||||
	Name         string
 | 
			
		||||
	Tags         FunctionTag
 | 
			
		||||
	Requirements []Function
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FunctionTag struct {
 | 
			
		||||
	Name string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type InventorySlot struct {
 | 
			
		||||
	Item     Item
 | 
			
		||||
	Quantity int64 // Positive
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Item struct {
 | 
			
		||||
	Name                string
 | 
			
		||||
	Functions           []Function
 | 
			
		||||
	FlavorText          string
 | 
			
		||||
	RulesDescription    string
 | 
			
		||||
	PhysrepRequirements string
 | 
			
		||||
	Tags                []ItemTag // Unique
 | 
			
		||||
	Customizations      []Customization
 | 
			
		||||
	Visibility          []Group // Unique
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ItemTag struct {
 | 
			
		||||
	Naem string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Customization struct {
 | 
			
		||||
	Name                string
 | 
			
		||||
	Functions           []Function
 | 
			
		||||
	FlavorText          string
 | 
			
		||||
	RulesDescription    string
 | 
			
		||||
	PhysrepRequirements string
 | 
			
		||||
	Tags                []ItemTag // Unique
 | 
			
		||||
	Visibility          []Group   // Unique
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Schematic struct {
 | 
			
		||||
	Material     []InventorySlot
 | 
			
		||||
	Tools        []InventorySlot
 | 
			
		||||
	Requirements []Function
 | 
			
		||||
	TimeUnits    int64 // Positive
 | 
			
		||||
	Result       InventorySlot
 | 
			
		||||
	Visibility   []Group // Unique
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue