# privileged

Since 5.15.0

Helpers for working with Sitevision privileged actions from `@sitevision/api/server/privileged`.

The API wraps `privileged.doPrivilegedAction()` and adds two optional checks before the callback is executed:

* Verify that privileged actions are configured for the app.
* Verify that the privileged user has the permissions your action requires on a target node.

## Import

```js
import {
  privilegedAction,
  isPrivilegedConfigured,
  getPrivilegedUser,
} from '@soleil-se/app-util/server/privileged';
```

## privilegedAction(callback, options)

Execute a callback as a privileged action.

| Param    | Type                      | Description                                        |
| -------- | ------------------------- | -------------------------------------------------- |
| callback | `() => T`                 | Function to execute inside `doPrivilegedAction()`. |
| options  | `PrivilegedActionOptions` | Optional configuration for pre-flight checks.      |

**Returns:** `T` - The return value from the callback.

**Throws:** `Error` - If the callback throws, that same error is rethrown. An error is also thrown before execution if `requireConfiguration` is `true` and privileged actions are not configured, or if `requiredPermissions` is provided and the privileged user is missing one or more of those permissions.

### Options

| Property             | Type           | Default                               | Description                                                        |
| -------------------- | -------------- | ------------------------------------- | ------------------------------------------------------------------ |
| requireConfiguration | `boolean`      | `true`                                | Throw error if privileged actions are not configured.              |
| requiredPermissions  | `Permission[]` | `[]`                                  | Permissions the privileged user must have on the permissions node. |
| permissionsNode      | `Node`         | `PortletContextUtil.getCurrentPage()` | Node to check permissions against.                                 |

### Basic usage

```js
import { privilegedAction } from '@soleil-se/app-util/server/privileged';


privilegedAction(() => {
  // Code here runs inside Sitevision's privileged action context.
  doSomethingThatRequiresPrivileges();
});
```

Also supports returning values from the callback:

```js
import { privilegedAction } from '@soleil-se/app-util/server/privileged';


const result = privilegedAction(() => {
  // Code here runs inside Sitevision's privileged action context.
  return doSomethingThatRequiresPrivileges();
});
```

### Require privileged configuration

Use `requireConfiguration` when your code still should run even if privileged actions are not configured.

```js
import { privilegedAction } from '@soleil-se/app-util/server/privileged';


const article = privilegedAction(() => {
  // Code here runs inside Sitevision's privileged action context.
  return doSomethingThatRequiresPrivileges();
}, { requireConfiguration: false });
```

### Require permissions before execution

Use `requiredPermissions` to verify the privileged user can perform the action on a specific node before the callback runs.

```js
import Permission from '@sitevision/api/server/PermissionUtil.Permission';
import PortletContextUtil from '@sitevision/api/server/PortletContextUtil';
import { privilegedAction } from '@soleil-se/app-util/server/privileged';


const node = PortletContextUtil.getCurrentPage();


privilegedAction(() => {
  // Code here runs inside Sitevision's privileged action context.
  return doSomethingThatRequiresPrivileges();
}, {
  requiredPermissions: [Permission.WRITE, Permission.PUBLISH],
  permissionsNode: node, // Optional, defaults to the current page
});
```

If `requiredPermissions` is configured and one or more permissions are missing, the function throws an error listing the missing permissions.

### Return values and thrown errors

`privilegedAction()` returns whatever your callback returns. If the callback itself throws, the original error is rethrown after the privileged action finishes. The other validation errors are only thrown when the related options are configured.

```js
import { privilegedAction } from '@soleil-se/app-util/server/privileged';


try {
  const result = privilegedAction(() => {
    if (!node) {
      throw new Error('Node is missing');
    }
    return getSomethingThatRequiresPrivileges();
  });


  console.log(result);
} catch (error) {
  console.error(error.message);
}
```

## isPrivilegedConfigured()

Check if privileged actions are configured for the current app.

**Returns:** `boolean` - `true` if the app has a configured privileged user, otherwise `false`.

```js
import { isPrivilegedConfigured, privilegedAction } from '@soleil-se/app-util/server/privileged';


if (isPrivilegedConfigured()) {
  privilegedAction(() => {
    doSomethingThatRequiresPrivileges();
  });
}
```

This is useful when privileged behavior is optional and you want to gracefully skip it instead of throwing an error.

## getPrivilegedUser()

Get the privileged action user.

**Returns:** `Node | null` - The configured privileged user node, or `null` if privileged actions are not configured.

```js
import { getPrivilegedUser } from '@soleil-se/app-util/server/privileged';


const privilegedUser = getPrivilegedUser();


if (privilegedUser) {
  console.log(privilegedUser.getIdentifier());
}
```

## Notes

* Permission checks are performed against `permissionsNode`, which defaults to `PortletContextUtil.getCurrentPage()`.
* If no privileged user is configured, permission checks fall back to `PortletContextUtil.getCurrentUser()`.
* Use this helper for short, explicit privileged operations. Keep the privileged callback focused on the minimum work required.