Custom Access Function
Custom Access Function allows more granular control on how the data in the endpoints is accessed. These functions are set up on the Project Dashboard and are executed on the server side for every request to the endpoint with this functionality enabled.
Why these functions are important
When is comes to accessing the data without a Custom Access Function, RESTED_DEV offers Secure endpoints, and Additional data options, these can be enabled on the Project Dashboard and the access control to the data is done on the server side. This already gives a good level of security, but the control to check who is accessing the data is limited, and used incorrecly could expose the data of the endpoint.
Custom Access Functions come in to help with more complex use cases and give more control to the administrator of a Project.
Let's start with an example of a typical use case to understand better this functionality.
Example - Chat application
Let's imagine you are building a Chat application that allows users to have private conversations with each other. When user1 send a message to user2, that message should only be available for those 2 users.
With Secure Endpoints and Custom Data Options only, this would not be possible. If user3 would try to request data from the endpoint containing messages (without JSONata filtering), all messages would be sent to the client - even though the client application can filter out the records, a more curious user could inspect the request and check the messages there.
For these use cases, the basic usage or the RESTED_DEV endpoints is not enough.
How Custom Access Functions solve this issue?
You can check who is requesting the message and decide whether or not that user can receive it. You do this by checking uniqueIds (and other data), and match it against the requested data, or even data from other endpoints.
You can easily implement role based access using this function.
Some important notes
- The function is written in JavaScript as a IIFE function
- To enable this function in an endpoint the funtion must be saved first in the Project configuration
- When this function is enabled for an endpoint, all other checks are ignored, you have full control to check who can access the data - be aware, if used incorrectly you can open the endpoint to authenticathed and non-authenticathed users.
Example of a function
In the context of a chat application, in the following function we are checking if the user accessing the data can receive access it. We do this by checking if their uniqueId is equal to fromUserId or toUserId.
Remember that this depends on how your data is structured. RESTED_DEV gives you the flexibility to structure the data in any way, so you need to write your function accordingly.
//GET|roles|rolesVar
//GET|messages|messagesVar
(function myCustomAccessFunction() {
// global vars:
// console.log('The data contained in accessed endpoint:', ACCESSED_DATA)
// console.log('The current signed in user:', SIGNED_IN_USER)
// console.log("Name of the accessed endpoint:", THIS_ENDPOINT_NAME);
// ...and more
// we can control the access to each endpoint in the project
// in this example, we just want to control access to the messages endpoint
if (THIS_ENDPOINT_NAME !== "messages") {
return true;
}
if (THIS_ENDPOINT_IS_SECURE && !SIGNED_IN_USER) {
throw new Error("This endpoint requires an authenticathed user");
}
// since we are sending messages, we allow the auth users to post anything
if (REQUEST_METHOD === "POST") {
// we could do other checks here
console.log("NEW_DATA_TO_PERSIST", NEW_DATA_TO_PERSIST);
return true;
}
// here we control which messages the user has access to
if (REQUEST_METHOD === "GET") {
// we could do other checks here
// we are gonna filter the record ids the logged in user has access to
const accessedData = Array.isArray(ACCESSED_DATA)
? ACCESSED_DATA
: [ACCESSED_DATA];
return accessedData
.filter((record) => {
const userUniqueId = SIGNED_IN_USER.uniqueId;
if (
record.data.fromUserId === userUniqueId ||
record.data.toUserId === userUniqueId
) {
return true;
}
})
.map((record) => record.uniqueId);
}
})();
The function must be written as a IIFE function and from within the function you will have access to enviroment variables.
Environment variables
Variable | Description |
SIGNED_IN_USER | If there's a user signed in, this variable will contain their data. |
ACCESSED_DATA | Contains the accessed data. This data is not avaialable for POST requests. |
THIS_ENDPOINT_NAME | Name of the endpoint. Currently you can only set one function per project, if you want to use it in multiple endpoints you can use this variable to conditionaly make checks to the data. |
NEW_DATA_TO_PERSIST | Contains the data to be persisted/updated. Only available for POST and PUT requests. |
THIS_ENDPOINT_IS_SECURE | Boolean where the accessed endpoint is secured. |
REQUEST_METHOD | Type of request: GET, POST, PUT, DELETE |
Accessing data from other endpoints
In some cases, like role based access, you might need to access data from other endoints.
To do so, before you define a function, you need to include the following string (like we did in the example above):
//GET|roles|rolesVar
The string is divided in 3 parts, delimited by the pipe "|" symbol:
//GET|name_of_the_endpoint|name_of_the_variable
name_of_the_endpoint | Name of the endpoint you want to get data from. The endpoint needs to exist in the Project. |
name_of_the_variable | The data will be requested will be available as an environment variable that can be accessed from within the function. |
You can get the data from multiple endpoints but we recomend not doing so as it will impact the response times of the request to the endpoint.
Return values
The function is expected to return certain values:
Return value | Description |
Boolean - true | Allow access to the data/endpoint. |
Boolean - false | Deny access to the data/endpoint. |
Array of uniqueIds | List of uniqueIds from the accessed data. The endpoint will only return records that match the ids. |
Debbugging
To debug the data, you need to enable debug mode for your endpoint. This can be done on the Dashboard, directly in the endpoint.
When enabled, the endpoint will return as well the output of anything logged within the function.
The structure of the response changes.
Be mindful when enabling debugging mode for a production endpoint: -The response format changes, if your application is not handling that it could cause problems; -Data logged in the function could be exposed to the user;