diff --git a/server/app/controllers/server.go b/server/app/controllers/server.go new file mode 100644 index 0000000..36d05ef --- /dev/null +++ b/server/app/controllers/server.go @@ -0,0 +1,90 @@ +package controllers + +import ( + "context" + + _ "github.com/cirnum/strain-hub/server/app/models" + "github.com/cirnum/strain-hub/server/app/utils" + "github.com/google/uuid" + + "github.com/cirnum/strain-hub/server/db" + "github.com/cirnum/strain-hub/server/db/models" + "github.com/cirnum/strain-hub/server/pkg/constants" + "github.com/gofiber/fiber/v2" +) + +// To Get all the Server +func GetAllServer(c *fiber.Ctx) error { + ctx := context.Background() + pagination := utils.GetPagination(c) + listServer, err := db.Provider.ListServer(ctx, &pagination) + + if err != nil { + return utils.ResponseError(c, err, "Failed to add the server.", 0) + } + return utils.ResponseSuccess(c, listServer, "Server added successfully.", 0) + +} + +// To Update server +func UpdateServer(c *fiber.Ctx) error { + ctx := context.Background() + serverPayload := &models.Server{} + + if err := c.BodyParser(serverPayload); err != nil { + return utils.ResponseError(c, err, constants.InvalidBody, fiber.StatusInternalServerError) + } + updatedServer, err := db.Provider.UpdateServer(ctx, *serverPayload) + + if err != nil { + return utils.ResponseError(c, err, "Failed to update the server.", 0) + } + return utils.ResponseSuccess(c, updatedServer, "Server Updated successfully.", 0) + +} + +func AddServer(c *fiber.Ctx) error { + + ctx := context.Background() + serverPayload := &models.Server{} + + if err := c.BodyParser(serverPayload); err != nil { + return utils.ResponseError(c, err, constants.InvalidBody, fiber.StatusInternalServerError) + } + serverPayload.ID = uuid.New().String() + jwtToken, err := utils.GenerateTokenKey(*serverPayload) + + if err != nil { + return utils.ResponseError(c, err, err.Error(), fiber.StatusInternalServerError) + } + + serverPayload.Token = jwtToken + server, err := db.Provider.AddServer(ctx, *serverPayload) + + if err != nil { + return utils.ResponseError(c, err, err.Error(), fiber.StatusInternalServerError) + } + return utils.ResponseSuccess(c, server, "Server added successfully.", fiber.StatusOK) +} + +func GetServerById(c *fiber.Ctx) error { + ctx := context.Background() + id := c.Params("id") + + server, err := db.Provider.GetRequestById(ctx, id) + if err != nil { + return utils.ResponseError(c, err, err.Error(), fiber.StatusInternalServerError) + } + return utils.ResponseSuccess(c, server, "Server retrieved successfully.", fiber.StatusOK) +} + +func DeleteServerById(c *fiber.Ctx) error { + ctx := context.Background() + id := c.Params("id") + + err := db.Provider.DeleteServerById(ctx, id) + if err != nil { + return utils.ResponseError(c, err, err.Error(), fiber.StatusInternalServerError) + } + return utils.ResponseSuccess(c, nil, "Fetched Server lists.", fiber.StatusOK) +} diff --git a/server/app/utils/jwt.go b/server/app/utils/jwt.go index 43b3e58..e88dc1f 100644 --- a/server/app/utils/jwt.go +++ b/server/app/utils/jwt.go @@ -44,6 +44,19 @@ func GenerateJWT(user models.User) (string, error) { return token, nil } +func GenerateTokenKey(server models.Server) (string, error) { + atClaims := jwt.MapClaims{} + atClaims["authorized"] = true + atClaims["id"] = server.ID + atClaims["user"] = server.UserID + + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + token, err := at.SignedString([]byte(os.Getenv("CLIENT_SECRET_KEY"))) + if err != nil { + return "", err + } + return token, nil +} func AutheticateRequest(r *http.Request) (bool, models.User) { var user models.User jwtToken := r.Header.Get("Authorization") diff --git a/server/db/models/server.go b/server/db/models/server.go new file mode 100644 index 0000000..5284c8a --- /dev/null +++ b/server/db/models/server.go @@ -0,0 +1,34 @@ +package models + +// type Request struct { +// ID string `gorm:"primaryKey;type:char(36)" json:"id,omitempty"` +// UserID string `json:"userID,omitempty"` +// URL string `json:"url"` +// Requests int64 `json:"requests"` +// Time int `json:"time"` +// Clients int `json:"clients"` +// Headers string `json:"headers"` +// Params string `json:"params"` +// KeepAlive bool `json:"keepAlive"` +// Method string `json:"method"` +// Ips string `json:"ips" bson:"ips"` +// PostData string `json:"postData,omitempty"` +// UpdatedAt int64 `json:"updated_at" bson:"updated_at"` +// CreatedAt int64 `json:"created_at" bson:"created_at"` +// } +type Server struct { + ID string `gorm:"primaryKey;type:char(36)" json:"id,omitempty"` + UserID string `json:"userID,omitempty"` + IP string `json:"ip"` + Port int64 `json:"port"` + Token string `json:"token"` + Active bool `json:"active"` + Interval int `json:"interval"` + UpdatedAt int64 `json:"updated_at" bson:"updated_at"` + CreatedAt int64 `json:"created_at" bson:"created_at"` +} + +type ServerList struct { + Pagination *Pagination `json:"pagination"` + Data []Server `json:"data"` +} diff --git a/server/db/providers/providers.go b/server/db/providers/providers.go index 6a44dea..03435d1 100644 --- a/server/db/providers/providers.go +++ b/server/db/providers/providers.go @@ -29,4 +29,15 @@ type Provider interface { AddLoadByRequestId(ctx context.Context, load models.Loadster) (models.Loadster, error) // Get load GetLoadByRequestId(ctx context.Context, pagination models.Pagination, requestId string) ([]models.Loadster, error) + // Add server + AddServer(ctx context.Context, server models.Server) (models.Server, error) + // UpdateUser to update user information in database + UpdateServer(ctx context.Context, server models.Server) (models.Server, error) + // DeleteUser to delete user information from database + DeleteServerById(ctx context.Context, id string) error + // ListUsers to get list of users from database + ListServer(ctx context.Context, pagination *models.Pagination) (*models.ServerList, error) + // GetuserByEmail + GetServerById(ctx context.Context, email string) (models.Server, error) + // Update server } diff --git a/server/db/providers/sql/provider.go b/server/db/providers/sql/provider.go index eddcc51..89e9d41 100644 --- a/server/db/providers/sql/provider.go +++ b/server/db/providers/sql/provider.go @@ -69,7 +69,7 @@ func NewProvider() (*provider, error) { logrus.Debug("Failed to drop phone number constraint:", err) } - err = sqlDB.AutoMigrate(&models.User{}, &models.Request{}, &models.Loadster{}) + err = sqlDB.AutoMigrate(&models.User{}, &models.Request{}, &models.Loadster{}, &models.Server{}) if err != nil { return nil, err } diff --git a/server/db/providers/sql/server.go b/server/db/providers/sql/server.go new file mode 100644 index 0000000..f4af830 --- /dev/null +++ b/server/db/providers/sql/server.go @@ -0,0 +1,98 @@ +package sql + +import ( + "context" + "errors" + "time" + + "github.com/cirnum/strain-hub/server/db/models" + "github.com/google/uuid" +) + +// AddServer to update user information in database +func (p *provider) AddServer(ctx context.Context, server models.Server) (models.Server, error) { + if server.ID == "" { + server.ID = uuid.New().String() + } + server.Token = uuid.New().String() + server.CreatedAt = time.Now().Unix() + server.UpdatedAt = time.Now().Unix() + + result := p.db.Create(&server) + + if result.Error != nil { + return server, result.Error + } + + return server, nil +} + +// AddServer to update user information in database +func (p *provider) UpdateServer(ctx context.Context, server models.Server) (models.Server, error) { + server.UpdatedAt = time.Now().Unix() + result := p.db.Model(&server).Where("id = ?", server.ID).Update("UpdatedAt", server.UpdatedAt) + if result.Error != nil { + return server, result.Error + } + return server, nil +} + +// ListServer to get list of users from database +func (p *provider) ListServer(ctx context.Context, pagination *models.Pagination) (*models.ServerList, error) { + var servers []models.Server + result := p.db.Limit(int(pagination.Limit)).Offset(int(pagination.Offset)).Order("created_at DESC").Find(&servers) + if result.Error != nil { + return nil, result.Error + } + + serverList := []models.Server{} + for _, request := range servers { + serverList = append(serverList, request) + } + + var total int64 + totalRes := p.db.Model(&models.Request{}).Count(&total) + if totalRes.Error != nil { + return nil, totalRes.Error + } + + paginationClone := pagination + paginationClone.Total = total + + return &models.ServerList{ + Pagination: paginationClone, + Data: serverList, + }, nil +} + +// GetServerById to update user information in database +func (p *provider) GetServerById(ctx context.Context, id string) (models.Server, error) { + var server models.Server + + if id == "" { + return server, errors.New("Request id missing.") + } + + result := p.db.Where("id = ?", id).First(&server) + if result.Error != nil { + return server, result.Error + } + + return server, nil +} + +// DeleteServerById Request by id to update user information in database +func (p *provider) DeleteServerById(ctx context.Context, id string) error { + + if id == "" { + return errors.New("Request id missing.") + } + + result := p.db.Delete(&models.Server{ + ID: id, + }) + if result.Error != nil { + return result.Error + } + return nil +} diff --git a/server/pkg/middleware/jwt.go b/server/pkg/middleware/jwt.go index a71ef68..0c28e3a 100644 --- a/server/pkg/middleware/jwt.go +++ b/server/pkg/middleware/jwt.go @@ -21,6 +21,17 @@ func JWTProtected() func(*fiber.Ctx) error { return jwtMiddleware.New(config) } +func JWTProtectedClient() func(*fiber.Ctx) error { + // Create config for JWT authentication middleware. + config := jwtMiddleware.Config{ + SigningKey: []byte(os.Getenv("CLIENT_SECRET_KEY")), + ContextKey: "jwt", // used in private routes + ErrorHandler: jwtError, + } + + return jwtMiddleware.New(config) +} + func jwtError(c *fiber.Ctx, err error) error { // Return status 401 and failed authentication error. if err.Error() == "Missing or malformed JWT" { diff --git a/server/pkg/routes/server.go b/server/pkg/routes/server.go new file mode 100644 index 0000000..fcf4ba9 --- /dev/null +++ b/server/pkg/routes/server.go @@ -0,0 +1,20 @@ +package routes + +import ( + "github.com/cirnum/strain-hub/server/app/controllers" + "github.com/cirnum/strain-hub/server/pkg/middleware" + "github.com/gofiber/fiber/v2" +) + +// PrivateRoutes func for describe group of private routes. +func ServerRoutes(a *fiber.App) { + // Create routes group. + server := "/server" + route := a.Group("/api/v1") + // user routes + route.Post(server, middleware.JWTProtected(), controllers.AddServer) + route.Get(server, middleware.JWTProtected(), controllers.GetAllServer) + route.Get(server+"/:id", middleware.JWTProtected(), controllers.GetServerById) + route.Delete(server+"/:id", middleware.JWTProtected(), controllers.DeleteServerById) + route.Put(server, middleware.JWTProtectedClient(), controllers.UpdateServer) +}