Initial commit

Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com>
Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com>
Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com>
Co-Authored-By: Michael Cartner <32543275+michaelcartner@users.noreply.github.com>
This commit is contained in:
Eric Tuvesson
2023-09-05 12:08:55 +02:00
commit 53f0d6320e
2704 changed files with 76354 additions and 0 deletions

View File

@@ -0,0 +1,199 @@
---
title: Emal Verification
hide_title: true
---
# Email Verification
Cloud functions play an important role when creating different log in and sign up flows. Using the nodes [Sign Up](/nodes/data/user/sign-up), [Log In](/nodes/data/user/log-in) and [Log Out](/nodes/data/user/log-out) you can create the most basic flow that will have the user sign up with a username, optionally email, and password and log in with username and password.
:::note
It's common to use email for both **username** and **email** when signing up, so you only ask the user for email and password, one less thing to remeber right.
:::
Once logged in you can use the [Access Control](/docs/guides/cloud-data/access-control) functions of the cloud database to control what a user has access to and not. The built in role system will allow you to create features like teams/groups of users.
This is a great way to get started and focus on building your application. But once you start getting to the point where you want to expose it to more users often you need a more solid sign up and log in flow. The first addition is likely the need to verify the email of users and allow them to reset the password and this is what we will cover in this guide.
There is a project template that contains a more complete sign up and log in flow that also covers sending emails to users on sign up, editing the profile etc, and it uses cloud functions to do some of these things that cannot be performed from the frontend for security reasons (cloud functions always have full access to the database).
You can either start a new project from the template, or you can import the cloud functions into your existing project. We will review them here in this guide, case by case.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/email-verification/signup-template.png)
</div>
## Settings
In order to make the email verification process work there are a few configuration parameters that need to be provided. This is done by opening up the dashboard for your **Cloud Serivce** and navigating to the **Config** tab using the sidebar. You can learn more about config parameters by looking at the [Config](/nodes/data/cloud-data/config) node. The configuration parameters you need a are shown below:
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/settings.png)
</div>
- `EmailVerificationDomain` Here you need to enter the domain where your application is deployed starting with `https://`. This is used for the links in the verification emails. When running locally this will automatically be `http://localhost:8574`, this is where the local Noodl web server is running.
- `EmailVerificationFrom` This is where you put the email address that should be used as the "from" email when sending verification emails to users. It's important that this is a valid email with **Send Grid** (the email sending service we use for the application).
- `SendGridAPIKey` The project template and email verification prefabs use [SendGrid](https://sendgrid.com/) as an email service, to use it you need to sign up and get an account (it's free to test). Then create an API Key and put it in the config. More info on how to use Send Grid with Noodl can be found [here](/library/prefabs/sendgrid).
## Signing up
Signing up is done with the [Sign Up](/nodes/data/user/sign-up) action node. After the user has successfully signed up the cloud function **Send Verification Email** is called. This function will send an email to the address provided by the user.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/sign-up-1.png)
</div>
Let's take a closer look at the cloud function. There is no need to dive into the details but it's good to review the main flow and blocks. The cloud function is found in the cloud function tab, in the **Sign Up** folder, it's called **Send Verification Email**. The first this when the function is started is that a **Request Email Verification** action component is used.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/sign-up-2.png)
</div>
This action create a secret token (a random string of characters, sort of a temporary password) that it stores with the current user. This token will later be sent to the user as part of an email. If the email is already verified a signal will be emitted on **Email Is Verified** which we will return as an error result for the cloud function.
The next part is actually sending the email to the user. This is done in the function with the **Format Email** and **Send Email** action components.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/sign-up-3.png)
</div>
The **Format Email** action takes as input the verification token and the email of the user and creates an email with a link. You can look at the properties of the **Format Email** node to see the content of the email.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/email-verification/sign-up-4.png)
</div>
As you can see it creates an email containing an HTML link, this link uses some fancy template syntax.
- **$Domain** This will be replaced by the format email node to the domain where your application is deployed, so that the link will take you back to the app. More on this later.
- **{Token}** This is the generated token from before.
- **{Email}** This is the email for the user, it will be used to fetch the user and marked the email as verified in the next step.
The **Format Email** node outputs the final email with the correct values for the above placeholders insterted. This email content is then sent to the **Send Email** node that actually sends the email to the user.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/email-verification/sign-up-5.png)
</div>
That's it. Now the user should have a fresh email with the subject **Email Verification!** in it's inbox. You can edit the **Subject** property of the **Send Email** action.
## Verifyng the email
We need one more thing in place for the email verification flow to work. We need the page that the link in the verification email points to. After the **Format Email** action have formatted the email template and inserted the **Token**, **Email** and **Domain** the resulting link will look something like this.
`<a href="https://your-app.sandbox.noodl.app/verify-email?token=abc&email=user@email.com">verify</a>`
This little thing will send the user back to your app (remember you can use `http://localhost:8574` as domain for testing, before your app is deployed) and specifically to the page `/verify-email`. So, let's take a look at the page in the project template.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/verify-email-1.png)
</div>
There is a lot of stuff here but the important things is the **Page Inputs** where we get the **Token** and **Email** as part of the query parameters in the link (the stuff after the `?` in the link), these are passed to the **Sign Up / Verify Email** cloud function that is called as soon as the page is loaded with the **Did Mount** signal.
If it succeeds, the email was verified and the user is sent to the log in page of the app with the **Navigate** node and a toast message is shown. If it fails, a message is displayed on the screen and a toast is shown using the **Show Toast** component (you can find this among the prefabs and install it into your project, same for the **Loading Spinner**).
Once logged in to your app you can inspect the user object by hovering over any **User** node. Here you can see some properties that have been set by the email verification cloud functions.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/email-verification/verify-email-2.png)
</div>
The most important is the **emailVerified** property of the user, this indicates if the user have verified their email of not. In the sign up project template the user is actually send to the home screen of the app even if the email address is not verfied and a banner is shown. You could for instance only enable certain parts of the application if the user have verified their email.
If the email was not received properly of if the user would like to have another verification email sent you can simply call the **Sign Up / Send Verification Email** cloud function again.
:::note
If you update the email with the **Set User Properties** action node, it will automatically switch the **emailVerified** property of the user to false.
:::
## Reset Password
Resetting a user password when it's been lost follows the same pattern as sending an email for verification. First you need to present some sort of UI where the user can enter their email address to recover their password.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/email-verification/reset-password-1.png)
</div>
There is a function called **Sign Up / Request Password Reset** that simply accepts an **Email** and it can be called without the user being logged in.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/reset-password-2.png)
</div>
The cloud function follow pretty much the same pattern as when sending email verifications. It will send an email to the user with a link containing a secret token just like when veryfing the email address.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/reset-password-3.png)
</div>
The **Request Password Reset** action will generate the secret token which is passed to the **Format Email** along with the users email. This time it will generate a link to a page called `/reset-password`. You can edit the content of the email in the **Format Email** node.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/reset-password-4.png)
</div>
The resulting link will look something like this:
`<a href="https://your-app.sandbox.noodl.app/reset-password?token=abc&email=user@email.com">link</a>`
The link will take the user to the `/reset-password` page which can contain a **Text Input** where the user can provide the new password.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/reset-password-6.png)
</div>
When the user hits the reset button we will call the **Sign Up / Reset Password** cloud function by supplying the secret token and user email that is received via the query parameters of the link and the **Page Inputs** node.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/email-verification/reset-password-5.png)
</div>
Provided that the secret token is correct and have not expired (tokens are valid for 24 hours) the password will be updated. You can then send the user back to the **Log In** page.
That's it, this is how you use cloud functions to create an email verification and password reset flow. You will use cloud functions for a lot of user management tasks that need to be performed on the backend with full database access.

