Add automatic lunch feature. Clean up some code.
This commit is contained in:
@@ -7,7 +7,13 @@ import {
|
||||
} from '@convex-dev/auth/server';
|
||||
import { api } from './_generated/api';
|
||||
import { type Id } from './_generated/dataModel';
|
||||
import { action, mutation, query } from './_generated/server';
|
||||
import {
|
||||
action,
|
||||
mutation,
|
||||
query,
|
||||
type MutationCtx,
|
||||
type QueryCtx,
|
||||
} from './_generated/server';
|
||||
import Authentik from '@auth/core/providers/authentik';
|
||||
import { Entra, Password, validatePassword } from './custom/auth';
|
||||
|
||||
@@ -24,127 +30,116 @@ 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;
|
||||
type RWCtx = MutationCtx | QueryCtx;
|
||||
type User = {
|
||||
id: Id<'users'>;
|
||||
email: string | null;
|
||||
name: string | null;
|
||||
image: Id<'_storage'> | null;
|
||||
lunchTime: string | null;
|
||||
automaticLunch: boolean;
|
||||
provider: string | null;
|
||||
};
|
||||
|
||||
const getUserData = async (ctx: RWCtx, userId: Id<'users'>): Promise<User> => {
|
||||
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;
|
||||
const authAccount = await ctx.db
|
||||
|
||||
const authAccount = await getUserAuthAccountData(ctx, userId);
|
||||
|
||||
return {
|
||||
id: user._id,
|
||||
email: user.email ?? null,
|
||||
name: user.name ?? null,
|
||||
image,
|
||||
lunchTime: user.lunchTime ?? null,
|
||||
automaticLunch: user.automaticLunch ?? false,
|
||||
provider: authAccount?.provider ?? null,
|
||||
};
|
||||
};
|
||||
|
||||
const getUserAuthAccountData = async (ctx: RWCtx, userId: Id<'users'>) => {
|
||||
const user = await ctx.db.get(userId);
|
||||
if (!user) throw new ConvexError('User not found.');
|
||||
const authAccountData = await ctx.db
|
||||
.query('authAccounts')
|
||||
.withIndex('userIdAndProvider', (q) => q.eq('userId', userId))
|
||||
.first();
|
||||
return {
|
||||
id: user._id,
|
||||
email: user?.email,
|
||||
name: user?.name,
|
||||
image,
|
||||
lunchTime: user?.lunchTime,
|
||||
automaticLunch: user.automaticLunch,
|
||||
provider: authAccount?.provider,
|
||||
};
|
||||
return authAccountData;
|
||||
};
|
||||
|
||||
export const getUser = query({
|
||||
args: { userId: v.optional(v.id('users')) },
|
||||
handler: async (ctx, args) => {
|
||||
const userId = args.userId ?? await getAuthUserId(ctx);
|
||||
if (!userId) return null;
|
||||
return getUserData(ctx, userId);
|
||||
},
|
||||
});
|
||||
|
||||
export const getUserAuthAccount = query(async (ctx) => {
|
||||
const userId = await getAuthUserId(ctx);
|
||||
if (!userId) return null;
|
||||
const authAccount = await ctx.db
|
||||
.query('authAccounts')
|
||||
.withIndex('userIdAndProvider', (q) => q.eq('userId', userId))
|
||||
.first();
|
||||
return authAccount;
|
||||
return getUserAuthAccountData(ctx, userId);
|
||||
});
|
||||
|
||||
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,
|
||||
lunchTime: u.lunchTime ?? null,
|
||||
automaticLUnch: u.automaticLunch ?? (false as boolean),
|
||||
}));
|
||||
return Promise.all(users.map((u) => getUserData(ctx, u._id)));
|
||||
});
|
||||
|
||||
export const getAllUserIds = query(async (ctx) => {
|
||||
const users = await ctx.db.query('users').collect();
|
||||
const userIds = users.map((u) => u._id);
|
||||
return userIds;
|
||||
return users.map((u) => u._id);
|
||||
});
|
||||
|
||||
export const updateUserName = mutation({
|
||||
export const updateUser = mutation({
|
||||
args: {
|
||||
name: v.string(),
|
||||
name: v.optional(v.string()),
|
||||
email: v.optional(v.string()),
|
||||
image: v.optional(v.id('_storage')),
|
||||
lunchTime: v.optional(v.string()),
|
||||
automaticLunch: v.optional(v.boolean()),
|
||||
},
|
||||
handler: async (ctx, { name }) => {
|
||||
handler: async (ctx, args) => {
|
||||
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 updateUserLunchtime = mutation({
|
||||
args: {
|
||||
lunchTime: v.string(),
|
||||
},
|
||||
handler: async (ctx, { lunchTime }) => {
|
||||
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.');
|
||||
if (!lunchTime.includes(':'))
|
||||
if (args.lunchTime !== undefined && !args.lunchTime.includes(':')) {
|
||||
throw new ConvexError('Lunch time is invalid.');
|
||||
await ctx.db.patch(userId, { lunchTime });
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
}
|
||||
const patch: Partial<{
|
||||
name: string;
|
||||
email: string;
|
||||
image: Id<'_storage'>;
|
||||
lunchTime: string;
|
||||
automaticLunch: boolean;
|
||||
}> = {};
|
||||
|
||||
if (args.name !== undefined) patch.name = args.name;
|
||||
if (args.email !== undefined) patch.email = args.email;
|
||||
if (args.lunchTime !== undefined) patch.lunchTime = args.lunchTime;
|
||||
if (args.automaticLunch !== undefined)
|
||||
patch.automaticLunch = args.automaticLunch;
|
||||
|
||||
if (args.image !== undefined) {
|
||||
const oldImage = user.image as Id<'_storage'> | undefined;
|
||||
patch.image = args.image;
|
||||
if (oldImage && oldImage !== args.image) {
|
||||
await ctx.storage.delete(oldImage);
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(patch).length > 0) {
|
||||
await ctx.db.patch(userId, patch);
|
||||
}
|
||||
|
||||
export const updateUserAutomaticLunch = mutation({
|
||||
args: { automaticLunch: v.boolean() },
|
||||
handler: async (ctx, { automaticLunch }) => {
|
||||
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.');
|
||||
if (user.automaticLunch === automaticLunch) return { success: true };
|
||||
await ctx.db.patch(userId, { automaticLunch });
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
@@ -157,7 +152,7 @@ export const updateUserPassword = action({
|
||||
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);
|
||||
const user = await ctx.runQuery(api.auth.getUser, { userId });
|
||||
if (!user?.email) throw new ConvexError('User not found.');
|
||||
const verified = await retrieveAccount(ctx, {
|
||||
provider: 'password',
|
||||
|
||||
Reference in New Issue
Block a user