123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- package fiber
- import (
- "log"
- _ "git.dmitriygnatenko.ru/dima/homethings/docs" //nolint
- authAPI "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/auth"
- imageAPI "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/image"
- notificationAPI "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/notification"
- placeAPI "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place"
- tagAPI "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag"
- thingAPI "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing"
- userAPI "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/user"
- "git.dmitriygnatenko.ru/dima/homethings/internal/factory"
- "git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
- "git.dmitriygnatenko.ru/dima/homethings/internal/middleware/timezone"
- "github.com/gofiber/fiber/v2"
- "github.com/gofiber/fiber/v2/middleware/basicauth"
- "github.com/gofiber/fiber/v2/middleware/cors"
- "github.com/gofiber/fiber/v2/middleware/monitor"
- "github.com/gofiber/fiber/v2/middleware/recover"
- jwt "github.com/gofiber/jwt/v3"
- "github.com/gofiber/swagger"
- )
- const (
- staticPath = "../../web/public"
- swaggerURI = "/docs/*"
- metricsURI = "/metrics"
- )
- func Init(sp interfaces.ServiceProvider) (*fiber.App, error) {
- fiberApp := fiber.New(getFiberConfig(sp))
- // Configure web root
- fiberApp.Static("/", staticPath)
- // Configure CORS middleware
- fiberApp.Use(cors.New(getCORSConfig(sp)))
- // Configure recover middleware
- fiberApp.Use(recover.New())
- // Configure client timezone middleware
- fiberApp.Use(timezone.New())
- // Configure JWT middleware
- jwtAuth := jwt.New(getJWTConfig(sp))
- // Configure Basic auth
- basicAuth := basicauth.New(basicauth.Config{
- Users: map[string]string{
- sp.GetEnvService().GetBasicAuthUser(): sp.GetEnvService().GetBasicAuthPassword(),
- },
- })
- // Swagger
- fiberApp.Get(swaggerURI, swagger.HandlerDefault)
- // Metrics
- fiberApp.Get(metricsURI, basicAuth, monitor.New(getMetricsConfig()))
- // API
- api := fiberApp.Group("/api", jwtAuth)
- registerHandlers(api, sp)
- return fiberApp, nil
- }
- func getFiberConfig(sp interfaces.ServiceProvider) fiber.Config {
- return fiber.Config{
- AppName: "Homethings",
- DisableStartupMessage: true,
- ErrorHandler: getErrorHandler(sp),
- }
- }
- func getErrorHandler(sp interfaces.ServiceProvider) fiber.ErrorHandler {
- return func(fctx *fiber.Ctx, err error) error {
- errCode := fiber.StatusInternalServerError
- if e, ok := err.(*fiber.Error); ok {
- errCode = e.Code
- }
- if err.Error() != "" {
- errorsEmail := sp.GetEnvService().GetErrorsEmail()
- if errCode == fiber.StatusInternalServerError && errorsEmail != "" {
- log.Println(err)
- // nolint
- sp.GetMailerService().Send(
- errorsEmail,
- "AUTO - Homethings error",
- err.Error(),
- )
- }
- return fctx.Status(errCode).JSON(factory.CreateErrorResponse(err))
- }
- return fctx.Status(errCode).JSON(factory.CreateEmptyResponse())
- }
- }
- // nolint
- func getJWTConfig(sp interfaces.ServiceProvider) jwt.Config {
- return jwt.Config{
- SigningKey: []byte(sp.GetEnvService().GetJWTSecretKey()),
- ErrorHandler: func(fctx *fiber.Ctx, err error) error {
- return fiber.NewError(fiber.StatusForbidden, err.Error())
- },
- Filter: func(fctx *fiber.Ctx) bool {
- method := fctx.Method()
- path := fctx.Path()
- if method != fiber.MethodGet && method != fiber.MethodPost &&
- method != fiber.MethodPut && method != fiber.MethodDelete {
- return true
- }
- if path == "/api/v1/auth/login" {
- return true
- }
- return false
- },
- }
- }
- func getMetricsConfig() monitor.Config {
- return monitor.Config{
- Title: "Homethings metrics",
- }
- }
- func getCORSConfig(sp interfaces.ServiceProvider) cors.Config {
- return cors.Config{
- AllowOrigins: sp.GetEnvService().GetCORSAllowOrigins(),
- AllowMethods: sp.GetEnvService().GetCORSAllowMethods(),
- }
- }
- func registerHandlers(r fiber.Router, sp interfaces.ServiceProvider) {
- // Public routes
- r.Post("/v1/auth/login", authAPI.LoginHandler(sp))
- // Protected routes
- r.Get("/v1/auth/check", authAPI.CheckAuthHandler(sp))
- r.Get("/v1/places", placeAPI.GetPlacesHandler(sp))
- r.Get("/v1/places/tree", placeAPI.GetPlaceTreeHandler(sp))
- r.Get("/v1/places/:placeId<int>", placeAPI.GetPlaceHandler(sp))
- r.Get("/v1/places/:parentPlaceId<int>/nested", placeAPI.GetNestedPlacesHandler(sp))
- r.Post("/v1/places", placeAPI.AddPlaceHandler(sp))
- r.Put("/v1/places/:placeId<int>", placeAPI.UpdatePlaceHandler(sp))
- r.Delete("/v1/places/:placeId<int>", placeAPI.DeletePlaceHandler(sp))
- r.Get("/v1/things/:thingId<int>", thingAPI.GetThingHandler(sp))
- r.Get("/v1/things/search/:search", thingAPI.SearchThingHandler(sp))
- r.Get("/v1/things/place/:placeId<int>", thingAPI.GetPlaceThingsHandler(sp))
- r.Post("/v1/things", thingAPI.AddThingHandler(sp))
- r.Put("/v1/things/:thingId<int>", thingAPI.UpdateThingHandler(sp))
- r.Delete("/v1/things/:thingId<int>", thingAPI.DeleteThingHandler(sp))
- r.Get("/v1/images/place/:placeId<int>", imageAPI.GetPlaceImagesHandler(sp))
- r.Get("/v1/images/thing/:thingId<int>", imageAPI.GetThingImagesHandler(sp))
- r.Post("/v1/images", imageAPI.AddImageHandler(sp))
- r.Delete("/v1/images/place/:imageId<int>", imageAPI.DeletePlaceImageHandler(sp))
- r.Delete("/v1/images/thing/:imageId<int>", imageAPI.DeleteThingImageHandler(sp))
- r.Get("/v1/tags", tagAPI.GetTagsHandler(sp))
- r.Get("/v1/tags/:tagId<int>", tagAPI.GetTagHandler(sp))
- r.Get("/v1/tags/thing/:thingId<int>", tagAPI.GetThingTagsHandler(sp))
- r.Post("/v1/tags", tagAPI.AddTagHandler(sp))
- r.Post("/v1/tags/:tagId<int>/thing/:thingId<int>", tagAPI.AddThingTagHandler(sp))
- r.Put("/v1/tags/:tagId<int>", tagAPI.UpdateTagHandler(sp))
- r.Delete("/v1/tags/:tagId<int>", tagAPI.DeleteTagHandler(sp))
- r.Delete("/v1/tags/:tagId<int>/thing/:thingId<int>", tagAPI.DeleteThingTagHandler(sp))
- r.Get("/v1/tags/:id<int>", tagAPI.GetTagHandler(sp))
- r.Post("/v1/tags", tagAPI.AddTagHandler(sp))
- r.Put("/v1/tags/:id<int>", tagAPI.UpdateTagHandler(sp))
- r.Delete("/v1/tags/:id<int>", tagAPI.DeleteTagHandler(sp))
- r.Get("/v1/things/notifications/:thingId<int>", notificationAPI.GetThingNotificationHandler(sp))
- r.Get("/v1/things/notifications/expired", notificationAPI.GetExpiredThingNotificationsHandler(sp))
- r.Post("/v1/things/notifications", notificationAPI.AddThingNotificationHandler(sp))
- r.Put("/v1/things/notifications/:thingId<int>", notificationAPI.UpdateThingNotificationHandler(sp))
- r.Delete("/v1/things/notifications/:thingId<int>", notificationAPI.DeleteThingNotificationHandler(sp))
- r.Post("/v1/users", userAPI.AddUserHandler(sp))
- r.Put("/v1/users", userAPI.UpdateUserHandler(sp))
- }
|