refactor!: Use gin router instead chi router
- Removed chi dependencies - Updated router registration logic
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.ostiwe.com/ostiwe-com/status/dto"
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/auth"
|
||||
httpApp "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||
"github.com/go-andiamo/chioas"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
authModule auth.Module
|
||||
}
|
||||
|
||||
func (*Controller) New() controller.Controller {
|
||||
return &Controller{
|
||||
authModule: auth.New(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) plainLogin(w http.ResponseWriter, r *http.Request) {
|
||||
var payload dto.LoginRequest
|
||||
|
||||
if err := render.Bind(r, &payload); err != nil {
|
||||
sendErr := httpApp.NewResponseErrBuilder().WithStatusCode(http.StatusBadRequest).WithMessage(err.Error()).Send(w, r)
|
||||
if sendErr != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
jwtString, err := c.authModule.Proceed(r.Context(), payload.Login, payload.Password)
|
||||
if err != nil {
|
||||
sendErr := httpApp.NewResponseErrBuilder().WithStatusCode(http.StatusBadRequest).WithMessage(err.Error()).Send(w, r)
|
||||
if sendErr != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
response := dto.LoginResponse{
|
||||
AccessToken: *jwtString,
|
||||
}
|
||||
|
||||
render.JSON(w, r, response)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
func (c *Controller) Group(r chi.Router) {
|
||||
r.Post("/auth/plain", c.plainLogin)
|
||||
}
|
||||
|
||||
func (c *Controller) Documentate() (*chioas.Paths, *chioas.Components) {
|
||||
return nil, nil
|
||||
}
|
||||
62
router/controller/auth/plain.go
Normal file
62
router/controller/auth/plain.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.ostiwe.com/ostiwe-com/status/dto"
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/auth"
|
||||
httpApp "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type PlainAuthController struct {
|
||||
authModule auth.Module
|
||||
}
|
||||
|
||||
func (c *PlainAuthController) Handler() gin.HandlerFunc {
|
||||
return func(ginCtx *gin.Context) {
|
||||
var payload dto.LoginRequest
|
||||
|
||||
if err := ginCtx.ShouldBindJSON(&payload); err != nil {
|
||||
sendErr := httpApp.NewResponseErrBuilder().WithStatusCode(http.StatusBadRequest).WithMessage(err.Error()).Send(ginCtx)
|
||||
if sendErr != nil {
|
||||
ginCtx.Writer.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
jwtString, err := c.authModule.Proceed(ginCtx.Request.Context(), payload.Login, payload.Password)
|
||||
if err != nil {
|
||||
sendErr := httpApp.NewResponseErrBuilder().WithStatusCode(http.StatusBadRequest).WithMessage(err.Error()).Send(ginCtx)
|
||||
if sendErr != nil {
|
||||
ginCtx.Writer.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
response := dto.LoginResponse{
|
||||
AccessToken: *jwtString,
|
||||
}
|
||||
|
||||
ginCtx.JSON(http.StatusOK, response)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *PlainAuthController) Method() string {
|
||||
return http.MethodPost
|
||||
}
|
||||
|
||||
func (c *PlainAuthController) Path() string {
|
||||
return "/api/v1/auth"
|
||||
}
|
||||
|
||||
func (*PlainAuthController) New() controller.Controller {
|
||||
return &PlainAuthController{
|
||||
authModule: auth.New(),
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,23 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-andiamo/chioas"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
// SecuredController - means, controller has middlewares
|
||||
// Maybe should rename it later
|
||||
type SecuredController interface {
|
||||
Middlewares() []gin.HandlerFunc
|
||||
}
|
||||
|
||||
type DocumentateController interface {
|
||||
Documentate() (*chioas.Paths, *chioas.Components)
|
||||
}
|
||||
|
||||
type Controller interface {
|
||||
New() Controller
|
||||
Group(r chi.Router)
|
||||
Documentate() (*chioas.Paths, *chioas.Components)
|
||||
Handler() gin.HandlerFunc
|
||||
Method() string
|
||||
Path() string
|
||||
}
|
||||
|
||||
@@ -5,27 +5,32 @@ import (
|
||||
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-andiamo/chioas"
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
}
|
||||
|
||||
func (c *Controller) Method() string {
|
||||
return http.MethodGet
|
||||
}
|
||||
|
||||
func (c *Controller) Path() string {
|
||||
return "/api/v1/ping"
|
||||
}
|
||||
|
||||
func (*Controller) New() controller.Controller {
|
||||
return &Controller{}
|
||||
}
|
||||
|
||||
func (c *Controller) Group(r chi.Router) {
|
||||
|
||||
r.Get("/ping", c.PingHandler)
|
||||
}
|
||||
|
||||
func (c *Controller) PingHandler(w http.ResponseWriter, _ *http.Request) {
|
||||
_, err := w.Write([]byte("pong"))
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
return
|
||||
func (c *Controller) Handler() gin.HandlerFunc {
|
||||
return func(ginCtx *gin.Context) {
|
||||
_, err := ginCtx.Writer.Write([]byte("pong"))
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +39,7 @@ func (c *Controller) Documentate() (*chioas.Paths, *chioas.Components) {
|
||||
"/ping": chioas.Path{
|
||||
Methods: map[string]chioas.Method{
|
||||
http.MethodGet: {
|
||||
Handler: c.PingHandler,
|
||||
Handler: c.Handler(),
|
||||
Responses: chioas.Responses{
|
||||
http.StatusOK: {
|
||||
ContentType: "plain/text",
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/jwt"
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
||||
http2 "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
||||
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/midlleware"
|
||||
"git.ostiwe.com/ostiwe-com/status/transform"
|
||||
"github.com/go-andiamo/chioas"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
serviceRepository repository.Service
|
||||
}
|
||||
|
||||
func (c *Controller) New() controller.Controller {
|
||||
return &Controller{
|
||||
serviceRepository: repository.NewServiceRepository(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) Group(r chi.Router) {
|
||||
c.public(r)
|
||||
c.internal(r)
|
||||
}
|
||||
|
||||
func (c *Controller) public(r chi.Router) {
|
||||
r.Get("/api/public/service", c.GetAllServicesPublic)
|
||||
}
|
||||
|
||||
func (c *Controller) internal(r chi.Router) {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(
|
||||
jwtauth.Verifier(jwt.TokenAuth),
|
||||
jwtauth.Authenticator(jwt.TokenAuth),
|
||||
midlleware.SetUserFromJWT,
|
||||
)
|
||||
|
||||
r.Get("/api/v1/service", c.GetAllServices)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (c *Controller) GetAllServicesPublic(w http.ResponseWriter, r *http.Request) {
|
||||
items, err := c.serviceRepository.All(r.Context(), -1, 0, true)
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
|
||||
writeErr := http2.NewResponseErrBuilder().
|
||||
WithMessage("Fetch service error").
|
||||
WithStatusCode(http.StatusInternalServerError).
|
||||
Send(w, r)
|
||||
if writeErr != nil {
|
||||
log.Global.Get(log.SERVER).Error(writeErr)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = http2.JSON(w, transform.PublicServices(items...), http.StatusOK)
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) GetAllServices(w http.ResponseWriter, r *http.Request) {
|
||||
limit, offset, errReady := http2.ExtractLimitOffset(r)
|
||||
if errReady != nil {
|
||||
err := errReady.Send(w)
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
items, err := c.serviceRepository.All(r.Context(), limit, offset, false)
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
|
||||
writeErr := http2.NewResponseErrBuilder().
|
||||
WithMessage("Fetch service error").
|
||||
WithStatusCode(http.StatusInternalServerError).
|
||||
Send(w, r)
|
||||
if writeErr != nil {
|
||||
log.Global.Get(log.SERVER).Error(writeErr)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
err = http2.JSON(w, items, http.StatusOK)
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) Documentate() (*chioas.Paths, *chioas.Components) {
|
||||
return nil, nil
|
||||
}
|
||||
60
router/controller/service/get.go
Normal file
60
router/controller/service/get.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/jwt"
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
||||
http2 "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
||||
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/midlleware"
|
||||
"git.ostiwe.com/ostiwe-com/status/transform"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type GetServices struct {
|
||||
serviceRepository repository.Service
|
||||
}
|
||||
|
||||
func (g *GetServices) New() controller.Controller {
|
||||
return &GetServices{
|
||||
serviceRepository: repository.NewServiceRepository(),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetServices) Handler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
items, err := g.serviceRepository.All(c.Request.Context(), -1, 0, true)
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
|
||||
writeErr := http2.NewResponseErrBuilder().
|
||||
WithMessage("Fetch service error").
|
||||
WithStatusCode(http.StatusInternalServerError).
|
||||
Send(c)
|
||||
if writeErr != nil {
|
||||
log.Global.Get(log.SERVER).Error(writeErr)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, transform.PublicServices(items...))
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GetServices) Method() string {
|
||||
return http.MethodGet
|
||||
}
|
||||
|
||||
func (g *GetServices) Path() string {
|
||||
return "/api/v1/services"
|
||||
}
|
||||
|
||||
func (g *GetServices) Middlewares() []gin.HandlerFunc {
|
||||
return []gin.HandlerFunc{
|
||||
jwt.AuthMiddleware.MiddlewareFunc(),
|
||||
midlleware.SetUserFromJWT(),
|
||||
}
|
||||
}
|
||||
51
router/controller/service/public_get.go
Normal file
51
router/controller/service/public_get.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/log"
|
||||
http2 "git.ostiwe.com/ostiwe-com/status/pkg/http"
|
||||
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/controller"
|
||||
"git.ostiwe.com/ostiwe-com/status/transform"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type PublicGetServicesController struct {
|
||||
serviceRepository repository.Service
|
||||
}
|
||||
|
||||
func (p *PublicGetServicesController) New() controller.Controller {
|
||||
return &PublicGetServicesController{
|
||||
serviceRepository: repository.NewServiceRepository(),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PublicGetServicesController) Handler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
items, err := p.serviceRepository.All(c.Request.Context(), -1, 0, true)
|
||||
if err != nil {
|
||||
log.Global.Get(log.SERVER).Error(err)
|
||||
|
||||
writeErr := http2.NewResponseErrBuilder().
|
||||
WithMessage("Fetch service error").
|
||||
WithStatusCode(http.StatusInternalServerError).
|
||||
Send(c)
|
||||
if writeErr != nil {
|
||||
log.Global.Get(log.SERVER).Error(writeErr)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, transform.PublicServices(items...))
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PublicGetServicesController) Method() string {
|
||||
return http.MethodGet
|
||||
}
|
||||
|
||||
func (p *PublicGetServicesController) Path() string {
|
||||
return "/api/v1/public/services"
|
||||
}
|
||||
@@ -4,30 +4,39 @@ import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"git.ostiwe.com/ostiwe-com/status/modules/jwt"
|
||||
"git.ostiwe.com/ostiwe-com/status/repository"
|
||||
"github.com/go-chi/jwtauth/v5"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func SetUserFromJWT(next http.Handler) http.Handler {
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
token, _, err := jwtauth.FromContext(ctx)
|
||||
func SetUserFromJWT() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
token, err := jwt.AuthMiddleware.ParseToken(c)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
c.Writer.WriteHeader(http.StatusUnauthorized)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
userRepo := repository.NewUserRepository()
|
||||
user, err := userRepo.FindByLogin(ctx, token.Subject())
|
||||
subject, err := token.Claims.GetSubject()
|
||||
if err != nil {
|
||||
c.Writer.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := userRepo.FindByLogin(ctx, subject)
|
||||
if err != nil || user == nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
c.Writer.WriteHeader(http.StatusUnauthorized)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
ctx = context.WithValue(ctx, "user", user)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
|
||||
c.Request = c.Request.WithContext(ctx)
|
||||
|
||||
c.Next()
|
||||
}
|
||||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
||||
@@ -11,39 +11,48 @@ import (
|
||||
"git.ostiwe.com/ostiwe-com/status/router/controller/ping"
|
||||
"git.ostiwe.com/ostiwe-com/status/router/controller/service"
|
||||
"git.ostiwe.com/ostiwe-com/status/version"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-andiamo/chioas"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/chi/v5/middleware"
|
||||
)
|
||||
|
||||
func getControllers() []controller.Controller {
|
||||
return []controller.Controller{
|
||||
new(ping.Controller).New(),
|
||||
new(service.Controller).New(),
|
||||
new(auth.Controller).New(),
|
||||
new(service.GetServices).New(),
|
||||
new(auth.PlainAuthController).New(),
|
||||
}
|
||||
}
|
||||
|
||||
func InitRoutes() *chi.Mux {
|
||||
func InitRoutes() *gin.Engine {
|
||||
log.Global.Get(log.SERVER).Info("Setting up routers")
|
||||
startTime := time.Now()
|
||||
|
||||
httpLogger := middleware.RequestLogger(&middleware.DefaultLogFormatter{Logger: log.Global.Get(log.SERVER), NoColor: false})
|
||||
|
||||
r := chi.NewRouter()
|
||||
r.Use(httpLogger)
|
||||
r := gin.New()
|
||||
r.Use(
|
||||
middleware.RequestID,
|
||||
middleware.RealIP,
|
||||
middleware.StripSlashes,
|
||||
middleware.Recoverer,
|
||||
middleware.CleanPath,
|
||||
middleware.Timeout(15*time.Second),
|
||||
gin.Recovery(),
|
||||
gin.LoggerWithConfig(gin.LoggerConfig{
|
||||
Output: log.Global.Get(log.SERVER).Out,
|
||||
}),
|
||||
)
|
||||
|
||||
ctrlList := getControllers()
|
||||
for _, ctrl := range ctrlList {
|
||||
r.Group(ctrl.Group)
|
||||
secured, ok := ctrl.(controller.SecuredController)
|
||||
if ok {
|
||||
r.Handle(
|
||||
ctrl.Method(),
|
||||
ctrl.Path(),
|
||||
append(secured.Middlewares(), ctrl.Handler())...,
|
||||
)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
r.Handle(
|
||||
ctrl.Method(),
|
||||
ctrl.Path(),
|
||||
ctrl.Handler(),
|
||||
)
|
||||
}
|
||||
|
||||
log.Global.Get(log.SERVER).Info(fmt.Sprintf("Initialized %d routers", len(ctrlList)))
|
||||
@@ -77,7 +86,12 @@ func Documentate() chioas.Definition {
|
||||
}
|
||||
|
||||
for _, ctrl := range ctrlList {
|
||||
documentatePaths, components := ctrl.Documentate()
|
||||
documentated, ok := ctrl.(controller.DocumentateController)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
documentatePaths, components := documentated.Documentate()
|
||||
|
||||
if documentatePaths != nil {
|
||||
for path, pathDoc := range *documentatePaths {
|
||||
|
||||
Reference in New Issue
Block a user