Implement backend API and database services in Docker setup
- Added a new `api` service for the NestJS backend, including health checks and dependencies on PostgreSQL, Redis, and MinIO. - Introduced PostgreSQL and Redis services with health checks and configurations for data persistence. - Added MinIO for S3-compatible object storage and a one-shot service to initialize required buckets. - Updated the Nginx configuration to proxy requests to the new backend API and MinIO storage. - Enhanced the Dockerfile to support the new API environment variables and configurations. - Updated the `package.json` and `package-lock.json` to include new dependencies for QR code generation and other utilities. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
60
backend/src/subscriptions/guards/pay-with-flash.guard.ts
Normal file
60
backend/src/subscriptions/guards/pay-with-flash.guard.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
Injectable,
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common';
|
||||
import * as jwt from 'jsonwebtoken';
|
||||
import { SubscriptionType } from '../enums/types.enum';
|
||||
|
||||
@Injectable()
|
||||
export class PayWithFlashAuthGuard implements CanActivate {
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const authHeader: string | undefined = request.headers.authorization;
|
||||
const token = (authHeader ?? '').split(' ')[1];
|
||||
|
||||
const { url } = request;
|
||||
|
||||
// get the type from the URL
|
||||
const type: SubscriptionType = url.split('/').pop() as SubscriptionType;
|
||||
|
||||
if (!token) {
|
||||
throw new UnauthorizedException('No token provided');
|
||||
}
|
||||
|
||||
let secret: string;
|
||||
switch (type) {
|
||||
case 'rss-addon': {
|
||||
secret = process.env.FLASH_JWT_SECRET_RSS_ADDON;
|
||||
break;
|
||||
}
|
||||
case 'verification-addon': {
|
||||
secret = process.env.FLASH_JWT_SECRET_VERIFICATION_ADDON;
|
||||
break;
|
||||
}
|
||||
case 'enthusiast': {
|
||||
secret = process.env.FLASH_JWT_SECRET_ENTHUSIAST;
|
||||
break;
|
||||
}
|
||||
case 'film-buff': {
|
||||
secret = process.env.FLASH_JWT_SECRET_FILM_BUFF;
|
||||
break;
|
||||
}
|
||||
case 'cinephile': {
|
||||
secret = process.env.FLASH_JWT_SECRET_CINEPHILE;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new UnauthorizedException('Invalid subscription type');
|
||||
}
|
||||
}
|
||||
try {
|
||||
const decoded = jwt.verify(token, secret);
|
||||
request.user = decoded; // Attach user information to the request
|
||||
return true;
|
||||
} catch {
|
||||
throw new UnauthorizedException('Invalid token');
|
||||
}
|
||||
}
|
||||
}
|
||||
41
backend/src/subscriptions/guards/subscription.guard.ts
Normal file
41
backend/src/subscriptions/guards/subscription.guard.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { Subscriptions } from '../decorators/subscriptions.decorator';
|
||||
import { User } from 'src/users/entities/user.entity';
|
||||
import { Subscription } from '../entities/subscription.entity';
|
||||
|
||||
@Injectable()
|
||||
export class SubscriptionsGuard implements CanActivate {
|
||||
constructor(private reflector: Reflector) {}
|
||||
|
||||
canActivate(context: ExecutionContext): boolean {
|
||||
const subscriptions = this.reflector.get(
|
||||
Subscriptions,
|
||||
context.getHandler(),
|
||||
);
|
||||
if (!subscriptions) {
|
||||
return true;
|
||||
}
|
||||
const enabledSubscriptions = new Set(subscriptions);
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const user: User = request.user;
|
||||
|
||||
if (subscriptions.includes('filmmaker')) return !!user.filmmaker;
|
||||
if (this.hasActiveSubscription(user.subscriptions)) {
|
||||
return user.subscriptions.some((sub) =>
|
||||
enabledSubscriptions.has(sub.type),
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
hasActiveSubscription(subscriptions: Subscription[]) {
|
||||
if (subscriptions.length === 0) return false;
|
||||
const latestSubscription = subscriptions[0];
|
||||
const currentDate = new Date();
|
||||
// get subscription expiration date
|
||||
const subscriptionExpirationDate = latestSubscription.periodEnd;
|
||||
// check if subscription is active
|
||||
return currentDate < subscriptionExpirationDate;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user