Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/firebase api #202

Merged
merged 3 commits into from
Jul 5, 2024
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
1 change: 1 addition & 0 deletions imageUpload/firebase.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dung xoa cai nay!!!!
1,336 changes: 1,315 additions & 21 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"express": "^4.19.2",
"express-rate-limit": "^7.3.1",
"express-validator": "^7.1.0",
"firebase-admin": "^12.2.0",
"http-status-codes": "^2.3.0",
"husky": "^9.0.11",
"jsonwebtoken": "^9.0.2",
Expand Down Expand Up @@ -68,6 +69,7 @@
"@types/passport-facebook": "^3.0.3",
"@types/passport-google-oauth20": "^2.0.16",
"@types/request": "^2.48.12",
"@types/uuid": "^10.0.0",
"@types/validator": "^13.12.0",
"@typescript-eslint/eslint-plugin": "^7.14.1",
"@typescript-eslint/parser": "^7.14.1",
Expand Down
22 changes: 22 additions & 0 deletions src/config/firebase.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as firebaseAdmin from "firebase-admin";
const a = {
type: process.env.TYPE,
project_id: process.env.PROJECT_ID,
private_key_id: process.env.PRIVATE_KEY_ID,
private_key: process.env.PRIVATE_KEY,
client_email: process.env.CLIENT_EMAIL,
client_id: process.env.CLIENT_IDFB,
auth_uri: process.env.AUTH_URI,
token_uri: process.env.TOKEN_URI,
auth_provider_x509_cert_url: process.env.AUTH_PROVIDER_X509_CERT_URL,
client_x509_cert_url: process.env.CLIENT_X509_CERT_URL,
universe_domain: process.env.UNIVERSE_DOMAIN,
};

const admin = firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert(
a as firebaseAdmin.ServiceAccount,
),
});

export const storageRef = admin.storage().bucket(process.env.BUCKET);
129 changes: 90 additions & 39 deletions src/modules/user/user.controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,22 @@ import { OTP_MESSAGES } from "../otp/otp.messages";
import { UserRole } from "./user.enum";
import { USER_MESSAGES } from "./user.messages";
import {

BlockBody,

ListAccountQuery,

LoginRequestBody,
LogoutReqBody,
RefreshTokenReqBody,
RegisterReqBody,
TokenPayload,
UpdateMeReqBody,
UserResponseAfterCheckEmailOrPhone
} from './user.requests'
import User from './user.schema'
import usersService from './user.services'
import adminService from "../admin/admin.services";
import { UserList } from "~/constants/user.type";
import { UserRole } from "./user.enum";


UserResponseAfterCheckEmailOrPhone,
} from "./user.requests";
import User from "./user.schema";
import usersService from "./user.services";
import { v4 as uuidv4 } from "uuid";
import path from "path";
import { storageRef } from "~/config/firebase.config";
import fs from "fs";

export const registerController = async (
req: Request<ParamsDictionary, any, RegisterReqBody>,
Expand Down Expand Up @@ -264,55 +260,54 @@ export const refreshTokenController = async (
return res.json({
message: USER_MESSAGES.REFRESH_TOKEN_SUCCESSFULLY,

data: { access_token }
})
}
data: { access_token },
});
};

export const blockAccountController = async (
req: Request<ParamsDictionary, any, BlockBody>,
res: Response
res: Response,
) => {
console.log(req.cookies['refresh_token'])
await usersService.logout(req.cookies['refresh_token'])
res.clearCookie('refresh_token')
console.log(req.cookies["refresh_token"]);
await usersService.logout(req.cookies["refresh_token"]);
res.clearCookie("refresh_token");
try {
const reason = req.body.description_reason
const picture_image_prove = req.body.picture_image_prove
const timeBlock = new Date()
const user_id = req.body._id
const reason = req.body.description_reason;
const picture_image_prove = req.body.picture_image_prove;
const timeBlock = new Date();
const user_id = req.body._id;
await usersService.blockAccount(
user_id,
reason,
picture_image_prove,
timeBlock
)
timeBlock,
);
return res.json({
message: USER_MESSAGES.USER_HAS_BEEN_BLOCKED
})
message: USER_MESSAGES.USER_HAS_BEEN_BLOCKED,
});
} catch (error) {
return res.status(400).json({
message: 'Bad request'
})
message: "Bad request",
});
}
}
};

