console/integration-tests/tests/api/rate-limit/emails.spec.ts
Laurin Quast 6540155fc7
feat: replace auth0 with supertokens (#303)
* add supertoken container to docker-compose file

* yeah I am sorry this one big commit and I am ashamed of it

* use logOut function

* feat: show header on 404 page

* feat: better handling for organization cookie when not authenticated

* wrap it

* check session within server side props

* add is_admin flag user migration

* simplify and annotate the config

* fix: handle status codes + fix email/password sign up with import from auth0

* no hardcoded env pls

* decode process.env

* secure update user id mapping via a key

* fix: login form

* lol we don't need to hit the API

* fix: do graphql api authorization via authorization header instead of cookie

* implement isAdmin flag

* fix: types :)

* skipit

* yo we can run this

* set env variables

* disable because it annoys the hell out of me

* use the right host

* add not about token length

* refactor: decode environment variables

* feat: store external user id from guthub/google provider in the database

* workaround supertokens omitting null values from the token

* re-enable check

* i have no time for this shit

* add missing env variable

* fix: email test; missing domain extension

* configure pulumi deployment

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Dotan Simha <dotansimha@gmail.com>

* configure pulumi deployment

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Dotan Simha <dotansimha@gmail.com>

* configure pulumi deployment

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Dotan Simha <dotansimha@gmail.com>

* configure pulumi deployment

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>

* fix: env names

* fix: link google account to the correct db record

* feat: email confirmation emails

* ?

* bump ts-node

* fix types

* omit package form the bundle

* remove it from dependencies...

* add emails apckage to dev deps

* resolve eslint issues

* remove comments

* update dev info + change env variable (no need to expose it on the frontend)

* use correct user id lol

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Dotan Simha <dotansimha@gmail.com>
2022-09-06 09:38:31 +02:00

120 lines
3.1 KiB
TypeScript

import { TargetAccessScope, ProjectType, ProjectAccessScope, OrganizationAccessScope } from '@app/gql/graphql';
import { createOrganization, createProject, createToken, updateOrgRateLimit, waitFor } from '../../../testkit/flow';
import * as emails from '../../../testkit/emails';
import { authenticate, userEmails } from '../../../testkit/auth';
import { collect } from '../../../testkit/usage';
function generateUnique() {
return Math.random().toString(36).substring(7);
}
function filterEmailsByOrg(orgName: string, emails: emails.Email[]) {
return emails.filter(email => email.subject.startsWith(orgName));
}
test('rate limit approaching and reached for organization', async () => {
const adminEmail = userEmails.admin;
const { access_token } = await authenticate('admin');
const orgResult = await createOrganization(
{
name: generateUnique(),
},
access_token
);
const org = orgResult.body.data!.createOrganization.ok!.createdOrganizationPayload.organization;
const projectResult = await createProject(
{
organization: org.cleanId,
type: ProjectType.Single,
name: 'bar',
},
access_token
);
const project = projectResult.body.data!.createProject.ok!.createdProject;
const target = projectResult.body.data!.createProject.ok!.createdTargets.find(t => t.name === 'production')!;
await updateOrgRateLimit(
{
organization: org.cleanId,
},
{
operations: 11,
},
access_token
);
const tokenResult = await createToken(
{
name: 'test',
organization: org.cleanId,
project: project.cleanId,
target: target.cleanId,
organizationScopes: [OrganizationAccessScope.Read],
projectScopes: [ProjectAccessScope.Read],
targetScopes: [TargetAccessScope.Read, TargetAccessScope.RegistryRead, TargetAccessScope.RegistryWrite],
},
access_token
);
expect(tokenResult.body.errors).not.toBeDefined();
const token = tokenResult.body.data!.createToken.ok!.secret;
const op = {
operation: 'query ping { ping }',
operationName: 'ping',
fields: ['Query', 'Query.ping'],
execution: {
ok: true,
duration: 200000000,
errorsTotal: 0,
},
};
const collectResult = await collect({
operations: new Array(10).fill(op),
token,
});
expect(collectResult.status).toEqual(200);
await waitFor(5_000);
let sent = await emails.history();
expect(sent).toContainEqual({
to: adminEmail,
subject: `${org.name} is approaching its rate limit`,
body: expect.any(String),
});
expect(filterEmailsByOrg(org.name, sent)).toHaveLength(1);
await collect({
operations: [op, op],
token,
});
await waitFor(5_000);
sent = await emails.history();
expect(sent).toContainEqual({
to: adminEmail,
subject: `${org.name} has exceeded its rate limit`,
body: expect.any(String),
});
expect(filterEmailsByOrg(org.name, sent)).toHaveLength(2);
// Make sure we don't send the same email again
await collect({
operations: [op, op],
token,
});
await waitFor(5_000);
// Nothing new
sent = await emails.history();
expect(filterEmailsByOrg(org.name, sent)).toHaveLength(2);
});