Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion API/app/Http/Controllers/GoogleAuthenticationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,37 @@ public function handleLogin(Request $request): Response
if ($googleId) {
$request->merge(['user_id' => $googleId]); // Add user_id to request

Log::info("User validated, setting cookie in request and returning...");
Log::info("User validated, setting cookie or token in request and returning...");

// This should work (consult official documentation for more)
$user = User::where('user_id', $googleId)->first();
if ($user) {
if (DEBUG_MODE) {
Log::debug("Logging in user: " . print_r($googleId, true));
}

// Determine the desired auth mode (cookie or token)
if ( $request->has('authMode') ) {
if ( $request->authMode === 'token' ) {
Log::info('Token mode chosen');
// Token-based authentication was requested by the user
// (THIS SHOULD ONLY BE USED IN THE FRONTEND FOR DEV/TESTING, NOT ON DEPLOYMENT!)
$token = $user->createToken('authToken')->plainTextToken;

return response()->json([
'token' => $token,
'status' => 'success'
], 200);
}
}
//Auth::login($user);
Auth::guard('web')->login($user);
} else {
Log::info("CAN'T LOGIN USER; IT'S NULL");
}

Log::info('Cookie mode chosen');


// Allow original request to proceed
return response()->json(['status' => 'success']);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
public function up(): void
{
Schema::table('personal_access_tokens', function (Blueprint $table) {
$table->string('tokenable_id')->change();
});
}

public function down(): void
{
Schema::table('personal_access_tokens', function (Blueprint $table) {
$table->integer('tokenable_id')->change();
});
}
};
29 changes: 29 additions & 0 deletions API/docker/development/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
version: '3.8'
services:
nginx:
build:
context: ../../ # Laravel Project root (API folder)
dockerfile: docker/development/nginx/Dockerfile
image: velocities/mynginx:latest # Use the remote image
volumes:
- /etc/letsencrypt:/etc/letsencrypt # Mount live certs into the container
- ./docker/development/nginx/conf.d:/etc/nginx/conf.d # Assuming your nginx configs are in ./docker/nginx/conf.d
- ./docker/development/nginx/snippets:/etc/nginx/snippets # If you have snippets to include
ports:
- "8080:80" # Map host port 8080 to container port 80
- "8443:443" # Map host port 8443 to container port 443
depends_on:
- app
app:
build:
context: ../../ # Laravel Project root (API folder)
dockerfile: docker/development/php/Dockerfile
image: velocities/myapp:latest # Use the remote image
volumes:
- ./database:/var/www/SpeedCart/API/database
- ./storage:/var/www/SpeedCart/API/storage
- ./bootstrap/cache:/var/www/SpeedCart/API/bootstrap/cache
- ./:/var/www/SpeedCart/API # Mount your source code (should make container restart upon save to code)
restart: always # Ensures the container restarts automatically if it stops
expose:
- "9000"
File renamed without changes.
23 changes: 23 additions & 0 deletions API/docker/development/nginx/conf.d/default.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
server {
listen 80;
server_name localhost;

root /var/www/SpeedCart/API/public;

index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
include fastcgi_params;
fastcgi_pass app:9000; # Match your app service name and port
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

location ~ /\.ht {
deny all;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ RUN docker-php-ext-install pdo pdo_sqlite mbstring exif pcntl bcmath gd intl zip
# into your Docker image, making Composer available for dependency management)
COPY --from=composer:2.1.3 /usr/bin/composer /usr/bin/composer

# Copy existing application directory contents from working directory
# Copy existing application directory contents from API directory
# on host to /var/www/SpeedCart/API in the container
COPY . /var/www/SpeedCart/API
COPY ../../ /var/www/SpeedCart/API

# Copy existing application directory permissions
COPY --chown=www-data:www-data . /var/www/SpeedCart/API
COPY --chown=www-data:www-data ../../ /var/www/SpeedCart/API

# Change current user to www-data (used by web servers to improve security)
USER www-data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ services:
nginx:
build:
context: .
dockerfile: docker/nginx/Dockerfile
dockerfile: nginx/Dockerfile
image: velocities/mynginx:latest # Use the remote image
volumes:
- /etc/letsencrypt:/etc/letsencrypt # Mount live certs into the container
- ./docker/nginx/conf.d:/etc/nginx/conf.d # Assuming your nginx configs are in ./docker/nginx/conf.d
- ./docker/nginx/snippets:/etc/nginx/snippets # If you have snippets to include
- ./nginx/conf.d:/etc/nginx/conf.d # Assuming your nginx configs are in ./docker/nginx/conf.d
- ./nginx/snippets:/etc/nginx/snippets # If you have snippets to include
ports:
- "8080:80" # Map host port 8080 to container port 80
- "8443:443" # Map host port 8443 to container port 443
Expand All @@ -17,11 +17,11 @@ services:
app:
build:
context: .
dockerfile: docker/php/Dockerfile
dockerfile: php/Dockerfile
image: velocities/myapp:latest # Use the remote image
volumes:
- ./database:/var/www/SpeedCart/API/database
- ./storage:/var/www/SpeedCart/API/storage
- ./bootstrap/cache:/var/www/SpeedCart/API/bootstrap/cache
- ../../database:/var/www/SpeedCart/API/database
- ../../storage:/var/www/SpeedCart/API/storage
- ../../bootstrap/cache:/var/www/SpeedCart/API/bootstrap/cache
expose:
- "9000"
10 changes: 10 additions & 0 deletions API/docker/production/nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# nginx Dockerfile

FROM nginx:alpine

WORKDIR /etc/nginx

# No need to COPY SSL certificates or other configuration info

# Expose ports
EXPOSE 80 443
5 changes: 5 additions & 0 deletions API/docker/production/nginx/snippets/fastcgi-php.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
50 changes: 50 additions & 0 deletions API/docker/production/php/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Use the official PHP image as a base image
FROM php:8.2-fpm

# Set working directory (all subsequent commands will be run in this directory)
WORKDIR /var/www/SpeedCart/API

# Install system dependencies
RUN apt-get update && apt-get install -y \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
jpegoptim optipng pngquant gifsicle \
vim \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip \
libzip-dev \
sqlite3 \
libsqlite3-dev \
--no-install-recommends

# Clear cache (This cleans up the package cache to reduce the size of the Docker image)
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install PHP extensions required by Laravel
RUN docker-php-ext-install pdo pdo_sqlite mbstring exif pcntl bcmath gd intl zip soap

# Install Composer (copies the composer binary from the latest Composer image
# into your Docker image, making Composer available for dependency management)
COPY --from=composer:2.1.3 /usr/bin/composer /usr/bin/composer

# Copy existing application directory contents from API directory
# on host to /var/www/SpeedCart/API in the container
COPY ../../ /var/www/SpeedCart/API

# Copy existing application directory permissions
COPY --chown=www-data:www-data ../../ /var/www/SpeedCart/API

# Change current user to www-data (used by web servers to improve security)
USER www-data

# Expose port 9000 (the default port for PHP-FPM to listen on) and start php-fpm server
# (Even if you are using Nginx as a reverse proxy, PHP-FPM will still need to be exposed
# internally within the Docker network, which is why we need EXPOSE 9000)
EXPOSE 9000
CMD ["php-fpm"]
4 changes: 2 additions & 2 deletions API/routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@
Route::post('/shopping-lists', [ShoppingListController::class, 'store'])
->middleware('auth:sanctum');

// Route for retrieving all shopping list titles (used for Dashboard page)
// Route for retrieving all owned shopping list titles (used for Dashboard page)
Route::get('/shopping-lists', [ShoppingListController::class, 'getUserShoppingLists'])
->middleware('auth:sanctum');

// Route for retrieving all shopping list titles (used for Dashboard page)
// Route for retrieving all shared shopping list titles (used for Dashboard page)
Route::get('/shopping-lists/shared', [ShoppingListController::class, 'getSharedShoppingLists'])
->middleware('auth:sanctum');

Expand Down
3 changes: 2 additions & 1 deletion Frontend/shared/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
API_DOMAIN=api.speedcartapp.com
API_PORT=8443
API_PORT=8443
TESTING_MODE=false
1 change: 1 addition & 0 deletions Frontend/shared/generate-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ dotenv.config();
const config = {
API_DOMAIN: process.env.API_DOMAIN,
API_PORT: process.env.API_PORT,
TESTING_MODE: process.env.TESTING_MODE,
};

// Write the config to a file in the shared directory
Expand Down
1 change: 1 addition & 0 deletions Frontend/shared/src/constants/BaseUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ const API_PORT = config.API_PORT;

// This can be reused for all backend interactions
export const BASE_URL: string = `https://${API_DOMAIN}:${API_PORT}`;
export const TESTING_MODE: boolean = config.TESTING_MODE === 'true';
33 changes: 33 additions & 0 deletions Frontend/shared/src/functions/backendAuthFetch/backendAuthFetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { BASE_URL, TESTING_MODE } from '@constants';

/**
* A utility function for making authenticated API requests to the backend.
* Automatically includes credentials and Authorization headers when needed.
*/
export const backendAuthFetch = async (endpoint: string, options: RequestInit = {}, authToken = '') => {
const headersInit: HeadersInit = {
'Content-Type': 'application/json',
Accept: 'application/json',
...options.headers,
};

const headers: Headers = new Headers(headersInit);

if (TESTING_MODE && authToken !== '') {
headers.set("Authorization", `Bearer ${authToken}`);
}

const fetchOptions: RequestInit = {
...options,
headers,
credentials: 'include',
};

const response = await fetch(`${BASE_URL}${endpoint}`, fetchOptions);

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}

return response;
};
1 change: 1 addition & 0 deletions Frontend/shared/src/functions/backendAuthFetch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { backendAuthFetch } from './backendAuthFetch';
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { BASE_URL } from '@constants';
import { GroceryItem } from '@types';
import { backendAuthFetch } from "../backendAuthFetch";
import { BackendFunction } from "@types";

export const createGroceryItem = async (item: GroceryItem) => {
return fetch(`${BASE_URL}/grocery-items`, {
export const createGroceryItem: BackendFunction<
{ item: GroceryItem },
Response
> = async (authToken = '', { item }) => {

return backendAuthFetch(
`/grocery-items`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(item)
});
body: JSON.stringify(item),
},
authToken
);
};
32 changes: 19 additions & 13 deletions Frontend/shared/src/functions/createShareLink/createShareLink.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { BASE_URL } from '@constants';
import { backendAuthFetch } from "../backendAuthFetch";
import { BackendFunction } from "@types";

export const createShareLink = async (shareListId: string, permissions: any) => {
return fetch(`${BASE_URL}/share/${shareListId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(
permissions
),
});
}
export const createShareLink: BackendFunction<
{ shareListId: string; permissions: string },
Response
> = async (
authToken = '',
{shareListId,
permissions}
) => {
return backendAuthFetch(
`/share/${shareListId}`,
{
method: 'POST',
body: JSON.stringify(permissions),
},
authToken
);
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import { BASE_URL } from '@constants';
import { BASE_URL, TESTING_MODE } from '@constants';
import { BackendFunction } from "@types";

export const createSharingPermissions: BackendFunction<
{token: string},
Response
>= async (authToken = '', {token}) => {
const headers: any = {
'Content-Type': 'application/json',
"Accept" : "application/json"
};

if (TESTING_MODE && authToken !== '') {
headers['Authorization'] = `Bearer ${authToken}`;
}

export const createSharingPermissions = async (token: string) => {
return fetch(`${BASE_URL}/share/${token}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
headers: headers,
credentials: 'include'
});
}
Loading