CloudSound is a full-stack web application, based on SoundCloud, with a reimagined fluffier feel.
- Javascript
- React
- Redux
- Node.js
- Express
- Sequelize
- Amazon Web Services
- PostgreSQL
- Clone the project
cd
into the project root folder and runnpm install
cd
into the backend folder and rename the.env.example
to.env
and change theJWT_SECRET
if desired- While in the backend run:
dotenv npx sequelize db:migrate
dotenv npx sequelize db:seed:all
- While still in the backend and once the database is properly migrated and seeded run
npm start
- In a seperate terminal cd into the frontend folder and run
npm start
- Signup
- Login
- Logout
- Songs
- Songs can be viewed on the splash page, ablum pages, and user pages
- Song details can be viewed on that songs page
- Songs can be created from the users profile page
- Songs can be updated and deleted from that songs page
- Comments
- Comments can be viewed, created, updated, and deleted on a songs page
- Albums
- Albums can be viewed on the splash page, and user pages
- Album details can be viewed on that albums page
- Albums can be created from the users profile page
All endpoints that require a current user to be logged in.
- Request: endpoints that require authentication
- Error Response: Require authentication
-
Status Code: 401
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Authentication required", "statusCode": 401 }
-
All endpoints that require authentication and the current user does not have the correct role(s) or permission(s).
- Request: endpoints that require proper authorization
- Error Response: Require proper authorization
-
Status Code: 403
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Forbidden", "statusCode": 403 }
-
Returns the information about the current user that is logged in.
-
Require Authentication: true
-
Request
- Method: GET
- URL: /session
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "firstName": "John", "lastName": "Smith", "email": "[email protected]", "username": "JohnSmith" }
-
Logs in a current user with valid credentials and returns the current user's information.
-
Require Authentication: false
-
Request
-
Method: POST
-
URL: /session
-
Headers:
- Content-Type: application/json
-
Body:
{ "email": "[email protected]", "password": "secret password" }
-
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "firstName": "John", "lastName": "Smith", "email": "[email protected]", "username": "JohnSmith", "token": "" }
-
-
Error Response: Invalid credentials
-
Status Code: 401
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Invalid credentials", "statusCode": 401 }
-
-
Error response: Body validation errors
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation error", "statusCode": 400, "errors": { "email": "Email is required", "password": "Password is required" } }
-
Creates a new user, logs them in as the current user, and returns the current user's information.
-
Require Authentication: false
-
Request
-
Method: POST
-
URL: /users
-
Headers:
- Content-Type: application/json
-
Body:
{ "firstName": "John", "lastName": "Smith", "username": "JohnSmith", "email": "[email protected]", "password": "secret password" }
-
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "firstName": "John", "lastName": "Smith", "username": "JohnSmith", "email": "[email protected]", "token": "" }
-
-
Error response: User already exists with the specified email
-
Status Code: 403
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "User already exists", "statusCode": 403, "errors": { "email": "User with that email already exists" } }
-
-
Error response: User already exists with the specified username
-
Status Code: 403
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "User already exists", "statusCode": 403, "errors": { "username": "User with that username already exists" } }
-
-
Error response: Body validation errors
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation error", "statusCode": 400, "errors": { "email": "Invalid email", "username": "Username is required", "firstName": "First Name is required", "lastName": "Last Name is required" } }
-
Returns all the songs.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /songs
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Songs":[ { "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
Returns all the songs created by the current user.
-
Require Authentication: true
-
Request
- Method: GET
- URL: /users/current/songs
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Songs": [ { "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
Returns the details of a song specified by its id.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /songs/:songId
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url", "Artist": { "id": 1, "username": "JohnSmith", "previewImage": "image url" }, "Album": { "id": 1, "title": "Time", "previewImage": "image url" } }
-
-
Error response: Couldn't find a Song with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Song couldn't be found", "statusCode": 404 }
-
Creates and returns a new song.
-
Require Authentication: true
-
Require proper authorization: Album must belong to the current user
-
Request
-
Method: POST
-
URL: /albums/:albumId/songs
-
Headers:
- Content-Type: application/json
-
Body:
{ "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "imageUrl": "image url" }
-
-
Successful Response
-
Status Code: 201
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" }
-
-
Error Response: Body validation error
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation Error", "statusCode": 400, "errors": { "title": "Song title is required", "url": "Audio is required" } }
-
-
Error response: Couldn't find an Album with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Album couldn't be found", "statusCode": 404 }
-
Updates and returns an existing song.
-
Require Authentication: true
-
Require proper authorization: Song must belong to the current user
-
Request
-
Method: PUT
-
URL: /songs/:songId
-
Headers:
- Content-Type: application/json
-
Body:
{ "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "imageUrl": "image url" }
-
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-20 20:00:00", "previewImage": "image url" }
-
-
Error Response: Body validation error
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation Error", "statusCode": 400, "errors": { "title": "Song title is required", "url": "Audio is required" } }
-
-
Error response: Couldn't find a Song with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Song couldn't be found", "statusCode": 404 }
-
Deletes an existing song.
-
Require Authentication: true
-
Require proper authorization: Song must belong to the current user
-
Request
- Method: DELETE
- URL: /songs/:songId
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Successfully deleted", "statusCode": 200 }
-
-
Error response: Couldn't find a Song with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Song couldn't be found", "statusCode": 404 }
-
Returns all the Albums.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /albums
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Albums": [ { "id": 1, "userId": 1, "title": "Time", "description": "An album about time.", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
Returns all the Albums created by the current user.
-
Require Authentication: true
-
Request
- Method: GET
- URL: /users/current/albums
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Albums":[ { "id": 1, "userId": 1, "title": "Time", "description": "An album about time.", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
Returns the details of an album specified by its id.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /albums/:albumId
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "title": "Time", "description": "An album about time.", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url", "Artist": { "id": 1, "username": "JohnSmith", "previewImage": "image url" }, "Songs": [ { "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
-
Error response: Couldn't find an Album with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Album couldn't be found", "statusCode": 404 }
-
Creates and returns a new album.
-
Require Authentication: true
-
Request
-
Method: POST
-
URL: /albums
-
Headers:
- Content-Type: application/json
-
Body:
{ "title": "Time", "description": "An album about time.", "imageUrl": "image url" }
-
-
Successful Response
-
Status Code: 201
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "title": "Time", "description": "An album about time.", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" }
-
-
Error Response: Body validation error
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation Error", "statusCode": 400, "errors": { "title": "Album title is required" } }
-
Updates and returns an existing album.
-
Require Authentication: true
-
Require proper authorization: Album must belong to the current user
-
Request
-
Method: PUT
-
URL: /albums/:albumId
-
Headers:
- Content-Type: application/json
-
Body:
{ "title": "Time", "description": "An album about time.", "imageUrl": "image url" }
-
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "title": "Time", "description": "An album about time.", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-20 20:00:00", "previewImage": "image url" }
-
-
Error Response: Body validation error
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation Error", "statusCode": 400, "errors": { "title": "Album title is required" } }
-
-
Error response: Couldn't find an Album with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Album couldn't be found", "statusCode": 404 }
-
Deletes an existing album.
-
Require Authentication: true
-
Require proper authorization: Album must belong to the current user
-
Request
- Method: DELETE
- URL: /albums/:albumId
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Successfully deleted", "statusCode": 200 }
-
-
Error response: Couldn't find an Album with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Album couldn't be found", "statusCode": 404 }
-
Returns all the comments that belong to a song specified by id.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /songs/:songId/comments
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Comments": [ { "id": 1, "userId": 1, "songId": 1, "body": "I love this song!", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36" , "User": { "id": 1, "username": "JohnSmith" }, } ] }
-
-
Error response: Couldn't find a Song with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Song couldn't be found", "statusCode": 404 }
-
Create and return a new comment for a song specified by id.
-
Require Authentication: true
-
Request
-
Method: POST
-
URL: /songs/:songId/comments
-
Headers:
- Content-Type: application/json
-
Body:
{ "body": "I love this song!" }
-
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "songId": 1, "body": "I love this song!", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36" , }
-
-
Error Response: Body validation errors
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation error", "statusCode": 400, "errors": { "body": "Comment body text is required" } }
-
-
Error response: Couldn't find a Song with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Song couldn't be found", "statusCode": 404 }
-
Update and return an existing comment.
-
Require Authentication: true
-
Require proper authorization: Comment must belong to the current user
-
Request
-
Method: PUT
-
URL: /comments/:commentId
-
Headers:
- Content-Type: application/json
-
Body:
{ "body": "I love this song!" }
-
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "songId": 1, "body": "I love this song!", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-20 20:00:00" }
-
-
Error Response: Body validation errors
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation error", "statusCode": 400, "errors": { "body": "Comment body text is required", } }
-
-
Error response: Couldn't find a Comment with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Comment couldn't be found", "statusCode": 404 }
-
Delete an existing comment.
-
Require Authentication: true
-
Require proper authorization: Comment must belong to the current user
-
Request
- Method: DELETE
- URL: /comments/:commentId
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Successfully deleted", "statusCode": 200 }
-
-
Error response: Couldn't find a Comment with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Comment couldn't be found", "statusCode": 404 }
-
Returns the details of an artist specified by their id.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /users/:userId
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "username": "JohnSmith", "totalSongs": 10, "totalAlbums": 2, "previewImage": "image url" }
-
-
Error response: Couldn't find an Artists with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Artist couldn't be found", "statusCode": 404 }
-
Returns all the songs created by the specified artist.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /users/:userId/songs
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Songs": [ { "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
-
Error response: Couldn't find an Artist with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Artist couldn't be found", "statusCode": 404 }
-
Returns all the albums created by the specified artist.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /users/:userId/albums
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Albums": [ { "id": 1, "userId": 1, "title": "Time", "description": "An album about time.", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
-
Error response: Couldn't find an Artist with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Artist couldn't be found", "statusCode": 404 }
-
Returns all the playlists created by the specified artist.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /users/:userId/playlists
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Playlists": [ { "id": 1, "userId": 1, "name": "Current Favorites", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
-
Error response: Couldn't find an Artist with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Artist couldn't be found", "statusCode": 404 }
-
Creates and returns a new playlist.
-
Require Authentication: true
-
Request
-
Method: POST
-
URL: /playlists
-
Headers:
- Content-Type: application/json
-
Body:
{ "name": "Current Favorites", "imageUrl": "image url" }
-
-
Successful Response
-
Status Code: 201
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "name": "Current Favorites", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" }
-
-
Error Response: Body validation error
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation Error", "statusCode": 400, "errors": { "name": "Playlist name is required" } }
-
Add a song to a playlist specified by the playlist's id.
-
Require Authentication: true
-
Require proper authorization: Playlist must belong to the current user
-
Request
-
Method: POST
-
URL: /playlists/:playlistId
-
Headers:
- Content-Type: application/json
-
Body:
{ "songId": 1 }
-
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "playlistId": 1, "songId": 1 }
-
-
Error response: Couldn't find a Playlist with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Playlist couldn't be found", "statusCode": 404 }
-
-
Error response: Couldn't find a Song with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Song couldn't be found", "statusCode": 404 }
-
Returns the details of a playlist specified by its id.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /playlists/:playlistId
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "name": "Current Favorites", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url", "Songs": [ { "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
-
Error response: Couldn't find a Playlist with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Playlist couldn't be found", "statusCode": 404 }
-
Updates and returns an existing playlist.
-
Require Authentication: true
-
Require proper authorization: Playlist must belong to the current user
-
Request
-
Method: PUT
-
URL: /playlists/:playlistId
-
Headers:
- Content-Type: application/json
-
Body:
{ "name": "Current Favorites", "imageUrl": "image url" }
-
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "id": 1, "userId": 1, "name": "Current Favorites", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-20 20:00:00", "previewImage": "image url" }
-
-
Error Response: Body validation error
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation Error", "statusCode": 400, "errors": { "name": "Playlist name is required" } }
-
-
Error response: Couldn't find a Playlist with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Playlist couldn't be found", "statusCode": 404 }
-
Deletes an existing playlist.
-
Require Authentication: true
-
Require proper authorization: Playlist must belong to the current user
-
Request
- Method: DELETE
- URL: /playlists/:playlistId
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Successfully deleted", "statusCode": 200 }
-
-
Error response: Couldn't find a Playlist with the specified id
-
Status Code: 404
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Playlist couldn't be found", "statusCode": 404 }
-
Returns all the playlists created by the current user.
-
Require Authentication: true
-
Request
- Method: GET
- URL: /users/current/playlists
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Playlists":[ { "id": 1, "userId": 1, "name": "Current Favorites", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ] }
-
Return songs filtered by query parameters.
-
Require Authentication: false
-
Request
- Method: GET
- URL: /songs
- Query Parameters
- page: integer, minimum: 0, maximum: 10, default: 0
- size: integer, minimum: 0, maximum: 20, default: 20
- title: string, optional
- createdAt: string, optional
- Body: none
-
Successful Response
-
Status Code: 200
-
Headers:
- Content-Type: application/json
-
Body:
{ "Songs":[ { "id": 1, "userId": 1, "albumId": 1, "title": "Yesterday", "description": "A song about the past.", "url": "audio url", "createdAt": "2021-11-19 20:39:36", "updatedAt": "2021-11-19 20:39:36", "previewImage": "image url" } ], "page": 2, "size": 25 }
-
-
Error Response: Query parameter validation errors
-
Status Code: 400
-
Headers:
- Content-Type: application/json
-
Body:
{ "message": "Validation Error", "statusCode": 400, "errors": { "page": "Page must be greater than or equal to 0", "size": "Size must be greater than or equal to 0", "createdAt": "CreatedAt is invalid" } }
-