This is my backend study project. It is an API service for creating resume data. Using Express.js framework and hosted in Firebase. You can try it to create your resume here. And see my example resume here.
These are all routes in the project. Grouped by the project's Express Router files:
/v1/auth
Method | Route | Descriptions |
---|---|---|
POST | /login | Create and send the JWT token |
POST | /register | Create user data (with verified = false) and send verification email to user |
POST | /send-verification-email | For resending a verification email |
POST | /send-reset-password | For sending a reset password link via email |
POST | /verify-email | Check the token (from user's email) and update user email, verified = true |
POST | /reset-password | Update new password with token check (from user's email) |
/v1/user
User ID token needed
Method | Route | Descriptions |
---|---|---|
GET | / | Get user data and their resumes list |
POST | /name | Update user name |
POST | Send an email change notification to user's old email, and verify new email to user's new email | |
DELETE | / | Delete user, user's resume and user's storage data |
/v1/resume
User ID token needed, except GET /:resumeId
Method | Route | Descriptions |
---|---|---|
GET | /:resumeId | Get all data of a resume (to use in the public resume page) |
GET | /:resumeId/summary | Get resume's summary data (owner name, resume name, active data) |
POST | / | Create an blank resume with template data |
PATCH | /:resumeId | Update resume name or active status |
DELETE | /:resumeId | Delete resume data and it's storage |
/v1/public_notes
This is a small social feature that lets anyone post some messages to anyone's resume page
Method | Route | Descriptions |
---|---|---|
GET | /:resumeId/public_notes | Get all messages |
POST | /:resumeId/public_notes | Create a new message |
DELETE | /:resumeId/public_notes/:noteId | Delete a message |
/v1/edit
For updating each resume's section. Each section has /GET and /PUT
- /:resumeId/settings
- /:resumeId/about
- /:resumeId/certifications
- /:resumeId/collections
- /:resumeId/education
- /:resumeId/experiences
- /:resumeId/languages
- /:resumeId/other_links
- /:resumeId/profile
- /:resumeId/projects
- /:resumeId/public_notes
- /:resumeId/skills
This project use Firestore as a database, which is a No-SQL. And Firebase Storage to store image files.
User collection:
{
name: string,
email: string,
password: string,
verified: string
}
Resume collection:
{
resume_name: string,
user_id: string,
created_at: date,
active: boolean
}
Resume subcollections (overview):
data: {
settings: object,
about: object,
certifications: object,
collections: object,
education: object,
experiences: object,
languages: object,
other_links: object,
profile: object,
projects: object,
public_notes: object,
skills: object,
}
public_notes: {
content: string,
number: number,
createdAt: date
}
Resume data subcollections (detail)
Note: The following attributes are additional data that may needed when submitted...
- *image_file: base64 Image file in base64 string
- *deleted_image_paths: string[] List of Firebase storage file paths to be removed (when delete resume data, remove image, etc.)
settings
layout: number,
background": {
mode: number,
color: string,
image_url: string,
image_path: string
*image_file: base64,
},
intro: {
title: string,
subtitle: string,
enter_button: string
}
profile
subtitle: string,
image_url: string,
image_path: string,
*image_file: base64,
contact: {
location: string,
email: string,
phone: string,
}
links: [
{
title: string,
url: string
},
]
about
active: boolean,
title: string,
subtitle: string,
data: [
{ content: string },
]
education
active: boolean,
title: string,
subtitle: string,
display_limit: number,
data: [
{
active: boolean,
title: string,
degree: string,
school: string,
from: string,
to: string,
current: boolean
},
]
experiences
active: boolean,
title: string,
subtitle: string,
display_limit: number,
data: [
{
active: boolean
title: string
company: string
from: string
to: string
current: boolean
description: [
{ content: string },
]
},
]
projects
active: boolean,
title: string,
subtitle: string,
display_limit: number,
display_mode: number,
data: [
{
title: string,
tags: string[],
image_url: string,
image_path: string,
*image_file: base64,
description: string,
public_link: string,
createdAt: string,
links: [
{
title: string,
url: string
},
]
},
]
*deleted_image_paths: string[]
skills
active: boolean,
title: string,
subtitle: string,
display_limit: number,
data: [
{
active: boolean,
title: string,
level: string,
description: string,
image_url: string,
image_path: string,
*image_file: base64,
isMono: boolean
}
]
*deleted_image_paths: string[]
collections
active: boolean,
title: string,
subtitle: string,
display_limit: number,
data: [
{
active: boolean,
title: string,
description: string,
image_url: string,
image_path: string,
*image_file: base64,
isMono: boolean
}
]
*deleted_image_paths: string[]
languages
active: boolean,
title: string,
subtitle: string,
display_limit: number,
read: { value: number, level: string },
write: { value: number, level: string },
listen: { value: number, level: string },
speak: { value: number, level: string },
certifications
active: boolean,
title: string,
subtitle: string,
display_limit: number,
data: [
{
active: boolean,
title: string,
issuedBy: string,
issuedDate: string,
credentialUrl: string,
image_url: string,
image_path: string,
*image_file: base64,
},
],
*deleted_image_paths: string[]
other_links
active: boolean,
title: string,
subtitle: string,
display_limit: number,
data: [
{ title: string, url: string },
]
public_notes
active: boolean,
title: string,
subtitle: string,
display_limit: number,
These are workflows that implement the frontend project
Register
sequenceDiagram
actor User
User->>Frontend: Input name, email, password
Frontend->>+Backend: POST /v1/auth/register
Backend->>Database: Write user data, hashed password, verified = false
Backend->>-User: Send token verification link via email
User->>Frontend: Click link to send token
Frontend->>Backend: POST /v1/auth/verify-email: Send token data
alt token is valid
Backend->>Database: Update verified = true
Backend->>Frontend: Response success
Frontend->>User: Show success, redirect to login
else token is not valid
Backend->>Frontend: Response error
Frontend->>User: Show error
note over Frontend,User: User can login to send another verification email
end
Login
sequenceDiagram
actor User
User->>Frontend: Input email, password
Frontend->>Backend: POST /v1/auth/login
Backend->>Database: Find user via email
Database-->>Backend: email and hashed password
break email not found
Backend->>Frontend: Response not found
Frontend->>User: Show not found error
end
break password not valid
Backend->>Frontend: Response unauthorized
Frontend->>User: Show invalid email or password error
end
Backend->>Frontend: Resopnse token
Frontend->>Frontend: Redirect to /create page
Frontend-->Database: Get data with access token
Change email
sequenceDiagram
actor User
User->>Frontend: Send new email address
Frontend->>Backend: POST /v1/user/email
participant Database
Backend->>User: Send notification to old email, <br> Send verification link to new email
User->>Frontend: Click link to send token
Frontend->>Backend: POST /v1/auth/verify-email <br> Send token (userId and new email)
alt token is valid
Backend->>Database: Update email and verified = true
Backend->>Frontend: Response success
Frontend->>User: Show success, redirect to login
else token is not valid
Backend->>Frontend: Response error
Frontend->>User: Show error
end
Reset password
sequenceDiagram
actor User
User->>Frontend: Click reset password
Frontend->>Backend: /v1/auth/send-reset-password
participant Database
Backend->>User: Send reset password link via email
User->>Frontend: Click link and input new password
Frontend->>Backend: /v1/auth/reset-password: send new password
alt token is valid
Backend->>Database: Update hashed password
Backend->>Frontend: Response success
Frontend->>User: Show success, redirect to login
else token is not valid
Backend->>Frontend: Response error
Frontend->>User: Show error
end
- Adjust the access token to be less lifetime and create a refresh token for more security.
- Implement social login.
- Implement Redis cache to reduce reading the firestore database directly.
- Make user can create API key so user can access their own raw data.