Super Administrator

Having the utilities in place, we can begin adding functionality to the application. First things first, we need a way to create a super administrator, a user that has access to the entire application. To accomplish this, we will add configuration settings, new models as well as controllers to the application.

Browse to the project directory.

cd ~/play-scala-web-app/play-scala-web-app

Launch the application.

sbt run

Open Google Chrome and point to http://localhost:9000.

As we work on the application, SBT will automatically recompile the code when changes are detected. Keep the browser window open, so that you can periodically test the application.

Configuration

Open conf/application.conf.

Add the following entries:

Using Terminal, generate a new super administrator key.

openssl rand -hex 56

Update sa configuration block:

  • Replace change_me with the generated key.
  • Replace name with your name.
  • Replace email with your email address.

Example: LineDrop Play/Scala Web Application - Configuration

Models Package

Application models are classes and objects that read, write, and hold values in a structured way. Models also perform operations that deal with the particular model’s logic. Most models utilize the Database utility. Add the models package to your project.

Ctrl-click app and select New - Package

Enter models in the name field and press Enter.

JsonStatus Model

JsonStatus is an enumeration object which contains two values: success and failure.

Ctrl-click models and select New - Scala Class.

Enter JsonStatus in the name field and double-click Object.

If prompted, click Add to add the file to version control.

Update the model to extend Enumeration and define success and failure values:

Example: LineDrop Play/Scala Web Application - JsonStatus Model

JsonResponse Model

JsonResponse model is used to standardize a response using a JsonStatus object and a string message.

Ctrl-click models and select New - Scala Class.

Enter JsonResponse in the name field and double-click Object.

If prompted, click Add to add the file to version control.

Add get method.

The get method accepts JsonStatus and a string as parameters and packages them into a Json-formatted string.

Example: LineDrop Play/Scala Web Application - JsonResponse Model

Role Model

Ctrl-click models and select New - Scala Class.

Enter Role in the name field and double-click Object.

If prompted, click Add to add the file to version control.

Update the model to extend Enumeration and define administrator and editor values:

Example: LineDrop Play/Scala Web Application - Role Model

User Model

To create the administrator user we need a User model equipped with the create method.

Ctrl-click models and select New - Scala Class.

Enter User in the name field and double-click Class.

If prompted, click Add to add the file to version control.

Add the following import statements below the package declaration:

Delete the current User class definition and replace it with the case class:

User case class contains the user data: email, name, role, password hash, and the timestamp when the user was created.

Add UserOperations object extending Logging:

Inside the object, add two private values:

Collection defines database collection users, where the model data is stored and log defines an instance of the Logger.

Add create method:

The create method accepts an instance of User case class. From the class instance, a MongoDB document is composed.

Using the Database utility the document is stored in the users collection.

A temporary password reset key is generated. The key is generated using the Key model’s create method which accepts the user and a boolean value as parameters. The boolean value false signifies that the key does not expire.

Welcome email with password reset instructions is composed for the user including the password reset link containing the token.

Welcome email is sent to the user with SendGrid utility.

Example: LineDrop Play/Scala Web Application - User Model

Key Model

Key model provides support for password reset keys.

Ctrl-click models and select New - Scala Class.

Enter Key in the name field and double-click Object.

If prompted, click Add to add the file to version control.

Add the following import statements below the package declaration:

Delete the current Key class definition and replace it with the case class:

Add KeyOperations object extending Logging:

Inside the object, add three private values:

Collection defines database collection users, where the model data is stored and log defines an instance of the Logger. Duration is the lifespan of the key, if the key expires.

Add create method:

The create method accepts user and a boolean value as parameters.

The method instantiates a new key defined by the user email with the random string as a token and a current timestamp. Random and TimeStamp utilities are used.

MondoDB document is composed.

If the boolean expires is set to true, a time is calculated by adding a configured number of hours to the current timestamp.

The document is inserted into the key collection using the Database utility and the Key instance is returned.

Example: LineDrop Play/Scala Web Application - Key Model

Init Controller

Init Controller accepts a key and compares it to the super administrator key stored in the configuration. If the keys match, an administrator user is created and the notification email is sent. The controller does not load a view, instead it prints a JSON-formatted response.

Ctrl-click controllers and select New - Scala Class.

Enter InitController in the name field and double-click Class.

If prompted, click Add to add the file to version control.

Add the following import statements below the package declaration:

Delete the current InitController class definition and replace it with the following:

Inside the class, add a log instance.

Add init method:

Init method accepts a string key as a request parameter.

The method loads the administrator key from configuration.

If the keys match, administrator name and email are loaded from configuration and a new with role administrator is created. Password hash is set to null. The controller returns Ok which is 200 HTTP equivalent and prints the success message.

If the keys do not match, the controller prints the failure message.

Example: LineDrop Play/Scala Web Application - Init Controller

Routing

As a final step, we need to add a route to map the request URL to the controller method.

Open the routes file and append the new route to the end of the file.

When the user browses to /init/value the init method of the controller is invoked and the value is passed to as the key string.

Test

Before testing, please make sure that the database and the application are running. Keep the terminal window with SBT visible so you can see the log.

Application Response

Open application.conf and copy the super administrator key (sa.key) value.

Open Chrome and browse to http://localhost:9000/init/key. Key is the value copied from sa.key setting.

You should see the success message printed in JSON format.

Log

Logger will have printed the debug message in the Terminal window. The log has also been written to /logs/application.log in the project’s directory.

Database Records

Launch MongoDB Compass.

When prompted, enter mongodb://localhost as the connection string and click Connect.

Click sample database. This database was created by the application. You should see keys and users collections.

Click on keys to view the document created to store the administrator's password reset key.

Click on users in the left panel to view the document created to store the new user.

Email Notification

Check your email. You should have received a Welcome email containing the link to create a password. Do not click the link, we have yet to add functionality to make it work. Please note that SendGrid changes the links to provide you with the ability to track user responses.

Review

Let’s review what happened when you browsed to the init link.

...

The router matches URL syntax to route definition and invokes the Init Controller’s init method passing the key in the request.

Init Controller’s init method loads the sa.key from configuration and compares both keys. On match, administrator name and email are read from configuration and the User Operations’ create method is invoked passing an instance of the User object with the password hash parameter set to null. Once the operation is complete, the success message is printed. If the keys do not match, the failure message is printed.

User Operations’ create method composes a document containing the new user data and invokes Database utility to insert the document into the database. Then, the Key Operations’ create method is invoked to generate a new password reset key. Welcome email message is composed.

The Key Operations’ create method composes a document containing the new key data and invokes Database utility to insert the document into the database.

Notice that since instances of the User and Key objects already exist prior to invoking the Database utility, both create methods do not wait for the database insert operation to complete.

The SendGrid’s utility send method is invoked to send the Welcome email to the user.

Commit and Push Changes

Select VCS - Commit from the top menu.

Review the files and directories and enter the commit message.

Click the dropdown arrow on the Commit button and select Commit and Push.

Click Push to confirm.


Next: Password Management