Home

Awesome

Addison Global Backend Technical Assesement

Introduction

Welcome to Addison Global Backend technical test.

The main goal of this exercise is to assess your approach to problem solving, as well as your ability to write clean, well tested and reusable code. There's no hard rules or tricky questions.

Note: Despite some snippets are written in Scala, the exercise can be developed in Java.

Glossary

Implementation example:

case class Credentials(username: String, password: String)
case class User(userId: String)
case class UserToken(token: String)

Exercise

The goal of the exercise is to improve the definition of a backend service/module and provide an implementation for it. Once this is finished, you'll create a microservice that offers a REST API to consume the service/module functionality.

Note: Favour simplicity, code the solution as a single module and use packages to structure it..

1. Service Trait / Interface

Given these two synchronous and asynchronous definitions of the TokenService

trait SyncTokenService {
  protected def authenticate(credentials: Credentials): User
  protected def issueToken(user: User): UserToken

  def requestToken(credentials: Credentials): UserToken = ???
}
import scala.concurrent.Future

trait AsyncTokenService {
  protected def authenticate(credentials: Credentials): Future[User]
  protected def issueToken(user: User): Future[UserToken]

  def requestToken(credentials: Credentials): Future[UserToken] = ???
}

Task: Provide both implementations of requestToken in terms of authenticate and issueToken. By doing that, whoever implements the service will only need to implement authenticate and issueToken.

Note: Bear in mind the scala.concurrent.Future in Scala is not equivalent to the java.util.concurrent.Future in Java. Future in Scala is composable, so if you're developing the solution in Java, feel free to change the signature in order to use most appropriate for Java. Suggestions: either java.util.concurrent.CompletionStage or java.util.concurrent.CompletableFuture.

2. Service Implementation

Provide an implementation for the following API, which is different from the one designed in the previous section:

 trait SimpleAsyncTokenService {
   def requestToken(credentials: Credentials): Future[UserToken]
 }

Note: Bear in mind the scala.concurrent.Future in Scala is not equivalent to the java.util.concurrent.Future in Java. Future in Scala is composable, so if you're developing the solution in Java, feel free to change the signature in order to use most appropriate for Java. Suggestions: either java.util.concurrent.CompletionStage or java.util.concurrent.CompletableFuture.

Task requirements / guidelines:

We prefer you to use an Actor Model implementation such as Akka, but it's not mandatory. You can use other frameworks like Spring or any other of your choice.

  1. Implement an Actor/Service/Module that:
    • Validates the Credentials and return an instance of a User.
    • The User instance will always be returned with a random delay between 0 and 5000 milliseconds.
    • If the password matches the username in uppercase, the validation is a success, otherwise is a failure. Examples:
      • username: house , password: HOUSE => Valid credentials.
      • username: house , password: House => Invalid credentials.
    • The userId of the returned user will be the provided username.
    • This logic has to be encapsulated in a separate Actor/Service/Module.
  2. Implement another Actor/Service/Module that:
    • Returns a UserToken for a given User.
    • The UserToken instance will always be returned with a random delay between 0 and 5000 milliseconds.
    • If the userId of the provided User starts with A, the call will fail.
    • The token attribute for the User Token will be the concatenation of the userId and the current date time in UTC: yyyy-MM-dd'T'HH:mm:ssZ.
      • Example: username: house => house_2017-01-01T10:00:00Z
    • This logic has to be encapsulated in a separate Actor/Service/Module.
  3. Implement the requestToken function/method from the SimpleAsyncTokenService trait/interface in a way that:
    • Its logic is encapsulated in an Actor/Service/Module.
    • It makes use of the previously defined actors/services/modules for authenticating users and granting tokens:
      • It will first use the validation of the Credentials to obtain a User.
      • After that it will then use the actor/service/module to obtain a UserToken.
      • Finally, returns the UserToken to the original caller.

Evaluation notes:

We're particularly interested on how the actor system (or the service orchestration) is designed and tested, paying special attention to the following aspects:

Keep in mind:

3. REST API

Task: Define a simple REST API to offer the functionality of the SimpleAsyncTokenService implemented in the previous block.

For its implementation we prefer you to use Akka HTTP, however, it's not mandatory and you can use other frameworks such as http4s, Play Framework or Spring Boot.

Evaluation notes:

We're interested on the structure and completeness of the API, so as how it is tested.

Deliverable

Note: Remember this is not a thesis, just few lines is enough. Favour self-documenting code.