[Core] Support signup verification code (#417)

This commit is contained in:
qianmoQ 2023-08-29 18:08:58 +08:00 committed by GitHub
commit 96a48c5cba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 127 additions and 44 deletions

View File

@ -20,7 +20,9 @@ public class ResultEntity
public void setExpression(String[] expression)
{
this.expression = expression.clone();
if (expression != null) {
this.expression = expression.clone();
}
}
@Override

View File

@ -43,18 +43,18 @@ datacap.cache.data=
datacap.openai.backend=https://api.openai.com
datacap.openai.token=
# Support list:
# gpt-3.5-turbo
# gpt-3.5-turbo-0301
# gpt-3.5-turbo-0613
# gpt-3.5-turbo-16k
# gpt-3.5-turbo-16k-0613
# gpt-4
# gpt-4-0314
# gpt-4-32k
# gpt-4-32k-0314
# gpt-4-0613
# gpt-4-32k-0613
datacap.openai.model=gpt-3.5-turbo-0613
# GPT_35_TURBO
# GPT_35_TURBO_0301
# GPT_35_TURBO_0613
# GPT_35_TURBO_16K
# GPT_35_TURBO_16K_0613
# GPT_4
# GPT_4_0314
# GPT_4_32K
# GPT_4_32K_0314
# GPT_4_0613
# GPT_4_32K_0613
datacap.openai.model=GPT_35_TURBO_0613
# Access remote API timeout, in seconds
datacap.openai.timeout=30

View File

@ -2,7 +2,6 @@ package io.edurt.datacap.server.controller.user;
import io.edurt.datacap.captcha.entity.ResultEntity;
import io.edurt.datacap.common.response.CommonResponse;
import io.edurt.datacap.common.response.JwtResponse;
import io.edurt.datacap.server.configure.InitializerConfigure;
import io.edurt.datacap.service.body.AuthBody;
import io.edurt.datacap.service.entity.UserEntity;
@ -28,22 +27,37 @@ public class AuthController
this.initializer = initializer;
}
@PostMapping("/signin")
public CommonResponse<JwtResponse> authenticateUser(@RequestBody @Validated(ValidationGroup.Crud.Auth.class) AuthBody configure)
/**
* Validates the captcha.
*
* @param configure the authentication body containing captcha information
* @return the common response object representing the result of the validation
*/
private CommonResponse<Object> validateCaptcha(AuthBody configure)
{
if (initializer.getCaptchaEnable()) {
if (ObjectUtils.isEmpty(configure.getCaptcha())) {
return CommonResponse.failure("Captcha must not empty");
return CommonResponse.failure("Captcha must not be empty");
}
ResultEntity entity = initializer.getCache().getIfPresent(configure.getTimestamp());
if (entity == null) {
return CommonResponse.failure("Captcha not exists");
return CommonResponse.failure("Captcha does not exists");
}
if (!entity.getResult().equals(configure.getCaptcha())) {
initializer.getCache().invalidate(configure.getTimestamp());
return CommonResponse.failure("The calculation result is incorrect");
}
}
return null;
}
@PostMapping("/signin")
public CommonResponse<Object> authenticateUser(@RequestBody @Validated(ValidationGroup.Crud.Auth.class) AuthBody configure)
{
CommonResponse<Object> captchaResponse = validateCaptcha(configure);
if (captchaResponse != null) {
return captchaResponse;
}
UserEntity user = new UserEntity();
user.setUsername(configure.getUsername());
@ -54,6 +68,15 @@ public class AuthController
@PostMapping("/signup")
public CommonResponse<?> registerUser(@RequestBody @Validated(ValidationGroup.Crud.Create.class) AuthBody configure)
{
if (!initializer.getRegistrationEnable()) {
return CommonResponse.failure("Registration is disabled");
}
CommonResponse<?> captchaResponse = validateCaptcha(configure);
if (captchaResponse != null) {
return captchaResponse;
}
UserEntity user = new UserEntity();
user.setUsername(configure.getUsername());
user.setPassword(configure.getPassword());

View File

@ -16,7 +16,7 @@
<properties>
<snakeyaml.version>2.0</snakeyaml.version>
<useragent.version>1.21</useragent.version>
<openai.version>1.5.0</openai.version>
<openai.version>1.9.0</openai.version>
</properties>
<dependencies>

View File

@ -1,7 +1,6 @@
package io.edurt.datacap.service.service;
import io.edurt.datacap.common.response.CommonResponse;
import io.edurt.datacap.common.response.JwtResponse;
import io.edurt.datacap.service.body.FilterBody;
import io.edurt.datacap.service.body.UserNameBody;
import io.edurt.datacap.service.body.UserPasswordBody;
@ -16,7 +15,7 @@ public interface UserService
{
CommonResponse<UserEntity> saveOrUpdate(UserEntity configure);
CommonResponse<JwtResponse> authenticate(UserEntity configure);
CommonResponse<Object> authenticate(UserEntity configure);
CommonResponse<UserEntity> info(Long userId);

View File

@ -22,11 +22,10 @@ import org.apache.commons.lang.text.StrSubstitutor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.devlive.sdk.openai.OpenAiClient;
import org.devlive.sdk.openai.entity.CompletionChatEntity;
import org.devlive.sdk.openai.entity.CompletionMessageEntity;
import org.devlive.sdk.openai.entity.UsageEntity;
import org.devlive.sdk.openai.model.CompletionMessageModel;
import org.devlive.sdk.openai.response.CompleteChatResponse;
import org.devlive.sdk.openai.model.CompletionModel;
import org.devlive.sdk.openai.model.MessageModel;
import org.devlive.sdk.openai.response.ChatResponse;
import org.springframework.core.env.Environment;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
@ -109,32 +108,32 @@ public class MessageServiceImpl
.apiKey(openApiToken)
.client(okHttpClient)
.build()) {
List<CompletionMessageEntity> messages = new ArrayList<>();
List<org.devlive.sdk.openai.entity.MessageEntity> messages = new ArrayList<>();
// Get the context in the conversation * 2
if (getContent) {
this.repository.findTopByChatOrderByCreateTimeDesc(configure.getChat(), questionMessage.getId(), Pageable.ofSize(contentCount * 2))
.stream()
.sorted(Comparator.comparing(MessageEntity::getId))
.forEach(message -> {
String role = message.getType() == MessageType.question ? CompletionMessageModel.USER.getName() : CompletionMessageModel.ASSISTANT.getName();
CompletionMessageEntity completionMessage = CompletionMessageEntity.builder()
String role = message.getType() == MessageType.question ? MessageModel.USER.getName() : MessageModel.ASSISTANT.getName();
org.devlive.sdk.openai.entity.MessageEntity completionMessage = org.devlive.sdk.openai.entity.MessageEntity.builder()
.role(role)
.content(message.getContent())
.build();
messages.add(completionMessage);
});
}
CompletionMessageEntity message = CompletionMessageEntity.builder()
.role(CompletionMessageModel.USER.getName())
org.devlive.sdk.openai.entity.MessageEntity message = org.devlive.sdk.openai.entity.MessageEntity.builder()
.role(MessageModel.USER.getName())
.content(questionMessage.getContent())
.build();
messages.add(message);
CompletionChatEntity chatCompletion = CompletionChatEntity.builder()
org.devlive.sdk.openai.entity.ChatEntity chatCompletion = org.devlive.sdk.openai.entity.ChatEntity.builder()
.messages(messages)
.maxTokens(2048)
.model(openApiModel)
.model(CompletionModel.valueOf(openApiModel))
.build();
CompleteChatResponse chatCompletionResponse = openAiClient.createChatCompletion(chatCompletion);
ChatResponse chatCompletionResponse = openAiClient.createChatCompletion(chatCompletion);
List<String> answer = Lists.newArrayList();
chatCompletionResponse.getChoices()
.forEach(e -> answer.add(e.getMessage().getContent()));
@ -218,16 +217,16 @@ public class MessageServiceImpl
.apiKey(openApiToken)
.client(okHttpClient)
.build()) {
List<CompletionMessageEntity> messages = Lists.newArrayList(CompletionMessageEntity.builder()
.role(CompletionMessageModel.USER.getName())
List<org.devlive.sdk.openai.entity.MessageEntity> messages = Lists.newArrayList(org.devlive.sdk.openai.entity.MessageEntity.builder()
.role(MessageModel.USER.getName())
.content(forwardContent)
.build());
CompletionChatEntity chatCompletion = CompletionChatEntity.builder()
org.devlive.sdk.openai.entity.ChatEntity chatCompletion = org.devlive.sdk.openai.entity.ChatEntity.builder()
.messages(messages)
.maxTokens(2048)
.model(openApiModel)
.model(CompletionModel.valueOf(openApiModel))
.build();
CompleteChatResponse chatCompletionResponse = openAiClient.createChatCompletion(chatCompletion);
ChatResponse chatCompletionResponse = openAiClient.createChatCompletion(chatCompletion);
List<String> answer = Lists.newArrayList();
chatCompletionResponse.getChoices()
.forEach(e -> answer.add(e.getMessage().getContent()));

View File

@ -105,7 +105,7 @@ public class UserServiceImpl
@AuditUserLog
@Override
public CommonResponse<JwtResponse> authenticate(UserEntity configure)
public CommonResponse<Object> authenticate(UserEntity configure)
{
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(configure.getUsername(), configure.getPassword());
Authentication authentication = authenticationManager.authenticate(authenticationToken);

View File

@ -0,0 +1,10 @@
.datacap-login-captcha .ivu-btn {
padding: 0;
}
.datacap-login-captcha .ivu-btn img {
height: 28px;
width: 100px;
position: relative;
top: 4px;
}

View File

@ -25,7 +25,19 @@
</div>
</template>
</Poptip>
<Password name="passwordConfirm" :rules="passwordConfirmRule" placeholder="确认密码"/>
<Password name="passwordConfirm"
:rules="passwordConfirmRule"
placeholder="确认密码">
</Password>
<Captcha v-if="showCaptcha"
class="datacap-login-captcha"
name="captcha"
:count-down="0"
@on-get-captcha="handlerRefererCaptcha">
<template #text>
<img :src="'data:image/png;base64,' + captchaImage">
</template>
</Captcha>
<Submit>{{ $t('common.register') }}</Submit>
<Button style="width: 100%; margin-top: 5px;" type="dashed" @click="handlerGoSignIn">{{ $t('common.login') }}</Button>
</Login>
@ -40,6 +52,8 @@ import {defineComponent} from 'vue';
import {AuthService} from "@/services/AuthService";
import router from "@/router";
import {AuthUser} from "@/model/AuthUser";
import CaptchaService from "@/services/CaptchaService";
import "@/css/datacap-login-captcha.css"
export default defineComponent({
data()
@ -68,7 +82,11 @@ export default defineComponent({
},
{validator: validatePassCheck, trigger: 'change'}
],
passwordLen: 0
passwordLen: 0,
loading: false,
showCaptcha: false,
captchaImage: null,
timestamp: null
}
},
computed: {
@ -97,17 +115,38 @@ export default defineComponent({
}
}
},
created()
{
this.handlerInitialize();
},
methods: {
handlerInitialize()
{
this.loading = true
this.timestamp = Date.parse(new Date().toString());
CaptchaService.getCaptcha(this.timestamp)
.then(response => {
if (response.data !== false) {
this.showCaptcha = true
this.captchaImage = response.data?.image
}
})
.finally(() => {
this.loading = false
})
},
handlerChangePassword(val)
{
this.passwordLen = val.length;
},
handlerSubmit(valid, {username, password, passwordConfirm})
handlerSubmit(valid, {username, password, captcha})
{
if (valid) {
const authUser: AuthUser = {
username: username,
password: password
password: password,
timestamp: this.timestamp,
captcha: captcha
}
new AuthService().signup(authUser)
.then(response => {
@ -116,10 +155,21 @@ export default defineComponent({
}
else {
this.$Message.error(response.message);
this.handlerRefererCaptcha()
}
});
}
},
handlerRefererCaptcha()
{
this.timestamp = Date.parse(new Date().toString());
CaptchaService.getCaptcha(this.timestamp)
.then(response => {
if (response.data !== false) {
this.captchaImage = response.data?.image
}
})
},
handlerGoSignIn()
{
router.push('/auth/signin');

View File

@ -14,7 +14,7 @@
<description>DataCap - H2</description>
<properties>
<h2.version>2.1.214</h2.version>
<h2.version>2.2.220</h2.version>
<plugin.name>jdbc-h2</plugin.name>
</properties>