Skip to content

Commit

Permalink
Merge branch 'feat/test' into stablization
Browse files Browse the repository at this point in the history
  • Loading branch information
Douglasj02 authored Sep 30, 2024
2 parents a33b195 + b2ab5f9 commit 866bdb6
Show file tree
Hide file tree
Showing 29 changed files with 314 additions and 193 deletions.
19 changes: 19 additions & 0 deletions Backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
"jest --coverage": "jest",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start": "cross-env NODE_ENV=development nest start",
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"start:prod": "cross-env NODE_ENV=production nest start --watch",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
Expand Down Expand Up @@ -54,6 +54,7 @@
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"coveralls": "^3.1.1",
"cross-env": "^7.0.3",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
Expand Down
2 changes: 1 addition & 1 deletion Backend/src/auth/controller/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class AuthController {
if (accessToken && refreshToken) {
try {
await this.authService.setSession(accessToken, refreshToken);
res.redirect(303, "http://localhost:4200/home");
res.redirect(303, "https://echo-bm8z.onrender.com/home");
} catch (error) {
console.error("Error setting session:", error);
res.status(500).send("Internal Server Error");
Expand Down
25 changes: 16 additions & 9 deletions Backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,32 @@ async function bootstrap() {
const app = await NestFactory.create(AppModule);
const configService = app.get(ConfigService);

// Enable CORS and configure origin from environment variable or default to localhost
// Define allowed origins as an array
const allowedOrigins = [
'https://echo-bm8z.onrender.com',
'http://localhost:4200'
];

// Enable CORS with dynamic origin checking
app.enableCors({
origin: configService.get<string>('CORS_ORIGIN', 'http://localhost:4200'),
origin: (origin, callback) => {
if (!origin) return callback(null, true);

if (allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
methods: "GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS",
credentials: true,
});

// Set global prefix for API
app.setGlobalPrefix('api');

// Use Render's assigned PORT environment variable, fallback to 3000 if not set
const port = configService.get<number>('PORT', 3000);

// Start the NestJS app
await app.listen(port);

// Log the application URL
console.log(`Application is running on: ${await app.getUrl()}`);
}

// Bootstrap the application
bootstrap();
81 changes: 58 additions & 23 deletions Backend/src/supabase/services/supabase.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,101 @@ import { AuthService } from "../../auth/services/auth.service";
import * as crypto from "crypto";

@Injectable()
export class SupabaseService {
export class SupabaseService
{
protected encryptionKey: Buffer;

constructor() {
constructor()
{
this.encryptionKey = Buffer.from(encryptionKey, "base64");
}

// This method is used to sign in with OAuth.using the given provider.
async signinWithOAuth(providerName: string) {
async signinWithOAuth(providerName: string)
{
const supabase = createSupabaseClient();
let scope: string = "";
if (providerName === "spotify") {
let redirectTo: string;

if (providerName === "spotify")
{
scope = "streaming user-read-email user-read-private user-read-recently-played user-read-playback-state user-modify-playback-state user-library-read user-top-read";
}

if (process.env.NODE_ENV === "production")
{
redirectTo = "https://echo-bm8z.onrender.com/login"; // Production URL
}
else
{
redirectTo = "http://localhost:4200/auth/callback"; // Development URL
}

const { data, error } = await supabase.auth.signInWithOAuth({
provider: providerName,
options: {
redirectTo: "http://localhost:4200/auth/callback",
redirectTo,
scopes: scope
}
});
if (error) {

if (error)
{
throw new Error(error.message);
}
return data.url;
}

// This method is used to exchange the code (returned by a provider) for a session (from Supabase).
async exchangeCodeForSession(code: string) {
async exchangeCodeForSession(code: string)
{
const supabase = createSupabaseClient();
const { error } = await supabase.auth.exchangeCodeForSession(code);
if (error) {
if (error)
{
throw new Error(error.message);
}
}

// This method is used to handle tokens from Spotify and store them in the Supabase user_tokens table.
async handleSpotifyTokens(accessToken: string, refreshToken: string, providerToken: string, providerRefreshToken: string) {
if (!(accessToken && refreshToken && providerToken && providerRefreshToken)) {
return {message: "Error occurred during OAuth Sign In while processing tokens - please try again."}
async handleSpotifyTokens(accessToken: string, refreshToken: string, providerToken: string, providerRefreshToken: string)
{
if (!(accessToken && refreshToken && providerToken && providerRefreshToken))
{
return { message: "Error occurred during OAuth Sign In while processing tokens - please try again." };
}
const supabase = createSupabaseClient();
const { error } = await supabase.auth.setSession({ access_token: accessToken, refresh_token: refreshToken });
if (error) {
if (error)
{
console.error("Error setting session:", error);
return;
}

const { data, error: userError } = await supabase.auth.getUser();

if (userError) {
if (userError)
{
console.error("Error retrieving user:", userError);
return;
}

if (data.user) {
if (data.user)
{
const userId: string = data.user.id;
await this.insertTokens(userId, this.encryptToken(providerToken), this.encryptToken(providerRefreshToken));
} else {
}
else
{
console.log("No user data available.");
}
}

// This method is used to insert tokens into the user_tokens table.
async insertTokens(userId: string, providerToken: string, providerRefreshToken: string): Promise<void> {
if (!(userId && providerToken && providerRefreshToken)) {
async insertTokens(userId: string, providerToken: string, providerRefreshToken: string): Promise<void>
{
if (!(userId && providerToken && providerRefreshToken))
{
return;
}
const encryptedProviderToken = providerToken;
Expand All @@ -89,15 +118,17 @@ export class SupabaseService {
onConflict: "user_id"
});

if (error) {
if (error)
{
console.error("Error updating or inserting token data:", error);
throw new Error("Failed to update or insert tokens");
}
return data;
}

// This method is used to encrypt a token.
encryptToken(token: string): string {
encryptToken(token: string): string
{
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv("aes-256-cbc", this.encryptionKey, iv);
let encrypted = cipher.update(token, "utf8", "base64");
Expand All @@ -106,7 +137,8 @@ export class SupabaseService {
}

// This method is used to decrypt a token.
decryptToken(encryptedToken: string): string {
decryptToken(encryptedToken: string): string
{
const [iv, encrypted] = encryptedToken.split(":");
const decipher = crypto.createDecipheriv("aes-256-cbc", this.encryptionKey, Buffer.from(iv, "base64"));
let decrypted = decipher.update(encrypted, "base64", "utf8");
Expand All @@ -115,7 +147,7 @@ export class SupabaseService {
}

// This method is used to retrieve tokens from the user_tokens table.

async retrieveTokens(userId: string) {
const supabase = createSupabaseClient();
const { data, error } = await supabase
Expand All @@ -124,17 +156,20 @@ export class SupabaseService {
.eq("user_id", userId)
.single();

if (error) {
if (error)
{
console.error("Error retrieving tokens:", error);
throw new Error("Failed to retrieve tokens");
}

if (data) {
if (data)
{
const providerToken = this.decryptToken(data.encrypted_provider_token);
const providerRefreshToken = this.decryptToken(data.encrypted_provider_refresh_token);
return { providerToken, providerRefreshToken };
}

return null;
}

}
35 changes: 23 additions & 12 deletions Frontend/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,25 @@
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/frontend",
"index": "src/index.html",
"browser": "src/main.ts",
"main": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets",
"src/manifest.webmanifest"
"src/manifest.webmanifest",
"src/static.json"
],
"styles": [
"src/styles/styles.css"
],
"scripts": [],
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
"entry": "server.ts"
}
"scripts": []
},
"configurations": {
"production": {
Expand All @@ -50,12 +46,26 @@
}
],
"outputHashing": "all",
"serviceWorker": "ngsw-config.json"
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"extractLicenses": true,
"sourceMap": false,
"namedChunks": false,
"vendorChunk": true,
"commonChunk": true,
"serviceWorker": true
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
"sourceMap": true,
"namedChunks": true,
"serviceWorker": false
}
},
"defaultConfiguration": "production"
Expand Down Expand Up @@ -92,7 +102,8 @@
"assets": [
"src/favicon.ico",
"src/assets",
"src/manifest.webmanifest"
"src/manifest.webmanifest",
"src/static.json"
],
"styles": [
"src/styles/tailwind.css",
Expand Down
17 changes: 17 additions & 0 deletions Frontend/ngsw-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,22 @@
]
}
}
],
"dataGroups": [
{
"name": "api-requests",
"urls": [
"https://echo-backend-1s8m.onrender.com/api/auth/**",
"https://echo-backend-1s8m.onrender.com/api/spotify/**",
"https://echo-backend-1s8m.onrender.com/api/youtube/**",
"https://echo-backend-1s8m.onrender.com/api/search/**"
],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 100,
"maxAge": "1d",
"timeout": "10s"
}
}
]
}
Loading

0 comments on commit 866bdb6

Please sign in to comment.