Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bun.lockb
Binary file not shown.
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"db:migrate": "drizzle-kit migrate"
},
"dependencies": {
"@auth/drizzle-adapter": "^1.2.0",
"@libsql/client": "^0.6.2",
"@auth/drizzle-adapter": "^1.1.0",
"@libsql/client": "^0.6.0",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-icons": "^1.3.0",
Expand All @@ -33,11 +33,11 @@
"drizzle-orm": "^0.30.10",
"libsql": "^0.3.18",
"lucide-react": "^0.379.0",
"next": "14.2.3",
"next-auth": "beta",
"next": "14.2.4",
"next-auth": "5.0.0-beta.18",
"next-themes": "^0.3.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "^18.3.0",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"resend": "^3.2.0",
"tailwind-merge": "^2.3.0",
Expand All @@ -46,21 +46,21 @@
},
"devDependencies": {
"@types/bcryptjs": "^2.4.6",
"@types/node": "^20.13.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"autoprefixer": "^10.4.19",
"drizzle-kit": "^0.21.4",
"eslint": "^8.57.0",
"eslint-config-next": "14.2.3",
"eslint": "^8",
"eslint-config-next": "14.2.4",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"husky": "^9.0.11",
"lint-staged": "^15.2.5",
"postcss": "^8.4.38",
"prettier": "^3.3.0",
"prettier-plugin-tailwindcss": "^0.5.14",
"tailwindcss": "^3.4.3",
"lint-staged": "^15.2.4",
"postcss": "^8",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.6.3",
"tailwindcss": "^3.4.4",
"typescript": "^5.4.5"
}
}
}
14 changes: 14 additions & 0 deletions src/actions/auth/delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use server';

import { deleteUser } from '@/db/query/User';
import { signOut } from '@/auth';
import { redirect } from 'next/navigation';
import { revalidatePath } from 'next/cache';

// =============================== deleteAccount ===============================
export async function deleteAccount(userId: string) {
await deleteUser(userId);
await signOut();
revalidatePath('/', 'layout');
redirect('/');
}
5 changes: 5 additions & 0 deletions src/actions/auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './oauth';
export * from './signin';
export * from './signup';
export * from './password';
export * from './delete';
23 changes: 23 additions & 0 deletions src/actions/auth/oauth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use server';

import { signIn } from '@/auth';
import { redirect } from 'next/navigation';

import { deleteUserAccount } from '@/db/query/User';
import { revalidatePath } from 'next/cache';

// =============================== Oauth Login ===============================
export async function oAuthLogin(provider: string) {
let user = '/';
user = await signIn(provider, {
redirect: false,
});

if (user) redirect(user);
}

// =============================== Oauth Remove ===============================
export async function oAuthRemove(userId: string, provider: string) {
await deleteUserAccount(userId, provider);
revalidatePath('/', 'layout');
}
230 changes: 2 additions & 228 deletions src/actions/authAction.ts → src/actions/auth/password.ts
Original file line number Diff line number Diff line change
@@ -1,230 +1,12 @@
'use server';

import {
createTokenForAddPassword,
createTokenForCreateUser,
createTokenForForgotPassword,
deleteToken,
} from '@/db/query/Token';
import {
addPasswordWithAccount,
createUser,
deleteUser,
savePassword,
deleteUserAccount,
} from '@/db/query/User';
import { addPasswordWithAccount, savePassword } from '@/db/query/User';
import { z } from 'zod';
import { signIn as signInUser, signOut } from '@/auth';
import { redirect } from 'next/navigation';
import { revalidatePath } from 'next/cache';

// =============================== Oauth Login ===============================
export async function oAuthLogin(provider: string) {
let user = '/';
user = await signInUser(provider, {
redirect: true,
});

if (user) redirect(user);
}

// =============================== Oauth Remove ===============================
export async function oAuthRemove(userId: string, provider: string) {
await deleteUserAccount(userId, provider);
revalidatePath('/', 'layout');
}

