fix(services): restrict GET /uploads/messages/:file to authorized users
This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "extends": ["standard-with-typescript", "eslint-config-prettier"],
 | 
					  "extends": ["standard-with-typescript", "prettier"],
 | 
				
			||||||
  "plugins": ["unicorn", "eslint-plugin-prettier"],
 | 
					  "plugins": ["unicorn", "import", "prettier"],
 | 
				
			||||||
  "parserOptions": {
 | 
					  "parserOptions": {
 | 
				
			||||||
    "project": "./tsconfig.json"
 | 
					    "project": "./tsconfig.json"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
@@ -10,6 +10,11 @@
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  "rules": {
 | 
					  "rules": {
 | 
				
			||||||
    "prettier/prettier": "error",
 | 
					    "prettier/prettier": "error",
 | 
				
			||||||
 | 
					    "import/order": [
 | 
				
			||||||
 | 
					      "error",
 | 
				
			||||||
 | 
					      { "groups": ["builtin", "external", "internal"] }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    "import/extensions": ["error", "always"],
 | 
				
			||||||
    "unicorn/prefer-node-protocol": "error",
 | 
					    "unicorn/prefer-node-protocol": "error",
 | 
				
			||||||
    "unicorn/prevent-abbreviations": "error"
 | 
					    "unicorn/prevent-abbreviations": "error"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							@@ -21,13 +21,27 @@ jobs:
 | 
				
			|||||||
      - name: 'Install'
 | 
					      - name: 'Install'
 | 
				
			||||||
        run: 'npm install'
 | 
					        run: 'npm install'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - run: 'npm run lint:commit -- --to "${{ github.sha }}"'
 | 
					      - name: 'lint:commit'
 | 
				
			||||||
      - run: 'npm run lint:editorconfig'
 | 
					        run: 'npm run lint:commit -- --to "${{ github.sha }}"'
 | 
				
			||||||
      - run: 'npm run lint:markdown'
 | 
					 | 
				
			||||||
      - run: 'npm run lint:docker'
 | 
					 | 
				
			||||||
      - run: 'npm run lint:typescript'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: 'dotenv-linter'
 | 
					      - name: 'lint:editorconfig'
 | 
				
			||||||
 | 
					        run: 'npm run lint:editorconfig'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: 'lint:markdown'
 | 
				
			||||||
 | 
					        run: 'npm run lint:markdown'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: 'lint:typescript'
 | 
				
			||||||
 | 
					        run: 'npm run lint:typescript'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: 'lint:prettier'
 | 
				
			||||||
 | 
					        run: 'npm run lint:prettier'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: 'lint:dotenv'
 | 
				
			||||||
        uses: 'dotenv-linter/action-dotenv-linter@v2'
 | 
					        uses: 'dotenv-linter/action-dotenv-linter@v2'
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          github_token: ${{ secrets.github_token }}
 | 
					          github_token: ${{ secrets.github_token }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: 'lint:docker'
 | 
				
			||||||
 | 
					        uses: 'hadolint/hadolint-action@v1.6.0'
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          dockerfile: './Dockerfile'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,5 @@
 | 
				
			|||||||
    "jest --findRelatedTests"
 | 
					    "jest --findRelatedTests"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "*.{yml,json}": ["prettier --write"],
 | 
					  "*.{yml,json}": ["prettier --write"],
 | 
				
			||||||
  "*.{md}": ["prettier --write", "markdownlint --dot --fix"],
 | 
					  "*.{md}": ["prettier --write", "markdownlint --dot --fix"]
 | 
				
			||||||
  "./Dockerfile": ["dockerfilelint"]
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,3 +3,4 @@ node_modules
 | 
				
			|||||||
coverage
 | 
					coverage
 | 
				
			||||||
package.json
 | 
					package.json
 | 
				
			||||||
package-lock.json
 | 
					package-lock.json
 | 
				
			||||||
 | 
					*.hbs
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "typescript.tsdk": "node_modules/typescript/lib",
 | 
					  "typescript.tsdk": "node_modules/typescript/lib",
 | 
				
			||||||
 | 
					  "typescript.preferences.importModuleSpecifierEnding": "js",
 | 
				
			||||||
  "prettier.configPath": ".prettierrc.json",
 | 
					  "prettier.configPath": ".prettierrc.json",
 | 
				
			||||||
  "editor.formatOnSave": true,
 | 
					  "editor.formatOnSave": true,
 | 
				
			||||||
  "editor.codeActionsOnSave": {
 | 
					  "editor.codeActionsOnSave": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +1,23 @@
 | 
				
			|||||||
FROM node:16.13.1 AS dependencies
 | 
					FROM node:16.13.1 AS dependencies
 | 
				
			||||||
WORKDIR /usr/src/app
 | 
					WORKDIR /usr/src/app
 | 
				
			||||||
COPY ./package*.json ./
 | 
					COPY ./package*.json ./
 | 
				
			||||||
RUN npm clean-install
 | 
					RUN npm install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FROM node:16.13.1 AS builder
 | 
					FROM node:16.13.1 AS builder
 | 
				
			||||||
WORKDIR /usr/src/app
 | 
					WORKDIR /usr/src/app
 | 
				
			||||||
COPY --from=dependencies /usr/src/app/node_modules ./node_modules
 | 
					COPY --from=dependencies /usr/src/app/node_modules ./node_modules
 | 
				
			||||||
COPY ./ ./
 | 
					COPY ./ ./
 | 
				
			||||||
RUN npx prisma generate
 | 
					RUN npm run prisma:generate && npm run build
 | 
				
			||||||
RUN npm run build
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
FROM node:16.13.1 AS runner
 | 
					FROM node:16.13.1 AS runner
 | 
				
			||||||
WORKDIR /usr/src/app
 | 
					WORKDIR /usr/src/app
 | 
				
			||||||
ENV NODE_ENV=production
 | 
					ENV NODE_ENV=production
 | 
				
			||||||
COPY --from=builder /usr/src/app/node_modules ./node_modules
 | 
					COPY --from=builder /usr/src/app/node_modules ./node_modules
 | 
				
			||||||
 | 
					COPY --from=builder /usr/src/app/start.sh ./start.sh
 | 
				
			||||||
 | 
					COPY --from=builder /usr/src/app/package.json ./package.json
 | 
				
			||||||
COPY --from=builder /usr/src/app/email ./email
 | 
					COPY --from=builder /usr/src/app/email ./email
 | 
				
			||||||
COPY --from=builder /usr/src/app/build ./build
 | 
					COPY --from=builder /usr/src/app/build ./build
 | 
				
			||||||
COPY --from=builder /usr/src/app/prisma ./prisma
 | 
					COPY --from=builder /usr/src/app/prisma ./prisma
 | 
				
			||||||
COPY --from=builder /usr/src/app/uploads ./uploads
 | 
					COPY --from=builder /usr/src/app/uploads ./uploads
 | 
				
			||||||
USER node
 | 
					USER node
 | 
				
			||||||
CMD npm run prisma:migrate:deploy && node build/index.js
 | 
					CMD ["./docker-start.sh"]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								docker-start.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										4
									
								
								docker-start.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					npm run prisma:migrate:deploy
 | 
				
			||||||
 | 
					node build/index.js
 | 
				
			||||||
							
								
								
									
										3538
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3538
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										17
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								package.json
									
									
									
									
									
								
							@@ -17,10 +17,10 @@
 | 
				
			|||||||
    "dev": "concurrently -k -n \"TypeScript,Node\" -p \"[{name}]\" -c \"blue,green\" \"swc ./src --out-dir ./build --watch\" \"cross-env NODE_ENV=development nodemon -e js,json,yaml build/index.js\"",
 | 
					    "dev": "concurrently -k -n \"TypeScript,Node\" -p \"[{name}]\" -c \"blue,green\" \"swc ./src --out-dir ./build --watch\" \"cross-env NODE_ENV=development nodemon -e js,json,yaml build/index.js\"",
 | 
				
			||||||
    "generate": "plop",
 | 
					    "generate": "plop",
 | 
				
			||||||
    "lint:commit": "commitlint",
 | 
					    "lint:commit": "commitlint",
 | 
				
			||||||
    "lint:docker": "dockerfilelint './Dockerfile'",
 | 
					 | 
				
			||||||
    "lint:editorconfig": "editorconfig-checker",
 | 
					    "lint:editorconfig": "editorconfig-checker",
 | 
				
			||||||
    "lint:markdown": "markdownlint '**/*.md' --dot --ignore 'node_modules'",
 | 
					    "lint:markdown": "markdownlint '**/*.md' --dot --ignore 'node_modules'",
 | 
				
			||||||
    "lint:typescript": "eslint '**/*.{js,ts,jsx,tsx}'",
 | 
					    "lint:typescript": "eslint '**/*.{js,ts,jsx,tsx}'",
 | 
				
			||||||
 | 
					    "lint:prettier": "prettier '.' --check",
 | 
				
			||||||
    "lint:staged": "lint-staged",
 | 
					    "lint:staged": "lint-staged",
 | 
				
			||||||
    "test": "jest",
 | 
					    "test": "jest",
 | 
				
			||||||
    "prisma:generate": "prisma generate",
 | 
					    "prisma:generate": "prisma generate",
 | 
				
			||||||
@@ -52,14 +52,14 @@
 | 
				
			|||||||
    "ms": "2.1.3",
 | 
					    "ms": "2.1.3",
 | 
				
			||||||
    "nodemailer": "6.7.2",
 | 
					    "nodemailer": "6.7.2",
 | 
				
			||||||
    "read-pkg": "5.2.0",
 | 
					    "read-pkg": "5.2.0",
 | 
				
			||||||
    "socket.io": "4.4.0"
 | 
					    "socket.io": "4.4.1"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@commitlint/cli": "16.0.1",
 | 
					    "@commitlint/cli": "16.0.1",
 | 
				
			||||||
    "@commitlint/config-conventional": "16.0.0",
 | 
					    "@commitlint/config-conventional": "16.0.0",
 | 
				
			||||||
    "@saithodev/semantic-release-backmerge": "2.1.0",
 | 
					    "@saithodev/semantic-release-backmerge": "2.1.0",
 | 
				
			||||||
    "@swc/cli": "0.1.55",
 | 
					    "@swc/cli": "0.1.55",
 | 
				
			||||||
    "@swc/core": "1.2.124",
 | 
					    "@swc/core": "1.2.127",
 | 
				
			||||||
    "@swc/jest": "0.2.15",
 | 
					    "@swc/jest": "0.2.15",
 | 
				
			||||||
    "@types/bcryptjs": "2.4.2",
 | 
					    "@types/bcryptjs": "2.4.2",
 | 
				
			||||||
    "@types/busboy": "0.3.1",
 | 
					    "@types/busboy": "0.3.1",
 | 
				
			||||||
@@ -68,26 +68,25 @@
 | 
				
			|||||||
    "@types/jest": "27.4.0",
 | 
					    "@types/jest": "27.4.0",
 | 
				
			||||||
    "@types/jsonwebtoken": "8.5.6",
 | 
					    "@types/jsonwebtoken": "8.5.6",
 | 
				
			||||||
    "@types/ms": "0.7.31",
 | 
					    "@types/ms": "0.7.31",
 | 
				
			||||||
    "@types/node": "17.0.5",
 | 
					    "@types/node": "17.0.8",
 | 
				
			||||||
    "@types/nodemailer": "6.4.4",
 | 
					    "@types/nodemailer": "6.4.4",
 | 
				
			||||||
    "@typescript-eslint/eslint-plugin": "4.33.0",
 | 
					    "@typescript-eslint/eslint-plugin": "4.33.0",
 | 
				
			||||||
    "concurrently": "6.5.1",
 | 
					    "concurrently": "7.0.0",
 | 
				
			||||||
    "cross-env": "7.0.3",
 | 
					    "cross-env": "7.0.3",
 | 
				
			||||||
    "dockerfilelint": "1.8.0",
 | 
					 | 
				
			||||||
    "editorconfig-checker": "4.0.2",
 | 
					    "editorconfig-checker": "4.0.2",
 | 
				
			||||||
    "eslint": "7.32.0",
 | 
					    "eslint": "7.32.0",
 | 
				
			||||||
    "eslint-config-prettier": "8.3.0",
 | 
					    "eslint-config-prettier": "8.3.0",
 | 
				
			||||||
    "eslint-config-standard-with-typescript": "21.0.1",
 | 
					    "eslint-config-standard-with-typescript": "21.0.1",
 | 
				
			||||||
    "eslint-plugin-import": "2.25.3",
 | 
					    "eslint-plugin-import": "2.25.4",
 | 
				
			||||||
    "eslint-plugin-node": "11.1.0",
 | 
					    "eslint-plugin-node": "11.1.0",
 | 
				
			||||||
    "eslint-plugin-prettier": "4.0.0",
 | 
					    "eslint-plugin-prettier": "4.0.0",
 | 
				
			||||||
    "eslint-plugin-promise": "5.1.1",
 | 
					    "eslint-plugin-promise": "5.1.1",
 | 
				
			||||||
    "eslint-plugin-unicorn": "40.0.0",
 | 
					    "eslint-plugin-unicorn": "40.0.0",
 | 
				
			||||||
    "husky": "7.0.4",
 | 
					    "husky": "7.0.4",
 | 
				
			||||||
    "jest": "27.4.5",
 | 
					    "jest": "27.4.7",
 | 
				
			||||||
    "jest-mock-extended": "2.0.4",
 | 
					    "jest-mock-extended": "2.0.4",
 | 
				
			||||||
    "jest-ts-webcompat-resolver": "1.0.0",
 | 
					    "jest-ts-webcompat-resolver": "1.0.0",
 | 
				
			||||||
    "lint-staged": "12.1.4",
 | 
					    "lint-staged": "12.1.5",
 | 
				
			||||||
    "markdownlint-cli": "0.30.0",
 | 
					    "markdownlint-cli": "0.30.0",
 | 
				
			||||||
    "nodemon": "2.0.15",
 | 
					    "nodemon": "2.0.15",
 | 
				
			||||||
    "plop": "3.0.5",
 | 
					    "plop": "3.0.5",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
import { PrismaClient } from '@prisma/client'
 | 
					import { PrismaClient } from '@prisma/client'
 | 
				
			||||||
import { mockDeep, mockReset } from 'jest-mock-extended'
 | 
					import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended'
 | 
				
			||||||
import { DeepMockProxy } from 'jest-mock-extended/lib/cjs/Mock'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import prisma from '../tools/database/prisma.js'
 | 
					import prisma from '../tools/database/prisma.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,8 @@ import { userSettingsExample } from '../../models/UserSettings.js'
 | 
				
			|||||||
import {
 | 
					import {
 | 
				
			||||||
  generateAccessToken,
 | 
					  generateAccessToken,
 | 
				
			||||||
  generateRefreshToken
 | 
					  generateRefreshToken
 | 
				
			||||||
} from '../../tools/utils/jwtToken'
 | 
					} from '../../tools/utils/jwtToken.js'
 | 
				
			||||||
import { prismaMock } from '../setup'
 | 
					import { prismaMock } from '../setup.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const authenticateUserTest = async (): Promise<{
 | 
					export const authenticateUserTest = async (): Promise<{
 | 
				
			||||||
  accessToken: string
 | 
					  accessToken: string
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import { application } from '../../../../application.js'
 | 
					import { application } from '../../../../application.js'
 | 
				
			||||||
import { authenticateUserTest } from '../../../../__test__/utils/authenticateUserTest.js'
 | 
					import { authenticateUserTest } from '../../../../__test__/utils/authenticateUserTest.js'
 | 
				
			||||||
import { prismaMock } from '../../../../__test__/setup.js'
 | 
					import { prismaMock } from '../../../../__test__/setup.js'
 | 
				
			||||||
import { memberExample } from '../../../../models/Member'
 | 
					import { memberExample } from '../../../../models/Member.js'
 | 
				
			||||||
import { channelExample } from '../../../../models/Channel.js'
 | 
					import { channelExample } from '../../../../models/Channel.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('GET /channels/[channelId]', () => {
 | 
					describe('GET /channels/[channelId]', () => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,7 +44,6 @@ const postServiceSchema: FastifySchema = {
 | 
				
			|||||||
    401: fastifyErrors[401],
 | 
					    401: fastifyErrors[401],
 | 
				
			||||||
    403: fastifyErrors[403],
 | 
					    403: fastifyErrors[403],
 | 
				
			||||||
    404: fastifyErrors[404],
 | 
					    404: fastifyErrors[404],
 | 
				
			||||||
    431: fastifyErrors[431],
 | 
					 | 
				
			||||||
    500: fastifyErrors[500]
 | 
					    500: fastifyErrors[500]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
} as const
 | 
					} as const
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,7 @@ const postServiceSchema: FastifySchema = {
 | 
				
			|||||||
    401: fastifyErrors[401],
 | 
					    401: fastifyErrors[401],
 | 
				
			||||||
    403: fastifyErrors[403],
 | 
					    403: fastifyErrors[403],
 | 
				
			||||||
    404: fastifyErrors[404],
 | 
					    404: fastifyErrors[404],
 | 
				
			||||||
 | 
					    431: fastifyErrors[431],
 | 
				
			||||||
    500: fastifyErrors[500]
 | 
					    500: fastifyErrors[500]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
} as const
 | 
					} as const
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
import { application } from '../../../../../application.js'
 | 
					import { application } from '../../../../../application.js'
 | 
				
			||||||
import { authenticateUserTest } from '../../../../../__test__/utils/authenticateUserTest.js'
 | 
					import { authenticateUserTest } from '../../../../../__test__/utils/authenticateUserTest.js'
 | 
				
			||||||
import { prismaMock } from '../../../../../__test__/setup.js'
 | 
					import { prismaMock } from '../../../../../__test__/setup.js'
 | 
				
			||||||
import { memberExample } from '../../../../../models/Member'
 | 
					import { memberExample } from '../../../../../models/Member.js'
 | 
				
			||||||
import { guildExample } from '../../../../../models/Guild'
 | 
					import { guildExample } from '../../../../../models/Guild.js'
 | 
				
			||||||
import { channelExample } from '../../../../../models/Channel.js'
 | 
					import { channelExample } from '../../../../../models/Channel.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('GET /guilds/[guildId]/channels', () => {
 | 
					describe('GET /guilds/[guildId]/channels', () => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
import { Static, Type } from '@sinclair/typebox'
 | 
					import { Static, Type } from '@sinclair/typebox'
 | 
				
			||||||
import { FastifyPluginAsync, FastifySchema } from 'fastify'
 | 
					import { FastifyPluginAsync, FastifySchema } from 'fastify'
 | 
				
			||||||
 | 
					import fastifyMultipart from 'fastify-multipart'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import authenticateUser from '../../../../tools/plugins/authenticateUser.js'
 | 
					import authenticateUser from '../../../../tools/plugins/authenticateUser.js'
 | 
				
			||||||
import { fastifyErrors } from '../../../../models/utils.js'
 | 
					import { fastifyErrors } from '../../../../models/utils.js'
 | 
				
			||||||
import fastifyMultipart from 'fastify-multipart'
 | 
					 | 
				
			||||||
import prisma from '../../../../tools/database/prisma.js'
 | 
					import prisma from '../../../../tools/database/prisma.js'
 | 
				
			||||||
import { uploadFile } from '../../../../tools/utils/uploadFile.js'
 | 
					import { uploadFile } from '../../../../tools/utils/uploadFile.js'
 | 
				
			||||||
import { guildSchema } from '../../../../models/Guild.js'
 | 
					import { guildSchema } from '../../../../models/Guild.js'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										40
									
								
								src/services/uploads/guilds/get.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/services/uploads/guilds/get.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					import path from 'node:path'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { FastifyPluginAsync, FastifySchema } from 'fastify'
 | 
				
			||||||
 | 
					import { Static, Type } from '@sinclair/typebox'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { fastifyErrors } from '../../../models/utils.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const parameters = Type.Object({
 | 
				
			||||||
 | 
					  file: Type.String()
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Parameters = Static<typeof parameters>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getServiceSchema: FastifySchema = {
 | 
				
			||||||
 | 
					  tags: ['uploads'] as string[],
 | 
				
			||||||
 | 
					  params: parameters,
 | 
				
			||||||
 | 
					  response: {
 | 
				
			||||||
 | 
					    200: {
 | 
				
			||||||
 | 
					      type: 'string',
 | 
				
			||||||
 | 
					      format: 'binary'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    400: fastifyErrors[400],
 | 
				
			||||||
 | 
					    404: fastifyErrors[404],
 | 
				
			||||||
 | 
					    500: fastifyErrors[500]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					} as const
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getGuildsUploadsService: FastifyPluginAsync = async (fastify) => {
 | 
				
			||||||
 | 
					  fastify.route<{
 | 
				
			||||||
 | 
					    Params: Parameters
 | 
				
			||||||
 | 
					  }>({
 | 
				
			||||||
 | 
					    method: 'GET',
 | 
				
			||||||
 | 
					    url: '/uploads/guilds/:file',
 | 
				
			||||||
 | 
					    schema: getServiceSchema,
 | 
				
			||||||
 | 
					    handler: async (request, reply) => {
 | 
				
			||||||
 | 
					      const { file } = request.params
 | 
				
			||||||
 | 
					      return await reply.sendFile(path.join('guilds', file))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,58 +1,11 @@
 | 
				
			|||||||
import path from 'node:path'
 | 
					import { FastifyPluginAsync } from 'fastify'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { FastifyPluginAsync, FastifySchema } from 'fastify'
 | 
					import { getGuildsUploadsService } from './guilds/get.js'
 | 
				
			||||||
import { Static, Type } from '@sinclair/typebox'
 | 
					import { getMessagesUploadsService } from './messages/get.js'
 | 
				
			||||||
 | 
					import { getUsersUploadsService } from './users/get.js'
 | 
				
			||||||
import { fastifyErrors } from '../../models/utils'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const parametersUploadsSchema = Type.Object({
 | 
					 | 
				
			||||||
  image: Type.String()
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type ParametersUploadsSchemaType = Static<typeof parametersUploadsSchema>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const getUploadsSchema: FastifySchema = {
 | 
					 | 
				
			||||||
  tags: ['uploads'] as string[],
 | 
					 | 
				
			||||||
  params: parametersUploadsSchema,
 | 
					 | 
				
			||||||
  response: {
 | 
					 | 
				
			||||||
    200: {
 | 
					 | 
				
			||||||
      type: 'string',
 | 
					 | 
				
			||||||
      format: 'binary'
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    400: fastifyErrors[400],
 | 
					 | 
				
			||||||
    404: fastifyErrors[404],
 | 
					 | 
				
			||||||
    500: fastifyErrors[500]
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
} as const
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const uploadsService: FastifyPluginAsync = async (fastify) => {
 | 
					export const uploadsService: FastifyPluginAsync = async (fastify) => {
 | 
				
			||||||
  fastify.route<{ Params: ParametersUploadsSchemaType }>({
 | 
					  await fastify.register(getGuildsUploadsService)
 | 
				
			||||||
    method: 'GET',
 | 
					  await fastify.register(getMessagesUploadsService)
 | 
				
			||||||
    url: '/uploads/users/:image',
 | 
					  await fastify.register(getUsersUploadsService)
 | 
				
			||||||
    schema: getUploadsSchema,
 | 
					 | 
				
			||||||
    handler: async (request, reply) => {
 | 
					 | 
				
			||||||
      const { image } = request.params
 | 
					 | 
				
			||||||
      return await reply.sendFile(path.join('users', image))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  fastify.route<{ Params: ParametersUploadsSchemaType }>({
 | 
					 | 
				
			||||||
    method: 'GET',
 | 
					 | 
				
			||||||
    url: '/uploads/guilds/:image',
 | 
					 | 
				
			||||||
    schema: getUploadsSchema,
 | 
					 | 
				
			||||||
    handler: async (request, reply) => {
 | 
					 | 
				
			||||||
      const { image } = request.params
 | 
					 | 
				
			||||||
      return await reply.sendFile(path.join('guilds', image))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  fastify.route<{ Params: ParametersUploadsSchemaType }>({
 | 
					 | 
				
			||||||
    method: 'GET',
 | 
					 | 
				
			||||||
    url: '/uploads/messages/:image',
 | 
					 | 
				
			||||||
    schema: getUploadsSchema,
 | 
					 | 
				
			||||||
    handler: async (request, reply) => {
 | 
					 | 
				
			||||||
      const { image } = request.params
 | 
					 | 
				
			||||||
      return await reply.sendFile(path.join('messages', image))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  })
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										76
									
								
								src/services/uploads/messages/get.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								src/services/uploads/messages/get.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					import path from 'node:path'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { FastifyPluginAsync, FastifySchema } from 'fastify'
 | 
				
			||||||
 | 
					import { Static, Type } from '@sinclair/typebox'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { fastifyErrors } from '../../../models/utils.js'
 | 
				
			||||||
 | 
					import authenticateUser from '../../../tools/plugins/authenticateUser.js'
 | 
				
			||||||
 | 
					import prisma from '../../../tools/database/prisma.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const parameters = Type.Object({
 | 
				
			||||||
 | 
					  file: Type.String()
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Parameters = Static<typeof parameters>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getServiceSchema: FastifySchema = {
 | 
				
			||||||
 | 
					  tags: ['uploads'] as string[],
 | 
				
			||||||
 | 
					  security: [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      bearerAuth: []
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ] as Array<{ [key: string]: [] }>,
 | 
				
			||||||
 | 
					  params: parameters,
 | 
				
			||||||
 | 
					  response: {
 | 
				
			||||||
 | 
					    200: {
 | 
				
			||||||
 | 
					      type: 'string',
 | 
				
			||||||
 | 
					      format: 'binary'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    400: fastifyErrors[400],
 | 
				
			||||||
 | 
					    401: fastifyErrors[401],
 | 
				
			||||||
 | 
					    403: fastifyErrors[403],
 | 
				
			||||||
 | 
					    404: fastifyErrors[404],
 | 
				
			||||||
 | 
					    500: fastifyErrors[500]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					} as const
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getMessagesUploadsService: FastifyPluginAsync = async (
 | 
				
			||||||
 | 
					  fastify
 | 
				
			||||||
 | 
					) => {
 | 
				
			||||||
 | 
					  await fastify.register(authenticateUser)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fastify.route<{
 | 
				
			||||||
 | 
					    Params: Parameters
 | 
				
			||||||
 | 
					  }>({
 | 
				
			||||||
 | 
					    method: 'GET',
 | 
				
			||||||
 | 
					    url: '/uploads/messages/:file',
 | 
				
			||||||
 | 
					    schema: getServiceSchema,
 | 
				
			||||||
 | 
					    handler: async (request, reply) => {
 | 
				
			||||||
 | 
					      if (request.user == null) {
 | 
				
			||||||
 | 
					        throw fastify.httpErrors.forbidden()
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      const { file } = request.params
 | 
				
			||||||
 | 
					      const message = await prisma.message.findFirst({
 | 
				
			||||||
 | 
					        where: { value: `/uploads/messages/${file}` },
 | 
				
			||||||
 | 
					        include: {
 | 
				
			||||||
 | 
					          member: {
 | 
				
			||||||
 | 
					            select: { guildId: true }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      if (message == null) {
 | 
				
			||||||
 | 
					        throw fastify.httpErrors.notFound('Message not found')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      const member = await prisma.member.findFirst({
 | 
				
			||||||
 | 
					        where: {
 | 
				
			||||||
 | 
					          guildId: message.member?.guildId,
 | 
				
			||||||
 | 
					          userId: request.user.current.id
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					      if (member == null) {
 | 
				
			||||||
 | 
					        throw fastify.httpErrors.notFound('Member not found')
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return await reply.sendFile(path.join('messages', file))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								src/services/uploads/users/get.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/services/uploads/users/get.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					import path from 'node:path'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { FastifyPluginAsync, FastifySchema } from 'fastify'
 | 
				
			||||||
 | 
					import { Static, Type } from '@sinclair/typebox'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { fastifyErrors } from '../../../models/utils.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const parameters = Type.Object({
 | 
				
			||||||
 | 
					  file: Type.String()
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Parameters = Static<typeof parameters>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getServiceSchema: FastifySchema = {
 | 
				
			||||||
 | 
					  tags: ['uploads'] as string[],
 | 
				
			||||||
 | 
					  params: parameters,
 | 
				
			||||||
 | 
					  response: {
 | 
				
			||||||
 | 
					    200: {
 | 
				
			||||||
 | 
					      type: 'string',
 | 
				
			||||||
 | 
					      format: 'binary'
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    400: fastifyErrors[400],
 | 
				
			||||||
 | 
					    404: fastifyErrors[404],
 | 
				
			||||||
 | 
					    500: fastifyErrors[500]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					} as const
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getUsersUploadsService: FastifyPluginAsync = async (fastify) => {
 | 
				
			||||||
 | 
					  fastify.route<{
 | 
				
			||||||
 | 
					    Params: Parameters
 | 
				
			||||||
 | 
					  }>({
 | 
				
			||||||
 | 
					    method: 'GET',
 | 
				
			||||||
 | 
					    url: '/uploads/users/:file',
 | 
				
			||||||
 | 
					    schema: getServiceSchema,
 | 
				
			||||||
 | 
					    handler: async (request, reply) => {
 | 
				
			||||||
 | 
					      const { file } = request.params
 | 
				
			||||||
 | 
					      return await reply.sendFile(path.join('users', file))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
import { Type } from '@sinclair/typebox'
 | 
					import { Type } from '@sinclair/typebox'
 | 
				
			||||||
import { FastifyPluginAsync, FastifySchema } from 'fastify'
 | 
					import { FastifyPluginAsync, FastifySchema } from 'fastify'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import fastifyMultipart from 'fastify-multipart'
 | 
				
			||||||
import authenticateUser from '../../../../tools/plugins/authenticateUser.js'
 | 
					import authenticateUser from '../../../../tools/plugins/authenticateUser.js'
 | 
				
			||||||
import { fastifyErrors } from '../../../../models/utils.js'
 | 
					import { fastifyErrors } from '../../../../models/utils.js'
 | 
				
			||||||
import fastifyMultipart from 'fastify-multipart'
 | 
					 | 
				
			||||||
import prisma from '../../../../tools/database/prisma.js'
 | 
					import prisma from '../../../../tools/database/prisma.js'
 | 
				
			||||||
import { uploadFile } from '../../../../tools/utils/uploadFile.js'
 | 
					import { uploadFile } from '../../../../tools/utils/uploadFile.js'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import dotenv from 'dotenv'
 | 
					import dotenv from 'dotenv'
 | 
				
			||||||
import nodemailer from 'nodemailer'
 | 
					import nodemailer from 'nodemailer'
 | 
				
			||||||
import SMTPTransport from 'nodemailer/lib/smtp-transport'
 | 
					import type SMTPTransport from 'nodemailer/lib/smtp-transport.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dotenv.config()
 | 
					dotenv.config()
 | 
				
			||||||
const EMAIL_PORT = parseInt(process.env.EMAIL_PORT ?? '465', 10)
 | 
					const EMAIL_PORT = parseInt(process.env.EMAIL_PORT ?? '465', 10)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import { parseStringNullish } from '../parseStringNullish'
 | 
					import { parseStringNullish } from '../parseStringNullish.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const defaultString = 'defaultString'
 | 
					const defaultString = 'defaultString'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user