Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
4dae3ad
added user models
jeramyleon Jul 31, 2025
fc7abb9
added echoes model
jeramyleon Jul 31, 2025
1eb36d2
created multiple users in seed for testing purposes and updated table…
jeramyleon Jul 31, 2025
d361c72
issues connecting to database resolved
jeramyleon Jul 31, 2025
7cc241b
changed name attribute to username
jeramyleon Jul 31, 2025
ccbe0fc
get user by id and get all user routes added
jeramyleon Jul 31, 2025
b42f077
Merge pull request #8 from TTP-Team-3/models
aarcher711 Jul 31, 2025
32b34e8
changing database names
jeramyleon Jul 31, 2025
f7d33f6
Merge pull request #9 from TTP-Team-3/models
jeramyleon Jul 31, 2025
612bd5a
addded echo_visibility model so users can customize who can see their…
jeramyleon Aug 1, 2025
525ded4
update some models with references and added echo_recipients model
jeramyleon Aug 1, 2025
b5e3a2a
added tags model
jeramyleon Aug 1, 2025
bbf270d
added echo tags model
jeramyleon Aug 1, 2025
25dc26d
media model created for image/video/audio uploads
jeramyleon Aug 4, 2025
952c8c7
added reports model for user reports
jeramyleon Aug 4, 2025
2053cc9
friends model so users can add one another as friends
jeramyleon Aug 4, 2025
134e426
replies model for user replies to echos and commments
jeramyleon Aug 4, 2025
78f682e
reaction model allows users to have one reaction to an echo
jeramyleon Aug 4, 2025
3d3ebae
done with models, starting associations now
jeramyleon Aug 4, 2025
432ffd7
Merge pull request #19 from TTP-Team-3/models
jeramyleon Aug 4, 2025
4356625
all associations between models completed
jeramyleon Aug 4, 2025
043d8d0
fixed belongsTo to belongsToMany for Echoes <> users associatons
jeramyleon Aug 4, 2025
676401b
added associatons
jeramyleon Aug 6, 2025
3518763
added seed data for echoes
jeramyleon Aug 6, 2025
a472f6a
added echoes data to seed
jeramyleon Aug 6, 2025
a8a0236
added route to get all echoes associated with one user id
jeramyleon Aug 7, 2025
434252c
Merge pull request #21 from TTP-Team-3/associations
jeramyleon Aug 7, 2025
0a67a89
just pulled changes from backend main
aarcher711 Aug 7, 2025
c2c841d
changes
jeramyleon Aug 7, 2025
046a401
updated passwords
aarcher711 Aug 7, 2025
d470a6f
updating passwords on this branch
aarcher711 Aug 7, 2025
c69f017
removed scope attribute from echo_visibility, already present in echo…
jeramyleon Aug 7, 2025
878a90c
Merge pull request #24 from TTP-Team-3/routes-and-seed
jeramyleon Aug 7, 2025
0b09d2c
added echo recipients seed data to test custom echoes
jeramyleon Aug 8, 2025
02fd16b
get echoes by id is finished, may be updated later to reflect changes…
jeramyleon Aug 8, 2025
c576b4f
changes
jeramyleon Aug 11, 2025
437c869
Merge pull request #25 from TTP-Team-3/routes-and-seed
aarcher711 Aug 11, 2025
11ac418
updated echoes model, changed echoes seed data to reflect thosechange…
jeramyleon Aug 11, 2025
2669508
Merge pull request #26 from TTP-Team-3/routes-and-seed
aarcher711 Aug 11, 2025
8d5a9b9
post request for sending friend requests is done
jeramyleon Aug 12, 2025
d3fecc2
added patch route for echoes to update archive status
jeramyleon Aug 12, 2025
58483b7
Implemented echo unlock route with ownership and unlock date validation
jeramyleon Aug 12, 2025
b698757
Implemented echo delete route with existence and ownership validation
jeramyleon Aug 12, 2025
3463bd9
adding comments for requests clarity in echoes
jeramyleon Aug 12, 2025
65af3ff
Merge pull request #29 from TTP-Team-3/routes-and-seed
EmmanuelR21 Aug 12, 2025
d5a0438
chore: Add S3 integration docs and implementation guide
EmmanuelR21 Aug 12, 2025
6ddc219
refactor: Prettier format applied
EmmanuelR21 Aug 12, 2025
6cbda53
did some formatting changes and added routes
heavenwilson Aug 13, 2025
10df9a9
GET friends route updated to find bidirectional friendship pairs
jeramyleon Aug 13, 2025
33be068
refactor: Prettier add trailing commas
EmmanuelR21 Aug 13, 2025
3e39dea
feat: Remove sharp dependency
EmmanuelR21 Aug 13, 2025
20eb8e1
feat: Add image_uuids array field to Echoes model
EmmanuelR21 Aug 13, 2025
91a208d
Implemented PATCH route to accept friend requests, restricting action…
jeramyleon Aug 13, 2025
e66112f
Updated GET route to get user friends and pending friend requests
jeramyleon Aug 13, 2025
82324c9
feat: Add S3 image upload support to echo creation
EmmanuelR21 Aug 13, 2025
c5f7c75
chore: Update S3 documentation with clearer setup instructions, and more
EmmanuelR21 Aug 13, 2025
00d1824
Implemented PATCH route for receivers to block senders on pending fri…
jeramyleon Aug 13, 2025
46c40fb
Implemented DELETE route so users can removed current friends or any …
jeramyleon Aug 13, 2025
a524f28
changes
jeramyleon Aug 13, 2025
93add04
feat: Add signed URLs for echo image model. Succesful GET from S3.
EmmanuelR21 Aug 13, 2025
1f07e40
update GET route
EmmanuelR21 Aug 13, 2025
514800b
Implemented POST route to post replies, only allowed by authenticated…
jeramyleon Aug 13, 2025
b62aea7
Implemented GEt route to find all replies associated with a specific …
jeramyleon Aug 13, 2025
f518556
Implemented DELETE route for users to remove replies on echoes with u…
jeramyleon Aug 13, 2025
7b00126
seed: populate sample replies, including nested replies, for testing …
jeramyleon Aug 13, 2025
e61d7eb
Fixed bugs with replies routes
jeramyleon Aug 13, 2025
38d5fd0
Implemented POST route so users can react to echos using user and rea…
jeramyleon Aug 14, 2025
073a7f9
Implemented GET route to fetch all reactions for an echo
jeramyleon Aug 14, 2025
ae5f052
Mounted reactions router at /reactions and added seed data for reactions
jeramyleon Aug 14, 2025
fd022a1
Implemented GET route to get all tags
jeramyleon Aug 14, 2025
2a4e3db
Seeded database with tags
jeramyleon Aug 14, 2025
77376f5
Merge pull request #30 from TTP-Team-3/routes-and-seed
jeramyleon Aug 14, 2025
60f9d9d
feat: Implement S3 parallel upload and add file size validation, and S3
EmmanuelR21 Aug 15, 2025
d70b33f
chore: Add media table for handling S3 data
EmmanuelR21 Aug 15, 2025
78ad6a2
Merge branch 'main' into pc/switch
jeramyleon Aug 18, 2025
c631629
Merge pull request #31 from TTP-Team-3/pc/switch
jeramyleon Aug 18, 2025
87fcc81
deleted the wrong router when merging, is fixed now
jeramyleon Aug 18, 2025
f02c158
Merge branch 'main' into aws-s3-integration
jeramyleon Aug 18, 2025
c810539
Merge pull request #32 from TTP-Team-3/aws-s3-integration
jeramyleon Aug 18, 2025
aaa89ec
added the neccessary routes needed in order to make the component in …
heavenwilson Aug 18, 2025
bb8a3fc
Merge pull request #33 from TTP-Team-3/routes/friends/users
jeramyleon Aug 19, 2025
c997ba0
added email
EmmanuelR21 Aug 19, 2025
cdc3820
implemeneted email into JWT
EmmanuelR21 Aug 19, 2025
9fc495f
merge from main
EmmanuelR21 Aug 19, 2025
7b7c638
fixed passwordhash not saving correctly
EmmanuelR21 Aug 19, 2025
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
3 changes: 0 additions & 3 deletions .env.example

