اپلود روی لیارا

This commit is contained in:
vahidrezvani 2025-07-08 10:10:52 +03:30
parent 25f8bfe69b
commit 6a26ea9b78
8 changed files with 131 additions and 29 deletions

40
Dockerfile Normal file
View File

@ -0,0 +1,40 @@
# ---- Base Stage ----
FROM node:20-slim AS base
# ---- Build Stage ----
FROM base AS build
WORKDIR /app
COPY package.json package-lock.json ./
# Install ALL dependencies (dev and prod)
# This is cached and only re-runs if the lockfile changes.
RUN npm ci
# Copy the rest of the source code
COPY . .
# Build the application
RUN npm run build
# ---- Production Stage ----
# Create the final, lean production image by copying only what's needed.
# This stage is very fast as it only contains COPY commands.
FROM base AS production
WORKDIR /app
# Copy the pruned production dependencies, the built app, and package.json
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/package.json ./package.json
# Expose the port the app runs on
EXPOSE 3000
# Run the application as a non-root user for better security
USER node
# Command to run the application
CMD ["node", "dist/main"]

51
package-lock.json generated
View File

@ -18,6 +18,7 @@
"@nestjs/mongoose": "^11.0.3", "@nestjs/mongoose": "^11.0.3",
"@nestjs/passport": "^11.0.5", "@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^11.0.1", "@nestjs/platform-express": "^11.0.1",
"@types/passport-google-oauth20": "^2.0.16",
"aws-sdk": "^2.1692.0", "aws-sdk": "^2.1692.0",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.2", "class-validator": "^0.14.2",
@ -5228,7 +5229,6 @@
"version": "1.19.6", "version": "1.19.6",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
"integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/connect": "*", "@types/connect": "*",
@ -5239,7 +5239,6 @@
"version": "3.4.38", "version": "3.4.38",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
"integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
@ -5285,7 +5284,6 @@
"version": "5.0.3", "version": "5.0.3",
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz",
"integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/body-parser": "*", "@types/body-parser": "*",
@ -5297,7 +5295,6 @@
"version": "5.0.6", "version": "5.0.6",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz",
"integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/node": "*", "@types/node": "*",
@ -5327,7 +5324,6 @@
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
"integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/istanbul-lib-coverage": { "node_modules/@types/istanbul-lib-coverage": {
@ -5395,7 +5391,6 @@
"version": "1.3.5", "version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/multer": { "node_modules/@types/multer": {
@ -5417,25 +5412,62 @@
"undici-types": "~6.21.0" "undici-types": "~6.21.0"
} }
}, },
"node_modules/@types/oauth": {
"version": "0.9.6",
"resolved": "https://registry.npmjs.org/@types/oauth/-/oauth-0.9.6.tgz",
"integrity": "sha512-H9TRCVKBNOhZZmyHLqFt9drPM9l+ShWiqqJijU1B8P3DX3ub84NjxDuy+Hjrz+fEca5Kwip3qPMKNyiLgNJtIA==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/passport": {
"version": "1.0.17",
"resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.17.tgz",
"integrity": "sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==",
"license": "MIT",
"dependencies": {
"@types/express": "*"
}
},
"node_modules/@types/passport-google-oauth20": {
"version": "2.0.16",
"resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.16.tgz",
"integrity": "sha512-ayXK2CJ7uVieqhYOc6k/pIr5pcQxOLB6kBev+QUGS7oEZeTgIs1odDobXRqgfBPvXzl0wXCQHftV5220czZCPA==",
"license": "MIT",
"dependencies": {
"@types/express": "*",
"@types/passport": "*",
"@types/passport-oauth2": "*"
}
},
"node_modules/@types/passport-oauth2": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@types/passport-oauth2/-/passport-oauth2-1.8.0.tgz",
"integrity": "sha512-6//z+4orIOy/g3zx17HyQ71GSRK4bs7Sb+zFasRoc2xzlv7ZCJ+vkDBYFci8U6HY+or6Zy7ajf4mz4rK7nsWJQ==",
"license": "MIT",
"dependencies": {
"@types/express": "*",
"@types/oauth": "*",
"@types/passport": "*"
}
},
"node_modules/@types/qs": { "node_modules/@types/qs": {
"version": "6.14.0", "version": "6.14.0",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/range-parser": { "node_modules/@types/range-parser": {
"version": "1.2.7", "version": "1.2.7",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/send": { "node_modules/@types/send": {
"version": "0.17.5", "version": "0.17.5",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz",
"integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/mime": "^1", "@types/mime": "^1",
@ -5446,7 +5478,6 @@
"version": "1.15.8", "version": "1.15.8",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz",
"integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/http-errors": "*", "@types/http-errors": "*",

View File

@ -29,6 +29,7 @@
"@nestjs/mongoose": "^11.0.3", "@nestjs/mongoose": "^11.0.3",
"@nestjs/passport": "^11.0.5", "@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^11.0.1", "@nestjs/platform-express": "^11.0.1",
"@types/passport-google-oauth20": "^2.0.16",
"aws-sdk": "^2.1692.0", "aws-sdk": "^2.1692.0",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.14.2", "class-validator": "^0.14.2",

View File

@ -18,7 +18,7 @@ import { DiscountTypeModule } from './discount-type/discount-type.module';
@Module({ @Module({
imports: [ imports: [
CategoryModule,UploadModule,LoginModule,ShopModule,ProductModule,DiscountModule, CategoryModule,UploadModule,LoginModule,ShopModule,ProductModule,DiscountModule,
MongooseModule.forRoot('mongodb://localhost/fartak'), MongooseModule.forRoot('mongodb://root:FcpaOAxvZd2IiqK5Vl5QRMTE@fartakdatabase:27017/my-app?authSource=admin'),
ConfigModule.forRoot({ isGlobal: true }), DiscountTypeModule ConfigModule.forRoot({ isGlobal: true }), DiscountTypeModule
], ],
controllers: [AppController], controllers: [AppController],

View File

@ -1,6 +1,37 @@
import { Controller } from '@nestjs/common'; import { Controller, Get, Req, Res, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { JwtService } from '@nestjs/jwt';
import { Response, Request } from 'express';
@Controller('auth') @Controller('auth')
export class AuthController { export class AuthController {
constructor(private jwtService: JwtService) {}
@Get('google')
@UseGuards(AuthGuard('google'))
async googleAuth() {
// Redirects to Google
}
@Get('google/redirect')
@UseGuards(AuthGuard('google'))
async googleRedirect(@Req() req: Request, @Res() res: Response) {
const user = req.user as any;
// You can store user in DB here if needed
const payload = {
email: user.email,
name: `${user.firstName} ${user.lastName}`,
picture: user.picture,
};
const token = this.jwtService.sign(payload);
// ✅ Option 1: Send token as JSON
// res.json({ token });
// ✅ Option 2: Redirect to frontend with token
res.redirect(`http://localhost:4200/login/success?token=${token}`);
}
} }

View File

@ -1,22 +1,26 @@
// auth/google.strategy.ts
import { PassportStrategy } from '@nestjs/passport'; import { PassportStrategy } from '@nestjs/passport';
import { Strategy, VerifyCallback } from 'passport-google-oauth20'; import { Strategy, VerifyCallback, StrategyOptions } from 'passport-google-oauth20';
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import * as dotenv from 'dotenv'; import { ConfigService } from '@nestjs/config';
dotenv.config();
@Injectable() @Injectable()
export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { export class GoogleStrategy extends PassportStrategy(Strategy, 'google') {
constructor() { constructor(private configService: ConfigService) {
super({ super({
clientID: process.env.GOOGLE_CLIENT_ID, clientID: configService.get<string>('GOOGLE_CLIENT_ID'),
clientSecret: process.env.GOOGLE_CLIENT_SECRET, clientSecret: configService.get<string>('GOOGLE_CLIENT_SECRET'),
callbackURL: 'http://localhost:3000/auth/google/redirect', callbackURL: configService.get<string>('GOOGLE_CALLBACK_URL'),
scope: ['email', 'profile'], scope: ['email', 'profile'],
}); } as StrategyOptions); // Fixes the typing error
} }
async validate(accessToken: string, refreshToken: string, profile: any, done: VerifyCallback): Promise<any> { async validate(
accessToken: string,
refreshToken: string,
profile: any,
done: VerifyCallback,
): Promise<any> {
const { name, emails, photos } = profile; const { name, emails, photos } = profile;
const user = { const user = {

View File

@ -41,7 +41,6 @@ export class DiscountTypeService {
} }
async findDiscountType(id:string) :Promise <CreateSellerResponse> { async findDiscountType(id:string) :Promise <CreateSellerResponse> {
const category = await this.discountTypeModel.findOne({ID:id}) const category = await this.discountTypeModel.findOne({ID:id})

View File

@ -1,9 +1,5 @@
// src/redis.client.ts
import Redis from 'ioredis'; import Redis from 'ioredis';
const redis = new Redis({ const redis = new Redis(process.env.REDIS_URL || 'redis://:eCwxwRr7YX9q0ynso4uR6HNf@fartakredis:6379/0');
host: 'localhost', // یا IP سرور Redis
port: 6379, // پورت پیش‌فرض Redis
});
export default redis; export default redis;