export const unblockAccountController = async (
req: Request<ParamsDictionary, any, BlockBody>,
res: Response
res: Response,
) => {
try {
const user_id = req.body._id
await usersService.unblockAccount(user_id)
const user_id = req.body._id;
await usersService.unblockAccount(user_id);
return res.json({
message: USER_MESSAGES.USER_UNBLOCK_SUCCESSFULLY
})
message: USER_MESSAGES.USER_UNBLOCK_SUCCESSFULLY,
});
} catch (error) {
return res.status(400).json({
message: 'Bad request'
})
message: "Bad request",
});
}
}

};

export const getListUserController = async (req: Request, res: Response) => {
const query = req.queryListAccount as ListAccountQuery;
Expand Down Expand Up @@ -400,4 +395,60 @@ export const getListUserController = async (req: Request, res: Response) => {
});
}
};
async function downloadAndUploadImage(
imageUrl: string,
filename: string,
): Promise<string> {
const response = await fetch(imageUrl);
if (!response.ok) {
throw new Error(`Failed to download image from ${imageUrl}`);
}
const buffer = await response.arrayBuffer();
const tempFilePath = path.resolve("imageUpload") + `\\${filename}.jpeg`;
// //checkTypeLink
// const fileType = await fileTypeFromBuffer(buffer)
// if (!fileType || !fileType.mime.startsWith('image/')) {
// await fs.promises.unlink(tempFilePath)
// throw new Error(`File ${tempFilePath} is not an image!!!`)
// }
await fs.promises.writeFile(tempFilePath, Buffer.from(buffer));
try {
const url = await uploadFile(tempFilePath, filename);
return url;
} catch (err) {
throw new Error(USER_MESSAGES.CANT_UPLOAD_IMG);
} finally {
await fs.promises.unlink(tempFilePath);
}
}

export const getLinkPicture = async (
req: Request<ParamsDictionary, any, UpdateMeReqBody>,
res: Response,
) => {
const imageUrl = req.body.avatar_url;
const user_Id = (req.body as User)._id;
if (!imageUrl) {
return res.json({
message: USER_MESSAGES.CANT_FIND_THIS_IMAGE,
});
}
const url = await downloadAndUploadImage(imageUrl, `${user_Id}`);
console.log(url);
return res.status(200).json({
message: USER_MESSAGES.UPLOAD_PICTURE_SUCCESSFULLY,
details: url,
});
};
async function uploadFile(path: string, filename: string): Promise<string> {
// Upload the File
const storage = await storageRef.upload(path, {
public: true,
destination: `/uploads/${filename}`,
metadata: {
contentType: "image/jpeg",
firebaseStorageDownloadTokens: uuidv4(),
},
});
return storage[0].metadata.mediaLink ?? "";
}
14 changes: 9 additions & 5 deletions src/modules/user/user.messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,17 @@ export const USER_MESSAGES = {

//token

REFRESH_TOKEN_IS_REQUIRED: 'Refresh token is required',
OTP_IS_INCORRECT: 'OTP is incorrect',
REFRESH_TOKEN_IS_REQUIRED: "Refresh token is required",
OTP_IS_INCORRECT: "OTP is incorrect",
// block
USER_HAS_BEEN_BLOCKED: 'user has been blocked',
USER_UNBLOCK_SUCCESSFULLY: 'user unblock successfully'
USER_HAS_BEEN_BLOCKED: "user has been blocked",
USER_UNBLOCK_SUCCESSFULLY: "user unblock successfully",

//don't have permission
DONT_HAVE_PERMISSION: `You don't have permission`,
} as const;