View File

@@ -0,0 +1,120 @@
---
title: Introduction to Cloud Functions
hide_title: true
---
# Introduction to Cloud Functions
**Cloud Functions** in Noodl is a way to create logic that run in the cloud using the same techniques that you use when building business logic in your frontend, namely connecting logic and action nodes into flows, injecting Javascript where needed.
A **Cloud Function** is just another component in your project, but they don't live among the frontend components. Instead you find them in the **Cloud Functions** tab.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/introduction/cloud-functions-tab.png)
</div>
You create a new **Cloud Function** component by clicking the **+** icon in the sidebar and selection **Cloud Component Function**.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/introduction/new-cloud-function.png)
</div>
You give the cloud function a name and click **Create**.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/introduction/cloud-function-name.png)
</div>
You can also create **Folders** and **Logic Components** just like you do on the frontend to keep things organised and to seperate functionality into reusable logic components.
## Anatomy of a cloud function
When you create a new **Cloud Function** you will end up with two nodes that are the backbone, the [Request](/nodes/cloud-functions/request) and the [Response](/nodes/cloud-functions/response) nodes.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/introduction/cloud-function-empty.png)
</div>
First let's look closer at the **Request** node. When a cloud function is called from the client this is where the logic flow starts.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/introduction/cloud-function-request.png)
</div>
The logic flow is initiated by the <span class="ndl-signal">Received</span> signal. So the first actions that you want the cloud function to perform should be connected to this signal. There are also a couple of important properties on the **Request** node that we should look at:
**Allow unauthenticated**. This is an important property, by default all cloud functions need the user to be logged in to be accessible. But if you for some reason want the function to be callable without a user you can check this property. You must be careful since all cloud functions have full access to your database and can do things that might be limited in the client for security reasons.
**Parameters**. Here you add the parameters for your cloud function, these will become outputs on the **Request** node and inputs on the **Cloud Function** node in the frontend that you use to call your functions.
In the very simple example above we use the **Set User Properties** node to set the password of a user, this obviously needs a logged in user (otherwise the **Set User Properties** node wont work), we accept the new password as a parameter and trigger the action node on the **Received** signal.
When a **Cloud Function** completes it needs to either succeed or fail, this is done using the second important cloud function node, namely the **Response** node.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/introduction/cloud-function-response.png)
</div>
When the function completes you should send a **Send** signal on the **Response** node. By default this will result in a successful completion of the function with no result parameters. If you need to send a failure you can change the **Status** property to **Failure** and provide an error message.
If you need to return a result to the client you specify result **Parameters** in the properties of the **Response** node and make appropriate connections.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/introduction/cloud-function-results.png)
</div>
## Calling cloud functions
When your **Cloud Function** is in place you will need to call it from your frontend, this is done using the [Cloud Function](/nodes/data/cloud-data/cloud-function) node. First you need to pick the cloud function that you want to call using the dropdown in the node properties.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/introduction/cloud-function-call-props.png)
</div>
Then you can hook up the node. You call the function by sending a signal to the <span class="ndl-signal">Call</span> signal input.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/introduction/cloud-function-call.png)
</div>
If you have any parameters in your **Request** node of the selected cloud function then they will show up on the **Cloud Function** node as inputs, same for result parameters in the **Repsonse** nodes.
When your cloud function has completed running it will result in either a <span class="ndl-signal">Success</span> or <span class="ndl-signal">Failure</span> signal.
## Deploying
This is the basics of cloud function, keep reading the guides in this section to learn more about the details and different use cases. Finally you will want to deploy your application, and for the cloud functions to work properly you need to make sure you have a cloud services selected when deploying.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/introduction/cloud-functions-deploy.png)
</div>

