Deployed App | Front End Repo -- I'm deployed on a free instance, so I might take some time to start up
A react application for searching for photos publicly uploaded by users. This repository contains only the back end. For front end repository or deployed project, click a link above.
Some features of this application can be accessed only as a logged in user.
To test features without creating an account, you can press the guest account button on the right side of the main menu.
This account will automatically add photos marked as uploaded by this user, and has the full range of functionality of a normal account.
When this account is logged out or when 1 day passes, this account will delete itself.
A list of live features in the current version:
- Users can view and search images
- Users can view details about an image by clicking on it
- Users can create accounts and login/logout
- Logged-in users can upload images and mark them with name, description, and tags (up to 10 at a time)
- Logged-in users can search by images they have uploaded
- Logged-in users can mark images as favorites, then search by image they have marked
- Logged-in users can edit the name, description, and tags of an image they have uploaded
Information about running a local development environment here
Guidelines for contributing here
This project is still in development. For a list of features and bugs that need to be addressed here
Below is a brief summary of this project's tech stack. For detailed information about the tech stack for this project here
- Front end framework: React
- Front end component library: Ant Design
- Back end framework: Express
- Database: Postgres + Cloudinary for image storage
- Deployment: Heroku
Detailed information about the API endpoints here
| Method | Endpoint | Params | Description |
|---|---|---|---|
| GET | /api/users/:userid/photos |
int userid required |
Returns list of photo ids uploaded by specified User |
| GET | /api/users/:userid |
int userid required |
Returns data about a single user |
| GET | /api/users/name/:username |
str username required |
Returns row from user table with matching username |
| GET | /api/users/:userid/favorites |
int userid required |
Returns rows from photos matching ids in specified user's favorites column |
| PUT | /api/users/:userid/favorites/add/:photoid |
int userid required, int photoid required |
Updates favorites by adding photo id to user's favorites |
| PUT | api/users/:userid/favorites/remove/:photoid |
int userid required, int photoid required |
Updates favorites by removing photo id from user's favorites |
| DELETE | api/users/:userid |
int userid required |
Removes user with matching id from user table and deletes all photos uploaded by them |
GET /api/users/:userid/photos response:
[
{
"id" : int (PK),
"public_id" : str,
"name" : str,
"image_path" : str (url),
"height" : int,
"width" : int,
"description" : str,
"tags" : [ str, ... ],
"uploader" : int (FK -> users)
},
...
]GET /api/users/:userid response:
{
"id" : int (PK),
"username" : str,
"password" : "**********",
"isGuest" : bool,
"favorites" : [ int, ... ]
}GET /api/users/name/:username response:
[
{
"id" : int (PK),
"username" : str,
"password" : "**********",
"isGuest" : bool,
"favorites : [ int, ... ]
}
]GET /api/users/:userid/favorites response:
[
{
"id" : int (PK),
"public_id" : str,
"name" : str,
"image_path" : str (url),
"height" : int,
"width" : int,
"description" : str,
"tags" : [ str, ... ],
"uploader" : int (FK -> users)
},
...
]PUT /api/users/:userid/favorites/add/:photoid response:
1PUT /api/users/:userid/favorites/remove/:photoid response:
1DELETE api/users/:userid response:
{
"id" : int (PK),
"username" : str,
"password" : "**********",
"isGuest" : bool,
"favorites" : [ int, ... ]
}| Method | Endpoint | Params | Description |
|---|---|---|---|
| GET | /api/photos/all |
None | Returns all rows from photos table |
| GET | /api/photos/batch/:photoIds |
comma separated str, photoIds required |
Returns rows from photos with id that match photoIds |
| GET | /api/photos/:photoid |
int photoid required |
Returns row from photos with id that matches photoid |
| GET | /api/photos/tags/:tag |
str tag required |
Returns rows from photos with specified tag |
| POST | /api/photos/search |
body required -- see below | Returns rows from photos that match search terms |
| DELETE | api/photos/:photoid |
int photoid required |
Removes row with matching id from photo table |
GET /api/photos/all response:
[
{
"id" : int (PK),
"public_id" : str,
"name" : str,
"image_path" : str (url),
"height" : int,
"width" : int,
"description" : str,
"tags" : [ str, ... ],
"uploader" : int (FK -> users)
},
...
]GET /api/photos/batch/:photoIds response:
[
{
"id" : int (PK),
"public_id" : str,
"name" : str,
"image_path" : str (url),
"height" : int,
"width" : int,
"description" : str,
"tags" : [ str, ... ],
"uploader" : int (FK -> users)
},
...
]GET /api/photos/:photoid response:
{
"id" : int (PK),
"public_id" : str,
"name" : str,
"image_path" : str (url),
"height" : int,
"width" : int,
"description" : str,
"tags" : [ str, ... ],
"uploader" : int (FK -> users)
}GET /api/photos/tags/:tag response:
[
{
"id" : int (PK),
"public_id" : str,
"name" : str,
"image_path" : str (url),
"height" : int,
"width" : int,
"description" : str,
"tags" : [ str, ... ],
"uploader" : int (FK -> users)
},
...
]POST /api/photos/search body:
{
"search_type" : enum("all-images", "my-favs", "my-uploads") required,
"search_term" : str required,
"user" : int (optional for "all-images")
}POST /api/photos/search response:
[
{
"id" : int (PK),
"public_id" : str,
"name" : str,
"image_path" : str (url),
"height" : int,
"width" : int,
"description" : str,
"tags" : [ str, ... ],
"uploader" : int (FK -> users)
},
...
]DELETE api/photos/:photoid response:
1| Method | Endpoint | Params | Description |
|---|---|---|---|
| GET | /api/auth/verify/:token |
str token required |
Checks whether a token is expired |
| GET | /api/auth/guest/create |
None | Adds a new row to users, adds 10 photos associated with new user to photos, returns token, setTimeout 1d -> delete user |
| POST | /api/auth/register |
body required -- see below | Adds a new row to users, returns token |
| POST | /api/auth/login |
body required -- see below | Returns a token |
| POST | /api/auth/signature |
None | Returns a cloudinary signature for uploading image |
| DELETE | api/auth/guest/:id |
int id required |
Removes row with matching id from photo table |
GET /api/auth/verify/:token response:
{
"expired" : bool
}GET /api/auth/guest/create response:
{
"id" : int,
"username" : `guest${int}`,
"password" : "**********",
"isGuest" : true,
"favorites" : [],
"token" : str (JWT)
}POST /api/auth/register body:
{
"username" : str (unique),
"password" : str
}POST /api/auth/register response:
{
"id" : int,
"username" : str,
"password" : "**********",
"isGuest" : false,
"favorites" : [],
"token" : str (JWT)
}POST /api/auth/login body:
{
"username" : str,
"password" : str
}POST /api/auth/login response:
{
"id" : int,
"username" : str,
"password" : "**********",
"isGuest" : bool,
"favorites" : [ int, ... ],
"token" : str (JWT)
}
OR
{
"message" : "Invalid Credentials"
}POST /api/auth/signature response:
{
"timestamp" : int (datetime),
"signature" : str
}DELETE /api/auth/guest/:id response:
1