feat(licenses): enhance license validation and loading state management

- Added loading state management in the EnablePaidFeatures component to improve user experience during license validation.
- Updated validateLicense function to return detailed error messages for better feedback.
- Modified user API to return validation results instead of a boolean, enhancing error handling.
- Removed unused SQL files and updated package.json scripts for better development workflow.
This commit is contained in:
Mauricio Siu
2025-03-23 12:29:55 -06:00
parent 9e30525569
commit c8e6df4c29
9 changed files with 28 additions and 224 deletions

View File

@@ -1,22 +0,0 @@
CREATE TYPE "public"."billing_type" AS ENUM('monthly', 'annual');--> statement-breakpoint
CREATE TYPE "public"."license_status" AS ENUM('active', 'expired', 'cancelled', 'payment_pending');--> statement-breakpoint
CREATE TYPE "public"."license_type" AS ENUM('basic', 'premium', 'business');--> statement-breakpoint
CREATE TABLE "licenses" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"product_id" text NOT NULL,
"license_key" text NOT NULL,
"status" "license_status" DEFAULT 'active' NOT NULL,
"type" "license_type" NOT NULL,
"billing_type" "billing_type" NOT NULL,
"server_ip" text,
"activated_at" timestamp,
"last_verified_at" timestamp,
"expires_at" timestamp NOT NULL,
"stripeCustomerId" text NOT NULL,
"stripeSubscriptionId" text NOT NULL,
"created_at" timestamp DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamp DEFAULT CURRENT_TIMESTAMP,
"metadata" text,
"email" text NOT NULL,
CONSTRAINT "licenses_license_key_unique" UNIQUE("license_key")
);

View File

@@ -1,171 +0,0 @@
{
"id": "5a996744-b11f-4f1a-b4b0-91f6bf5c2bed",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.licenses": {
"name": "licenses",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "uuid",
"primaryKey": true,
"notNull": true,
"default": "gen_random_uuid()"
},
"product_id": {
"name": "product_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"license_key": {
"name": "license_key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "license_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'active'"
},
"type": {
"name": "type",
"type": "license_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"billing_type": {
"name": "billing_type",
"type": "billing_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"server_ip": {
"name": "server_ip",
"type": "text",
"primaryKey": false,
"notNull": false
},
"activated_at": {
"name": "activated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"last_verified_at": {
"name": "last_verified_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"stripeCustomerId": {
"name": "stripeCustomerId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"stripeSubscriptionId": {
"name": "stripeSubscriptionId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "CURRENT_TIMESTAMP"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "CURRENT_TIMESTAMP"
},
"metadata": {
"name": "metadata",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"licenses_license_key_unique": {
"name": "licenses_license_key_unique",
"nullsNotDistinct": false,
"columns": [
"license_key"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"public.billing_type": {
"name": "billing_type",
"schema": "public",
"values": [
"monthly",
"annual"
]
},
"public.license_status": {
"name": "license_status",
"schema": "public",
"values": [
"active",
"expired",
"cancelled",
"payment_pending"
]
},
"public.license_type": {
"name": "license_type",
"schema": "public",
"values": [
"basic",
"premium",
"business"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,13 +1,5 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1742369437742,
"tag": "0000_noisy_epoch",
"breakpoints": true
}
]
"entries": []
}

View File

@@ -9,6 +9,7 @@
"typecheck": "tsc --noEmit",
"generate": "drizzle-kit generate",
"drop": "drizzle-kit drop",
"push": "drizzle-kit push",
"migrate": "tsx ./migrate.ts",
"truncate": "tsx ./truncate.ts",
"reset:all": "tsx ./truncate.ts && tsx ./migrate.ts",

View File

@@ -58,13 +58,12 @@ router.get("/health", async (c) => {
router.post("/validate", zValidator("json", validateSchema), async (c) => {
const { licenseKey, serverIp } = c.req.valid("json");
console.log("Validating license", licenseKey, serverIp);
try {
const result = await validateLicense(licenseKey, serverIp);
console.log("Result", result);
return c.json(result);
} catch (error) {
logger.error("Error validating license:", error);
logger.error("Error validating license:", { error });
return c.json({ isValid: false, error: "Error validating license" }, 500);
}
});
@@ -125,12 +124,7 @@ router.post("/resend-license", zValidator("json", resendSchema), async (c) => {
customerName: license.email,
}),
);
// await transporter.sendMail({
// from: fromAddress,
// to: toAddresses.join(", "),
// subject,
// html: htmlContent,
// });
await transporter.sendMail({
from: process.env.SMTP_FROM_ADDRESS,
to: license.email,
@@ -199,7 +193,7 @@ router.post("/stripe/webhook", async (c) => {
billingType,
email: session.customer_details?.email!,
stripeCustomerId: customerResponse.id,
stripeSubscriptionId: session.id,
stripeSubscriptionId: session.subscription as string,
});
console.log("License created", license);

View File

@@ -60,6 +60,8 @@ export const validateLicense = async (
license.stripeSubscriptionId,
);
console.log("Suscription", suscription);
if (suscription.status !== "active") {
return {
isValid: false,