AHHHH Idekgit add -Agit add -A

This commit is contained in:
Gabriel Brown 2024-08-07 16:09:45 -05:00
parent b2df111d5a
commit b7990488d3
7 changed files with 686 additions and 70 deletions

3
.gitignore vendored
View File

@ -31,6 +31,9 @@ yarn-debug.log*
yarn-error.log* yarn-error.log*
.pnpm-debug.log* .pnpm-debug.log*
# Apple Private Key
*.p8
# local env files # 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 # 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 .env

View File

@ -11,35 +11,42 @@
"db:studio": "drizzle-kit studio", "db:studio": "drizzle-kit studio",
"dev": "next dev", "dev": "next dev",
"lint": "next lint", "lint": "next lint",
"start": "next start" "start": "next start",
"generate-apple-secret": "tsx src/scripts/generate_apple_secret.ts"
}, },
"dependencies": { "dependencies": {
"@auth/drizzle-adapter": "^1.4.2",
"@t3-oss/env-nextjs": "^0.10.1", "@t3-oss/env-nextjs": "^0.10.1",
"@types/jsonwebtoken": "^9.0.6",
"dotenv": "^16.4.5",
"drizzle-orm": "^0.30.10", "drizzle-orm": "^0.30.10",
"geist": "^1.3.0", "geist": "^1.3.1",
"next": "^14.2.4", "jsonwebtoken": "^9.0.2",
"next": "^14.2.5",
"next-auth": "5.0.0-beta.20", "next-auth": "5.0.0-beta.20",
"postgres": "^3.4.4", "postgres": "^3.4.4",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"zod": "^3.23.3" "zod": "^3.23.8"
}, },
"devDependencies": { "devDependencies": {
"@types/eslint": "^8.56.10", "@types/eslint": "^8.56.11",
"@types/node": "^20.14.10", "@types/node": "^20.14.14",
"@types/react": "^18.3.3", "@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.1.1", "@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.1.1", "@typescript-eslint/parser": "^7.18.0",
"drizzle-kit": "^0.21.4", "drizzle-kit": "^0.21.4",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-next": "^14.2.4", "eslint-config-next": "^14.2.5",
"eslint-plugin-drizzle": "^0.2.3", "eslint-plugin-drizzle": "^0.2.3",
"postcss": "^8.4.39", "postcss": "^8.4.41",
"prettier": "^3.3.2", "prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.5", "prettier-plugin-tailwindcss": "^0.6.5",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.8",
"typescript": "^5.5.3" "ts-node": "^10.9.2",
"tsx": "^4.16.5",
"typescript": "^5.5.4"
}, },
"ct3aMetadata": { "ct3aMetadata": {
"initVersion": "7.36.2" "initVersion": "7.36.2"

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,9 @@
import NextAuth from "next-auth" 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({ export const { handlers, signIn, signOut, auth } = NextAuth({
providers: [], adapter: DrizzleAdapter(db),
providers: [Apple],
}) })

View 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`);

View File

@ -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 { import {
index, boolean,
pgTableCreator,
serial,
timestamp, timestamp,
varchar, pgTable,
} from "drizzle-orm/pg-core"; 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 ?? "";
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same const pool = postgres(connectionString, { max: 1 })
* 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( export const db = drizzle(pool)
"post",
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(), userId: text("userId")
name: varchar("name", { length: 256 }), .notNull()
createdAt: timestamp("created_at", { withTimezone: true }) .references(() => users.id, { onDelete: "cascade" }),
.default(sql`CURRENT_TIMESTAMP`) type: text("type").$type<AdapterAccountType>().notNull(),
.notNull(), provider: text("provider").notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).$onUpdate( providerAccountId: text("providerAccountId").notNull(),
() => new Date() 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) => ({ (account) => ({
nameIndex: index("name_idx").on(example.name), 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],
}),
})
)

View File

@ -36,7 +36,8 @@
"**/*.tsx", "**/*.tsx",
"**/*.cjs", "**/*.cjs",
"**/*.js", "**/*.js",
".next/types/**/*.ts" ".next/types/**/*.ts",
"src/scripts/*"
], ],
"exclude": ["node_modules"] "exclude": ["node_modules"]
} }