Skip to content

Commit

Permalink
Merge pull request #45 from dheffer/backend-lambda
Browse files Browse the repository at this point in the history
Majority of Lambda functions completed
  • Loading branch information
dheffer authored Apr 13, 2024
2 parents 8f960fe + fa64da2 commit 83b10a2
Show file tree
Hide file tree
Showing 44 changed files with 1,067 additions and 8 deletions.
38 changes: 38 additions & 0 deletions .github/workflows/deploy-to-lambda.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Deploy to AWS Lambda
on:
release:
types: [published]

defaults:
run:
working-directory: ./backend-lambda
jobs:
deploy_source:
name: Build and deploy
strategy:
matrix:
node-version: [21.x]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Use node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}

- name: npm install
run: |
cd deleteMaintenanceHistory
npm install
- name: zip
uses: montudor/[email protected]
with:
args: zip -qq -r ./bundle.zip ./
- name: default deploy
uses: appleboy/lambda-action@master
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws_region: eu-west-1
function_name: my-function
zip_file: bundle.zip
2 changes: 1 addition & 1 deletion .github/workflows/deploy-to-s3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ jobs:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
SOURCE_DIR: "./frontend/build"
SOURCE_DIR: "./frontend/build"
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ node_modules
backend/.env
.env
Project_Default.xml
package-lock.json
package-lock.json

# ignore any zip files
*.zip
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Driveline is a web application designed to streamline and automate the process o

## Key Features:
- [x] **OAuth Login Page:** Utilizes OAuth for secure login, enabling users to create profiles seamlessly.
- [ ] **Vehicle Management:** Users can upload, edit, and remove vehicles from their Garage with ease.
- [ ] **Service History & Upcoming Services:** Users can view detailed service history, upcoming maintenance tasks, and general vehicle information when selecting a vehicle in their garage.
- [x] **Vehicle Management:** Users can upload, edit, and remove vehicles from their Garage with ease.
- [x] **Service History & Upcoming Services:** Users can view detailed service history, upcoming maintenance tasks, and general vehicle information when selecting a vehicle in their garage.
- [ ] **Settings Configuration:** The settings page allows users to customize their profile and app settings, including preferences like light & dark mode

## Technologies Used:
Expand Down
23 changes: 23 additions & 0 deletions backend-lambda/OAuthGetUrl/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { google } from 'googleapis'

export const handler = async (event, context) => {
const url = getGoogleAuthUrl();

return { url };
};

const getGoogleAuthUrl = () => {
const oauth = new google.auth.OAuth2(
process.env.CLIENT_ID,
process.env.CLIENT_SECRET,
process.env.OAUTH_CALLBACK_URL
);
return oauth.generateAuthUrl({
access_type: 'offline',
prompt: 'consent',
scope: [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
],
});
};
5 changes: 5 additions & 0 deletions backend-lambda/OAuthGetUrl/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"dependencies": {
"googleapis": "^134.0.0"
}
}
92 changes: 92 additions & 0 deletions backend-lambda/OAuthProcessing/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { google } from 'googleapis';
import { MongoClient, ServerApiVersion } from "mongodb";
import 'dotenv/config';
import jwt from 'jsonwebtoken';

export const handler = async (event, context) => {

const JWTSecret = process.env.JWT_SECRET;
const oauthClient = new google.auth.OAuth2(
process.env.CLIENT_ID,
process.env.CLIENT_SECRET,
process.env.OAUTH_CALLBACK_URL
);
const { code } = event['queryStringParameters'];
const { tokens } = await oauthClient.getToken(code);
const url = getAccessAndBearerTokenUrl(tokens.access_token);

const myHeaders = new Headers();
const bearerToken = "Bearer "+tokens.id_token;
myHeaders.append("Authorization", bearerToken);

const reqOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
return await fetch(url, reqOptions)
.then(response => response.json())
.then(res => {
let user = updateOrCreateUserFromOAuth(res);
const token = jwt.sign( {"name":user.name, "email":user.email}, JWTSecret, {expiresIn: '2d'} );
return {
statusCode: 200,
headers: {
"Location": `${process.env.APP_URL}/login?token=${token}`
}
};
}).catch(err => {
return {
statusCode: 500,
body: JSON.stringify({ message: `Internal Server Error: ${err.message}` })
};
});
};

const updateOrCreateUserFromOAuth = async (user) => {
const uri = process.env.MONGO_URI;
const client = new MongoClient(uri, {
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true,
}
}
);
const { name, email } = user;

