diff --git a/backend/cookies/create-cookies.ts b/backend/cookies/create-cookies.ts index 42652d8..7e75d5e 100644 --- a/backend/cookies/create-cookies.ts +++ b/backend/cookies/create-cookies.ts @@ -1,64 +1,83 @@ -import {Response } from "express"; +import { Response } from "express"; import env from "../enviroment/env"; -const maxAgeAccess = 60 * 1000 * 20; +const maxAgeAccess = 60 * 1000 * 20; //const maxAgeAccess = 1000; const maxAgeRefresh = 60 * 1000 * 60 * 24 * 30; //const maxAgeRefresh = 1000; const maxAgeStreamVideo = 60 * 1000 * 60 * 24; -const secureCookies = env.secureCookies ? env.secureCookies === "true" ? true : false : false; +const secureCookies = env.secureCookies + ? env.secureCookies === "true" + ? true + : false + : false; -export const createLoginCookie = (res: Response, accessToken: string, refreshToken: string) => { +export const createLoginCookie = ( + res: Response, + accessToken: string, + refreshToken: string +) => { + res.cookie("access-token", accessToken, { + httpOnly: true, + maxAge: maxAgeAccess, + sameSite: "strict", + secure: secureCookies, + }); - res.cookie("access-token",accessToken, { - httpOnly: true, - maxAge: maxAgeAccess, - sameSite: "strict", - secure: secureCookies - }) - - res.cookie("refresh-token",refreshToken, { - httpOnly: true, - maxAge: maxAgeRefresh, - sameSite: "strict", - secure: secureCookies - }) -} + res.cookie("refresh-token", refreshToken, { + httpOnly: true, + maxAge: maxAgeRefresh, + sameSite: "strict", + secure: secureCookies, + }); +}; export const createLogoutCookie = (res: Response) => { + res.cookie( + "access-token", + {}, + { + httpOnly: true, + maxAge: 0, + sameSite: "strict", + secure: secureCookies, + } + ); - res.cookie("access-token", {}, { - httpOnly: true, - maxAge: 0, - sameSite: "strict", - secure: secureCookies - }) + res.cookie( + "refresh-token", + {}, + { + httpOnly: true, + maxAge: 0, + sameSite: "strict", + secure: secureCookies, + } + ); +}; - res.cookie("refresh-token", {}, { - httpOnly: true, - maxAge: 0, - sameSite: "strict", - secure: secureCookies - }) -} - -export const createStreamVideoCookie = (res: Response, streamVideoAccessToken: string) => { - - res.cookie("video-access-token", streamVideoAccessToken, { - httpOnly: true, - maxAge: maxAgeStreamVideo, - sameSite: "strict", - secure: secureCookies - }) -} +export const createStreamVideoCookie = ( + res: Response, + streamVideoAccessToken: string +) => { + res.cookie("video-access-token", streamVideoAccessToken, { + httpOnly: true, + maxAge: maxAgeStreamVideo, + sameSite: "strict", + secure: secureCookies, + }); +}; export const removeStreamVideoCookie = (res: Response) => { - - res.cookie("video-access-token", {}, { - httpOnly: true, - maxAge: 0, - sameSite: "strict", - secure: secureCookies - }) -} \ No newline at end of file + res.cookie( + "video-access-token", + {}, + { + httpOnly: true, + maxAge: 0, + sameSite: "strict", + secure: secureCookies, + } + ); +}; diff --git a/backend/server/server-start.ts b/backend/server/server-start.ts index 6f2bc17..579f1ef 100644 --- a/backend/server/server-start.ts +++ b/backend/server/server-start.ts @@ -28,7 +28,7 @@ const serverStart = async () => { const port = process.env.HTTP_PORT || process.env.PORT; server.listen(port, process.env.URL, () => { - console.log("Development Backend Server Running On :", port); + console.log("\nDevelopment Backend Server Running On :", port); }); } }; diff --git a/backend/services/user-service/user-service.ts b/backend/services/user-service/user-service.ts index 42634d9..13b80af 100644 --- a/backend/services/user-service/user-service.ts +++ b/backend/services/user-service/user-service.ts @@ -96,9 +96,14 @@ class UserService { await user.generateEncryptionKeys(); const { accessToken, refreshToken } = await user.generateAuthToken(uuid); - const emailToken = await user.generateEmailVerifyToken(); - const emailSent = await sendEmailVerification(user, emailToken); + let emailSent = false; + + if (env.emailVerification === "true") { + const emailToken = await user.generateEmailVerifyToken(); + + emailSent = await sendEmailVerification(user, emailToken); + } if (!accessToken || !refreshToken) throw new InternalServerError("Could Not Create New User Error"); diff --git a/backend/tsconfig.json b/backend/tsconfig.json index 2394933..b38a93d 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -66,7 +66,6 @@ "exclude": [ "serverUtils", "src", - "tests", "key", "public", "node_modules", diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..c2c208b --- /dev/null +++ b/jest.config.js @@ -0,0 +1,198 @@ +/** + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ + +/** @type {import('jest').Config} */ +const config = { + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "/private/var/folders/zh/sgf63g810ss17919rfg886r00000gn/T/jest_dx", + + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + // collectCoverage: true, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, + + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "/node_modules/" + // ], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "v8", + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // The default configuration for fake timers + // fakeTimers: { + // "enableGlobally": false + // }, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "mjs", + // "cjs", + // "jsx", + // "ts", + // "tsx", + // "json", + // "node" + // ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + // moduleNameMapper: {}, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + // preset: undefined, + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state before every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state and implementation before every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + // testEnvironment: "jest-environment-node", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + // testMatch: [ + // "**/__tests__/**/*.[jt]s?(x)", + // "**/?(*.)+(spec|test).[tj]s?(x)" + // ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "/node_modules/" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", + + // A map from regular expressions to paths to transformers + // transform: undefined, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "/node_modules/", + // "\\.pnp\\.[^\\/]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; + +module.exports = config; diff --git a/jest.config.json b/jest.config.json deleted file mode 100755 index 74387ea..0000000 --- a/jest.config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "setupFiles": [ - "raf/polyfill", - "/tests/setupTests.js" - ], - "snapshotSerializers": [ - "enzyme-to-json/serializer" - ] -} \ No newline at end of file diff --git a/package.json b/package.json index daf384e..e0981d5 100755 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "create-video-thumbnails": "NODE_ENV=production node serverUtils/createVideoThumbnails.js", "create-video-thumbnails:dev": "NODE_ENV=development node serverUtils/createVideoThumbnails.js", "migrate-to-mydrive4": "NODE_ENV=production node serverUtils/migrateMyDrive4.js", - "migrate-to-mydrive4:dev": "NODE_ENV=development node serverUtils/migrateMyDrive4.js" + "migrate-to-mydrive4:dev": "NODE_ENV=development node serverUtils/migrateMyDrive4.js", + "test": "NODE_ENV=test jest" }, "dependencies": { "@babel/core": "^7.8.4", @@ -76,6 +77,7 @@ "jsonwebtoken": "^9.0.2", "lodash.debounce": "^4.0.8", "mongodb": "^6.7.0", + "mongodb-memory-server": "^10.1.3", "mongoose": "^8.4.1", "nodemailer": "^6.9.14", "normalize.css": "^8.0.1", @@ -109,9 +111,11 @@ "@types/bytes": "^3.1.4", "@types/cors": "^2.8.17", "@types/fluent-ffmpeg": "^2.1.24", + "@types/jest": "^29.5.14", "@types/lodash": "^4.17.5", "@types/nodemailer": "^6.4.15", "@types/prompts": "^2.4.9", + "@types/supertest": "^6.0.2", "concurrently": "^8.2.2", "cross-env": "^6.0.3", "dart-sass": "^1.25.0", @@ -124,7 +128,7 @@ "rollup-plugin-visualizer": "^5.14.0", "sass": "^1.77.4", "superagent-binary-parser": "^1.0.1", - "supertest": "^6.0.1", + "supertest": "^6.3.4", "tailwindcss": "^3.4.4", "typescript-eslint": "^7.14.1" } diff --git a/tests/controller/file-controller.test.js b/tests/controller/file-controller.test.js new file mode 100644 index 0000000..0386eb0 --- /dev/null +++ b/tests/controller/file-controller.test.js @@ -0,0 +1,46 @@ +const request = require("supertest"); +const app = require("../utils/express-app"); +const mongoose = require("mongoose"); +const { MongoMemoryServer } = require("mongodb-memory-server"); +const getEnvVariables = require("../../dist-backend/enviroment/get-env-variables"); +const getKey = require("../../dist-backend/key/get-key").default; +getEnvVariables(); +const env = require("../../dist-backend/enviroment/env"); +const { envFileFix } = require("../utils/db-setup"); + +let mongoServer; + +describe("File Controller", () => { + let authToken; + + beforeAll(async () => { + envFileFix(env); + await getKey(); + + mongoServer = await MongoMemoryServer.create(); + await mongoose.connect(mongoServer.getUri(), { useNewUrlParser: true }); + + const user = await request(app) + .post("/user-service/create") + .send({ + email: "test@test.com", + password: "test1234", + }) + .set("uuid", 12314123123); + + console.log(user.body); + + authToken = user.body.accessToken; + }); + + afterAll(async () => { + await mongoose.disconnect(); + await mongoServer.stop(); + }); + + describe("File info: GET /file-service/info/:id", () => { + test("Should return file info", () => { + expect(true).toBe(true); + }); + }); +}); diff --git a/tests/utils/db-setup.js b/tests/utils/db-setup.js new file mode 100644 index 0000000..83d8d19 --- /dev/null +++ b/tests/utils/db-setup.js @@ -0,0 +1,48 @@ +const createTestData = (mongoose) => { + const file = new mongoose.model("fs.files"); + + file.create({ + name: "test.txt", + type: "text/plain", + size: 10, + userId: "5f7e5d8d1f962d5a0f5e8a9e", + }); +}; + +const envFileFix = (env) => { + env.key = process.env.KEY; + env.newKey = process.env.NEW_KEY; + env.passwordAccess = process.env.PASSWORD_ACCESS; + env.passwordRefresh = process.env.PASSWORD_REFRESH; + env.passwordCookie = process.env.PASSWORD_COOKIE; + env.createAcctBlocked = process.env.BLOCK_CREATE_ACCOUNT; + env.root = process.env.ROOT; + env.url = process.env.URL; + env.mongoURL = process.env.MONGODB_URL; + env.dbType = process.env.DB_TYPE; + env.fsDirectory = process.env.FS_DIRECTORY; + env.s3ID = process.env.S3_ID; + env.s3Key = process.env.S3_KEY; + env.s3Bucket = process.env.S3_BUCKET; + env.useDocumentDB = process.env.USE_DOCUMENT_DB; + env.documentDBBundle = process.env.DOCUMENT_DB_BUNDLE; + env.sendgridKey = process.env.SENDGRID_KEY; + env.sendgridEmail = process.env.SENDGRID_EMAIL; + env.remoteURL = process.env.REMOTE_URL; + env.secureCookies = process.env.SECURE_COOKIES; + env.tempDirectory = process.env.TEMP_DIRECTORY; + env.emailVerification = process.env.EMAIL_VERIFICATION; + env.emailDomain = process.env.EMAIL_DOMAIN; + env.emailAPIKey = process.env.EMAIL_API_KEY; + env.emailHost = process.env.EMAIL_HOST; + env.emailPort = process.env.EMAIL_PORT; + env.emailAddress = process.env.EMAIL_ADDRESS; + env.videoThumbnailsEnabled = process.env.VIDEO_THUMBNAILS_ENABLED === "true"; + env.tempVideoThumbnailLimit = process.env.TEMP_VIDEO_THUMBNAIL_LIMIT + ? +process.env.TEMP_VIDEO_THUMBNAIL_LIMIT + : 0; +}; + +module.exports = { + envFileFix, +}; diff --git a/tests/utils/express-app.js b/tests/utils/express-app.js new file mode 100644 index 0000000..d920d8c --- /dev/null +++ b/tests/utils/express-app.js @@ -0,0 +1,49 @@ +const express = require("express"); +// const requestIp = require("request-ip"); +const bodyParser = require("body-parser"); +const cookieParser = require("cookie-parser"); +const helmet = require("helmet"); +const compression = require("compression"); +const busboy = require("connect-busboy"); +const userRouter = + require("../../dist-backend/express-routers/user-router").default; +const fileRouter = + require("../../dist-backend/express-routers/file-router").default; +const folderRouter = + require("../../dist-backend/express-routers/folder-router").default; +const env = require("../../dist-backend/enviroment/env"); +const middlewareErrorHandler = + require("../../dist-backend/middleware/utils/middleware-utils").middlewareErrorHandler; +const getEnviromentVariables = require("../../dist-backend/enviroment/get-env-variables"); + +process.env.NODE_ENV = "test"; + +getEnviromentVariables(); + +const app = express(); + +app.use(cookieParser(env.passwordCookie)); +app.use(helmet()); +app.use(compression()); +app.use(express.json()); +app.use(bodyParser.json({ limit: "50mb" })); +app.use( + bodyParser.urlencoded({ + limit: "50mb", + extended: true, + parameterLimit: 50000, + }) +); +// app.use(requestIp.mw()); + +app.use( + busboy({ + highWaterMark: 2 * 1024 * 1024, + }) +); + +app.use(userRouter, fileRouter, folderRouter); + +app.use(middlewareErrorHandler); + +module.exports = app;