deps: update outdated and critical dependencies (#532)

* deps: bump critical deps version

* chore: specify sentry and dd debug mode

* chore: enable SwcMinify

* chore: casing

* deps: bump mongoose version to 6.8.3

* Revert "deps: bump mongoose version to 6.8.3"

This reverts commit d5b90b5c0909545d4d21553d50c5681bd93a57a4.

* deps: change mongoose version to 5.13.15

* fix: typing

* deps: update audited deps

* deps: update next-pwa and dd-trace@2

* deps: update dd-trace@3 and sentry

* fix: redirects

* fix: style

* feat: redirect using next config

* deps: update mongoose to 6.9.0

* chore: change next version in package.json

* chore: change next version to 12.3.2

* fix: model compile issue

* chore: lint

* chore: remove any

* deps: update jest version to 29

* deps: resolve remaining vulnerabilities

---------

Co-authored-by: skinmaker1345 <me@skinmaker.dev>
This commit is contained in:
Eunwoo Choi 2023-02-01 01:34:30 +09:00 committed by GitHub
parent 5a28ac284c
commit 2d68f7aadd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 3132 additions and 2877 deletions

View File

@ -18,4 +18,7 @@ DISCORD_CLIENT_INTENTS=32767
GITHUB_CLIENT_ID=GH_CLIENT_ID
GITHUB_CLIENT_SECRET=GH_CLIENT_SECRET
CSRF_SECRET=CSRF_SECRET
CSRF_SECRET=CSRF_SECRET
DD_TRACE_DEBUG=true
DD_TRACE_ENABLED=true

View File

@ -1,8 +1,6 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const tracer = require('dd-trace')
tracer.init({
debug: true
})
tracer.init()
module.exports = tracer

View File

@ -1,7 +1,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
moduleDirectories: ['node_modules', '.'],
moduleDirectories: ['node_modules', __dirname],
moduleNameMapper: {
'@types': '<rootDir>/types',
'^@utils/(.*)$': '<rootDir>/utils/$1',

1
next-env.d.ts vendored
View File

@ -1,5 +1,4 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited

View File

@ -1,8 +1,14 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { withSentryConfig } = require('@sentry/nextjs')
const withPWA = require('next-pwa')
const withPWA = require('next-pwa')({
disable: process.env.NODE_ENV !== 'production',
register: false
})
const VERSION = require('./package.json').version
/**
* @type {import('next').NextConfig}
*/
const NextConfig = {
webpack: (config, { isServer }) => {
if (!isServer) {
@ -10,10 +16,6 @@ const NextConfig = {
}
return config
},
pwa: {
disable: process.env.NODE_ENV !== 'production',
register: false
},
env: {
NEXT_PUBLIC_RELEASE_VERSION: VERSION,
SENTRY_SKIP_AUTO_RELEASE: true
@ -21,6 +23,21 @@ const NextConfig = {
future: {},
experimental: {
scrollRestoration: true
},
swcMinify: true,
redirects: async () => {
return [
{
source: '/developers',
destination: '/developers/applications',
permanent: true
},
{
source: '/developers/docs',
destination: '/developers/docs/시작하기',
permanent: true
}
]
}
}
module.exports = withSentryConfig(withPWA(NextConfig))

View File

@ -16,10 +16,7 @@
"dependencies": {
"@fortawesome/fontawesome-free": "5.15.3",
"@hcaptcha/react-hcaptcha": "0.3.6",
"@sentry/nextjs": "6.10.0",
"@sentry/node": "6.10.0",
"@sentry/react": "^6.10.0",
"@sentry/tracing": "6.10.0",
"@sentry/nextjs": "^7.31.1",
"abort-controller": "3.0.0",
"autoprefixer": "^10.3.1",
"badgen": "3.2.2",
@ -27,7 +24,7 @@
"csrf": "3.1.0",
"dataloader": "2.0.0",
"dayjs": "^1.10.6",
"dd-trace": "^1.1.0",
"dd-trace": "^3.11.0",
"difflib": "0.2.4",
"discord.js": "^14.2.0",
"emoji-mart": "3.0.1",
@ -36,13 +33,13 @@
"formik": "2.2.9",
"generate-license-file": "1.1.0",
"josa": "3.0.1",
"jsonwebtoken": "8.5.1",
"knex": "^0.95.8",
"mongoose": "^5.13.4",
"jsonwebtoken": "^9.0.0",
"knex": "^2.4.0",
"mongoose": "6.9.0",
"mysql": "2.18.1",
"next": "^11.1.3",
"next": "^12.3.2",
"next-connect": "0.10.1",
"next-pwa": "^5.2.24",
"next-pwa": "^5.6.0",
"next-seo": "^4.26.0",
"next-session": "3.4.0",
"node-emoji": "1.10.0",
@ -60,7 +57,7 @@
"react-showdown": "2.3.0",
"react-sortable-hoc": "2.0.0",
"react-use-clipboard": "1.0.7",
"sanitize-html": "2.4.0",
"sanitize-html": "^2.8.1",
"tailwindcss": "2.2.7",
"tlru": "1.0.2",
"twemoji": "13.1.0",
@ -76,7 +73,7 @@
"@types/express-rate-limit": "^5.1.3",
"@types/jest": "^26.0.24",
"@types/josa": "3.0.2",
"@types/jsonwebtoken": "^8.5.4",
"@types/jsonwebtoken": "^9.0.1",
"@types/node": "16.4.3",
"@types/node-emoji": "1.8.1",
"@types/node-fetch": "^2.5.12",
@ -84,7 +81,7 @@
"@types/rc-tooltip": "^3.7.4",
"@types/react": "^17.0.15",
"@types/react-select": "^4.0.17",
"@types/sanitize-html": "^2.3.2",
"@types/sanitize-html": "^2.8.0",
"@types/twemoji": "^12.1.2",
"@types/url-regex-safe": "1.0.0",
"@typescript-eslint/eslint-plugin": "4.28.5",
@ -96,10 +93,10 @@
"eslint-plugin-prettier": "3.4.0",
"eslint-plugin-react": "7.24.0",
"eslint-plugin-react-hooks": "4.2.0",
"jest": "27.0.6",
"jest": "^29.4.1",
"prettier": "^2.3.2",
"prettier-plugin-tailwind": "^2.2.12",
"ts-jest": "27.0.4",
"ts-jest": "^29.0.5",
"typescript": "4.6.4"
},
"license": "AGPL-3.0"

View File

@ -346,9 +346,11 @@ export const getServerSideProps = async (ctx: Context) => {
const desc = await get.botDescSafe(data.id)
const user = await get.Authorization(parsed?.token)
if((checkBotFlag(data.flags, 'trusted') || checkBotFlag(data.flags, 'partnered')) && data.vanity && data.vanity !== ctx.query.id) {
ctx.res.statusCode = 301
ctx.res.setHeader('Location', `/bots/${data.vanity}`)
return {
redirect: {
destination: `/bots/${data.vanity}`,
permanent: true
},
props: {}
}
}

View File

@ -9,7 +9,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
const data = await get.bot.load(ctx.query.id as string)
if(!data) return { props: {} }
const record = await Bots.updateOne({ _id: data.id, 'inviteMetrix.day': getYYMMDD() }, { $inc: { 'inviteMetrix.$.count': 1 } })
if(record.n === 0) await Bots.findByIdAndUpdate(data.id, { $push: { inviteMetrix: { count: 1 } } }, { upsert: true })
if(record.matchedCount === 0) await Bots.findByIdAndUpdate(data.id, { $push: { inviteMetrix: { count: 1 } } }, { upsert: true })
ctx.res.statusCode = 307
ctx.res.setHeader('Location', data.url || `https://discordapp.com/oauth2/authorize?client_id=${data.id}&scope=bot&permissions=0`)
return {

View File

@ -52,9 +52,13 @@ const Search:NextPage<SearchProps> = ({ botData, query }) => {
export const getServerSideProps = async(ctx: Context) => {
if(ctx.query.query && !ctx.query.q) ctx.query.q = ctx.query.query
if(!ctx.query?.q) {
ctx.res.statusCode = 301
ctx.res.setHeader('Location', '/')
return { props: {} }
return {
redirect: {
destination: '/',
permanent: true
},
props: {}
}
}
if(!ctx.query.page) ctx.query.page = '1'
const validate = await SearchQuerySchema.validate(ctx.query).then(el => el).catch(() => null)

View File

@ -1,15 +0,0 @@
import { GetServerSideProps, NextPage } from 'next'
const Docs: NextPage = () => {
return <></>
}
export const getServerSideProps: GetServerSideProps = async (ctx) => {
ctx.res.statusCode = 301
ctx.res.setHeader('Location', encodeURI('/developers/docs/시작하기'))
return {
props: {}
}
}
export default Docs

View File

@ -1,15 +0,0 @@
import { GetServerSideProps, NextPage } from 'next'
const Developers: NextPage = () => {
return <></>
}
export const getServerSideProps: GetServerSideProps = async (ctx) => {
ctx.res.statusCode = 301
ctx.res.setHeader('Location', '/developers/applications')
return {
props: {}
}
}
export default Developers

View File

@ -57,9 +57,13 @@ const Search:NextPage<SearchProps> = ({ botData, serverData, priority, query })
export const getServerSideProps = async(ctx: Context) => {
if(ctx.query.query && !ctx.query.q) ctx.query.q = ctx.query.query
if(!ctx.query?.q) {
ctx.res.statusCode = 301
ctx.res.setHeader('Location', '/')
return { props: {} }
return {
redirect: {
destination: '/',
permanent: true
},
props: {}
}
}
if(!ctx.query.page) ctx.query.page = '1'
const validate = await SearchQuerySchema.validate(ctx.query).then(el => el).catch(() => null)

View File

@ -281,9 +281,11 @@ export const getServerSideProps = async (ctx: Context) => {
const desc = safeImageHost(data.desc)
const user = await get.Authorization(parsed?.token)
if((checkServerFlag(data.flags, 'trusted') || checkServerFlag(data.flags, 'partnered')) && data.vanity && data.vanity !== ctx.query.id) {
ctx.res.statusCode = 301
ctx.res.setHeader('Location', `/servers/${data.vanity}`)
return {
redirect: {
destination: `/servers/${data.vanity}`,
permanent: true
},
props: {}
}
}

View File

@ -52,9 +52,13 @@ const Search:NextPage<SearchProps> = ({ serverData, query }) => {
export const getServerSideProps = async(ctx: Context) => {
if(ctx.query.query && !ctx.query.q) ctx.query.q = ctx.query.query
if(!ctx.query?.q) {
ctx.res.statusCode = 301
ctx.res.setHeader('Location', '/')
return { props: {} }
return {
redirect: {
destination: '/',
permanent: true
},
props: {}
}
}
if(!ctx.query.page) ctx.query.page = '1'
const validate = await SearchQuerySchema.validate(ctx.query).then(el => el).catch(() => null)

View File

@ -8,7 +8,7 @@ const SENTRY_DSN = process.env.NEXT_PUBLIC_SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
debug: true,
debug: process.env.SENTRY_DEBUG === 'true',
enabled: process.env.NODE_ENV === 'production'
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so

View File

@ -8,7 +8,7 @@ const SENTRY_DSN = process.env.SENTRY_DSN
Sentry.init({
dsn: SENTRY_DSN,
debug: true,
debug: process.env.SENTRY_DEBUG === 'true',
enabled: process.env.NODE_ENV=== 'production'
// Note: if you want to override the automatic release value, do not set a
// `release` value here - use the environment variable `SENTRY_RELEASE`, so

View File

@ -1,25 +1,42 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["components/*"],
"@utils/*": ["utils/*"],
"@types": ["types/index.ts"]
},
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": [
"components/*"
],
"@utils/*": [
"utils/*"
],
"@types": [
"types/index.ts"
]
},
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}

View File

@ -5,14 +5,15 @@ const privateKey = process.env.PRIVATE_KEY?.replace(/\\n/g, '\n')
export function sign(payload: string | Record<string, unknown>, options?: JWTSignOption): string | null {
try {
return jwt.sign(payload, privateKey, options ? { ...options, algorithm: 'RS256' } : { algorithm: 'RS256' })
return jwt.sign(payload, privateKey, options ? { ...options, algorithm: 'RS256', allowInsecureKeySizes: true } : { algorithm: 'RS256', allowInsecureKeySizes: true })
} catch {
return null
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function verify(token: string): any | null {
export function verify(token?: string): any | null {
if(!token) return null
try {
return jwt.verify(token, publicPem)
} catch(e) {

View File

@ -1,4 +1,4 @@
import mongoose from 'mongoose'
import mongoose, { InferSchemaType, Model, ObtainSchemaGeneric, Schema } from 'mongoose'
import { getYYMMDD } from './Tools'
mongoose.connect(`mongodb://${process.env.MONGO_USER}:${process.env.MONGO_PASSWORD}@${process.env.MONGO_HOST || 'localhost'}/${process.env.MONGO_DATABASE}`)
@ -25,5 +25,14 @@ const serverSchema = new mongoose.Schema({
data: {}
})
export const Bots = mongoose.models.bots || mongoose.model('bots', botSchema)
export const Servers = mongoose.models.servers || mongoose.model('servers', serverSchema)
type ModelType<TSchema extends Schema> = Model<
InferSchemaType<TSchema>,
ObtainSchemaGeneric<TSchema, 'TQueryHelpers'>,
ObtainSchemaGeneric<TSchema, 'TInstanceMethods'>,
ObtainSchemaGeneric<TSchema, 'TVirtuals'>,
TSchema
> &
ObtainSchemaGeneric<TSchema, 'TStaticMethods'>
export const Bots = (mongoose.models.bots as ModelType<typeof botSchema>) || mongoose.model('bots', botSchema)
export const Servers = (mongoose.models.servers as ModelType<typeof serverSchema>) || mongoose.model('servers', serverSchema)

View File

@ -376,7 +376,7 @@ async function voteBot(userID: string, botID: string): Promise<number|boolean> {
await knex('bots').where({ id: botID }).increment('votes', 1)
await knex('users').where({ id: userID }).update({ votes: JSON.stringify(data) })
const record = await Bots.updateOne({ _id: botID, 'voteMetrix.day': getYYMMDD() }, { $inc: { 'voteMetrix.$.increasement': 1, 'voteMetrix.$.count': 1 } })
if(record.n === 0) await Bots.findByIdAndUpdate(botID, { $push: { voteMetrix: { count: (await knex('bots').where({ id: botID }))[0].votes } } }, { upsert: true })
if(record.matchedCount === 0) await Bots.findByIdAndUpdate(botID, { $push: { voteMetrix: { count: (await knex('bots').where({ id: botID }))[0].votes } } }, { upsert: true })
return true
}
@ -705,7 +705,7 @@ export function safeImageHost(text: string) {
async function viewBot(id: string) {
const record = await Bots.updateOne({ _id: id, 'viewMetrix.day': getYYMMDD() }, { $inc: { 'viewMetrix.$.count': 1 } })
if(record.n === 0) await Bots.findByIdAndUpdate(id, { $push: { viewMetrix: { count: 0 } } }, { upsert: true })
if(record.matchedCount === 0) await Bots.findByIdAndUpdate(id, { $push: { viewMetrix: { count: 0 } } }, { upsert: true })
}
export const get = {

5778
yarn.lock

File diff suppressed because it is too large Load Diff