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());
+ }
+ }
}