//Upload picture
CANT_UPLOAD_IMG: "Cannot upload image",
CANT_FIND_THIS_IMAGE: "Cannot find this image",
UPLOAD_PICTURE_SUCCESSFULLY: "Upload picture successfully",
} as const;
21 changes: 17 additions & 4 deletions src/modules/user/user.middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ import { isValidPhoneNumberForCountry, validate } from "~/utils/validation";
import { OTP_STATUS } from "../otp/otp.enum";
import { OTP_MESSAGES } from "../otp/otp.messages";
import otpService from "../otp/otp.services";
import {
NoticeUser,
Subscription,
UserVerifyStatus,
UserRole,
} from "./user.enum";
import { PROTECT_MESSAGES } from "../protectRouting/protect.messages";
import { checkRole, routesConfig } from "../protectRouting/protect.utils";
import { NoticeUser, UserRole, UserVerifyStatus } from "./user.enum";
import { LoginRequestBody, TokenPayload } from "./user.requests";
import usersService from "./user.services";
//! Prevent db injection, XSS attack
Expand Down Expand Up @@ -289,9 +294,8 @@ export const loginValidator = validate(

if (
user.notice === NoticeUser.Banned ||
user.reasonBanned !== '' ||
user.reasonBanned !== "" ||
user.block === Subscription.True

) {
throw new ErrorWithStatus({
message: USER_MESSAGES.ACCOUNT_IS_BANNED,
Expand Down Expand Up @@ -376,7 +380,7 @@ export const loginValidator = validate(

if (
user.notice === NoticeUser.Banned ||
user.reasonBanned !== '' ||
user.reasonBanned !== "" ||
user.block === Subscription.True
) {
throw new ErrorWithStatus({
Expand Down Expand Up @@ -1302,3 +1306,12 @@ export const pagination = async (
next();
}
};

export const getLinkImg = validate(
checkSchema(
{
avatar_url: imageSchema,
},
["body"],
),
);
14 changes: 7 additions & 7 deletions src/modules/user/user.requests.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ObjectId } from 'mongodb'
import { ObjectId } from "mongodb";
import { JwtPayload } from "jsonwebtoken";
import {
Subscription,
Expand Down Expand Up @@ -80,13 +80,13 @@ export type LogoutReqBody = {
};

export type RefreshTokenReqBody = {
refresh_token: string
}
refresh_token: string;
};
export interface BlockBody {
_id: ObjectId
description_reason?: string
picture_image_prove?: string
refresh_token: string
_id: ObjectId;
description_reason?: string;
picture_image_prove?: string;
refresh_token: string;
}

export type ListAccountQuery = {
Expand Down
16 changes: 10 additions & 6 deletions src/modules/user/user.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
blockAccountController,
changePasswordController,
forgotPasswordController,
getLinkPicture,
getListUserController,
getMeController,
loginController,
Expand All @@ -28,6 +29,7 @@ import {
checkNewPasswordValidator,
checkVerifyAccount,
forgotPasswordValidator,
getLinkImg,
isUserRole,
loginValidator,
pagination,
Expand Down Expand Up @@ -235,17 +237,17 @@ usersRouter.post(
usersRouter.post(
"/refresh-token",
refreshTokenCookieValidator,
wrapAsync(refreshTokenController)
)
wrapAsync(refreshTokenController),
);

usersRouter.post(
'/block',
"/block",
accessTokenValidator,
refreshTokenCookieValidator,
wrapAsync(blockAccountController)
)
wrapAsync(blockAccountController),
);

usersRouter.post('/unblock', wrapAsync(unblockAccountController))
usersRouter.post("/unblock", wrapAsync(unblockAccountController));

usersRouter.get(
"/list-account",
Expand All @@ -255,4 +257,6 @@ usersRouter.get(
wrapAsync(getListUserController),
);

usersRouter.post("/getLinkPic", getLinkImg, wrapAsync(getLinkPicture));

export default usersRouter;
Loading