Module Server Side
Module Server Side
Contents
1. MODULE_SERVER_SIDE.docx
2. MODULE_SERVER_SIDE_MEDIA.zip
Introduction
A new founded company is looking for full stack developers to create an online browser
gaming platform. Game developers can upload their games to the platform and users can
play them online in the browser.
There are three parts to the platform:
● Developer Portal: A web application for game developers to upload their games to
the platform.
● Administrator Portal: A web application for administrators to manage the platform
with its users and games.
● Gaming Portal: A web application for players to play games online in the browser.
The company wants to create a minimum viable product (MVP) for the platform. The MVP
should already contain the aforementioned parts, but it is acceptable that the Game
Developer Portal and the Administrator.
Portal are not fleshed out yet. The Gaming Portal should be fully functional, so that users
can play games online in the browser.
Description of Projects
The project is split into two phases:
● Phase one for building the API and static pages using a PHP framework and MySQL
database.
● Phase two for building the frontend parts using HTML/CSS and a JavaScript
framework, consuming the API developed in phase one.
You can find the provided media files to support your work:
- Provided frameworks (laravel, vuejs, reactjs)
- Postman collection and environment
- Template GUI (to build frontend UI)
- lks-server.sql (a database with structures and dummy data)
Phase 1 : RESTful API
In this phase, you should build a RESTful API using the Laravel framework according to the
documentation below.
Username Password
admin1 hellouniverse1!
admin2 hellouniverse2!
Developer
Username Password
dev1 hellobyte1!
dev2 hellobyte2!
Players
Username Password
player1 helloworld1!
player2 helloworld2!
● The response bodies contain some static example data. Dynamic data from the database
should be used.
● Placeholder parameters in the URL are marked with a preceding colon (e.g. :slug or :id).
● The order of properties in objects does not matter, but the order in an arrays does.
● The Content-Type header of a request must always be application/json for POST, PUT,
PATCH.
● The Content-Type header of a response is always application/json unless specified
otherwise.
● Timestamps are formatted as ISO-8601 strings. E.g. 2032-01-31T21:59:35.000Z.
● The given URLs are relative to the base URL of the API. E.g. /api/v1/games is the URL to
get all games.
● The API URLs must not end in .php or .html or any other file extension. The game files
are an exception to this.
● The token for protected endpoints must be specified as a Bearer token in the
`Authorization` header. I.e. `Authorization: Bearer <token>`
1. Authentication
You should create Login and Logout endpoints. The accessToken must be generated by sanctum and
will be placed in the request headers Authorization Bearer.
Sign Up
POST [domain]/api/v1/auth/signup
Request Body:
"username": "testuser",
"password": "asdf1234"
PROPERTY COMMENT
username required, unique, min length 4, max length 60
Response:
"status": "success",
"token": "xxx"
Sign In
POST [domain]/api/v1/auth/signin
This checks the username and password against all known users. If found, a session token is returned.
Valid response:
Request Body:
"username": "testuser",
"password": "asdf1234"
PROPERTY DESCRIPTION
username required, unique, min length 4, max length 60
Response Body:
"status": "success",
"token": "xxx",
“role”: “admin” | “user”
Response Body:
{
"status": "invalid",
Sign Out
POST [domain]/api/v1/auth/signout
Valid response:
Response Body:
"status": "success"
2. Users
Get all admin data
GET [domain]/api/v1/admins
Response:
{
"totalElements": 2,
"content": [
"username": "admin1",
"last_login_at": "",
},
"username": "admin2",
"last_login_at": "2024-04-05 20:55:40",
}
]
Response Body:
"status": "forbidden",
POST [domain]/api/v1/users
Request Body:
"username": "testuser",
"password": "asdf1234"
PROPERTY COMMENT
username required, unique, min length 4, max length 60
Response:
Response Body:
{
"status": "success",
"username": "testuser"
Existing username:
If the username is not unique, the admin user cannot be created and instead the following response is
returned.
Response:
"status": "invalid",
Response Body:
"status": "forbidden",
GET [domain]/api/v1/users
Response:
{
"totalElements": 2,
"content": [
"username": "player1",
"last_login_at": "",
},
"username": "player2",
}
]
Response Body:
"status": "forbidden",
PUT [domain]/api/v1/users/:id
Request Body:
"username": "testuser",
"password": "asdf1234"
PROPERTY COMMENT
username required, unique, min length 4, max length 60
password required, min length 5, max length 20
Response:
Response Body:
"status": "success",
"username": "testuser"
Existing username:
If the username is not unique, the admin user cannot be created and instead the following response is
returned.
Response:
"status": "invalid",
Response Body:
"status": "forbidden",
DELETE [domain]/api/v1/users/:id
This returns an empty body. The `Content-Type` header does not have to be `application/json`.
Response Body:
"status": "not-found",
"message": "User Not found"
Response Body:
"status": "forbidden",
3. Games
GET [domain]/api/v1/games
Query Parameters:
popular Counts the total number of scores per game and sorts by this count
In `content`, the fields `thumbnail` and `uploadTimestamp` refer only to the latest version.
Response:
Response Body:
"page": 0,
"size": 10,
"totalElements": 15,
"content": [
"slug": "demo-game-1",
"thumbnail": "/games/:slug/:version/thumbnail.png",
"uploadTimestamp": "2032-01-31T21:59:35.000Z",
"author": "dev1",
"scoreCount": 5
FIELD DESCRIPTION
It can also be computed if the returned page is the last page by multiplying the (page+1) by
requested page size and checking if the result is less than or equal to the total elements.
Note 1: If there is a game that has no game version yet, it is not included in the response nor the total
count.
POST [domain]/api/v1/games
This endpoint can be used to create a game. However, the game version needs to be uploaded
in a separate step. If a game does not have a version yet, it is not returned in this endpoint.
Request Body:
PROPERTY DESCRIPTION
title required, min length 3, max length 60
Response:
Response Body:
"status": "success",
"slug": "generated-game-slug"
}
Existing slug:
If the generated slug is not unique, the game cannot be created and instead the following response is
returned.
Response:
"status": "invalid",
GET [domain]/api/v1/games/:slug
Response:
"slug": "demo-game-1",
"thumbnail": "/games/:slug/:version/thumbnail.png",
"uploadTimestamp": "2032-01-31T21:59:35.000Z",
"author": "dev1",
"scoreCount": 5,
"gamePath": "/games/demo-game-1/1/"
The `gamePath` field points to a URL path that browsers can use to render the game. This
means this is a reachable asset path.
The user can upload a new version of a game if they are the author of that game.
• This is not a REST endpoint and rather it accepts a file upload. The parameter name is `zipfile`.
• The version of the game is an integer and incrementing. The first version is `1`. The user
cannot control the version.
If the upload fails because of one of these possible reasons, the response must be a plain text
explanation of the error.
The game files that were uploaded are served under that path which is public.
PUT [domain]/api/v1/games/:slug
This endpoint allows the author of the game to update the game title and description.
Request Body:
Response:
Response Body:
"status": "success"
}
User is not game author response:
Response Body:
"status": "forbidden",
DELETE [domain]/api/v1/games/:slug
The author can delete their game. This deletes the game, all versions and all scores.
Response:
This returns an empty body. The `Content-Type` header does not have to be `application/json`.
Response Body:
"status": "forbidden",
GET [domain]/api/v1/users/:username
Response Body:
{
"username": "dev1",
"registeredTimestamp": "2032-01-31T21:59:35.000Z",
"authoredGames": [
"slug": "demo-game-1",
],
"highscores": [
"game": {
"slug": "demo-game-1",
},
"score": 15,
"timestamp": "2032-01-31T21:59:35.000Z"
The authoredGames is an array that returns all games with at least one version where this user is the
author. If the user requesting the user details is the user itself, this returns also games that have no
version yet.
GET [domain]/api/v1/games/:slug/scores
Returns the highest scores of each player that played any version of the game, sorted by score
(descending).
Response:
Status Code: 200
Response Body:
"scores": [
"username": "player2",
"score": 20,
"timestamp": "2032-01-31T21:59:35.000Z"
},
"username": "player1",
"score": 15,
"timestamp": "2032-01-31T21:59:35.000Z"
POST [domain]/api/v1/games/:slug/scores
When a user ends a game run, the score can be posted to this endpoint.
Request Body:
"score": 100
The game version associated to the score is the latest one available.
Response:
Response Body:
{
"status": "success"
Response Body:
"status": "invalid",
"violations": {
"field_name": {
"message": "required"
},
"field_name": {
},
"field_name": {
In the above example, all possible violations are shown. The actual returned violations should
only be the fields which were actually invalid. At most one validation per field is shown.
Validations are executed in order of appearance in the example above. field_name must be
replaced with the actual field name.
The messages for length must include the actual length requirement value.
Response Body:
"status": "unauthenticated",
If the consumer makes a call to a path that requires the auth header to be present, but provides an
invalid or not existing token, this must be the response:
Response Body:
"status": "unauthenticated",
If the consumer makes a call to a path that requires the auth header to be present, but the user is
blocked, this must be the response:
Response Body:
"status": "blocked",
Note: The reason is a dynamic value, chosen by the admin that blocks the user.
The following method and path patterns require a valid session header to be present:
• POST /api/v1/auth/signout
• POST, PUT, DELETE /api/v1/games/**
• GET /api/v1/admins/**
Response Body:
"status": "not-found",
}
Phase 2 : Front-end Development
In this part, you should build a front-end application using one of the provided frameworks
(vue js or react js). You can use the provided template gui on the media files to build the
front-end ui.
Pages / Features Description
- The admin can see all admin users in the database with
List Admin
username, created timestamp and last login timestamp.
Instructions
- Save your REST Api in the directory called “SERVER_MODULE/backend” and
save it in the repository folder.
- Db-dump.png sama db-diagram.pdf
- Save your front-end app in the directory called “SERVER_MODULE/frontend” and
save it in the repository folder.
- When developing the Frontend, you can use/consume the provided REST API.
- You should build the frontend app to production mode and save the production
files in the “SERVER_MODULE/frontend/build” folder before you push it to the
github repository.
- Make sure the “/build” folder isn't written on the .gitgnore file.
- You should commit and push your changes to the github repository at least every 30
minutes.