chore: update database schema and enhance authentication features
- Add `username` column to the `user` table and enforce uniqueness constraint. - Introduce new SQL migration file for the `username` addition. - Update `schema.ts` to reflect changes in the `user`, `session`, and `account` tables. - Enhance authentication client by integrating `usernameClient` plugin for better user management. - Adjust session management settings for improved caching and freshness. - Refactor metadata generation in the home page for consistency.
This commit is contained in:
parent
0045ecf91e
commit
2ba2eebbaa
@ -15,7 +15,8 @@
|
|||||||
"build/**",
|
"build/**",
|
||||||
"src/components/ui/*.tsx",
|
"src/components/ui/*.tsx",
|
||||||
"src/components/magicui/*.tsx",
|
"src/components/magicui/*.tsx",
|
||||||
"tailwind.config.ts"
|
"tailwind.config.ts",
|
||||||
|
"src/db/schema.ts"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"formatter": {
|
"formatter": {
|
||||||
@ -52,7 +53,8 @@
|
|||||||
"build/**",
|
"build/**",
|
||||||
"src/components/ui/*.tsx",
|
"src/components/ui/*.tsx",
|
||||||
"src/components/magicui/*.tsx",
|
"src/components/magicui/*.tsx",
|
||||||
"tailwind.config.ts"
|
"tailwind.config.ts",
|
||||||
|
"src/db/schema.ts"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"javascript": {
|
"javascript": {
|
||||||
|
2
drizzle/0002_talented_greymalkin.sql
Normal file
2
drizzle/0002_talented_greymalkin.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "user" ADD COLUMN "username" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "user" ADD CONSTRAINT "user_username_unique" UNIQUE("username");
|
362
drizzle/meta/0002_snapshot.json
Normal file
362
drizzle/meta/0002_snapshot.json
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
{
|
||||||
|
"id": "21c4862e-1256-46f8-ac51-312d90aa61f8",
|
||||||
|
"prevId": "53387f51-ed0d-4c44-b8ed-5af936eef75e",
|
||||||
|
"version": "7",
|
||||||
|
"dialect": "postgresql",
|
||||||
|
"tables": {
|
||||||
|
"public.account": {
|
||||||
|
"name": "account",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"account_id": {
|
||||||
|
"name": "account_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"provider_id": {
|
||||||
|
"name": "provider_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"access_token": {
|
||||||
|
"name": "access_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"refresh_token": {
|
||||||
|
"name": "refresh_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"id_token": {
|
||||||
|
"name": "id_token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"access_token_expires_at": {
|
||||||
|
"name": "access_token_expires_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"refresh_token_expires_at": {
|
||||||
|
"name": "refresh_token_expires_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"name": "scope",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"name": "password",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"account_user_id_user_id_fk": {
|
||||||
|
"name": "account_user_id_user_id_fk",
|
||||||
|
"tableFrom": "account",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.session": {
|
||||||
|
"name": "session",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"token": {
|
||||||
|
"name": "token",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"ip_address": {
|
||||||
|
"name": "ip_address",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"user_agent": {
|
||||||
|
"name": "user_agent",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"user_id": {
|
||||||
|
"name": "user_id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"impersonated_by": {
|
||||||
|
"name": "impersonated_by",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {
|
||||||
|
"session_user_id_user_id_fk": {
|
||||||
|
"name": "session_user_id_user_id_fk",
|
||||||
|
"tableFrom": "session",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsFrom": [
|
||||||
|
"user_id"
|
||||||
|
],
|
||||||
|
"columnsTo": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"onDelete": "cascade",
|
||||||
|
"onUpdate": "no action"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"session_token_unique": {
|
||||||
|
"name": "session_token_unique",
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"columns": [
|
||||||
|
"token"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.user": {
|
||||||
|
"name": "user",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"name": "name",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"email": {
|
||||||
|
"name": "email",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"email_verified": {
|
||||||
|
"name": "email_verified",
|
||||||
|
"type": "boolean",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"name": "image",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"name": "username",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"name": "role",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"banned": {
|
||||||
|
"name": "banned",
|
||||||
|
"type": "boolean",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"ban_reason": {
|
||||||
|
"name": "ban_reason",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"ban_expires": {
|
||||||
|
"name": "ban_expires",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {
|
||||||
|
"user_email_unique": {
|
||||||
|
"name": "user_email_unique",
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"columns": [
|
||||||
|
"email"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"user_username_unique": {
|
||||||
|
"name": "user_username_unique",
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"columns": [
|
||||||
|
"username"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
},
|
||||||
|
"public.verification": {
|
||||||
|
"name": "verification",
|
||||||
|
"schema": "",
|
||||||
|
"columns": {
|
||||||
|
"id": {
|
||||||
|
"name": "id",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": true,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"identifier": {
|
||||||
|
"name": "identifier",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"value": {
|
||||||
|
"name": "value",
|
||||||
|
"type": "text",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"expires_at": {
|
||||||
|
"name": "expires_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"name": "created_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"name": "updated_at",
|
||||||
|
"type": "timestamp",
|
||||||
|
"primaryKey": false,
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"indexes": {},
|
||||||
|
"foreignKeys": {},
|
||||||
|
"compositePrimaryKeys": {},
|
||||||
|
"uniqueConstraints": {},
|
||||||
|
"policies": {},
|
||||||
|
"checkConstraints": {},
|
||||||
|
"isRLSEnabled": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"enums": {},
|
||||||
|
"schemas": {},
|
||||||
|
"sequences": {},
|
||||||
|
"roles": {},
|
||||||
|
"policies": {},
|
||||||
|
"views": {},
|
||||||
|
"_meta": {
|
||||||
|
"columns": {},
|
||||||
|
"schemas": {},
|
||||||
|
"tables": {}
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,13 @@
|
|||||||
"when": 1740323860731,
|
"when": 1740323860731,
|
||||||
"tag": "0001_shocking_wild_pack",
|
"tag": "0001_shocking_wild_pack",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 2,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1741971106943,
|
||||||
|
"tag": "0002_talented_greymalkin",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -26,7 +26,7 @@ export async function generateMetadata({
|
|||||||
return constructMetadata({
|
return constructMetadata({
|
||||||
title: t('title'),
|
title: t('title'),
|
||||||
description: t('description'),
|
description: t('description'),
|
||||||
canonicalUrl: `${getBaseUrlWithLocale(locale)}/`,
|
canonicalUrl: `${getBaseUrlWithLocale(locale)}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
107
src/db/schema.ts
107
src/db/schema.ts
@ -1,62 +1,53 @@
|
|||||||
import {
|
import { pgTable, text, integer, timestamp, boolean } from "drizzle-orm/pg-core";
|
||||||
pgTable,
|
|
||||||
text,
|
|
||||||
integer,
|
|
||||||
timestamp,
|
|
||||||
boolean,
|
|
||||||
} from 'drizzle-orm/pg-core';
|
|
||||||
|
|
||||||
export const user = pgTable('user', {
|
export const user = pgTable("user", {
|
||||||
id: text('id').primaryKey(),
|
id: text("id").primaryKey(),
|
||||||
name: text('name').notNull(),
|
name: text('name').notNull(),
|
||||||
email: text('email').notNull().unique(),
|
email: text('email').notNull().unique(),
|
||||||
emailVerified: boolean('email_verified').notNull(),
|
emailVerified: boolean('email_verified').notNull(),
|
||||||
image: text('image'),
|
image: text('image'),
|
||||||
createdAt: timestamp('created_at').notNull(),
|
createdAt: timestamp('created_at').notNull(),
|
||||||
updatedAt: timestamp('updated_at').notNull(),
|
updatedAt: timestamp('updated_at').notNull(),
|
||||||
role: text('role'),
|
username: text('username').unique(),
|
||||||
banned: boolean('banned'),
|
role: text('role'),
|
||||||
banReason: text('ban_reason'),
|
banned: boolean('banned'),
|
||||||
banExpires: timestamp('ban_expires'),
|
banReason: text('ban_reason'),
|
||||||
});
|
banExpires: timestamp('ban_expires')
|
||||||
|
});
|
||||||
|
|
||||||
export const session = pgTable('session', {
|
export const session = pgTable("session", {
|
||||||
id: text('id').primaryKey(),
|
id: text("id").primaryKey(),
|
||||||
expiresAt: timestamp('expires_at').notNull(),
|
expiresAt: timestamp('expires_at').notNull(),
|
||||||
token: text('token').notNull().unique(),
|
token: text('token').notNull().unique(),
|
||||||
createdAt: timestamp('created_at').notNull(),
|
createdAt: timestamp('created_at').notNull(),
|
||||||
updatedAt: timestamp('updated_at').notNull(),
|
updatedAt: timestamp('updated_at').notNull(),
|
||||||
ipAddress: text('ip_address'),
|
ipAddress: text('ip_address'),
|
||||||
userAgent: text('user_agent'),
|
userAgent: text('user_agent'),
|
||||||
userId: text('user_id')
|
userId: text('user_id').notNull().references(()=> user.id, { onDelete: 'cascade' }),
|
||||||
.notNull()
|
impersonatedBy: text('impersonated_by')
|
||||||
.references(() => user.id, { onDelete: 'cascade' }),
|
});
|
||||||
impersonatedBy: text('impersonated_by'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const account = pgTable('account', {
|
export const account = pgTable("account", {
|
||||||
id: text('id').primaryKey(),
|
id: text("id").primaryKey(),
|
||||||
accountId: text('account_id').notNull(),
|
accountId: text('account_id').notNull(),
|
||||||
providerId: text('provider_id').notNull(),
|
providerId: text('provider_id').notNull(),
|
||||||
userId: text('user_id')
|
userId: text('user_id').notNull().references(()=> user.id, { onDelete: 'cascade' }),
|
||||||
.notNull()
|
accessToken: text('access_token'),
|
||||||
.references(() => user.id, { onDelete: 'cascade' }),
|
refreshToken: text('refresh_token'),
|
||||||
accessToken: text('access_token'),
|
idToken: text('id_token'),
|
||||||
refreshToken: text('refresh_token'),
|
accessTokenExpiresAt: timestamp('access_token_expires_at'),
|
||||||
idToken: text('id_token'),
|
refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
|
||||||
accessTokenExpiresAt: timestamp('access_token_expires_at'),
|
scope: text('scope'),
|
||||||
refreshTokenExpiresAt: timestamp('refresh_token_expires_at'),
|
password: text('password'),
|
||||||
scope: text('scope'),
|
createdAt: timestamp('created_at').notNull(),
|
||||||
password: text('password'),
|
updatedAt: timestamp('updated_at').notNull()
|
||||||
createdAt: timestamp('created_at').notNull(),
|
});
|
||||||
updatedAt: timestamp('updated_at').notNull(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const verification = pgTable('verification', {
|
export const verification = pgTable("verification", {
|
||||||
id: text('id').primaryKey(),
|
id: text("id").primaryKey(),
|
||||||
identifier: text('identifier').notNull(),
|
identifier: text('identifier').notNull(),
|
||||||
value: text('value').notNull(),
|
value: text('value').notNull(),
|
||||||
expiresAt: timestamp('expires_at').notNull(),
|
expiresAt: timestamp('expires_at').notNull(),
|
||||||
createdAt: timestamp('created_at'),
|
createdAt: timestamp('created_at'),
|
||||||
updatedAt: timestamp('updated_at'),
|
updatedAt: timestamp('updated_at')
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createAuthClient } from 'better-auth/react';
|
import { createAuthClient } from 'better-auth/react';
|
||||||
import { adminClient } from 'better-auth/client/plugins';
|
import { adminClient, usernameClient } from 'better-auth/client/plugins';
|
||||||
import { getBaseUrl } from './urls/get-base-url';
|
import { getBaseUrl } from './urls/get-base-url';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8,6 +8,8 @@ import { getBaseUrl } from './urls/get-base-url';
|
|||||||
export const authClient = createAuthClient({
|
export const authClient = createAuthClient({
|
||||||
baseURL: getBaseUrl(),
|
baseURL: getBaseUrl(),
|
||||||
plugins: [
|
plugins: [
|
||||||
|
// https://www.better-auth.com/docs/plugins/username
|
||||||
|
usernameClient(),
|
||||||
// https://www.better-auth.com/docs/plugins/admin#add-the-client-plugin
|
// https://www.better-auth.com/docs/plugins/admin#add-the-client-plugin
|
||||||
adminClient(),
|
adminClient(),
|
||||||
],
|
],
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
import { getWebsiteInfo } from '@/config';
|
|
||||||
import db from '@/db/index';
|
import db from '@/db/index';
|
||||||
import { account, session, user, verification } from '@/db/schema';
|
import { account, session, user, verification } from '@/db/schema';
|
||||||
import { createTranslator } from '@/i18n/translator';
|
|
||||||
import { getLocaleFromRequest } from '@/lib/utils';
|
import { getLocaleFromRequest } from '@/lib/utils';
|
||||||
import { send } from '@/mail';
|
import { send } from '@/mail';
|
||||||
import { betterAuth } from 'better-auth';
|
import { betterAuth } from 'better-auth';
|
||||||
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
|
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
|
||||||
import { admin } from 'better-auth/plugins';
|
import { admin, username } from 'better-auth/plugins';
|
||||||
|
|
||||||
// Create a simple translator function for default values
|
|
||||||
const t = createTranslator((key: string) => key);
|
|
||||||
const websiteInfo = getWebsiteInfo(t);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://www.better-auth.com/docs/reference/options
|
||||||
|
*/
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
appName: websiteInfo.name,
|
appName: 'MkSaaS',
|
||||||
database: drizzleAdapter(db, {
|
database: drizzleAdapter(db, {
|
||||||
provider: 'pg', // or "mysql", "sqlite"
|
provider: 'pg', // or "mysql", "sqlite"
|
||||||
// The schema object that defines the tables and fields
|
// The schema object that defines the tables and fields
|
||||||
// [BetterAuthError]: [# Drizzle Adapter]: The model "verification" was not found in the schema object.
|
// [BetterAuthError]: [# Drizzle Adapter]: The model "verification" was not found in the schema object.
|
||||||
// Please pass the schema directly to the adapter options.
|
// Please pass the schema directly to the adapter options.
|
||||||
|
// https://www.better-auth.com/docs/adapters/drizzle#additional-information
|
||||||
schema: {
|
schema: {
|
||||||
user: user,
|
user: user,
|
||||||
session: session,
|
session: session,
|
||||||
@ -30,12 +28,13 @@ export const auth = betterAuth({
|
|||||||
// https://www.better-auth.com/docs/concepts/session-management#cookie-cache
|
// https://www.better-auth.com/docs/concepts/session-management#cookie-cache
|
||||||
cookieCache: {
|
cookieCache: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
maxAge: 5 * 60, // Cache duration in seconds
|
maxAge: 60 * 60, // Cache duration in seconds
|
||||||
},
|
},
|
||||||
// https://www.better-auth.com/docs/concepts/session-management#session-expiration
|
// https://www.better-auth.com/docs/concepts/session-management#session-expiration
|
||||||
expiresIn: 60 * 60 * 24 * 7,
|
expiresIn: 60 * 60 * 24 * 7,
|
||||||
updateAge: 60 * 60 * 24,
|
updateAge: 60 * 60 * 24,
|
||||||
freshAge: 60 * 5,
|
// https://www.better-auth.com/docs/concepts/session-management#session-freshness
|
||||||
|
freshAge: 60 * 60 * 24,
|
||||||
},
|
},
|
||||||
emailAndPassword: {
|
emailAndPassword: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
@ -44,7 +43,6 @@ export const auth = betterAuth({
|
|||||||
// https://www.better-auth.com/docs/authentication/email-password#forget-password
|
// https://www.better-auth.com/docs/authentication/email-password#forget-password
|
||||||
async sendResetPassword({ user, url }, request) {
|
async sendResetPassword({ user, url }, request) {
|
||||||
const locale = getLocaleFromRequest(request);
|
const locale = getLocaleFromRequest(request);
|
||||||
console.log('sendResetPassword, locale:', locale);
|
|
||||||
await send({
|
await send({
|
||||||
to: user.email,
|
to: user.email,
|
||||||
template: 'forgotPassword',
|
template: 'forgotPassword',
|
||||||
@ -62,7 +60,6 @@ export const auth = betterAuth({
|
|||||||
// https://www.better-auth.com/docs/authentication/email-password#require-email-verification
|
// https://www.better-auth.com/docs/authentication/email-password#require-email-verification
|
||||||
sendVerificationEmail: async ({ user, url, token }, request) => {
|
sendVerificationEmail: async ({ user, url, token }, request) => {
|
||||||
const locale = getLocaleFromRequest(request);
|
const locale = getLocaleFromRequest(request);
|
||||||
console.log('sendVerificationEmail, locale:', locale);
|
|
||||||
await send({
|
await send({
|
||||||
to: user.email,
|
to: user.email,
|
||||||
template: 'verifyEmail',
|
template: 'verifyEmail',
|
||||||
@ -93,8 +90,26 @@ export const auth = betterAuth({
|
|||||||
trustedProviders: ['google', 'github'],
|
trustedProviders: ['google', 'github'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
user: {
|
||||||
|
// https://www.better-auth.com/docs/concepts/users-accounts#delete-user
|
||||||
|
deleteUser: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
// https://www.better-auth.com/docs/plugins/username
|
||||||
|
username({
|
||||||
|
minUsernameLength: 3,
|
||||||
|
maxUsernameLength: 30,
|
||||||
|
}),
|
||||||
// https://www.better-auth.com/docs/plugins/admin
|
// https://www.better-auth.com/docs/plugins/admin
|
||||||
admin(),
|
admin(),
|
||||||
],
|
],
|
||||||
|
onAPIError: {
|
||||||
|
// https://www.better-auth.com/docs/reference/options#onapierror
|
||||||
|
errorURL: '/auth/error',
|
||||||
|
onError: (error, ctx) => {
|
||||||
|
console.error('auth error:', error);
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user