AHHHH Idekgit add -Agit add -A
This commit is contained in:
@ -1,5 +1,9 @@
|
||||
import NextAuth from "next-auth"
|
||||
import { DrizzleAdapter } from "@auth/drizzle-adapter"
|
||||
import { db } from "~/server/db/schema"
|
||||
import Apple from "next-auth/providers/apple"
|
||||
|
||||
export const { handlers, signIn, signOut, auth } = NextAuth({
|
||||
providers: [],
|
||||
adapter: DrizzleAdapter(db),
|
||||
providers: [Apple],
|
||||
})
|
||||
|
57
src/scripts/generate_apple_secret.ts
Normal file
57
src/scripts/generate_apple_secret.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import jwt from 'jsonwebtoken';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
// Load environment variables from .env file
|
||||
dotenv.config();
|
||||
|
||||
// Type definitions for Apple Auth Configuration
|
||||
interface AppleAuthConfig {
|
||||
teamId: string;
|
||||
clientId: string;
|
||||
keyId: string;
|
||||
privateKeyPath: string;
|
||||
}
|
||||
|
||||
// Get the directory name of the current module
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const generateAppleSecret = (config: AppleAuthConfig): string => {
|
||||
const { teamId, clientId, keyId, privateKeyPath } = config;
|
||||
|
||||
const privateKey = fs.readFileSync(privateKeyPath).toString();
|
||||
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
|
||||
const payload = {
|
||||
iss: teamId,
|
||||
iat: now,
|
||||
exp: now + 86400 * 180, // 180 days
|
||||
aud: 'https://appleid.apple.com',
|
||||
sub: clientId,
|
||||
};
|
||||
|
||||
const headers = {
|
||||
alg: 'ES256',
|
||||
kid: keyId,
|
||||
};
|
||||
|
||||
return jwt.sign(payload, privateKey, { algorithm: 'ES256', header: headers });
|
||||
};
|
||||
|
||||
const config: AppleAuthConfig = {
|
||||
teamId: process.env.APPLE_TEAM_ID ?? '',
|
||||
clientId: process.env.AUTH_APPLE_ID ?? '',
|
||||
keyId: process.env.APPLE_KEY_ID ?? '',
|
||||
privateKeyPath: path.resolve(__dirname, process.env.APPLE_PRIVATE_KEY_PATH ?? ''),
|
||||
};
|
||||
|
||||
if (!config.teamId || !config.clientId || !config.keyId || !config.privateKeyPath) {
|
||||
console.error('Missing necessary Apple configuration');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const appleSecret = generateAppleSecret(config);
|
||||
console.log(`Your Apple Secret:\n\n${appleSecret}\n`);
|
@ -1,36 +1,93 @@
|
||||
// Example model schema from the Drizzle docs
|
||||
// https://orm.drizzle.team/docs/sql-schema-declaration
|
||||
|
||||
import { sql } from "drizzle-orm";
|
||||
import {
|
||||
index,
|
||||
pgTableCreator,
|
||||
serial,
|
||||
boolean,
|
||||
timestamp,
|
||||
varchar,
|
||||
} from "drizzle-orm/pg-core";
|
||||
|
||||
/**
|
||||
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
|
||||
* database instance for multiple projects.
|
||||
*
|
||||
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
|
||||
*/
|
||||
export const createTable = pgTableCreator((name) => `rent_portal_${name}`);
|
||||
|
||||
export const posts = createTable(
|
||||
"post",
|
||||
pgTable,
|
||||
text,
|
||||
primaryKey,
|
||||
integer,
|
||||
} from "drizzle-orm/pg-core"
|
||||
import postgres from "postgres"
|
||||
import { drizzle } from "drizzle-orm/postgres-js"
|
||||
import type { AdapterAccountType } from "next-auth/adapters"
|
||||
|
||||
const connectionString = process.env.DATABASE_URL ?? "";
|
||||
const pool = postgres(connectionString, { max: 1 })
|
||||
|
||||
export const db = drizzle(pool)
|
||||
|
||||
export const users = pgTable("user", {
|
||||
id: text("id")
|
||||
.primaryKey()
|
||||
.$defaultFn(() => crypto.randomUUID()),
|
||||
name: text("name"),
|
||||
email: text("email").unique(),
|
||||
emailVerified: timestamp("emailVerified", { mode: "date" }),
|
||||
image: text("image"),
|
||||
})
|
||||
|
||||
export const accounts = pgTable(
|
||||
"account",
|
||||
{
|
||||
id: serial("id").primaryKey(),
|
||||
name: varchar("name", { length: 256 }),
|
||||
createdAt: timestamp("created_at", { withTimezone: true })
|
||||
.default(sql`CURRENT_TIMESTAMP`)
|
||||
.notNull(),
|
||||
updatedAt: timestamp("updated_at", { withTimezone: true }).$onUpdate(
|
||||
() => new Date()
|
||||
),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: "cascade" }),
|
||||
type: text("type").$type<AdapterAccountType>().notNull(),
|
||||
provider: text("provider").notNull(),
|
||||
providerAccountId: text("providerAccountId").notNull(),
|
||||
refresh_token: text("refresh_token"),
|
||||
access_token: text("access_token"),
|
||||
expires_at: integer("expires_at"),
|
||||
token_type: text("token_type"),
|
||||
scope: text("scope"),
|
||||
id_token: text("id_token"),
|
||||
session_state: text("session_state"),
|
||||
},
|
||||
(example) => ({
|
||||
nameIndex: index("name_idx").on(example.name),
|
||||
(account) => ({
|
||||
compoundKey: primaryKey({
|
||||
columns: [account.provider, account.providerAccountId],
|
||||
}),
|
||||
})
|
||||
);
|
||||
)
|
||||
|
||||
export const sessions = pgTable("session", {
|
||||
sessionToken: text("sessionToken").primaryKey(),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: "cascade" }),
|
||||
expires: timestamp("expires", { mode: "date" }).notNull(),
|
||||
})
|
||||
|
||||
export const verificationTokens = pgTable(
|
||||
"verificationToken",
|
||||
{
|
||||
identifier: text("identifier").notNull(),
|
||||
token: text("token").notNull(),
|
||||
expires: timestamp("expires", { mode: "date" }).notNull(),
|
||||
},
|
||||
(verificationToken) => ({
|
||||
compositePk: primaryKey({
|
||||
columns: [verificationToken.identifier, verificationToken.token],
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
export const authenticators = pgTable(
|
||||
"authenticator",
|
||||
{
|
||||
credentialID: text("credentialID").notNull().unique(),
|
||||
userId: text("userId")
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: "cascade" }),
|
||||
providerAccountId: text("providerAccountId").notNull(),
|
||||
credentialPublicKey: text("credentialPublicKey").notNull(),
|
||||
counter: integer("counter").notNull(),
|
||||
credentialDeviceType: text("credentialDeviceType").notNull(),
|
||||
credentialBackedUp: boolean("credentialBackedUp").notNull(),
|
||||
transports: text("transports"),
|
||||
},
|
||||
(authenticator) => ({
|
||||
compositePK: primaryKey({
|
||||
columns: [authenticator.userId, authenticator.credentialID],
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
Reference in New Issue
Block a user