Skip to content

Commit

Permalink
refactor(signups): add more allowed hosts than fflogs
Browse files Browse the repository at this point in the history
  • Loading branch information
ssilve1989 committed Apr 14, 2024
1 parent 87ec756 commit 08fbadd
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/commands/signup/signup-command.handler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('Signup Command Handler', () => {
return Encounter.DSR;
case 'character':
return 'Test Character';
case 'fflogs':
case 'prog-proof-link':
return 'https://www.fflogs.com/reports/foo';
case 'availability':
return 'Monday, Wednesday, Friday';
Expand Down
14 changes: 7 additions & 7 deletions src/commands/signup/signup-command.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ class SignupCommandHandler implements ICommandHandler<SignupCommand> {

const embed = this.createSignupConfirmationEmbed(signupRequest);

const ConfirmationRow = new ActionRowBuilder().addComponents(
const confirmationRow = new ActionRowBuilder().addComponents(
ConfirmButton,
CancelButton,
);

const confirmationInteraction = await interaction.editReply({
components: [ConfirmationRow as any], // the typings are wrong here? annoying af
components: [confirmationRow as any], // the typings are wrong here? annoying af
embeds: [embed],
});
try {
Expand Down Expand Up @@ -153,7 +153,7 @@ class SignupCommandHandler implements ICommandHandler<SignupCommand> {
character: options.getString('character')!,
discordId: user.id,
encounter: options.getString('encounter')! as Encounter,
fflogsLink: options.getString('fflogs'),
proofOfProgLink: options.getString('prog-proof-link'),
progPointRequested: options.getString('prog-point')!,
role: options.getString('job')!,
screenshot: options.getAttachment('screenshot')?.url,
Expand All @@ -175,7 +175,7 @@ class SignupCommandHandler implements ICommandHandler<SignupCommand> {
availability,
character,
encounter,
fflogsLink,
proofOfProgLink,
role,
screenshot,
world,
Expand All @@ -196,11 +196,11 @@ class SignupCommandHandler implements ICommandHandler<SignupCommand> {
{ name: 'Role', value: role, inline: true },
]);

if (fflogsLink) {
if (proofOfProgLink) {
embed = embed.addFields([
{
name: 'FF Logs Link',
value: `[View Report](${fflogsLink})`,
name: 'Prog Proof Link',
value: `[View](${proofOfProgLink})`,
inline: true,
},
]);
Expand Down
16 changes: 10 additions & 6 deletions src/commands/signup/signup-interaction.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { ToLowercase } from '../../common/decorators/to-lowercase.js';
import { TransformUrl } from '../../common/decorators/transform-url.js';
import { Encounter } from '../../encounters/encounters.consts.js';
import { SignupDocument } from '../../firebase/models/signup.model.js';
import {
PROG_PROOF_HOSTS_WHITELIST,
WHITELIST_VALIDATION_ERROR,
} from './signup.consts.js';

class SignupInteractionDto
implements Omit<SignupDocument, 'status' | 'partyType' | 'expiresAt'>
Expand All @@ -27,20 +31,20 @@ class SignupInteractionDto
encounter: Encounter;

@IsUrl(
{ host_whitelist: [/fflogs\.com/] },
// biome-ignore lint/style/useNamingConvention: <we don't controls this property>
{ host_whitelist: PROG_PROOF_HOSTS_WHITELIST },
{
message:
'A valid fflogs URL must be provided if no screenshot is attached',
message: WHITELIST_VALIDATION_ERROR,
},
)
@TransformUrl()
@ValidateIf(({ screenshot }) => !screenshot)
fflogsLink?: string | null;
proofOfProgLink?: string | null;

@IsString({
message: 'A screenshot must be attached if no fflogs link is provided',
message: 'A screenshot must be attached if no link is provided',
})
@ValidateIf(({ fflogsLink }) => !fflogsLink)
@ValidateIf(({ proofOfProgLink }) => !proofOfProgLink)
screenshot?: string | null;

@IsString()
Expand Down
6 changes: 4 additions & 2 deletions src/commands/signup/signup-slash-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ export const SignupSlashCommand = new SlashCommandBuilder()
)
.addStringOption((option) =>
option
.setDescription('FF Logs Link for selected encounter showing prog point')
.setName('fflogs'),
.setDescription(
'Link your proof of prog-point here (fflogs/youtube/twitch etc)',
)
.setName('prog-proof-link'),
)
.addAttachmentOption((option) =>
option
Expand Down
43 changes: 43 additions & 0 deletions src/commands/signup/signup.command.dto.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
import { Encounter } from '../../encounters/encounters.consts.js';
import { SignupInteractionDto } from './signup-interaction.dto.js';
import { PROG_PROOF_HOSTS_WHITELIST } from './signup.consts.js';

function createBaseObject(proofOfProgLink: string) {
return {
availability: 'test',
character: 'test',
discordId: 'test',
role: 'test',
progPointRequested: 'test',
encounter: Encounter.TOP,
proofOfProgLink,
username: 'test',
world: 'test',
};
}

describe('SignupInteractionDto', () => {
it.each(PROG_PROOF_HOSTS_WHITELIST)(
'should allow URLs from host %s',
async (host) => {
const dto = plainToInstance(
SignupInteractionDto,
createBaseObject(`${host.source.replace(/\\/g, '')}`),
);
const errors = await validate(dto);
expect(errors).toHaveLength(0);
},
);

it('should not allow URLs not in the whitelist', async () => {
const dto = plainToInstance(
SignupInteractionDto,
createBaseObject('https://not-in-whitelist.com/test'),
);
const errors = await validate(dto);
expect(errors).toHaveLength(1);
expect(errors[0].property).toBe('proofOfProgLink');
});
});
16 changes: 16 additions & 0 deletions src/commands/signup/signup.consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,19 @@ export const SIGNUP_REVIEW_REACTIONS: Record<
DECLINED: '❌',
PENDING: ':question:',
};

// string validation via IsUrl does not work the same as regex. It does like
// this weird strict equality wheras regex just looks at the hostname portion?
// In any case, we just use regexes for now
export const PROG_PROOF_HOSTS_WHITELIST = [
/fflogs.com/,
/streamable.com/,
/tomestone.gg/,
/twitch.tv/,
/youtube.com/,
];

// which makes us need to do this mapping for presentation
export const WHITELIST_VALIDATION_ERROR = `A link from one of these sources must be provided if no screenshot is attached: ${PROG_PROOF_HOSTS_WHITELIST.map(
(v) => v.source.replaceAll('/', ''),
).join('\n')}`;
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class SendSignupReviewCommandHandler
availability,
character,
encounter,
fflogsLink,
proofOfProgLink,
screenshot,
world,
role,
Expand All @@ -100,9 +100,9 @@ class SendSignupReviewCommandHandler
{ name: 'Job', value: role, inline: true },
]);

if (fflogsLink) {
if (proofOfProgLink) {
embed = embed.addFields([
{ name: 'FFLogs Link', value: `[View Report](${fflogsLink})` },
{ name: 'Prog Proof Link', value: `[View](${proofOfProgLink})` },
]);
}

Expand Down
2 changes: 1 addition & 1 deletion src/firebase/models/signup.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface SignupDocument {
character: string;
discordId: string;
encounter: Encounter;
fflogsLink?: string | null;
proofOfProgLink?: string | null;
// freeform field representing the characters job/role/class
role: string;
// the prog point specified by the coodinator upon review
Expand Down

0 comments on commit 08fbadd

Please sign in to comment.