diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java index b467cce2..930792e4 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/ErrCode.java @@ -19,6 +19,13 @@ public enum ErrCode implements IEnum { UNSUPPORTED_OPERATION_EXCEPTION(10000009, "方法未实现"), DATA_NOT_EXIST(10000010, "数据不存在"), + /** + * openapi通用异常段 + */ + IDENTIFIER_ERROR(00000000, "签名验证失败"), + API_LOGIN_ERROR(00000000, "登录验证失败"), + + /** * 组件通用异常段 */ @@ -70,6 +77,7 @@ public enum ErrCode implements IEnum { DEVICE_NOT_FOUND(00000000, "设备不存在"), DEVICE_OFFLINE(00000000, "设备已离线"), DEVICE_ALREADY(00000000, "设备已存在"), + MODEL_DEVICE_ALREADY(00000000, "设备DN已存在"), DEVICE_HAS_ASSOCIATED(00000000, "设备已关联"), MODEL_ALREADY(00000000, "型号已存在"), @@ -99,6 +107,7 @@ public enum ErrCode implements IEnum { FILE_NAME_IS_NULL(00000000, "文件名为空,获取文件名失败"); + private int code; private String message; diff --git a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java index 7eb2fd04..ce4d00e0 100644 --- a/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java +++ b/iot-common/iot-common-core/src/main/java/cc/iotkit/common/enums/UserType.java @@ -20,6 +20,11 @@ public enum UserType { */ SYS_USER("sys_user"), + /** + * 第三方api + */ + API_USER("api_user"), + /** * app端 */ diff --git a/iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java b/iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java index 0ec3b110..c88835ec 100644 --- a/iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java +++ b/iot-module/iot-manager/src/main/java/cc/iotkit/manager/service/impl/DeviceServiceImpl.java @@ -120,7 +120,11 @@ public class DeviceServiceImpl implements IDeviceService { if (product == null) { throw new BizException(ErrCode.PRODUCT_NOT_FOUND); } - + //同产品不可重复设备名 + DeviceInfo deviceRepetition = deviceInfoData.findByProductKeyAndDeviceName(productKey, deviceName); + if (deviceRepetition != null) { + throw new BizException(ErrCode.MODEL_DEVICE_ALREADY); + } //生成设备密钥 String chars = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678"; int maxPos = chars.length(); diff --git a/iot-module/iot-openapi/pom.xml b/iot-module/iot-openapi/pom.xml new file mode 100644 index 00000000..dc1baf17 --- /dev/null +++ b/iot-module/iot-openapi/pom.xml @@ -0,0 +1,144 @@ + + + + iot-module + cc.iotkit + 0.4.5-SNAPSHOT + + 4.0.0 + + iot-openapi + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.bouncycastle + bcprov-jdk15on + + + + com.aliyun.oss + aliyun-sdk-oss + + + + joda-time + joda-time + + + + it.ozimov + embedded-redis + + + slf4j-simple + org.slf4j + + + + + + cc.iotkit + iot-common-model + + + + cc.iotkit + iot-common-core + + + + cc.iotkit + iot-rule-engine + + + + cc.iotkit + iot-screen + + + + cc.iotkit + iot-component-server + + + + cc.iotkit + iot-component-converter + + + + cc.iotkit + iot-virtual-device + + + + cc.iotkit + iot-message-core + + + + cc.iotkit + iot-common-oss + + + + cc.iotkit + iot-temporal-service + + + + cc.iotkit + iot-data-serviceImpl-rdb + + + + cc.iotkit + iot-data-serviceImpl-cache + + + + cc.iotkit + iot-common-web + + + + cc.iotkit + iot-common-doc + + + cc.iotkit + iot-common-satoken + + + + cc.iotkit + iot-common-excel + + + cc.iotkit + iot-common-log + + + io.github.linpeilie + mapstruct-plus-spring-boot-starter + + + cc.iotkit + iot-system + + + + + 11 + 11 + + + \ No newline at end of file diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenBaseController.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenBaseController.java new file mode 100644 index 00000000..7da850de --- /dev/null +++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenBaseController.java @@ -0,0 +1,34 @@ +package cc.iotkit.openapi.controller; + +import cc.iotkit.common.api.Request; +import cc.iotkit.model.InvokeResult; +import cc.iotkit.openapi.dto.bo.TokenVerifyBo; +import cc.iotkit.openapi.service.OpenBaseService; +import cc.iotkit.openapi.service.OpenDeviceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = {"openapi-基础"}) +@Slf4j +@RestController +@RequestMapping("/openapi") +public class OpenBaseController { + + @Autowired + private OpenBaseService openBaseService; + + @ApiOperation(value = "token获取", notes = "token获取", httpMethod = "POST") + @PostMapping("/v1/getToken") + public InvokeResult OpenApiGetToken(@RequestBody @Validated Request request) { + return new InvokeResult(openBaseService.getToken(request.getData())); + } + + +} diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenDeviceController.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenDeviceController.java new file mode 100644 index 00000000..25b640ae --- /dev/null +++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/controller/OpenDeviceController.java @@ -0,0 +1,36 @@ +package cc.iotkit.openapi.controller; + +import cc.iotkit.common.api.Request; +import cc.iotkit.model.device.DeviceInfo; +import cc.iotkit.openapi.dto.bo.device.OpenapiDeviceBo; +import cc.iotkit.openapi.service.OpenBaseService; +import cc.iotkit.openapi.service.OpenDeviceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Api(tags = {"openapi-设备"}) +@Slf4j +@RestController +@RequestMapping("/openapi/v1/device") +public class OpenDeviceController { + + @Autowired + private OpenBaseService openBaseService; + + @Autowired + private OpenDeviceService openDeviceService; + + @ApiOperation("获取设备详情") + @PostMapping("/detail") + public DeviceInfo getDetail(@RequestBody @Validated Request request) { + return openDeviceService.getDetail(request.getData()); + } + +} diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/TokenVerifyBo.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/TokenVerifyBo.java new file mode 100644 index 00000000..24696550 --- /dev/null +++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/TokenVerifyBo.java @@ -0,0 +1,30 @@ +package cc.iotkit.openapi.dto.bo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@ApiModel(value = "DeviceConsumerBo") +@Data +public class TokenVerifyBo { + private static final long serialVersionUID = -1L; + + @NotBlank(message = "appid不能为空") + @ApiModelProperty(value = "appid") + private String appid; + + @NotBlank(message = "timeStamp不能为空") + @ApiModelProperty(value = "时间戳") + private String timeStamp; + + @NotBlank(message = "identifier不能为空") + @ApiModelProperty(value = "标识符") + private String identifier; + + @NotBlank(message = "{tenant.number.not.blank}") + @ApiModelProperty(value = "租户ID") + private String tenantId; + + +} diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/device/OpenapiDeviceBo.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/device/OpenapiDeviceBo.java new file mode 100644 index 00000000..06a35fa4 --- /dev/null +++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/dto/bo/device/OpenapiDeviceBo.java @@ -0,0 +1,20 @@ +package cc.iotkit.openapi.dto.bo.device; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +@ApiModel(value = "OpenapiDeviceBo") +@Data +public class OpenapiDeviceBo { + private static final long serialVersionUID = -1L; + + @NotBlank(message = "deviceName不能为空") + @ApiModelProperty(value = "产品名称") + private String deviceName; + + @NotBlank(message = "productKey不能为空") + @ApiModelProperty(value = "产品key") + private String productKey; +} diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenBaseService.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenBaseService.java new file mode 100644 index 00000000..43c952ea --- /dev/null +++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenBaseService.java @@ -0,0 +1,14 @@ +package cc.iotkit.openapi.service; + +import cc.iotkit.openapi.dto.bo.TokenVerifyBo; + +/** + * @Author: dsy + * @Date: 2023/7/24 11:30 + * @Version: V1.0 + * @Description: openapi基础服务接口 + */ +public interface OpenBaseService { + + String getToken(TokenVerifyBo bo); +} diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenDeviceService.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenDeviceService.java new file mode 100644 index 00000000..a37ab774 --- /dev/null +++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/OpenDeviceService.java @@ -0,0 +1,14 @@ +package cc.iotkit.openapi.service; + +import cc.iotkit.model.device.DeviceInfo; +import cc.iotkit.openapi.dto.bo.device.OpenapiDeviceBo; + +/** + * @Author: dsy + * @Date: 2023/7/24 11:05 + * @Version: V1.0 + * @Description: openapi设备服务接口 + */ +public interface OpenDeviceService { + DeviceInfo getDetail(OpenapiDeviceBo bo); +} diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenBaseServiceImpl.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenBaseServiceImpl.java new file mode 100644 index 00000000..d9dcce6b --- /dev/null +++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenBaseServiceImpl.java @@ -0,0 +1,125 @@ +package cc.iotkit.openapi.service.impl; + +import cc.iotkit.common.constant.Constants; +import cc.iotkit.common.enums.DeviceType; +import cc.iotkit.common.enums.ErrCode; +import cc.iotkit.common.enums.LoginType; +import cc.iotkit.common.exception.BizException; +import cc.iotkit.common.log.event.LogininforEvent; +import cc.iotkit.common.satoken.utils.LoginHelper; +import cc.iotkit.common.undefined.LoginUser; +import cc.iotkit.common.undefined.RoleDTO; +import cc.iotkit.common.utils.CodecUtil; +import cc.iotkit.common.utils.DateUtils; +import cc.iotkit.common.utils.MessageUtils; +import cc.iotkit.common.utils.SpringUtils; +import cc.iotkit.common.web.utils.ServletUtils; +import cc.iotkit.data.system.ISysUserData; +import cc.iotkit.model.system.SysUser; +import cc.iotkit.openapi.dto.bo.TokenVerifyBo; +import cc.iotkit.openapi.service.OpenBaseService; +import cc.iotkit.system.service.ISysPermissionService; +import cn.dev33.satoken.secure.BCrypt; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class OpenBaseServiceImpl implements OpenBaseService { + + @Value("${openapi.appid}") + private String appid; + + @Value("${openapi.password}") + private String password; + + @Autowired + private ISysUserData userData; + + @Autowired + private ISysPermissionService permissionService; + + @Override + public String getToken(TokenVerifyBo bo) { + String boAppid = bo.getAppid(); + String boIdentifier = bo.getIdentifier(); + String boTimeStamp = bo.getTimeStamp(); + + // 校验租户 + checkTenant(bo.getTenantId()); + + if (!CodecUtil.md5Str(boAppid + password + boTimeStamp).equals(boIdentifier)){ + throw new BizException(ErrCode.IDENTIFIER_ERROR); + } + if (!boAppid.equals(appid)){ + throw new BizException(ErrCode.API_LOGIN_ERROR); + } + SysUser sysUser = userData.selectUserByUserName(appid); + if (sysUser == null){ + //用户不存在是否新建? + } + LoginUser loginUser = buildLoginUser(sysUser); + // 生成token + LoginHelper.loginByDevice(loginUser, DeviceType.PC); + + recordLoginInfo(loginUser.getTenantId(), bo.getAppid(), Constants.LOGIN_SUCCESS, MessageUtils.message("openapi.login.success")); + recordLoginInfo(sysUser.getId()); + return StpUtil.getTokenValue(); + } + + private void checkTenant(String tenantId) { + + } + /** + * 构建登录用户 + */ + private LoginUser buildLoginUser(SysUser user) { + LoginUser loginUser = new LoginUser(); + loginUser.setTenantId(user.getTenantId()); + loginUser.setUserId(user.getId()); + loginUser.setDeptId(user.getDeptId()); + loginUser.setUsername(user.getUserName()); + loginUser.setUserType(user.getUserType()); + loginUser.setMenuPermission(permissionService.getMenuPermission(user.getId())); + loginUser.setRolePermission(permissionService.getRolePermission(user.getId())); + loginUser.setDeptName(ObjectUtil.isNull(user.getDept()) ? "" : user.getDept().getDeptName()); + List roles = BeanUtil.copyToList(user.getRoles(), RoleDTO.class); + loginUser.setRoles(roles); + return loginUser; + } + + /** + * 记录登录信息 + * + * @param tenantId 租户ID + * @param username 用户名 + * @param status 状态 + * @param message 消息内容 + */ + private void recordLoginInfo(String tenantId, String username, String status, String message) { + LogininforEvent logininforEvent = new LogininforEvent(); + logininforEvent.setTenantId(tenantId); + logininforEvent.setUsername(username); + logininforEvent.setStatus(status); + logininforEvent.setMessage(message); + logininforEvent.setRequest(ServletUtils.getRequest()); + SpringUtils.context().publishEvent(logininforEvent); + } + /** + * 记录登录信息 + * + * @param userId 用户ID + */ + public void recordLoginInfo(Long userId) { + SysUser sysUser = userData.findById(userId); + sysUser.setLoginIp(ServletUtils.getClientIP()); + sysUser.setLoginDate(DateUtils.getNowDate()); + sysUser.setUpdateBy(userId); + userData.save(sysUser); + } +} diff --git a/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenDeviceServiceImpl.java b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenDeviceServiceImpl.java new file mode 100644 index 00000000..3a9d6703 --- /dev/null +++ b/iot-module/iot-openapi/src/main/java/cc/iotkit/openapi/service/impl/OpenDeviceServiceImpl.java @@ -0,0 +1,24 @@ +package cc.iotkit.openapi.service.impl; + +import cc.iotkit.data.manager.IDeviceInfoData; +import cc.iotkit.model.device.DeviceInfo; +import cc.iotkit.openapi.dto.bo.device.OpenapiDeviceBo; +import cc.iotkit.openapi.service.OpenDeviceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Service; + +@Service +public class OpenDeviceServiceImpl implements OpenDeviceService { + + @Autowired + @Qualifier("deviceInfoDataCache") + private IDeviceInfoData deviceInfoData; + + @Override + public DeviceInfo getDetail(OpenapiDeviceBo data) { + DeviceInfo deviceInfo = deviceInfoData.findByProductKeyAndDeviceName(data.getProductKey(), data.getDeviceName()); + deviceInfo.setProperty(deviceInfoData.getProperties(deviceInfo.getDeviceId())); + return deviceInfo; + } +} diff --git a/iot-module/pom.xml b/iot-module/pom.xml index 144f180b..6d796b8e 100644 --- a/iot-module/pom.xml +++ b/iot-module/pom.xml @@ -20,6 +20,7 @@ iot-generator iot-screen iot-contribution + iot-openapi diff --git a/iot-starter/src/main/resources/application.yml b/iot-starter/src/main/resources/application.yml index 6ac99fb9..7a8ea07d 100644 --- a/iot-starter/src/main/resources/application.yml +++ b/iot-starter/src/main/resources/application.yml @@ -184,6 +184,12 @@ user: # 密码锁定时间(默认10分钟) lockTime: 10 +# openapi配置 +openapi: + appid: 123456789 + password: 123456 + + oss: region: xxxxx endpoint: xxxxx