return client.connect()
.then(async () => {
const database = client.db("vehicleDB");
const users = database.collection("users");
const existingUser = await users.findOne({email})
if( existingUser ) {
const result = await users.findOneAndUpdate({email},
{ $set: {name, email}},
{ returnDocument: "after"}
);
return {
statusCode: 200,
body: JSON.stringify(result.value)
};
}
else {
const result = await users.insertOne( {email, name});
return {
statusCode: 200,
body: JSON.stringify(result.value)
};
}
}).catch(err => {
return {
statusCode: 500,
body: JSON.stringify({ message: `Internal Server Error: ${err.message}` })
};
}).finally(() => client.close());
};



const getAccessAndBearerTokenUrl = (access_token) => {
return `https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token=${access_token}`;
};
8 changes: 8 additions & 0 deletions backend-lambda/OAuthProcessing/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"dependencies": {
"dotenv": "^16.4.5",
"googleapis": "^134.0.0",
"jsonwebtoken": "^9.0.2",
"mongodb": "^6.5.0"
}
}
46 changes: 46 additions & 0 deletions backend-lambda/deleteMaintenanceHistory/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {MongoClient, ServerApiVersion} from "mongodb";
import 'dotenv/config';

export const handler = async (event, context) => {

const uri = process.env.MONGO_URI;
const client = new MongoClient(uri, {
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true
}
});
const config_id = event['config_id'];
const email = event.headers['email'];
const { type, date, maintenance, cost } = event.body;

return client.connect()
.then(async () => {
const database = client.db("vehicleDB");
const garage = database.collection("user_vehicle_info");
await garage.updateOne(
{
email: email,
config_id: parseInt(config_id)
},
{$pull: { completed_maintenance: {
type: type,
date: date,
maintenance: maintenance,
cost: cost
}
}
}
);
return {
statusCode: 200,
body: JSON.stringify({message: `History deleted: ${type} ${date} ${maintenance} ${cost} deleted from config ${config_id}`})
};
}).catch(err => {
return {
statusCode: 500,
body: JSON.stringify({ message: `Internal Server Error: ${err.message}` })
};
}).finally(() => client.close());
};
6 changes: 6 additions & 0 deletions backend-lambda/deleteMaintenanceHistory/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"dependencies": {
"dotenv": "^16.4.5",
"mongodb": "^6.5.0"
}
}
45 changes: 45 additions & 0 deletions backend-lambda/deleteUserVehicle/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {MongoClient, ServerApiVersion} from "mongodb";
import 'dotenv/config';

export const handler = async (event, context) => {

const uri = process.env.MONGO_URI;
const client = new MongoClient(uri, {
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true
}
});
const config_id = event['config_id'];
const email = event.headers['email'];

return client.connect()
.then(async () => {
const database = client.db("vehicleDB");
const garage = database.collection("user_garage");
await garage.updateOne(
{ email: email },
{ $pull: { vehicle_config_ids: config_id } }
);
return {
statusCode: 200,
body: JSON.stringify({message: `Vehicle with config ${config_id} deleted from garage`})
};
}).then(async () => {
const database = client.db("vehicleDB");
const vehicInfo = database.collection("user_vehicle_info");
await vehicInfo.deleteOne(
{ email: email, config_id: config_id }
);
return {
statusCode: 200,
body: JSON.stringify({message: `Vehicle with config ${config_id} deleted from garage`})
};
}).catch(err => {
return {
statusCode: 500,
body: JSON.stringify({ message: `Internal Server Error: ${err.message}` })
};
}).finally(() => client.close());
};
6 changes: 6 additions & 0 deletions backend-lambda/deleteUserVehicle/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"dependencies": {
"dotenv": "^16.4.5",
"mongodb": "^6.5.0"
}
}
44 changes: 44 additions & 0 deletions backend-lambda/getConfigId/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {MongoClient, ServerApiVersion} from "mongodb";
import 'dotenv/config';

export const handler = async (event, context) => {

const uri = process.env.MONGO_URI;
const client = new MongoClient(uri, {
serverApi: {
version: ServerApiVersion.v1,
strict: true,
deprecationErrors: true,
}
}
);
const year = event['year'];
const make = event['make'];
const model = event['model'];
const engine = event['engine'];
const transmission = event['transmission'];

return client.connect()
.then(async () => {
const database = client.db("vehicleDB");
const config = database.collection("configurations");
const vehicle_config = await config.findOne({
year: parseInt(year),
make: make,
model: model,
engine: engine,
transmission: transmission
});
return vehicle_config.map(config => config.config_id);
}).then(config => {
return {
statusCode: 200,
body: JSON.stringify(config)
};
}).catch(err => {
return {
statusCode: 500,
body: JSON.stringify({ message: `Internal Server Error: ${err.message}` })
};
}).finally(() => client.close());
};
6 changes: 6 additions & 0 deletions backend-lambda/getConfigId/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"dependencies": {
"dotenv": "^16.4.5",
"mongodb": "^6.5.0"
}
}
Loading

0 comments on commit 83b10a2

Please sign in to comment.