Skip to content
Open
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: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ _Note:_ This is a general overview and may vary per library/package. For authori
- **Core subset:** `yarn start mza`
- **Ports:** `yarn ports`
- **Nx:** `nx build <pkg>`, `nx lint <pkg>`, `nx test-unit <pkg>`, `nx test-integration <pkg>`, `nx start <pkg>`
- **Pkg scripts:** `cd packages/<name> && yarn <script>`
- **Pkg scripts:** `cd packages/<name> && yarn <script>` — Run these through Nx (`nx build <pkg>`, `nx build-storybook <pkg>`); invoking them with plain `yarn` will **not** run their dependency steps.
- **L10N:** `yarn l10n:prime`
- **DB migrations:** add new SQL under `packages/db-migrations/databases/fxa/patches/` → `nx run db-migrations:migrate`
**Never edit existing published migration files.**
Expand Down
15 changes: 11 additions & 4 deletions _dev/pm2/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,19 @@ else
pm2 start _dev/pm2/infrastructure.config.js
fi

echo "waiting for containers to start"

_scripts/check-url.sh localhost:4100/health 200 "goaws (SNS)"
_scripts/check-url.sh localhost:9299/api/config 200 "firebase emulator"
echo "Waiting for mysql"
_scripts/check-mysql.sh

echo "Waiting for Redis"
_scripts/check-redis.sh

echo "waiting for DB patches"
_scripts/check-db-patcher.sh

# Check that goaws simulator is up
echo "Waiting for goaws"
_scripts/check-url.sh localhost:4100/health 200 "goaws (SNS)"

