diff --git a/readme.md b/readme.md index 211d260..061bf76 100644 --- a/readme.md +++ b/readme.md @@ -269,6 +269,17 @@ Default: `false` Watch for any changes in the config file and call the callback for `onDidChange` or `onDidAnyChange` if set. This is useful if there are multiple processes changing the same config file. +#### configFileMode + +Type: `number`\ +Default: `0o666` + +The [mode](https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation) that will be used for the config file. + +You would usually not need this, but it could be useful if you want to restrict the permissions of the config file. Setting a permission such as `0o600` would result in a config file that can only be accessed by the user running the program. + +Note that setting restrictive permissions can cause problems if different users need to read the file. A common problem is a user running your tool with and without `sudo` and then not being able to access the config the second time. + ### Instance You can use [dot-notation](https://github.com/sindresorhus/dot-prop) in a `key` to access nested properties. diff --git a/source/index.ts b/source/index.ts index f521acd..d50646d 100644 --- a/source/index.ts +++ b/source/index.ts @@ -67,6 +67,7 @@ class Conf = Record> implements I projectSuffix: 'nodejs', clearInvalidConfig: false, accessPropertiesByDotNotation: true, + configFileMode: 0o666, ...partialOptions }; @@ -461,16 +462,16 @@ class Conf = Record> implements I // Temporary workaround for Conf being packaged in a Ubuntu Snap app. // See https://github.com/sindresorhus/conf/pull/82 if (process.env.SNAP) { - fs.writeFileSync(this.path, data); + fs.writeFileSync(this.path, data, {mode: this.#options.configFileMode}); } else { try { - atomically.writeFileSync(this.path, data); + atomically.writeFileSync(this.path, data, {mode: this.#options.configFileMode}); } catch (error: any) { // Fix for https://github.com/sindresorhus/electron-store/issues/106 // Sometimes on Windows, we will get an EXDEV error when atomic writing // (even though to the same directory), so we fall back to non atomic write if (error?.code === 'EXDEV') { - fs.writeFileSync(this.path, data); + fs.writeFileSync(this.path, data, {mode: this.#options.configFileMode}); return; } diff --git a/source/types.ts b/source/types.ts index be8885b..1d6e77c 100644 --- a/source/types.ts +++ b/source/types.ts @@ -212,6 +212,17 @@ export interface Options { @default false */ readonly watch?: boolean; + + /** + The [mode](https://en.wikipedia.org/wiki/File-system_permissions#Numeric_notation) that will be used for the config file. + + You would usually not need this, but it could be useful if you want to restrict the permissions of the config file. Setting a permission such as `0o600` would result in a config file that can only be accessed by the user running the program. + + Note that setting restrictive permissions can cause problems if different users need to read the file. A common problem is a user running your tool with and without `sudo` and then not being able to access the config the second time. + + @default 0o666 + */ + readonly configFileMode: number; } export type Migrations = Record) => void>; diff --git a/test/index.test-d.ts b/test/index.test-d.ts index b73f58d..066947d 100644 --- a/test/index.test-d.ts +++ b/test/index.test-d.ts @@ -26,6 +26,7 @@ new Conf({encryptionKey: Buffer.from('')}); new Conf({encryptionKey: new Uint8Array([1])}); new Conf({encryptionKey: new DataView(new ArrayBuffer(2))}); new Conf({fileExtension: '.foo'}); +new Conf({configFileMode: 0o600}); new Conf({clearInvalidConfig: false}); new Conf({serialize: () => 'foo'}); new Conf({deserialize: () => ({foo: 'foo', unicorn: true})});