1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-01 08:31:59 +00:00

fix(cli): auth file should be chmod 600 (#6925)

* wip new tests

* test for auth file mode

* check perms internally

* chore: lint
This commit is contained in:
Jonathan Jogenfors 2024-02-06 00:40:22 +01:00 committed by GitHub
parent 6ed33da2a4
commit ce6dc3b7af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 45 additions and 23 deletions

32
cli/package-lock.json generated
View file

@ -3810,6 +3810,15 @@
"get-func-name": "^2.0.1"
}
},
"node_modules/lru-cache": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
"dev": true,
"engines": {
"node": "14 || >=16.14"
}
},
"node_modules/magic-string": {
"version": "0.30.5",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
@ -4182,15 +4191,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
"integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
"dev": true,
"engines": {
"node": "14 || >=16.14"
}
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@ -8566,6 +8566,12 @@
"get-func-name": "^2.0.1"
}
},
"lru-cache": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
"dev": true
},
"magic-string": {
"version": "0.30.5",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz",
@ -8834,14 +8840,6 @@
"requires": {
"lru-cache": "^9.1.1 || ^10.0.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"dependencies": {
"lru-cache": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
"integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
"dev": true
}
}
},
"path-type": {

View file

@ -8,11 +8,11 @@ export abstract class BaseCommand {
protected user!: UserResponseDto;
protected serverVersion!: ServerVersionResponseDto;
constructor(options: { config?: string }) {
if (!options.config) {
constructor(options: { configDirectory?: string }) {
if (!options.configDirectory) {
throw new Error('Config directory is required');
}
this.sessionService = new SessionService(options.config);
this.sessionService = new SessionService(options.configDirectory);
}
public async connect(): Promise<void> {

View file

@ -82,7 +82,7 @@ export class SessionService {
}
}
await writeFile(this.authPath, yaml.stringify({ instanceUrl, apiKey }));
await writeFile(this.authPath, yaml.stringify({ instanceUrl, apiKey }), { mode: 0o600 });
console.log('Wrote auth info to ' + this.authPath);

View file

@ -7,7 +7,7 @@ export const TEST_AUTH_FILE = path.join(TEST_CONFIG_DIR, 'auth.yml');
export const TEST_IMMICH_INSTANCE_URL = 'https://test/api';
export const TEST_IMMICH_API_KEY = 'pNussssKSYo5WasdgalvKJ1n9kdvaasdfbluPg';
export const CLI_BASE_OPTIONS = { config: TEST_CONFIG_DIR };
export const CLI_BASE_OPTIONS = { configDirectory: TEST_CONFIG_DIR };
export const setup = async () => {
const api = new ImmichApi(process.env.IMMICH_INSTANCE_URL as string, '');

View file

@ -1,6 +1,8 @@
import { restoreTempFolder, testApp } from '@test-utils';
import { CLI_BASE_OPTIONS, setup, spyOnConsole } from 'test/cli-test-utils';
import { CLI_BASE_OPTIONS, TEST_AUTH_FILE, deleteAuthFile, setup, spyOnConsole } from 'test/cli-test-utils';
import { readFile, stat } from 'node:fs/promises';
import { LoginCommand } from '../../src/commands/login';
import yaml from 'yaml';
describe(`login-key (e2e)`, () => {
let apiKey: string;
@ -20,6 +22,7 @@ describe(`login-key (e2e)`, () => {
afterAll(async () => {
await testApp.teardown();
await restoreTempFolder();
deleteAuthFile();
});
beforeEach(async () => {
@ -28,6 +31,8 @@ describe(`login-key (e2e)`, () => {
const api = await setup();
apiKey = api.apiKey;
deleteAuthFile();
});
it('should error when providing an invalid API key', async () => {
@ -39,4 +44,23 @@ describe(`login-key (e2e)`, () => {
it('should log in when providing the correct API key', async () => {
await new LoginCommand(CLI_BASE_OPTIONS).run(instanceUrl, apiKey);
});
it('should create an auth file when logging in', async () => {
await new LoginCommand(CLI_BASE_OPTIONS).run(instanceUrl, apiKey);
const data: string = await readFile(TEST_AUTH_FILE, 'utf8');
const parsedConfig = yaml.parse(data);
expect(parsedConfig).toEqual(expect.objectContaining({ instanceUrl, apiKey }));
});
it('should create an auth file with chmod 600', async () => {
await new LoginCommand(CLI_BASE_OPTIONS).run(instanceUrl, apiKey);
const stats = await stat(TEST_AUTH_FILE);
const mode = (stats.mode & 0o777).toString(8);
expect(mode).toEqual('600');
});
});