init push

This commit is contained in:
2026-07-16 22:16:45 +07:00
commit 8b068bdb10
1021 changed files with 332816 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
package handlers
import (
"context"
"strings"
"time"
"github.com/gofiber/fiber/v2"
"wucher/internal/shared/pkg/userctx"
"wucher/internal/shared/pkg/uuidv7"
responsedto "wucher/internal/transport/http/dto/response"
)
func userRef(id []byte, name string) *responsedto.UserRef {
trimmed := strings.TrimSpace(name)
if len(id) == 0 && trimmed == "" {
return nil
}
if trimmed == "" && len(id) > 0 {
trimmed = userctx.GetDisplayName(context.TODO(), id)
}
return &responsedto.UserRef{
UUID: idString(id),
Name: trimmed,
}
}
// updatedAuditOrCreated returns the "last modified" timestamp (RFC3339) and actor for an
// audited row, falling back to the creation timestamp/actor when the row was never
// updated after creation (updated_by unset — e.g. seed/legacy rows). This guarantees an
// updated_at/updated_by is always presentable instead of silently omitted.
func updatedAuditOrCreated(updatedAt, createdAt time.Time, updatedBy []byte, updatedByName string, createdBy []byte, createdByName string) (string, *responsedto.UserRef) {
if len(updatedBy) == 0 {
updatedBy, updatedByName = createdBy, createdByName
}
if updatedAt.IsZero() {
updatedAt = createdAt
}
at := ""
if !updatedAt.IsZero() {
at = updatedAt.UTC().Format(time.RFC3339)
}
return at, userRef(updatedBy, updatedByName)
}
func actorUserID(c *fiber.Ctx) []byte {
raw := c.Locals("user_id")
userID, ok := raw.([]byte)
if !ok || len(userID) == 0 {
return nil
}
// Return a copy to avoid accidental mutation of local context values.
return append([]byte(nil), userID...)
}
// uuidStringOrEmpty resolves a user ID to their last name using the global userctx getter
// if set; otherwise falls back to the UUID string representation.
func uuidStringOrEmpty(id []byte) string {
if len(id) == 0 {
return ""
}
if name := userctx.GetDisplayName(context.TODO(), id); name != "" {
return name
}
// Fallback to UUID string when no getter is available or user not found.
val, err := uuidv7.BytesToString(id)
if err != nil {
return ""
}
return val
}
// idString converts a resource ID byte slice to a UUID string.
// Unlike uuidStringOrEmpty, this does not attempt user name resolution.
// Use this for primary keys and resource IDs, not for audit/user reference fields.
func idString(id []byte) string {
if len(id) == 0 {
return ""
}
val, err := uuidv7.BytesToString(id)
if err != nil {
return ""
}
return val
}
func timeStringOrEmpty(t *time.Time) string {
if t == nil || t.IsZero() {
return ""
}
return t.UTC().Format(time.RFC3339)
}