Skip to content

Commit fed3728

Browse files
Project structure created and Creating the necessary files
1 parent 2aa72dc commit fed3728

29 files changed

+2002
-0
lines changed

.gitignore

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work
22+
*.DS_store
23+
*.log
24+
*.log.gz
25+
__debug_bin
26+
*/cmd/uploads

api/api.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package api
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/Asrez/GoAPIBlog/config"
7+
"github.com/gin-gonic/gin"
8+
)
9+
10+
func InitServer(){
11+
config := config.GetConfig()
12+
r := gin.New()
13+
r.Use(gin.Logger() ,gin.Recovery())
14+
15+
// v1 := r.Group("api/v1")
16+
// {
17+
18+
// }
19+
20+
r.Run(fmt.Sprintf(":%s", config.Server.InternalPort))
21+
}

api/dto/auth.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package dto
2+
3+
type TokenDetail struct {
4+
AccessToken string `json:"accessToken"`
5+
RefreshToken string `json:"refreshToken"`
6+
AccessTokenExpireTime int64 `json:"accessTokenExpireTime"`
7+
RefreshTokenExpireTime int64 `json:"refreshTokenExpireTime"`
8+
}
9+
10+
type RegisterUserByUsernameRequest struct {
11+
FirstName string `json:"firstName" binding:"required,min=3"`
12+
LastName string `json:"lastName" binding:"required,min=6"`
13+
Username string `json:"username" binding:"required,min=5"`
14+
Email string `json:"email" binding:"min=6,email"`
15+
Password string `json:"password" binding:"required,password,min=6"`
16+
}
17+
18+
type LoginByUsernameRequest struct {
19+
Username string `json:"username" binding:"required,min=5"`
20+
Password string `json:"password" binding:"required,min=6"`
21+
}

api/helpers/base_response.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package helper
2+
3+
import (
4+
validation "github.com/Asrez/GoAPIBlog/api/validations"
5+
)
6+
7+
8+
type BaseHttpResponse struct {
9+
Result any `json:"result"`
10+
Success bool `json:"success"`
11+
ResultCode ResultCode `json:"resultCode"`
12+
ValidationErrors *[]validation.ValidationError `json:"validationErrors"`
13+
Error any `json:"error"`
14+
}
15+
16+
func GenerateBaseResponse(result any, success bool, resultCode ResultCode) *BaseHttpResponse {
17+
return &BaseHttpResponse{Result: result,
18+
Success: success,
19+
ResultCode: resultCode,
20+
}
21+
}
22+
23+
func GenerateBaseResponseWithError(result any, success bool, resultCode ResultCode, err error) *BaseHttpResponse {
24+
return &BaseHttpResponse{Result: result,
25+
Success: success,
26+
ResultCode: resultCode,
27+
Error: err.Error(),
28+
}
29+
30+
}
31+
32+
func GenerateBaseResponseWithAnyError(result any, success bool, resultCode ResultCode, err any) *BaseHttpResponse {
33+
return &BaseHttpResponse{Result: result,
34+
Success: success,
35+
ResultCode: resultCode,
36+
Error: err,
37+
}
38+
}
39+
40+
func GenerateBaseResponseWithValidationError(result any, success bool, resultCode ResultCode, err error) *BaseHttpResponse {
41+
return &BaseHttpResponse{Result: result,
42+
Success: success,
43+
ResultCode: resultCode,
44+
ValidationErrors: validation.GetValidationErrors(err),
45+
}
46+
}

api/helpers/result_code.go

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package helper
2+
3+
type ResultCode int
4+
5+
const (
6+
Success ResultCode = 0
7+
ValidationError ResultCode = 40001
8+
AuthError ResultCode = 40101
9+
ForbiddenError ResultCode = 40301
10+
NotFoundError ResultCode = 40401
11+
LimiterError ResultCode = 42901
12+
OtpLimiterError ResultCode = 42902
13+
CustomRecovery ResultCode = 50001
14+
InternalError ResultCode = 50002
15+
)

api/helpers/status_code_mapping.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package helper
2+
3+
import (
4+
"net/http"
5+
"github.com/Asrez/GoAPIBlog/pkg/service_errors"
6+
)
7+
8+
var StatusCodeMapping = map[string]int{
9+
// User
10+
service_errors.EmailExists: 409,
11+
service_errors.UsernameExists: 409,
12+
service_errors.RecordNotFound: 404,
13+
service_errors.PermissionDenied: 403,
14+
}
15+
16+
func TranslateErrorToStatusCode(err error) int {
17+
value, ok := StatusCodeMapping[err.Error()]
18+
if !ok {
19+
return http.StatusInternalServerError
20+
}
21+
return value
22+
}

