fix(services): restrict GET /uploads/messages/:file to authorized users
This commit is contained in:
parent
03946f26e7
commit
97b1d04261
@ -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