Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ehmicky/unix-permissions

Swiss Army knife for Unix permissions
https://github.com/ehmicky/unix-permissions

access-control acl chmod cli javascript library nodejs octal permissions posix setgid setuid shell stat sticky symbolic terminal typescript umask unix

Last synced: 5 days ago
JSON representation

Swiss Army knife for Unix permissions

Awesome Lists containing this project

README

        


unix-permissions logo

[![Node](https://img.shields.io/badge/-Node.js-808080?logo=node.js&colorA=404040&logoColor=66cc33)](https://www.npmjs.com/package/unix-permissions)
[![Browsers](https://img.shields.io/badge/-Browsers-808080?logo=firefox&colorA=404040)](https://unpkg.com/unix-permissions?module)
[![TypeScript](https://img.shields.io/badge/-Typed-808080?logo=typescript&colorA=404040&logoColor=0096ff)](/src/main.d.ts)
[![Codecov](https://img.shields.io/badge/-Tested%20100%25-808080?logo=codecov&colorA=404040)](https://codecov.io/gh/ehmicky/unix-permissions)
[![Minified size](https://img.shields.io/bundlephobia/minzip/unix-permissions?label&colorA=404040&colorB=808080&logo=webpack)](https://bundlephobia.com/package/unix-permissions)
[![Mastodon](https://img.shields.io/badge/-Mastodon-808080.svg?logo=mastodon&colorA=404040&logoColor=9590F9)](https://fosstodon.org/@ehmicky)
[![Medium](https://img.shields.io/badge/-Medium-808080.svg?logo=medium&colorA=404040)](https://medium.com/@ehmicky)

Swiss Army knife for Unix permissions.

[Unix file permissions](https://en.wikipedia.org/wiki/File_system_permissions)
can take many [shapes](#permission-types): [symbolic](docs/types.md#symbolic)
(`ug+rw`), [octal](docs/types.md#octal) (`660`) or a
[list of characters](docs/types.md#stat) (`drw-rw----`). This library enables
using any of [these](#permission-types) (instead of being limited to a single
one) with any [Node.js](#examples) or [CLI command](#examples).

This library can also perform operations on Unix permissions such as:

- [testing](docs/API.md#containpermission-permissions),
[setting](docs/API.md#setpermission-permissions) and
[unsetting](docs/API.md#notpermission). Using bitwise operations (`|`, `&`,
`^`, `~`) can be tedious and error-prone otherwise.
- [validating](docs/API.md#normalizepermission) syntax.
- [normalizing](docs/API.md#normalizepermission). For example `u+r,u+w` can be
shortened to `u+rw`.
- [inverting](docs/API.md#invertpermission). For example a
[`umask`](https://linux.die.net/man/2/umask) of `117` means new files will be
created with `661` permissions.
- checking the [minimal](docs/API.md#minpermissions) or
[maximal](docs/API.md#maxpermissions) permissions among a list of them. This
can be useful to aggregate all the permissions of several files, e.g. during a
directory recursion.

Permissions are manipulated as strings, not as file paths. This means you must
use other utilities (such as [`chmod`](https://linux.die.net/man/1/chmod) or
[`stat`](https://linux.die.net/man/2/stat)) to get and set file permissions
using those strings.

# Hire me

Please
[reach out](https://www.linkedin.com/feed/update/urn:li:activity:7117265228068716545/)
if you're looking for a Node.js API or CLI engineer (11 years of experience).
Most recently I have been [Netlify Build](https://github.com/netlify/build)'s
and [Netlify Plugins](https://www.netlify.com/products/build/plugins/)'
technical lead for 2.5 years. I am available for full-time remote positions.

# Examples

In JavaScript:

```js
import { convert } from 'unix-permissions'

// Retrieve a file's permission as an object like
// `{ user: { write: false, read: true, ... }, ... }` instead of a number
convert.object(fs.statSync('/etc/passwd').mode)

// Set a file's permission using `symbolic` notation instead of a number
fs.chmod('/etc/passwd', convert.number('a=r'))

// Set a file's permission using `symbolic` notation instead of a number
fs.writeFile('/my/file', content, { mode: convert.number('a=r') })

// Disallow executing new files using `umask`
process.umask(convert.number(invert('a-x')))

// If your library takes Unix permissions as input, using
// `unix-permissions` under the hood lets your users choose their
// favorite Unix permissions type.
myLibrary.method({ mode: 'a-wx' })
myLibrary.method({ mode: '444' })
```

On the command line:

```bash
$ stat -c "%a" /etc/passwd
644

$ unix-permissions convert.symbolic "$(stat -c "%a" /etc/passwd)"
u=rw,go=r
```

# Install

```bash
npm install unix-permissions
```

This package works in both Node.js >=18.18.0 and
[browsers](https://raw.githubusercontent.com/ehmicky/dev-tasks/main/src/browserslist).

This is an ES module. It must be loaded using
[an `import` or `import()` statement](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c),
not `require()`. If TypeScript is used, it must be configured to
[output ES modules](https://www.typescriptlang.org/docs/handbook/esm-node.html),
not CommonJS.

# Usage (JavaScript)

```js
import { convert } from 'unix-permissions'

// `permission` will be set to `rw-rw----`
const permission = convert.stat('660')
```

Several methods other than `convert` are available but they mostly follow the
same pattern. Permission strings are passed as input and returned as output.

# Usage (CLI)

```bash
$ unix-permissions convert.stat 660
rw-rw----
```

The same methods as in JavaScript are available. Exit code will be `1` if an
error occurred, e.g. if the permission syntax is invalid.

# Permission types

You can use any of the following permission types as input. You can also
[`convert()`](docs/API.md#convertoctalnumberstatsymbolicobjectpermission)
between them:

- [`octal`](docs/types.md#octal) strings like `"422"`
- decimal [`number`](docs/types.md#number) like `274`
- [`stat`](docs/types.md#stat) like `rw-rw-r--`
- [`symbolic`](docs/types.md#symbolic) like `a+rw`
- [`object`](docs/types.md#object) like
`{ user: { read: true, write: false, execute: false }, group: { write: false }, others: { write: false } }`

Special permissions ([setuid](https://en.wikipedia.org/wiki/Setuid),
[setgid](https://en.wikipedia.org/wiki/Setuid),
[sticky](https://en.wikipedia.org/wiki/Sticky_bit)) can be used.

Please see the [types full documentation](docs/types.md).

# Methods

## convert.octal|number|stat|symbolic|object(permission)

Converts `permission` to another type.\
[Full documentation](docs/API.md#convertoctalnumberstatsymbolicobjectpermission).

## type(permission)

Returns the `permission`'s type or `invalid`.\
[Full documentation](docs/API.md#typepermission).

## normalize(permission)

Normalizes a `permission` to its canonical shape. Throw if `permission` is
invalid.\
[Full documentation](docs/API.md#normalizepermission).

## positive(permission)

Removes all negative permissions.\
[Full documentation](docs/API.md#positivepermission).

## contain(permission, permissions...)

Tests whether `permission` includes `permissions`.\
[Full documentation](docs/API.md#containpermission-permissions).

## equal(permission, permissions...)

Tests whether `permission` equals exactly `permissions`.\
[Full documentation](docs/API.md#equalpermission-permissions).

## set(permission, permissions...)

Sets `permissions` on `permission`. This is useful to avoid error-prone bitwise
operations (`|`, `&`, `^`, `~`).\
[Full documentation](docs/API.md#setpermission-permissions).

## not(permission)

Inverts `permission` including special permissions. This can be used in
combination with `set()` to unset `permissions` instead of setting them.\
[Full documentation](docs/API.md#notpermission).

## invert(permission)

Inverts `permission` and removes special permissions.\
[Full documentation](docs/API.md#invertpermission).

## min(permissions...)

Retrieves the lowest permissions among all arguments.\
[Full documentation](docs/API.md#minpermissions).

## max(permissions...)

Retrieves the highest permissions among all arguments.\
[Full documentation](docs/API.md#maxpermissions).

# Support

For any question, _don't hesitate_ to [submit an issue on GitHub](../../issues).

Everyone is welcome regardless of personal background. We enforce a
[Code of conduct](CODE_OF_CONDUCT.md) in order to promote a positive and
inclusive environment.

# Contributing

This project was made with ❤️. The simplest way to give back is by starring and
sharing it online.

If the documentation is unclear or has a typo, please click on the page's `Edit`
button (pencil icon) and suggest a correction.

If you would like to help us fix a bug or add a new feature, please check our
[guidelines](CONTRIBUTING.md). Pull requests are welcome!