diff options
Diffstat (limited to 'utils')
| -rw-r--r-- | utils/auth/auth.go | 46 | ||||
| -rw-r--r-- | utils/auth/constants.go | 5 | ||||
| -rw-r--r-- | utils/meta/body.go | 12 | ||||
| -rw-r--r-- | utils/shortcuts/error.go | 65 | ||||
| -rw-r--r-- | utils/shortcuts/functions.go | 97 | ||||
| -rw-r--r-- | utils/shortcuts/redirect.go | 25 | ||||
| -rw-r--r-- | utils/shortcuts/render.go | 22 |
7 files changed, 272 insertions, 0 deletions
diff --git a/utils/auth/auth.go b/utils/auth/auth.go new file mode 100644 index 0000000..5abb496 --- /dev/null +++ b/utils/auth/auth.go @@ -0,0 +1,46 @@ +package auth + +import ( + "dove/session" + + "github.com/gofiber/fiber/v2" +) + +func IsAuthenticated(context *fiber.Ctx) bool { + activeSession, sessionError := session.Store.Get(context) + if sessionError != nil { + return false + } + + return activeSession.Get(SESSION_AUTHENTICATED_KEY) != nil +} + +func RequireAuthentication(handler fiber.Handler) fiber.Handler { + return func(context *fiber.Ctx) error { + switch IsAuthenticated(context) { + case true: + return handler(context) + default: + return fiber.ErrUnauthorized + } + } +} + +func Authenticate(context *fiber.Ctx) error { + activeSession, sessionError := session.Store.Get(context) + if sessionError != nil { + return sessionError + } + + activeSession.Set(SESSION_AUTHENTICATED_KEY, true) + return activeSession.Save() +} + +func Deauthenticate(context *fiber.Ctx) error { + activeSession, sessionError := session.Store.Get(context) + if sessionError != nil { + return sessionError + } + + return activeSession.Destroy() +} diff --git a/utils/auth/constants.go b/utils/auth/constants.go new file mode 100644 index 0000000..99f5a85 --- /dev/null +++ b/utils/auth/constants.go @@ -0,0 +1,5 @@ +package auth + +const ( + SESSION_AUTHENTICATED_KEY = "authenticated" +) diff --git a/utils/meta/body.go b/utils/meta/body.go new file mode 100644 index 0000000..ce10bde --- /dev/null +++ b/utils/meta/body.go @@ -0,0 +1,12 @@ +package meta + +import "github.com/gofiber/fiber/v2" + +func Body[T any](context *fiber.Ctx) (T, error) { + var body T + if parseError := context.BodyParser(&body); parseError != nil { + return body, parseError + } + + return body, nil +} diff --git a/utils/shortcuts/error.go b/utils/shortcuts/error.go new file mode 100644 index 0000000..71fa4bd --- /dev/null +++ b/utils/shortcuts/error.go @@ -0,0 +1,65 @@ +package shortcuts + +import ( + "dove/enums" + "dove/types" + + "github.com/gofiber/fiber/v2" +) + +var statusMap = map[enums.ErrorKind]int{ + enums.BadRequest: fiber.StatusBadRequest, + enums.Forbidden: fiber.StatusForbidden, + enums.Internal: fiber.StatusInternalServerError, + enums.NotFound: fiber.StatusNotFound, + enums.Unauthorized: fiber.StatusUnauthorized, + enums.Unprocessable: fiber.StatusUnprocessableEntity, +} + +func ServiceError(kind enums.ErrorKind, message string) *types.ServiceError { + return &types.ServiceError{ + Kind: kind, + Message: message, + } +} + +func HandleError(context *fiber.Ctx, serviceError *types.ServiceError) error { + statusCode, exists := statusMap[serviceError.Kind] + if !exists { + statusCode = fiber.StatusInternalServerError + } + + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": serviceError.Message, + }, statusCode) +} + +func BadRequest(context *fiber.Ctx, err error) error { + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": err.Error(), + }, fiber.StatusBadRequest) +} + +func Forbidden(context *fiber.Ctx, err error) error { + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": err.Error(), + }, fiber.StatusForbidden) +} + +func InternalServerError(context *fiber.Ctx, err error) error { + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": err.Error(), + }, fiber.StatusInternalServerError) +} + +func NotFound(context *fiber.Ctx, err error) error { + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": err.Error(), + }, fiber.StatusNotFound) +} + +func Unauthorized(context *fiber.Ctx, err error) error { + return RenderWithStatus(context, "error", fiber.Map{ + "ErrorMessage": err.Error(), + }, fiber.StatusUnauthorized) +} diff --git a/utils/shortcuts/functions.go b/utils/shortcuts/functions.go new file mode 100644 index 0000000..df00dcf --- /dev/null +++ b/utils/shortcuts/functions.go @@ -0,0 +1,97 @@ +package shortcuts + +import ( + "maps" + "reflect" + "strings" + + "dove/messages" + "dove/utils/errors" + + "github.com/gofiber/fiber/v2" +) + +func mergeContextValues(context *fiber.Ctx, targetMap fiber.Map) { + context.Context().VisitUserValues(func(key []byte, value any) { + targetMap[string(key)] = value + }) +} + +func mergeBindData(targetMap fiber.Map, data any) error { + normalizedData, normalizeError := normalizeToMap(data) + if normalizeError != nil { + return normalizeError + } + + maps.Copy(targetMap, normalizedData) + return nil +} + +func normalizeToMap(data any) (fiber.Map, error) { + switch typedData := data.(type) { + case fiber.Map: + return typedData, nil + case map[string]any: + return fiber.Map(typedData), nil + default: + return convertStructToMap(data) + } +} + +func convertStructToMap(data any) (fiber.Map, error) { + structValue := reflect.ValueOf(data) + + switch structValue.Kind() { + case reflect.Pointer: + structValue = structValue.Elem() + } + + switch structValue.Kind() { + case reflect.Struct: + return extractStructFields(structValue), nil + default: + return nil, errors.Error(messages.ShortcutUnsupportedBindType) + } +} + +func extractStructFields(structValue reflect.Value) fiber.Map { + structType := structValue.Type() + fieldMap := make(fiber.Map, structValue.NumField()) + + for fieldIndex := range structType.NumField() { + fieldDescriptor := structType.Field(fieldIndex) + + if !fieldDescriptor.IsExported() { + continue + } + + fieldKey := resolveFieldKey(fieldDescriptor) + fieldMap[fieldKey] = structValue.Field(fieldIndex).Interface() + } + + return fieldMap +} + +func resolveFieldKey(fieldDescriptor reflect.StructField) string { + jsonTag := fieldDescriptor.Tag.Get("json") + + switch { + case jsonTag == "" || jsonTag == "-": + return fieldDescriptor.Name + default: + return extractTagName(jsonTag, fieldDescriptor.Name) + } +} + +func extractTagName(jsonTag string, fallbackName string) string { + separatorIndex := strings.IndexByte(jsonTag, ',') + + switch { + case separatorIndex < 0: + return jsonTag + case separatorIndex > 0: + return jsonTag[:separatorIndex] + default: + return fallbackName + } +}
\ No newline at end of file diff --git a/utils/shortcuts/redirect.go b/utils/shortcuts/redirect.go new file mode 100644 index 0000000..627538d --- /dev/null +++ b/utils/shortcuts/redirect.go @@ -0,0 +1,25 @@ +package shortcuts + +import ( + "dove/utils/urls" + + "github.com/gofiber/fiber/v2" +) + +func Redirect(context *fiber.Ctx, routeName string) error { + fullPath, exists := urls.GetFullPath(routeName) + if !exists { + return fiber.ErrNotFound + } + + return context.Redirect(fullPath) +} + +func RedirectWithStatus(context *fiber.Ctx, routeName string, statusCode int) error { + fullPath, exists := urls.GetFullPath(routeName) + if !exists { + return fiber.ErrNotFound + } + + return context.Redirect(fullPath, statusCode) +}
\ No newline at end of file diff --git a/utils/shortcuts/render.go b/utils/shortcuts/render.go new file mode 100644 index 0000000..29c7a8f --- /dev/null +++ b/utils/shortcuts/render.go @@ -0,0 +1,22 @@ +package shortcuts + +import "github.com/gofiber/fiber/v2" + +func Render(context *fiber.Ctx, templateName string, data any) error { + templateData := make(fiber.Map) + + mergeContextValues(context, templateData) + + if data != nil { + if mergeError := mergeBindData(templateData, data); mergeError != nil { + return mergeError + } + } + + return context.Render(templateName, templateData) +} + +func RenderWithStatus(context *fiber.Ctx, templateName string, data any, statusCode int) error { + context.Status(statusCode) + return Render(context, templateName, data) +} |
