A digital streaming platform that allows users view actors, movies, and review them with up to 5 star rating. It is also a software solution for Digital Streaming System that allows admistrators to manage movies, actors, users, and user movie reviews. It is also a place for many handpicked movies around the world.
- React - Typescript
- HTML - SCSS
- Mantine UI
- Redux Toolkit
- Loopback 4 + Authentication and Authorization
- MongoDB
- Sonarqube
- React Testing Library + Jest + Mock Service Worker
- View Movies (Users)
- View movie details such as rating, description and more.
- Search for movies.
- View actors that are part of the movie.
- View admin approved user reviews.
- Give Movie Reviews (Users)
- Submit a review of a movie.
- Requires account login and activation from the admin.
- Created review will be subjected for admin approval.
- View Actors (Users)
- With actor details such as name, link, etc.
- Search for actors.
- View the movies that the actor is part of.
- A Dashboard for managing movies, actors, reviews, and users. (Admin)
- Perform CRUD operations on all table management.
- Activate/ Deactivate user.
- Approve/ Disapprove movie reviews done by users.
A running instance of a MongoDB server is required for the app to start. The MongoDB is used for storing all data.
Do the following to clone and start the project. Install all dependencies, both frontend and backend.
$ git clone https://github.com/Bernz322/digital-streaming-system.git
$ cd digital-streaming-system
$ cd frontend
$ nvm install
$ npm i
$ cd ..
$ cd backend
$ npm i
Open two terminals and cd to frontend and backend folders respectively and start them
$ cd frontend
$ npm start
$ cd backend
$ npm start
The frontend app will be running at http://localhost:3005. The backend together with the API Explorer will be at http://localhost:3000/explorer/.
The app will have no data initially. The first user who will register will be treated as the root admin. This admin cannot be deleted nor edited.
A separate directory named 'db' in the root folder contains JSON files of several collections that the app uses. Import them to mongodb with a database named 'digital-streaming-system'.
This app has the following models:
User
- a model representing the users of the app.UserCredentials
- a model representing sensitive credentials like a password of the users.Movies
- a model representing the movies of the app.Actors
- a model representing the actors of the app.MovieCast
- a model to represent the actors of a movie and vice versa.Reviews
- a model representing the reviews of a user to a movie.
User
is marked as having one UserCredentials
model using the @hasOne
decorator. The belongsTo
relation for UserCredentials
to User
has not been created to keep the scope smaller.
Movies
is marked as having many Actors
through the MovieCast
model using the @hasMany(() => Actors, { through: {model: () => MovieCast})
to denote that it has many to many connection with the Actors
model. It is also marked as having many Reviews
using the @hasMany
decorator.
Similar to the Movies
model, the Actors
model is also marked as having many Movies
through the MovieCast
model using the @hasMany(() => Movies, { through: {model: () => MovieCast})
to denote that it has many to many connection with the Movies
model.
Reviews
is marked as belonging to the User
and Movies
models by the use of the @belongsTo
model decorator. Correspondingly, the User
and Movies
models are marked as having many Reviews
using the @hasMany
model decorator.
Controllers expose API endpoints for interacting with the models and more.
In this app, there are four controllers:
user
- controller for creating users, fetching user info, updating user info, deleting users, and logging in.movies
- controller for creating movies, fetching movie info, searching movies, updating movie info, and deleting movies.actors
- controller for creating actors, fetching actor info, searching actors, updating actor info, and deleting actors.reviews
- controller for creating, updating (approval), deleting movie reviews.
Services are modular components that can be plugged into a LoopBack application in various locations to contribute additional capabilities and features to the application.
This app has two services:
services/user.service
- responsible for verifying if user exists and the submitted credentials matches that of an existing user. It is also responsible for creating a profile to be used for the generation of JWT.services/jwt.service
- responsible for generating and verifying JSON Web Token with additionalrole
field for authorization.
Note: This app contains a login
endpoint ('users/login') for the authentication.
The endpoint for logging in a user is a POST
request to /users/login
.
Once the credentials are extracted, the logging-in implementation at the controller level is just a four step process. This level of simplicity is made possible by the use of the UserService
service provided by @loopback/authentication
. In this app, these services are customized to cater the needed implementation.
const user = await this.userService.verifyCredentials(credentials)
- verify the credentials.const userProfile = this.userService.convertToUserProfile(user)
- generate user profile object.const token = await this.jwtService.generateToken(userProfile)
- generate JWT based on the user profile object.return token
- send JWT.
Endpoint authorization is done using the @loopback/authorization. Wherein, the @authorize
decorator is used to restrict controller access with the allowedRoles
property.
A customized authorization provider is binded to authorizationProviders.my-authorizer-provider
to cater the roles of a user decoded from the JWT token.
The app has two roles: admin
, and user
. All get request endpoints of movies and actors controllers has no authorization instilled to it as it is a public route.
The frontend app has Unit test with backend API mocks using Mock Service Worker integrated to it. The backend controllers are unit tested with loopback testlab's stub implementation to the respective repositories to isolate and test controllers.
To execute the test, both frontend and backend must run simultaneously. Open another two terminals for frontend and backend respectively and run:
$ cd frontend
$ npm test
$ cd backend
$ npm test
To see the test coverage, follow the above instructions and run:
$ cd frontend
$ npm run coverage
$ cd backend
$ npm run coverage
Both frontend and backend are connected to sonarqube for scanning of code smells, bugs, security risks, vulnerabilities as well as see the test coverage. Below are the results for frontend (former) and backend (latter).