YaMa: Yet another Messaging app
This Technical Solution Design document for YaMa includes all technical reports and diagrams associated with the installation, running, testing, and usage of the YaMa Chat app.
As modern developers, our code of ethics plays an important role in everything we produce.
The team at Yama is tackling the very important issue of privacy, and the lack of it in many of the most popular apps people use every day, by creating a new cutting edge chat app.
We see the lack of privacy as a massive hole in the chat app market today, so we have developed a very simple, minimalistic app that offers end-to-end encryption straight out of the box.
We understand that the interests of the public should be at the forefront of technology.
That is why our app can be trusted to ensure the users' data is always kept secure and out of the clutches of the corporations that seek profit over quality of life.
Our app may be minimalistic at a glance, but under the hood, runs the highest level of security and encryption technology, that every Internet user should be given as their basic right.
Yama solves the problem of having to search through a mountain of settings to turn on privacy, by making it a default for all users.
Yama is seeking to empower the everyday user with a secure, minimalistic app that is intuitive and easy to use.
The Release section contains information regarding release notes and version information.
The Installation section contains instructions for the installation and running of the app.
The Vercel Deployment URL to the cloud is https://yama-chat.vercel.app/
End-User Guide
Instructions for YaMa users
This section contains the following information, and can also be accessed from the table of contents under the hamburger menu icon
.- Hamburger Menu
- Sun and Moon Icons
- Login and Logout
- Register as a New User
- YaMa chat page
- Friends
- Channel settings page
- User Settings page
- Forgotten Password
- About Us
Hamburger menu
Once you push the top left hamburger menu, you can select from these options:
Home goes to the logout page.
Chat goes to the YaMa chat page.
Settings goes to the settings page.
About goes to the about us page.
Logout goes to the logout page.
Sun and moon icons
In the top right, users can select from Daylight or Night time mode by pushing the sun or moon icon.
changes to Daytime Mode
changes to Night time Mode
Login
You must log in with your credentials to progress to the chat page.
- Push the Login button.
- Enter your username* or email address* exactly as you typed it when you created your account.
- Enter the password* you set during account creation.
* Required Field
Logout
Push the Logout button from the hamburger menu to simply logout of YaMa.
Register as a new user
Before you can log in, you must first create an account.
- Push Create Account from the home page.
- Enter your name.
- Enter your date of birth.
- Enter a contact phone number.
- Enter an email address (this must be a valid email address).*
- Enter a username (this must be unique and have no spaces).*
- Enter a strong password.*
- Push the Submit button.
Email address, username, and password, are all * Required Fields
Your password must be at least 8 characters in length and contain Upper and Lowercase characters and numbers and special characters.
An email will be sent to that address inviting you to join YaMa.
Once you receive the email, push the Accept Invite button to join YaMa.
YaMa chat page
Once you are logged in, you will arrive at the chat page, where you can select a Group from the options on the left:
Add a new group button
Push to add a new Group.
Push to leave a Group or Channel.
Enter a name for your new Group and push the Create button to create you new Group.
Use the toggle to make the Group either Public or Private.
A Private group can only be accessed by the members invited to it.
A Public group can be joined by any user.
Friends button
Push to display your list of friends. (see the Friends page for more information)
Select a group button
Push to display the list of Channels in that Group.
Once you have selected a Group, the Channels belonging to that Group will be shown.
Push on one of the Channels to start chatting!
Friends
The friends’ menu displays the list of friends.
Invite a new friend button
Push to invite a new friend.
Search for a friend
Instead of scrolling to find your friend, simply search for their username in the Filter Friends area.
Once you push on the name of your friend, you can start chatting!
Push the
icon to remove a friend.Invite a new friend page
To invite a new friend, simply fill in their details and push the Invite Friend button.
- New user's email address*
- New user’s name
- A message to a new user.
* Required Field
Push the Invite New Member button.
An invitation will be sent to your friend’s email address.
Once they accept the invitation, you can start chatting!
Channel settings page
Administrator access
Admin level users will see a cog icon
next to the name of the Channel.Push on the cog icon
to edit the settings for that Channel.Create New Channel
After pushing the Create New Channel button to create a new channel under your Group.
Enter the new Channel name and push the Create button.
Push Back to go back to group settings page.
Push the
icon closes the page to reveal the chat screen.Invite New Members
Push the Invite New Members button to invite a new person to your Group.
Enter the new user's email address*, their name, and a message to the new user.
Once you push the Invite New Members button, an email will be sent to that address.
The new user must accept the email invitation before they will be authorised to join your Group.
* Required Field
Email sent
Channel Settings
The user can edit the channel name, delete the channel, or modify who has access to the channel here.
Enter a new channel name and push the Change button.
Push the Delete Channel to delete the channel.
You will be taken to a confirmation screen informing you of the actions that will be taken once the Channel has been deleted.
Once you read and understand the actions, push the Delete Channel again.
Push Back or the button to go back to the previous screen.
Remove Members
Push the Remove Members button to remove a current member from your Group.
Once you push the Remove Members button, the member will be removed from your Group.
Push Back or the button to go back to the previous screen.
Delete a group
When you push the Delete Group button, you will be taken to a confirmation screen informing you of the actions that will be taken once the Group has been deleted.
Once you read and understand the actions, push the Delete Group again.
Return to previous screen
Push the
button to go back to the previous screen.User Settings page
To reach the Settings page, push the Settings link from the Hamburger menu.
You will be asked to Confirm Credentials before being given access to the Settings page.
Once confirmed, the user will be able to edit their personal details, including changing their Avatar.
Forgotten Password
Users can Reset their passwords by pushing the Reset forgotten password link.
Simply enter a valid email address and push the Request Password Reset button.
A thank you message will appear on the screen and an email will be sent to that address so that you can reset your password.
Thank you
You have been emailed a link you can use to reset your password.
Once you have reset your password, you can start chatting on YaMa.
Email sent
About us
Hello, and welcome to YaMa, a secure messaging app for the modern world.
YaMa provides an easy, enjoyable way to communicate with your family, friends or colleagues.
It is a web application that is simple and free to use for everyone.
With YaMa you can send text or voice messages as well as create groups or channels for people to join and communicate with.
Our mission is to provide users with a messaging application that is both private and secure.
That is why at YaMa we support end-to-end encryption for voice and text messages so you can be ensured that your conversations remain private.
The team
David Ceccato | Lead Developer | "Success is a journey not a destination"
Jaekyoung Chang | Tester | "Collect moments, not things"
Murray Lowis | Developer | "Laziness is the first step to efficiency"
Stephen Patrikios | Project Owner | "Live, laugh, love"
Jacob Pyke | Information Architect | "Do or do not, there is no try"
Malcolm Tsang | UX/UI Designer | "The happiest people don't have the best of everything, they make the best of everything"
Technical Environment
Overview
This section details the technical environment for YaMa. It will detail the tools used to complete the project, why those specific tools were chosen, and how the team came to that conclusion.
Source Control - GitHub
For source control, the option was going to be straightforward. Within the development team we all had high levels of experience with GitHub. GitHub is the leader for source control solutions with a wide variety of features that also will increase developer productivity. One key extra feature is GitHub actions.
Backend Hosting/Infrastructure - AWS
For the back-end functions used by YAMA we chose to utilise Amazon Web Services, or AWS.
AWS allows the easy provisioning of services based on application load without the need for procurement, configuration or maintenance of the underlying hardware or operating systems.
Within the AWS ecosystem, we are utilising Amazon Gateway and Lambda functions.
The gateway allows us to rapidly built API endpoints that can be accessed directly by the front-end, while the Lambda functions called by the gateway offer optimised containers that spin up only when required. This provides efficiency, scalability, and cost benefits. Each Lambda function is launched only when required and terminates when complete, limiting service charges, while many Lambda functions can be launched simultaneously to handle increased load.
The Lambda functions provide secure access to all the database CRUD operations that will be required.
Database - MongoDB
The database system we chose to store all our data, is MongoDB.
MongoDB provides a fast NO-SQL database that stores information as collections of documents in a highly optimised binary JSON format.
It was estimated that MongoDB would offer efficiencies for accessing YAMA chat messages, as NO-SQL databases such as Mongo are great at streaming data that does not require complex relationships or joins. The lack of an SQL command interpreter that can be utilised in a relational SQL database means that data can be processed more quickly, while server load is significantly reduced.
With the free-tier offered by MongoDB’s ATLAS, we are able to manage the database, view all the data, and perform queries online via any browser. This allows the team to easily collaborate using the same data store and test query results that will be integrated into the application.
Frontend Framework - Svelte
The front-end of the YAMA chat app has been developed as a reactive single page application using Svelte with components adhering to Google’s Material Design specification.
Svelte offers similar benefits of other reactive JavaScript frameworks such as React or Vue, where changes in state or value of a variable can be kept synchronised with the DOM with little effort by the developer. However Svelte has one key difference, it is a compiler rather than a traditional bundled framework.
With Svelte, any code that is written to take advantage of the enhanced reactive capabilities offered is compiled to native JavaScript. This way no framework needs to be loaded by the client. This reduces the size of the JavaScript payload, as well as increasing speed by running the code natively in the browser rather than requiring commands to be first interpreted by a framework.
CI/CD - GitHub Actions and Vercel
GitHub Actions
GitHub actions allow us to create automated processes that trigger based on changes to our code repository. We use GitHub actions for a multitude of purposes including running automated tests once our code is uploaded. As well as automatically deploying the latest development or productive branch to Vercel, they are highly dynamic and can support multiple helpful use cases.
Vercel
For deploying YAMA to the internet, we needed to ensure that we found a deployment platform that filled three key criteria. Firstly, deploying development builds quickly. As we are a small dev team that are geographically distant it is important that we are keeping up to date with the project. Secondly, low effort. Due to our small manpower, it is important that we can setup the tool quickly. Finally, cost, as the goal of this project is to keep costs to a minimum, this is arguable the most important factor. Software that we found that fits all three requirements perfectly is Vercel.
Svelte Guide
To create a new project based on this template using degit:
npx degit sveltejs/template NAME_OF_YOUR_PROJECT
cd NAME_OF_YOUR_PROJECT
Get started
Install the dependencies from inside/your/project_folder
cd inside/your/project_folder
npm i
Start Rollup:
npm run dev
Navigate to localhost:8080 to see your app running.
By default, the server will only respond to requests from localhost
.
To allow connections from other computers, edit the sirv
commands in package.json
to include the option --host 0.0.0.0
.
If your project does not need to be accessed from other computers whilst developing, there is no need to add --host
to your package.json
file.
If you're using Visual Studio Code we recommend installing the official extension Svelte for VS Code. If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
Building and running in production mode
To create an optimised version of the app:
npm run build
You can run the newly built app with npm run start
.
This uses sirv, which is included in your package.json's dependencies
so that the app will work when deployed to Vercel.
Updating CSS
Whenever you make global changes to the CSS you will need to run the following command:
npm rum prepare
For this project we are using Svelte Material-UI components and styling, so whilst developing, if changes are made to the src/theme/_smui-theme.scss
or src/theme/dark/_smui-theme.scss
files, npm run prepare
needs to be run before any of your changes will be seen on your localhost:8080
.
Vercel Guide
Installing Vercel into your project
Only one team member needs to do this.
Only one org_id and one project_id Vercel token are required.
To use Vercel as the deployment service for this project, it needs to be installed into your project folder.
Step 1
cd inside/your/project_folder
inside/your/project_folder: npm i vercel
# added 97 packages, and audited 148 packages in 18s
#
# 11 packages are looking for funding
# run `npm fund` for details
#
# found 0 vulnerabilities
inside/your/project_folder: vercel
Vercel CLI 24.0.0
? Set up and deploy “~/inside/your/project_folder”? [Y/n] y
? Which scope do you want to deploy to? name_of_your_github_repo
? Link to existing project? [y/N] n
? What’s your project’s name? project_folder_name
? In which directory is your code located? ./
No framework detected. Default Project Settings:
- Build Command: `npm run vercel-build` or `npm run build`
- Output Directory: `public` if it exists, or `.`
- Development Command: None
? Want to override the settings? [y/N] n
🔗 Linked to name_of_your_github_repo/project_folder_name (created .vercel)
🔍 Inspect: https://vercel.com/name_of_your_github_repo/project_folder_name/A3MAa479CsfwGWD9 [2s]
✅ Production: https://project_folder_name-orcin.vercel.app [copied to clipboard] [13s]
📝 Deployed to production. Run `vercel --prod` to overwrite later (https://vercel.link/2F).
💡 To change the domain or build command, go to https://vercel.com/name_of_your_github_repo/project_folder_name/settings
inside/your/project_folder:
Step 2
In your project folder there will be a newly created .vercel
folder.
Open the project.json file and take note of the org_id
and project_id
values. These need to be added to the GitHub repository.
Adding Vercel tokens to GitHub
Step 1
Login to your Vercel account and navigate to the Settings
page from your main dashboard.
Click on Tokens
on the left.
Click on Create
, enter the name of your new token, and select Full access
from the Scope
dropdown menu to create a new token.
Step 2
Go to your GitHub repository and navigate to Settings -> Secrets -> Actions
Click on New repository secret
and create the following three Action secrets
.
Secret 1:
Name:
- VERCEL_TOKEN
Value:
- Paste in the new token you just created in Vercel
Secret 2:
Name:
- VERCEL_ORG_ID
Value:
- Paste in the `orgId` token from you `project.json` file in the `.vercel` folder
Secret 3:
Name:
- VERCEL_PROJECT_ID
Value:
- Paste in the `projectId` token from you `project.json` file in the `.vercel` folder
Playwright Guide
Playwright and the Playwright Library was chosen to run the end-to-end testing requirements for YaMa.
Using Playwright will allow for:
- Tests to be run across all browsers
- Tests to be run in parallel
- The identification of points of failure
Local testing will require the local installation of all of the Browsers you want to test for.
Our git action script to automate Playwright testing includes the additional installation of both MS Edge and Chrome.
Installation
Navigate to the root directory of your project and run the npm init
command.
cd inside/your/project_folder
# Run this command to install the latest version of Playwright
npm init playwright@latest
# Need to install the following packages:
# create-playwright@latest
# Ok to proceed? (y) (Enter y to proceed)
# Getting started with writing end-to-end tests with Playwright:
# Initializing project in '.'
# ? Do you want to use TypeScript or JavaScript? … (use your arrow keys to select JavaScript and hit Enter)
TypeScript
▸ JavaScript
# ? Where to put your end-to-end tests? ‣ yama-tests (enter a name for your test here e.g.yama-tests and hit Enter)
# ? Add a GitHub Actions workflow? (Y/n) ‣ true (Enter y to proceed)
# ? Install Playwright operating system dependencies (requires sudo / root - can be done manually via sudo npx playwright install-deps')? (y/N) ‣ false (Enter n to proceed. We will do this later.)
# Note: Entering y will not work on an Arch Based Linux disrto as the automatic install script contains apt-get commands which do not work on Arch Based Linux distros.
Once you hit n
, the installation process shall begin.
# Installing Playwright Test (npm install --save-dev @playwright/test)…
up to date, audited 341 packages in 751ms
27 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Downloading browsers (npx playwright install)…
Downloading Playwright build of chromium v978106 - 130.7 Mb [====================] 100% 0.0s
Playwright build of chromium v978106 downloaded to /$HOME/.cache/ms-playwright/chromium-978106
Downloading Playwright build of ffmpeg v1007 - 2.6 Mb [====================] 100% 0.0s
Playwright build of ffmpeg v1007 downloaded to /$HOME/.cache/ms-playwright/ffmpeg-1007
Downloading Playwright build of firefox v1319 - 75.5 Mb [====================] 100% 0.0s
Playwright build of firefox v1319 downloaded to /$HOME/.cache/ms-playwright/firefox-1319
Downloading Playwright build of webkit v1616 - 78.8 Mb [====================] 100% 0.0s
Playwright build of webkit v1616 downloaded to /$HOME/.cache/ms-playwright/webkit-1616
Writing playwright.config.js.
Writing .github/workflows/playwright.yml.
Writing yama-tests/example.spec.js.
Writing package.json.
✔ Success! Created a Playwright Test project at /$HOME/your-project-folder/yama
Inside that directory, you can run several commands:
npx playwright test
Runs the end-to-end tests.
npx playwright test --project=chromium
Runs the tests only on Desktop Chrome.
npx playwright test yama-tests/example.spec.js
Runs the tests of a specific file.
npx playwright test --debug
Runs the tests in debug mode.
We suggest that you begin by typing:
npx playwright test
And check out the following files:
- ./yama-tests/example.spec.js - Example end-to-end test
- ./playwright.config.js - Playwright Test configuration
Visit https://playwright.dev/docs/intro for more information. ✨
Happy hacking! 🎭
➜ user@name ~/your-project-folder/yama git:(main) ✗
How to run a test locally
From your project folder, let's follow the suggestion and run a test using npx playwright test
.
To see the results of the test enter npx playwright show-report
.
Your Browser will now open and show you the results from the Playwright test you just ran.
Manjaro users
First we need to install the browser dependencies for Manjaro from the Arch repository, as they are only included for Ubuntu when using the sudo npx playwright install-deps
command.
Browser Dependency 1
yay -S enchant1.6
loading packages...
resolving dependencies...
looking for conflicting packages...
Packages (1) enchant1.6-1.6.1-9
Total Installed Size: 0.18 MiB
:: Proceed with installation? [Y/n]
(1/1) checking keys in keyring [########################################] 100%
(1/1) checking package integrity [########################################] 100%
(1/1) loading package files [########################################] 100%
(1/1) checking for file conflicts [########################################] 100%
(1/1) checking available disk space [########################################] 100%
:: Processing package changes...
(1/1) installing enchant1.6 [########################################] 100%
:: Running post-transaction hooks...
(1/2) Arming ConditionNeedsUpdate...
(2/2) Refreshing PackageKit...
➜ user@name ~
Browser Dependency 2
yay -S icu66
:: Checking for conflicts...
:: Checking for inner conflicts...
[Aur:1] icu66-66.1-1
:: (1/1) Downloaded PKGBUILD: icu66
1 icu66 (Build Files Exist)
==> Diffs to show?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==> 1
==> Proceed with install? [Y/n]
loading packages...
resolving dependencies...
looking for conflicting packages...
Packages (1) icu66-66.1-1
Total Installed Size: 32.15 MiB
:: Proceed with installation? [Y/n]
(1/1) checking keys in keyring [########################################] 100%
(1/1) checking package integrity [########################################] 100%
(1/1) loading package files [########################################] 100%
(1/1) checking for file conflicts [########################################] 100%
(1/1) checking available disk space [########################################] 100%
:: Processing package changes...
(1/1) installing icu66 [########################################] 100%
:: Running post-transaction hooks...
(1/2) Arming ConditionNeedsUpdate...
(2/2) Refreshing PackageKit...
➜ user@name ~
Browser Dependency 3
yay -S libwebp052
:: Checking for conflicts...
:: Checking for inner conflicts...
[Aur:1] libwebp052-0.5.2-2
:: (1/1) Downloaded PKGBUILD: libwebp052
1 libwebp052 (Build Files Exist)
==> Diffs to show?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==> 1
==> Proceed with install? [Y/n]
loading packages...
resolving dependencies...
looking for conflicting packages...
Packages (1) libwebp052-0.5.2-2
Total Installed Size: 0.93 MiB
:: Proceed with installation? [Y/n]
(1/1) checking keys in keyring [########################################] 100%
(1/1) checking package integrity [########################################] 100%
(1/1) loading package files [########################################] 100%
(1/1) checking for file conflicts [########################################] 100%
(1/1) checking available disk space [########################################] 100%
:: Processing package changes...
(1/1) installing libwebp052 [########################################] 100%
Optional dependencies for libwebp052
freeglut: vwebp viewer [installed]
:: Running post-transaction hooks...
(1/2) Arming ConditionNeedsUpdate...
(2/2) Refreshing PackageKit...
➜ user@name ~
Now that we have the correct browser dependencies installed for Manjaro we can run the test command npx playwright test
.
➜ user@name ~/your-project-folder/yama git:(main) ✗ npx playwright test
Running 75 tests using 3 workers
Slow test file: [webkit] › example.spec.js (25s)
Slow test file: [firefox] › example.spec.js (22s)
Slow test file: [chromium] › example.spec.js (15s)
Consider splitting slow test files to speed up parallel execution
75 passed (25s)
To open last HTML report run:
npx playwright show-report
➜ user@name ~/your-project-folder/yama git:(main) ✗
To see the results of the browser tests, run npx playwright show-report
.
A browser window will automatically open at the address indicated and display your test results.
➜ user@name ~/your-project-folder/yama git:(main) ✗ npx playwright show-report
Serving HTML report at http://127.0.0.1:9323. Press Ctrl+C to quit.
^C
➜ user@name ~/your-project-folder/yama git:(main) ✗
MongoDB Guide
Information on how to access MongoDB Atlas
Installation steps for MongoDB Compass
General instructions on how to install MongoDB Compass locally can be found on the MongoDB Compass site.
Using MongoDB Compass
In order to use MongoDB Compass locally, you'll need to create a new user from the MongoDB Atlas web interface.
After you log in, click on Database Access on the left, then Add new database user on the right.
Create a new user to give yourself access to the database using MongoDB Compass.
Once you've done this, you'll have a username and password that MongoDB Compass can use to connect you to the database.
Click on Database on the left, and the connect button in the middle.
Select the bottom option, Connect using MongoDB Compass, copy the connection string.
Open your local version of MongoDB Compass, click on the New Connection button and add your connection string to the URI.
You can now access your database locally.
Installation steps for MacOS
This installation guide is written for MacOS Monterey 12.3 (21E230). Keep in mind that MacOS often makes sweeping changes per major version
This guide will use Homebrew to install the required packages. In the event that you already have Homebrew on your system (Can be verified by running brew --version
) then skip to Installing.
In order to install Homebrew run in a terminal:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
After that, verify correct installation:
brew --version
Installing MongoDB Compass for MacOS
Run in a terminal after installing Homebrew:
brew install --cask mongodb-compass
Then, check the /Applications/
or the Launchpad
for the MongoDB Compass App
AWS SAM Guide
AWS Severless Application Model (SAM) Command Line Interface (CLI) - installation instructions.
The Amazon Developer Guide contains instructions for installing AWS SAM CLI on Windows, macOS, and Linux.
Manjaro users
Step 1
Check which version of Python you have installed on your local machine using python --version
.
If you do not have python 3.9 installed, the sam build
will fail. If you do have python 3.9 installed then move to Step 2.
Having python 3.10 installed globally here /usr/bin, makes sam build
fail.
Therefore, rollback to python 3.9.10 using the following commands:
# Install pyenv so you are able to select the version of python you want to be installed.
sudo pacman -S pyenv
# Running the next command will give you a list of the available versions
pyenv install 3.9
# Install python 3.9.10 using
pyenv install 3.9.10
Now that python 3.9.10 is installed, we need to set its PATH.
# Open your .bashrc or .zshrc file (whichever you are using) and
# add the following to the bottom of the page:
export PATH=$PATH:$HOME/.pyenv/versions/3.9.10/bin/
We have now informed AWS the location of python 3.9.10 on your machine and can now run sam build
.
Step 2
Run the following command to install the SAM CLI.
pip3 install aws-sam-cli
Start using the AWS SAM CLI with these commands.
Installation steps for MacOS
This installation guide is written for MacOS Monterey 12.3 (21E230). Keep in mind that MacOS often makes sweeping changes per major version
Whilst it is optional, it is highly recommended that Docker Desktop is installed for using the AWS SAM CLI. This install guide will cover the installation of Docker Desktop. In the event you have already installed Docker Desktop, then skip to here
Installing Docker Desktop
Step 1 - Installing Homebrew
This guide will use Homebrew to install the required packages. In the event that you already have Homebrew on your system (Can be verified by running brew --version
) then skip to Installing.
In order to install Homebrew run in a terminal:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
After that, verify correct installation:
brew --version
Step 2 - Installing Docker
Run in a terminal after installing Homebrew:
brew install --cask mongodb-compass
Then, check the /Applications/
or the Launchpad
for the MongoDB Compass App
Installing SAM CLI - MacOS
Run in a terminal after installing both Homebrew and Docker Desktop:
brew tap aws/tap
brew install aws-sam-cli
After this command has completed, verify that AWS SAM CLI is installed by running:
sam --version
VS Code Extension - AWS SAM CLI
AWS Toolkit VS Code extension can help deploy your application.
Node Modules
DevDependencies used in this project
This list can be found in the package.json
file of the project.
These can be installed using npm i -D <package-name>
(e.g. npm i -D @smui-extra/accordion)
➜ user@name ~/your-project-folder/yama git:(main) npm list
svelte-app@1.0.0 ~/your-project-folder/yama
├── @dicebear/avatars-identicon-sprites@4.10.2
├── @dicebear/avatars@4.10.2
├── @material/button@13.0.0
├── @material/elevation@13.0.0
├── @playwright/test@1.21.1
├── @rollup/plugin-commonjs@17.1.0
├── @rollup/plugin-node-resolve@11.2.1
├── @rollup/plugin-typescript@8.3.2
├── @smui-extra/accordion@6.0.0-beta.16
├── @smui-extra/badge@6.0.0-beta.16
├── @smui/button@6.0.0-beta.16
├── @smui/checkbox@6.0.0-beta.16
├── @smui/drawer@6.0.0-beta.16
├── @smui/fab@6.0.0-beta.16
├── @smui/form-field@6.0.0-beta.16
├── @smui/icon-button@6.0.0-beta.16
├── @smui/layout-grid@6.0.0-beta.16
├── @smui/list@6.0.0-beta.16
├── @smui/paper@6.0.0-beta.16
├── @smui/switch@6.0.0-beta.16
├── @smui/textfield@6.0.0-beta.16
├── @smui/tooltip@6.0.0-beta.16
├── @smui/top-app-bar@6.0.0-beta.16
├── @tsconfig/svelte@2.0.1
├── @types/crypto-js@4.1.1
├── @types/node@17.0.31
├── @types/webcrypto@0.0.28
├── autoprefixer@10.4.7
├── node-sass@7.0.1
├── postcss@8.4.13
├── recordrtc@5.6.2
├── rollup-plugin-css-only@3.1.0
├── rollup-plugin-livereload@2.0.5
├── rollup-plugin-postcss@4.0.2
├── rollup-plugin-svelte@7.1.0
├── rollup-plugin-terser@7.0.2
├── rollup@2.72.1
├── sass@1.51.0
├── sirv-cli@2.0.2
├── smui-theme@6.0.0-beta.16
├── snyk@1.922.0
├── svelte-check@2.7.0
├── svelte-preprocess@4.10.6
├── svelte-spa-router@3.2.0
├── svelte@3.48.0
├── tslib@2.4.0
├── typescript@4.6.4
└── unset-value@2.0.1
➜ user@name ~/your-project-folder/yama git:(main)
Installing Node.js
Windows users
Windows users who are using the Windows Subsystem for Linux (WSL) in Windows 11 will need to update to a more current version of Node.js.
The Node.js included in the WSL Ubuntu 20.04 is version 10.19.
This version is currently unsupported and unmaintained, and will cause problems for the user when installing packages and dependencies.
Run the following commands from inside your project folder to update to the latest version of Node.js.
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
MacOS Users
Step 1 - Installing Homebrew
This guide will use Homebrew to install the required packages. In the event that you already have Homebrew on your system (Can be verified by running brew --version
) then skip to Installing.
In order to install Homebrew run in a terminal:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
After that, verify correct installation:
brew --version
Step 2 - Installing NodeJS
Run in a terminal after installing both Homebrew and Docker Desktop:
brew install node
After this command has completed, verify that AWS SAM CLI is installed by running:
node --version
mdBook Installation and Usage Guide
Installation Guide
The easiest method for installing mdBook on your particular operating system is to download the executable binary file from the mdBook GitHub Releases page.
Once you have downloaded the file, extract it in your preferred method and run the executable.
In the Windows zip file there is a .exe file for you to use.
For Mac users, there is a tar ball for you to use.
In the Linux .tar.gz file, open a shell in the folder you want to extract the executable file, and use the following command to download and extract the executable file.
wget -O- https://github.com/rust-lang/mdBook/releases/download/v0.4.15/mdbook-v0.4.15-x86_64-unknown-linux-gnu.tar.gz | tar xzvf -
The commands
The commands used in the wget
are as follows:
- We can use -O- to send to STDOUT (the standard out)
- We use the pipe | to pipe it into the tar ball using
tar xzvf -
- Which essentially does an un-gz on the tar ball
- v is verbose (i.e. the type of output you produce)
- f is file (in this case it was the STDOUT file)
- So the tar ball was extracted out from the STDOUT file
- The STDOUT of wget became the STDIN for the tar ball
- Important: The final dash
-
is to extract from the STDOUT
After extraction
In your shell run ./mdbook
This will install mdbook
on your local machine.
➜ user@name ~ ./mdbook
mdbook v0.4.15
Mathieu David <mathieudavid@mathieudavid.org>
Creates a book from markdown files
USAGE:
mdbook [SUBCOMMAND]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
SUBCOMMANDS:
build Builds a book from its markdown files
clean Deletes a built book
completions Generate shell completions for your shell to stdout
help Prints this message or the help of the given subcommand(s)
init Creates the boilerplate structure and files for a new book
serve Serves a book at http://localhost:3000, and rebuilds it on changes
test Tests that a book's Rust code samples compile
watch Watches a book's files and rebuilds it on changes
For more information about a specific command, try `mdbook <command> --help`
The source code for mdBook is available at: https://github.com/rust-lang/mdBook
How to use mdBook
Clone the GitHub Repo to your local machine and open it in your code editor of choice and make a new branch for yourself.
The Table of Contents on the left side of the website is created in the SUMMARY.md
file.
If you want to add a new section, the follow the styling in the SUMMARY.md
file to add your new page.
How to add a new section
// The "#" represents a H1 tag
# Heading Of Your New Section
// dash is an unordered list.
- Unordered List
- Unordered List
// Inside the [ ] is the hyperlink name and inside the ( ) is the hyperlink path.
[New Subsection Name](Heading Of Your New Section/NewFileName.md)
Now, save and run mdbook build
in your shell and your new section and file will automatically appear in the Table of Contents.
Open the file that you have just created and write your content using Markdown.
Useful sites about using Markdown
Once you have finished creating your content save and run mdbook build
in your shell again.
This creates all of the HTML files that will be displayed on the website.
As we are using a GitHub Action
to build
the book once it is pushed to GitHub, it is not necessary to run mdbook build
before you push to GitHub.
How to add your changes to GitHub and deploy to Vercel
VS Code
- Stage the files you made changes to and add a meaningful comment.
- Push your files to GitHub
Command Shell
Use the following commands to add your changes:
git commit -m "Add_A_Meaningful_Comment" file_you_changed_1 file_you_changed_2 ...
git push -u origin [the name of the branch you are currently working on] // without the [ ]
There is a GitHub Action
in the yama-documentation repo that will automatically build
and deploy
your changes once you push
them to Github.
What is in the src folder
The src folder contains all of the markdown files that are shown on the documentation site.
When you want to edit a page, this is where you can do that.
The book folder contains all of the HTML files that are automatically produced when mdbook build
is run.
You only need to run mdbook build
if you are testing on your local machine.
You should have book/.*
in your .gitignore file.
Call-out styling with mdbook-admonish
mdbook-admonish is a plugin for mdBook that will allow you to add Material UI style call-outs to your book.
Step 1
cd inside/your/project_folder
inside/your/project_folder: cargo install mdbook-admonish
Step 2
Install the required files and configuration code using:
inside/your/project_folder: mdbook-admonish install
These two configuration settings will be added to your book.toml file.
[preprocessor.admonish]
command = "mdbook-admonish"
[output.html]
additional-css = ["./mdbook-admonish.css"]
Step 3
Copy the file mdbook-admonish.css
into the book directory of your project if it's not already there.
Step 4
Build your book using:
inside/your/project_folder: mdbook
Continuous Integration / Continuous Development
GitHub Actions for YaMa
Automate Playwright testing
This action installs Playwright, with the necessary dependencies, so that all of the tests can run before deploying to Vercel.
name: Playwright Tests
on:
push:
branches: [ main, master, testing ]
pull_request:
branches: [ main, master, testing ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14.x'
- name: Install dependencies
run: npm i
- name: Install Playwright
run: npx playwright install --with-deps
- name: Install Microsoft Edge
run: npx playwright install msedge
- name: Install Google Chrome
run: npx playwright install chrome
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v2
if: failure()
with:
name: playwright-report
path: playwright-report/
retention-days: 7
Deploy YaMa to Vercel
This action installs Vercel and then deploys the app.
The benefit of this action is that an instance of Vercel is initialised only when needed.
name: Deploy to Vercel
on:
push:
branches: [ main, testing ]
jobs:
buildAndDeploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Setup Node.js (required to install Vercel CLI)
uses: actions/setup-node@v3
- name: Install Vercel CLI
run: npm install --global vercel
- name: Deploy static content to Vercel
run: |
productionFlag=""
if [[ ${GITHUB_REF} == "refs/heads/main" ]]; then
productionFlag="--prod"
fi
vercel . --token ${VERCEL_TOKEN} $productionFlag
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
Automate the build and deployment of the mdBook site.
This action installs mdBook, installs Admonish for Material UI call-outs styling, builds the book (html files), and then deploys it to Vercel .
The benefit of this action is that an instance of mdBook is initialised only when needed.
The following Environment Variables should be added as Encrypted Secrets in GitHub.
VERCEL_TOKEN
refers to the special access token which will be used to authenticate the login session in the CI/CD environment.
Refer to this support article on Vercel Access Token for more information.
The VERCEL_PROJECT_ID
& VERCEL_ORG_ID
are found inside the .vercel/project.json
file of your project.
name: Build Book & Deploy to Vercel
on: [push, pull_request]
jobs:
buildAndDeploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Install mdBook
uses: extractions/setup-crate@v1
with:
owner: rust-lang
name: mdBook
- name: Install mdBook Admonish
run: cargo install mdbook-admonish
- name: Add required files and configuration for Admonish
run: mdbook-admonish install
- name: Generate static content for the book
run: mdbook build
- name: Setup Node.js (required to install Vercel CLI)
uses: actions/setup-node@v3
- name: Install Vercel CLI
run: npm install --global vercel
- name: Deploy static content to Vercel
run: |
productionFlag=""
if [[ ${GITHUB_REF} == "refs/heads/main" ]]; then
productionFlag="--prod"
fi
vercel . --token ${VERCEL_TOKEN} $productionFlag
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
Automate the saving of .drawio files to .png.
In order for this action to work, the .drawio file must have changed after this action was initially run.
If no changes have been made to the .drawio file, this action will not do anything.
name: Export drawio files to png and keep updates synchronised
on:
push:
branches: [ main, testing ]
pull_request:
branches: [ main, testing ]
paths:
- "**.drawio"
- .github/workflows/drawio-export-png.yaml
concurrency:
group: drawio-export-${{ github.ref }}
cancel-in-progress: true
jobs:
drawio-export:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Draw.io Export Action
uses: rlespinasse/drawio-export-action@2.1.0
with:
# Path to the drawio files to export
path: diagrams
# Exported format [default: pdf] [possible values: adoc, jpg, pdf, png, svg, vsdx, xml]
format: png
# Exported folder name (default location is same a path above)
output: ../src/media
# Remove the Page label (i.e. Page-1) from file name
remove-page-suffix: true
# Sets the border width around the diagram
border: 5
- name: Get author and committer info from HEAD commit
uses: rlespinasse/git-commit-data-action@v1
if: github.ref == 'refs/heads/main'
- name: Commit changed files
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "docs: sync drawio exported files"
commit_user_name: "${{ env.GIT_COMMIT_COMMITTER_NAME }}"
commit_user_email: "${{ env.GIT_COMMIT_COMMITTER_EMAIL }}"
commit_author: "${{ env.GIT_COMMIT_AUTHOR }}"
if: github.ref == 'refs/heads/main'
Overall Architecture
The application makes use of four key services to function:
- Svelte – A special frontend framework that allows responsive code to be written, and then compiled to standard javascript.
- Vercel – A hosting service that allows us to easily deploy the Svelte frontend.
- AWS – Provides a gateway that links to serverless Lambda functions to perform logic operations and CRUD access to the database.
- MongoDB – A NoSQL cloud hosted database to store the data.
1.1 Svelte
Svelte is a unique component framework that allows for reactive and rapid development in a similar way to more well-known frameworks such as React or Vue. The difference with Svelte is that it compiles everything to standard JavaScript rather than requiring a framework to be downloaded by the client.
The Svelte generated frontend which is hosted on a Vercel virtual environment makes calls to the backend via the AWS REST API gateway using the Fetch API. Every time the client does an action that requires data transfer to the backend, a HTTP request is sent to a specified gateway endpoint for processing and the result is relayed to the client.
1.2 Vercel
Vercel offers a virtual hosting environment that integrates well with Svelte. Within our GitHub repository we have an action script that automatically initiates a build and deployment to Vercel every time a push is made.
Vercel automatically builds and deploys the code to either a preview environment, or when pushing to the main branch, a production environment. This allows the easy identification of any build errors, as well as providing a fast to inspect the state of the application and perform any required tests in a hosted environment.
1.3 Amazon Web Services (AWS)
AWS is a cloud operator that offers a huge range of services that allow rapid development without the need for procurement of the required hardware.
The AWS Gateway that we use for our application is set up with a number of endpoint that accept a designated HTTP request type such as GET or POST. Each endpoint and request type is configured to pass the request on to a designated Lambda function for processing.
Lambda functions are a lean virtual environments that contain just enough dependencies to process the passed request. The Lambda environment spins up when it receives a request, processes the request, and then terminates when the request is complete, saving resources and cost.
The Lambda functions direct CRUD operations over the internet to MongoDB Atlas. MongoDB processes the request and returns the result of the database action back to the Lambda function.
Once the database data is returned to the Lambda function, the data is further manipulated and processed as required by the Lambda. Once complete, the required results are returned back through the gateway, and on to the clients browser.
1.4 MongoDB Atlas
MongoDB Atlas is a cloud-hosted NoSQL database that is used to store all the client data. The free-tier that we are using for the assignment exists on a shared virtual server running on AWS infrastructure.
When the request is received from the Lambda function, the user is first validated, and then the request is processed by the virtual server. As MongoDB is a NoSQL database, there is no SQL query language interpreter running on the server. To access the data, a series or structured JSON requests must be passed to the server which is then actioned against the data.
System Architecture
GitHub Repository:
Project Yama GitHub Repository
- We will create a new branch for each feature being worked.
- Team members will pull from the testing branch at the start of each sprint and then merge to the testing branch once they feel each task has been completed and passed all tests locally.
- Once a merge has been done to the testing branch, the automated Playwright testing and Vercel build process will be initiated.
- When we have completed enough for a relatively stable release, or we need to deploy for submission, the testing branch can then be merged into the Main branch and a release created if required.
Development Architecture:
- The front-end will be developed using the Svelte framework/compiler.
- When pushed to GitHub, an Action script will initiate a suite of Playwright automated tests to ensure everything is working as expected and automatically builds the code and deploys the application to Vercel. Any deployments from the Main branch are automatically pushed to production, while other branches are pushed to randomly generated URLs for testing.
- The back-end will be developed using AWS Server Application Model (SAM) that allows local development, testing and deployment to AWS. A bash script has been written to automate the running of test-calls to the local instance of the API that is built in a Docker container to ensure everything is working before deployment.
- As MongoDB is a NoSQL database and does not have a fixed schema, we do not need to test or deploy anything after the initial setup.
Database Architecture
Database Structure
As we are using MongoDB, a NoSQL database, we do not have a fixed schema or rigid entity relationship between the tables. However, we did plan an initial database structure using a basic ER Diagram to follow as a guide during development.
Initial ER Diagram
Revised MongoDB ER Diagram
Reasoning
We chose MongoDB as a learning experience and because we initially felt that the structure of the chat application would not require any complex relationships or queries. NoSQL databases like MongoDB offer an efficient way to write simple data to documents in a fast and efficient way without the overhead of a SQL interpreter.
We designed the structure of the database to try and have a limited number of tables and relationships, with all data in consistent groupings for fast read and write. We made extensive use of the Array and Object data types that MongoDB offers in order to maintain efficiency and easily map the data to variables in the code.
In practice however, we found that MongoDB had a number of shortcomings and limitations that slowed development. As there is not fixed schema to ensure the consistency of data and the relationships between those data points, all the rules for reading and writing must be managed within the backend code.
In hindsight, using an SQL-based database system that we were more familiar with would have reduced the number of issues we faced with data consistency and rules management. If the chat application was just one big public forum with limited rules, MongoDB would have been the perfect choice.
Scalability
We hosted our MongoDB database on Atlas, a cloud hosted database management platform that removes the need for managing the underlying server infrastructure and software, allowing us to focus on the development of the application.
MongoDB Atlas offers a number of tiers which run on either dedicated hardware or a shared virtualised instance, with a wide selection of processing power, memory and storage limits.
For this assignment we are using the free tier that is a shared M0 AWS virtual server with 512MB of storage which could be easily moved to a higher tier of server to cope for a much higher load.
MongoDB stores the database as a group of shared clusters and allows for scaling by automatically increasing the number of clusters to manage increased load, or reducing the number of clusters to save resources when requests are reduced. The clusters allow for parallel processing of data requests and can be configured to replicate all data for redundancy.
Sequence Diagram
Representing the interactions between objects over time.
Logging In
The interactions between objects that occur over time in order for a user to login.
Registration
The interactions between objects that occur over time in order for a new user to create an account.
Use Case Diagram
This use case diagram captures what the system will do.
Activity Diagrams
Representing the workflow of the system.
Group Creation
Activity Diagram showing the workflow for a user to create a group.
Group Invitation
Activity Diagram showing the workflow for a user to be invited to a group.
Channel Creation
Activity Diagram showing the workflow for a user creating a channel
Channel Invitation
Activity Diagram showing the workflow for a user to be invited to a channel.
Functionalities / Features
The following functions and features are included in the final release of the YaMa chat app.
- Create a new account
- Secure log in/out
- Create a new chat group
- Invite a new member to chat group
- Join groups via invitation
- Ability to leave groups
- Swap between channels
- Send chat messages in a group chat
- Create new subchannels in a chat group
- Visible history of chat messages from a chat group
- Upload voice recordings
- Send/receive private message to other members
- Encryption of all message data
- Group admin can create different channels for the group
- Group admin can limit the access of group members to each channel
- Users can add each other as friends and chat directly with each other, one on one
- A dashboard where users can view and edit their profile and avatar
- Admins can kick members from groups
- Group admin can assign different user permissions
- Change avatar of account
- Display usernames and avatars alongside chat
- Dark / Light mode
Non-Functional Specifications
1. Performance Constraints
Lambda Spin Up Delay
Using AWS Lambda functions gives us the ability to scale and easily deploy to alternate server locations for redundancy and lower latency for clients around the world. As Lambda functions do not persist and only spin up instances when demand requires it, we can take advantage of cost savings due to billed usage being tied to the execution time of the Lambda. However, this has a performance constraint that should be noted.
When a request is made to a Lamda function that is not already active due to a previous call, the instance of the Lambda must spin up to a workable state in order to start processing the request. This results in a small perceptible delay in request response time every time a new Lambda is spun up.
Message Refresh Timing
Initially it was planned to set up the connection to the backend for message retrieval as a persistent Web Socket link. Initial testing unearthed an issue with the AWS gateway continually dropping the connection when the Lambda terminated, and we were unable to rectify the problem in the timeframe provided. Ultimately, periodically polling the REST gateway for new messages proved to be an acceptable solution.
The current poll rate for new messages is every 5 seconds.
Free-Tier Services
As this is an assignment and not a commercial exercise, we have used the free-tier of all the services we have used. Naturally, this gives an allocation of a low level of virtualised hardware longer that results in longer latency, lower bandwidth, and a reduced capacity to handle load.
The AWS Lambda free tier is limited to one million requests per month, and has a lower priority when requesting access to compute resources. This means that we are limited by the load that the Lambda functions can handle, and their responsiveness is often less than that provided within the paid tiers.
The MongoDB Atlas free tier we configured is limited to shared virtual server running on AWS that uses a shared CPU and memory, and allows for just 512MB of storage. This limits our capacity, and increases response times, especially under periods of higher load.
The Vercel free tier has both constraints on development resources as well as reduced bandwidth. During development we were restricted to only one member of the team having direct access to Vercel, as team members are not permitted on the hobby plan, while builds are slowed and cannot occur concurrently. Pro plans also offer a bandwidth of 1TB, as opposed to 100GB for the hobby plan.
2. Operating Constraints
Member Constraints
As is often the case, the time commitment that each member was able to devote to the project differed greatly, as did the level of knowledge and each member could provide. These constraints meant that there was often only one or two members of the team that could be allocated to certain tasks, reducing the progression of the project.
Accessibility Constraints
The free tier systems we used to develop the project created several issues during development, and would be a further issue during the ongoing maintenance and operation of the application.
Each of the services we used are limited to a low-priority email-only support level. This created a major issue when Vercel suddenly stopped validating our connection for automated builds, resulting in the application not being built and deployed for an extended period. Support was sadly lacking and resulted in a lot of frustration and waisted time. In a commercial setting, this would be unacceptable. Additionally, Vercel does not allow team members to be assigned to a project when using the hobby plan. This meant that there was only one person that could deal with the issue.
3. Interface Constraints
One of the major issues when building an application for the browser is that you must take into account that it will be used in many different operating environments. More real-world testing should have been carried out using a wide variety of devices, operating systems, browsers, and form factors.
While the interface is functional, and does meet the majority of needs, it would greatly benefit from further design improvements. An example of this is that the "audio" element is rendered very differently in different browsers resulting in an inconsistent interface being presented to the user.
Another issue that this caused was with the Safari browser in particular. The RecordRTC library was chosen to record audio as we were having issues with cross-browser functionality using in-build JavaScript functions. This resulting in audio recording working in Chrome and in Firefox, but we could not get it working on Safari running in iOS. Eventually it was discovered that the latest build of Safari broke audio support in the library, however it was too late in the project to devise a solution.
Automatic scrolling was implemented in the application to ensure that the screen scrolled up when the latest messages arrived to make sure the user sees them as they arrive. Unfortunately, this proved to be inconsistent across browsers, and was unresolved at the time of writing. This results in the scroll function not going all the way to the latest messages in the message display area.
Finally, the other major issue with the interface is there is no indication when a new message is received in another channel. We added an audio alert to sound when a new message comes in for the channel the user is actively viewing, but there is no notification of a new message being available in any other channel.
4. Economic Constraints
While the application has been built using free resources, this would not be feasible for a commercial release. Each of the services we used would require migration to a paid tier.
Migrating to the Pro tier of Vercel would allow project access for up to 10 members and offer higher bandwidth for $20/month for each member.
MongoDB Atlas has a number of tiers that could be progressively moved through as demand for resources increased, starting at the M2 plan for $9/month that would give us 2GB of storage on a shared instance.
The AWS free tier we are using is time-limited to 12 Months. After the free period expires, Amazon charges based on the amount of resources used each month and is a much harder cost to calculate. Costs would be incurred based on the number of requests processed by the gateway (https://aws.amazon.com/api-gateway/pricing/) plus the amount of resources consumed be the Lambda functions (https://aws.amazon.com/lambda/pricing/). In addition, there are likely to be additional costs in setting up additional services required for a commercial deployment such as domain and routing costs if a custom domain was required.
5. Design Constraints
While the code should be easily maintainable and extendable by anyone in the team, and the frontend of the application can be deployed virtually anywhere, there is a major design constraint that is a biproduct of utilising a serverless backend.
As the backend functions are written specifically to take advantage of AWS Lambda functions, migrating the backend to a different provider would be a difficult undertaking. Every lambda function would have to be partially rewritten to run on a different system even if the system still utilised NodeJS. This vendor lock-in is an unfortunate side-effect of cloud services.
Even more intrinsic to the design of the application is the MongoDB database used. While migrating the data set to a different MongoDB server such as moving to a self-hosed build would be trivial, migrating the service to a different database system would be a massive undertaking. Every interaction with the database is coded as MongoDB function calls, and would require the backend Layer functions be entirely rewritten.
YaMa User Stories
User Login / Register
User Story
As a user, I want to have the ability a register my details in the application so that I can login to the application.
Acceptance Criteria
Given a user provides registration details,
When they click the create account button,
Then they will have an account created and can login to the application.
User Profile
User Story
As a user, I want access to a dashboard so that I can edit my profile and avatar.
Acceptance Criteria
Given a user accesses the account management dashboard,
When they click 'edit' button,
Then they can input new profile details and update their avatar.
Groups
User Story
As a user, I want the ability to make groups so that I can invite other users to engage in group conversations.
Acceptance Criteria
Given a user inputs a group name, public status and other details,
When they click the "create group" button,
Then the group is created and they can access it as an Admin and invite other users or otherwise manage the group.
Search Users
User Story
As a user, I want to add other users as friends so that I chat directly with them one on one.
Acceptance Criteria
Given that the user enters the username of the friend they would like to add
When the user clicks the "add friend" button
Then the friend should be added to the user's friend list.
Channels
User Story
As a group admin, I want to be able to create different channels for the group so that conversations can be categorized and group members can be limited for each channel.
Acceptance Criteria
Given a group Admin,
When they click the 'create channel' button,
Then a new channel will be created and users can be managed separately for that channel.
Communication
User Story
As a user, I want to be able to send a text or record and send a voice message so that I can communicate with other users.
Acceptance Criteria
Given the user enters some text or records a voice message
When the user clicks the "send" button
Then the recipient should receive the text or voice message.
Server
User Story
As a developer, I want to have a robust server system that scales so that it can handle the traffic of a growing number of users.
Acceptance Criteria
Given multiple users are in a channel
When a user clicks the "send" button to send a message
Then the server should redirect the message to all recipients in the channel
Project Management
User Story
As a team member, I want to have a system for documentation so that I can easily access all the administrative tasks required for the Group’s assessment.
Acceptance Criteria
Given documents need to be produced
When a team member needs to create or update their administrative tasks
Then the information related to that administrative task will be accessible to all team members.
Frontend UI/UX
User Story
As a developer, I want to have a UI/UX area so that the application will be able to meet all of our design criteria.
Acceptance Criteria
Given a developer is designing the application
When a developer makes a UI/UX design choice
Then the application UI/UX will reflect that choice.
Test Documentation
This section contains the following information.
Non-technical Documentation
Playwright Test Script
Individual scripts have been written to test various parts of the system.
Tests
import './register.spec.ts';
import './login.spec.ts';
import './chat.spec.ts';
Common
// my-test.ts
import { test as base } from '@playwright/test';
export type TestOptions = {
uid: number;
name: string;
password: string;
};
let uid_ = Date.now()
export const test = base.extend<TestOptions>({
// Define an option and provide a default value.
// We can later override it in the config.
uid: [uid_, { option: true }],
name: [uid_ + 'test-user', { option: true }],
password: ['Test-Password-1', { option: true}]
});
Chat Test
import { test } from './common';
import { expect, Locator, Page } from '@playwright/test';
test.describe('Test Chat Page', () => {
test.beforeEach(async ({ page, name, password }) => {
await page.goto('/#/');
await page.locator('input.mdc-text-field__input >> nth=0').fill(name);
await page.locator('input.mdc-text-field__input >> nth=1').fill(password);
await page.locator('button.mdc-button:has-text("Login")').click()
});
test('Browse to Add Group Page', async ({ page }) => {
// click add button
await page.locator('#add-group').click()
// check on add group page
// TODO: found Add a Group cancel instead of Add a Group
await expect(page.locator('h2 >> nth=1')).toHaveText(/Add a Group.*/)
})
test('Add Group', async ({ page, isMobile, uid }) => {
test.skip(isMobile, "Add group feature not yet implemented for mobile")
// click add button
await page.locator('#add-group').click()
// check on add group page
await expect(page.locator('h2 >> nth=1')).toHaveText(/Add a Group.*/)
// TODO: should this switch be tested?
// await page.locator('button.mdc-switch >> nth=0');
if (isMobile) {
// TODO: implement this when complete - use #mobile-chat
} else {
// enter group name (unique)
await page.locator('#chat-panel input.mdc-text-field__input >> nth=0').fill(`${uid}-test-group`);
await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=0')).toHaveValue(`${uid}-test-group`);
// click create button
await page.locator('#chat-panel button.mdc-button:has-text("Create")').click()
}
// check on chat page
await expect(page.locator('h2 >> nth=1')).toHaveText('YaMa Chat')
})
test('Browse to Group Page', async ({ page, isMobile, uid }) => {
test.skip(isMobile, "Browse to Group page not yet implemented for mobile")
await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()
// check on group page
await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)
})
test('Browse to Group Settings Page', async ({ page, isMobile, uid }) => {
test.skip(isMobile, "Browse to Group Settings page not yet implemented for mobile")
await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()
// check on group page
await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)
// click settings button
await page.locator(`button:has-text("settings")`).click()
// check on settings page
await expect(page.locator('h2 >> nth=1')).toContainText(new RegExp(`Group Settings: .* ${uid}-test-group`))
})
test('Add new channel', async ({ page, isMobile, uid }) => {
test.skip(isMobile, "Browse to Group Settings page not yet implemented for mobile")
await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()
// check on group page
await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)
// click settings button
await page.locator(`button:has-text("settings")`).click()
// check on settings page
await expect(page.locator('h2 >> nth=1')).toContainText(new RegExp(`Group Settings: .* ${uid}-test-group`))
// click the button
await page.locator(`#chat-panel button:has-text("CREATE NEW CHANNEL")`).click()
await page.locator('#chat-panel input.mdc-text-field__input >> nth=0').fill("NEWCHANNEL");
await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=0')).toHaveValue("NEWCHANNEL");
// click create button
await page.locator(`#chat-panel button.mdc-button:has-text("CREATE")`).click()
})
test('Invite new member', async ({ page, isMobile, uid }) => {
test.skip(isMobile, "Browse to Group Settings page not yet implemented for mobile")
await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()
// check on group page
await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)
// click settings button
await page.locator(`button:has-text("settings")`).click()
// check on settings page
await expect(page.locator('h2 >> nth=1')).toContainText(new RegExp(`Group Settings: .* ${uid}-test-group`))
// click the button
await page.locator(`#chat-panel button:has-text("INVITE NEW MEMBERS")`).click()
// email
await page.locator('#chat-panel input.mdc-text-field__input >> nth=0').fill("test2@test.com");
await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=0')).toHaveValue("test2@test.com");
// name
await page.locator('#chat-panel input.mdc-text-field__input >> nth=1').fill("Test Name");
await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=1')).toHaveValue("Test Name");
// msg
await page.locator('#chat-panel input.mdc-text-field__input >> nth=2').fill("message");
await expect(page.locator('#chat-panel input.mdc-text-field__input >> nth=2')).toHaveValue("message");
// click the button
await page.locator(`#chat-panel button:has-text("INVITE NEW MEMBER")`).click()
await expect(page.locator('#chat-screen')).toHaveText(' Select a group and a channel to start chatting');
})
test('Delete group', async ({ page, isMobile, uid }) => {
test.skip(isMobile, "Browse to Group Settings page not yet implemented for mobile")
await page.locator(`//div[contains(@class, "${uid}-test-group")]`).click()
// check on group page
await expect(page.locator('h2 >> nth=1')).toContainText(`${uid}-test-group`)
// click settings button
await page.locator(`button:has-text("settings")`).click()
// check on settings page
await expect(page.locator('h2 >> nth=1')).toContainText(new RegExp(`Group Settings: .* ${uid}-test-group`))
// click the button
await page.locator(`#chat-panel button:has-text("DELETE GROUP")`).click()
await expect(page.locator('h3 >> nth=1')).toHaveText(/Delete Group Confirmation/)
// click the button
await page.locator(`#chat-panel button:has-text("DELETE GROUP")`).click()
await expect(page.locator('#chat-screen')).toHaveText(' Select a group and a channel to start chatting');
})
test.afterEach(async ({ page }) => {
await page.goto('/#/');
await page.locator('button:has-text("Logout")').click();
});
})
Login Test
import { test } from './common';
import { expect, Locator, Page } from '@playwright/test';
test.describe('Test Login Page', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/#/');
});
test('Browse to Login Page', async ({ page }) => {
// check on login page
await expect(page.locator('button.mdc-button')).toHaveText("Login")
})
test('Use Login Form - Success', async ({ page, name, password }) => {
// enter username
await page.locator('input.mdc-text-field__input >> nth=0').fill(name);
await expect(page.locator('input.mdc-text-field__input >> nth=0')).toHaveValue(name);
// enter password
await page.locator('input.mdc-text-field__input >> nth=1').fill(password);
await expect(page.locator('input.mdc-text-field__input >> nth=1')).toHaveValue(password);
// click login button
await page.locator('button.mdc-button').click()
// check on chat page
await expect(page.locator('h2 >> nth=1')).toContainText('YaMa Chat')
})
test('Use Login Form - Invalid Data', async ({ page, name, password }) => {
// enter username
await page.locator('input.mdc-text-field__input >> nth=0').fill(name + "wrong");
await expect(page.locator('input.mdc-text-field__input >> nth=0')).toHaveValue(name + "wrong");
// enter password
await page.locator('input.mdc-text-field__input >> nth=1').fill(password);
await expect(page.locator('input.mdc-text-field__input >> nth=1')).toHaveValue(password);
// click login button
await Promise.all([
page.locator('button.mdc-button').click(),
page.waitForResponse(response => response.status() === 401),
])
})
test('Browse to Register Form', async ({ page }) => {
// click register link
await page.locator('a:has-text("Create Account")').click()
// check on register page
await expect(page.locator('h1 >> nth=1')).toHaveText('Create Account')
})
})
Registration Test
import { test } from './common';
import { expect, Locator, Page } from '@playwright/test';
test.describe('Test Register Page', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/#/register/');
});
test('Use Register Form - Success', async ({ page, name, password }) => {
// enter name
await page.locator('input.mdc-text-field__input >> nth=0').fill(name);
await expect(page.locator('input.mdc-text-field__input >> nth=0')).toHaveValue(name);
// enter date of birth
await page.locator('input.mdc-text-field__input >> nth=1').fill('1970-01-01');
await expect(page.locator('input.mdc-text-field__input >> nth=1')).toHaveValue('1970-01-01');
// enter phone number
await page.locator('input.mdc-text-field__input >> nth=2').fill('12345');
await expect(page.locator('input.mdc-text-field__input >> nth=2')).toHaveValue('12345');
// enter email address (unique)
await page.locator('input.mdc-text-field__input >> nth=3').fill(name + '@test.com');
await expect(page.locator('input.mdc-text-field__input >> nth=3')).toHaveValue(name + '@test.com');
// enter username (unique)
await page.locator('input.mdc-text-field__input >> nth=4').fill(name);
await expect(page.locator('input.mdc-text-field__input >> nth=4')).toHaveValue(name);
// enter password
await page.locator('input.mdc-text-field__input >> nth=5').fill(password);
await expect(page.locator('input.mdc-text-field__input >> nth=5')).toHaveValue(password);
// confirm password
await page.locator('input.mdc-text-field__input >> nth=6').fill(password);
await expect(page.locator('input.mdc-text-field__input >> nth=6')).toHaveValue(password);
// click register button
await Promise.all([
page.locator('button.mdc-button').click(),
page.waitForResponse(response => response.status() === 200),
])
// need a way to check if the registration is done, until then
await page.evaluate(() => {
return new Promise((resolve) => setTimeout(resolve, 5000));
})
// check on email verification page
await expect(page.locator('h1 >> nth=2')).toHaveText('Email Verification')
})
test('Use Register Form - Invalid Data', async ({ page, name }) => {
// get unique identifier
const uid = Date.now();
// enter name
await page.locator('input.mdc-text-field__input >> nth=0').fill(name);
await expect(page.locator('input.mdc-text-field__input >> nth=0')).toHaveValue(name);
// enter invalid date of birth
await page.locator('input.mdc-text-field__input >> nth=1').fill('2070-01-01');
await expect(page.locator('input.mdc-text-field__input >> nth=1')).toHaveValue('2070-01-01');
// enter phone number
await page.locator('input.mdc-text-field__input >> nth=2').fill('12345');
await expect(page.locator('input.mdc-text-field__input >> nth=2')).toHaveValue('12345');
// enter invalid email address (unique)
await page.locator('input.mdc-text-field__input >> nth=3').fill(name);
await expect(page.locator('input.mdc-text-field__input >> nth=3')).toHaveValue(name);
// enter username (unique)
await page.locator('input.mdc-text-field__input >> nth=4').fill(name + '@test-user.com');
await expect(page.locator('input.mdc-text-field__input >> nth=4')).toHaveValue(name + '@test-user.com');
// enter invalid password
await page.locator('input.mdc-text-field__input >> nth=5').fill('password1');
await expect(page.locator('input.mdc-text-field__input >> nth=5')).toHaveValue('password1');
// confirm invalid password
await page.locator('input.mdc-text-field__input >> nth=6').fill('password2');
await expect(page.locator('input.mdc-text-field__input >> nth=6')).toHaveValue("password2");
// check error messages
await expect(page.locator('div#dob-error.input_error.invalid')).toHaveText('Invalid date of birth.');
await expect(page.locator('div#email-error.input_error.invalid')).toHaveText('Please enter a valid email address.');
await expect(page.locator('div#username-error.input_error.invalid')).toHaveText('Usernames must have at least 3 characters and contain no spaces or the \'@\' symbol.');
await expect(page.locator('div#password-error.input_error.invalid')).toHaveText('Passwords must have at least 8 characters. Please use lower-case and upper-case characters, numbers, and special characters.');
// click register button
await page.locator('button.mdc-button').click()
await page.waitForLoadState('load');
// check on register page
await expect(page.locator('h1 >> nth=1')).toHaveText('Create Account')
// check error messages
await expect(page.locator('div#confirmation-error.input_error.invalid')).toHaveText('The entered passwords do not match.');
})
})
Data Management Information
Database
YaMa is using MongoDB Version 5.0.8.
Connection information
Primary Cluster
- mongocluster0-shard-00-01.3ch0w.mongodb.net:27017
Connecting using a NodeJS server
- mongodb+srv://
: @mongocluster0.3ch0w.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
Connecting using Compass
- mongodb+srv://
: @mongocluster0.3ch0w.mongodb.net/test
Connecting using Mongo Shell
- mongosh "mongodb+srv://mongocluster0.3ch0w.mongodb.net/myFirstDatabase" --apiVersion 1 --username
Implementation Instructions
MongoDB
The MongoDB database can be accessed via the browser interface at Atlas, by using the Compass application, maintained by using the Database Tools CLI, or accessed via the MongoDB Shell.
Atlas
Atlas can be accessed using the URL: https://cloud.mongodb.com/user.
Only members of “RMIT” will have access to the “YaMa” project within Atlas.
The database is deployed to MongoCluster0
and is hosted on a shared virtual instance running on AWS.
To modify or query the “yama” database, click on the “Browse Collections” button and select the “yama” database.
The “yama” database has just three functional collections (or tables in SQL terminology):
- user: Hold the user data.
- group: Holds data on groups created by the registered users.
- channel: Holds data on channels created in a group, as well as the chat messages that have been sent in that channel.
Clicking on the desired collection allows queries to be run on the data, with results displayed below the query box.
MongoDB has a very thorough online manual.
Database Tools CLI
Database dumps for migration and backup can be done using the Database Tools CLI that is available for Linux, MacOS, and Windows systems.
The CLI can be downloaded from here.
The mongodump
command can be used to backup or extract the database in the binary JSON format used by mongoDB. This could be used to move the database to another MongoDB account, or migrating to a self hosted server, or just to backup the data.
The command to dump the Yama database is:
mongodump --uri mongodb+srv://rmit:<password>@mongocluster0.3ch0w.mongodb.net/yama
Where <password>
is the database password, not your user password.
The database could then be restored from this backup using the command:
mongorestore --uri mongodb+srv://rmit:<password>@mongocluster0.3ch0w.mongodb.net
The database dump to be restored is read from the dump/ sub-directory of the current directory; to restore from a different directory, pass in the path to the directory as a final argument.
If migration to a different database solution is required, the mongoexport
command can export the data in CSV or JSON format.
The command to export the database is:
mongoexport --uri mongodb+srv://rmit:<password>@mongocluster0.3ch0w.mongodb.net/yama --collection <collection> --type <filetype> --out <filename>
Where <password>
is the database password, not your user password, <collection>
is the name of the collection you want to export (the table name), the <filetype>
can be "json" or "csv", and <filename>
is the name of the file it will be exported to.
Further information on additional commands that may be of use can be found here.
MongoDB Shell
The Yama MongoDB Atlas database can also be accessed and manipulated via a command-line shell interface called mongosh
.
The shell application is available for Windows, MacOS, and Linux. You can download the shell from here: https://www.mongodb.com/docs/atlas/mongo-shell-connection/
The command to connect to the Yama database and run commands in the shell is:
mongosh "mongodb+srv://mongocluster0.3ch0w.mongodb.net/yama" --apiVersion 1 --username rmit
You will be prompted for the database password.
For a guide on how to use mongosh
, consult the online manual: https://docs.mongodb.com/mongodb-shell/
Compass
MongoDB Compass is a desktop application that can be used to run queries and manage the Yama MongoDB Atlas database. It is available for Linux, MacOS and Windows. You can download the application from: https://www.mongodb.com/products/compass
When you run Compass, you will be prompted to enter a connection string to connect to Atlas. The connection string required is:
mongodb+srv://rmit:<password>@mongocluster0.3ch0w.mongodb.net/yama
Where <password>
is the database password, not your user password.
Compass offers a very similar experience to the online interface of Atlas and further information on using Atlas can be found in the online documentation: https://www.mongodb.com/docs/compass/current/
Project Mockups - Figma Designs
Wireframes
Friends
Friend request
Sign in
Register
High Fidelity - Light
Sign in light mode
Register light mode
Main screen light mode
Settings screen light mode
High Fidelity - Dark
Sign in dark mode
Register dark mode
Main screen dark mode
About screen dark mode
Settings screen dark mode
Groups screen dark mode
UI Performance Report
PageSpeed insights generated reports
Summary of the desktop Yama PageSpeed Insights Report.
The full desktop Yama PageSpeed Insights Report can be seen here.
Summary of the mobile Yama PageSpeed Insights Report.
The full mobile Yama PageSpeed Insights Report can be seen here.
OWASP Security Threads/Vulnerabilities Report
OWASP Security Threads/Vulnerabilities Report. Refer to the latest OWASP guidelines or the 2017 full doc.
The following report details the OWASP top 10 list for the most common web application security risks in 2021. The report will go into what the security is, the consequences of the security risk and the effect the security risk has on our application including measures taken to prevent or mitigate the security risk.
1. Broken Access Control
Broken Access Control refers to a vulnerability whereby a user can access or perform an action outside of their intended permission. As a result, this vulnerability can lead to unauthorized disclosure of information and a user performing an unauthorized action such as modifying or deleting data.
To mitigate this security risk the following preventative measures have been implemented:
- All functions that require authentication are denied by default. The JWT token must be authenticated for these functions to proceed.
- For the assignment we used MongoDB accessed via Atlas over the Internet. This was done as learning opportunity and was authorised by the supervisor (Reza) at the very beginning of the project. If this were a real commercial product, we would have utilised Amazon’s DynamoDB commercial service which can communicate with Lambda functions via a Virtual Private Cloud (VPC). This routes calls to the database over Amazon’s internal network infrastructure rather than passing the calls over the public Internet.
- Each back-end REST end-point handles a single function after authentication. This limits the scope of each function to its intended specific purpose and helps to prevent any leakage of information via an API call.
- All the back-end gateways end-points on Amazon are protected with SSL encryption.
- Parameters for the Lambda functions are held as environmental variables in AWS, while the database credentials are held in the Lambda Layer that is deployed to AWS. Credentials could be further protected using Amazon Secrets, a commercial product that acts as an encrypted store for holding sensitive information.
- The front-end files are deployed to a secure container running on Vercel. All access is via SSL encrypted links and Vercel also encrypts all secrets at rest and in transit while offering extended services such as DDOS protection when using the professional plans. (https://vercel.com/security)
- Rate limiting is set in the AWS API gateway. The current default setting is 10000 request per second with a burst of 5000 for the production gateway, but this could be limited according to the load generated in a commercial environment.
- Local data is deleted when the user logs out and a new JWT token needs to be generated at login. The lifetime of the JWT token is currently set as 7 days, but could easily be set to any value that achieves an acceptable balance between usability and security.
- Each user must validate their email address by clicking on link that is emailed to their supplied email address. Users are set to inactive by default when registering and cannot login without successful email validation.
2. Cryptographic Failures
Cryptographic Failures is a vulnerability where the cryptography used by an application fails to securely encrypt and protect sensitive data. A cryptographic failure can occur when data is stored or transmitted in plain text or a weak encryption is used to protect the data. As a result, this can lead to the exposure of sensitive data such as passwords, credit card numbers, and personal information.
To mitigate this security risk the following preventative measures have been implemented:
- The application now has end-to-end encryption where all messages are stored in the database in encrypted form. The key to decrypt the message must be decrypted by each channel member’s private key in order to reveal the message.
- Messages are transmitted in encrypted form, and decrypted on the client using the client’s password which is only stored in hashed format on the server. The server cannot decrypt the messages.
- Keys used to decrypt the messages are stored on the local device only and deleted when the user logs out. The keys are regenerated after successful login.
- Both the back-end API and the front-end are transferred in a HTTPS tunnel as managed by Amazon and Vercel.
- The JWT token uses a 64-byte hex string as a secret.
- Passwords are SHA512 hashed with a 16 byte salt using 2048 iterations.
- YaMa’s End-To-End encryption is based on AES-256 Encryption. AES is an Industry standard and is adopted by institutions that have an inherent interest in protecting encrypted data such as the US Government and European Union.
- AES-256 is currently virtually impenetrable using brute-force methods on current computer hardware.
- YaMa’s encryption library is subtle crypto which is based on the Web Cryptography API. The Web Cryptography API is the current encryption standard for most modern browsers and all major modern browsers provide supports and are contributors to the open source project.
3. Injection
Injection refers to a vulnerability whereby an attacker supplies untrusted user input data which is then executed by the application as part of a command or query. Some of the most common types of injection attacks include SQL injections, cross-site scripting (XSS) and code injection. As a result, this vulnerability can lead to unauthorized disclosure of data, destruction of data, loss of data integrity and denial of service.
To mitigate this security risk the following preventative measures have been implemented:
- User credential input is validated on the front-end and the back-end before being stored in MongoDB.
- Svelte (the front-end framework we are using), treats all strings as plain-text by default and does not parse any code entered within a message.
- As MongoDB is a No-SQL database, any form of SQL-Injection attack is completely mitigated.
4. Insecure Design
Insecure Design refers to a vulnerability associated with the design or architecture of an application. Insecure design should not be confused with an insecure implementation. A vulnerability found in an insecure design cannot be rectified by a perfect implementation.
To mitigate this security risk the following preventative measures have been implemented:
- The cryptographic functions used in the application utilise well supported and secure libraries. We used the “crypto” and “jsonwebtoken” NodeJS libraries for hashing and authentication token management respectively, and the standard “crypto” browser library to implement end-to-end encryption.
- The entire application was developed with robust validation and authentication from the very beginning.
- The user that creates a group or channel is set as the administrator. Only administrators can modify the parameters of the group or channel including kicking or inviting additional users. This is validated in the front-end and re-validated in the MongoDB functions executed in the back-end.
5. Security Misconfiguration
Security Misconfiguration is a vulnerability where the security components within an application are left insecure or misconfigured. A security misconfiguration has the potential to allow an attacker to gain unauthorized access to the application’s data and functionality which can lead to the whole application system being compromised.
To mitigate this security risk the following preventative measures have been implemented:
- The development environment can easily be replicated with each user having to set their access credentials in order to deploy.
- The CI/CD pipeline we used centres around pushing code to GitHub which triggers front-end deployment to Vercel, while the back-end is tested and deploying to AWS using SAM. Pushing to GitHub, and deployment to AWS requires individual developer authentication.
- The repository that has been used in GitHub is private and accessible by authorised members of the team only.
- The secrets required for automated deployment to Vercel via a GitHub action are held as encrypted secrets in GitHub.
- Access to the Amazon backend and automated deployment via SAM is restricted to users that have a registered access key Id and a valid secret access token. Access can also be secured by multi-factor authentication.
- User rights in AWS have been restricted to only the services used by the application using Amazon Identity and Access Management (IAM).
- MongoDB Atlas access is restricted to authorised members of the team.
- Access to upload to S3 buckets (where the audio is stored) uses a unique pre-authorised link with a time-limited authentication token that is generated at time of recording. Once the token expires (set to 1 minute), the link can no longer be used to upload data.
- Only required frameworks have been included in the code.
6. Vulnerable and Outdated Components
Vulnerable and Outdated Components refers to a vulnerability whereby a component used by the application is either out of date, no longer supported or vulnerable to a known exploit. This vulnerability can lead to attacks that target both client and server-side components. As a result, an application would become more susceptible to attacks if it is using components that are out of date with a known flaw or vulnerability.
To mitigate this security risk the following preventative measures have been implemented:
- The GitHub repository we used has been set to enable Dependabot scanning. The code is automatically scanned for vulnerabilities periodically, with alerts being sent to team members if an issue is found, and a Pull Request automatically created if a solution is known.
- On top of this, we also use Snyk (https://snyk.io/) that we use to scan the code for vulnerabilities. Snyk has the convenience of both a web interface, and a Visual Code plugin to examine issues found in the code-base.
- We ensured that for all End-to-End encryption components, we used the most secure and modern methods possible to ensure that the End-to-End encryption lasts the longest possible time before modern computing components and methods catch up.
7. Identification and Authentication Failures
Identification and Authentication Failures refers to a vulnerability whereby the application’s functions relating to confirming a user identity, authentication, and session management is not properly protected or correctly implemented. As a result, this can lead to automated attacks such as credential stuffing or a brute force attack in order for an attacker to assume another users’ identity.
To mitigate this security risk the following preventative measures have been implemented:
- We have not implemented MFA for this project, however, all user passwords require a minimum of 8 characters, and requires the use of lower and upper case letters, numbers, and special characters.
- User emails are also verified before they can login.
- There are no default passwords or credentials used.
- Password recovery sends a link to the validated email address recorded in the database with a time-limited token. To change the password, the user must click this link to set a new password.
- Authentication tokens are generated every time the user logs into the application, and are currently valid for 7 days but can be limited to any length desired.
8. Software and Data Integrity Failures
Software and Data Integrity Failures refers to a vulnerability associated with using code or infrastructure without verifying its integrity. This vulnerability can occur when an application uses software from an untrusted source or software that has been manipulated at the source and is subsequently downloaded without checking for code integrity.
To mitigate this security risk the following preventative measures have been implemented:
- A limited set of trusted libraries have been used for the application.
- The use of Svelte to generate a reactive front-end means that the code is compiled to vanilla JavaScript before deployment.
- Both GitHub Dependabot and Snyk are employed to scan the code and dependencies for vulnerabilities.
9. Security Logging and Monitoring Failures
Security Logging and Monitoring Failures is a vulnerability that focuses on the failure of an application system to properly monitor and maintain security logs. By not having an adequate logging system to log, monitor, or report suspicious activity such as failed login attempts the likelihood of a successful attack by an attacker increase.
To mitigate this security risk the following preventative measures have been implemented:
- AWS logs all Lambda activity in the back-end to a service called “CloudWatch”. This enables all activity and system utilisation to be monitored, with the ability to set actions that are triggered by events or other services within the AWS ecosystem.
- The logs are secured with authentication by AWS, and access can be restricted by user or user group.
- AWS can be easily configured for replication, redundancy and fault tolerance in a commercial situation for a price.
- Different gateway end-points can be utilised in different geographic locations, while the Lambda functions are scaled based on utilisation.
- MongoDB also utilises clusters and can have replication and backups in the professional-grade tiers.
- Vercel offers commercial plans that enable scalability and enhanced protection if required.
10. Server-Side Request Forgery
Server-Side Request Forgery refers to a vulnerability whereby an attacker abuses server functionality in order to read, access or modify internal resources. The attack forces the application to send a request to an unexpected destination which will often bypass any security controls in place and allow the attacker to access unintended resources.
To mitigate this security risk the following preventative measures have been implemented:
- Not hosting the application on our own infrastructure or virtualised system gives us the advantage of being able to leverage the resources provided by Amazon and Vercel to protect our application.
- One of the advantages in using AWS serverless Lambda functions is that you afforded the protections offered by a large scale provider without being responsible for maintaining the security of the underlying operating system or services software.
- All user data is sanitised where required on the front-end, and the back-end.
Issues Register
Risk Register
11 Appendix
Jira
Our Jira board that was used to manage the project can be found at the link.
User stories, including links to them on our Jira board, can be found in the User Stories section.
Links to Other Resources Used
Versions
What's Changed
- YC-191 Fixed bug with password validation. by @s3338610 in https://github.com/Programming-Project-1/yama/pull/2
- jae-to-testing by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/3
- YC-193 Added confirm password to registration form. by @s3338610 in https://github.com/Programming-Project-1/yama/pull/4
- Corrected issue preventing Vercel compiling SMUI CSS files. by @s3338610 in https://github.com/Programming-Project-1/yama/pull/5
- YC-200 Feature theme mode by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/6
- YC-199 Feature groups by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/7
- YC-165 Frontend Dev - Svelte Styled - Registration page by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/9
- YC-165 changed topbarapp icons back to material-icons, except theme switcher by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/10
- YC-197 test by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/11
- YC-188 /channel/create/ POST API end-point by @s3338610 in https://github.com/Programming-Project-1/yama/pull/8
- jae-to-testing by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/13
- YC-184 /GROUP/CREATE by @JPyke3 in https://github.com/Programming-Project-1/yama/pull/12
- Yc 189 /channel/invite/ api end point by @s3338610 in https://github.com/Programming-Project-1/yama/pull/14
- YC-169 Feature login registration by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/15
- YC-185 group/get/exists and channel/get/exists API end points by @s3338610 in https://github.com/Programming-Project-1/yama/pull/16
- Yc 186 /group/post/search/ api endpoint for searching for a group by @s3338610 in https://github.com/Programming-Project-1/yama/pull/17
- Merge pull request #16 from Programming-Project-1/YC-185-GROUP/GET/EX… by @JPyke3 in https://github.com/Programming-Project-1/yama/pull/20
- YC-197 by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/18
- Added DOB Validation by @JPyke3 in https://github.com/Programming-Project-1/yama/pull/21
- YC-187 aws api endpoint to invite a user to a group by @s3338610 in https://github.com/Programming-Project-1/yama/pull/19
- Allow users to create a new group by @s3338610 in https://github.com/Programming-Project-1/yama/pull/22
- YC-306 added navigation to Title in top bar. added width and height to logo … by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/23
- YC-311 Added iOS Support by @JPyke3 in https://github.com/Programming-Project-1/yama/pull/24
- YC-120 Create channels under a group by @s3338610 in https://github.com/Programming-Project-1/yama/pull/25
- YC-310 by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/26
- YC-304 non web socket chat functionality by @s3338610 in https://github.com/Programming-Project-1/yama/pull/28
- YC-126 End-to-End encryption by @JPyke3 in https://github.com/Programming-Project-1/yama/pull/27
- YC-313 script to automate vercel deployment by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/29
- YC-313 script to automate vercel deployment by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/30
- YC-320 fix infinite message fetch bug by @s3338610 in https://github.com/Programming-Project-1/yama/pull/31
- YC-319 stop registration endpoint saving all event data by @s3338610 in https://github.com/Programming-Project-1/yama/pull/32
- YC-318 Chat screen styling by @JPyke3 in https://github.com/Programming-Project-1/yama/pull/33
- Release Version: 0.7 by @s3338610 in https://github.com/Programming-Project-1/yama/pull/34
- added main to deployment scipt by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/36
- YC310 Playwright Tests by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/38
- YC-310 Playwright Tests by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/40
- Update yaml file for deployment by @JPyke3 in https://github.com/Programming-Project-1/yama/pull/41
New Contributors
- @s3338610 made their first contribution in https://github.com/Programming-Project-1/yama/pull/2
- @JaekyoungChang made their first contribution in https://github.com/Programming-Project-1/yama/pull/3
- @SRMITGit made their first contribution in https://github.com/Programming-Project-1/yama/pull/6
Full Changelog: https://github.com/Programming-Project-1/yama/commits/v0.7.1
What's Changed
- YC-322 Dicebear avatars by @JPyke3 in https://github.com/Programming-Project-1/yama/pull/35
- YC-171 invitation to join a group by @s3338610 in https://github.com/Programming-Project-1/yama/pull/43
- [Snyk] Upgrade mongodb from 4.4.1 to 4.5.0 by @s3338610 in https://github.com/Programming-Project-1/yama/pull/45
- YC-310 Playwright chat tests by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/42
- YC-388, YC-272, YC-335, YC-270 and YC-332 by @s3338610 in https://github.com/Programming-Project-1/yama/pull/49
- YC-325 change git hub readme for the project by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/51
- [Snyk] Upgrade ses from 0.15.11 to 0.15.12 by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/52
- [Snyk] Upgrade ses from 0.15.12 to 0.15.13 by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/53
- [Snyk] Upgrade ses from 0.15.12 to 0.15.14 by @s3338610 in https://github.com/Programming-Project-1/yama/pull/56
- [Snyk] Upgrade ses from 0.15.12 to 0.15.15 by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/58
- YC-121,YC-284,YC-283, YC-289 by @s3338610 in https://github.com/Programming-Project-1/yama/pull/57
- Added highlighting of selected channel by @s3338610 in https://github.com/Programming-Project-1/yama/pull/59
- YC-310 Playwright chat tests by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/65
- YC-274 allow user to leave a group by @s3338610 in https://github.com/Programming-Project-1/yama/pull/61
- YC-339 reset a forgotten password by @s3338610 in https://github.com/Programming-Project-1/yama/pull/62
- YC-341 message encryption by @s3338610 in https://github.com/Programming-Project-1/yama/pull/63
- YC-352 friends filter by @s3338610 in https://github.com/Programming-Project-1/yama/pull/64
- run tests in sequence on both CI and local by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/68
- YC-310 use new user for the tests by @JaekyoungChang in https://github.com/Programming-Project-1/yama/pull/72
- YC-300 save and load data from local storage by @s3338610 in https://github.com/Programming-Project-1/yama/pull/66
- YC-356 move userdata to a svelte store by @s3338610 in https://github.com/Programming-Project-1/yama/pull/67
- YC-355 create endpoints for the settings page by @s3338610 in https://github.com/Programming-Project-1/yama/pull/69
- Fix coding errors highlighted by snyk by @s3338610 in https://github.com/Programming-Project-1/yama/pull/70
- YC-358 fix tooltips on hover for group avatars by @s3338610 in https://github.com/Programming-Project-1/yama/pull/71
- YC-354 change garbage icons to x and onclick clear field by @s3338610 in https://github.com/Programming-Project-1/yama/pull/73
- YC-355 add api function to call /user/data patch endpoint by @s3338610 in https://github.com/Programming-Project-1/yama/pull/74
- Better styling for selected channel by @s3338610 in https://github.com/Programming-Project-1/yama/pull/75
- YC-362 fix issue with adding a user to a channel by @s3338610 in https://github.com/Programming-Project-1/yama/pull/76
- Return user pub key with channel information by @s3338610 in https://github.com/Programming-Project-1/yama/pull/77
- YC-296 add pwa functionality to the app evf by @SRMITGit in https://github.com/Programming-Project-1/yama/pull/79
- YC-365 fix audio start on enter in the chat message field by @s3338610 in https://github.com/Programming-Project-1/yama/pull/78
Full Changelog: https://github.com/Programming-Project-1/yama/compare/v0.7...v0.11.1
Releases from this point forward have been made on the forked branch due to GitHub Actions time limits being used up.
v0.12.1
Released on 22/05/2022
Auto generated release notes from GitHub
Pre-release.
What's Changed
- YC-279 record audio and save to aws s3 by @s3338610 in https://github.com/s3338610/yama/pull/2
- YC-363,YC-364 email verification and compare usernames case insensitive by @s3338610 in https://github.com/s3338610/yama/pull/3
- Fixed issue with registered users not able to login. by @s3338610 in https://github.com/s3338610/yama/pull/4
- fix logo hyperlink by @s3338610 in https://github.com/s3338610/yama/pull/5
- Removed user active check for group acceptance. Added html reminding … by @s3338610 in https://github.com/s3338610/yama/pull/7
- YC-340, YC-342, YC-346, YC-347 front end updates by @s3338610 in https://github.com/s3338610/yama/pull/6
- New release for week 12. by @s3338610 in https://github.com/s3338610/yama/pull/8
New Contributors
- @s3338610 made their first contribution in https://github.com/s3338610/yama/pull/2
Full Changelog: https://github.com/s3338610/yama/compare/v0.11.1...v0.12.1
What's Changed
- add more tests by @JaekyoungChang in https://github.com/s3338610/yama/pull/9
- YC-341 E2E debug by @s3338610 in https://github.com/s3338610/yama/pull/10
- YC-369 styling by @s3338610 in https://github.com/s3338610/yama/pull/11
- changed body font by @s3333925 in https://github.com/s3338610/yama/pull/12
- Move setting componet styling to the setting page by @s3338610 in https://github.com/s3338610/yama/pull/14
- Fixed app styling by @s3338610 in https://github.com/s3338610/yama/pull/16
- Fixed footer by @s3338610 in https://github.com/s3338610/yama/pull/17
- Reduced settings page width for smaller screens by @MurrayLowisRMIT in https://github.com/s3338610/yama/pull/18
- YC-409 bug fix friend selection on a mobile by @s3338610 in https://github.com/s3338610/yama/pull/13
- Made registration form fields all the same length and moved "confirm … by @s3338610 in https://github.com/s3338610/yama/pull/19
- Bug fix add and remove friend mobile view by @s3338610 in https://github.com/s3338610/yama/pull/20
- Push Testing code to Main repo by @s3338610 in https://github.com/s3338610/yama/pull/21
New Contributors
- @JaekyoungChang made their first contribution in https://github.com/s3338610/yama/pull/9
- @s3333925 made their first contribution in https://github.com/s3338610/yama/pull/12
- @MurrayLowisRMIT made their first contribution in https://github.com/s3338610/yama/pull/18
Full Changelog: https://github.com/s3338610/yama/compare/v0.12.1...v0.13.01
What's Changed
- Bug fixes and enhancements by @s3338610 in https://github.com/s3338610/yama/pull/22
- YC-370 snackbar alerts by @s3338610 in https://github.com/s3338610/yama/pull/24
- Removed STORE_userdata and STORE_token by @s3338610 in https://github.com/s3338610/yama/pull/25
- Test fork - updated readme by @SRMITGit in https://github.com/s3338610/yama/pull/26
- Minor front end updates by @s3333925 in https://github.com/s3338610/yama/pull/27
- YC-370 snackbar alerts by @s3338610 in https://github.com/s3338610/yama/pull/28
- Merge Testing into Main for release by @s3338610 in https://github.com/s3338610/yama/pull/29
New Contributors
- @SRMITGit made their first contribution in https://github.com/s3338610/yama/pull/26
Full Changelog: https://github.com/s3338610/yama/compare/v0.13.01...v0.13.02
What's Changed
- YC-292 spinner while waiting by @s3338610 in https://github.com/s3338610/yama/pull/30
- Testing to main for release by @s3338610 in https://github.com/s3338610/yama/pull/31
Full Changelog: https://github.com/s3338610/yama/compare/v0.13.02...v0.13.03
Final Release
Issues/Bugs
- Group search feature was not included due to MongoDB issues.
- User search feature was not included due to MongoDB issues.
- Web Sockets created a bug that was beyond the scope of this project to research and find a solution to.
- Safari browser is unable to use the sound recording feature of the app.
- Auto-scroll does not consistently scroll to the bottom of the chat page.
- Users can only log into one device at a time, but this is seen as a security feature.
- The browser needs to be refreshed or the user must logout to get new group information
What's Changed
- final enhancements by @s3338610 in https://github.com/s3338610/yama/pull/32
Full Changelog: https://github.com/s3338610/yama/compare/v0.13.03...v1.0
Contributors
Team Members and Assumed Role(s)
Jaekyoung Chang - Developer / Tester
Murray Lowis - Developer
Stephen Patrikios - Project Manager / Admin / Product Owner
Malcolm Tsang - UI/UX Designer
Jacob Pyke - Information Architect
David Ceccato - Developer
References
7Span n.d., Material Design Colors, Color Palette | Material UI, MaterialUI, viewed 5 May 2022, https://materialui.co/colors/.
Agilest LLC n.d., Agile Governance Made Easy - Maximize Value of Agile Process | Agilest, Agilest®, viewed 19 March 2022, https://www.agilest.org/agile-project-management/governance/.
Alie, SS 2015, ‘Project governance: #1 critical success factor.’, in PA: Project Management Institute., viewed 19 March 2022, https://www.pmi.org/learning/library/project-governance-critical-success-9945.
Amazon Web Services, Inc. 2022. AWS | Amazon Simple Email Service (SES) | Verification Successful. [online] Available at: https://aws.amazon.com/ses/verifysuccess/ [Accessed 18 May 2022].
Andrews, A n.d., Material Design Icons, materialdesignicons.com, viewed 5 May 2022, https://materialdesignicons.com/.
Avatars.dicebear.com. 2022. DiceBear Avatars. [online] Available at: https://avatars.dicebear.com/ [Accessed 11 May 2022].
AWS 2022. [online] Available at: https://docs.aws.amazon.com/AmazonS3/latest/userguide/enabling-cors-examples.html [Accessed 16 May 2022].
AWS 2022. [online] Available at: https://docs.aws.amazon.com/AmazonS3/latest/userguide/S3_Authentication2.html [Accessed 19 May 2022].
Base64, H., Converter, B. and Encode, B., 2022. Audio to Base64 | Base64 Encode | Base64 Converter | Base64. [online] Base64.guru. Available at: https://base64.guru/converter/encode/audio [Accessed 19 May 2022].
Bathman, J 2016, Markdown Table Maker, jakebathman.github.io, viewed 5 May 2022, https://jakebathman.github.io/Markdown-Table-Generator/.
Beedle, M, Bennekum, A van, Cockburn, A, Cunningham, W, Fowler, M, Highsmith, J, Hunt, A, Jeffries, R, Kern, J, Marick, B, Martin, RC, Schwaber, K, Sutherland, J & Thomas, D 2019, Principles behind the Agile Manifesto, Agilemanifesto.org, viewed 19 March 2022, http://agilemanifesto.org/principles.html.
Boucheron, B 2021, How To Install Node.js on Ubuntu 20.04 | DigitalOcean, www.digitalocean.com, viewed 13 May 2022, https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-20-04.
Caniuse.com. 2022. MediaRecorder API: mimeType | Can I use... Support tables for HTML5, CSS3, etc. [online] Available at: https://caniuse.com/mdn-api_mediarecorder_mimetype [Accessed 19 May 2022].
Chrome Developers. 2022. Record audio and video with MediaRecorder - Chrome Developers. [online] Available at: https://developer.chrome.com/blog/mediarecorder/ [Accessed 19 May 2022].
Cloud.mongodb.com. 2022. Cloud: MongoDB Cloud. [online] Available at: https://cloud.mongodb.com/v2/622157c379268a2e47fdbe75#clusters [Accessed 5 May 2022].
Code Utility. 2022. Upload a video file as blob to AWS S3 using JavaScript or Angular CLI - Code Utility. [online] Available at: https://codeutility.org/upload-a-video-file-as-blob-to-aws-s3-using-javascript-or-angular-cli-stack-overflow/ [Accessed 19 May 2022].
Codereview.chromium.org. 2022. Issue 1579693006: MediaRecorder: support sampling rate adaption in AudioTrackRecorder - Code Review. [online] Available at: https://codereview.chromium.org/1579693006 [Accessed 20 May 2022].
CSS-Tricks. 2022. max-lines | CSS-Tricks. [online] Available at: https://css-tricks.com/max-lines/#:~:text=none%20%3A%20No%20maximum%20number%20of,Only%20positive%20integers%20are%20accepted. [Accessed 25 May 2022].
Deconstruct. 2022. Recording Audio in the Browser Using the MediaStream Recorder API. [online] Available at: https://blog.addpipe.com/recording-audio-in-the-browser-using-pure-html5-and-minimal-javascript/ [Accessed 19 May 2022].
DEV Community. 2022. 🚀 Svelte Quick Tip: Connect a store to local storage. [online] Available at: https://dev.to/danawoodman/svelte-quick-tip-connect-a-store-to-local-storage-4idi [Accessed 17 May 2022].
Developer.mozilla.org. 2022. Blob.stream() - Web APIs | MDN. [online] Available at: https://developer.mozilla.org/en-US/docs/Web/API/Blob/stream [Accessed 18 May 2022].
Developer.mozilla.org. 2022. Crypto - Web APIs | MDN. [online] Available at: https://developer.mozilla.org/en-US/docs/Web/API/Crypto [Accessed 13 May 2022].
Developer.mozilla.org. 2022. Element.scrollTo() - Web APIs | MDN. [online] Available at: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTo [Accessed 16 May 2022].
Developer.mozilla.org. 2022. MediaRecorder: dataavailable event - Web APIs | MDN. [online] Available at: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/dataavailable_event [Accessed 19 May 2022].
Developer.mozilla.org. 2022. MediaRecorder.stop() - Web APIs | MDN. [online] Available at: https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/stop [Accessed 18 May 2022].
Developer.mozilla.org. 2022. Working with Svelte stores - Learn web development | MDN. [online] Available at: https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_stores [Accessed 26 May 2022].
Developer.mozilla.org. 2022. Working with Svelte stores - Learn web development | MDN. [online] Available at: https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_stores [Accessed 26 May 2022].
Evans, A 2021, Building a PWA with Svelte, LogRocket Blog, viewed 5 May 2022, https://blog.logrocket.com/building-a-pwa-with-svelte/.
Falk, I 2021, Handling Forms in Svelte, This Dot Labs, viewed 5 May 2022, https://www.thisdot.co/blog/handling-forms-in-svelte.
Fireship 2020, Progressive Web Apps in 100 Seconds // Build a PWA from Scratch, youtube.com, viewed 5 May 2022, https://www.youtube.com/watch?v=sFsRylCQblw.
Gardón, DS 2022, Svelte.js Guide: The Framework to Write Faster JavaScript, Snipcart, viewed 5 May 2022, https://snipcart.com/blog/svelte-js-framework-tutorial.
GitHub n.d., material-components-web, GitHub, viewed 5 May 2022, https://github.com/material-components/material-components-web/tree/v13.0.0/packages/mdc-layout-grid.
Google n.d., Material Design, Material Design, viewed 5 May 2022, https://material.io/develop/web/theming/theming-guide.
Grace, F 2021, How to Make Bulletproof Email Buttons (HTML, CSS, and VML), www.activecampaign.com viewed 5 May 2022, https://www.activecampaign.com/blog/email-buttons.
HackTheStuff 2019, What is manifest.json file and how it is useful, hackthestuff.com, viewed 5 May 2022, https://hackthestuff.com/article/what-is-manifest-json-file-and-how-it-is-useful.
Harris, R n.d., Svelte • Cybernetically enhanced web apps, svelte.dev, viewed 5 May 2022, https://svelte.dev/.
Iqcode.com. 2022. mongodb add to array if not exists Code Example. [online] Available at: https://iqcode.com/code/other/mongodb-add-to-array-if-not-exists [Accessed 2 May 2022].
Kumar, R., 2022. RecordRTC.js Example to Build a WebRTC Audio Recorder From Microphone and Play, Download Recorded Audio as Mp3 File in Browser Using Javascript - Coding Diksha. [online] Coding Diksha. Available at: https://codingdiksha.com/recordrtc-js-example-to-build-a-webrtc-audio-recorder-from-microphone-and-play-download-recorded-audio-as-mp3-file-in-browser-using-javascript/ [Accessed 20 May 2022].
Kumar, R., 2022. Svelte.js Scroll to Element With Horizontal & Vertical Animation in Browser - Coding Diksha. [online] Coding Diksha. Available at: https://codingdiksha.com/svelte-js-scroll-to-element-with-horizontal-vertical-animation-in-browser/ [Accessed 16 May 2022].
Leading Agile 2019, AGILE ADOPTION GOVERNANCE MODEL, Leading Agile, March, viewed 19 March 2022, https://content.leadingagile.com/wp-content/uploads/2019/03/Agile-Adoption-Governance-Model-LeadingAgile.pdf.
LePage, P 2020, How to provide your own in-app install experience, web.dev, viewed 5 May 2022, https://web.dev/customize-install/.
Lespinasse, R & Supcik, J n.d., Draw.io Export Action - GitHub Marketplace, GitHub, viewed 5 May 2022, https://github.com/marketplace/actions/draw-io-export-action.
LogRocket Blog. 2022. Build a single-page application in Svelte with svelte-spa-router - LogRocket Blog. [online] Available at: https://blog.logrocket.com/build-spa-svelte-svelte-spa-router/ [Accessed 9 May 2022].
Luna, A, Kruchten, P, Riccio, E & Moura, H 2016, ‘Foundations for an Agile Governance Manifesto: a bridge for business agility’, 13th International Conference on Management of Technology and Information Systems, viewed 18 March 2022, https://www.researchgate.net/publication/299578743_Foundations_for_an_Agile_Governance_Manifesto_a_bridge_for_business_agility.
Luna, AJH de O, Marinho, MLM & de Moura, HP 2019, ‘Agile governance theory: operationalization’, Innovations in Systems and Software Engineering, vol. 16, no. 1, pp. 3–44, viewed 18 March 2022, https://link-springer-com.ezproxy.lib.rmit.edu.au/article/10.1007/s11334-019-00345-3.
Madewithsvelte.com. 2022. UI Component - Made with Svelte. [online] Available at: https://madewithsvelte.com/ui-component [Accessed 4 May 2022].
Medium. 2022. A Long Time Coming: The MediaRecorder API Is Widely Adopted. [online] Available at: https://blog.bitsrc.io/a-long-time-coming-the-mediarecorder-api-is-widely-adopted-2f8565a5fb5b [Accessed 16 May 2022].
Milligan, T 2022, mdbook-admonish, GitHub, viewed 5 May 2022, https://github.com/tommilligan/mdbook-admonish.
MongoDB: How do I update a single subelement in an array, r., 2022. MongoDB: How do I update a single subelement in an array, referenced by the index within the array?. [online] Stack Overflow. Available at: https://stackoverflow.com/questions/11372065/mongodb-how-do-i-update-a-single-subelement-in-an-array-referenced-by-the-inde [Accessed 2 May 2022].
Node Source 2022, NodeSource Node.js Binary Distributions, GitHub, viewed 13 May 2022, https://github.com/nodesource/distributions/blob/master/README.md.
OpenJS Foundation n.d., Find the installed version of an npm package, Find the installed version of an npm package, viewed 5 May 2022, https://nodejs.dev/learn/find-the-installed-version-of-an-npm-package.
Perrin, H n.d., Svelte Material UI, sveltematerialui.com, viewed 5 May 2022, https://sveltematerialui.com/.
Playwright.dev. 2022. Getting started | Playwright. [online] Available at: https://playwright.dev/docs/intro#first-test [Accessed 24 May 2022].
Progressive Web Apps n.d., web.dev, viewed 5 May 2022, https://web.dev/progressive-web-apps/.
Romero, D 2020, How To Create Color Schemes For Your UI Design Using The 60-30-10 Technique, Digital Synopsis, viewed 5 May 2022, https://digitalsynopsis.com/design/how-to-apply-color-to-user-interface/.
Schwaber, K & Sutherland, J 2017, Scrum Guide | Scrum Guides, Scrumguides.org, viewed 19 March 2022, https://scrumguides.org/scrum-guide.html.
Shields.io n.d., Shields.io: Quality metadata badges for open source projects, shields.io, viewed 5 May 2022, https://shields.io/.
Slater, C 2021, Email Buttons: 5 Ways to Make Them Bulletproof & Beautiful, Litmus, viewed 5 May 2022, https://www.litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design/.
Smith, ED n.d., Svelteit, Svelteit, viewed 5 May 2022, https://docs.svelteit.dev/layouts.
Snyk Limited n.d., Snyk | Developer security | Develop fast. Stay secure., snyk.io, viewed 5 May 2022, https://snyk.io/.
Snyk Vulnerability Database. 2022. Prototype Pollution in unset-value | Snyk. [online] Available at: https://security.snyk.io/vuln/SNYK-JS-UNSETVALUE-2400660 [Accessed 11 May 2022].
Srivastava, N n.d., App Privacy Policy Generator, app-privacy-policy-generator.nisrulz.com, viewed 5 May 2022, https://app-privacy-policy-generator.nisrulz.com/.
Stack Overflow, M. and Dennis, L., 2022. MongoDB: Is it possible to make a case-insensitive query?. [online] Stack Overflow. Available at: https://stackoverflow.com/questions/1863399/mongodb-is-it-possible-to-make-a-case-insensitive-query [Accessed 16 May 2022].
Svelte Society n.d., Home, Svelte Society, viewed 5 May 2022, https://sveltesociety.dev/.
Teamwork 2020, Agile Project Management – The Beginners Guide, Teamwork.com, viewed 19 March 2022, https://www.teamwork.com/project-management-guide/agile-project-management/.
The Open Group 2020, 8. Agile Governance: Open Agile ArchitectureTM, pubs.opengroup.org, viewed 19 March 2022, https://pubs.opengroup.org/architecture/o-aa-standard/a-governance.html#agile-governance.
Vejseli, S, Proba, D, Rossmann, A & Jung, R 2018, The Agile Strategies In It Governance: Towards A Framework Of Agile It Governance In The Banking Industry, Semantic Scholar, 1 November, viewed 19 March 2022, https://www.semanticscholar.org/paper/The-Agile-Strategies-in-IT-Governance%3A-Towards-a-of-Vejseli-Proba/ba490e5cc7a70797ff14ad31a2d82735fbe16b86.
Verheyen, G 2014, Accountability is a Quality of Agile, Scrum.org, viewed 19 March 2022, https://www.scrum.org/resources/blog/accountability-quality-agile.
Villanova University 2022, Controlling Process: 5 Steps in the Control Process of Project Management, Villanovau.com, viewed 19 March 2022, https://www.villanovau.com/resources/project-management/controlling-process-project-management/.
Youtube 2021, Svelte Material UI in SvelteKit Tutorial, www.youtube.com, viewed 5 May 2022, https://www.youtube.com/watch?v=OyjZ7dezADw.
Privacy Policy
Yama Pty Ltd built the YaMa app as an Open Source app. This SERVICE is provided by Yama Pty Ltd at no cost and is intended for use as is.
This page is used to inform visitors regarding our policies with the collection, use, and disclosure of Personal Information if anyone decided to use our Service.
If you choose to use our Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that we collect is used for providing and improving the Service. We will not use or share your information with anyone except as described in this Privacy Policy.
The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which are accessible at YaMa unless otherwise defined in this Privacy Policy.
Information Collection and Use
For a better experience, while using our Service, we may require you to provide us with certain personally identifiable information. The information that we request will be retained by us and used as described in this privacy policy.
The app does use third-party services that may collect information used to identify you.
Link to the privacy policy of third-party service providers used by the app
Log Data
We want to inform you that whenever you use our Service, in a case of an error in the app we collect data and information (through third-party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing our Service, the time and date of your use of the Service, and other statistics.
Cookies
Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.
This Service does not use these “cookies” explicitly. However, the app may use third-party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service.
Service Providers
We may employ third-party companies and individuals due to the following reasons:
- To facilitate our Service;
- To provide the Service on our behalf;
- To perform Service-related services; or
- To assist us in analysing how our Service is used.
We want to inform users of this Service that these third parties have access to their Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.
Security
We value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and we cannot guarantee its absolute security.
Links to Other Sites
This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by us. Therefore, we strongly advise you to review the Privacy Policy of these websites. We have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.
Children’s Privacy
These Services do not address anyone under the age of 13. We do not knowingly collect personally identifiable information from children under 13 years of age. In the case we discover that a child under 13 has provided us with personal information, we immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact us so that we will be able to do the necessary actions.
Changes to This Privacy Policy
We may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. We will notify you of any changes by posting the new Privacy Policy on this page.
This policy is effective as of 2022-04-21
Contact Us
If you have any questions or suggestions about our Privacy Policy, do not hesitate to contact us at contact-yama@yama.com.au.