// =============================== signUp ===============================
const signUpSchema = z.object({
email: z.string().email('Please enter valid email address.').min(5),
});
export async function signUp(prevState: any, formData: FormData) {
const validatedFields = signUpSchema.safeParse({
email: formData.get('email'),
});

// Return early if the form data is invalid
if (!validatedFields.success) {
return {
type: 'error',
errors: validatedFields.error.flatten().fieldErrors,
message: 'Missing Fields!!',
resetKey: '',
};
}

try {
let emailData = await createTokenForCreateUser(validatedFields.data.email);

if (!emailData.success) {
return {
type: 'error',
errors: {
email: undefined,
},
message: 'Failed to signUp.',
resetKey: '',
};
}

return {
type: 'success',
errors: null,
message: 'Please check your email for next step',
resetKey: Date.now().toString(),
};
} catch (error: any) {
console.error('Failed to signUp', error);
return {
type: 'error',
errors: {
email: undefined,
},
message: error.message || 'Failed to signUp.',
resetKey: '',
};
}
}

// =============================== signUp > onBoarding ===============================
const onBoardingSchema = z.object({
name: z.string().min(2, { message: 'Must be 2 or more characters long' }),
username: z.string().min(3, { message: 'Must be 3 or more characters long' }),
email: z.string().email('Please enter valid email address.').min(5),
password: z.string().min(8, { message: 'Must be 8 or more characters long' }),
password2: z.string(),
});
export async function onBoarding(
email: string,
prevState: any,
formData: FormData,
) {
const validatedFields = onBoardingSchema.safeParse({
name: formData.get('name'),
email: email,
username: formData.get('username'),
password: formData.get('password'),
password2: formData.get('password2'),
});

// Return early if the form data is invalid
if (!validatedFields.success) {
return {
type: 'error',
errors: validatedFields.error.flatten().fieldErrors,
message: 'Missing Fields!!',
};
}

// check for password match
if (validatedFields.data.password !== validatedFields.data.password2) {
return {
type: 'error',
errors: {
name: undefined,
username: undefined,
email: undefined,
password: undefined,
password2: undefined,
},
message: 'Passwords do not match.',
};
}

try {
let user = await createUser(
validatedFields.data.name,
email,
validatedFields.data.username,
validatedFields.data.password,
);

if (user.length === 0) {
return {
type: 'error',
errors: {
name: undefined,
username: undefined,
email: undefined,
password: undefined,
password2: undefined,
},
message: 'Failed to signUp. Please try again.',
};
}

// delete the token
await deleteToken(email);

return {
type: 'success',
errors: null,
message: 'Successfully signed up.',
};
} catch (error: any) {
console.error('Failed to signUp', error);
return {
type: 'error',
errors: {
name: undefined,
username: undefined,
email: undefined,
password: undefined,
password2: undefined,
},
message: error.message || 'Failed to signUp.',
};
}
}

// =============================== signIn ===============================
const signInSchema = z.object({
username: z.string().min(3, { message: 'Must be 3 or more characters long' }),
password: z.string().min(8, { message: 'Must be 8 or more characters long' }),
});
export async function signIn(prevState: any, formData: FormData) {
const validatedFields = signInSchema.safeParse({
username: formData.get('username'),
password: formData.get('password'),
});

// Return early if the form data is invalid
if (!validatedFields.success) {
return {
type: 'error',
errors: validatedFields.error.flatten().fieldErrors,
message: 'Missing Fields!!',
};
}

try {
await signInUser('credentials', {
username: validatedFields.data.username,
password: validatedFields.data.password,
redirect: false,
});
} catch (error: any) {
if (error.code === 'invalid-credentials') {
return {
type: 'error',
errors: {
username: undefined,
password: undefined,
},
message: error.message,
};
} else {
return {
type: 'error',
errors: {
username: undefined,
password: undefined,
},
message: 'Something went wrong. Please try again.',
};
}
}
redirect('/profile');
}

// =============================== forgotPassword ===============================
const forgetPasswordSchema = z.object({
Expand Down Expand Up @@ -523,11 +305,3 @@ export async function changePassword(
};
}
}

// =============================== deleteAccount ===============================
export async function deleteAccount(userId: string) {
await deleteUser(userId);
await signOut();
revalidatePath('/', 'layout');
redirect('/');
}
Loading