Skip to content

Commit 1f134ac

Browse files
committed
add edit profile picture
- add coverage folder to dockerignore - update backend services swagger yml for images api - update user service readme to include firebase setup - add edit profile picture functionality
1 parent 7a60038 commit 1f134ac

File tree

20 files changed

+1774
-69
lines changed

20 files changed

+1774
-69
lines changed

backend/question-service/.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
coverage
12
node_modules
23
tests
34
.env*

backend/question-service/src/controllers/questionController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ export const createImageLink = async (
8181
const uploadPromises = files.map((file) => uploadFileToFirebase(file));
8282
const imageUrls = await Promise.all(uploadPromises);
8383
console.log(imageUrls);
84-
res
84+
return res
8585
.status(200)
8686
.json({ message: "Images uploaded successfully", imageUrls });
8787
} catch (error) {
88-
res.status(500).json({ message: "Server error", error });
88+
return res.status(500).json({ message: "Server error", error });
8989
}
9090
});
9191
};

backend/question-service/swagger.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,46 @@ paths:
350350
application/json:
351351
schema:
352352
$ref: "#/definitions/ServerError"
353+
/api/questions/images:
354+
post:
355+
summary: Publish image to firebase storage
356+
tags:
357+
- questions
358+
security:
359+
- bearerAuth: []
360+
requestBody:
361+
content:
362+
multipart/form-data:
363+
schema:
364+
type: object
365+
properties:
366+
profilePic:
367+
type: string
368+
format: binary
369+
required: true
370+
responses:
371+
200:
372+
description: Successful Response
373+
content:
374+
application/json:
375+
schema:
376+
type: object
377+
properties:
378+
message:
379+
type: string
380+
description: Message
381+
imageUrl:
382+
type: string
383+
description: image url
384+
400:
385+
description: Bad Request
386+
content:
387+
application/json:
388+
schema:
389+
$ref: "#/components/schemas/ErrorResponse"
390+
500:
391+
description: Internal Server Error
392+
content:
393+
application/json:
394+
schema:
395+
$ref: "#/components/schemas/ServerErrorResponse"

backend/user-service/.env.sample

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,11 @@ ADMIN_USERNAME=administrator
1111
ADMIN_EMAIL=[email protected]
1212
ADMIN_PASSWORD=Admin@123
1313

14+
# firebase
15+
FIREBASE_PROJECT_ID=FIREBASE_PROJECT_ID
16+
FIREBASE_PRIVATE_KEY=FIREBASE_PRIVATE_KEY
17+
FIREBASE_CLIENT_EMAIL=FIREBASE_CLIENT_EMAIL
18+
FIREBASE_STORAGE_BUCKET=FIREBASE_STORAGE_BUCKET
19+
1420
# origins for cors
1521
ORIGINS=http://localhost:5173,http://127.0.0.1:5173

backend/user-service/README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,38 @@
2828

2929
6. Update the `DB_CLOUD_URI` of the `.env` file, and paste the string we copied earlier in step 4.
3030

31+
## Setting-up Firebase
32+
33+
1. Go to https://console.firebase.google.com/u/0/.
34+
35+
2. Create a project and choose a project name. Navigate to `Storage` and click on it to activate it.
36+
37+
3. Select `Start in production mode` and your preferred cloud storage region.
38+
39+
4. After Storage is created, go to `Rules` section and set rule to:
40+
41+
```
42+
rules_version = '2';
43+
service firebase.storage {
44+
match /b/{bucket}/o {
45+
match /{allPaths=**} {
46+
allow read: if true;
47+
allow write: if request.auth != null;
48+
}
49+
}
50+
}
51+
```
52+
53+
This rule ensures that only verified users can upload images while ensuring that URLs of images are public. Remember to click `Publish` to save changes.
54+
55+
5. Go to `Settings`, `Project settings`, `Service accounts` and click `Generate new private key`. This will download a `.json` file, which will contain your credentials.
56+
57+
6. In `.env` of user service, replace:
58+
- `FIREBASE_PROJECT_ID` with `project_id` found in the downloaded json file.
59+
- `FIREBASE_PRIVATE_KEY` with `private_key` found in the downloaded json file.
60+
- `FIREBASE_CLIENT_EMAIL` with `client_email` found in the downloaded json file.
61+
- `FIREBASE_STORAGE_BUCKET` with the folder path of the Storage. It should look something like `gs://<appname>.appspot.com`.
62+
3163
## Running User Service
3264

3365
1. Follow the instructions [here](https://nodejs.org/en/download/package-manager) to set up Node v20.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import admin from "firebase-admin";
2+
3+
admin.initializeApp({
4+
credential: admin.credential.cert({
5+
projectId: process.env.FIREBASE_PROJECT_ID,
6+
privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, "\n"),
7+
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
8+
} as admin.ServiceAccount),
9+
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
10+
});
11+
12+
const bucket = admin.storage().bucket();
13+
14+
export { bucket };
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import multer from "multer";
2+
3+
const storage = multer.memoryStorage();
4+
const upload = multer({ storage }).single("profilePic");
5+
6+
export { upload };

backend/user-service/controller/user-controller.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import {
2020
validateBiography,
2121
} from "../utils/validators";
2222
import { IUser } from "../model/user-model";
23+
import { upload } from "../config/multer";
24+
import { uploadFileToFirebase } from "../utils/utils";
2325

2426
export async function createUser(
2527
req: Request,
@@ -92,6 +94,34 @@ export async function createUser(
9294
}
9395
}
9496

97+
export const createImageLink = async (
98+
req: Request,
99+
res: Response
100+
): Promise<void> => {
101+
upload(req, res, async (err) => {
102+
if (err) {
103+
return res
104+
.status(500)
105+
.json({ message: "Failed to upload image", error: err.message });
106+
}
107+
108+
if (!req.file) {
109+
return res.status(400).json({ message: "No image uploaded" });
110+
}
111+
112+
try {
113+
const file = req.file as Express.Multer.File;
114+
const imageUrl = await uploadFileToFirebase("profilePics/", file);
115+
116+
return res
117+
.status(200)
118+
.json({ message: "Image uploaded successfully", imageUrl: imageUrl });
119+
} catch (error) {
120+
return res.status(500).json({ message: "Server error", error });
121+
}
122+
});
123+
};
124+
95125
export async function getUser(req: Request, res: Response): Promise<Response> {
96126
try {
97127
const userId = req.params.id;

0 commit comments

Comments
 (0)