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
2 changes: 2 additions & 0 deletions convex/_generated/api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ import type * as _model_utils_createTestTournament from "../_model/utils/createT
import type * as _model_utils_createTestTournamentMatchResults from "../_model/utils/createTestTournamentMatchResults.js";
import type * as _model_utils_deleteTestTournament from "../_model/utils/deleteTestTournament.js";
import type * as _model_utils_index from "../_model/utils/index.js";
import type * as _model_utils_mergeUser from "../_model/utils/mergeUser.js";
import type * as auth_ResendOtpPasswordReset from "../auth/ResendOtpPasswordReset.js";
import type * as auth_ResendOtpVerification from "../auth/ResendOtpVerification.js";
import type * as auth from "../auth.js";
Expand Down Expand Up @@ -343,6 +344,7 @@ declare const fullApi: ApiFromModules<{
"_model/utils/createTestTournamentMatchResults": typeof _model_utils_createTestTournamentMatchResults;
"_model/utils/deleteTestTournament": typeof _model_utils_deleteTestTournament;
"_model/utils/index": typeof _model_utils_index;
"_model/utils/mergeUser": typeof _model_utils_mergeUser;
"auth/ResendOtpPasswordReset": typeof auth_ResendOtpPasswordReset;
"auth/ResendOtpVerification": typeof auth_ResendOtpVerification;
auth: typeof auth;
Expand Down
2 changes: 1 addition & 1 deletion convex/_model/tournaments/queries/getTournamentsByUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const getTournamentsByUser = async (
}
const userIds = [
...tournament.organizerUserIds,
...tournament.activePlayerUserIds,
...tournament.playerUserIds,
];
if (!userIds.includes(args.userId)) {
return false;
Expand Down
4 changes: 4 additions & 0 deletions convex/_model/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ export {
deleteTestTournament,
deleteTestTournamentArgs,
} from './deleteTestTournament';
export {
mergeUser,
mergeUserArgs,
} from './mergeUser';
103 changes: 103 additions & 0 deletions convex/_model/utils/mergeUser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { getAuthUserId } from '@convex-dev/auth/server';
import { Infer, v } from 'convex/values';

import { MutationCtx } from '../../_generated/server';

export const mergeUserArgs = v.object({
primaryId: v.id('users'),
secondaryId: v.id('users'),
});

/**
* Merges a secondary user into a primary user.
*
* @param ctx - Convex query context
* @param args - User data
*/
export const mergeUser = async (
ctx: MutationCtx,
args: Infer<typeof mergeUserArgs>,
): Promise<void> => {

// --- CHECK AUTH ----
// TODO: This should be admin roles or something
const userId = await getAuthUserId(ctx);
if (!userId) {
throw new Error('Auth required');
}

// ---- PRIMARY ACTIONS ----
// Match Result Comments
const matchResultComments = await ctx.db.query('matchResultComments')
.withIndex('by_user_id', (q) => q.eq('userId', args.secondaryId))
.collect();
for (const record of matchResultComments) {
await ctx.db.patch(record._id, { userId: args.primaryId });
}

// Match Result Likes
const matchResultLikes = await ctx.db.query('matchResultLikes')
.withIndex('by_user_id', (q) => q.eq('userId', args.secondaryId))
.collect();
for (const record of matchResultLikes) {
await ctx.db.patch(record._id, { userId: args.primaryId });
}

// Match Results
const matchResults = await ctx.db.query('matchResults')
.filter((q) => q.or(
q.eq(q.field('player0UserId'), args.secondaryId),
q.eq(q.field('player1UserId'), args.secondaryId),
))
.collect();
for (const record of matchResults) {
if (record.player0UserId === args.secondaryId) {
await ctx.db.patch(record._id, { player0UserId: args.primaryId });
}
if (record.player1UserId === args.secondaryId) {
await ctx.db.patch(record._id, { player1UserId: args.primaryId });
}
}

// Tournament Competitors
const tournamentCompetitors = await ctx.db.query('tournamentCompetitors').collect();
for (const record of tournamentCompetitors) {
if (record.players.find((p) => p.userId === args.secondaryId)) {
await ctx.db.patch(record._id, {
players: record.players.map((p) => p.userId === args.secondaryId ? {
...p,
userId: args.primaryId,
} : p),
});
}
}

// Tournament Organizers
const tournaments = await ctx.db.query('tournaments').collect();
for (const record of tournaments) {
if (record.organizerUserIds.includes(args.secondaryId)) {
await ctx.db.patch(record._id, {
organizerUserIds: record.organizerUserIds.map((id) => id === args.secondaryId ? args.primaryId : id),
});
}
}

// Friendships
const friendships = await ctx.db.query('friendships')
.filter((q) => q.or(
q.eq(q.field('senderUserId'), args.secondaryId),
q.eq(q.field('recipientUserId'), args.secondaryId),
))
.collect();
for (const record of friendships) {
if (record.senderUserId === args.secondaryId) {
await ctx.db.patch(record._id, { senderUserId: args.primaryId });
}
if (record.recipientUserId === args.secondaryId) {
await ctx.db.patch(record._id, { recipientUserId: args.primaryId });
}
}

// Clean up the loose ID
await ctx.db.delete(args.secondaryId);
};
26 changes: 12 additions & 14 deletions convex/utils.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import { mutation } from './_generated/server';
import {
createTestTournament as createTestTournamentHandler,
createTestTournamentArgs,
createTestTournamentMatchResults as createTestTournamentMatchResultsHandler,
createTestTournamentMatchResultsArgs,
deleteTestTournament as deleteTestTournamentHandler,
deleteTestTournamentArgs,
} from './_model/utils';
import * as model from './_model/utils';

export const createTestTournament = mutation({
args: createTestTournamentArgs,
handler: createTestTournamentHandler,
args: model.createTestTournamentArgs,
handler: model.createTestTournament,
});

export const createTestTournamentMatchResults = mutation({
args: createTestTournamentMatchResultsArgs,
handler: createTestTournamentMatchResultsHandler,
args: model.createTestTournamentMatchResultsArgs,
handler: model.createTestTournamentMatchResults,
});

export const deleteTestTournament = mutation({
args: deleteTestTournamentArgs,
handler: deleteTestTournamentHandler,
args: model.deleteTestTournamentArgs,
handler: model.deleteTestTournament,
});

export const mergeUser = mutation({
args: model.mergeUserArgs,
handler: model.mergeUser,
});