Skip to content

A platform for writing, publishing, and showcasing essays on some films I like.

License

Notifications You must be signed in to change notification settings

michaelhyi/film-blog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Film Blog

Website

About

This repository contains the source code to a film blog I started last year. It is a platform where I can explore my passion for movies and write for fun.

Though not my most "impressive" project, it's my favorite one to have worked on thus far. I have put several hundred commits into this project, all while experimenting with different technologies and learning along the way.

Source code has been moved here on October 25th, 2024. It was previously part of my personal website's respository.

Development

Getting Started

Getting Started

Pre-Requisites

  • Gradle
  • MySQL
  • Redis
  • Node
  1. Setup environment variables.
export ADMIN_PW=<your-admin-password>
export JWT_SECRET_KEY=<your-jwt-secret-key>

Set ADMIN_PW equal to a secure, hashed password. Generate one using openssl or any password manager, and then hash it using Spring Security's BCryptPasswordEncoder. To generate a JWT secret key, use openssl rand -base64 512.

  1. Create a MySQL database.

Create a new database called film_blog. Make sure that your MySQL master username and password are both set to root.

  1. Install dependencies and run projects.

Open three terminal instances. Follow the below code blocks to run each app.

cd backend/java
./gradlew bootRun
cd frontend/admin 
npm i
npm start
cd frontend/main
npm i
npm start

Testing

Unit Tests

Unit Tests

Auth Package
  • AuthService.java
    • willThrowLoginWhenWrongPassword
    • canLogin
    • willThrowValidateTokenWhenTokenIsMalformed
    • willThrowValidateTokenWhenTokenIsUnauthorized
    • canValidateToken
  • AuthUtil.java
    • willReturnFalseDuringIsAuthHeaderValidWhenHeaderIsNull
    • willReturnFalseDuringIsAuthHeaderValidWhenHeaderIsBlank
    • willReturnFalseDuringIsAuthHeaderValidWhenHeaderIsEmpty
    • willReturnFalseDuringIsAuthHeaderValidWhenHeaderStartsWithWrongPrefix
    • willReturnTrueDuringIsAuthHeaderValidWhenHeaderIsValid
  • JwtService.java
    • canGetSigningKey
    • canGenerateToken
    • willThrowValidateTokenWhenTokenIsNotJwt
    • willThrowValidateTokenWhenTokenUsesWrongSigningKey
    • willThrowValidateTokenWhenTokenIsExpired
    • canValidateToken
Cache Package
  • CacheDao.java
    • canSet
    • canGet
    • canDelete
  • CacheService.java
    • willReturnNullDuringGetWhenKeyNotFound
    • canGetValueUsingClazz
    • canGetValueUsingTypeReference
    • willReturnDuringSetWhenDataIsNull
    • canSet
    • canDelete
Post Package
  • PostService.java
    • canGetAllPostsWhenCacheHit
    • canGetAllPosts
    • willThrowUpdatePostWhenPostNotFound
    • canUpdatePost
    • willThrowDeletePostWhenNotFound
    • canDeletePost
  • PostUtil.java
    • willThrowConstructPostWhenTextHasNoTitle
    • willThrowConstructPostWhenTextHasNoContent
    • canConstructPost
    • willThrowGetImageWhenMultipartFileIsNull
    • willThrowGetImageWhenMultipartFileIsEmpty
    • willThrowGetImageWhenMultipartFileHasSizeZero
    • willThrowGetImageWhenMultipartFileHasInvalidFileExtension
    • willThrowGetImageWhenMultipartFileHasInvalidContentType
    • canGetImage
Health Package
  • HealthService.java
    • canGetHealthWithDatabasesUp
    • canGetHealthWithDatabasesDown
    • canGetHealthWithMysqlUpAndRedisDown
    • canGetHealthWithMysqlDownAndRedisUp
  • HealthUtil.java
    • canGetUptime
    • canGetMysqlUpStatus
    • canGetMysqlDownStatus
    • canGetRedisUpStatus
    • canGetRedisDownStatus
Util Package
  • StringUtil.java
    • willReturnFalseDuringIsStringValidWhenStringIsNull
    • willReturnFalseDuringIsStringValidWhenStringIsBlank
    • willReturnFalseDuringIsStringValidWhenStringIsEmpty
    • willReturnTrueDuringIsStringValidWhenStringIsValid
  • DateUtil.java
    • canGetTotalHours
    • canGetRemainingMinutes
    • canGetRemainingSeconds
    • canGetRemainingMillis

Integration Tests

Integration Tests

Deployment

Deployed using DigitalOcean + Vercel.

MySQL on Ubuntu
  1. Install MySQL: https://ubuntu.com/server/docs/install-and-configure-a-mysql-server

  2. Login to MySQL and create a new user, database, and grant privileges.

sudo mysql
CREATE USER '<USERNAME>'@'%' IDENTIFIED BY '<PASSWORD>';
CREATE DATABASE film_blog;
GRANT ALL PRIVILEGES ON film_blog.* TO '<USERNAME>'@'%';
FLUSH PRIVILEGES;
  1. Initialize the database with tables.
USE film_blog;
# source all migration code from ./backend/java/src/main/resources/db/migration
Redis on Ubuntu
  1. Install Redis: https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/

  2. Generate a new Redis password.

openssl rand -base64 512
  1. Edit the Redis config change the password.
redis-cli
CONFIG SET requirepass <password>
Backend Deployment
  1. Install Nginx: https://ubuntu.com/tutorials/install-and-configure-nginx#1-overview

  2. Install Certbot and follow its instructions for Nginx: https://certbot.eff.org/

  3. Configure Nginx.

sudo vi /etc/nginx/sites-enabled/<domain>

Paste the following:

server {
    listen 80;
    server_name <domain>;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name <domain>;

    ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/<domain>/chain.pem;
    
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
  1. Ensure DNS settings are configured properly.
Github Actions CI/CD Secrets
  1. Navigate to the GitHub repository, click Settings. Under Security, click Secrets and variables and Actions.

  2. Set the following secrets:

Set ADMIN_PW to your secure, hashed password for logging into the admin platform.

Set JWT_SECRET_KEY to your JWT signing key.

Set SPRING_DATASOURCE_PASSWORD to the MySQL user password.

Set SPRING_DATASOURCE_USERNAME to the MySQL user username.

Set SPRING_DATA_REDIS_PASSWORD to the Redis server authentication password.

Set SSH_HOST to the IP address of the EC2 instance hosting the Spring Boot app.

Set SSH_KEY to the content in the keypair that authorizes SSH connections to the EC2 instance hosting the Spring Boot app.

Set TEST_ADMIN_PW to a secure, hashed password for logging into the admin platform for integration tests only.

About

A platform for writing, publishing, and showcasing essays on some films I like.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published