Move to monorepo for React Native!
This commit is contained in:
138
packages/backend/convex/auth.ts
Normal file
138
packages/backend/convex/auth.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
import { ConvexError, v } from 'convex/values';
|
||||
import {
|
||||
convexAuth,
|
||||
getAuthUserId,
|
||||
retrieveAccount,
|
||||
modifyAccountCredentials,
|
||||
} from '@convex-dev/auth/server';
|
||||
import { api } from './_generated/api';
|
||||
import { type Id } from './_generated/dataModel';
|
||||
import { action, mutation, query } from './_generated/server';
|
||||
import Password from './CustomPassword';
|
||||
|
||||
export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
|
||||
providers: [Password],
|
||||
});
|
||||
|
||||
export const PASSWORD_MIN = 8;
|
||||
export const PASSWORD_MAX = 100;
|
||||
export const PASSWORD_REGEX =
|
||||
/^(?=.{8,100}$)(?!.*\s)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\p{P}\p{S}]).*$/u;
|
||||
|
||||
export const getUser = query(async (ctx) => {
|
||||
const userId = await getAuthUserId(ctx);
|
||||
if (!userId) return null;
|
||||
const user = await ctx.db.get(userId);
|
||||
if (!user) throw new ConvexError('User not found.');
|
||||
const image: Id<'_storage'> | null =
|
||||
typeof user.image === 'string' && user.image.length > 0
|
||||
? (user.image as Id<'_storage'>)
|
||||
: null;
|
||||
return {
|
||||
id: user._id,
|
||||
email: user.email ?? null,
|
||||
name: user.name ?? null,
|
||||
image,
|
||||
};
|
||||
});
|
||||
|
||||
export const getAllUsers = query(async (ctx) => {
|
||||
const users = await ctx.db.query('users').collect();
|
||||
return users.map((u) => ({
|
||||
id: u._id,
|
||||
email: u.email ?? null,
|
||||
name: u.name ?? null,
|
||||
image: u.image ?? null,
|
||||
}));
|
||||
});
|
||||
|
||||
export const getAllUserIds = query(async (ctx) => {
|
||||
const users = await ctx.db.query('users').collect();
|
||||
const userIds = users.map((u) => u._id);
|
||||
return userIds;
|
||||
});
|
||||
|
||||
export const updateUserName = mutation({
|
||||
args: {
|
||||
name: v.string(),
|
||||
},
|
||||
handler: async (ctx, { name }) => {
|
||||
const userId = await getAuthUserId(ctx);
|
||||
if (!userId) throw new ConvexError('Not authenticated.');
|
||||
const user = await ctx.db.get(userId);
|
||||
if (!user) throw new ConvexError('User not found.');
|
||||
await ctx.db.patch(userId, { name });
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
|
||||
export const updateUserEmail = mutation({
|
||||
args: {
|
||||
email: v.string(),
|
||||
},
|
||||
handler: async (ctx, { email }) => {
|
||||
const userId = await getAuthUserId(ctx);
|
||||
if (!userId) throw new ConvexError('Not authenticated.');
|
||||
const user = await ctx.db.get(userId);
|
||||
if (!user) throw new ConvexError('User not found.');
|
||||
await ctx.db.patch(userId, { email });
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
|
||||
export const updateUserImage = mutation({
|
||||
args: {
|
||||
storageId: v.id('_storage'),
|
||||
},
|
||||
handler: async (ctx, { storageId }) => {
|
||||
const userId = await getAuthUserId(ctx);
|
||||
if (!userId) throw new ConvexError('Not authenticated.');
|
||||
const user = await ctx.db.get(userId);
|
||||
if (!user) throw new ConvexError('User not found.');
|
||||
const oldImage = user.image as Id<'_storage'> | undefined;
|
||||
await ctx.db.patch(userId, { image: storageId });
|
||||
if (oldImage && oldImage !== storageId) await ctx.storage.delete(oldImage);
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
|
||||
export const validatePassword = (password: string): boolean => {
|
||||
if (
|
||||
password.length < 8 ||
|
||||
password.length > 100 ||
|
||||
!/\d/.test(password) ||
|
||||
!/[a-z]/.test(password) ||
|
||||
!/[A-Z]/.test(password)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const updateUserPassword = action({
|
||||
args: {
|
||||
currentPassword: v.string(),
|
||||
newPassword: v.string(),
|
||||
},
|
||||
handler: async (ctx, { currentPassword, newPassword }) => {
|
||||
const userId = await getAuthUserId(ctx);
|
||||
if (!userId) throw new ConvexError('Not authenticated.');
|
||||
const user = await ctx.runQuery(api.auth.getUser);
|
||||
if (!user?.email) throw new ConvexError('User not found.');
|
||||
const verified = await retrieveAccount(ctx, {
|
||||
provider: 'password',
|
||||
account: { id: user.email, secret: currentPassword },
|
||||
});
|
||||
if (!verified) throw new ConvexError('Current password is incorrect.');
|
||||
|
||||
if (!validatePassword(newPassword))
|
||||
throw new ConvexError('Invalid password.');
|
||||
|
||||
await modifyAccountCredentials(ctx, {
|
||||
provider: 'password',
|
||||
account: { id: user.email, secret: newPassword },
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
},
|
||||
});
|
Reference in New Issue
Block a user