From 57722116d6a1eb714d2d957c2d303964f91cda6f Mon Sep 17 00:00:00 2001 From: Florian Beisel Date: Wed, 24 Jan 2024 11:03:08 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20rules=20routes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/rule_handlers.go | 49 ++++++++++++++++++++++++++++++ docs/docs.go | 71 ++++++++++++++++++++++++++++---------------- docs/swagger.json | 71 ++++++++++++++++++++++++++++---------------- docs/swagger.yaml | 47 ++++++++++++++++++----------- router/router.go | 12 +++++++- 5 files changed, 180 insertions(+), 70 deletions(-) diff --git a/api/rule_handlers.go b/api/rule_handlers.go index d7b9d92..10de347 100644 --- a/api/rule_handlers.go +++ b/api/rule_handlers.go @@ -17,11 +17,19 @@ package api import ( "errors" "net/http" + "reflect" "git.beisel.it/florian/hostname-service/rules" "github.com/gin-gonic/gin" ) +// @Summary Returns a list of available rules +// @Description Return a list of names of Rules which are known in the RulesRegistry +// @ID get-rules +// @Produce json +// @Security Bearer +// @Tags Querying Rules +// @Router /rules [get] func ListAvailableRules(c *gin.Context) { descriptions := make(map[string]string) for category, descriptor := range rules.RulesRegistry { @@ -36,3 +44,44 @@ func getHostnameRuleByCategory(category string) (rules.HostnameRule, error) { } return nil, errors.New("unknown category") } + +// @Summary Returns details about a rule +// @Description Returns two obea an Input Object and an Output Object +// @Description describing the Rules stored values and required parameters +// @ID get-rule-details +// @Produce json +// @Success 200 {object} models.SimpleHostnameResponse "Hostname" +// @Security Bearer +// @Tags Querying Rules +// @Router /rules/:rule [get] +func GetRuleStruct(c *gin.Context) { + ruleName := c.Param("rule") + + descriptor, exists := rules.RulesRegistry[ruleName] + if !exists { + c.JSON(http.StatusNotFound, gin.H{"error": "Rule not found"}) + return + } + + // Create instances of the rule and its input struct + ruleInstance := descriptor.Factory() + inputInstance := reflect.New(reflect.TypeOf(ruleInstance).Elem()).Interface() + + // Serialize instances to JSON + ruleJSON, err := rules.StructToJSON(ruleInstance) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Error serializing rule struct"}) + return + } + + inputJSON, err := rules.StructToJSON(inputInstance) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Error serializing input struct"}) + return + } + + c.JSON(http.StatusOK, gin.H{ + "input": inputJSON, + "output": ruleJSON, + }) +} diff --git a/docs/docs.go b/docs/docs.go index 96a8763..a9eff52 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -101,32 +101,6 @@ const docTemplate = `{ } } }, - "/api/rules": { - "get": { - "description": "Get a list of all available hostname generation rules.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Rules" - ], - "summary": "List Available Rules", - "responses": { - "200": { - "description": "List of available rules with descriptions", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, "/api/server": { "put": { "security": [ @@ -286,6 +260,51 @@ const docTemplate = `{ } } }, + "/rules": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Return a list of names of Rules which are known in the RulesRegistry", + "produces": [ + "application/json" + ], + "tags": [ + "Querying Rules" + ], + "summary": "Returns a list of available rules", + "operationId": "get-rules", + "responses": {} + } + }, + "/rules/:rule": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Returns two obea an Input Object and an Output Object\ndescribing the Rules stored values and required parameters", + "produces": [ + "application/json" + ], + "tags": [ + "Querying Rules" + ], + "summary": "Returns details about a rule", + "operationId": "get-rule-details", + "responses": { + "200": { + "description": "Hostname", + "schema": { + "$ref": "#/definitions/models.SimpleHostnameResponse" + } + } + } + } + }, "/{category}": { "get": { "security": [ diff --git a/docs/swagger.json b/docs/swagger.json index 832d121..d845660 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -95,32 +95,6 @@ } } }, - "/api/rules": { - "get": { - "description": "Get a list of all available hostname generation rules.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Rules" - ], - "summary": "List Available Rules", - "responses": { - "200": { - "description": "List of available rules with descriptions", - "schema": { - "type": "object", - "additionalProperties": { - "type": "string" - } - } - } - } - } - }, "/api/server": { "put": { "security": [ @@ -280,6 +254,51 @@ } } }, + "/rules": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Return a list of names of Rules which are known in the RulesRegistry", + "produces": [ + "application/json" + ], + "tags": [ + "Querying Rules" + ], + "summary": "Returns a list of available rules", + "operationId": "get-rules", + "responses": {} + } + }, + "/rules/:rule": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Returns two obea an Input Object and an Output Object\ndescribing the Rules stored values and required parameters", + "produces": [ + "application/json" + ], + "tags": [ + "Querying Rules" + ], + "summary": "Returns details about a rule", + "operationId": "get-rule-details", + "responses": { + "200": { + "description": "Hostname", + "schema": { + "$ref": "#/definitions/models.SimpleHostnameResponse" + } + } + } + } + }, "/{category}": { "get": { "security": [ diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 2639f25..f4d22bf 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -212,23 +212,6 @@ paths: summary: Update hostname for category "notebook" tags: - Manipulate existing Hostnames - /api/rules: - get: - consumes: - - application/json - description: Get a list of all available hostname generation rules. - produces: - - application/json - responses: - "200": - description: List of available rules with descriptions - schema: - additionalProperties: - type: string - type: object - summary: List Available Rules - tags: - - Rules /api/server: post: consumes: @@ -330,6 +313,36 @@ paths: summary: User login tags: - Authentication + /rules: + get: + description: Return a list of names of Rules which are known in the RulesRegistry + operationId: get-rules + produces: + - application/json + responses: {} + security: + - Bearer: [] + summary: Returns a list of available rules + tags: + - Querying Rules + /rules/:rule: + get: + description: |- + Returns two obea an Input Object and an Output Object + describing the Rules stored values and required parameters + operationId: get-rule-details + produces: + - application/json + responses: + "200": + description: Hostname + schema: + $ref: '#/definitions/models.SimpleHostnameResponse' + security: + - Bearer: [] + summary: Returns details about a rule + tags: + - Querying Rules securityDefinitions: Bearer: description: Type "Bearer" followed by a space and JWT token. diff --git a/router/router.go b/router/router.go index 9532c97..1942e8f 100644 --- a/router/router.go +++ b/router/router.go @@ -19,6 +19,7 @@ import ( "git.beisel.it/florian/hostname-service/auth" "git.beisel.it/florian/hostname-service/docs" "git.beisel.it/florian/hostname-service/middleware" + "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" @@ -27,7 +28,14 @@ import ( func New() *gin.Engine { gin.SetMode(gin.DebugMode) + router := gin.Default() + // // Configure CORS + config := cors.DefaultConfig() + config.AllowOrigins = []string{"http://localhost:3000", "http://localhost:8080", "*"} // Set to your frontend's URL + config.AllowMethods = []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"} + config.AllowHeaders = []string{"Origin", "Content-Type", "Authorization"} + router.Use(cors.New(config)) docs.SwaggerInfo.Host = "localhost:8080" docs.SwaggerInfo.BasePath = "/api/v1" @@ -36,6 +44,7 @@ func New() *gin.Engine { { // public routes v1.POST("/login", auth.LoginHandler) + v1.GET("/login", api.Helloworld) // Protected Routes authenticated := v1.Group("/").Use(middleware.Authenticate()) @@ -62,7 +71,8 @@ func New() *gin.Engine { authenticated.GET("/:category", api.ListHostnamesByCategory) // List available Rules - authenticated.GET("/api/rules", api.ListAvailableRules) + authenticated.GET("/rules", api.ListAvailableRules) + authenticated.GET("/rules/:rule", api.GetRuleStruct) } }