Added ability for users to update their password. Minor tidy up.
This commit is contained in:
@@ -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}
|
||||
>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<div
|
||||
style={{
|
||||
padding: '20px',
|
||||
borderRadius: '20px',
|
||||
background: brandColours.white,
|
||||
margin: '50px',
|
||||
color: brandColours.dark,
|
||||
maxWidth: '450px',
|
||||
}}
|
||||
>
|
||||
<h1>You're in, {props.playerName}!</h1>
|
||||
<p>
|
||||
You've been invited to join {process.env.PRODUCT_NAME}, please click the button below to
|
||||
finish signing up.
|
||||
</p>
|
||||
<p
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<div
|
||||
style={{
|
||||
marginBottom: '40px',
|
||||
padding: '20px',
|
||||
borderRadius: '20px',
|
||||
background: brandColours.white,
|
||||
margin: '50px',
|
||||
color: brandColours.dark,
|
||||
maxWidth: '450px',
|
||||
}}
|
||||
>
|
||||
<a
|
||||
<h1>You're in, {props.playerName}!</h1>
|
||||
<p>
|
||||
You've been invited to join {process.env.PRODUCT_NAME}, please click the button below to
|
||||
finish signing up.
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
padding: '10px 20px',
|
||||
borderRadius: '5px',
|
||||
background: brandColours.primary,
|
||||
textDecoration: 'none',
|
||||
color: brandColours.light,
|
||||
fontSize: '20px',
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '40px',
|
||||
}}
|
||||
href={`${process.env.ROOT_URL}/invitation/${props.inviteCode}`}
|
||||
>
|
||||
Join {process.env.PRODUCT_NAME}
|
||||
</a>
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
fontSize: '0.8rem',
|
||||
opacity: '80%',
|
||||
}}
|
||||
>
|
||||
If above button does not work, copy the link below into a new browser tab:
|
||||
<br />
|
||||
{`${process.env.ROOT_URL}/invitation/${props.inviteCode}`}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<a
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
padding: '10px 20px',
|
||||
borderRadius: '5px',
|
||||
background: brandColours.primary,
|
||||
textDecoration: 'none',
|
||||
color: brandColours.light,
|
||||
fontSize: '20px',
|
||||
fontWeight: 'bold',
|
||||
}}
|
||||
href={`${process.env.ROOT_URL}/invitation/${props.inviteCode}`}
|
||||
>
|
||||
Join {process.env.PRODUCT_NAME}
|
||||
</a>
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
fontSize: '0.8rem',
|
||||
opacity: '80%',
|
||||
}}
|
||||
>
|
||||
If above button does not work, copy the link below into a new browser tab:
|
||||
<br />
|
||||
{`${process.env.ROOT_URL}/invitation/${props.inviteCode}`}
|
||||
</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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}`
|
||||
|
||||
@@ -24,9 +24,15 @@ export class User {
|
||||
}
|
||||
|
||||
export class UsersOrm {
|
||||
async create(
|
||||
{ email, password, playerId }: { email: string; password: string; playerId: PlayerId },
|
||||
): Promise<User> {
|
||||
async create({
|
||||
email,
|
||||
password,
|
||||
playerId,
|
||||
}: {
|
||||
email: string;
|
||||
password: string;
|
||||
playerId: PlayerId;
|
||||
}): Promise<User> {
|
||||
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<void> {
|
||||
async changePassword(id: UserId, oldPassword: string | null, newPassword: string, claims?: Claims): Promise<void> {
|
||||
const isAdmin = Claims.test(Claims.ADMIN, claims);
|
||||
if (!(isAdmin || (Claims.test(Claims.USERS.SELF.UPDATE, claims) && id === claims?.userId))) {
|
||||
throw new UnauthorizedError();
|
||||
|
||||
@@ -66,6 +66,6 @@ export function unwrapMethod<T = {}>(
|
||||
): (r: Request) => Promise<Response> {
|
||||
return async (request: Request) => {
|
||||
const unwrappedRequest = await unwrap<T>(request);
|
||||
return await methodToUnwrap(unwrappedRequest);
|
||||
return methodToUnwrap(unwrappedRequest);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface CreateUserRequest {
|
||||
export interface UpdateUserRequest {
|
||||
isActive?: boolean;
|
||||
isAdmin?: boolean;
|
||||
password?: string;
|
||||
}
|
||||
export interface InviteUserRequest {
|
||||
email: string;
|
||||
|
||||
Reference in New Issue
Block a user