diff --git a/src/emails/invite.tsx b/src/emails/invite.tsx
index 14df498..36cd095 100644
--- a/src/emails/invite.tsx
+++ b/src/emails/invite.tsx
@@ -1,6 +1,5 @@
import * as React from 'react';
import { brandColours } from '../utilities/helpers';
-import { size } from 'lodash';
interface InviteEmailProperties {
playerName: string;
@@ -21,57 +20,59 @@ export const InviteEmail = (props: InviteEmailProperties) => (
cellSpacing={0}
cellPadding={0}
>
-
-
-
- You're in, {props.playerName}!
-
- You've been invited to join {process.env.PRODUCT_NAME}, please click the button below to
- finish signing up.
-
-
+
+ |
+
- |
-
+
+ Join {process.env.PRODUCT_NAME}
+
+
+
+ If above button does not work, copy the link below into a new browser tab:
+
+ {`${process.env.ROOT_URL}/invitation/${props.inviteCode}`}
+
+
+ |
+
+
);
diff --git a/src/orm/matches.ts b/src/orm/matches.ts
index 8792dee..20c5174 100644
--- a/src/orm/matches.ts
+++ b/src/orm/matches.ts
@@ -189,7 +189,7 @@ export class MatchOrm {
const player = await orm.players.get(playerId);
- sql.transaction(async (tx) => {
+ await sql.transaction(async (tx) => {
const eloRefund = parseInt(
(
await tx`SELECT elo_change FROM public.match_players WHERE match_id=${matchId.raw} AND player_id = ${playerId.raw}`
diff --git a/src/orm/user.ts b/src/orm/user.ts
index 7e388cd..679968c 100644
--- a/src/orm/user.ts
+++ b/src/orm/user.ts
@@ -24,9 +24,15 @@ export class User {
}
export class UsersOrm {
- async create(
- { email, password, playerId }: { email: string; password: string; playerId: PlayerId },
- ): Promise {
+ async create({
+ email,
+ password,
+ playerId,
+ }: {
+ email: string;
+ password: string;
+ playerId: PlayerId;
+ }): Promise {
const existingUser: any = first(
await sql`SELECT id
FROM users
@@ -100,10 +106,18 @@ export class UsersOrm {
userToUpdate.isAdmin = patch.isAdmin ?? userToUpdate.isAdmin;
}
- await sql`UPDATE users
- SET is_active=${userToUpdate.isActive},
- is_admin=${userToUpdate.isAdmin}
- WHERE id = ${id.raw}`;
+ await sql.transaction(async (tx) => {
+ await tx`UPDATE users
+ SET is_active=${userToUpdate.isActive},
+ is_admin=${userToUpdate.isAdmin}
+ WHERE id = ${id.raw}`;
+
+ if (id === claims?.userId && patch.password) {
+ const passwordHash = await argon2.hash(patch.password);
+ await tx`UPDATE users
+ SET pass_hash = ${passwordHash}`;
+ }
+ });
return await this.get(id);
}
@@ -133,10 +147,7 @@ export class UsersOrm {
return;
}
- async verifyCredentials(
- email: string,
- password: string,
- ): Promise<{ userId: UserId; refreshCount: string } | null> {
+ async verifyCredentials(email: string, password: string): Promise<{ userId: UserId; refreshCount: string } | null> {
const dbResult: any = first(
await sql`SELECT *
FROM users
@@ -168,12 +179,7 @@ export class UsersOrm {
return dbResult.refresh_count === refreshCount;
}
- async changePassword(
- id: UserId,
- oldPassword: string | null,
- newPassword: string,
- claims?: Claims,
- ): Promise {
+ async changePassword(id: UserId, oldPassword: string | null, newPassword: string, claims?: Claims): Promise {
const isAdmin = Claims.test(Claims.ADMIN, claims);
if (!(isAdmin || (Claims.test(Claims.USERS.SELF.UPDATE, claims) && id === claims?.userId))) {
throw new UnauthorizedError();
diff --git a/src/utilities/guard.ts b/src/utilities/guard.ts
index 1a65fe7..a403477 100644
--- a/src/utilities/guard.ts
+++ b/src/utilities/guard.ts
@@ -66,6 +66,6 @@ export function unwrapMethod(
): (r: Request) => Promise {
return async (request: Request) => {
const unwrappedRequest = await unwrap(request);
- return await methodToUnwrap(unwrappedRequest);
+ return methodToUnwrap(unwrappedRequest);
};
}
diff --git a/src/utilities/requestModels.ts b/src/utilities/requestModels.ts
index 3d26d35..9071b7e 100644
--- a/src/utilities/requestModels.ts
+++ b/src/utilities/requestModels.ts
@@ -14,6 +14,7 @@ export interface CreateUserRequest {
export interface UpdateUserRequest {
isActive?: boolean;
isAdmin?: boolean;
+ password?: string;
}
export interface InviteUserRequest {
email: string;