Build status:
dev |
master |
---|---|
Dråpen i Havet/A Drop in the Ocean is a volunteer organization. If you want to contribute, take a look at the issues or contact the head of the organization Trude, at trude [@] drapenihavet [dot] no.
- Get a task on JIRA by talking to you teammates and looking at the sprint backlog.
- Create a new branch from the
dev
-branch, naming it using our branch naming strategy described below. - Code away and commit often. Try to follow good commit practice. Remember to write tests (and run them).
- When you're done (see definition of done on GitHub), create a pull request with reference to the JIRA-issue (preferably a link) and an overview of what the pull request is about. Await code review (you can tag people or yell for them on Slack to get your review faster).
- When you've reworked your code after the code review, the pull request will be merged.
The project has a strategy for what to name our branches, so that changes in them are easily traceable to user stories and issues in our issue tracking system JIRA. Another reason for having a naming strategy is that it makes it easy to find distinct types of proposed changes, as well as what's being worked on.
Name your branches in the following way, where DIH-num
is a task ID on JIRA:
- If it's a feature (new functionality) name the branch
feature/DIH-num
. - If it's a bugfix name the branch
bugfix/DIH-num
. - If it's a technical task, name the branch
tech/DIH-num
To setup the project locally install Postgres and set PG_URL
to your database. The format should postgres://USERNAME:PASSWORD@localhost/DB
. The capitalized words should be replaced with your own values.
To export your variable on a Unix-system, simply use the export
command, i.e. export PG_URL=your value
.
The system uses AWS SES for e-mails and sms notifications. You'll need to have the correct role installed on the instance running the application.
You can also set your AWS region with REGION
.
Contact one of the contributors to get more information on how to be added to the AWS teams, or take a look at Confluence for some standard values you can use for testing.
Run yarn build
to get a transpiled version of the API, then start with yarn start
.
If you're gonna develop:
- Install nodemon
npm install -g nodemon
& yarnnpm install -g yarn
- Spin up docker-compose to run services like db and emails locally.
- Run
yarn start:dev
Remember that you can run it with environment variables in before the command, i.e.PG_URL=value yarn start:dev
.
This will watch for changes and keep the application open for you.
To enter some test data into your database, run yarn load
. It will give you some test users
Role | Username |
---|---|
User | [email protected] |
Moderator | [email protected] |
Administrator | [email protected] |
All these users have the password password
.
To enter some test data into your database, run npm run load
.
When you've added your migration, do the following:
- Delete the old dataabase, and restart the app from a branch that does not have your changed data model. This creates the previous data model for you.
- Switch to the branch with the new data model and migration.
- Build with
npm run build
- Run the build with
PG_URL
set to your database, andNODE_ENV=production
. You run the built code withnpm start
- Check for errors, and see if the data model was updated in the database. If not, you'll have to fix issues and start from step number 1 again.
I.e. you create the old database, run your migration as it would run in production, and see that the migrations works.
- Run unit tests & code lint with
yarn test
. This will use your local database. - Run just unit tests with
yarn tests
withNODE_ENV=test
. This will use your local database.
Run the unit tests continuously with yarn test:watch
, only the tests currently worked on will run when updated.
All tests will run when a server file is updated. This will use your local database.
We have continuous deployment with Circle CI, which builds Docker-images and pushes to AWS EC2.
- The
dev
-branch is the main branch, and has CI to our staging environment. - The
master
-branch is the stable branch, and has CI to our production environment.
We use jsdoc to document modules and methods. You can find the generated documentation here, http://docs.dih.capra.me/, and of course also in the code.
Det betyr at du i koden vår finner et minimum av dokumentasjon for metoder på følgende format:
That means that you'll find a minimum of the following as documnetation for methods:
/**
* methodName - method description
*
* @function methodName
* @memberOf moduleType/moduleName
* @param {Type} paramName1 - paramName1 description
* @param {Type} paramName2 - paramName2 description
* @return {Type} - Description of return value
*/
For modules we document in the following way:
/**
* Module description
* @module type/name
*/
moduleType
is e.g. model
, controller
or component
.
When submitting pull requests or doing changes, please make sure you maintain the documentation format and quality - or rather increase it.
Property | Value |
---|---|
AUTH | No |
Header | json/application |
Data format:
Property | Type | Description | Restrictions | Default value | Required | Can be null |
---|---|---|---|---|---|---|
status | String ENUM | Status of trip | Must be in ['PENDING', 'ACCEPTED', 'REJECTED', 'ACTIVE' 'CLOSED, 'PRESENT', 'LEFT'] | PENDING | No | No |
userId | Integer | Id of user taking the trip | Must be a valid userId | None | Yes | No |
destinationId | Integer | Destination for trip | Must be a valid destinationId | None | Yes | No |
wishStartDate | Date | When the user wants this trip to start | None | Yes | No | |
wishEndDate | Date | When the user wnats this trip to end | None | Yes | No | |
startDate | Date | When the trip starts | None | Yes | Yes | |
endDate | Date | When the trip ends | None | Yes | Yes | |
travelMethod | String ENUM | Method of travel for trip | Must be in ['PLANE', 'OTHER'] | None | No | Yes |
departureAirport | String | Departure airport when plane is travel method | None | No | Yes | |
flightNumber | String | Flight number when plane is travel method | None | No | Yes | |
arrivalDate | Date | Arrival date for travel | None | No | Yes | |
departureDate | Date | Departure date for travel | None | No | Yes | |
otherTravelInformation | Text | Free text field when other travel methos is used | None | No | Yes |
On GET-requests the elements also holds destination
and user
as objects.
Request | Endpoint | Description | Request body | Query params | Sucessful response code | Sucessful response body |
---|---|---|---|---|---|---|
GET | Get all elements | None | destinationId , userId , status |
200 | Array of elements | |
POST | Create an new element | Element | 201 | The new element | ||
PUT | /:id | Update an element | Changed element | 204 | None | |
DELETE | /:id | Delete an element | None | 204 | None |
Property | Value |
---|---|
AUTH | Yes |
Header | json/application |
Data format:
Property | Type | Description | Restrictions | Default value | Required | Can be null |
---|---|---|---|---|---|---|
travelMethod | String ENUM | Method of travel for trip | Must be in ['SMS', 'EMAIL'] | None | Yes | No |
messages | String | Email or sms message, (Email can be in html format) | None | Yes | No | |
sender | String | string for sender id in sms | MAX 11 characters | None | No | Yes |
subject | String | Subject of the email to be sent | None | No | Yes | |
recipients | Array | Array of recipients (users) | None | Yes | No |
Request | Endpoint | Description | Request body | Query params | Sucessful response code | Sucessful response body |
---|---|---|---|---|---|---|
POST | / | Sends the speciefied message to each recipient | Element | 200 | report regarding the sended entities |
Property | Value |
---|---|
AUTH | No |
Header | json/application |
Data format:
Property | Type | Description | Restrictions | Default value | Required | Can be null |
---|---|---|---|---|---|---|
name | String | Name of destination | Letters only | None | Yes | No |
acceptedStatusMailTemplateId | Integer | Reference to mailTemplate for status accepted | Reference to element in malTemplates | New standard element | No | Yes |
rejectedStatusMailTemplateId | Integer | Reference to mailTemplate for status rejected | Reference to element in malTemplates | New standard element | No | Yes |
pendingStatusMailTemplateId | Integer | Reference to mailTemplate for status pending | Reference to element in malTemplates | New standard element | No | Yes |
miminmumTripDurationInDays | Integer | Minimum number of days a volunteer has to be available for to get accepted at the destination |
10 | No | No | |
startDate | Date | When the destination becomes active | Now | No | No | |
endDate | Date | When the destinations ends | null | No | Yes |
GET-requests includes the calculated field countOfActiveVolunteers
and isActive
Request | Endpoint | Description | Request body | Sucessful response code | Sucessful response body |
---|---|---|---|---|---|
GET | Get all elements | None | 200 | Array of elements | |
GET | /:id | Get all elements | None | 200 | Single element of given id |
POST | Create an new element | Element | 201 | The new element | |
PUT | /:id | Update an element | Changed element | 204 | None |
DELETE | /:id | Delete an element | None | 204 | None |
Property | Value |
---|---|
AUTH | No |
Header | json/application |
Data format:
Property | Type | Description | Restrictions | Default value | Required | Can be null |
---|---|---|---|---|---|---|
html | String | HTML-template for an e-mail | None | Yes | No |
Request | Endpoint | Description | Request body | Sucessful response code | Sucessful response body |
---|---|---|---|---|---|
GET | Get all elements | None | 200 | Array of elements | |
POST | Create an new element | Element | 201 | The new element | |
PUT | /:id | Update an element | Changed element | 204 | None |
DELETE | /:id | Delete an element | None | 204 | None |
Property | Value |
---|---|
AUTH | Yes |
Header | Authorization - Bearer jwt |
Header | Content-Type - json/application |
Data format:
Property | Type | Description | Restrictions | Default value | Required | Can be null |
---|---|---|---|---|---|---|
String (valid email) | the users email | must be a valid email | None | Yes | No | |
firstname | String | the users firstname | None | Yes | No | |
lastname | String | the users lastname | None | Yes | No | |
birth | Date | Birth date of the user | None | Yes | No | |
role | String ENUM | The user role | Must be in ['USER', 'MODERATOR', 'ADMIN'] | USER | No | No |
password | String (valid password) | The password in plain text | Must be set before the user can use the system. (login flow) | None | No | Yes |
volunteerInfo | Text | Occupatio and experience | Empty string | No | No | |
phoneNumber | String | User's phoneNumber | Yes | |||
languages | Text | Languages the user masters | Empty string | No | ||
medicalDegree | String | User's medical degree - type | Yes | |||
medicalDegreeLicenseNumber | String | License number of medical degree | Yes |
Also virtual field fullName
Request | Endpoint | Description | Request body | Sucessful response code | Sucessful response body |
---|---|---|---|---|---|
GET | / | Get the current user based on jwt | None | 200 | User object with id encoded in the jwt |
PUT | / | Update the current user based on jwt | Changes on the user object | 204 | None |
Property | Value |
---|---|
AUTH | No |
Header | Authorization - Bearer jwt |
Header | Content-Type - json/application |
Request | Endpoint | Description | AUTH | Request body | Sucessful response code | Sucessful response body |
---|---|---|---|---|---|---|
POST | / | user login | NO | email + password | 200 | object containing jwt |
POST | /password | update password given the jwt used has right premissions | YES ( jwt needs field setPassword = true ) | password | 200 | object containing jwt |
Property | Value |
---|---|
AUTH | No |
Header | Content-Type - json/application |
** **
Data format:
Property | Type | Description | Restrictions | Default value | Required | Can be null |
---|---|---|---|---|---|---|
String (valid email) | the users email | must be a valid email | None | Yes | No | |
firstname | String | the users firstname | None | Yes | No | |
lastname | String | the users lastname | None | Yes | No | |
birth | Date | Birth date of the user | None | Yes | No | |
role | String ENUM | The user role | Must be in ['USER', 'MODERATOR', 'ADMIN'] | USER | No | No |
phoneNumber | String | User's phoneNumber | Yes | |||
languages | Text | Languages the user masters | Empty string | No | ||
medicalDegree | String | User's medical degree - type | Yes | |||
medicalDegreeLicenseNumber | String | License number of medical degree | Yes | |||
volunteerInfo | Text | Occupation and experience | None | No | Yes | |
notes | String | Admins notes about the user | None | No | Yes |
Also virtual field fullName
Request | Endpoint | Description | Request body | Sucessful response code | Sucessful response body |
---|---|---|---|---|---|
POST | / | Create a new user | The user to be created | 201 | The created user |
PUT | /:id | Update a user by ID | The fields to be updated | 204 | N/A |
If there's no error body, then use the HTTP status code for handling:
HTTP status code | Description |
---|---|
404 | Not found |
400 | Bad request, i.e. something wrong with your request |
500 | Intenral server error |
The format of the errors is:
{
name: String,
message: String describing the error
}
The following errors can be thrown:
Error name | HTTP status code | Description |
---|---|---|
ValidationError | 400 | Thrown when you're trying to POST or PUT data that has data that isn't accepted. Check your request. |
ResourceNotFoundError | 404 | Thrown when a resource you're requesting isn't found. |
AuthenticationError | 401 | Thrown when you're not logged in and trying to access a resource that's available only to logged in users |