AHHHH Idekgit add -Agit add -A
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										33
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								package.json
									
									
									
									
									
								
							@@ -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"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										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 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],
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										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 {
 | 
					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: serial("id").primaryKey(),
 | 
					  id: text("id")
 | 
				
			||||||
    name: varchar("name", { length: 256 }),
 | 
					    .primaryKey()
 | 
				
			||||||
    createdAt: timestamp("created_at", { withTimezone: true })
 | 
					    .$defaultFn(() => crypto.randomUUID()),
 | 
				
			||||||
      .default(sql`CURRENT_TIMESTAMP`)
 | 
					  name: text("name"),
 | 
				
			||||||
      .notNull(),
 | 
					  email: text("email").unique(),
 | 
				
			||||||
    updatedAt: timestamp("updated_at", { withTimezone: true }).$onUpdate(
 | 
					  emailVerified: timestamp("emailVerified", { mode: "date" }),
 | 
				
			||||||
      () => new Date()
 | 
					  image: text("image"),
 | 
				
			||||||
    ),
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  (example) => ({
 | 
					 | 
				
			||||||
    nameIndex: index("name_idx").on(example.name),
 | 
					 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
);
 | 
					 
 | 
				
			||||||
 | 
					export const accounts = pgTable(
 | 
				
			||||||
 | 
					  "account",
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    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"),
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  (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",
 | 
					    "**/*.tsx",
 | 
				
			||||||
    "**/*.cjs",
 | 
					    "**/*.cjs",
 | 
				
			||||||
    "**/*.js",
 | 
					    "**/*.js",
 | 
				
			||||||
    ".next/types/**/*.ts"
 | 
					    ".next/types/**/*.ts",
 | 
				
			||||||
 | 
					    "src/scripts/*"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "exclude": ["node_modules"]
 | 
					  "exclude": ["node_modules"]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user