View File

@@ -0,0 +1,54 @@
---
title: Javascript in Cloud Functions
hide_title: true
---
# Javascript in Cloud Functions
Not all nodes are available to cloud functions but in terms of writing Javascript the **Function** and **Expression** nodes are available. However there are some caveats, most notably when deployed cloud functions are not running in a browser they are running in the cloud and they have a much more limited runtime environment. This means that you cannot access most of the browser APIs, the cloud runtime is limited to:
- **Core Javascript Objects and Functions** The Javascript language contains a set of core objects and functions that are all available to the cloud runtime. More info [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects).
- **The Noodl API** A subset of the Noodl API is available to cloud functions. Read more about the Noodl APIs [here](/javascript/overview). Some of the functions and objects are labeled **Only available on the frontend** and some are labeled as **Only available in cloud functions**, the rest are shared between frontend and cloud functions.
## Fetch
A subset of the **Fetch API** available on the browser also works in cloud functions, which is very useful for making HTTP requests to external services.
**`fetch(url,options)`**
The **Fetch API** first takes the endpoint of the HTTP request and then an object with options. Here are a few examples, first making a simple POST request to an endpoint:
```javascript
const res = await fetch("https://some-endpoint",{
method:'POST',
headers:{
'content-type':'application/json'
},
body:JSON.stringify({
someParameters:"hello"
})
})
if(res.ok) {
Outputs.Success()
}
else Outputs.Failure()
```
## The Request Object
In Javascript in your cloud functions you can access the request object containing data on the current request being handled.
```javascript
const request = Noodl.Objects.Request;
request.UserId // Contains the user if of the user that called the cloud function, if authenticated
request.Authenticated // Will be true if this call is authenticated
request.Parameters // An object with the parameters of the current cloud function request
request.Headers // An object with the HTTP headers of the current cloud function request
```

View File