api/middlewares/auth.go

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package middlewares
2+
3+
import (
4+
"net/http"
5+
"strings"
6+
helper "github.com/Asrez/GoAPIBlog/api/helpers"
7+
"github.com/Asrez/GoAPIBlog/config"
8+
"github.com/Asrez/GoAPIBlog/constants"
9+
"github.com/Asrez/GoAPIBlog/pkg/service_errors"
10+
"github.com/Asrez/GoAPIBlog/services"
11+
"github.com/gin-gonic/gin"
12+
"github.com/golang-jwt/jwt"
13+
)
14+
15+
func Authentication(cfg *config.Config) gin.HandlerFunc {
16+
var tokenService = services.NewTokenService(cfg)
17+
18+
return func(c *gin.Context) {
19+
var err error
20+
claimMap := map[string]interface{}{}
21+
auth := c.GetHeader(constants.AuthorizationHeaderKey)
22+
token := strings.Split(auth, " ")
23+
if auth == "" {
24+
err = &service_errors.ServiceError{EndUserMessage: service_errors.TokenRequired}
25+
} else {
26+
claimMap, err = tokenService.GetClaims(token[1])
27+
if err != nil {
28+
switch err.(*jwt.ValidationError).Errors {
29+
case jwt.ValidationErrorExpired:
30+
err = &service_errors.ServiceError{EndUserMessage: service_errors.TokenExpired}
31+
default:
32+
err = &service_errors.ServiceError{EndUserMessage: service_errors.TokenInvalid}
33+
}
34+
}
35+
}
36+
if err != nil {
37+
c.AbortWithStatusJSON(http.StatusUnauthorized, helper.GenerateBaseResponseWithError(
38+
nil, false, helper.AuthError, err,
39+
))
40+
return
41+
}
42+
43+
c.Set(constants.UserIdKey, claimMap[constants.UserIdKey])
44+
c.Set(constants.FirstNameKey, claimMap[constants.FirstNameKey])
45+
c.Set(constants.LastNameKey, claimMap[constants.LastNameKey])
46+
c.Set(constants.UsernameKey, claimMap[constants.UsernameKey])
47+
c.Set(constants.EmailKey, claimMap[constants.EmailKey])
48+
c.Set(constants.ExpireTimeKey, claimMap[constants.ExpireTimeKey])
49+
50+
c.Next()
51+
}
52+
}

api/validations/custom.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package validation
2+
3+
import (
4+
"errors"
5+
"github.com/go-playground/validator/v10"
6+
)
7+
8+
type ValidationError struct {
9+
Property string `json:"property"`
10+
Tag string `json:"tag"`
11+
Value string `json:"value"`
12+
Message string `json:"message"`
13+
}
14+
15+
func GetValidationErrors(err error) *[]ValidationError {
16+
var validationErrors []ValidationError
17+
var ve validator.ValidationErrors
18+
if errors.As(err,&ve){
19+
for _, err := range err.(validator.ValidationErrors){
20+
var el ValidationError
21+
el.Property = err.Field()
22+
el.Tag = err.Tag()
23+
el.Value = err.Param()
24+
validationErrors = append(validationErrors, el)
25+
}
26+
return &validationErrors
27+
}
28+
return nil
29+
}

api/validations/passwod.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package validation
2+
3+
import (
4+
"github.com/Asrez/GoAPIBlog/common"
5+
"github.com/go-playground/validator/v10"
6+
)
7+
8+
func PasswordValidator(fld validator.FieldLevel) bool {
9+
value, ok := fld.Field().Interface().(string)
10+
if !ok {
11+
fld.Param()
12+
return false
13+
}
14+
15+
return common.CheckPassword(value)
16+
}

cmd/main.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
import (
4+
"github.com/Asrez/GoAPIBlog/api"
5+
"github.com/Asrez/GoAPIBlog/config"
6+
"github.com/Asrez/GoAPIBlog/data/db"
7+
"github.com/Asrez/GoAPIBlog/data/migration"
8+
"github.com/Asrez/GoAPIBlog/pkg/logging"
9+
)
10+
11+
func main(){
12+
cfg := config.GetConfig()
13+
logger := logging.NewLogger(cfg)
14+
err := db.InitDb(cfg)
15+
defer db.CloseDb()
16+
17+
if err != nil {
18+
logger.Fatal(logging.Postgres , logging.Startup , err.Error(),nil)
19+
}
20+
21+
migration.Up()
22+
api.InitServer()
23+
}

0 commit comments

Comments
 (0)