AHHHH Idekgit add -Agit add -A
This commit is contained in:
parent
b2df111d5a
commit
b7990488d3
3
.gitignore
vendored
3
.gitignore
vendored
@ -31,6 +31,9 @@ yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Apple Private Key
|
||||
*.p8
|
||||
|
||||
# local env files
|
||||
# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables
|
||||
.env
|
||||
|
33
package.json
33
package.json
@ -11,35 +11,42 @@
|
||||
"db:studio": "drizzle-kit studio",
|
||||
"dev": "next dev",
|
||||
"lint": "next lint",
|
||||
"start": "next start"
|
||||
"start": "next start",
|
||||
"generate-apple-secret": "tsx src/scripts/generate_apple_secret.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/drizzle-adapter": "^1.4.2",
|
||||
"@t3-oss/env-nextjs": "^0.10.1",
|
||||
"@types/jsonwebtoken": "^9.0.6",
|
||||
"dotenv": "^16.4.5",
|
||||
"drizzle-orm": "^0.30.10",
|
||||
"geist": "^1.3.0",
|
||||
"next": "^14.2.4",
|
||||
"geist": "^1.3.1",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"next": "^14.2.5",
|
||||
"next-auth": "5.0.0-beta.20",
|
||||
"postgres": "^3.4.4",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"zod": "^3.23.3"
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/eslint": "^8.56.10",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/eslint": "^8.56.11",
|
||||
"@types/node": "^20.14.14",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||
"@typescript-eslint/parser": "^7.18.0",
|
||||
"drizzle-kit": "^0.21.4",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-next": "^14.2.4",
|
||||
"eslint-config-next": "^14.2.5",
|
||||
"eslint-plugin-drizzle": "^0.2.3",
|
||||
"postcss": "^8.4.39",
|
||||
"prettier": "^3.3.2",
|
||||
"postcss": "^8.4.41",
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||
"tailwindcss": "^3.4.3",
|
||||
"typescript": "^5.5.3"
|
||||
"tailwindcss": "^3.4.8",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsx": "^4.16.5",
|
||||
"typescript": "^5.5.4"
|
||||
},
|
||||
"ct3aMetadata": {
|
||||
"initVersion": "7.36.2"
|
||||
|
533
pnpm-lock.yaml
generated
533
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -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";
|
||||
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"
|
||||
|
||||
/**
|
||||
* 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}`);
|
||||
const connectionString = process.env.DATABASE_URL ?? "";
|
||||
const pool = postgres(connectionString, { max: 1 })
|
||||
|
||||
export const posts = createTable(
|
||||
"post",
|
||||
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],
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
@ -36,7 +36,8 @@
|
||||
"**/*.tsx",
|
||||
"**/*.cjs",
|
||||
"**/*.js",
|
||||
".next/types/**/*.ts"
|
||||
".next/types/**/*.ts",
|
||||
"src/scripts/*"
|
||||
],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user