This file was deleted.

193 changes: 193 additions & 0 deletions api/Amazon_S3_Integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# Reason

I have very little hope I will actually remember the steps I took to complete the Amazon s3 task.

Below is a step by step breakdown of the process, inspired by [this video](https://www.youtube.com/watch?v=eQAIojcArRY&t=996s)

## Quick Setup

If you just want to setup on your local machine S3 access, go to [Bucket Access](#bucket-access) and copy and paste the `.env` variables into your `.env` file. The `ACCESS_KEY` and `SECRET_ACCESS_KEY` and `BUCKET_NAME` are not in this file for _obvious_ reasons(hiding bucket name might just me being paranoid). If the `SECRET_ACCESS_KEY` ends up getting _lost_, then I will have to make a new **IAM** user, so please let me know.

Next install the npm packages if you haven't done this setup before. This way you install the packages in [Express Server File Handling](#express-server-file-handling) and [Amazon S3 SDK](#amazon-s3-sdk).

```bash
npm install
```

Thats it! You can now run requests to the Amazon S3 bucket, and our PostgreSQL DB. If you run into any issues, please reach out to me @EmmanuelR21.

## Bucket Access

1. Our bucket is essentially the storage DB that holds the images and video files. The media files are known as **"Objects"**
2. There is an Amazon **IAM** user known as `echo-cache`, which has 3 permissions(given by a custom policy I created), they are:
1. `PUT` object to DB. (They do not call it POST for some reason)
2. `GET` object from DB.
3. `DELETE` object from DB.

**_IMPORTANT: To be able to use the user within our express server, the following PRIVATE keys must be used in an `.env` file:_**

```env
BUCKET_NAME='capstone-2-echo-cache'
BUCKET_REGION='us-east-2'
ACCESS_KEY=''
SECRET_ACCESS_KEY=''
```

## Express Server File Handling

Our express server will not understand how to deal with `multipart/form-data`(This is the `Content-Type` of the media we send through the `<input type="file"/>`) by default, so we will need to use a middleware known as `multer`. We will also need `sharp` which is a package we will use for image/video resizing. `sharp` isn't strictly necessary but it would be nice to have all of our video and image formats in a portrait mode.

```bash
npm install multer sharp # sharp is not strictly required
```

Next put in some of these important variables. **NOTE:** that the `crypto` variable is imported from a built in Javascript library, so there should be no need to install `crypto`. It will be used later for unique ID creation.

```javascript
const multer = require("multer");
const crypto = require("crypto");
const sharp = require("sharp"); // To create a resized image, for example to put images into portrait mode.

const storage = multer.memoryStorage(); //This designates the server to store the media in memory, instead of on disk.
const upload = multer({ storage: storage });
```

Our `upload` variable will be used later in our route as a middleware.

## Amazon S3 SDK

After having created an access point to the bucket, now what is needed is to install to the express server `@aws-sdk/client-s3` for creating `POST` request to our Bucket, and `@aws-sdk/s3-request-presigner` for `GET` requests to the Bucket:

```bash
npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner
```

After installing, paste these variables into the header of the file, these will all serve a purpose for our `GET`, `POST` and `DELETE`:

```javascript
const {
S3Client,
PutObjectCommand,
GetObjectCommand,
DeleteObjectsCommand,
} = require("@aws-sdk/client-s3");
const { getSignedUrl } = require("@aws-sdk/s3-request-presigner");
```

Next, we will need to create an `s3Client` using our `.env` variables:

```javascript
const bucketName = process.env.BUCKET_NAME;
const bucketRegion = process.env.BUCKET_REGION;
const accessKey = process.env.ACCESS_KEY;
const secretAccessKey = process.env.SECRET_ACCESS_KEY;

const s3 = new S3Client({
credentials: {
accessKeyId: accessKey,
secretAccessKey: secretAccessKey,
},
region: bucketRegion,
});
```

### Quick **IMPORTANT** note

Its important I clarify a few things:

1. Our Amazon s3 bucket exists on my AWS account, with a free tier for 3 months more or less, or until my credits run out, which I have ample enough for our testing phase. Please see number 3 :)
2. The Sequelize related models functions/method names are all guesswork for now, as I have not fully implemented the activity within our own DB. I will update with proper naming, and behavior when it gets implemented officially.
3. There is **NO** validation being done right now. In theory someone could upload a zetabyte of horse videos and my AWS account bill will go 📈. _Please_ do **NOT** do this and be cautious on the size of content you are uploading. If we reach double digits in GB's, please let me know you are doing this so I can monitor my usage on AWS. Thanks :)!
4. I did not keep security in mind when developing the routes as I was moving quickly to develop the rough idea. I will update this as we continue developing the routes.

### Posting to our Bucket

```javascript
/*
- upload.array() will take an array of "files" named "media". The name "media" can be literally anything, just depends on what you name the array of files being sent from the client.
- upload.array() will store the file buffers in req.files when it is done.
*/
router.post(
"/",
[authenticateJWT, upload.array("media", 10)],
async (req, res) => {
// We use UUID's to prevent file name collision, which will overwrite one file over the other. We will also use it to retrieve the media later so we store it in our Postgres DB.
const image_uuids = [];
// S3 does not allow you to upload several files at once, so we have to loop
for (let i = 0; i < req.files.length; i++) {
const buffer = await sharp(req.files[i].buffer)
.resize({ height: 1920, width: 1080, fit: "contain" })
.toBuffer(); //This is for resizing an image to portrait mode. The image wont get affected, but black bars will fill the gaps.
const uniqueImgId = crypto.randomUUID();
const params = {
Bucket: bucketName,
Key: uniqueImgId,
Body: buffer, //This is strictly for image resizing, if uploading videos you would have to use req.files[i].buffer and or use another package to resize the video.
ContentType: req.files[i].mimetype,
};

const command = new PutObjectCommand(params);
// The following uses the s3Client variable we made earlier, to store to the AWS DB bucket
await s3.send(command);
// Upon successful completion we also save the UUID in our array
image_uuids.push(uniqueImgId);
}
await Echoes.create({
/*
Include here all relevant info for creating the echo
*/
image_uuids,
});

res.send(post);
},
);
```

### Getting from our Bucket

```javascript
router.get("/:id", authenticateJWT, async (req, res) => {
const echo = await Echo.getByPk(echoId);
const signed_urls = [];
for (let i = 0; i < echo.image_uuids.length; i++) {
const objectParams = {
Bucket: bucketName,
Key: echo.image_uuids[i],
};
const command = new GetObjectCommand(objectParams);
const url = await getSignedUrl(s3, command, { expiresIn: 3600 });
signed_urls.push(url);
}
// I prefer this method as opposed to using Sequelize's "update" method, as the AWS signed url is rather long, and might throw an error to the server (although it will still attach itself properly)
echo.signed_urls = signed_urls;
res.send(echo);
});
```

### Deleting from our Bucket

```javascript
router.delete("/:id", async (req, res) => {
const echoId = req.params.id;
const echo = await Echo.findByPk(echoId);
const params = {
Bucket: bucketName,
// Takes an array called "Objects" which will have the array of the multiple uuids, to delete all at once.
Delete: {
Objects: echo.uuids.map((uuid) => ({ Key: uuid })),
},
};
// Delete multiple objects from the bucket
const command = new DeleteObjectsCommand(params);
await s3.send(command);

// Sequelize deletes from our db here
await echo.destroy();
res.send({});
});
```

## Final Note

I'm so happy I'm done with this 😭
Loading