What are we going to build?
In this tutorial, we’ll build an app where users can log in, register, and recover forgotten passwords via the email they specified when registering. This app uses the Appery.io database and server code, shows how to create a sign in/registration feature, and shows how to use server scripts in the app to recover password.
Before you begin
Tutorial level: advanced.
This tutorial assumes you know how to build mobile pages, add and map services, and write server code scripts.
To send an email with a secret code to restore the password, you need a SendGrid account.
Creating from the backup
You can build this app by following our step-by-step tutorial below or create it from the backup.
To create an app from the backup:
- Click “Create new app.”
- Type an app name.
- Click “From backup” and select the project backup file.
- Click “Create.”
You still have to create the database and Server Code scripts manually. If you’ve already created the database, locate the X-Appery-Database-Id
and paste it to PasswordRecoveryDB_settings > database_id
.
Also, specify the URLs for sendEmail_service
and resetPassword_service
. Find how to create them here and here.
Creating a new app
Switch to the Apps
tab, and create a new app (use any name). The app builder opens. We’ll create three pages, one each for: registering, logging in, and recovering the password.
Creating pages
The loginScreen
is the start screen of the app. It is used to log into the database.
2. The Input
components are defined as placeholders
. Name the Input
components: loginInput
and passwordInput
.
3. Name the Button
components: loginButton
, registerButton
and recoverPasswordButton
.
The registerScreen
is used for registering new users.
5. All Input
components are defined as placeholders
. Name the Input
components: loginInput
, emailInput
, passwordInput
, and confirmPasswordInput
.
6. Name the button registerButton
.
The recoverScreen
is used to recover the password, with the help of a secret code sent to the user’s email.
8. All Input
components are defined as placeholders
. Name the Input
components: loginInput
, secretCodeInput
, newPasswordInput
, and confirmNewPasswordInput
.
9. Name buttons: getCodeButton and changePasswordButton.
Now we’ll create a database to store users’ data.
Creating a new database
1. Go to https://appery.io/database, and create a new database. In the app, we need only the Users
collection. It has two predefined columns: username
and password
. Add two more columns: user’s e-mail (email
) and the secret code (secret_code
):
2. Now, we need to create REST
services for registering and signing into the database. The services should then be mapped and the events invoking them defined.
Creating & invoking database services
1. To create the signup and login services, select Create New > Database Services
, select your database, and then check the Login
and Signup
services.
2. Open the loginScreen
, switch to the DATA
tab, and add a login service. Rename the service instance to loginService
:
3. Create the following Before send
mapping:
In this tutorial, no Success
mapping is needed.
4. Add the following events to see whether the login failed or succeeded:
loginService > Success > Run JavaScript >
add the following script:
1alert("You have successfully logged in");loginService > Error > Run JavaScript >
add the following script:
12345try {alert(JSON.parse(jqXHR.responseText).description);} catch (e) {alert('Login failed');}
5. Switch to the DESIGN
tab, and add the following events:
loginButton > Click > Invoke service > loginService
registerButton > Click > Navigate to page > registerScreen
recoverPasswordButton > Click > Navigate to page > recoverScreen
The loginScreen
is ready.
The database services import doesn’t include user-defined fields as
secret_code
. So they must be added manually.
6. Open Database_signup_service
(it’s listed under the Services
folder) and go to the Request
tab. Add the email
parameter:
7. Open registerScreen
, switch to the DATA
tab, and add the sign-up service. Rename the service instance to signupService
:
8. Create the following Before send
mapping:
9. Add the following events to see whether registration failed or succeeded:
signupService > Success > Run JavaScript >
add the following script:
1alert("You have successfully registered");signupService > Error > Run JavaScript >
add the following script:
12345try {alert(JSON.parse(jqXHR.responseText).description);} catch (e) {alert('Registration failed');}
10. Switch to the DESIGN
tab, and add the following event on button click:
registerButton > Click > Run JavaScript >
add the script; check that all values are correct and then invoke the service:
1234567891011121314151617if ($.trim(Appery("loginInput").val()) != "") {if (Appery("passwordInput").val() == Appery("confirmPasswordInput").val()) {if ($.trim(Appery("emailInput").val()) != "") {if (!document.getElementsByName("emailInput")[0].checkValidity || document.getElementsByName("emailInput")[0].checkValidity()) {signupService.execute({});} else {alert("Please enter a valid email");}} else {alert("Please specify your email");}} else {alert("Passwords don't match!");}} else {alert("Please enter your login");}
Before adding services to the recoverScreen
, you need to create server scripts.
Creating server script to send password recovery code
1. Go to https://appery.io/servercode/, and create a new script. Name it SendEmail
.
2. Add the following code (it generates the secret code and sends it to the user’s email):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
var responseBody = {}, requestParams = {}, paramKeys = request.keys(); for (var key = 0; key < paramKeys.length; key++) { requestParams[paramKeys[key]] = request.get(paramKeys[key]); } // Declare database ID and Master key var dbId = "Database ID"; var masterKey = "Master Key"; // Get username from request parameters var username = requestParams['username']; // Generate a random secret code var secretCode = Math.random().toString(36).slice(-12); console.log(secretCode); try { // Get the user with a given username from the database var XHRResponse = XHR.send("GET", "https://api.appery.io/rest/1/db/users/", { "headers": { "X-Appery-Database-Id": dbId, "X-Appery-Master-Key": masterKey }, "parameters": { "where": '{"username": "' + username + '"}' } }); // If the user exists update user's secret code with the generated value if (XHRResponse.body.length) { var userId = XHRResponse.body[0]["_id"]; var email = XHRResponse.body[0]["email"]; var XHRResponse = XHR.send("PUT", "https://api.appery.io/rest/1/db/users/" + userId, { "headers": { "X-Appery-Database-Id": dbId, "X-Appery-Master-Key": masterKey, "Content-Type": "application/json" }, "body": { "secret_code": secretCode } }); // If secret code was successfully updated, send email with the code to user with Sendgrid API if (XHRResponse.status == 200 && email) { var XHRResponse = XHR.send("POST", "https://api.sendgrid.com/api/mail.send.json", { "parameters": { "api_user": "Sendgrid username", "api_key": "Sendgrid password", "to": email, "toname": "", "subject": "Password Recovery", "text": "Your recovery code is: " + secretCode + ". Copy and this code into the field provided.", "from": "admin@company.com" } }); // If the email was successfully sent, inform the user about it if (XHRResponse.status == 200) { responseBody.message = "An email with the recovery code has been sent to you. Please follow the instructions to reset your password"; } else { responseBody.message = "An error occured while sending the email"; } } else { responseBody.message = "Database error"; } } else { responseBody.message = "User not found"; } response.success(responseBody, "application/json"); } catch (e) { response.success("message: " + e.message + "\ncode: " + e.code); //If something goes wrong, error message appears } |
In this script, you should enter the following custom data:
Database ID
– replace with your Database ID.Master Key
– replace with your Master Key.Sendgrid username
,Sendgrid password
– replace with your SendGrid credentials.admin@company.com
– replace with your email.
Now, you need to create one more script to recover the password in the database.
Creating server script to change password
1. Create a new script, and name it ResetPassword
. Add the following code (it checks the entered secret code and updates the password):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
var responseBody = {}, requestParams = {}, paramKeys = request.keys(); for (var key = 0; key < paramKeys.length; key++) { requestParams[paramKeys[key]] = request.get(paramKeys[key]); } // Declare database ID and Master key var dbId = ""; var masterKey = ""; // Get username, new password and secret code from request parameters var username = requestParams['username']; var newPassword = requestParams['newPassword']; var secretCode = requestParams['secretCode']; try { // Get the user with a given username from the database var XHRResponse = XHR.send("GET", "https://api.appery.io/rest/1/db/users/", { "headers": { "X-Appery-Database-Id": dbId, "X-Appery-Master-Key": masterKey }, "parameters": { "where": '{"username": "' + username + '"}' } }); // If the user exists, get his email, id and secret code from response if (XHRResponse.body.length) { var email = XHRResponse.body[0]["email"]; var userId = XHRResponse.body[0]["_id"]; var secretCodeDB = XHRResponse.body[0]["secret_code"]; // If the secret code from the database matches the secret code received from user, // update the password with the new value if (secretCode == secretCodeDB) { // If new password is not blank if (newPassword != '') { var XHRResponse = XHR.send("PUT", "https://api.appery.io/rest/1/db/users/" + userId, { "headers": { "X-Appery-Database-Id": dbId, "X-Appery-Master-Key": masterKey, "Content-Type": "application/json" }, // Update user's password with a new value "body": { "password": newPassword } }); // If the password update was successful, send an email to the user if (XHRResponse.status == 200) { var XHRResponse = XHR.send("POST", "https://api.sendgrid.com/api/mail.send.json", { "parameters": { "api_user": "Sendgrid username", "api_key": "Sendgrid password", "to": email, "toname": "", "subject": "Password Recovery Complete", "text": "You have successfully changed your password", "from": "admin@company.com" } }); if (XHRResponse.status == 200) { // If the email was successfully sent, inform the user about it responseBody.message = "Your pasword was successfully changed. A confirmation email has been sent to you"; } else { // Email was not sent, but the password reset was still successful responseBody.message = "Your pasword was successfully changed"; } } else { responseBody.message = "Database error"; } } else { responseBody.message = "New password is not provided"; } } else { responseBody.message = "Wrong secret code"; } } else { responseBody.message = "User not found"; } response.success(responseBody, "application/json"); } catch (e) { response.success("message: " + e.message + "\ncode: " + e.code); //If something goes wrong error message will appear } |
Where:
Database ID
– your Database ID.Master Key
– your Master Key.Sendgrid username
,Sendgrid password
– your SendGrid credentials.admin@company.com
– your email.
Creating REST services to invoke server code scripts
sendEmail_service
1. Inside the app builder, select CREATE NEW > Service
. Create a REST
service, name it sendEmail_service
. Define the following settings:
2. To get the URL
value, go to Server Code > SendEmail script > Script
tab, and copy the Execute URL
value:
3. Create only one request
parameter – username
:
4. There’s only one response
parameter: message
. The service response
can be automatically created from the Test
tab:
resetPassword_service
1. Select CREATE NEW > Service
. Create a REST
service, and name it resetPassword_service
. Define the following settings:
2. To get the URL
value, go to Server Code > ResetPassword script > Script
tab, and copy the Execute URL
value:
3. There are three request
parameters: username
, secretCode
, and newPassword
:
4. There may be one response in this service, message
, but since we’re not going to use it, disregard it.
Invoking server code on the page
1. Open the recoverScreen
, switch to the DATA
tab, and two services are created. Name them sendEmailService
and resetPasswordService
:
2. In the sendEmailService,
create the following Before send
mapping:
3. Click “Save and return”.
4. In the resetPasswordService
, create the following Before send
mapping:
In both services, no response mapping is needed.
Switch to the DESIGN
tab, and add the following button click events:
getCodeButton > Click > Invoke service > sendEmailService
.changePasswordButton > Click > Run JavaScript
and add the following script:
123if (Appery("newPasswordInput").val() == Appery("confirmNewPasswordInput").val()) {resetPasswordService.execute({});}
Switch to the DATA
tab, and add events for successful executing services:
sendEmailService > Success > Run JavaScript
and add the following script:
1alert(data.message);resetPasswordService > Success > Run JavaScript
and add the following script:
1alert(data.message);
Now the app is ready and you can test it.
Testing the app
When testing the app, you’ll first see the login page:
If you have users in your database, enter the username and password (or wrong password) to check if the app works correctly.
You can also enter the wrong username:
If you want to change the password, on the login page, click “Recover password” and enter the username:
Enter the secret code from the email you received, and the new password: