mirror of
https://github.com/koreanbots/core.git
synced 2025-12-15 14:10:22 +00:00
feat: added captcha at addbot
This commit is contained in:
parent
c90afdb75d
commit
0a7edca2d8
@ -1,4 +1,5 @@
|
||||
import HCaptcha from '@hcaptcha/react-hcaptcha'
|
||||
import { Ref } from 'react'
|
||||
|
||||
const Captcha = ({ dark, onVerify }:CaptchaProps):JSX.Element => {
|
||||
return <HCaptcha sitekey='43e556b4-cc90-494f-b100-378b906bb736' theme={dark ? 'dark' : 'light'} onVerify={onVerify}/>
|
||||
@ -7,6 +8,7 @@ const Captcha = ({ dark, onVerify }:CaptchaProps):JSX.Element => {
|
||||
interface CaptchaProps {
|
||||
dark: boolean
|
||||
onVerify(token: string, eKey?: string): void
|
||||
ref?: Ref<HCaptcha>
|
||||
}
|
||||
|
||||
export default Captcha
|
||||
@ -1,9 +1,10 @@
|
||||
import { NextPage, NextPageContext } from 'next'
|
||||
import { useState } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import dynamic from 'next/dynamic'
|
||||
import Link from 'next/link'
|
||||
import { Form, Formik } from 'formik'
|
||||
import HCaptcha from '@hcaptcha/react-hcaptcha'
|
||||
|
||||
import { get } from '@utils/Query'
|
||||
import { cleanObject, parseCookie, redirectTo } from '@utils/Tools'
|
||||
@ -25,18 +26,44 @@ const Selects = dynamic(() => import('@components/Form/Selects'))
|
||||
const Button = dynamic(() => import('@components/Button'))
|
||||
const Container = dynamic(() => import('@components/Container'))
|
||||
const Message = dynamic(() => import('@components/Message'))
|
||||
const Captcha = dynamic(() => import('@components/Captcha'))
|
||||
const SEO = dynamic(() => import('@components/SEO'))
|
||||
|
||||
const AddBot:NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
|
||||
const [ data, setData ] = useState<ResponseProps<SubmittedBot>>(null)
|
||||
const [ captcha, setCaptcha ] = useState(false)
|
||||
const captchaRef = useRef<HCaptcha>()
|
||||
const router = useRouter()
|
||||
const initialValues: AddBotSubmit = {
|
||||
agree: false,
|
||||
id: '',
|
||||
prefix: '',
|
||||
library: '',
|
||||
category: [],
|
||||
intro: '',
|
||||
desc: `<!-- 이 설명을 지우시고 원하시는 설명을 적으셔도 좋습니다! -->
|
||||
# 봇이름
|
||||
자신의 봇을 자유롭게 표현해보세요!
|
||||
|
||||
## ✏️ 소개
|
||||
|
||||
무엇이 목적인 봇인가요?
|
||||
|
||||
## 🛠️ 기능
|
||||
|
||||
- 어떤
|
||||
- 기능
|
||||
- 있나요?`,
|
||||
_csrf: csrfToken,
|
||||
_captcha: 'captcha'
|
||||
}
|
||||
function toLogin() {
|
||||
localStorage.redirectTo = window.location.href
|
||||
redirectTo(router, 'login')
|
||||
}
|
||||
|
||||
async function submitBot(value: AddBotSubmit) {
|
||||
const res = await Fetch<SubmittedBot>(`/bots/${value.id}`, { method: 'POST', body: JSON.stringify(cleanObject<AddBotSubmit>(value)) })
|
||||
async function submitBot(value: AddBotSubmit, token: string) {
|
||||
const res = await Fetch<SubmittedBot>(`/bots/${value.id}`, { method: 'POST', body: JSON.stringify(cleanObject<AddBotSubmit>({ ...value, _captcha: token})) })
|
||||
setData(res)
|
||||
}
|
||||
if(!logged) {
|
||||
@ -61,31 +88,10 @@ const AddBot:NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
|
||||
|
||||
</Message> : <></>
|
||||
}
|
||||
<Formik initialValues={{
|
||||
agree: false,
|
||||
id: '',
|
||||
prefix: '',
|
||||
library: '',
|
||||
category: [],
|
||||
intro: '',
|
||||
desc: `<!-- 이 설명을 지우시고 원하시는 설명을 적으셔도 좋습니다! -->
|
||||
# 봇이름
|
||||
자신의 봇을 자유롭게 표현해보세요!
|
||||
|
||||
## ✏️ 소개
|
||||
|
||||
무엇이 목적인 봇인가요?
|
||||
|
||||
## 🛠️ 기능
|
||||
|
||||
- 어떤
|
||||
- 기능
|
||||
- 있나요?`,
|
||||
_csrf: csrfToken
|
||||
}}
|
||||
<Formik initialValues={initialValues}
|
||||
validationSchema={AddBotSubmitSchema}
|
||||
onSubmit={submitBot}>
|
||||
{({ errors, touched, values, setFieldTouched, setFieldValue }) => (
|
||||
onSubmit={() => setCaptcha(true)}>
|
||||
{({ errors, touched, values, isValid, setFieldTouched, setFieldValue }) => (
|
||||
<Form>
|
||||
<div className='py-3'>
|
||||
<Message type='warning'>
|
||||
@ -113,7 +119,6 @@ const AddBot:NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
|
||||
</div>
|
||||
</Label>
|
||||
<Divider />
|
||||
|
||||
<Label For='id' label='봇 ID' labelDesc='봇의 클라이언트 ID를 의미합니다.' error={errors.id && touched.id ? errors.id : null} short required>
|
||||
<Input name='id' placeholder='653534001742741552' />
|
||||
</Label>
|
||||
@ -169,11 +174,20 @@ const AddBot:NextPage<AddBotProps> = ({ logged, user, csrfToken, theme }) => {
|
||||
</Segment>
|
||||
</Label>
|
||||
<Divider />
|
||||
<Button type='submit' onClick={() => window.scrollTo({ top: 0 })}>
|
||||
{
|
||||
captcha ? <Captcha ref={captchaRef} dark={theme === 'dark'} onVerify={(token) => {
|
||||
submitBot(values, token)
|
||||
window.scrollTo({ top: 0 })
|
||||
setCaptcha(false)
|
||||
captchaRef?.current?.resetCaptcha()
|
||||
}} /> : <Button type='submit' onClick={() => {
|
||||
if(!isValid) window.scrollTo({ top: 0 })
|
||||
} }>
|
||||
<>
|
||||
<i className='far fa-paper-plane'/> 제출
|
||||
</>
|
||||
</Button>
|
||||
}
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { NextApiRequest } from 'next'
|
||||
import rateLimit from 'express-rate-limit'
|
||||
|
||||
import { get, put, update } from '@utils/Query'
|
||||
import { CaptchaVerify, get, put, update } from '@utils/Query'
|
||||
import ResponseWrapper from '@utils/ResponseWrapper'
|
||||
import { checkToken } from '@utils/Csrf'
|
||||
import { AddBotSubmit, AddBotSubmitSchema, ManageBot, ManageBotSchema } from '@utils/Yup'
|
||||
@ -41,6 +41,8 @@ const Bots = RequestHandler()
|
||||
if (!validated) return
|
||||
if (validated.id !== req.query.id)
|
||||
return ResponseWrapper(res, { code: 400, errors: ['요청 주소와 Body의 정보가 다릅니다.'] })
|
||||
const captcha = await CaptchaVerify(validated._captcha)
|
||||
if(!captcha) return ResponseWrapper(res, { code: 400, message: '캡챠 검증에 실패하였습니다.' })
|
||||
const result = await put.submitBot(user, validated)
|
||||
if (result === 1)
|
||||
return ResponseWrapper(res, {
|
||||
|
||||
@ -185,6 +185,9 @@ export const SpecialEndPoints = {
|
||||
Github: {
|
||||
Token: (clientID: string, clientSecret: string, code: string) => `https://github.com/login/oauth/access_token?client_id=${clientID}&client_secret=${clientSecret}&code=${code}`,
|
||||
Me: 'https://api.github.com/user'
|
||||
},
|
||||
HCaptcha: {
|
||||
Verify: 'https://hcaptcha.com/siteverify'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,12 +4,12 @@ import DataLoader from 'dataloader'
|
||||
import { User as DiscordUser } from 'discord.js'
|
||||
|
||||
import { Bot, User, ListType, BotList, TokenRegister, BotFlags, DiscordUserFlags, SubmittedBot } from '@types'
|
||||
import { categories } from './Constants'
|
||||
import { categories, SpecialEndPoints } from './Constants'
|
||||
|
||||
import knex from './Knex'
|
||||
import { DiscordBot, getMainGuild } from './DiscordBot'
|
||||
import { sign, verify } from './Jwt'
|
||||
import { serialize } from './Tools'
|
||||
import { formData, serialize } from './Tools'
|
||||
import { AddBotSubmit, ManageBot } from './Yup'
|
||||
|
||||
export const imageRateLimit = new TLRU<unknown, number>({ maxAgeMs: 60000 })
|
||||
@ -321,6 +321,23 @@ async function addRequest(ip: string, map: TLRU<unknown, number>) {
|
||||
map.set(ip, map.get(ip) + 1)
|
||||
}
|
||||
|
||||
export async function CaptchaVerify(response: string): Promise<boolean> {
|
||||
const res:{ success: boolean } = await fetch(SpecialEndPoints.HCaptcha.Verify, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: formData({
|
||||
response,
|
||||
secret: process.env.HCAPTCHA_KEY
|
||||
})
|
||||
}).then(r=> r.json())
|
||||
|
||||
console.log(res)
|
||||
|
||||
return res.success
|
||||
}
|
||||
|
||||
export const get = {
|
||||
discord: {
|
||||
user: new DataLoader(
|
||||
|
||||
@ -167,6 +167,7 @@ export const AddBotSubmitSchema: Yup.SchemaOf<AddBotSubmit> = Yup.object({
|
||||
.max(1500, '봇 설명은 최대 1500자여야합니다.')
|
||||
.required('봇 설명은 필수 항목입니다.'),
|
||||
_csrf: Yup.string().required(),
|
||||
_captcha: Yup.string().required()
|
||||
})
|
||||
|
||||
export interface AddBotSubmit {
|
||||
@ -182,6 +183,7 @@ export interface AddBotSubmit {
|
||||
intro: string
|
||||
desc: string
|
||||
_csrf: string
|
||||
_captcha?: string
|
||||
}
|
||||
|
||||
export const BotStatUpdateSchema: Yup.SchemaOf<BotStatUpdate> = Yup.object({
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user