Categorygithub.com/Karthika-Rajagopal/go-restful
modulepackage
0.0.0-20230724073748-4eaf66b3e6b8
Repository: https://github.com/karthika-rajagopal/go-restful.git
Documentation: pkg.go.dev

# README

please note: swagger docs folder and files are generated inside the cmd folder Auto-generated by running go install github.com/swaggo/swag/cmd/swag@latest command, then swag init in the cmd directory.

swagger.go:

This code initializes the Swagger documentation for your API using the gin-swagger package. The code imports the required packages for Swagger documentation: gin, ginSwagger, and swaggerFiles.The Initialize function sets up the Swagger documentation.A new instance of the Gin router is created using gin.Default(). This will be used to define the Swagger UI route.The url variable is set to the URL path where the API definition is located. In this case, it's set to /swagger/doc.json. You should make sure to generate the API definition file and provide the correct path here.This line defines the route for the Swagger UI. The GET request to /swagger/*any will be handled by the ginSwagger.WrapHandler function, which wraps the Swagger UI handler from swaggerFiles.Handler. The url parameter is passed to the WrapHandler function to specify the URL of the API definition.

By calling this Initialize function in your main code, you can set up the Swagger UI route and access the Swagger documentation for your API.

main.go:

The code imports the required packages for your application, including Gin, Gorm, godotenv, and Swagger-related packages.This code uses the godotenv package to load environment variables from the .env file. If there is an error loading the file, the application will terminate.The config.InitDB() function initializes the database connection using the configuration provided. The connection is stored in the db variable, and defer db.Close() ensures that the connection is closed when the function returns.This line of code performs the auto migration using Gorm. It creates the necessary database tables based on the defined models. In this case, it migrates the User model.A new instance of the Gin router is created using gin.Default(). The middlewares.ErrorHandler() middleware is added to handle errors.This code sets up the Swagger documentation integration. The docs.SwaggerInfo struct is populated with the required information about the API. The /swagger/*any route is defined to serve the Swagger UI using ginSwagger.WrapHandler.A new group v1 is created to prefix all API routes with /v1.Within the v1 group, an auth group is created to handle authentication-related routes. The /register and /login routes are defined with their corresponding controller functions.Another group user is created within the v1 group to handle user-related routes. The middlewares.Authenticate() middleware is added to authenticate the user before accessing the /profile and /update routes. The corresponding controller functions are assigned to these routes.The application is started by calling r.Run(":8080"), which runs the Gin engine on port 8080.

This code sets up the necessary configurations, initializes the database, defines the API routes, integrates Swagger documentation, and starts the application server.

config/config.go:

This code provides a configuration package that handles loading environment variables from a .env file and retrieving specific environment variable values.The code imports the required packages, including log for logging errors, os for accessing environment variables, and github.com/joho/godotenv for loading variables from the .env file.The LoadEnv function loads the environment variables from the .env file. It uses the godotenv.Load function to read the file and assigns any variables found to the environment. If there is an error loading the file, it logs a fatal error.The GetEnv function retrieves the value of a specified environment variable by its key. It uses os.Getenv to fetch the value from the environment. It then returns the value as a string.

By using these functions, you can easily load environment variables from the .env file using LoadEnv and retrieve specific variables using GetEnv.

config/database.go:

This code provides a configuration package that handles the database connection and automigration using Gorm with PostgreSQL.The code imports the necessary packages, including fmt for string formatting, log for logging errors, gorm.io/driver/postgres for the PostgreSQL database driver, gorm.io/gorm for the Gorm ORM, and github.com/Karthika-Rajagopal/go-restful/models for the models package.The DB variable represents the database connection and will be used throughout the application.The InitDB function initializes the database connection. It constructs the Data Source Name (DSN) string using the environment variables for the host, port, user, password, and database name. Then, it uses gorm.Open to establish a connection to the PostgreSQL database. If there is an error connecting to the database, it logs a fatal error.The AutoMigrate function performs the database auto migration. It uses DB.AutoMigrate to automatically create or update the database tables based on the provided model structs. In this case, it performs auto migration for the User model. If there is an error during auto migration, it logs a fatal error.

By using these functions, you can initialize the database connection using InitDB and perform auto migration using AutoMigrate to ensure the database schema matches the defined models.

controllers/auth_controller.go:

This code defines a controller package that contains the implementation for the registration API.The code imports the necessary packages, including net/http for HTTP status codes, github.com/gin-gonic/gin for the Gin framework, github.com/Karthika-Rajagopal/go-restful/models for the models package, github.com/Karthika-Rajagopal/go-restful/config for the config package, and github.com/Karthika-Rajagopal/go-restful/utils for utility functions.The RegisterRequest struct represents the request body for the register API. It has Email and Password fields with corresponding JSON tags for binding and validation.The RegisterResponse struct represents the response body for the register API. It has a PublicAddress field to hold the public address associated with the registered user.The Register function handles the register API request. It first binds the JSON request body to the req variable, which is an instance of RegisterRequest. If there is an error in the binding, it returns a JSON response with a bad request status code.

The function then hashes the password using the utils.HashPassword function, which returns the hashed password and an error if it fails. If hashing fails, it returns a JSON response with an internal server error status code.

Next, it creates a new User struct with the email and hashed password obtained from the request. It uses config.DB.Create to create a new user record in the database. If there is an error during creation, it returns a JSON response with an internal server error status code.

Finally, it constructs the response body by assigning the user's MetamaskAddr field to PublicAddress and returns a JSON response with a success status code.

Overall, this code handles the registration API by validating and processing the request, creating a new user record in the database, and returning a response with the user's public address.

controllers/user_controller.go:

This code defines a controller package that contains the implementation for the login, get profile, and update profile APIs.The code imports the necessary packages, including net/http for HTTP status codes, github.com/gin-gonic/gin for the Gin framework, github.com/Karthika-Rajagopal/go-restful/models for the models package, github.com/Karthika-Rajagopal/go-restful/config for the config package, and github.com/Karthika-Rajagopal/go-restful/utils for utility functions.The LoginRequest struct represents the request body for the login API. It has Email and Password fields with corresponding JSON tags for binding and validation.The LoginResponse struct represents the response body for the login API. It has a User field of type models.User to hold the user object and a Token field to hold the authentication token.The Login function handles the login API request. It first binds the JSON request body to the req variable, which is an instance of LoginRequest. If there is an error in the binding, it returns a JSON response with a bad request status code.

The function queries the database to find a user with a matching email using config.DB.Where("email = ?", req.Email).First(&user). If no user is found, it returns a JSON response with an unauthorized status code.

It then verifies the password by comparing the provided password (req.Password) with the stored hashed password (user.Password) using utils.VerifyPassword. If the password verification fails, it returns a JSON response with an unauthorized status code.

If the email and password are valid, it generates a JWT token for the user ID using utils.GenerateJWTToken. If there is an error during token generation, it returns a JSON response with an internal server error status code.

Finally, it constructs the response body with the user object and token, and returns a JSON response with a success status code.The GetProfile function handles the get profile API request. It retrieves the user ID from the context using c.Get("userID"). It then queries the database to find the user with the specified ID using config.DB.First(&user, userID). If there is an error or the user is not found, it returns a JSON response with an internal server error status code.

If the user is found, it returns a JSON response with the user object and a success status code.The UpdateProfileRequest struct represents the request body for the update profile API. It has Message and Signature fields with corresponding JSON tags for binding and validation.The UpdateProfile function handles the update profile API request. It first binds the JSON request body to the req variable, which is an instance of UpdateProfileRequest. If there is an error in the binding, it returns a JSON response with a bad request status code.

The function retrieves the user ID from the context using c.Get("userID") and queries the database to find the user with the specified ID using config.DB.First(&user, userID). If there is an error or the user is not found, it returns a JSON response with an internal server error status code.

The function updates the MetamaskAddr field of the user object with the Message field from the request. This is a placeholder logic to extract the public address from the message/signature.

It then saves the updated user object to the database using config.DB.Save(&user). If there is an error during the save operation, it returns a JSON response with an internal server error status code.

Finally, it constructs the response body with the updated user's public address and returns a JSON response with a success status code.

Overall, this code implements the login, get profile, and update profile APIs by handling the requests, interacting with the database, and returning appropriate JSON responses.

middlewares/auth_middleware.go:

This code defines a middleware package that contains an AuthMiddleware function.The code imports the necessary packages, including net/http for HTTP status codes, github.com/gin-gonic/gin for the Gin framework, and github.com/Karthika-Rajagopal/go-restful/utils for utility functions.The AuthMiddleware function returns a Gin middleware handler function. This middleware is responsible for validating the JWT token included in the request's Authorization header and setting the user ID in the context.

The middleware function starts by retrieving the Authorization header from the request using c.GetHeader("Authorization"). If the header is missing or empty, it returns a JSON response with a status code of Unauthorized (401) and an error message. It also calls c.Abort() to stop the execution of subsequent middleware and handlers in the chain.

If the Authorization header is present, it extracts the token string by removing the "Bearer " prefix using strings.ReplaceAll(authHeader, "Bearer ", "").

The token string is then passed to the utils.VerifyJWTToken function to verify the token's authenticity and validity. If the token is invalid or there is an error during verification, it returns a JSON response with a status code of Unauthorized (401) and an error message. It also calls c.Abort() to stop the execution of subsequent middleware and handlers.

Assuming the token is valid, it attempts to parse the token claims into a JwtCustomClaims struct using a type assertion. If the assertion fails, indicating an issue with parsing the claims, it returns a JSON response with a status code of Unauthorized (401) and an error message. It also calls c.Abort() to stop the execution of subsequent middleware and handlers.

If the token and claims are valid, the middleware sets the user ID from the claims into the context using c.Set("userID", claims.UserID).

Finally, it calls c.Next() to continue the execution of subsequent middleware and handlers in the chain.

This middleware can be used to protect routes that require authentication. By adding this middleware to a route or a group of routes, it ensures that the request is accompanied by a valid JWT token in the Authorization header, and the user ID is available in the context for further processing.

models/auth.go:

This code defines several models for request and response structures used in a RESTful API. The RegisterRequest struct represents the request body structure for the register API. It has two fields: Email and Password. The json tags specify the JSON key names for the fields, and the binding tags define the validation rules for each field. In this case, the Email field is required and should be a valid email address, and the Password field is required and should have a minimum length of 6 characters.The LoginRequest struct represents the request body structure for the login API. It has two fields: Email and Password. Similar to the RegisterRequest, the json tags define the JSON key names, and the binding tags specify the validation rules. In this case, the Email field is required and should be a valid email address, and the Password field is required.The LoginResponse struct represents the response body structure for the login API. It has two fields: User and Token. The User field is of type User, which is assumed to be defined elsewhere, and it represents the user information. The Token field holds the authentication token for the logged-in user. The json tags specify the JSON key names for each field.The ErrorResponse struct represents the response body structure for error messages. It has a single field called Message, which holds the error message to be returned in the response. The json tag specifies the JSON key name for the field.

These model structures provide a convenient way to define the expected request and response formats for different API endpoints in a structured manner. They can be used for JSON serialization and deserialization, as well as for input validation using the binding tags.

models/user.go:

This code defines several models related to user management in a RESTful API. The User struct represents the user model. It includes the following fields:

gorm.Model: This field is embedded from the gorm.Model struct, which provides common fields like ID, CreatedAt, UpdatedAt, and DeletedAt. It allows you to leverage the features provided by the GORM library for database operations. Email: This field represents the email address of the user. The gorm:"unique" tag specifies that the email should be unique in the database. Password: This field holds the password of the user. PublicAddress: This field represents the public address associated with the user. The UpdateProfileRequest struct represents the request body structure for the update profile API. It has two fields:

Message: This field holds the message for updating the user's profile. Signature: This field holds the signature associated with the message. The UpdateProfileResponse struct represents the response body structure for the update profile API. It has a single field:

PublicAddress: This field represents the updated public address of the user. These models provide a structured representation of user-related data and can be used for database operations, request validation, and JSON serialization/deserialization. The gorm tags in the User struct define the mapping between the struct fields and the corresponding database columns, allowing you to leverage the GORM library for database operations.

utils/jwt.go:

This code provides utility functions for working with JSON Web Tokens (JWT) in the context of user authentication and authorization.The JwtCustomClaims struct represents the custom claims used in JWT. It includes the UserID field, which holds the user ID associated with the token, and embeds the jwt.StandardClaims struct provided by the jwt-go package. The embedded StandardClaims struct includes fields like ExpiresAt for token expiration.The GenerateJWTToken function generates a new JWT token for the specified user ID. It creates a new JwtCustomClaims instance with the provided user ID and sets the expiration time for the token. It then creates a new token using the jwt.NewWithClaims function, specifying the signing method and the claims. The token is signed with the JWT secret obtained from the configuration. Finally, the token is converted to a string representation and returned.The VerifyJWTToken function verifies the validity of a JWT token. It takes the token string as input and uses the jwt.ParseWithClaims function to parse and validate the token. The JwtCustomClaims struct is provided as the type for claims. The function also specifies a callback function that returns the JWT secret as the key for verification. If the token is valid, it is returned along with no error. Otherwise, an error is returned.

These utility functions enable the generation and verification of JWT tokens using the jwt-go package. They are useful for implementing authentication and authorization mechanisms in the RESTful API by issuing and validating tokens for user identification and access control.

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author