From 0352fc5c0a81a036df0119d5e526f69532d2f4bf Mon Sep 17 00:00:00 2001 From: Rutuparn Puranik Date: Thu, 19 Feb 2026 03:51:54 +0530 Subject: [PATCH 1/2] Fix #18859: Correct City/Country language display in sync flow --- .gitignore | 4 + packages/fxa-auth-server/lib/geodb.js | 4 +- .../lib/senders/emails/sass-compile-files.ts | 10 +- packages/fxa-auth-server/lib/server.js | 2 +- packages/fxa-auth-server/test/local/geodb.js | 91 +++++++++++++++++++ .../src/components/DeviceInfoBlock/index.tsx | 10 +- packages/fxa-shared/express/geo-locate.ts | 6 +- 7 files changed, 113 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index ab026be376e..7e97e20761a 100644 --- a/.gitignore +++ b/.gitignore @@ -194,3 +194,7 @@ libs/shared/cms/src/__generated__/graphql.js # Sentry Config File .env.sentry-build-plugin + +# Local build logs +build_log.txt +build_log_2.txt diff --git a/packages/fxa-auth-server/lib/geodb.js b/packages/fxa-auth-server/lib/geodb.js index 29aa3741360..d83f66b9c9d 100644 --- a/packages/fxa-auth-server/lib/geodb.js +++ b/packages/fxa-auth-server/lib/geodb.js @@ -22,7 +22,7 @@ geodb(knownIp); module.exports = (log) => { log.info('geodb.start', { enabled: config.enabled, dbPath: config.dbPath }); - return (ip) => { + return (ip, locale) => { if (config.enabled === false) { return {}; } @@ -37,7 +37,7 @@ module.exports = (log) => { return config.locationOverride; } - const location = geodb(ip); + const location = geodb(ip, { userLocale: locale }); const accuracy = location.accuracy; let confidence = 'fxa.location.accuracy.'; diff --git a/packages/fxa-auth-server/lib/senders/emails/sass-compile-files.ts b/packages/fxa-auth-server/lib/senders/emails/sass-compile-files.ts index 70680755e8c..80ca8570ac0 100644 --- a/packages/fxa-auth-server/lib/senders/emails/sass-compile-files.ts +++ b/packages/fxa-auth-server/lib/senders/emails/sass-compile-files.ts @@ -3,13 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { renderSync } from 'sass'; -import { - writeFileSync, - mkdirSync, - existsSync, - rmdirSync, - readdirSync, -} from 'fs'; +import { writeFileSync, mkdirSync, existsSync, rmSync, readdirSync } from 'fs'; import path from 'path'; const getDirectories = (source: string) => @@ -38,7 +32,7 @@ async function compileSass(dir: string, subdir: string) { async function main(directories: Record) { // remove css directory if already present if (existsSync(path.join(__dirname, 'css'))) { - rmdirSync(path.join(__dirname, 'css'), { recursive: true }); + rmSync(path.join(__dirname, 'css'), { recursive: true, force: true }); } mkdirSync(path.join(__dirname, 'css')); diff --git a/packages/fxa-auth-server/lib/server.js b/packages/fxa-auth-server/lib/server.js index f9eb3db0ce3..a567c0304af 100644 --- a/packages/fxa-auth-server/lib/server.js +++ b/packages/fxa-auth-server/lib/server.js @@ -209,7 +209,7 @@ async function create(log, error, config, routes, db, statsd, glean, customs) { userAgent(request.headers['user-agent']) ); defineLazyGetter(request.app, 'geo', () => - getGeoData(request.app.clientAddress) + getGeoData(request.app.clientAddress, request.app.locale) ); defineLazyGetter(request.app, 'metricsContext', () => metricsContext.get(request) diff --git a/packages/fxa-auth-server/test/local/geodb.js b/packages/fxa-auth-server/test/local/geodb.js index aaa2697b2d0..c709639108f 100644 --- a/packages/fxa-auth-server/test/local/geodb.js +++ b/packages/fxa-auth-server/test/local/geodb.js @@ -64,4 +64,95 @@ describe('geodb', () => { const geoData = getGeoData('8.8.8.8'); assert.deepEqual(geoData, {}); }); + it('passes userLocale to geodb', () => { + const moduleMocks = { + '../config': { + default: { + get: function (item) { + if (item === 'geodb') { + return { + enabled: true, + locationOverride: {}, + }; + } + }, + }, + }, + 'fxa-geodb': function (config) { + return function (ip, options) { + if (options && options.userLocale === 'fr') { + return { + city: { names: { fr: 'Paris' } }, + country: { names: { fr: 'France', iso_code: 'FR' } }, + accuracy: 10, + }; + } + return {}; + }; + }, + }; + const thisMockLog = mockLog({}); + + const getGeoData = proxyquire(modulePath, moduleMocks)(thisMockLog); + // Call with IP and locale 'fr' + const geoData = getGeoData('8.8.8.8', 'fr'); + + // effective return from getGeoData constructs the object from geodb result + // geodb.js:63: city: location.city, country: location.country + // But wait, geodb.js uses location.city directly. + // In fxa-geodb/lib/fxa-geodb.js it returns new Location(locationData, userLocale). + // Location object has .city, .country etc. + // So my mock should return an object that looks like a Location instance or has those properties. + // fxa-geodb returns: { city: 'Paris', country: 'France', ... } if localized. + // So let's return that structure directly from mock. + + // Re-mocking to match expected geodb return + }); + + it('passes userLocale to geodb and returns localized data', () => { + const moduleMocks = { + '../config': { + default: { + get: function (item) { + if (item === 'geodb') { + return { + enabled: true, + locationOverride: {}, + }; + } + }, + }, + }, + 'fxa-geodb': function (config) { + return function (ip, options) { + if (options && options.userLocale === 'fr') { + return { + city: 'Paris', + country: 'France', + countryCode: 'FR', + accuracy: 10, + }; + } + return { + city: 'Mountain View', + country: 'United States', + countryCode: 'US', + accuracy: 10, + }; + }; + }, + }; + const thisMockLog = mockLog({}); + + const getGeoData = proxyquire(modulePath, moduleMocks)(thisMockLog); + + // Call with 'fr' + const geoDataFr = getGeoData('8.8.8.8', 'fr'); + assert.equal(geoDataFr.location.country, 'France'); + assert.equal(geoDataFr.location.city, 'Paris'); + + // Call with 'en' or undefined (defaults to mock else) + const geoDataEn = getGeoData('8.8.8.8', 'en'); + assert.equal(geoDataEn.location.country, 'United States'); + }); }); diff --git a/packages/fxa-settings/src/components/DeviceInfoBlock/index.tsx b/packages/fxa-settings/src/components/DeviceInfoBlock/index.tsx index 06266db1168..e3ded38e427 100644 --- a/packages/fxa-settings/src/components/DeviceInfoBlock/index.tsx +++ b/packages/fxa-settings/src/components/DeviceInfoBlock/index.tsx @@ -61,13 +61,19 @@ export const DeviceInfoBlock = ({ remoteMetadata }: DeviceInfoBlockProps) => { return (
{deviceName &&

{deviceName}

} - +

{`${deviceFamily} on ${deviceOS}`}

- +

{`IP address: ${ipAddress}`}

diff --git a/packages/fxa-shared/express/geo-locate.ts b/packages/fxa-shared/express/geo-locate.ts index 3172a0dd900..e5af11bf632 100644 --- a/packages/fxa-shared/express/geo-locate.ts +++ b/packages/fxa-shared/express/geo-locate.ts @@ -13,7 +13,11 @@ export const geolocate = (log: Logger) => (request: express.Request) => { try { - return geodb(remoteAddress(request).clientAddress); + // @ts-ignore - locale/lang might not be in standard Request type but injected by middleware + const locale = request.locale || request.lang; + return geodb(remoteAddress(request).clientAddress, { + userLocale: locale, + }); } catch (err) { log.error('geodb.error', err); return {}; From 67a19cf05d5b2a542aa618a4ab6a8c6a89e21a3f Mon Sep 17 00:00:00 2001 From: Rutuparn Puranik Date: Thu, 19 Feb 2026 03:51:55 +0530 Subject: [PATCH 2/2] Refactor: remove unprofessional comments and cleanup geodb tests --- packages/fxa-auth-server/test/local/geodb.js | 45 -------------------- 1 file changed, 45 deletions(-) diff --git a/packages/fxa-auth-server/test/local/geodb.js b/packages/fxa-auth-server/test/local/geodb.js index c709639108f..45cd19992e4 100644 --- a/packages/fxa-auth-server/test/local/geodb.js +++ b/packages/fxa-auth-server/test/local/geodb.js @@ -64,51 +64,6 @@ describe('geodb', () => { const geoData = getGeoData('8.8.8.8'); assert.deepEqual(geoData, {}); }); - it('passes userLocale to geodb', () => { - const moduleMocks = { - '../config': { - default: { - get: function (item) { - if (item === 'geodb') { - return { - enabled: true, - locationOverride: {}, - }; - } - }, - }, - }, - 'fxa-geodb': function (config) { - return function (ip, options) { - if (options && options.userLocale === 'fr') { - return { - city: { names: { fr: 'Paris' } }, - country: { names: { fr: 'France', iso_code: 'FR' } }, - accuracy: 10, - }; - } - return {}; - }; - }, - }; - const thisMockLog = mockLog({}); - - const getGeoData = proxyquire(modulePath, moduleMocks)(thisMockLog); - // Call with IP and locale 'fr' - const geoData = getGeoData('8.8.8.8', 'fr'); - - // effective return from getGeoData constructs the object from geodb result - // geodb.js:63: city: location.city, country: location.country - // But wait, geodb.js uses location.city directly. - // In fxa-geodb/lib/fxa-geodb.js it returns new Location(locationData, userLocale). - // Location object has .city, .country etc. - // So my mock should return an object that looks like a Location instance or has those properties. - // fxa-geodb returns: { city: 'Paris', country: 'France', ... } if localized. - // So let's return that structure directly from mock. - - // Re-mocking to match expected geodb return - }); - it('passes userLocale to geodb and returns localized data', () => { const moduleMocks = { '../config': {