From fd10d4dbc448f1c53b7721b5b23416f260cc5e21 Mon Sep 17 00:00:00 2001 From: shahaibo <1023316923@qq.com> Date: Wed, 13 Nov 2024 15:44:48 +0800 Subject: [PATCH] =?UTF-8?q?TASK:=E8=B0=B7=E6=AD=8C=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 22 +++ .../ai/da/controller/AccountController.java | 35 ++++ .../da/controller/ThirdPartyController.java | 8 + .../ai/da/mapper/primary/entity/Account.java | 14 ++ .../com/ai/da/model/dto/AccountLoginDTO.java | 2 + .../com/ai/da/model/dto/AddSubAccountDTO.java | 12 ++ .../ai/da/model/dto/SubAccountPageDTO.java | 9 + .../com/ai/da/service/AccountService.java | 16 ++ .../da/service/impl/AccountServiceImpl.java | 187 ++++++++++++++++++ 9 files changed, 305 insertions(+) create mode 100644 src/main/java/com/ai/da/model/dto/AddSubAccountDTO.java create mode 100644 src/main/java/com/ai/da/model/dto/SubAccountPageDTO.java diff --git a/pom.xml b/pom.xml index e20e83e1..ff9df865 100644 --- a/pom.xml +++ b/pom.xml @@ -288,6 +288,28 @@ spring-boot-starter-websocket + + com.google.auth + google-auth-library-oauth2-http + 1.8.0 + + + + com.google.api-client + google-api-client + 1.32.1 + + + com.google.oauth-client + google-oauth-client + 1.32.1 + + + com.google.http-client + google-http-client-jackson2 + 1.41.5 + + diff --git a/src/main/java/com/ai/da/controller/AccountController.java b/src/main/java/com/ai/da/controller/AccountController.java index c73fcdaa..0332154a 100644 --- a/src/main/java/com/ai/da/controller/AccountController.java +++ b/src/main/java/com/ai/da/controller/AccountController.java @@ -3,6 +3,7 @@ package com.ai.da.controller; import com.ai.da.common.config.exception.BusinessException; import com.ai.da.common.response.PageBaseResponse; import com.ai.da.common.response.Response; +import com.ai.da.mapper.primary.entity.Account; import com.ai.da.mapper.primary.entity.TrialOrder; import com.ai.da.model.dto.*; import com.ai.da.model.vo.AccountLoginVO; @@ -261,5 +262,39 @@ public class AccountController { return Response.success(true); } + @PostMapping("enterpriseLogin") + @ApiOperation(value = "企业登录") + public Response enterpriseLogin(@Valid @RequestBody AccountLoginDTO accountDTO) { + return Response.success(accountService.enterpriseLogin(accountDTO)); + } + @PostMapping("schoolLogin") + @ApiOperation(value = "学校登录") + public Response schoolLogin(@Valid @RequestBody AccountLoginDTO accountDTO) { + return Response.success(accountService.schoolLogin(accountDTO)); + } + + @PostMapping("addOrUpdateSubAccount") + @ApiOperation(value = "子账号新增") + public Response addSubAccount(@Valid @RequestBody AddSubAccountDTO addSubAccountDTO) { + return Response.success(accountService.addSubAccount(addSubAccountDTO)); + } + + @PostMapping("deleteSubAccount") + @ApiOperation(value = "子账号删除") + public Response deleteSubAccount(@Valid @RequestBody AddSubAccountDTO addSubAccountDTO) { + return Response.success(accountService.deleteSubAccount(addSubAccountDTO)); + } + + @PostMapping("subAccountList") + @ApiOperation(value = "子账号查询") + public Response> subAccountList(@Valid @RequestBody SubAccountPageDTO subAccountPageDTO) { + return Response.success(accountService.subAccountList(subAccountPageDTO)); + } + + @GetMapping("accountDetail") + @ApiOperation(value = "账号详情") + public Response accountDetail(@RequestParam("id") Long id) { + return Response.success(accountService.accountDetail(id)); + } } diff --git a/src/main/java/com/ai/da/controller/ThirdPartyController.java b/src/main/java/com/ai/da/controller/ThirdPartyController.java index e077fa8c..e0047d62 100644 --- a/src/main/java/com/ai/da/controller/ThirdPartyController.java +++ b/src/main/java/com/ai/da/controller/ThirdPartyController.java @@ -1,6 +1,7 @@ package com.ai.da.controller; import com.ai.da.common.response.Response; +import com.ai.da.mapper.primary.entity.GoogleUser; import com.ai.da.model.dto.*; import com.ai.da.model.vo.AccountLoginVO; import com.ai.da.service.AccountService; @@ -121,4 +122,11 @@ public class ThirdPartyController { public Response googleCallback(@RequestParam("code") String code, HttpSession session) { return Response.success(accountService.googleCallback(code, session)); } + @CrossOrigin + @GetMapping("/parseGoogleCredential") + public Response parseGoogleCredential(@RequestParam("credential") String credential) { + return Response.success(accountService.parseGoogleCredential(credential)); + } + + } diff --git a/src/main/java/com/ai/da/mapper/primary/entity/Account.java b/src/main/java/com/ai/da/mapper/primary/entity/Account.java index 285acd90..3629eedf 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/Account.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/Account.java @@ -97,6 +97,10 @@ public class Account implements Serializable { * 2 : 月付用户 * 3 : 试用用户 * 4 : 参加活动获取30天有效期和6000个积分的用户 + * 5 : 企业管理员账号 + * 6 : 企业子账号 + * 7 : 学校管理员 + * 8 : 学校子账号 */ private Integer systemUser; @@ -104,4 +108,14 @@ public class Account implements Serializable { * 头像 */ private String avatar; + + private String organizationName; + + private Long parentId; + + private Integer isAdmin; + + private BigDecimal shareCredits; + + private Integer subAccountNum; } diff --git a/src/main/java/com/ai/da/model/dto/AccountLoginDTO.java b/src/main/java/com/ai/da/model/dto/AccountLoginDTO.java index 2c1483c9..2f536ffb 100644 --- a/src/main/java/com/ai/da/model/dto/AccountLoginDTO.java +++ b/src/main/java/com/ai/da/model/dto/AccountLoginDTO.java @@ -32,4 +32,6 @@ public class AccountLoginDTO { @ApiModelProperty("邮箱验证码") private String emailVerifyCode; + private String organizationName; + } diff --git a/src/main/java/com/ai/da/model/dto/AddSubAccountDTO.java b/src/main/java/com/ai/da/model/dto/AddSubAccountDTO.java new file mode 100644 index 00000000..2f894789 --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/AddSubAccountDTO.java @@ -0,0 +1,12 @@ +package com.ai.da.model.dto; + +import com.ai.da.mapper.primary.entity.Account; +import lombok.Data; + +import java.util.List; + +@Data +public class AddSubAccountDTO extends Account { + + private List deleteIdList; +} diff --git a/src/main/java/com/ai/da/model/dto/SubAccountPageDTO.java b/src/main/java/com/ai/da/model/dto/SubAccountPageDTO.java new file mode 100644 index 00000000..f5dcc995 --- /dev/null +++ b/src/main/java/com/ai/da/model/dto/SubAccountPageDTO.java @@ -0,0 +1,9 @@ +package com.ai.da.model.dto; + +import com.ai.da.model.vo.PageQueryBaseVo; +import lombok.Data; + +@Data +public class SubAccountPageDTO extends PageQueryBaseVo { + private String userName; +} diff --git a/src/main/java/com/ai/da/service/AccountService.java b/src/main/java/com/ai/da/service/AccountService.java index bd9c99b4..2d86fdf2 100644 --- a/src/main/java/com/ai/da/service/AccountService.java +++ b/src/main/java/com/ai/da/service/AccountService.java @@ -1,6 +1,8 @@ package com.ai.da.service; +import com.ai.da.common.response.PageBaseResponse; import com.ai.da.mapper.primary.entity.Account; +import com.ai.da.mapper.primary.entity.GoogleUser; import com.ai.da.mapper.primary.entity.TrialOrder; import com.ai.da.model.dto.*; import com.ai.da.model.vo.AccountLoginVO; @@ -186,4 +188,18 @@ public interface AccountService extends IService { String googleCallback(String code, HttpSession session); List getPaidCustomerEmail(); + + AccountLoginVO enterpriseLogin(AccountLoginDTO accountDTO); + + AccountLoginVO schoolLogin(AccountLoginDTO accountDTO); + + Boolean addSubAccount(AddSubAccountDTO addSubAccountDTO); + + Boolean deleteSubAccount(AddSubAccountDTO addSubAccountDTO); + + PageBaseResponse subAccountList(SubAccountPageDTO subAccountPageDTO); + + Account accountDetail(Long id); + + GoogleUser parseGoogleCredential(String credential); } diff --git a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java index bead403e..03145804 100644 --- a/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AccountServiceImpl.java @@ -7,6 +7,7 @@ import com.ai.da.common.context.UserContext; import com.ai.da.common.enums.AuthenticationOperationTypeEnum; import com.ai.da.common.enums.CreditsEventsEnum; import com.ai.da.common.enums.LoginTypeEnum; +import com.ai.da.common.response.PageBaseResponse; import com.ai.da.common.response.ResultEnum; import com.ai.da.common.security.jwt.JWTTokenHelper; import com.ai.da.common.utils.*; @@ -25,6 +26,13 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.auth.oauth2.IdToken; +import com.google.auth.oauth2.TokenVerifier; +import com.google.common.base.Function; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import io.netty.util.internal.StringUtil; @@ -1945,4 +1953,183 @@ public class AccountServiceImpl extends ServiceImpl impl // return userRepository.save(newUser); // } + + @Override + public AccountLoginVO enterpriseLogin(AccountLoginDTO accountDTO) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(Account::getUserName, accountDTO.getUserName()); + qw.lambda().eq(Account::getOrganizationName, accountDTO.getOrganizationName()); + List accounts = accountMapper.selectList(qw); + if (CollectionUtil.isEmpty(accounts)) { + throw new BusinessException("Username or enterprise name incorrect."); + } + qw.lambda().eq(Account::getUserPassword, accountDTO.getPassword()); + accounts = accountMapper.selectList(qw); + if (CollectionUtil.isEmpty(accounts)) { + throw new BusinessException("Password error."); + } + Account account = accounts.get(0); + AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); + response.setEmail(account.getUserEmail()); + String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); + if (StringUtils.isNotBlank(token)) { + //用户已登入 + response.setToken(token); + } else { + response.setToken(createAccountToken(account)); + } + response.setUserId(account.getId()); + response.setSystemUser(account.getSystemUser()); + // 设置头像 + String avatar; + if (StringUtil.isNullOrEmpty(account.getAvatar())){ + avatar = CommonConstant.DEFAULT_AVATAR; + }else { + avatar = account.getAvatar(); + } + response.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + response.setFolloweeCount(portfolioService.getFolloweeCount(account.getId())); + response.setFollowerCount(portfolioService.getFollowerCount(account.getId())); + //判断是否常用ip 不是则发邮件提示 +// calculateExceptionIp(RequestInfoUtil.getIpAddress(request), account); + return response; + } + + @Override + public AccountLoginVO schoolLogin(AccountLoginDTO accountDTO) { + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(Account::getUserName, accountDTO.getUserName()); + qw.lambda().eq(Account::getOrganizationName, accountDTO.getOrganizationName()); + List accounts = accountMapper.selectList(qw); + if (CollectionUtil.isEmpty(accounts)) { + throw new BusinessException("Username or school name incorrect."); + } + qw.lambda().eq(Account::getUserPassword, accountDTO.getPassword()); + accounts = accountMapper.selectList(qw); + if (CollectionUtil.isEmpty(accounts)) { + throw new BusinessException("Password error."); + } + Account account = accounts.get(0); + AccountLoginVO response = CopyUtil.copyObject(account, AccountLoginVO.class); + response.setEmail(account.getUserEmail()); + String token = LocalCacheUtils.getTokenCache(String.valueOf(account.getId())); + if (StringUtils.isNotBlank(token)) { + //用户已登入 + response.setToken(token); + } else { + response.setToken(createAccountToken(account)); + } + response.setUserId(account.getId()); + response.setSystemUser(account.getSystemUser()); + // 设置头像 + String avatar; + if (StringUtil.isNullOrEmpty(account.getAvatar())){ + avatar = CommonConstant.DEFAULT_AVATAR; + }else { + avatar = account.getAvatar(); + } + response.setAvatar(minioUtil.getPreSignedUrl(avatar, CommonConstant.MINIO_IMAGE_EXPIRE_TIME)); + response.setFolloweeCount(portfolioService.getFolloweeCount(account.getId())); + response.setFollowerCount(portfolioService.getFollowerCount(account.getId())); + //判断是否常用ip 不是则发邮件提示 +// calculateExceptionIp(RequestInfoUtil.getIpAddress(request), account); + return response; + } + + @Override + public Boolean addSubAccount(AddSubAccountDTO addSubAccountDTO) { + if (null == addSubAccountDTO.getId()) { + AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder(); + Account account = accountMapper.selectById(authPrincipalVo.getId()); + + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().eq(Account::getOrganizationName, account.getOrganizationName()); + List accounts = accountMapper.selectList(qw); + if (accounts.size() >= account.getSubAccountNum()) { + throw new BusinessException("The maximum number of sub accounts that can be created has been reached."); + } + + qw.lambda().eq(Account::getUserName, addSubAccountDTO.getUserName()); + accounts = accountMapper.selectList(qw); + if (CollectionUtil.isNotEmpty(accounts)) { + throw new BusinessException("The enterprise already has an account with the same username."); + } + + Account subAccount = CopyUtil.copyObject(addSubAccountDTO, Account.class); + subAccount.setSystemUser(6); + subAccount.setValidStartTime(account.getValidStartTime()); + subAccount.setValidEndTime(account.getValidEndTime()); + subAccount.setLanguage(Language.ENGLISH.name()); + subAccount.setCreateDate(new Date()); + subAccount.setIsTrial(0); + subAccount.setIsBeginner(1); + subAccount.setParentId(account.getParentId()); + accountMapper.insert(subAccount); + }else { + Account subAccount = CopyUtil.copyObject(addSubAccountDTO, Account.class); + accountMapper.updateById(subAccount); + } + + + return Boolean.TRUE; + } + + @Override + public Boolean deleteSubAccount(AddSubAccountDTO addSubAccountDTO) { + accountMapper.deleteBatchIds(addSubAccountDTO.getDeleteIdList()); + return Boolean.TRUE; + } + + @Override + public PageBaseResponse subAccountList(SubAccountPageDTO subAccountPageDTO) { + AuthPrincipalVo authPrincipalVo = UserContext.getUserHolder(); + Account account = accountMapper.selectById(authPrincipalVo); + QueryWrapper qw = new QueryWrapper<>(); + qw.lambda().ne(Account::getId, account.getId()); + qw.lambda().eq(Account::getOrganizationName, account.getOrganizationName()); + // 执行分页查询 + IPage page = accountMapper.selectPage(new Page<>(subAccountPageDTO.getPage(), subAccountPageDTO.getSize()), qw); + + return PageBaseResponse.success(page); + } + + @Override + public Account accountDetail(Long id) { + return accountMapper.selectById(id); + } + + @Override + public GoogleUser parseGoogleCredential(String credential) { + try { + // 配置 Google ID Token 验证器 + GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder( + new NetHttpTransport(), + JacksonFactory.getDefaultInstance()) + .setAudience(Collections.singletonList(CLIENT_ID)) + .build(); + + // 验证并解析 ID Token + GoogleIdToken idToken = verifier.verify(credential); + + if (idToken != null) { + GoogleIdToken.Payload payload = idToken.getPayload(); + + // 提取用户信息 + String userId = payload.getSubject(); + String email = payload.getEmail(); + String name = (String) payload.get("name"); + log.info(userId); + log.info(email); + log.info(name); + + return new GoogleUser(); + } else { + throw new IllegalArgumentException("Invalid ID token."); + } + + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("Failed to verify ID token: " + e.getMessage()); + } + } }