Skip to content

An API service project that lets you create personal resume data. You can use the service to create your resume by the following link

Notifications You must be signed in to change notification settings

themiddnight/My-Resume-Web-API-Firebase

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Introduction

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.

Routes

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 /email 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

Data structures

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,

Auth workflow

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
Loading

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
Loading

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
Loading

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
Loading

Todo next

  • 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.

About

An API service project that lets you create personal resume data. You can use the service to create your resume by the following link

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages