🎨 Refactor basic server structure
These changes refactor the router handling into its own package to keep main.go clean. Also API handlers are here refactored to their corresponding files.
This commit is contained in:
parent
a4748d7619
commit
c51a17993e
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2024 Florian Beisel
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Helloworld godoc
|
||||||
|
//
|
||||||
|
// @Summary Check your authentication
|
||||||
|
// @Schemes
|
||||||
|
// @Description Checks whether the user is successfully authenticated
|
||||||
|
// @ID hello
|
||||||
|
// @Tags Authentication
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Security Bearer
|
||||||
|
// @Success 200 {string} Helloworld
|
||||||
|
// @Router /hello [get]
|
||||||
|
func Helloworld(g *gin.Context) {
|
||||||
|
g.JSON(http.StatusOK, "helloworld")
|
||||||
|
}
|
161
api/handlers.go
161
api/handlers.go
|
@ -1,161 +0,0 @@
|
||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"git.beisel.it/florian/hostname-service/db"
|
|
||||||
"git.beisel.it/florian/hostname-service/models"
|
|
||||||
"git.beisel.it/florian/hostname-service/rules"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getHostnameRuleByCategory(category string) (rules.HostnameRule, error) {
|
|
||||||
switch category {
|
|
||||||
case "notebook":
|
|
||||||
return &rules.NotebookRule{}, nil
|
|
||||||
// ... other categories
|
|
||||||
default:
|
|
||||||
return nil, errors.New("unknown category")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateOrUpdateHostname handles the hostname generation
|
|
||||||
func CreateOrUpdateHostname(c *gin.Context, isUpdate bool) {
|
|
||||||
category := c.Param("category")
|
|
||||||
var oldHostname string
|
|
||||||
if isUpdate {
|
|
||||||
oldHostname = c.Param("oldhostname")
|
|
||||||
}
|
|
||||||
|
|
||||||
var params map[string]interface{}
|
|
||||||
if err := c.BindJSON(¶ms); err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid parameters"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rule, err := getHostnameRuleByCategory(category)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
hostname, paramsJSON, err := rule.Generate(params)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if isUpdate {
|
|
||||||
err = rule.Update(category, oldHostname, hostname, paramsJSON)
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "does not exist") {
|
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = rule.Insert(category, hostname, paramsJSON)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Error processing hostname"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
response := models.SimpleHostnameResponse{Hostname: hostname}
|
|
||||||
c.JSON(http.StatusOK, response)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Delete a hostname from the database
|
|
||||||
// @Description List all details for a given category
|
|
||||||
// @ID delete-hostnames-by-category-and-name
|
|
||||||
// @Produce json
|
|
||||||
// @Param category path string true "Category of the hostname"
|
|
||||||
// @Param hostname path string true "Hostname to delete"
|
|
||||||
// @Success 200 {object} models.SimpleHostnameResponse "Hostname"
|
|
||||||
// @Security Bearer
|
|
||||||
// @Tags Manipulate existing Hostnames
|
|
||||||
// @Router /{category}/{hostname} [delete]
|
|
||||||
func DeleteHostname(c *gin.Context) {
|
|
||||||
category := c.Param("category")
|
|
||||||
hostname := c.Param("hostname")
|
|
||||||
|
|
||||||
err := db.DeleteHostname(category, hostname)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
response := models.SimpleHostnameResponse{Hostname: hostname}
|
|
||||||
c.JSON(http.StatusOK, response)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Return a list of hosts and their details filtered by category
|
|
||||||
// @Description List all details for a given category
|
|
||||||
// @ID list-hostnames-by-category
|
|
||||||
// @Produce json
|
|
||||||
// @Param category path string true "Category of the hostname"
|
|
||||||
// @Success 200 {array} models.Hostname "An array of responses"
|
|
||||||
// @Security Bearer
|
|
||||||
// @Tags Querying Hostnames
|
|
||||||
// @Router /{category} [get]
|
|
||||||
func ListHostnamesByCategory(c *gin.Context) {
|
|
||||||
category := c.Param("category")
|
|
||||||
|
|
||||||
hostnames, err := db.GetHostnamesByCategory(category)
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "no rows found") {
|
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": "hostname not found"})
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Error retrieving hostnames"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, hostnames)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Return a single hostname by Category and Name
|
|
||||||
// @Description Return details for a single hostname identified by its category
|
|
||||||
// @ID get-hostname-by-category-and-name
|
|
||||||
// @Produce json
|
|
||||||
// @Param category path string true "Category of the hostname"
|
|
||||||
// @Param hostname path string true "Category of the hostname"
|
|
||||||
// @Success 200 {object} models.Hostname "A single response object"
|
|
||||||
// @Security Bearer
|
|
||||||
// @Tags Querying Hostnames
|
|
||||||
// @Router /{category}/{hostname} [get]
|
|
||||||
func GetHostnameByCategoryAndName(c *gin.Context) {
|
|
||||||
category := c.Param("category")
|
|
||||||
hostname := c.Param("hostname")
|
|
||||||
|
|
||||||
hostinfo, err := db.GetHostnameByCategoryAndName(category, hostname)
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "no rows found") {
|
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": "hostname not found"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Error retrieving hostname"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, hostinfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helloworld godoc
|
|
||||||
//
|
|
||||||
// @Summary Check your authentication
|
|
||||||
// @Schemes
|
|
||||||
// @Description Checks whether the user is successfully authenticated
|
|
||||||
// @ID hello
|
|
||||||
// @Tags Authentication
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Security Bearer
|
|
||||||
// @Success 200 {string} Helloworld
|
|
||||||
// @Router /hello [get]
|
|
||||||
func Helloworld(g *gin.Context) {
|
|
||||||
g.JSON(http.StatusOK, "helloworld")
|
|
||||||
}
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
// Copyright 2024 Florian Beisel
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.beisel.it/florian/hostname-service/db"
|
||||||
|
"git.beisel.it/florian/hostname-service/models"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @Summary Return a single hostname by Category and Name
|
||||||
|
// @Description Return details for a single hostname identified by its category
|
||||||
|
// @ID get-hostname-by-category-and-name
|
||||||
|
// @Produce json
|
||||||
|
// @Param category path string true "Category of the hostname"
|
||||||
|
// @Param hostname path string true "Category of the hostname"
|
||||||
|
// @Success 200 {object} models.Hostname "A single response object"
|
||||||
|
// @Security Bearer
|
||||||
|
// @Tags Querying Hostnames
|
||||||
|
// @Router /{category}/{hostname} [get]
|
||||||
|
func GetHostnameByCategoryAndName(c *gin.Context) {
|
||||||
|
category := c.Param("category")
|
||||||
|
hostname := c.Param("hostname")
|
||||||
|
|
||||||
|
hostinfo, err := db.GetHostnameByCategoryAndName(category, hostname)
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "no rows found") {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"error": "hostname not found"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Error retrieving hostname"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, hostinfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Return a list of hosts and their details filtered by category
|
||||||
|
// @Description List all details for a given category
|
||||||
|
// @ID list-hostnames-by-category
|
||||||
|
// @Produce json
|
||||||
|
// @Param category path string true "Category of the hostname"
|
||||||
|
// @Success 200 {array} models.Hostname "An array of responses"
|
||||||
|
// @Security Bearer
|
||||||
|
// @Tags Querying Hostnames
|
||||||
|
// @Router /{category} [get]
|
||||||
|
func ListHostnamesByCategory(c *gin.Context) {
|
||||||
|
category := c.Param("category")
|
||||||
|
|
||||||
|
hostnames, err := db.GetHostnamesByCategory(category)
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "no rows found") {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"error": "hostname not found"})
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Error retrieving hostnames"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, hostnames)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Delete a hostname from the database
|
||||||
|
// @Description List all details for a given category
|
||||||
|
// @ID delete-hostnames-by-category-and-name
|
||||||
|
// @Produce json
|
||||||
|
// @Param category path string true "Category of the hostname"
|
||||||
|
// @Param hostname path string true "Hostname to delete"
|
||||||
|
// @Success 200 {object} models.SimpleHostnameResponse "Hostname"
|
||||||
|
// @Security Bearer
|
||||||
|
// @Tags Manipulate existing Hostnames
|
||||||
|
// @Router /{category}/{hostname} [delete]
|
||||||
|
func DeleteHostname(c *gin.Context) {
|
||||||
|
category := c.Param("category")
|
||||||
|
hostname := c.Param("hostname")
|
||||||
|
|
||||||
|
err := db.DeleteHostname(category, hostname)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response := models.SimpleHostnameResponse{Hostname: hostname}
|
||||||
|
c.JSON(http.StatusOK, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateOrUpdateHostname(c *gin.Context, isUpdate bool) {
|
||||||
|
category := c.Param("category")
|
||||||
|
var oldHostname string
|
||||||
|
if isUpdate {
|
||||||
|
oldHostname = c.Param("oldhostname")
|
||||||
|
}
|
||||||
|
|
||||||
|
var params map[string]interface{}
|
||||||
|
if err := c.BindJSON(¶ms); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid parameters"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rule, err := getHostnameRuleByCategory(category)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var hostname string
|
||||||
|
if isUpdate {
|
||||||
|
hostname, err = rule.Update(category, oldHostname, params)
|
||||||
|
} else {
|
||||||
|
hostname, err = rule.Insert(category, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if isUpdate && strings.Contains(err.Error(), "does not exist") {
|
||||||
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||||||
|
} else {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response := models.SimpleHostnameResponse{Hostname: hostname}
|
||||||
|
c.JSON(http.StatusOK, response)
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Copyright 2024 Florian Beisel
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"git.beisel.it/florian/hostname-service/rules"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListAvailableRules(c *gin.Context) {
|
||||||
|
descriptions := make(map[string]string)
|
||||||
|
for category, descriptor := range rules.RulesRegistry {
|
||||||
|
descriptions[category] = descriptor.Description
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, descriptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getHostnameRuleByCategory(category string) (rules.HostnameRule, error) {
|
||||||
|
if descriptor, exists := rules.RulesRegistry[category]; exists {
|
||||||
|
return descriptor.Factory(), nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("unknown category")
|
||||||
|
}
|
51
main.go
51
main.go
|
@ -19,15 +19,9 @@ package main
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"git.beisel.it/florian/hostname-service/api"
|
|
||||||
"git.beisel.it/florian/hostname-service/auth"
|
|
||||||
"git.beisel.it/florian/hostname-service/config"
|
"git.beisel.it/florian/hostname-service/config"
|
||||||
"git.beisel.it/florian/hostname-service/db"
|
"git.beisel.it/florian/hostname-service/db"
|
||||||
"git.beisel.it/florian/hostname-service/docs"
|
"git.beisel.it/florian/hostname-service/router"
|
||||||
"git.beisel.it/florian/hostname-service/middleware"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
swaggerFiles "github.com/swaggo/files"
|
|
||||||
ginSwagger "github.com/swaggo/gin-swagger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @title Hostname Service API
|
// @title Hostname Service API
|
||||||
|
@ -54,48 +48,9 @@ func main() {
|
||||||
log.Fatalf("Failed to load configuration: %v", err)
|
log.Fatalf("Failed to load configuration: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gin.SetMode(gin.DebugMode)
|
|
||||||
|
|
||||||
db.Init(config.GlobalConfig.DatabaseFile)
|
db.Init(config.GlobalConfig.DatabaseFile)
|
||||||
|
|
||||||
router := gin.Default()
|
router := router.New()
|
||||||
|
|
||||||
docs.SwaggerInfo.Host = "localhost:8080"
|
|
||||||
docs.SwaggerInfo.BasePath = "/api/v1"
|
|
||||||
|
|
||||||
v1 := router.Group("/api/v1")
|
|
||||||
{
|
|
||||||
// public routes
|
|
||||||
v1.POST("/login", auth.LoginHandler)
|
|
||||||
|
|
||||||
// Protected Routes
|
|
||||||
authenticated := v1.Group("/").Use(middleware.Authenticate())
|
|
||||||
{
|
|
||||||
authenticated.GET("/hello", api.Helloworld)
|
|
||||||
|
|
||||||
// Create Host
|
|
||||||
authenticated.POST("/:category", func(c *gin.Context) {
|
|
||||||
api.CreateOrUpdateHostname(c, false)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Get Host Details
|
|
||||||
authenticated.GET("/:category/:hostname", api.GetHostnameByCategoryAndName)
|
|
||||||
|
|
||||||
// Update Host
|
|
||||||
authenticated.PUT("/:category/:oldhostname", func(c *gin.Context) {
|
|
||||||
api.CreateOrUpdateHostname(c, true)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Delete Host
|
|
||||||
authenticated.DELETE("/:category/:hostname", api.DeleteHostname)
|
|
||||||
|
|
||||||
// List Hostnames
|
|
||||||
authenticated.GET("/:category", api.ListHostnamesByCategory)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swagger endpoint
|
|
||||||
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
|
||||||
|
|
||||||
router.Run(":8080")
|
router.Run(":8080")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
// Copyright 2024 Florian Beisel
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.beisel.it/florian/hostname-service/api"
|
||||||
|
"git.beisel.it/florian/hostname-service/auth"
|
||||||
|
"git.beisel.it/florian/hostname-service/docs"
|
||||||
|
"git.beisel.it/florian/hostname-service/middleware"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
swaggerFiles "github.com/swaggo/files"
|
||||||
|
ginSwagger "github.com/swaggo/gin-swagger"
|
||||||
|
// ... other necessary imports ...
|
||||||
|
)
|
||||||
|
|
||||||
|
func New() *gin.Engine {
|
||||||
|
gin.SetMode(gin.DebugMode)
|
||||||
|
router := gin.Default()
|
||||||
|
|
||||||
|
docs.SwaggerInfo.Host = "localhost:8080"
|
||||||
|
docs.SwaggerInfo.BasePath = "/api/v1"
|
||||||
|
|
||||||
|
v1 := router.Group("/api/v1")
|
||||||
|
{
|
||||||
|
// public routes
|
||||||
|
v1.POST("/login", auth.LoginHandler)
|
||||||
|
|
||||||
|
// Protected Routes
|
||||||
|
authenticated := v1.Group("/").Use(middleware.Authenticate())
|
||||||
|
{
|
||||||
|
authenticated.GET("/hello", api.Helloworld)
|
||||||
|
|
||||||
|
// Create Host
|
||||||
|
authenticated.POST("/:category", func(c *gin.Context) {
|
||||||
|
api.CreateOrUpdateHostname(c, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Get Host Details
|
||||||
|
authenticated.GET("/:category/:hostname", api.GetHostnameByCategoryAndName)
|
||||||
|
|
||||||
|
// Update Host
|
||||||
|
authenticated.PUT("/:category/:oldhostname", func(c *gin.Context) {
|
||||||
|
api.CreateOrUpdateHostname(c, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Delete Host
|
||||||
|
authenticated.DELETE("/:category/:hostname", api.DeleteHostname)
|
||||||
|
|
||||||
|
// List Hostnames
|
||||||
|
authenticated.GET("/:category", api.ListHostnamesByCategory)
|
||||||
|
|
||||||
|
// List available Rules
|
||||||
|
authenticated.GET("/api/rules", api.ListAvailableRules)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swagger endpoint
|
||||||
|
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
Loading…
Reference in New Issue