Compare commits

..

8 Commits

Author SHA1 Message Date
skinmaker1345
c24c979931 fix: typo 2025-06-27 22:22:31 +09:00
skinmaker1345
fd5f3c537e chore: add license related enforcements 2025-06-27 20:17:28 +09:00
skinmaker1345
f4d388cca7 fix: do not send vanity log when no changes are made 2025-06-27 20:11:08 +09:00
skinmaker1345
c9df8d01e3 chore: specify enforcement description 2025-06-27 20:11:08 +09:00
skinmaker1345
5cdb0f5dd1 feat: add alert page 2025-06-27 20:11:08 +09:00
skinmaker1345
7a983d7d96 feat: add enforcements field 2025-06-27 20:11:08 +09:00
skinmaker1345
9aaf66018f fix: remove authorization check to /servers/:id/owners 2025-06-22 00:12:56 +09:00
SKINMAKER
a2adbf116e
feat: make all API Requests require authorization (#686) 2025-06-21 22:18:53 +09:00
10 changed files with 40 additions and 5 deletions

View File

@ -39,6 +39,10 @@ const patchLimiter = rateLimit({
}) })
const Bots = RequestHandler() const Bots = RequestHandler()
.get(async (req: GetApiRequest, res) => { .get(async (req: GetApiRequest, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const bot = await get.bot.load(req.query.id) const bot = await get.bot.load(req.query.id)
if (!bot) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' }) if (!bot) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 봇입니다.' })
else { else {

View File

@ -4,7 +4,11 @@ import ResponseWrapper from '@utils/ResponseWrapper'
import { Bot, List } from '@types' import { Bot, List } from '@types'
const NewList = RequestHandler().get(async (_req, res) => { const NewList = RequestHandler().get(async (req, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const result = await get.list.new.load(1) const result = await get.list.new.load(1)
return ResponseWrapper<List<Bot>>(res, { code: 200, data: result }) return ResponseWrapper<List<Bot>>(res, { code: 200, data: result })
}) })

View File

@ -6,6 +6,10 @@ import { Bot, List } from '@types'
import Yup from '@utils/Yup' import Yup from '@utils/Yup'
const VotesList = RequestHandler().get(async (req, res) => { const VotesList = RequestHandler().get(async (req, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const page = await Yup.number() const page = await Yup.number()
.positive() .positive()
.integer() .integer()

View File

@ -8,6 +8,10 @@ import { SearchQuerySchema } from '@utils/Yup'
import { Bot, Server, List } from '@types' import { Bot, Server, List } from '@types'
const Search = RequestHandler().get(async (req: ApiRequest, res) => { const Search = RequestHandler().get(async (req: ApiRequest, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const validated = await SearchQuerySchema.validate({ q: req.query.q || req.query.query, page: 1 }) const validated = await SearchQuerySchema.validate({ q: req.query.q || req.query.query, page: 1 })
.then((el) => el) .then((el) => el)
.catch((e) => { .catch((e) => {

View File

@ -8,6 +8,10 @@ import { SearchQuerySchema } from '@utils/Yup'
import { Bot, List } from '@types' import { Bot, List } from '@types'
const SearchBots = RequestHandler().get(async (req: ApiRequest, res: NextApiResponse) => { const SearchBots = RequestHandler().get(async (req: ApiRequest, res: NextApiResponse) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const validated = await SearchQuerySchema.validate({ const validated = await SearchQuerySchema.validate({
q: req.query.q || req.query.query, q: req.query.q || req.query.query,
page: req.query.page, page: req.query.page,

View File

@ -8,6 +8,10 @@ import { SearchQuerySchema } from '@utils/Yup'
import { Server, List } from '@types' import { Server, List } from '@types'
const SearchServers = RequestHandler().get(async (req: ApiRequest, res: NextApiResponse) => { const SearchServers = RequestHandler().get(async (req: ApiRequest, res: NextApiResponse) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const validated = await SearchQuerySchema.validate({ const validated = await SearchQuerySchema.validate({
q: req.query.q || req.query.query, q: req.query.q || req.query.query,
page: req.query.page, page: req.query.page,

View File

@ -36,6 +36,10 @@ const patchLimiter = rateLimit({
}) })
const Servers = RequestHandler() const Servers = RequestHandler()
.get(async (req: GetApiRequest, res) => { .get(async (req: GetApiRequest, res) => {
const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const server = await get.server.load(req.query.id) const server = await get.server.load(req.query.id)
if (!server) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 서버 입니다.' }) if (!server) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 서버 입니다.' })
else { else {

View File

@ -5,7 +5,10 @@ import ResponseWrapper from '@utils/ResponseWrapper'
import RequestHandler from '@utils/RequestHandler' import RequestHandler from '@utils/RequestHandler'
const Users = RequestHandler().get(async (req: ApiRequest, res) => { const Users = RequestHandler().get(async (req: ApiRequest, res) => {
console.log(req.query) const auth = req.headers.authorization
? await get.BotAuthorization(req.headers.authorization)
: await get.Authorization(req.cookies.token)
if (!auth) return ResponseWrapper(res, { code: 401 })
const user = await get.user.load(req.query?.id) const user = await get.user.load(req.query?.id)
if (!user) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 유저 입니다.' }) if (!user) return ResponseWrapper(res, { code: 404, message: '존재하지 않는 유저 입니다.' })
else return ResponseWrapper(res, { code: 200, data: user }) else return ResponseWrapper(res, { code: 200, data: user })

View File

@ -5,6 +5,8 @@ import type { NextPageContext } from 'next'
export type Nullable<T> = T | null export type Nullable<T> = T | null
export type ValueOf<T> = T[keyof T]
export interface Bot { export interface Bot {
id: string id: string
name: string name: string
@ -32,7 +34,7 @@ export interface Bot {
owners: User[] | string[] owners: User[] | string[]
} }
export type BotEnforcementKeys = 'JOIN_ENFORCED' | 'JOIN_PARTIALLY_ENFORCED' export type BotEnforcementKeys = ValueOf<typeof botEnforcements>
export interface RawGuild { export interface RawGuild {
id: string id: string

View File

@ -121,9 +121,11 @@ export const botCategoryDescription = {
} }
export const botEnforcements = { export const botEnforcements = {
'서버 참여가 강제되는 명령어가 있습니다': 'JOIN_PARTIALLY_ENFORCED', '서버 참여가 필요한 기능이 있습니다': 'JOIN_PARTIALLY_ENFORCED',
'서버 참여 없이는 봇의 핵심 기능을 사용할 수 없습니다': 'JOIN_ENFORCED', '서버 참여 없이는 봇의 핵심 기능을 사용할 수 없습니다': 'JOIN_ENFORCED',
} '유료 구매가 필요한 기능이 있습니다': 'LICENSE_PARTIALLY_ENFORCED',
'유료 구매 없이는 봇의 핵심 기능을 사용할 수 없습니다': 'LICENSE_ENFORCED',
} as const
export const botCategoryIcon = { export const botCategoryIcon = {
: 'fas fa-cogs', : 'fas fa-cogs',