download count added, and other code fixed
This commit is contained in:
parent
3ab9678f71
commit
f4d4a30999
16 changed files with 247 additions and 507 deletions
|
|
@ -4,6 +4,8 @@ CREATE TABLE "projects" (
|
||||||
"object" json,
|
"object" json,
|
||||||
"name" text,
|
"name" text,
|
||||||
"description" text,
|
"description" text,
|
||||||
|
"is_active" boolean DEFAULT false NOT NULL,
|
||||||
|
"preview_url" text,
|
||||||
"created_at" timestamp DEFAULT now(),
|
"created_at" timestamp DEFAULT now(),
|
||||||
"updated_at" timestamp DEFAULT now()
|
"updated_at" timestamp DEFAULT now()
|
||||||
);
|
);
|
||||||
|
|
@ -19,9 +21,15 @@ CREATE TABLE "uploads" (
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
CREATE TABLE "users" (
|
CREATE TABLE "users" (
|
||||||
"user_id" text PRIMARY KEY NOT NULL,
|
"user_id" text PRIMARY KEY NOT NULL,
|
||||||
|
"email" text NOT NULL,
|
||||||
|
"last_name" text,
|
||||||
|
"first_name" text,
|
||||||
|
"image" text,
|
||||||
"paid_status" text,
|
"paid_status" text,
|
||||||
"expires_in" text,
|
"expires_in" text,
|
||||||
"refresh_token" text
|
"refresh_token" text,
|
||||||
|
"download_limit" integer DEFAULT 3 NOT NULL,
|
||||||
|
"downloads_today" jsonb DEFAULT '{"date":null,"count":0}'::jsonb
|
||||||
);
|
);
|
||||||
--> statement-breakpoint
|
--> statement-breakpoint
|
||||||
ALTER TABLE "projects" ADD CONSTRAINT "projects_user_id_users_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("user_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
ALTER TABLE "projects" ADD CONSTRAINT "projects_user_id_users_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("user_id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
ALTER TABLE "users" ADD COLUMN "email" text NOT NULL;--> statement-breakpoint
|
|
||||||
ALTER TABLE "users" ADD COLUMN "last_name" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "users" ADD COLUMN "first_name" text;--> statement-breakpoint
|
|
||||||
ALTER TABLE "users" ADD COLUMN "image" text;
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
ALTER TABLE "projects" ADD COLUMN "is_active" boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
|
||||||
ALTER TABLE "projects" ADD COLUMN "preview_url" text;
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"id": "a0fe5e52-63bf-4a92-adb0-ae296fb9f33e",
|
"id": "844ebb59-bcf8-407d-8eec-e1d26325a0fa",
|
||||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"dialect": "postgresql",
|
"dialect": "postgresql",
|
||||||
|
|
@ -39,6 +39,19 @@
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
|
"is_active": {
|
||||||
|
"name": "is_active",
|
||||||
|
"type": "boolean",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"preview_url": {
|
||||||
|
"name": "preview_url",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"name": "created_at",
|
"name": "created_at",
|
||||||
"type": "timestamp",
|
"type": "timestamp",
|
||||||
|
|
@ -152,6 +165,30 @@
|
||||||
"primaryKey": true,
|
"primaryKey": true,
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"last_name": {
|
||||||
|
"name": "last_name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"first_name": {
|
||||||
|
"name": "first_name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"name": "image",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
"paid_status": {
|
"paid_status": {
|
||||||
"name": "paid_status",
|
"name": "paid_status",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
|
@ -169,6 +206,20 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"primaryKey": false,
|
"primaryKey": false,
|
||||||
"notNull": false
|
"notNull": false
|
||||||
|
},
|
||||||
|
"download_limit": {
|
||||||
|
"name": "download_limit",
|
||||||
|
"type": "integer",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true,
|
||||||
|
"default": 3
|
||||||
|
},
|
||||||
|
"downloads_today": {
|
||||||
|
"name": "downloads_today",
|
||||||
|
"type": "jsonb",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false,
|
||||||
|
"default": "'{\"date\":null,\"count\":0}'::jsonb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"indexes": {},
|
"indexes": {},
|
||||||
|
|
|
||||||
|
|
@ -1,218 +0,0 @@
|
||||||
{
|
|
||||||
"id": "b6897b47-e0f0-48c5-8917-696944c8524b",
|
|
||||||
"prevId": "a0fe5e52-63bf-4a92-adb0-ae296fb9f33e",
|
|
||||||
"version": "7",
|
|
||||||
"dialect": "postgresql",
|
|
||||||
"tables": {
|
|
||||||
"public.projects": {
|
|
||||||
"name": "projects",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"project_id": {
|
|
||||||
"name": "project_id",
|
|
||||||
"type": "uuid",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "gen_random_uuid()"
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"object": {
|
|
||||||
"name": "object",
|
|
||||||
"type": "json",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"name": "description",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "now()"
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "now()"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"projects_user_id_users_user_id_fk": {
|
|
||||||
"name": "projects_user_id_users_user_id_fk",
|
|
||||||
"tableFrom": "projects",
|
|
||||||
"tableTo": "users",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.uploads": {
|
|
||||||
"name": "uploads",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "uuid",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "gen_random_uuid()"
|
|
||||||
},
|
|
||||||
"filename": {
|
|
||||||
"name": "filename",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"name": "url",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"projectId": {
|
|
||||||
"name": "projectId",
|
|
||||||
"type": "uuid",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "now()"
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "now()"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"uploads_projectId_projects_project_id_fk": {
|
|
||||||
"name": "uploads_projectId_projects_project_id_fk",
|
|
||||||
"tableFrom": "uploads",
|
|
||||||
"tableTo": "projects",
|
|
||||||
"columnsFrom": [
|
|
||||||
"projectId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"project_id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.users": {
|
|
||||||
"name": "users",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"name": "email",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"last_name": {
|
|
||||||
"name": "last_name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"first_name": {
|
|
||||||
"name": "first_name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"name": "image",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"paid_status": {
|
|
||||||
"name": "paid_status",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"expires_in": {
|
|
||||||
"name": "expires_in",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"enums": {},
|
|
||||||
"schemas": {},
|
|
||||||
"sequences": {},
|
|
||||||
"roles": {},
|
|
||||||
"policies": {},
|
|
||||||
"views": {},
|
|
||||||
"_meta": {
|
|
||||||
"columns": {},
|
|
||||||
"schemas": {},
|
|
||||||
"tables": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,231 +0,0 @@
|
||||||
{
|
|
||||||
"id": "97be3edd-38c0-499d-accc-13797e7318aa",
|
|
||||||
"prevId": "b6897b47-e0f0-48c5-8917-696944c8524b",
|
|
||||||
"version": "7",
|
|
||||||
"dialect": "postgresql",
|
|
||||||
"tables": {
|
|
||||||
"public.projects": {
|
|
||||||
"name": "projects",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"project_id": {
|
|
||||||
"name": "project_id",
|
|
||||||
"type": "uuid",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "gen_random_uuid()"
|
|
||||||
},
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"object": {
|
|
||||||
"name": "object",
|
|
||||||
"type": "json",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"name": {
|
|
||||||
"name": "name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"description": {
|
|
||||||
"name": "description",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"is_active": {
|
|
||||||
"name": "is_active",
|
|
||||||
"type": "boolean",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true,
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"preview_url": {
|
|
||||||
"name": "preview_url",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "now()"
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "now()"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"projects_user_id_users_user_id_fk": {
|
|
||||||
"name": "projects_user_id_users_user_id_fk",
|
|
||||||
"tableFrom": "projects",
|
|
||||||
"tableTo": "users",
|
|
||||||
"columnsFrom": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"user_id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.uploads": {
|
|
||||||
"name": "uploads",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"id": {
|
|
||||||
"name": "id",
|
|
||||||
"type": "uuid",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true,
|
|
||||||
"default": "gen_random_uuid()"
|
|
||||||
},
|
|
||||||
"filename": {
|
|
||||||
"name": "filename",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"name": "url",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"projectId": {
|
|
||||||
"name": "projectId",
|
|
||||||
"type": "uuid",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"created_at": {
|
|
||||||
"name": "created_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "now()"
|
|
||||||
},
|
|
||||||
"updated_at": {
|
|
||||||
"name": "updated_at",
|
|
||||||
"type": "timestamp",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false,
|
|
||||||
"default": "now()"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {
|
|
||||||
"uploads_projectId_projects_project_id_fk": {
|
|
||||||
"name": "uploads_projectId_projects_project_id_fk",
|
|
||||||
"tableFrom": "uploads",
|
|
||||||
"tableTo": "projects",
|
|
||||||
"columnsFrom": [
|
|
||||||
"projectId"
|
|
||||||
],
|
|
||||||
"columnsTo": [
|
|
||||||
"project_id"
|
|
||||||
],
|
|
||||||
"onDelete": "no action",
|
|
||||||
"onUpdate": "no action"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
},
|
|
||||||
"public.users": {
|
|
||||||
"name": "users",
|
|
||||||
"schema": "",
|
|
||||||
"columns": {
|
|
||||||
"user_id": {
|
|
||||||
"name": "user_id",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": true,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"name": "email",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
"last_name": {
|
|
||||||
"name": "last_name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"first_name": {
|
|
||||||
"name": "first_name",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"image": {
|
|
||||||
"name": "image",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"paid_status": {
|
|
||||||
"name": "paid_status",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"expires_in": {
|
|
||||||
"name": "expires_in",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
"refresh_token": {
|
|
||||||
"name": "refresh_token",
|
|
||||||
"type": "text",
|
|
||||||
"primaryKey": false,
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"indexes": {},
|
|
||||||
"foreignKeys": {},
|
|
||||||
"compositePrimaryKeys": {},
|
|
||||||
"uniqueConstraints": {},
|
|
||||||
"policies": {},
|
|
||||||
"checkConstraints": {},
|
|
||||||
"isRLSEnabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"enums": {},
|
|
||||||
"schemas": {},
|
|
||||||
"sequences": {},
|
|
||||||
"roles": {},
|
|
||||||
"policies": {},
|
|
||||||
"views": {},
|
|
||||||
"_meta": {
|
|
||||||
"columns": {},
|
|
||||||
"schemas": {},
|
|
||||||
"tables": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,22 +5,8 @@
|
||||||
{
|
{
|
||||||
"idx": 0,
|
"idx": 0,
|
||||||
"version": "7",
|
"version": "7",
|
||||||
"when": 1737876637906,
|
"when": 1739164927235,
|
||||||
"tag": "0000_tidy_echo",
|
"tag": "0000_cultured_groot",
|
||||||
"breakpoints": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 1,
|
|
||||||
"version": "7",
|
|
||||||
"when": 1737876981144,
|
|
||||||
"tag": "0001_shallow_umar",
|
|
||||||
"breakpoints": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idx": 2,
|
|
||||||
"version": "7",
|
|
||||||
"when": 1738213216210,
|
|
||||||
"tag": "0002_serious_green_goblin",
|
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ export const generateToken = async (context: any) => {
|
||||||
maxAge: 7 * 24 * 60 * 60, // 7 days in seconds
|
maxAge: 7 * 24 * 60 * 60, // 7 days in seconds
|
||||||
});
|
});
|
||||||
|
|
||||||
return { status: 201, message: "Token generated successfully", token: accessToken, userId: user?.id };
|
return { status: 201, message: "Token generated successfully", token: accessToken, user: user.user };
|
||||||
}
|
}
|
||||||
return { status: 500, message: "An error occurred while storing the refresh token" };
|
return { status: 500, message: "An error occurred while storing the refresh token" };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import Elysia, { t } from "elysia";
|
import Elysia, { t } from "elysia";
|
||||||
import { generateToken, getUserData, updateUser } from "./auth.controller";
|
import { generateToken, getUserData, updateUser } from "./auth.controller";
|
||||||
|
import { verifyAuth } from "../../middlewares/auth.middlewares";
|
||||||
|
|
||||||
export const authRoute = new Elysia({
|
export const authRoute = new Elysia({
|
||||||
prefix: "/auth",
|
prefix: "/auth",
|
||||||
|
|
@ -27,3 +28,20 @@ authRoute.post("/user/update/:userId", async ({ params: { userId }, body }) => a
|
||||||
|
|
||||||
authRoute.get("/generate-token/:userId", async (context) => await generateToken(context));
|
authRoute.get("/generate-token/:userId", async (context) => await generateToken(context));
|
||||||
|
|
||||||
|
authRoute.get("/user/me", async ({ cookie }) => {
|
||||||
|
const authData = await verifyAuth(cookie);
|
||||||
|
if (authData.status !== 200) {
|
||||||
|
return authData;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const userId: string | any = authData.userId;
|
||||||
|
const response = await getUserData(userId);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
return { ...response.data, token: authData.token, status: 200, message: "User data fetched successfully" };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
|
||||||
50
src/api/downloadCount/download.count.controller.ts
Normal file
50
src/api/downloadCount/download.count.controller.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
import { db } from "../../db";
|
||||||
|
import { users } from "../../db/schema";
|
||||||
|
|
||||||
|
export const downloadCount = async (userId: string, token: string, date: string) => {
|
||||||
|
try {
|
||||||
|
// Fetch user data
|
||||||
|
const [user] = await db.select().from(users).where(eq(users.id, userId));
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return { success: false, status: 404, message: "User not found" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the expected structure for downloads_today
|
||||||
|
type DownloadsToday = { date: string; count: number };
|
||||||
|
|
||||||
|
let downloads_today: DownloadsToday = user.downloads_today as DownloadsToday || { date: "", count: 0 };
|
||||||
|
let { download_limit } = user;
|
||||||
|
|
||||||
|
// Initialize downloads_today if not present
|
||||||
|
if (!downloads_today.date) {
|
||||||
|
downloads_today = { date, count: 1 };
|
||||||
|
}
|
||||||
|
else if (downloads_today.date !== date) {
|
||||||
|
downloads_today = { date, count: 1 }; // Reset count for a new date
|
||||||
|
}
|
||||||
|
else if ((downloads_today.count || 0) >= download_limit) {
|
||||||
|
return { success: false, status: 400, message: "Download limit reached for today", token };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
downloads_today.count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the database
|
||||||
|
await db.update(users).set({ downloads_today }).where(eq(users.id, userId));
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
success: true,
|
||||||
|
message: `Download allowed. Remaining downloads: ${download_limit - downloads_today.count}`,
|
||||||
|
downloads_today,
|
||||||
|
token,
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating download count:", error);
|
||||||
|
return { status: 500, message: "An error occurred while updating the download count", token };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
32
src/api/downloadCount/download.count.route.ts
Normal file
32
src/api/downloadCount/download.count.route.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import Elysia, { t } from "elysia";
|
||||||
|
import { verifyAuth } from "../../middlewares/auth.middlewares";
|
||||||
|
import { downloadCount } from "./download.count.controller";
|
||||||
|
|
||||||
|
export const downloadRoute = new Elysia({
|
||||||
|
prefix: "/download-count",
|
||||||
|
tags: ["Download Count"],
|
||||||
|
detail: {
|
||||||
|
description: "Routes for download count",
|
||||||
|
}
|
||||||
|
}).derive(async ({ cookie }) => {
|
||||||
|
const authData = await verifyAuth(cookie);
|
||||||
|
return { authData }; // Inject into context
|
||||||
|
})
|
||||||
|
|
||||||
|
downloadRoute.post("/", async ({ authData, body }) => {
|
||||||
|
if (authData.status !== 200)
|
||||||
|
return authData;
|
||||||
|
else {
|
||||||
|
const userId: String | any = authData.userId;
|
||||||
|
const token = authData.token;
|
||||||
|
const { date } = body;
|
||||||
|
const response = await downloadCount(userId, token, date);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
body: t.Object({
|
||||||
|
date: t.String(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2,6 +2,7 @@ import Elysia from "elysia";
|
||||||
import { projectRoutes } from "./project/project.route";
|
import { projectRoutes } from "./project/project.route";
|
||||||
import { uploadRoutes } from "./upload/upload.route";
|
import { uploadRoutes } from "./upload/upload.route";
|
||||||
import { authRoute } from "./auth/auth.route";
|
import { authRoute } from "./auth/auth.route";
|
||||||
|
import { downloadRoute } from "./downloadCount/download.count.route";
|
||||||
|
|
||||||
export const api = new Elysia({
|
export const api = new Elysia({
|
||||||
prefix: "/api",
|
prefix: "/api",
|
||||||
|
|
@ -9,4 +10,5 @@ export const api = new Elysia({
|
||||||
|
|
||||||
api.use(authRoute);
|
api.use(authRoute);
|
||||||
api.use(projectRoutes);
|
api.use(projectRoutes);
|
||||||
api.use(uploadRoutes);
|
api.use(uploadRoutes);
|
||||||
|
api.use(downloadRoute);
|
||||||
|
|
@ -5,6 +5,56 @@ import { createEmptyProject } from "../../helper/projects/createProject";
|
||||||
import { createBucket } from "../../helper/upload/createBucket";
|
import { createBucket } from "../../helper/upload/createBucket";
|
||||||
import { removeBucket } from "../../helper/upload/removeBucket";
|
import { removeBucket } from "../../helper/upload/removeBucket";
|
||||||
|
|
||||||
|
export const getAllProjects = async (userId: string, token: string) => {
|
||||||
|
try {
|
||||||
|
// Fetch all projects for the given user
|
||||||
|
const allProjects = await db.select({
|
||||||
|
id: projects.id,
|
||||||
|
name: projects.name,
|
||||||
|
description: projects.description,
|
||||||
|
preview_url: projects.preview_url,
|
||||||
|
object: projects.object,
|
||||||
|
}).from(projects).where(eq(projects.userId, userId));
|
||||||
|
|
||||||
|
// Identify projects where 'object' is empty or 'object.objects' is empty
|
||||||
|
const projectsToDelete = allProjects.filter(proj =>
|
||||||
|
(proj.object && typeof proj.object === "object" && Object.keys(proj.object).length === 0) ||
|
||||||
|
(proj.object?.objects && Array.isArray(proj.object.objects) && proj.object.objects.length === 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete projects with empty 'object' or empty 'object.objects'
|
||||||
|
await Promise.all(
|
||||||
|
projectsToDelete.map(async (proj) => {
|
||||||
|
// Step 1: Delete associated uploads first
|
||||||
|
await db.delete(uploads).where(eq(uploads.projectId, proj.id));
|
||||||
|
|
||||||
|
// Step 2: Delete the project itself
|
||||||
|
await db.delete(projects).where(eq(projects.id, proj.id));
|
||||||
|
|
||||||
|
// Step 3: Delete the associated bucket
|
||||||
|
await removeBucket(proj.id);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get remaining projects
|
||||||
|
const remainingProjects = allProjects.filter(proj =>
|
||||||
|
!(
|
||||||
|
(proj.object && typeof proj.object === "object" && Object.keys(proj.object).length === 0) ||
|
||||||
|
(proj.object?.objects && Array.isArray(proj.object.objects) && proj.object.objects.length === 0)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (remainingProjects.length === 0) {
|
||||||
|
return { status: 404, message: "No projects found", token };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { status: 200, message: "Projects fetched successfully", data: remainingProjects, token };
|
||||||
|
} catch (error: any) {
|
||||||
|
console.log(error.message);
|
||||||
|
return { status: 500, message: "An error occurred while fetching projects", token };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const getEachProjects = async (id: string, token: string) => {
|
export const getEachProjects = async (id: string, token: string) => {
|
||||||
try {
|
try {
|
||||||
const project = await db.select({
|
const project = await db.select({
|
||||||
|
|
@ -24,28 +74,6 @@ export const getEachProjects = async (id: string, token: string) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAllProjects = async (userId: string, token: string) => {
|
|
||||||
try {
|
|
||||||
// Fetch all projects for the given user
|
|
||||||
const allProjects = await db.select({
|
|
||||||
id: projects.id,
|
|
||||||
name: projects.name,
|
|
||||||
description: projects.description,
|
|
||||||
preview_url: projects.preview_url,
|
|
||||||
object: projects.object,
|
|
||||||
}).from(projects).where(eq(projects.userId, userId));
|
|
||||||
|
|
||||||
if (allProjects.length === 0) {
|
|
||||||
return { status: 404, message: "No projects found", token };
|
|
||||||
}
|
|
||||||
|
|
||||||
return { status: 200, message: "Projects fetched successfully", data: allProjects, token };
|
|
||||||
} catch (error: any) {
|
|
||||||
console.log(error.message);
|
|
||||||
return { status: 500, message: "An error occurred while fetching projects", token };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createProject = async (userId: string, token: string) => {
|
export const createProject = async (userId: string, token: string) => {
|
||||||
try {
|
try {
|
||||||
const { id } = await createEmptyProject(userId);
|
const { id } = await createEmptyProject(userId);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,10 @@ const allowedOrigins = [
|
||||||
"https://your-production-site.com",
|
"https://your-production-site.com",
|
||||||
];
|
];
|
||||||
|
|
||||||
const app = new Elysia()
|
const app = new Elysia({
|
||||||
|
prefix: "",
|
||||||
|
tags: ["Default"],
|
||||||
|
})
|
||||||
.use(cors({
|
.use(cors({
|
||||||
origin: allowedOrigins,
|
origin: allowedOrigins,
|
||||||
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"],
|
methods: ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"],
|
||||||
|
|
@ -46,6 +49,10 @@ const app = new Elysia()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
app.get("/", () => {
|
||||||
|
return "Hello from PlanPostAI Canvas API";
|
||||||
|
});
|
||||||
|
|
||||||
// all routes here
|
// all routes here
|
||||||
app.use(api);
|
app.use(api);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { boolean, json, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
|
import { boolean, integer, json, pgTable, text, timestamp, uuid, jsonb } from "drizzle-orm/pg-core";
|
||||||
|
|
||||||
export const users = pgTable("users", {
|
export const users = pgTable("users", {
|
||||||
id: text("user_id").primaryKey().notNull(),
|
id: text("user_id").primaryKey().notNull(),
|
||||||
|
|
@ -9,6 +9,8 @@ export const users = pgTable("users", {
|
||||||
paid_status: text("paid_status"),
|
paid_status: text("paid_status"),
|
||||||
expires_in: text("expires_in"),
|
expires_in: text("expires_in"),
|
||||||
refresh_token: text("refresh_token"),
|
refresh_token: text("refresh_token"),
|
||||||
|
download_limit: integer("download_limit").notNull().default(3),
|
||||||
|
downloads_today: jsonb("downloads_today").default({ date: null, count: 0 }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const projects = pgTable("projects", {
|
export const projects = pgTable("projects", {
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,27 @@ type User = {
|
||||||
// this will check the user into our local canvas database
|
// this will check the user into our local canvas database
|
||||||
export const checkUserInDB = async (id: string) => {
|
export const checkUserInDB = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
const user = await db.select().from(users).where(eq(users.id, id));
|
const user = await db
|
||||||
if (user.length > 0) {
|
.select({
|
||||||
return { found: true, id: user[0]?.id };
|
email: users.email,
|
||||||
}
|
lastName: users.lastName,
|
||||||
else {
|
firstName: users.firstName,
|
||||||
return { found: false };
|
image: users.image,
|
||||||
}
|
paidStatus: users.paid_status,
|
||||||
|
expiresIn: users.expires_in,
|
||||||
|
download_limit: users.download_limit,
|
||||||
|
download_today: users.downloads_today
|
||||||
|
})
|
||||||
|
.from(users)
|
||||||
|
.where(eq(users.id, id));
|
||||||
|
|
||||||
|
return user.length > 0
|
||||||
|
? { found: true, user: user[0] }
|
||||||
|
: { found: false };
|
||||||
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("Error in checkUserInDB:", error.message || error.toString());
|
console.error("Error in checkUserInDB:", error.message || error.toString());
|
||||||
return { status: 500, message: `An error occurred while checking the user in DB` };
|
return { status: 500, message: "An error occurred while checking the user in DB" };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue