mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
feat(settings): set the Google Maps key through PLACES_API_KEY
The server already put PLACES_API_KEY ahead of the key saved in the admin panel, but nothing said so: the variable was in no template and the admin field kept showing a stored value that no search used. GET /me/settings now answers env_keys, the variable behind each key the environment sets (Google, Unsplash, Amap), and null for that key's value. The admin field turns read-only and names the variable, Test still probes the key a search resolves to, and a save leaves those names out so the stored fallback survives. The variable is documented in .env.example, docker-compose.yml, the Helm chart (as a secret) and the wiki. Addresses discussion #1881.
This commit is contained in:
@@ -38,7 +38,7 @@ describe('OVERPASS_TIMEOUT_MS in the templates', () => {
|
||||
describe('the Places and Amap switches in the templates', () => {
|
||||
// The index is asked by default and the only way to stop that is this
|
||||
// variable, so an operator has to be able to find it where they look.
|
||||
const documented = ['TREK_PLACES_ENABLED', 'TREK_PLACES_URL', 'AMAP_API_KEY', 'AMAP_API_SECRET', 'AMAP_API_BASE'];
|
||||
const documented = ['TREK_PLACES_ENABLED', 'TREK_PLACES_URL', 'PLACES_API_KEY', 'AMAP_API_KEY', 'AMAP_API_SECRET', 'AMAP_API_BASE'];
|
||||
|
||||
it('.env.example documents every one of them', () => {
|
||||
for (const name of documented) {
|
||||
@@ -66,12 +66,12 @@ describe('the Places and Amap switches in the templates', () => {
|
||||
expect(helmConfigMap).toContain('{{- if not (kindIs "invalid" .Values.env.TREK_PLACES_ENABLED) }}');
|
||||
});
|
||||
|
||||
it('the Helm chart carries the Amap credentials in the Secret, never in the ConfigMap', () => {
|
||||
it('the Helm chart carries the Google and Amap credentials in the Secret, never in the ConfigMap', () => {
|
||||
// A ConfigMap is readable by anyone who can read the namespace; the key and
|
||||
// its signing secret belong next to the other credentials, in both the
|
||||
// plain and the generated branch of the Secret, and the pod reads them from
|
||||
// there like it reads the Unsplash key.
|
||||
for (const name of ['AMAP_API_KEY', 'AMAP_API_SECRET']) {
|
||||
for (const name of ['PLACES_API_KEY', 'AMAP_API_KEY', 'AMAP_API_SECRET']) {
|
||||
expect(helmValues).toContain(` ${name}: ""`);
|
||||
expect(helmSecret).toContain(`${name}: {{ .Values.secretEnv.${name} | b64enc | quote }}`);
|
||||
expect(helmSecret).toContain(`${name}: {{ .Values.secretEnv.${name} }}`);
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
readInstanceApiKey,
|
||||
writeInstanceApiKey,
|
||||
resolveApiKey,
|
||||
operatorKeyVariables,
|
||||
} from '../../../../src/nest/settings/instance-api-keys';
|
||||
|
||||
const db = new DatabaseService(testDb);
|
||||
@@ -137,3 +138,43 @@ describe('instance API keys', () => {
|
||||
expect(resolveApiKey(db, 'unsplash_api_key', user.id, undefined)).toEqual({ key: null, source: null });
|
||||
});
|
||||
});
|
||||
|
||||
describe('operatorKeyVariables (#1881)', () => {
|
||||
const VARS = ['PLACES_API_KEY', 'UNSPLASH_ACCESS_KEY', 'AMAP_API_KEY'] as const;
|
||||
const saved: Partial<Record<(typeof VARS)[number], string>> = {};
|
||||
beforeEach(() => {
|
||||
for (const v of VARS) {
|
||||
saved[v] = process.env[v];
|
||||
delete process.env[v];
|
||||
}
|
||||
});
|
||||
afterAll(() => {
|
||||
for (const v of VARS) {
|
||||
if (saved[v] === undefined) delete process.env[v];
|
||||
else process.env[v] = saved[v];
|
||||
}
|
||||
});
|
||||
|
||||
it('INSTKEY-010: names nothing while no variable is set', () => {
|
||||
expect(operatorKeyVariables()).toEqual({});
|
||||
});
|
||||
|
||||
it('INSTKEY-011: names the variable behind each key that has one, never its value', () => {
|
||||
process.env.PLACES_API_KEY = 'google-from-env';
|
||||
process.env.UNSPLASH_ACCESS_KEY = 'unsplash-from-env';
|
||||
process.env.AMAP_API_KEY = 'amap-from-env';
|
||||
const set = operatorKeyVariables();
|
||||
expect(set).toEqual({
|
||||
maps_api_key: 'PLACES_API_KEY',
|
||||
unsplash_api_key: 'UNSPLASH_ACCESS_KEY',
|
||||
amap_api_key: 'AMAP_API_KEY',
|
||||
});
|
||||
expect(JSON.stringify(set)).not.toContain('from-env');
|
||||
});
|
||||
|
||||
it('INSTKEY-012: a blank variable does not count as set', () => {
|
||||
process.env.PLACES_API_KEY = '';
|
||||
process.env.UNSPLASH_ACCESS_KEY = ' ';
|
||||
expect(operatorKeyVariables()).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -157,6 +157,30 @@ describe('getSettings', () => {
|
||||
// getSettings returns the stored key to the admin.
|
||||
expect(profile.getSettings(user.id).settings?.unsplash_api_key).toBe('unsplash-secret-key');
|
||||
});
|
||||
|
||||
it('AUTH-DB-010c: a key set in the environment comes back as its variable name, not a value (#1881)', () => {
|
||||
const prev = process.env.PLACES_API_KEY;
|
||||
process.env.PLACES_API_KEY = 'google-from-env';
|
||||
try {
|
||||
const { user } = createAdmin(testDb);
|
||||
profile.updateApiKeys(user.id, { maps_api_key: 'stored-but-overridden', unsplash_api_key: 'stored-unsplash' });
|
||||
const settings = profile.getSettings(user.id).settings;
|
||||
// Neither the stored value nobody searches with nor the operator's own.
|
||||
expect(settings?.maps_api_key).toBeNull();
|
||||
expect(settings?.env_keys).toEqual({ maps_api_key: 'PLACES_API_KEY' });
|
||||
expect(JSON.stringify(settings)).not.toContain('google-from-env');
|
||||
// A key without a variable reads as before.
|
||||
expect(settings?.unsplash_api_key).toBe('stored-unsplash');
|
||||
} finally {
|
||||
if (prev === undefined) delete process.env.PLACES_API_KEY;
|
||||
else process.env.PLACES_API_KEY = prev;
|
||||
}
|
||||
});
|
||||
|
||||
it('AUTH-DB-010d: without a variable env_keys is empty', () => {
|
||||
const { user } = createAdmin(testDb);
|
||||
expect(profile.getSettings(user.id).settings?.env_keys).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user