@@ -0,0 +1,80 @@
---
title: Logging and Debugging
hide_title: true
---
import useBaseUrl from '@docusaurus/useBaseUrl'
# Logging and Debugging
When building cloud functions it's important to know how to spot errors and problems quickly. This is where logging and debugging comes in.
## Running locally
When you are running your application in the Noodl editor all cloud functions are run on your local computer. The are accessing the active cloud service of the project, just as they will when deployed. The easiest way to find errors in your cloud functions is to inspect data and signal connections in your node graph as your functions are running locally.
<div className="ndl-video">
<video width="100%" autoPlay muted loop src={useBaseUrl("/docs/guides/cloud-logic/logging/cf-inspect.mp4")}/>
</div>
Simply bring up the cloud functions tab, choose the function you want to inspect and then trigger it from the app preview. You will see the data and signals flowing through your graph and you can inspect the values afterwards just like in your frontend components.
Sometimes this is not enough and we need to open the **Cloud Runtime Debugger**, you can launch it from the top of the sidebar in the cloud functions tab.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/logging/open-debug.png)
</div>
This will open a web debugger, just like when debugging your front end. When your cloud functions run locally they run in a web runtime which means that you have access to all the same debug tools. Most notably you can debug network calls from your function, as well as the logging to the console, more on that in a bit.
The **Refresh cloud functions** button above is also very useful if you want to clear error messages and inspect data and run your function clean.
If you want to call your cloud functions from external tools while running locally you can do this by accessing the local Noodl clound functions server directly.
```bash
curl -X POST http://localhost:8577/functions/my-func -H 'Content-Type: application/json' -d '{"someParameter":"value"}'
```
This can be very useful when working with e.g. webhooks as they can be tested locally without having to deploy.
## Logging
Another important tool to make sure your functions are running as expected is logging, especially when finding problems in deployed applications. When you are running locally you will find the logs in the **Cloud Runtime Debugger** under the **Console** tab.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/logging/console-log.png)
</div>
There are three functions you can use to log from your cloud functions:
```javascript
// These two both log messages as "info" severity
console.log('Some message')
console.info('Another message')
// This is logged with "error" severity and should be reserved for
// critical issues. So they will be easier to find.
console.error("An error occured")
```
When you have deployed your application you can find the logs in the dashboard for the cloud service that you have deployed to.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/logging/log-dashboard-info.png)
</div>
The logs are divided into **info** and **error** depending on which log function you used above. If you make sure to reserv error for more critical issues they will be easier to find.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/logging/log-dashboard-error.png)
</div>

View File

