Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -235,21 +235,4 @@ Hook still has access to the virtual field `updates.password`, and we use built-
After hook is executed, `updates.password` will be removed from the record since it is virtual, so password itself will not be saved to the database.


### Backend-only fields

Another important point is that `hashed_password` field should never be passed to frontend due to security reasons.

To do it we have 2 options:

1) Do not list `password_hash` in the `columns` array of the resource. If AdminForth knows nothing about field
it will never pass this field to frontend.
2) Define `password_hash` in columns way but set `backendOnly`. The scond option is more explicit and should be preferrred

```ts
{
name: 'password_hash',
type: AdminForthDataTypes.STRING,
showIn: { all: false },
backendOnly: true, // will never go to frontend
}
```

Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,72 @@ server {
proxy_set_header X-Forwarded-For $remote_addr;
}
}
```
```



### Backend-only fields

Some fields should never be accessed on frontend. For example, `hashed_password` field which is always created using CLI initial app, should never be passed to frontend due to security reasons.
If any user of system can read `hashed_password` of another user, it can lead to account compromise.

To eliminate it we have 2 options:

1) Do not list `password_hash` in the `columns` array of the resource. If AdminForth knows nothing about field
it will never pass this field to frontend!
2) Define `password_hash` in columns way but set `backendOnly`.

The second option is more explicit and should be preferred. This option is used by default in CLI-bootstrapped projects:

```ts
{
name: 'password_hash',
type: AdminForthDataTypes.STRING,
showIn: { all: false },
backendOnly: true, // will never go to frontend
}
```

#### Dynamically hide fields depending on user ACL / role

You can use `column.showIn` to show or hide column for user depending on his role.

However even if `showIn` value (or value returned by showIn function) is `false`, record value will still go to frontend and will be
visible in the Network tab, so advanced user can still access field value. We did it in this way to provide AdminForth developers with ability to quickly use any record field in custom components.

However if you need securely hide only certain fields depending on role, you should use `column.backendOnly` and pass function there.

Let's consider example:

```ts
{
name: 'email',
type: AdminForthDataTypes.STRING,
showIn: {
//diff-add
all: false,
//diff-add
list: ({ adminUser }: { adminUser: AdminUser }) => adminUser.dbUser.role === 'superadmin',
},
}
```

So if you will configure the email column in user resource like this, only superadmin will be able to see emails, and only in the list view.
However, the email will still be present in the record and can be accessed by advanced users through the Network tab.

So to completely hide the email field from all users apart superadmins, you should use `column.backendOnly` and pass a function there.

```ts
{
name: 'email',
type: AdminForthDataTypes.STRING,
//diff-add
backendOnly: ({ adminUser }: { adminUser: AdminUser }) => adminUser.dbUser.role === 'superadmin',
showIn: {
all: false,
list: ({ adminUser }: { adminUser: AdminUser }) => adminUser.dbUser.role === 'superadmin',
},
}
```

So if you will configure the email column in user resource like this, only superadmin will be able to see emails, and only in the list view.
1 change: 1 addition & 0 deletions adminforth/modules/restApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,7 @@ export default class AdminForthRestAPI implements IAdminForthRestAPI {

const { record } = body;

// todo if showIn.create is function, code below will be buggy (will not detect required fact)
for (const column of resource.columns) {
if (
(column.required as {create?: boolean, edit?: boolean})?.create &&
Expand Down