feat(auth): include subscription tier in token and session payload
- Adds subscription tier info to access/refresh tokens. - Stores tier details in session Redis record. - Returns tier data in login/register response. - Uses default tier when user has none.
This commit is contained in:
1 parent
7f42def478
commit
d27526e026
20 files changed
+2133
-40
No files matched your search
@@ -199,6 +199,118 @@ export const registerServerCharacterSchema = z.object({
|
||||
isMain: z.boolean().optional().default(false),
|
||||
});
|
||||
|
||||
// ============================================
|
||||
// SCHEMAS DE ASSINATURAS E PERMISSÕES
|
||||
// ============================================
|
||||
|
||||
const tierSlugRegex = /^[a-z0-9-]+$/;
|
||||
const featureKeyRegex = /^[a-z0-9_.-]+$/;
|
||||
|
||||
const subscriptionTierFeatureSchema = z.object({
|
||||
featureKey: z
|
||||
.string()
|
||||
.min(2, "featureKey deve ter no mínimo 2 caracteres")
|
||||
.max(100, "featureKey deve ter no máximo 100 caracteres")
|
||||
.regex(featureKeyRegex, "featureKey deve conter apenas letras, números, ponto, hífen ou underscore")
|
||||
.transform((key) => key.trim().toLowerCase()),
|
||||
label: z
|
||||
.string()
|
||||
.min(3, "Label deve ter no mínimo 3 caracteres")
|
||||
.max(255, "Label deve ter no máximo 255 caracteres")
|
||||
.transform((value) => value.trim()),
|
||||
description: z
|
||||
.string()
|
||||
.max(500, "Descrição deve ter no máximo 500 caracteres")
|
||||
.transform((value) => value.trim())
|
||||
.optional()
|
||||
.nullable(),
|
||||
sortOrder: z.number().int().min(0).max(1000).optional(),
|
||||
});
|
||||
|
||||
export const createSubscriptionTierSchema = z
|
||||
.object({
|
||||
name: z
|
||||
.string()
|
||||
.min(3, "Nome deve ter no mínimo 3 caracteres")
|
||||
.max(100, "Nome deve ter no máximo 100 caracteres")
|
||||
.transform((value) => value.trim()),
|
||||
slug: z
|
||||
.string()
|
||||
.min(2, "Slug deve ter no mínimo 2 caracteres")
|
||||
.max(50, "Slug deve ter no máximo 50 caracteres")
|
||||
.regex(tierSlugRegex, "Slug deve conter apenas letras minúsculas, números e hífen")
|
||||
.transform((value) => value.trim().toLowerCase()),
|
||||
description: z
|
||||
.string()
|
||||
.max(500, "Descrição deve ter no máximo 500 caracteres")
|
||||
.transform((value) => value.trim())
|
||||
.optional()
|
||||
.nullable(),
|
||||
level: z.number().int().min(0).max(99).optional(),
|
||||
priceMonthly: z.number().min(0).max(100000).nullable().optional(),
|
||||
priceYearly: z.number().min(0).max(1000000).nullable().optional(),
|
||||
isActive: z.boolean().optional(),
|
||||
features: z.array(subscriptionTierFeatureSchema).max(50).optional(),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
if (
|
||||
data.priceMonthly !== undefined &&
|
||||
data.priceYearly !== undefined &&
|
||||
data.priceYearly !== null &&
|
||||
data.priceMonthly !== null
|
||||
) {
|
||||
return data.priceYearly >= data.priceMonthly;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: "Preço anual deve ser maior ou igual ao mensal",
|
||||
path: ["priceYearly"],
|
||||
}
|
||||
);
|
||||
|
||||
export const updateSubscriptionTierSchema = createSubscriptionTierSchema
|
||||
.partial()
|
||||
.extend({
|
||||
slug: z
|
||||
.string()
|
||||
.min(2, "Slug deve ter no mínimo 2 caracteres")
|
||||
.max(50, "Slug deve ter no máximo 50 caracteres")
|
||||
.regex(tierSlugRegex, "Slug deve conter apenas letras minúsculas, números e hífen")
|
||||
.transform((value) => value.trim().toLowerCase())
|
||||
.optional(),
|
||||
features: z
|
||||
.array(
|
||||
subscriptionTierFeatureSchema.extend({
|
||||
featureId: z.number().int().positive().optional(),
|
||||
_delete: z.boolean().optional(),
|
||||
})
|
||||
)
|
||||
.max(50)
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const assignSubscriptionTierSchema = z
|
||||
.object({
|
||||
userId: z.number().int().positive(),
|
||||
tierId: z.number().int().positive().nullable().optional(),
|
||||
tierSlug: z
|
||||
.string()
|
||||
.min(2, "Slug deve ter no mínimo 2 caracteres")
|
||||
.max(50, "Slug deve ter no máximo 50 caracteres")
|
||||
.regex(tierSlugRegex, "Slug deve conter apenas letras minúsculas, números e hífen")
|
||||
.transform((value) => value.trim().toLowerCase())
|
||||
.optional(),
|
||||
})
|
||||
.refine(
|
||||
(data) => data.tierId !== undefined || data.tierSlug !== undefined,
|
||||
{
|
||||
message: "Informe tierId ou tierSlug",
|
||||
path: ["tierId"],
|
||||
}
|
||||
);
|
||||
|
||||
// Schema para registro de usuário
|
||||
export const registerSchema = z.object({
|
||||
username: usernameSchema,
|
||||
|
||||
Reference in new issue
Block a user