@@ -0,0 +1,212 @@
---
title: Scheduled Jobs
hide_title: true
---
# Scheduled Jobs
One very useful task for cloud functions are scheduled jobs. This is logic that you want to run in the cloud at specific intervals, such as every 15 minutes, hourly or daily. These jobs typically take care of housekeeping tasks that run in the "background" of your application.
Let's say for this example that we have a class in the database where a lot of records gets created as the application is running and to not use unnecessary data storage we want to prune the records that are older than 48 hours.
## The job cloud function
We start by creating a simple cloud function that will do the cloud job. Let's call it **Cleanup**.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-1.png)
</div>
In this function we add a small logic flow that first find all **Photos** that are older than 48 hours. This is done with a [Query Records](/nodes/data/cloud-data/query-records) node and a date filter, passing in the date we want to compare **createdAt** too via a small **Function** snippet.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-nodes-1.png)
</div>
The **Date** object to compare to is calcuated as such (date right now, and back up 48 hours). We want all **Photo** records that have a date that is less (earlier) than this.
```javascript
Outputs.FilterDate = new Date(Date.now() - 48*60*60*1000)
```
If successful the photos are passed into a handy node called [Run Tasks](/nodes/data/run-tasks) which will perform a logic component task for each item in the array that is fed to it, reporting **Done** when the are all processed. We need to create the logic component, I called it **Delete Task** and added it as a child component to the cloud function.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-delete-0.png)
</div>
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-delete-1.png)
</div>
The **Delete Task** is very simple, it uses the [Delete Record](/nodes/data/cloud-data/delete-record) node triggered when the **Do** is sent. This signal is sent by the **Run Tasks** node.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-delete-2.png)
</div>
The **Run Tasks** node will create an instance of the task component (**Delete Task**) for each item in the array (that is for each **Photo** we want to delete) and just like the [Repeater](/nodes/ui-controls/repeater) node you can specify that the **Delete Record** node should operate on the current record.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-delete-3.png)
</div>
Then we just need one more thing for out **Cleanup** cloud function and that is to make sure it can be called without **Authentication**, we will get back to this a bit later. Make sure the **Request** node in the **Cleanup** cloud function has this property checked.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-noauth.png)
</div>
## Testing and deploying
The easiest way to test your background job is to trigger it manually from the UI of your application. Add a button somewhere (maybe in an admin panel of your app) and simply run the function. This will allow you to test if properly and debug it in the Noodl editor before deploying.
<div className="ndl-image-with-background m">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-test-1.png)
</div>
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/scheduled-jobs/cleanup-test-2.png)
</div>
When it's working to your liking, deploy it to your backend. Take a look in this [guide](/docs/guides/cloud-logic/introduction#deploying) to learn more about deploying.
## Scheduling the job
When the cloud function is deploy we need to schedule it to be run at the interval we want. You can run a deployed cloud function from outside of Noodl, this is very handy for tasks like handling paymnents with external providers etc, and it's super useful for scheduling cloud jobs too. First, find your cloud service in the cloud services tab, and look for **Manage Cloud Service**.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/scheduled-jobs/bg-schedule-1.png)
</div>
<div className="ndl-image-with-background m">
![](/docs/guides/cloud-logic/scheduled-jobs/bg-schedule-2.png)
</div>
This will open a popup showing you information about the selected cloud services, we are looking for the **Endpoint**, this is the HTTP address you use to access your cloud service.
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/scheduled-jobs/bg-schedule-3.png)
</div>
The endpoint will have the following format:
```
https://backend.noodl.cloud/xyz/123
```
With the endpoint in hand you can go ahead and set up the scheduling for your cloud job. There are a wide range of tools for scheduling HTTP calls and my absolute favorite is [cron-job.org](https://cron-job.org/), it's clean, simple and free.
Once you have created an account and sign in, look for the **Create Cronjob** button.
<div className="ndl-image-with-background m">
![](/docs/guides/cloud-logic/scheduled-jobs/cron-1.png)
</div>
First you provide the endpoint of the cloud function that is your backgroud job that you want to schedule, you use the endpoint for above and add ```/functions/{function-name}```
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/scheduled-jobs/cron-2.png)
</div>
:::note
Some tools don't handle urls with big and small cases to it might be a good idea to just use small cases in the names of your cloud functions and no spaces or other special characters.
:::
Move on to choosing the schedule interval for your background job:
<div className="ndl-image-with-background m">
![](/docs/guides/cloud-logic/scheduled-jobs/cron-3.png)
</div>
:::note
Don't schedule your tasks too often. In Noodl hosted cloud services (and generally self hosted too) you are billed for the amount of time your cloud function runs, and if you are using a free plan and run too many cloud functions they will be throttled after a while and your application performance will suffer.
:::
Now move over to the **Advanced** tab for some additional settings. Mainly that you need to change the **Request Method** to **POST** as that is how you invoke cloud functions in Noodl.
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/scheduled-jobs/cron-4.png)
</div>
That's it, you can now test your function using the **Test Run** button and it should run successfully. Then go ahead and create it.
<div className="ndl-image-with-background m">
![](/docs/guides/cloud-logic/scheduled-jobs/cron-5.png)
</div>
Now your cloud function will be scheduled and you can just sit back and watch as your photos are clean up (or whatever you choose to do in your background job) nicely.
## Security
One final note on security. Above we set the cloud function to **allow unauthenticated requests**, this means that anyone can call this function whenever. It's not a huge problem since it doesn't do anything sensitive, it will simply prune our photos a bit more often. But it might run up our bill. So let's add a secret key that is needed to make the call.
Simply add parameter to your cloud function called **Secret**, and add a small logic in the beginning of your function to verify it (you can pick any secret you like).
<div className="ndl-image-with-background xl">
![](/docs/guides/cloud-logic/scheduled-jobs/security-1.png)
</div>
If the secret provided when calling this function does not match, then send an error response back.
<div className="ndl-image-with-background m">
![](/docs/guides/cloud-logic/scheduled-jobs/security-2.png)
</div>
This will make sure that no one can call your function (or at least, it won't do any possibly expensive work) without knowing your secret. Finally, provide the same secret when scheduling your background job, this can be done in the **Advanced** tab in [cron-job.org](https://cron-job.org/).
<div className="ndl-image-with-background l">
![](/docs/guides/cloud-logic/scheduled-jobs/security-3.png)
</div>
There you go, now you have a scheduled cloud job up and running. Calling cloud functions from external services like this is a very useful pattern to integrate Noodl with other services, it will be a recurring pattern in other guides so it's good to know.