# Check firestore is up
echo "Waiting for firestore"
_scripts/check-url.sh localhost:9299/api/config 200 "firebase emulator"
24 changes: 14 additions & 10 deletions apps/payments/next/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/payments/next",
"projectType": "application",
"tags": ["app", "payments", "type:sp3"],
"targets": {
"build": {
"dependsOn": ["l10n-bundle", "glean-generate", "payments-metrics:glean-generate-frontend"]
"dependsOn": [
"l10n-bundle",
"glean-generate",
"payments-metrics:glean-generate-frontend"
]
},
"dev": {
"options": {
Expand Down Expand Up @@ -39,7 +44,11 @@
},
"start": {
"command": "pm2 start apps/payments/next/pm2.config.js && yarn check:url localhost:3035/__heartbeat__",
"dependsOn": ["l10n-bundle", "glean-generate", "payments-metrics:glean-generate-frontend"]
"dependsOn": [
"l10n-bundle",
"glean-generate",
"payments-metrics:glean-generate-frontend"
]
},
"stop": {
"command": "pm2 stop apps/payments/next/pm2.config.js"
Expand All @@ -56,9 +65,7 @@
"command": "yarn grunt --gruntfile='apps/payments/next/Gruntfile.js' merge-ftl",
"dependsOn": ["l10n-prime"],
"inputs": ["{projectRoot}/gruntfile.js", "{projectRoot}/app/**/en.ftl"],
"outputs": [
"{projectRoot}/public/locales/en/payments-next.ftl"
]
"outputs": ["{projectRoot}/public/locales/en/payments-next.ftl"]
},
"l10n-prime": {
"command": "./_scripts/l10n/prime.sh apps/payments/next"
Expand All @@ -74,9 +81,7 @@
"{projectRoot}/public/locales/**/payments-next.ftl",
"{projectRoot}/public/locales/**/react.ftl"
],
"outputs": [
"{projectRoot}/public/locales/**/main.ftl"
]
"outputs": ["{projectRoot}/public/locales/**/main.ftl"]
},
"watchers": {
"command": "yarn grunt --gruntfile='apps/payments/next/Gruntfile.js' watchers"
Expand All @@ -99,6 +104,5 @@
"{workspaceRoot}/libs/shared/metrics/glean/src/registry/subplat-backend-metrics.yaml"
]
}
},
"tags": ["app", "payments", "type:sp3"]
}
}
2 changes: 2 additions & 0 deletions libs/accounts/email-renderer/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"build": {
"dependsOn": ["build-ts", "l10n-merge", "build-css"],
"executor": "nx:run-commands",
"outputs": ["{workspaceRoot}/dist/{projectRoot}/public/locales"],
"options": {
"commands": [
"# Important!!! We have to do this cause these are .gitingored, which means nx ingores them too.",
Expand Down Expand Up @@ -61,6 +62,7 @@
"test-integration": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"dependsOn": ["l10n-merge"],
"options": {
"jestConfig": "libs/accounts/email-renderer/jest.config.ts",
"testPathPattern": ["\\.in\\.spec\\.ts$"]
Expand Down
2 changes: 1 addition & 1 deletion libs/accounts/email-renderer/tsconfig.lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
"exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
}
4 changes: 2 additions & 2 deletions libs/accounts/email-sender/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/email-sender/jest.config.ts",
"testPathPattern": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
"testPathPatterns": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
}
},
"test-integration": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/email-sender/jest.config.ts",
"testPathPattern": ["\\.in\\.spec\\.ts$"]
"testPathPatterns": ["\\.in\\.spec\\.ts$"]
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions libs/accounts/errors/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/errors/jest.config.ts",
"testPathPattern": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
"testPathPatterns": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
}
},
"test-integration": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/errors/jest.config.ts",
"testPathPattern": ["\\.in\\.spec\\.ts$"]
"testPathPatterns": ["\\.in\\.spec\\.ts$"]
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions libs/accounts/passkey/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/passkey/jest.config.ts",
"testPathPattern": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
"testPathPatterns": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
}
},
"test-integration": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/passkey/jest.config.ts",
"testPathPattern": ["\\.in\\.spec\\.ts$"]
"testPathPatterns": ["\\.in\\.spec\\.ts$"]
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions libs/accounts/rate-limit/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/rate-limit/jest.config.ts",
"testPathPattern": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
"testPathPatterns": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
}
},
"test-integration": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/rate-limit/jest.config.ts",
"testPathPattern": ["\\.in\\.spec\\.ts$"]
"testPathPatterns": ["\\.in\\.spec\\.ts$"]
}
}
}
Expand Down
30 changes: 15 additions & 15 deletions libs/accounts/rate-limit/src/lib/rate-limit.in.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ describe('rate-limit', () => {
expect(check2?.reason).toEqual('too-many-attempts');
expect(check2?.retryAfter).toEqual(1000);

expect(mockIncrement).toBeCalledTimes(1);
expect(mockIncrement).toBeCalledWith('rate_limit.block', [
expect(mockIncrement).toHaveBeenCalledTimes(1);
expect(mockIncrement).toHaveBeenCalledWith('rate_limit.block', [
`on:${blockOn}`,
'action:testBlock',
]);
Expand Down Expand Up @@ -91,8 +91,8 @@ describe('rate-limit', () => {
expect(check1).toBeNull();
expect(check2).toBeNull();

expect(mockIncrement).toBeCalledTimes(1);
expect(mockIncrement).toBeCalledWith('rate_limit.report', [
expect(mockIncrement).toHaveBeenCalledTimes(1);
expect(mockIncrement).toHaveBeenCalledWith('rate_limit.report', [
`on:${blockOn}`,
'action:testReport',
]);
Expand Down Expand Up @@ -217,7 +217,7 @@ describe('rate-limit', () => {

expect(check1).toBeNull();
expect(check2?.retryAfter).toEqual(1000);
expect(check3?.retryAfter).toBeLessThan(501);
expect(check3?.retryAfter).toBeLessThan(550);
expect(check3?.retryAfter).toBeGreaterThan(450);
expect(check4).toBeNull();
});
Expand Down Expand Up @@ -268,19 +268,19 @@ describe('rate-limit', () => {
expect(checkReportOnly2).toBeNull();
expect(checkReportOnly3).toBeNull();

expect(statsd.increment).toBeCalledTimes(5);
expect(statsd.increment).toHaveBeenCalledTimes(5);
// For unblock calls
expect(statsd.increment).toBeCalledWith('rate_limit.unblock', [
expect(statsd.increment).toHaveBeenCalledWith('rate_limit.unblock', [
'on:ip',
'action:testBlock',
]);
// For two blocked calls
expect(statsd.increment).toBeCalledWith('rate_limit.block', [
expect(statsd.increment).toHaveBeenCalledWith('rate_limit.block', [
'on:ip',
'action:testBlock',
]);
// For two report only calls
expect(statsd.increment).toBeCalledWith('rate_limit.report', [
expect(statsd.increment).toHaveBeenCalledWith('rate_limit.report', [
'on:ip',
'action:testReport',
]);
Expand Down Expand Up @@ -317,8 +317,8 @@ describe('rate-limit', () => {
expect(check2?.reason).toEqual('too-many-attempts');
expect(check2?.retryAfter).toEqual(1000);

expect(mockIncrement).toBeCalledTimes(1);
expect(mockIncrement).toBeCalledWith('rate_limit.block', [
expect(mockIncrement).toHaveBeenCalledTimes(1);
expect(mockIncrement).toHaveBeenCalledWith('rate_limit.block', [
'on:ip',
'action:testBlock',
]);
Expand Down Expand Up @@ -377,8 +377,8 @@ describe('rate-limit', () => {
expect(check4).not.toBeNull();
expect(check5).toBeNull();

expect(statsd.increment).toBeCalledTimes(1);
expect(statsd.increment).toBeCalledWith('rate_limit.ban', [
expect(statsd.increment).toHaveBeenCalledTimes(1);
expect(statsd.increment).toHaveBeenCalledWith('rate_limit.ban', [
'on:ip',
'action:testBan',
]);
Expand Down Expand Up @@ -460,9 +460,9 @@ describe('rate-limit', () => {

expect(check1).toBeNull();
expect(check2?.retryAfter).toEqual(1000);
expect(check3?.retryAfter).toBeLessThan(501);
expect(check3?.retryAfter).toBeLessThan(550);
expect(check3?.retryAfter).toBeGreaterThan(450);
expect(check3b?.retryAfter).toBeLessThan(501);
expect(check3b?.retryAfter).toBeLessThan(550);
expect(check3b?.retryAfter).toBeGreaterThan(450);
expect(check4).toBeNull();
expect(check4b).toBeNull();
Expand Down
44 changes: 19 additions & 25 deletions libs/accounts/rate-limit/src/lib/rate-limit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ describe('rate-limit', () => {
expect(rateLimit.skip('test', { email: 'foo@firefox.com' })).toBeTruthy();
expect(rateLimit.skip('test', { email: 'bar@firefox.com ' })).toBeFalsy();
expect(rateLimit.skip('test', {})).toBeFalsy();
expect(statsd.increment).toBeCalledWith('rate_limit.ignore.email');
expect(statsd.increment).toHaveBeenCalledWith('rate_limit.ignore.email');
});

it('can ignore certain ips', () => {
Expand All @@ -168,7 +168,7 @@ describe('rate-limit', () => {
expect(rateLimit.skip('test', { ip: '127.0.0.1' })).toBeTruthy();
expect(rateLimit.skip('test', { ip: '0.0.0.0' })).toBeFalsy();
expect(rateLimit.skip('test', {})).toBeFalsy();
expect(statsd.increment).toBeCalledWith('rate_limit.ignore.ip');
expect(statsd.increment).toHaveBeenCalledWith('rate_limit.ignore.ip');
});

it('can ignore certain uids', () => {
Expand All @@ -184,7 +184,7 @@ describe('rate-limit', () => {
expect(rateLimit.skip('test', { uid: '000-000-000' })).toBeTruthy();
expect(rateLimit.skip('test', { uid: '000-000-001' })).toBeFalsy();
expect(rateLimit.skip('test', {})).toBeFalsy();
expect(statsd.increment).toBeCalledWith('rate_limit.ignore.uid');
expect(statsd.increment).toHaveBeenCalledWith('rate_limit.ignore.uid');
});

describe('rate limit search', () => {
Expand Down Expand Up @@ -601,31 +601,25 @@ describe('rate-limit', () => {
test : ip : 1 : 1 second : 1s : block
test : ip : 1 : 1 second : 1s : block
`)
).toThrowError(/Invalid configuration! Duplicates detected:/);
).toThrow(/Invalid configuration! Duplicates detected:/);
});

it('throws on malformed rule', () => {
expect(() => parseConfigRules('foo!23:ip:1:1s:1s:block')).toThrowError();
expect(() => parseConfigRules('foo:bar:1:1s:1s:block')).toThrowError();
expect(() => parseConfigRules('foo:bar:-2:1s:1s:block')).toThrowError();
expect(() =>
parseConfigRules('foo:bar:1:1sdfds:1s:block')
).toThrowError();
expect(() =>
parseConfigRules('foo:bar:1:1s:1dsfds:block')
).toThrowError();
expect(() =>
parseConfigRules('foo:bar:1:1s:-1h:block:ban')
).toThrowError();
expect(() => parseConfigRules('foo:bar:1:1s:-1h:block')).toThrowError();
expect(() => parseConfigRules(':bar:1:1s:-1h:block')).toThrowError();
expect(() => parseConfigRules('foo::1:1s:-1h:block')).toThrowError();
expect(() => parseConfigRules('foo:bar::1s:-1h:block')).toThrowError();
expect(() => parseConfigRules('foo:bar:1::-1h:block')).toThrowError();
expect(() => parseConfigRules('foo:bar:1:1s::block')).toThrowError();
expect(() => parseConfigRules('foo:bar:1')).toThrowError();
expect(() => parseConfigRules('foo!23:ip:1:1s:1s:')).toThrowError();
expect(() => parseConfigRules('foo!23:ip:1:1s:1s:foo')).toThrowError();
expect(() => parseConfigRules('foo!23:ip:1:1s:1s:block')).toThrow();
expect(() => parseConfigRules('foo:bar:1:1s:1s:block')).toThrow();
expect(() => parseConfigRules('foo:bar:-2:1s:1s:block')).toThrow();
expect(() => parseConfigRules('foo:bar:1:1sdfds:1s:block')).toThrow();
expect(() => parseConfigRules('foo:bar:1:1s:1dsfds:block')).toThrow();
expect(() => parseConfigRules('foo:bar:1:1s:-1h:block:ban')).toThrow();
expect(() => parseConfigRules('foo:bar:1:1s:-1h:block')).toThrow();
expect(() => parseConfigRules(':bar:1:1s:-1h:block')).toThrow();
expect(() => parseConfigRules('foo::1:1s:-1h:block')).toThrow();
expect(() => parseConfigRules('foo:bar::1s:-1h:block')).toThrow();
expect(() => parseConfigRules('foo:bar:1::-1h:block')).toThrow();
expect(() => parseConfigRules('foo:bar:1:1s::block')).toThrow();
expect(() => parseConfigRules('foo:bar:1')).toThrow();
expect(() => parseConfigRules('foo!23:ip:1:1s:1s:')).toThrow();
expect(() => parseConfigRules('foo!23:ip:1:1s:1s:foo')).toThrow();
});
});

Expand Down
4 changes: 2 additions & 2 deletions libs/accounts/recovery-phone/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/recovery-phone/jest.config.ts",
"testPathPattern": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
"testPathPatterns": ["^(?!.*\\.in\\.spec\\.ts$).*$"]
}
},
"test-integration": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "libs/accounts/recovery-phone/jest.config.ts",
"testPathPattern": ["\\.in\\.spec\\.ts$"]
"testPathPatterns": ["\\.in\\.spec\\.ts$"]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ describe('RecoveryPhoneManager', () => {
mockLookUpData
);

expect(insertIntoSpy).toBeCalledWith('recoveryPhones');
expect(insertIntoSpy).toHaveBeenCalledWith('recoveryPhones');
});

it('should fail for invalid format phone number', async () => {
Expand Down Expand Up @@ -171,7 +171,7 @@ describe('RecoveryPhoneManager', () => {
const result = await recoveryPhoneManager.removePhoneNumber(
mockPhone.uid.toString('hex')
);
expect(deleteFromSpy).toBeCalledWith('recoveryPhones');
expect(deleteFromSpy).toHaveBeenCalledWith('recoveryPhones');
expect(result).toBe(true);
});

Expand All @@ -183,7 +183,7 @@ describe('RecoveryPhoneManager', () => {
await expect(
recoveryPhoneManager.removePhoneNumber(uid.toString('hex'))
).rejects.toThrow('Recovery number does not exist');
expect(deleteFromSpy).toBeCalledWith('recoveryPhones');
expect(deleteFromSpy).toHaveBeenCalledWith('recoveryPhones');
});

it('should change a recovery phone', async () => {
Expand Down
Loading