├── docker-compose ├── Dockerfile_device ├── Dockerfile_studio ├── Dockerfile_iot ├── Dockerfile_mongo ├── Dockerfile_rabbit ├── setup.js └── docker-compose.yml ├── src └── main │ ├── resources │ ├── application-local.properties │ ├── application-docker.properties │ ├── application.properties │ └── logback-spring.xml │ └── java │ └── top │ └── microiot │ ├── repository │ ├── UserRepository.java │ ├── DomainRepository.java │ ├── EventRepository.java │ ├── AlarmRepository.java │ ├── CustomConfigRepository.java │ ├── CustomFavoriteRepository.java │ ├── CustomEventRepository.java │ ├── SiteRepository.java │ ├── LoginUserRepository.java │ ├── CustomAlarmRepository.java │ ├── CustomLoginUserRepository.java │ ├── CustomSiteRepository.java │ ├── CustomDeviceRepository.java │ ├── SiteTypeRepository.java │ ├── ConfigRepository.java │ ├── DeviceTypeRepository.java │ ├── DeviceGroupRepository.java │ ├── FavoriteRepository.java │ ├── DeviceRepository.java │ ├── PageRepository.java │ ├── FavoriteRepositoryImpl.java │ ├── ConfigRepositoryImpl.java │ ├── SiteRepositoryImpl.java │ ├── DeviceRepositoryImpl.java │ ├── LoginUserRepositoryImpl.java │ ├── EventRepositoryImpl.java │ └── AlarmRepositoryImpl.java │ ├── controller │ ├── IoTController.java │ ├── CurrentUserControllerAdvice.java │ ├── EventController.java │ ├── AlarmController.java │ ├── TokenController.java │ ├── ConfigController.java │ ├── FavoriteController.java │ ├── DomainController.java │ ├── UserController.java │ ├── SiteController.java │ ├── DeviceGroupController.java │ ├── SiteTypeController.java │ ├── QueryController.java │ ├── DeviceController.java │ └── DeviceTypeController.java │ ├── security │ ├── IoTPasswordEncoder.java │ ├── authentication │ │ ├── TokenAuthenticationFailureHandler.java │ │ ├── SkipPathRequestMatcher.java │ │ ├── TokenSettings.java │ │ ├── TokenAuthenticationProvider.java │ │ ├── TokenAuthenticationProcessingFilter.java │ │ └── TokenFactory.java │ ├── CustomUserService.java │ ├── WebsocketSecurityConfig.java │ ├── CustomUserDetails.java │ └── WebSecurityConfig.java │ ├── web │ ├── WebMvcConfig.java │ ├── WebsocketSetting.java │ ├── WebsocketConfig.java │ ├── WebsocketConnectedListener.java │ ├── WebsocketDisconnectListener.java │ ├── MyStompHeaderAccessor.java │ └── WebsocketAuthorityInterceptor.java │ ├── service │ ├── IoTService.java │ ├── EventService.java │ ├── FavoriteService.java │ ├── AlarmService.java │ ├── MOService.java │ ├── ConfigService.java │ ├── SiteTypeService.java │ ├── DeviceService.java │ ├── DomainService.java │ ├── DeviceGroupService.java │ ├── QueryService.java │ ├── UserService.java │ ├── SiteService.java │ ├── TokenService.java │ └── DeviceManageService.java │ └── IotPlatformApplication.java ├── Dockerfile ├── README.md ├── pom.xml ├── mvnw.cmd └── mvnw /docker-compose/Dockerfile_device: -------------------------------------------------------------------------------- 1 | FROM microiot/device:1.0.3 -------------------------------------------------------------------------------- /docker-compose/Dockerfile_studio: -------------------------------------------------------------------------------- 1 | FROM microiot/studio:1.0.5 -------------------------------------------------------------------------------- /docker-compose/Dockerfile_iot: -------------------------------------------------------------------------------- 1 | FROM microiot/iotplatform:1.3.0 -------------------------------------------------------------------------------- /docker-compose/Dockerfile_mongo: -------------------------------------------------------------------------------- 1 | FROM mongo:3.6 2 | 3 | COPY ./setup.js /docker-entrypoint-initdb.d/ -------------------------------------------------------------------------------- /src/main/resources/application-local.properties: -------------------------------------------------------------------------------- 1 | microiot.mongo=localhost 2 | microiot.rabbitmq=localhost -------------------------------------------------------------------------------- /docker-compose/Dockerfile_rabbit: -------------------------------------------------------------------------------- 1 | FROM rabbitmq:3.7-management 2 | RUN rabbitmq-plugins enable --offline rabbitmq_stomp -------------------------------------------------------------------------------- /src/main/resources/application-docker.properties: -------------------------------------------------------------------------------- 1 | microiot.mongo=microiot_mongo 2 | microiot.rabbitmq=microiot_rabbitmq -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-alpine 2 | VOLUME /tmp 3 | ARG JAR_FILE 4 | 5 | EXPOSE 8082 6 | COPY ${JAR_FILE} app.jar 7 | 8 | ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"] -------------------------------------------------------------------------------- /docker-compose/setup.js: -------------------------------------------------------------------------------- 1 | db = db.getSiblingDB('iot'); 2 | db.createCollection('user'); 3 | db.user.insert( 4 | {"_class":"top.microiot.domain.User", 5 | "username":"admin", 6 | "password":"password", 7 | "status":"enable", 8 | "email":"13601161480@139.com", 9 | "roles":["SYSTEM"]} 10 | ); 11 | 12 | db.device.dropIndex("deviceAccount.username"); -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import org.springframework.data.mongodb.repository.MongoRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import top.microiot.domain.User; 7 | 8 | @Repository 9 | public interface UserRepository extends MongoRepository { 10 | public User findByUsername(String username); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/DomainRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import org.springframework.data.mongodb.repository.MongoRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import top.microiot.domain.Domain; 7 | 8 | @Repository 9 | public interface DomainRepository extends MongoRepository { 10 | public Domain findByName(String name); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/IoTController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import org.springframework.validation.BindingResult; 4 | 5 | import top.microiot.exception.ValueException; 6 | 7 | public abstract class IoTController { 8 | protected void throwError(BindingResult result) { 9 | if(result.hasErrors()) 10 | throw new ValueException(result.getFieldError().getDefaultMessage()); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/EventRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | 4 | import org.springframework.data.mongodb.repository.MongoRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import top.microiot.domain.Event; 8 | 9 | @Repository 10 | public interface EventRepository extends MongoRepository, CustomEventRepository { 11 | public void deleteByDomainId(String id); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/AlarmRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import org.springframework.data.mongodb.repository.MongoRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import top.microiot.domain.Alarm; 7 | 8 | @Repository 9 | public interface AlarmRepository extends MongoRepository, CustomAlarmRepository{ 10 | public int countByAlarmType(String alarmTypeId); 11 | public void deleteByDomainId(String id); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/CustomConfigRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import top.microiot.domain.Configuration; 6 | 7 | public interface CustomConfigRepository { 8 | public List queryConfiguration(String domainId, String userId, Boolean top, Boolean silent, Boolean subscribe); 9 | public Configuration findByUserAndNotifyObject(String userId, String notifyObjectId); 10 | public void deleteByNotifyObjectId(String id); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/CustomFavoriteRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import org.springframework.data.domain.Page; 4 | import org.springframework.data.domain.Pageable; 5 | 6 | import top.microiot.domain.Favorite; 7 | 8 | public interface CustomFavoriteRepository { 9 | public Page queryFavorite(String userId, String name, String type, String domainId, Pageable pageable); 10 | public Favorite getFavorite(String userId, String moId); 11 | public void deleteByMoId(String id); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/CustomEventRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | import top.microiot.domain.Event; 9 | 10 | public interface CustomEventRepository { 11 | public Page queryEvent(String domainId, String notifyObjectId, String attribute, Date reportFrom, Date reportTo, Date receiveFrom, Date receiveTo, Pageable pageable); 12 | public void deleteByNotifyObjectId(String id); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/IoTPasswordEncoder.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security; 2 | 3 | import org.springframework.security.crypto.password.PasswordEncoder; 4 | 5 | public class IoTPasswordEncoder implements PasswordEncoder { 6 | 7 | @Override 8 | public String encode(CharSequence arg0) { 9 | // TODO Auto-generated method stub 10 | return arg0.toString(); 11 | } 12 | 13 | @Override 14 | public boolean matches(CharSequence arg0, String arg1) { 15 | // TODO Auto-generated method stub 16 | return arg1.equals(arg0.toString()); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/SiteRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import org.springframework.data.mongodb.repository.MongoRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | import top.microiot.domain.Site; 7 | 8 | @Repository 9 | public interface SiteRepository extends MongoRepository, CustomSiteRepository { 10 | public Site findByNameAndSiteTypeIdAndLocation(String name, String siteTypeId, String parentId); 11 | public int countBySiteType(String siteTypeId); 12 | public void deleteByDomainId(String id); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/LoginUserRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import org.springframework.data.mongodb.repository.MongoRepository; 4 | 5 | import top.microiot.domain.LoginUser; 6 | 7 | public interface LoginUserRepository extends MongoRepository, CustomLoginUserRepository { 8 | public LoginUser findByToken(String token); 9 | public LoginUser findByRefreshToken(String refreshToken); 10 | public boolean existsByToken(String token); 11 | public boolean existsByUsername(String username); 12 | public void deleteByUsername(String username); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/CustomAlarmRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | import top.microiot.domain.Alarm; 9 | 10 | public interface CustomAlarmRepository { 11 | public Page queryAlarm(String domainId, String notifyObjectId, String alarmType, Date reportFrom, Date reportTo, Date receiveFrom, Date receiveTo, Pageable pageable); 12 | public void deleteByNotifyObjectId(String id); 13 | public Alarm queryLastAlarm(String deviceId); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/CustomLoginUserRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | import top.microiot.domain.LoginUser; 9 | 10 | public interface CustomLoginUserRepository { 11 | public Page queryLoginUser(Boolean isDevice, Boolean isExpire, Pageable pageable); 12 | public List removeLoginUserExpire(String username); 13 | public List removeLoginUser(String username); 14 | public boolean existLoginUserNotExpire(String username); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/CustomSiteRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | import top.microiot.domain.Site; 9 | 10 | public interface CustomSiteRepository { 11 | public Page querySite(String locationId, String domainId, String siteTypeId, String siteName, Pageable pageable); 12 | public List listSite(String locationId, String domainId, String siteTypeId, String siteName); 13 | public long countSite(String locationId, String domainId, String siteTypeId, String siteName); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/CurrentUserControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import org.springframework.security.core.Authentication; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ModelAttribute; 6 | 7 | import top.microiot.security.CustomUserDetails; 8 | 9 | @ControllerAdvice 10 | public class CurrentUserControllerAdvice { 11 | @ModelAttribute("currentUser") 12 | public CustomUserDetails getCurrentUser(Authentication authentication) { 13 | return (authentication == null) ? null : (CustomUserDetails) authentication.getPrincipal(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/CustomDeviceRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | 8 | import top.microiot.domain.Device; 9 | 10 | public interface CustomDeviceRepository { 11 | public Page queryDevice(String locationId, String domainId, String deviceName, String deviceTypeId, Pageable pageable); 12 | public List listDevice(String locationId, String domainId, String deviceName, String deviceTypeId); 13 | public long countDevice(String locationId, String domainId, String deviceName, String deviceTypeId); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=docker 2 | server.port=8082 3 | 4 | spring.data.mongodb.uri=mongodb://${microiot.mongo}:27017/iot 5 | 6 | management.endpoints.web.exposure.include=* 7 | management.endpoint.health.show-details=when-authorized 8 | 9 | microiot.websocket.host=${microiot.rabbitmq} 10 | microiot.websocket.port=61613 11 | microiot.websocket.username=guest 12 | microiot.websocket.password=guest 13 | microiot.websocket.virtual-host=/ 14 | microiot.websocket.endpoint=ws_iot 15 | 16 | microiot.authenticate.token.issuer=microiot 17 | microiot.authenticate.token.signing-key=xm8EV6Hy5RMFK4EEACIDAwQus 18 | microiot.authenticate.token.expiration-time=1 19 | microiot.authenticate.token.refresh-exp-time=24 -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/SiteTypeRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.mongodb.repository.MongoRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import top.microiot.domain.SiteType; 11 | 12 | @Repository 13 | public interface SiteTypeRepository extends MongoRepository { 14 | public SiteType findByNameAndDomain(String name, String domainId); 15 | public List findByDomainId(String domainId); 16 | public Page findByDomain(String domainId, Pageable pageable); 17 | public void deleteByDomainId(String id); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/ConfigRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.mongodb.repository.MongoRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import top.microiot.domain.Configuration; 11 | 12 | @Repository 13 | public interface ConfigRepository extends MongoRepository, CustomConfigRepository { 14 | public List findByUserId(String userId); 15 | public Page findByUserId(String userId, Pageable pageable); 16 | public void deleteByDomainId(String id); 17 | public void deleteByUserId(String id); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/DeviceTypeRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.mongodb.repository.MongoRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import top.microiot.domain.DeviceType; 11 | 12 | @Repository 13 | public interface DeviceTypeRepository extends MongoRepository { 14 | public DeviceType findByNameAndDomain(String typeName, String domainId); 15 | public List findByDomainId(String domainId); 16 | public Page findByDomain(String domainId, Pageable pageable); 17 | public void deleteByDomainId(String id); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/DeviceGroupRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.mongodb.repository.MongoRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import top.microiot.domain.DeviceGroup; 11 | 12 | @Repository 13 | public interface DeviceGroupRepository extends MongoRepository { 14 | public List findByDomainId(String id); 15 | public Page findByDomain(String id, Pageable pageable); 16 | public boolean existsByDevicesContaining(List devices); 17 | public List findByDevicesId(String deviceId); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/FavoriteRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.mongodb.repository.MongoRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import top.microiot.domain.Favorite; 11 | 12 | @Repository 13 | public interface FavoriteRepository extends MongoRepository, CustomFavoriteRepository { 14 | public Page findByUser(String userId, Pageable page); 15 | public List deleteByUserId(String userId); 16 | public Page findByUserAndNameLike(String userId, String name, Pageable page); 17 | public void deleteByDomainId(String id); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/DeviceRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.mongodb.repository.MongoRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import top.microiot.domain.Device; 11 | 12 | @Repository 13 | public interface DeviceRepository extends MongoRepository, CustomDeviceRepository { 14 | public int countByDeviceTypeInAndNameLike(List typeIds, String deviceName); 15 | public Device findByDeviceAccountUsername(String username); 16 | public Page findByNameLike(String deviceName, Pageable page); 17 | public int countByNameLike(String deviceName); 18 | public int countByDeviceType(String deviceTypeId); 19 | public void deleteByDomainId(String id); 20 | public List findByGatewayId(String id); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/authentication/TokenAuthenticationFailureHandler.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security.authentication; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.security.core.AuthenticationException; 11 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 12 | import org.springframework.stereotype.Component; 13 | 14 | @Component 15 | public class TokenAuthenticationFailureHandler implements AuthenticationFailureHandler { 16 | @Autowired 17 | public TokenAuthenticationFailureHandler() { 18 | } 19 | 20 | @Override 21 | public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, 22 | AuthenticationException e) throws IOException, ServletException { 23 | 24 | response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 25 | response.getWriter().append(e.getMessage()); 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/web/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | package top.microiot.web; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.http.converter.HttpMessageConverter; 6 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 7 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 8 | 9 | import com.fasterxml.jackson.databind.ObjectMapper; 10 | import com.fasterxml.jackson.databind.module.SimpleModule; 11 | 12 | import top.microiot.domain.User; 13 | import top.microiot.domain.UserSerializer; 14 | 15 | public class WebMvcConfig implements WebMvcConfigurer { 16 | 17 | @Override 18 | public void configureMessageConverters(List> converters) { 19 | MappingJackson2HttpMessageConverter jacksonMessageConverter = new MappingJackson2HttpMessageConverter(); 20 | ObjectMapper objectMapper = jacksonMessageConverter.getObjectMapper(); 21 | 22 | SimpleModule module = new SimpleModule(); 23 | module.addSerializer(User.class, new UserSerializer()); 24 | objectMapper.registerModule(module); 25 | 26 | converters.add(jacksonMessageConverter); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/authentication/SkipPathRequestMatcher.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security.authentication; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | 8 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 9 | import org.springframework.security.web.util.matcher.OrRequestMatcher; 10 | import org.springframework.security.web.util.matcher.RequestMatcher; 11 | 12 | public class SkipPathRequestMatcher implements RequestMatcher { 13 | private OrRequestMatcher matchers; 14 | private RequestMatcher processingMatcher; 15 | 16 | public SkipPathRequestMatcher(List pathsToSkip, String processingPath) { 17 | List m = pathsToSkip.stream().map(path -> new AntPathRequestMatcher(path)).collect(Collectors.toList()); 18 | matchers = new OrRequestMatcher(m); 19 | processingMatcher = new AntPathRequestMatcher(processingPath); 20 | } 21 | 22 | @Override 23 | public boolean matches(HttpServletRequest request) { 24 | if (matchers.matches(request)) { 25 | return false; 26 | } 27 | return processingMatcher.matches(request) ? true : false; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docker-compose/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | iot: 4 | build: 5 | context: ./ 6 | dockerfile: Dockerfile_iot 7 | restart: always 8 | container_name: "microiot_iot" 9 | ports: 10 | - 8082:8082 11 | links: 12 | - mongo 13 | - rabbitmq 14 | 15 | studio: 16 | build: 17 | context: ./ 18 | dockerfile: Dockerfile_studio 19 | container_name: "microiot_studio" 20 | restart: always 21 | ports: 22 | - 8081:80 23 | 24 | device: 25 | build: 26 | context: ./ 27 | dockerfile: Dockerfile_device 28 | container_name: "microiot_device" 29 | restart: always 30 | ports: 31 | - 8083:80 32 | 33 | mongo: 34 | build: 35 | context: ./ 36 | dockerfile: Dockerfile_mongo 37 | container_name: "microiot_mongo" 38 | restart: always 39 | ports: 40 | - 27017:27017 41 | 42 | rabbitmq: 43 | build: 44 | context: ./ 45 | dockerfile: Dockerfile_rabbit 46 | container_name: "microiot_rabbitmq" 47 | restart: always 48 | ports: 49 | - 5672:5672 50 | - 15672:15672 51 | - 61613:61613 52 | 53 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/authentication/TokenSettings.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security.authentication; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @ConfigurationProperties(prefix = "microiot.authenticate.token") 8 | public class TokenSettings { 9 | private Integer expirationTime; 10 | private String issuer; 11 | private String signingKey; 12 | private Integer refreshExpTime; 13 | 14 | public Integer getExpirationTime() { 15 | return expirationTime; 16 | } 17 | public void setExpirationTime(Integer expirationTime) { 18 | this.expirationTime = expirationTime; 19 | } 20 | public String getIssuer() { 21 | return issuer; 22 | } 23 | public void setIssuer(String issuer) { 24 | this.issuer = issuer; 25 | } 26 | public String getSigningKey() { 27 | return signingKey; 28 | } 29 | public void setSigningKey(String signingKey) { 30 | this.signingKey = signingKey; 31 | } 32 | public Integer getRefreshExpTime() { 33 | return refreshExpTime; 34 | } 35 | public void setRefreshExpTime(Integer refreshExpTime) { 36 | this.refreshExpTime = refreshExpTime; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/PageRepository.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.PageImpl; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.mongodb.core.MongoTemplate; 10 | import org.springframework.data.mongodb.core.query.Query; 11 | import org.springframework.stereotype.Repository; 12 | 13 | @Repository 14 | public class PageRepository { 15 | @Autowired 16 | private MongoTemplate mongoTemplate; 17 | 18 | public Page getPage(Class entityClass, Query query, Pageable pageable){ 19 | long total = mongoTemplate.count(query, entityClass); 20 | 21 | query.skip(pageable.getOffset()); 22 | query.limit(pageable.getPageSize()); 23 | query.with(pageable.getSort()); 24 | 25 | List data = mongoTemplate.find(query, entityClass); 26 | 27 | return new PageImpl(data, pageable, total); 28 | } 29 | 30 | public long count(Class entityClass, Query query){ 31 | return mongoTemplate.count(query, entityClass); 32 | } 33 | 34 | public List query(Class entityClass, Query query){ 35 | return mongoTemplate.find(query, entityClass); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/CustomUserService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | import org.springframework.security.core.userdetails.UserDetailsService; 6 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 7 | import org.springframework.stereotype.Component; 8 | 9 | import top.microiot.domain.Device; 10 | import top.microiot.domain.User; 11 | import top.microiot.repository.DeviceRepository; 12 | import top.microiot.repository.UserRepository; 13 | 14 | @Component 15 | public class CustomUserService implements UserDetailsService { 16 | @Autowired 17 | private UserRepository repository; 18 | @Autowired 19 | private DeviceRepository deviceRepository; 20 | 21 | @Override 22 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 23 | User user = repository.findByUsername(username); 24 | if(user != null) 25 | return new CustomUserDetails(user); 26 | else { 27 | Device device = deviceRepository.findByDeviceAccountUsername(username); 28 | if(device != null) 29 | return new CustomUserDetails(device.getDeviceAccount()); 30 | else 31 | throw new UsernameNotFoundException(String.format("User: %s was not found", username)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/web/WebsocketSetting.java: -------------------------------------------------------------------------------- 1 | package top.microiot.web; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | @Configuration 7 | @ConfigurationProperties(prefix = "microiot.websocket") 8 | public class WebsocketSetting { 9 | private String username; 10 | private String password; 11 | private String host; 12 | private int port; 13 | private String virtualHost; 14 | private String endpoint; 15 | 16 | public String getUsername() { 17 | return username; 18 | } 19 | public void setUsername(String username) { 20 | this.username = username; 21 | } 22 | public String getPassword() { 23 | return password; 24 | } 25 | public void setPassword(String password) { 26 | this.password = password; 27 | } 28 | public String getHost() { 29 | return host; 30 | } 31 | public void setHost(String host) { 32 | this.host = host; 33 | } 34 | public int getPort() { 35 | return port; 36 | } 37 | public void setPort(int port) { 38 | this.port = port; 39 | } 40 | public String getVirtualHost() { 41 | return virtualHost; 42 | } 43 | public void setVirtualHost(String virtualHost) { 44 | this.virtualHost = virtualHost; 45 | } 46 | public String getEndpoint() { 47 | return endpoint; 48 | } 49 | public void setEndpoint(String endpoint) { 50 | this.endpoint = endpoint; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Logo

2 |

MicroIoT

3 | MicroIoT是基于微服务架构的物联网平台,通过软件定义物联网元数据信息,对物联网进行配置和管理,利用这种集中式的物联网管理方法,将物联网基础设施和应用分离,使得MicroIoT物联网平台可以监视,控制任意类型的“物”,物联网应用与“物”之间、或者“物”与“物”之间的通信可以通过MicroIoT提供的API实现,加快物联网产品上市速度。 4 | 5 | ## 主要特色 6 | 7 | - MicroIoT物联网平台从业务的角度出发设计系统,支持快速定义任意类型“物”。对定义的各种类型“物”,实时生成监控界面,实时模拟生成数据,极大提高物联网应用开发的效率。 8 | - MicroIoT物联网平台从应用的角度出发设计系统,对用户隐藏技术细节,用户不需要了解底层的物联网通信协议和数据格式,不需要关心订阅消息主题,极大降低物联网应用开发的门槛。 9 | 10 | 11 | ## 产品家族 12 | 13 | | 项目 | 描述 | 14 | | ----------------------------------------------------------- | -------------------------------------- | 15 | | [MicroIoT Server](https://github.com/MicroIoT/iotplatform) | MicroIoT后台服务器 | 16 | | [MicroIoT API for Java](https://github.com/MicroIoT/iotapi) | MicroIoT应用端、设备端Java应用编程接口 | 17 | | [MicroIoT Studio](https://github.com/MicroIoT/studio) | MicroIoT web图形界面管理工具 | 18 | | [MicroIoT Device](https://github.com/MicroIoT/device) | MicroIoT web图形界面设备模拟器工具 | 19 | 20 | ## 文档 21 | 22 | MicroIoT文档包括入门指南,开发指南,API参考,请访问MicroIoT网站:[microiot.top](https://www.microiot.top) 23 | 24 | ## 社区 25 | 26 | 如果有任何意见或建议,请使用官方QQ交流群:856599970。 27 | 28 | ## 版权协议 29 | 30 | [GPL 3.0](https://opensource.org/licenses/GPL-3.0) 31 | 32 | Copyright (c) 2019, Cao XinYu 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/authentication/TokenAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security.authentication; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.security.authentication.AuthenticationServiceException; 5 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 6 | import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.stereotype.Component; 10 | 11 | import top.microiot.service.TokenService; 12 | 13 | @Component 14 | public class TokenAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { 15 | @Autowired 16 | private TokenService tokenService; 17 | 18 | @Override 19 | protected void additionalAuthenticationChecks(UserDetails userDetails, 20 | UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { 21 | // TODO Auto-generated method stub 22 | 23 | } 24 | 25 | @Override 26 | protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) 27 | throws AuthenticationException { 28 | String token= (String) authentication.getPrincipal(); 29 | try{ 30 | return tokenService.getCheckUser(token); 31 | } catch(Throwable e) { 32 | throw new AuthenticationServiceException(e.getMessage()); 33 | } 34 | 35 | } 36 | 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/WebsocketSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry; 5 | import org.springframework.security.config.annotation.web.socket.AbstractSecurityWebSocketMessageBrokerConfigurer; 6 | 7 | import top.microiot.domain.Role; 8 | import top.microiot.domain.Topic; 9 | 10 | @Configuration 11 | public class WebsocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer { 12 | private String topicAlarm = Topic.TOPIC_ALARM + "*"; 13 | private String topicResult = Topic.TOPIC_RESULT + "*.*.*"; 14 | private String topicOperation = Topic.TOPIC_OPERATION + "*.*"; 15 | 16 | @Override 17 | protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { 18 | messages 19 | .simpSubscribeDestMatchers(topicAlarm).hasAnyAuthority(Role.SYSTEM.toString(), Role.AREA.toString(), Role.DEVICE.toString()) 20 | .simpSubscribeDestMatchers(topicOperation).hasAuthority(Role.DEVICE.toString()) 21 | .simpSubscribeDestMatchers(topicResult).hasAnyAuthority(Role.SYSTEM.toString(), Role.AREA.toString(), Role.DEVICE.toString()) 22 | .simpMessageDestMatchers(topicOperation).hasAnyAuthority(Role.SYSTEM.toString(), Role.AREA.toString(), Role.DEVICE.toString()) 23 | .simpMessageDestMatchers(topicResult).hasAuthority(Role.DEVICE.toString()) 24 | .anyMessage().permitAll(); 25 | } 26 | 27 | @Override 28 | protected boolean sameOriginDisabled() { 29 | return true; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/web/WebsocketConfig.java: -------------------------------------------------------------------------------- 1 | package top.microiot.web; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.messaging.simp.config.ChannelRegistration; 6 | import org.springframework.messaging.simp.config.MessageBrokerRegistry; 7 | import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; 8 | import org.springframework.web.socket.config.annotation.StompEndpointRegistry; 9 | import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; 10 | 11 | @Configuration 12 | @EnableWebSocketMessageBroker 13 | public class WebsocketConfig implements WebSocketMessageBrokerConfigurer { 14 | @Autowired 15 | private WebsocketSetting wsSetting; 16 | @Autowired 17 | private WebsocketAuthorityInterceptor interceptor; 18 | 19 | @Override 20 | public void registerStompEndpoints(StompEndpointRegistry registry) { 21 | registry.addEndpoint(wsSetting.getEndpoint()).setAllowedOrigins("*"); 22 | } 23 | 24 | @Override 25 | public void configureMessageBroker(MessageBrokerRegistry registry) { 26 | registry.setApplicationDestinationPrefixes("/app"); 27 | registry.enableStompBrokerRelay("/topic", "/queue/") 28 | .setClientLogin(wsSetting.getUsername()) 29 | .setClientPasscode(wsSetting.getPassword()) 30 | .setSystemLogin(wsSetting.getUsername()) 31 | .setSystemPasscode(wsSetting.getPassword()) 32 | .setRelayHost(wsSetting.getHost()) 33 | .setRelayPort(wsSetting.getPort()) 34 | .setVirtualHost(wsSetting.getVirtualHost()); 35 | } 36 | 37 | @Override 38 | public void configureClientInboundChannel(ChannelRegistration registration) { 39 | registration.interceptors(interceptor); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/FavoriteRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import org.bson.types.ObjectId; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.mongodb.core.MongoTemplate; 8 | import org.springframework.data.mongodb.core.query.Criteria; 9 | import org.springframework.data.mongodb.core.query.Query; 10 | 11 | import top.microiot.domain.Favorite; 12 | 13 | public class FavoriteRepositoryImpl implements CustomFavoriteRepository { 14 | @Autowired 15 | private PageRepository page; 16 | @Autowired 17 | private MongoTemplate mongoTemplate; 18 | 19 | @Override 20 | public Page queryFavorite(String userId, String name, String type, String domainId, Pageable pageable) { 21 | Query query = new Query(); 22 | query.addCriteria(Criteria.where("user.$id").is(new ObjectId(userId))); 23 | query.addCriteria(Criteria.where("domain.$id").is(new ObjectId(domainId))); 24 | 25 | if(type != null && type.length() > 0) 26 | query.addCriteria(Criteria.where("mo.$ref").is(type)); 27 | if(name != null) 28 | query.addCriteria(Criteria.where("name").regex(name)); 29 | 30 | return page.getPage(Favorite.class, query, pageable); 31 | } 32 | 33 | public Favorite getFavorite(String userId, String moId) { 34 | Query query = new Query(); 35 | query.addCriteria(Criteria.where("mo.$id").is(new ObjectId(moId))); 36 | query.addCriteria(Criteria.where("user.$id").is(new ObjectId(userId))); 37 | 38 | return mongoTemplate.findOne(query, Favorite.class); 39 | } 40 | 41 | @Override 42 | public void deleteByMoId(String id) { 43 | Query query = Query.query(Criteria.where("mo.$id").is(new ObjectId(id))); 44 | mongoTemplate.remove(query, Favorite.class); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/ConfigRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.bson.types.ObjectId; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.mongodb.core.MongoTemplate; 8 | import org.springframework.data.mongodb.core.query.Criteria; 9 | import org.springframework.data.mongodb.core.query.Query; 10 | 11 | import top.microiot.domain.Configuration; 12 | 13 | public class ConfigRepositoryImpl implements CustomConfigRepository { 14 | @Autowired 15 | private MongoTemplate mongoTemplate; 16 | 17 | @Override 18 | public List queryConfiguration(String domainId, String userId, Boolean top, Boolean silent, Boolean subscribe) { 19 | Query query = new Query(); 20 | if(userId != null && userId.length() > 0) 21 | query.addCriteria(Criteria.where("user.$id").is(new ObjectId(userId))); 22 | 23 | if(top != null) 24 | query.addCriteria(Criteria.where("top").is(top)); 25 | 26 | if(silent != null) 27 | query.addCriteria(Criteria.where("silent").is(silent)); 28 | 29 | if(subscribe != null) 30 | query.addCriteria(Criteria.where("subscribe").is(subscribe)); 31 | 32 | if(domainId != null ) { 33 | query.addCriteria(Criteria.where("domain.$id").is(new ObjectId(domainId))); 34 | } 35 | return mongoTemplate.find(query, Configuration.class); 36 | } 37 | 38 | @Override 39 | public Configuration findByUserAndNotifyObject(String userId, String notifyObjectId) { 40 | Query query = new Query(); 41 | query.addCriteria(Criteria.where("notifyObject.$id").is(new ObjectId(notifyObjectId))); 42 | query.addCriteria(Criteria.where("user.$id").is(new ObjectId(userId))); 43 | 44 | return mongoTemplate.findOne(query, Configuration.class); 45 | } 46 | 47 | @Override 48 | public void deleteByNotifyObjectId(String id) { 49 | Query query = Query.query(Criteria.where("notifyObject.$id").is(new ObjectId(id))); 50 | mongoTemplate.remove(query, Configuration.class); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/EventController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import javax.validation.Valid; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.security.access.prepost.PreAuthorize; 8 | import org.springframework.validation.BindingResult; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.PostMapping; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import top.microiot.domain.Event; 17 | import top.microiot.dto.EventInfo; 18 | import top.microiot.dto.EventPageInfo; 19 | import top.microiot.dto.SubDeviceEventInfo; 20 | import top.microiot.service.EventService; 21 | 22 | @RestController 23 | @RequestMapping("/events") 24 | public class EventController extends IoTController{ 25 | @Autowired 26 | private EventService eventService; 27 | 28 | @PreAuthorize("hasAuthority('DEVICE')") 29 | @PostMapping("") 30 | public void report(@RequestBody @Valid EventInfo info, BindingResult result) { 31 | throwError(result); 32 | eventService.report(info); 33 | } 34 | 35 | @PreAuthorize("hasAuthority('DEVICE')") 36 | @PostMapping("/subdevice") 37 | public void report(@RequestBody @Valid SubDeviceEventInfo info, BindingResult result) { 38 | throwError(result); 39 | eventService.report(info); 40 | } 41 | 42 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 43 | @GetMapping("/{id}") 44 | public Event getEvent(@PathVariable String id){ 45 | return eventService.listEvent(id); 46 | } 47 | 48 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 49 | @GetMapping("") 50 | public Page listEvent(@Valid EventPageInfo info, BindingResult result){ 51 | throwError(result); 52 | return eventService.listEvents(info); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | logback 4 | 5 | 6 | 7 | 10 | 11 | %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n 12 | 13 | 14 | 15 | 16 | 17 | ${log.path} 18 | 19 | logback.%d{yyyy-MM-dd}.log 20 | 21 | 22 | %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/AlarmController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import javax.validation.Valid; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.security.access.prepost.PreAuthorize; 8 | import org.springframework.validation.BindingResult; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PathVariable; 11 | import org.springframework.web.bind.annotation.PostMapping; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import top.microiot.domain.Alarm; 17 | import top.microiot.dto.AlarmInfo; 18 | import top.microiot.dto.AlarmPageInfo; 19 | import top.microiot.dto.SubDeviceAlarmInfo; 20 | import top.microiot.service.AlarmService; 21 | 22 | @RestController 23 | @RequestMapping("/alarms") 24 | public class AlarmController extends IoTController{ 25 | @Autowired 26 | private AlarmService alarmService; 27 | 28 | @PreAuthorize("hasAuthority('DEVICE')") 29 | @PostMapping("") 30 | public Alarm report(@RequestBody @Valid AlarmInfo info, BindingResult result) { 31 | throwError(result); 32 | return alarmService.report(info); 33 | } 34 | 35 | @PreAuthorize("hasAuthority('DEVICE')") 36 | @PostMapping("/subdevice") 37 | public Alarm report(@RequestBody @Valid SubDeviceAlarmInfo info, BindingResult result) { 38 | throwError(result); 39 | return alarmService.report(info); 40 | } 41 | 42 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 43 | @GetMapping("/{id}") 44 | public Alarm getAlarm(@PathVariable String id){ 45 | return alarmService.listAlarm(id); 46 | } 47 | 48 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 49 | @GetMapping("") 50 | public Page listAlarm(@Valid AlarmPageInfo info, BindingResult result){ 51 | throwError(result); 52 | 53 | return alarmService.listAlarms(info); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/SiteRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.bson.types.ObjectId; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.mongodb.core.query.Criteria; 10 | import org.springframework.data.mongodb.core.query.Query; 11 | 12 | import top.microiot.domain.Site; 13 | 14 | public class SiteRepositoryImpl implements CustomSiteRepository { 15 | @Autowired 16 | private PageRepository page; 17 | 18 | @Override 19 | public Page querySite(String locationId, String domainId, String siteTypeId, String siteName, Pageable pageable) { 20 | Query query = getQuery(locationId, domainId, siteTypeId, siteName); 21 | 22 | Page p = page.getPage(Site.class, query, pageable); 23 | return p; 24 | } 25 | 26 | @Override 27 | public List listSite(String locationId, String domainId, String siteTypeId, String siteName) { 28 | Query query = getQuery(locationId, domainId, siteTypeId, siteName); 29 | 30 | return page.query(Site.class, query); 31 | } 32 | 33 | @Override 34 | public long countSite(String locationId, String domainId, String siteTypeId, String name) { 35 | Query query = getQuery(locationId, domainId, siteTypeId, name); 36 | 37 | return page.count(Site.class, query); 38 | } 39 | 40 | private Query getQuery(String locationId, String domainId, String siteTypeId, String siteName) { 41 | Query query = new Query(); 42 | if(domainId != null && domainId.length() > 0) 43 | query.addCriteria(Criteria.where("domain.$id").is(new ObjectId(domainId))); 44 | 45 | if(siteTypeId != null && siteTypeId.length() > 0) 46 | query.addCriteria(Criteria.where("siteType.$id").is(new ObjectId(siteTypeId))); 47 | 48 | if(siteName != null && siteName.length() > 0) 49 | query.addCriteria(Criteria.where("name").regex(siteName)); 50 | 51 | if(locationId != null) { 52 | query.addCriteria(Criteria.where("location.$id").is(new ObjectId(locationId))); 53 | } 54 | 55 | return query; 56 | } 57 | 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/IoTService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.domain.PageRequest; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.data.domain.Sort; 7 | import org.springframework.data.domain.Sort.Direction; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.security.core.context.SecurityContextHolder; 10 | import org.springframework.stereotype.Component; 11 | 12 | import top.microiot.domain.Device; 13 | import top.microiot.domain.Domain; 14 | import top.microiot.domain.User; 15 | import top.microiot.dto.PageInfo; 16 | import top.microiot.exception.StatusException; 17 | import top.microiot.repository.DeviceRepository; 18 | import top.microiot.security.CustomUserDetails; 19 | 20 | @Component 21 | public abstract class IoTService { 22 | @Autowired 23 | private DeviceRepository deviceRepository; 24 | 25 | public User getCurrentUser() { 26 | Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 27 | CustomUserDetails user = (CustomUserDetails) auth.getPrincipal(); 28 | return user.getUser(); 29 | } 30 | 31 | public Device getCurrentDevice() { 32 | Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 33 | CustomUserDetails user = (CustomUserDetails) auth.getPrincipal(); 34 | return deviceRepository.findByDeviceAccountUsername(user.getUsername()); 35 | } 36 | 37 | public Domain getCurrentDomain() { 38 | Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 39 | CustomUserDetails user = (CustomUserDetails) auth.getPrincipal(); 40 | Domain domain = user.getDomain(); 41 | if (domain == null) 42 | throw new StatusException("Please choose domain first."); 43 | else 44 | return domain; 45 | } 46 | 47 | protected Pageable getPageable(PageInfo info) { 48 | if (info == null) 49 | info = new PageInfo(); 50 | 51 | Sort sort = new Sort(Direction.DESC, "id"); 52 | Pageable pageable = PageRequest.of(info.getCurrentPage(), info.getNumPerPage(), sort); 53 | return pageable; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/DeviceRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.bson.types.ObjectId; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.mongodb.core.query.Criteria; 10 | import org.springframework.data.mongodb.core.query.Query; 11 | 12 | import top.microiot.domain.Device; 13 | 14 | public class DeviceRepositoryImpl implements CustomDeviceRepository { 15 | @Autowired 16 | private PageRepository page; 17 | 18 | @Override 19 | public Page queryDevice(String locationId, String domainId, String deviceName, String deviceTypeId, Pageable pageable) { 20 | Query query = getQuery(locationId, domainId, deviceName, deviceTypeId); 21 | 22 | Page p = page.getPage(Device.class, query, pageable); 23 | return p; 24 | } 25 | 26 | @Override 27 | public long countDevice(String locationId, String domainId, String name, String deviceTypeId) { 28 | Query query = getQuery(locationId, domainId, name, deviceTypeId); 29 | 30 | return page.count(Device.class, query); 31 | } 32 | 33 | private Query getQuery(String locationId, String domainId, String name, String deviceTypeId) { 34 | Query query = new Query(); 35 | if (deviceTypeId != null && deviceTypeId.length() > 0) { 36 | query.addCriteria(Criteria.where("deviceType.$id").is(new ObjectId(deviceTypeId))); 37 | } 38 | 39 | if (name != null && name.length() > 0) 40 | query.addCriteria(Criteria.where("name").regex(name)); 41 | 42 | if(locationId != null && locationId.length() > 0) { 43 | query.addCriteria(Criteria.where("location.$id").is(new ObjectId(locationId))); 44 | } 45 | 46 | if(domainId != null ) { 47 | query.addCriteria(Criteria.where("domain.$id").is(new ObjectId(domainId))); 48 | } 49 | return query; 50 | } 51 | 52 | @Override 53 | public List listDevice(String siteId, String domainId, String deviceName, String deviceTypeId) { 54 | Query query = getQuery(siteId, domainId, deviceName, deviceTypeId); 55 | 56 | return page.query(Device.class, query); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/LoginUserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.mongodb.core.MongoTemplate; 10 | import org.springframework.data.mongodb.core.query.Criteria; 11 | import org.springframework.data.mongodb.core.query.Query; 12 | 13 | import top.microiot.domain.LoginUser; 14 | 15 | public class LoginUserRepositoryImpl implements CustomLoginUserRepository { 16 | @Autowired 17 | private PageRepository page; 18 | @Autowired 19 | private MongoTemplate mongoTemplate; 20 | 21 | @Override 22 | public Page queryLoginUser(Boolean isDevice, Boolean isExpire, Pageable pageable) { 23 | Query query = new Query(); 24 | if(isDevice != null) 25 | query.addCriteria(Criteria.where("isDevice").is(isDevice)); 26 | if(isExpire != null) { 27 | if(isExpire) 28 | query.addCriteria(Criteria.where("refreshExpire").lt(new Date())); 29 | else 30 | query.addCriteria(Criteria.where("refreshExpire").gt(new Date())); 31 | } 32 | return page.getPage(LoginUser.class, query, pageable); 33 | } 34 | 35 | @Override 36 | public List removeLoginUserExpire(String username) { 37 | Query query = new Query(); 38 | query.addCriteria(Criteria.where("username").is(username)); 39 | query.addCriteria(Criteria.where("refreshExpire").lt(new Date())); 40 | return mongoTemplate.findAllAndRemove(query, LoginUser.class); 41 | } 42 | 43 | @Override 44 | public List removeLoginUser(String username) { 45 | Query query = new Query(); 46 | query.addCriteria(Criteria.where("username").is(username)); 47 | return mongoTemplate.findAllAndRemove(query, LoginUser.class); 48 | } 49 | 50 | @Override 51 | public boolean existLoginUserNotExpire(String username) { 52 | Query query = new Query(); 53 | query.addCriteria(Criteria.where("username").is(username)); 54 | query.addCriteria(Criteria.where("refreshExpire").gt(new Date())); 55 | return mongoTemplate.exists(query, LoginUser.class); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/TokenController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import static org.springframework.http.HttpHeaders.AUTHORIZATION; 4 | 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.validation.Valid; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.data.domain.Page; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.validation.BindingResult; 12 | import org.springframework.web.bind.annotation.DeleteMapping; 13 | import org.springframework.web.bind.annotation.GetMapping; 14 | import org.springframework.web.bind.annotation.PathVariable; 15 | import org.springframework.web.bind.annotation.PostMapping; 16 | import org.springframework.web.bind.annotation.RequestBody; 17 | import org.springframework.web.bind.annotation.RestController; 18 | 19 | import top.microiot.domain.LoginUser; 20 | import top.microiot.domain.Token; 21 | import top.microiot.dto.LoginInfo; 22 | import top.microiot.dto.LoginUserPageInfo; 23 | import top.microiot.service.TokenService; 24 | 25 | @RestController 26 | public class TokenController extends IoTController{ 27 | @Autowired 28 | private TokenService tokenService; 29 | 30 | @PostMapping("/login") 31 | public Token login(HttpServletRequest request, @RequestBody @Valid LoginInfo info, BindingResult result) { 32 | throwError(result); 33 | String ip = request.getRemoteAddr(); 34 | return tokenService.login(info, ip); 35 | } 36 | 37 | @GetMapping("/token") 38 | public Token refresh(HttpServletRequest request) { 39 | String token = request.getHeader(AUTHORIZATION); 40 | return tokenService.refreshToken(token); 41 | } 42 | 43 | @PreAuthorize("hasAuthority('SYSTEM')") 44 | @GetMapping("/sessions") 45 | public Page queryLoginUser(@Valid LoginUserPageInfo info, BindingResult result) { 46 | throwError(result); 47 | 48 | return tokenService.queryLoginUser(info); 49 | } 50 | 51 | @PreAuthorize("hasAuthority('SYSTEM')") 52 | @DeleteMapping("/sessions/{id}") 53 | public void delete(@PathVariable String id){ 54 | tokenService.delete(id); 55 | } 56 | 57 | @PreAuthorize("hasAuthority('SYSTEM')") 58 | @GetMapping("/sessions/{id}") 59 | public LoginUser getSession(@PathVariable String id){ 60 | return tokenService.get(id); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/web/WebsocketConnectedListener.java: -------------------------------------------------------------------------------- 1 | package top.microiot.web; 2 | 3 | import java.util.Date; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.context.ApplicationListener; 9 | import org.springframework.messaging.simp.SimpMessagingTemplate; 10 | import org.springframework.security.core.Authentication; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.web.socket.messaging.SessionConnectedEvent; 13 | 14 | import top.microiot.domain.Alarm; 15 | import top.microiot.domain.AlarmType; 16 | import top.microiot.domain.Device; 17 | import top.microiot.repository.AlarmRepository; 18 | import top.microiot.repository.DeviceRepository; 19 | import top.microiot.security.CustomUserDetails; 20 | 21 | @Component 22 | public class WebsocketConnectedListener implements ApplicationListener { 23 | private Logger logger = LoggerFactory.getLogger(this.getClass()); 24 | @Autowired 25 | private DeviceRepository deviceRepository; 26 | @Autowired 27 | private AlarmRepository alarmRepository; 28 | @Autowired 29 | private SimpMessagingTemplate template; 30 | 31 | @Override 32 | public void onApplicationEvent(SessionConnectedEvent event) { 33 | SessionConnectedEvent e = (SessionConnectedEvent)event; 34 | Date date = new Date(e.getTimestamp()); 35 | 36 | if((Authentication)e.getUser() != null) { 37 | CustomUserDetails user = (CustomUserDetails) ((Authentication)e.getUser()).getPrincipal(); 38 | if (user.isDevice()){ 39 | Device device = deviceRepository.findByDeviceAccountUsername(user.getUsername()); 40 | logger.debug("connected device is " + user.getUsername() + " at " + date); 41 | Alarm last = alarmRepository.queryLastAlarm(device.getId()); 42 | if(last == null || (last != null && last.getReportTime().before(date))) { 43 | if(!device.isConnected()){ 44 | device.setConnected(true); 45 | deviceRepository.save(device); 46 | } 47 | Alarm alarm = new Alarm(device, AlarmType.CONNECTED_ALARM, null, date); 48 | alarm = alarmRepository.save(alarm); 49 | String destination = "/topic/alarm." + device.getId(); 50 | template.convertAndSend(destination, alarm); 51 | } 52 | } 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/web/WebsocketDisconnectListener.java: -------------------------------------------------------------------------------- 1 | package top.microiot.web; 2 | 3 | import java.util.Date; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.context.ApplicationListener; 9 | import org.springframework.messaging.simp.SimpMessagingTemplate; 10 | import org.springframework.security.core.Authentication; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.web.socket.messaging.SessionDisconnectEvent; 13 | 14 | import top.microiot.domain.Alarm; 15 | import top.microiot.domain.AlarmType; 16 | import top.microiot.domain.Device; 17 | import top.microiot.repository.AlarmRepository; 18 | import top.microiot.repository.DeviceRepository; 19 | import top.microiot.security.CustomUserDetails; 20 | 21 | @Component 22 | public class WebsocketDisconnectListener implements ApplicationListener { 23 | private Logger logger = LoggerFactory.getLogger(this.getClass()); 24 | @Autowired 25 | private DeviceRepository deviceRepository; 26 | @Autowired 27 | private AlarmRepository alarmRepository; 28 | @Autowired 29 | private SimpMessagingTemplate template; 30 | 31 | @Override 32 | public void onApplicationEvent(SessionDisconnectEvent event) { 33 | SessionDisconnectEvent e = (SessionDisconnectEvent)event; 34 | Date date = new Date(e.getTimestamp()); 35 | if((Authentication)e.getUser() != null) { 36 | CustomUserDetails user = (CustomUserDetails) ((Authentication)e.getUser()).getPrincipal(); 37 | if (user.isDevice()){ 38 | Device device = deviceRepository.findByDeviceAccountUsername(user.getUsername()); 39 | logger.debug("disconnected device is " + user.getUsername() + " at " + date); 40 | Alarm last = alarmRepository.queryLastAlarm(device.getId()); 41 | if(last == null || (last != null && last.getReportTime().before(date))) { 42 | if(device.isConnected()){ 43 | device.setConnected(false); 44 | deviceRepository.save(device); 45 | } 46 | Alarm alarm = new Alarm(device, AlarmType.DISCONNECTED_ALARM, null, date); 47 | alarm = alarmRepository.save(alarm); 48 | String destination = "/topic/alarm." + device.getId(); 49 | template.convertAndSend(destination, alarm); 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/ConfigController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import java.util.List; 4 | 5 | import javax.validation.Valid; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.access.prepost.PreAuthorize; 9 | import org.springframework.validation.BindingResult; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.PatchMapping; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RestController; 16 | 17 | import top.microiot.domain.Configuration; 18 | import top.microiot.dto.ConfigInfo; 19 | import top.microiot.dto.ConfigListInfo; 20 | import top.microiot.exception.ValueException; 21 | import top.microiot.service.ConfigService; 22 | 23 | @RestController 24 | @RequestMapping("/configurations") 25 | public class ConfigController extends IoTController{ 26 | @Autowired 27 | private ConfigService configService; 28 | 29 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 30 | @GetMapping("/list") 31 | public List listAll(@Valid ConfigListInfo info, BindingResult result){ 32 | throwError(result); 33 | return configService.queryConfiguration(info.getTop(), info.getSilent(), info.getSubscribe()); 34 | } 35 | 36 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 37 | @GetMapping("/{moId}") 38 | public Configuration listOne(@PathVariable String moId){ 39 | return configService.listOne(moId); 40 | } 41 | 42 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 43 | @PatchMapping("") 44 | public Configuration config(@RequestBody @Valid ConfigInfo info, BindingResult result) { 45 | throwError(result); 46 | if(info.getKey().equals("silent")) 47 | return configService.configSilent(info.getNotifyObjectId(), info.getValue()); 48 | else if(info.getKey().equals("top")) 49 | return configService.configTop(info.getNotifyObjectId(), info.getValue()); 50 | else if(info.getKey().equals("subscribe")) 51 | return configService.configSubscribe(info.getNotifyObjectId(), info.getValue()); 52 | else 53 | throw new ValueException("illegal config: " + info.getKey()); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/EventRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.Date; 4 | 5 | import org.bson.types.ObjectId; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.mongodb.core.MongoTemplate; 10 | import org.springframework.data.mongodb.core.query.Criteria; 11 | import org.springframework.data.mongodb.core.query.Query; 12 | 13 | import top.microiot.domain.Event; 14 | 15 | public class EventRepositoryImpl implements CustomEventRepository { 16 | @Autowired 17 | private PageRepository page; 18 | @Autowired 19 | private MongoTemplate mongoTemplate; 20 | 21 | @Override 22 | public Page queryEvent(String domainId, String deviceId, String attribute, Date reportFrom, Date reportTo, Date receiveFrom, Date receiveTo, Pageable pageable) { 23 | Query query = new Query(); 24 | query.addCriteria(Criteria.where("domain.$id").is(new ObjectId(domainId))); 25 | 26 | if(deviceId != null) 27 | query.addCriteria(Criteria.where("notifyObject.$id").is(new ObjectId(deviceId))); 28 | if(attribute != null) 29 | query.addCriteria(Criteria.where("attribute").is(attribute)); 30 | 31 | if(reportFrom != null && reportTo != null){ 32 | Criteria c = new Criteria().andOperator(Criteria.where("reportTime").gt(reportFrom), Criteria.where("reportTime").lt(reportTo)); 33 | query.addCriteria(c); 34 | } 35 | if(reportFrom != null && reportTo == null) 36 | query.addCriteria(Criteria.where("reportTime").gt(reportFrom)); 37 | if(reportFrom == null && reportTo != null) 38 | query.addCriteria(Criteria.where("reportTime").lt(reportTo)); 39 | 40 | if(receiveFrom != null && receiveTo != null){ 41 | Criteria c = new Criteria().andOperator(Criteria.where("receiveTime").gt(reportFrom), Criteria.where("receiveTime").lt(reportTo)); 42 | query.addCriteria(c); 43 | } 44 | if(receiveFrom != null && receiveTo == null) 45 | query.addCriteria(Criteria.where("receiveTime").gt(reportFrom)); 46 | if(receiveFrom == null && receiveTo != null) 47 | query.addCriteria(Criteria.where("receiveTime").lt(reportTo)); 48 | 49 | return page.getPage(Event.class, query, pageable); 50 | } 51 | 52 | @Override 53 | public void deleteByNotifyObjectId(String id) { 54 | Query query = Query.query(Criteria.where("notifyObject.$id").is(new ObjectId(id))); 55 | mongoTemplate.remove(query, Event.class); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/authentication/TokenAuthenticationProcessingFilter.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security.authentication; 2 | 3 | import static org.springframework.http.HttpHeaders.AUTHORIZATION; 4 | 5 | import java.io.IOException; 6 | 7 | import javax.servlet.FilterChain; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 14 | import org.springframework.security.core.Authentication; 15 | import org.springframework.security.core.AuthenticationException; 16 | import org.springframework.security.core.context.SecurityContextHolder; 17 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; 18 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 19 | import org.springframework.security.web.util.matcher.RequestMatcher; 20 | 21 | import top.microiot.service.TokenService; 22 | 23 | public class TokenAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter { 24 | private AuthenticationFailureHandler failureHandler; 25 | private TokenService tokenService; 26 | 27 | @Autowired 28 | public TokenAuthenticationProcessingFilter(TokenService tokenService, AuthenticationFailureHandler failureHandler, RequestMatcher requestMatcher) { 29 | super(requestMatcher); 30 | this.tokenService = tokenService; 31 | this.failureHandler = failureHandler; 32 | } 33 | 34 | @Override 35 | public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) 36 | throws AuthenticationException, IOException, ServletException { 37 | String token = request.getHeader(AUTHORIZATION); 38 | token = tokenService.extractToken(token); 39 | Authentication requestAuthentication = new UsernamePasswordAuthenticationToken(token, null); 40 | return getAuthenticationManager().authenticate(requestAuthentication); 41 | } 42 | 43 | 44 | 45 | @Override 46 | protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, 47 | Authentication authResult) throws IOException, ServletException { 48 | SecurityContextHolder.getContext().setAuthentication(authResult); 49 | chain.doFilter(request, response); 50 | } 51 | 52 | @Override 53 | protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, 54 | AuthenticationException failed) throws IOException, ServletException { 55 | SecurityContextHolder.clearContext(); 56 | failureHandler.onAuthenticationFailure(request, response, failed); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/FavoriteController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import javax.validation.Valid; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.security.access.prepost.PreAuthorize; 8 | import org.springframework.validation.BindingResult; 9 | import org.springframework.web.bind.annotation.DeleteMapping; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.PatchMapping; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | import org.springframework.web.bind.annotation.PostMapping; 14 | import org.springframework.web.bind.annotation.RequestBody; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import top.microiot.domain.Favorite; 19 | import top.microiot.dto.FavoriteExistInfo; 20 | import top.microiot.dto.FavoriteInfo; 21 | import top.microiot.dto.FavoritePageInfo; 22 | import top.microiot.dto.FavoriteUpdateInfo; 23 | import top.microiot.service.FavoriteService; 24 | 25 | @RestController 26 | @RequestMapping("/favorites") 27 | public class FavoriteController extends IoTController{ 28 | @Autowired 29 | private FavoriteService favoriteService; 30 | 31 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 32 | @PostMapping("") 33 | public Favorite add(@RequestBody @Valid FavoriteInfo info, BindingResult result) { 34 | throwError(result); 35 | return favoriteService.add(info); 36 | } 37 | 38 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 39 | @DeleteMapping("/{id}") 40 | public void delete(@PathVariable String id){ 41 | favoriteService.delete(id); 42 | } 43 | 44 | @PreAuthorize("hasAuthority('AREA') or hasAuthority('SYSTEM')") 45 | @GetMapping("") 46 | public Page getAll(@Valid FavoritePageInfo info, BindingResult result){ 47 | throwError(result); 48 | return favoriteService.listAll(info); 49 | } 50 | 51 | @PreAuthorize("hasAuthority('AREA') or hasAuthority('SYSTEM')") 52 | @GetMapping("/{id}") 53 | public Favorite getFavorite(@PathVariable String id){ 54 | return favoriteService.listFavorite(id); 55 | } 56 | 57 | @PreAuthorize("hasAuthority('AREA') or hasAuthority('SYSTEM')") 58 | @PatchMapping("") 59 | public Favorite update(@RequestBody @Valid FavoriteUpdateInfo info, BindingResult result) { 60 | throwError(result); 61 | return favoriteService.update(info); 62 | } 63 | 64 | @PreAuthorize("hasAuthority('AREA') or hasAuthority('SYSTEM')") 65 | @GetMapping("/exist") 66 | public Favorite isExist(@Valid FavoriteExistInfo info, BindingResult result) { 67 | throwError(result); 68 | return favoriteService.get(info); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/repository/AlarmRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package top.microiot.repository; 2 | 3 | import java.util.Date; 4 | 5 | import org.bson.types.ObjectId; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.data.domain.Sort; 10 | import org.springframework.data.mongodb.core.MongoTemplate; 11 | import org.springframework.data.mongodb.core.query.Criteria; 12 | import org.springframework.data.mongodb.core.query.Query; 13 | 14 | import top.microiot.domain.Alarm; 15 | 16 | public class AlarmRepositoryImpl implements CustomAlarmRepository { 17 | @Autowired 18 | private PageRepository page; 19 | @Autowired 20 | private MongoTemplate mongoTemplate; 21 | 22 | @Override 23 | public Page queryAlarm(String domainId, String notifyObjectId, String alarmType, Date reportFrom, Date reportTo, Date receiveFrom, Date receiveTo, Pageable pageable) { 24 | Query query = new Query(); 25 | query.addCriteria(Criteria.where("domain.$id").is(new ObjectId(domainId))); 26 | 27 | if(notifyObjectId != null) 28 | query.addCriteria(Criteria.where("notifyObject.$id").is(new ObjectId(notifyObjectId))); 29 | 30 | if(alarmType != null) 31 | query.addCriteria(Criteria.where("alarmType").is(alarmType)); 32 | 33 | if(reportFrom != null && reportTo != null){ 34 | Criteria c = new Criteria().andOperator(Criteria.where("reportTime").gt(reportFrom), Criteria.where("reportTime").lt(reportTo)); 35 | query.addCriteria(c); 36 | } 37 | if(reportFrom != null && reportTo == null) 38 | query.addCriteria(Criteria.where("reportTime").gt(reportFrom)); 39 | if(reportFrom == null && reportTo != null) 40 | query.addCriteria(Criteria.where("reportTime").lt(reportTo)); 41 | 42 | if(reportFrom != null && reportTo != null){ 43 | Criteria c = new Criteria().andOperator(Criteria.where("receiveTime").gt(reportFrom), Criteria.where("receiveTime").lt(reportTo)); 44 | query.addCriteria(c); 45 | } 46 | if(reportFrom != null && reportTo == null) 47 | query.addCriteria(Criteria.where("receiveTime").gt(reportFrom)); 48 | if(reportFrom == null && reportTo != null) 49 | query.addCriteria(Criteria.where("receiveTime").lt(reportTo)); 50 | 51 | return page.getPage(Alarm.class, query, pageable); 52 | } 53 | 54 | @Override 55 | public void deleteByNotifyObjectId(String id) { 56 | Query query = Query.query(Criteria.where("notifyObject.$id").is(new ObjectId(id))); 57 | mongoTemplate.remove(query, Alarm.class); 58 | } 59 | 60 | @Override 61 | public Alarm queryLastAlarm(String deviceId) { 62 | Query query = new Query(); 63 | query.addCriteria(Criteria.where("notifyObject.$id").is(new ObjectId(deviceId))); 64 | query.with(new Sort(Sort.Direction.DESC, "reportTime")); 65 | 66 | return mongoTemplate.findOne(query, Alarm.class); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/CustomUserDetails.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.List; 6 | 7 | import org.springframework.security.core.GrantedAuthority; 8 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | 11 | import top.microiot.domain.Domain; 12 | import top.microiot.domain.Role; 13 | import top.microiot.domain.User; 14 | 15 | @SuppressWarnings("serial") 16 | public class CustomUserDetails implements UserDetails { 17 | private User user; 18 | private Domain domain; 19 | 20 | public User getUser() { 21 | return user; 22 | } 23 | 24 | public Domain getDomain() { 25 | return domain; 26 | } 27 | 28 | public void setDomain(Domain domain) { 29 | this.domain = domain; 30 | } 31 | 32 | public CustomUserDetails(User user){ 33 | this.user = user; 34 | } 35 | 36 | public String getUserId(){ 37 | return user.getId(); 38 | } 39 | 40 | public boolean isSystem(){ 41 | return user.isSystem(); 42 | } 43 | 44 | public boolean isArea() { 45 | return user.isArea(); 46 | } 47 | 48 | public boolean isDevice(){ 49 | return user.isDevice(); 50 | } 51 | @Override 52 | public Collection getAuthorities() { 53 | Collection authorities = new ArrayList(); 54 | List roles = user.getRoles(); 55 | 56 | if(roles != null){ 57 | for(Role role : roles){ 58 | SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.toString()); 59 | authorities.add(authority); 60 | } 61 | } 62 | return authorities; 63 | } 64 | 65 | @Override 66 | public String getPassword() { 67 | // TODO Auto-generated method stub 68 | return user.getPassword(); 69 | } 70 | 71 | @Override 72 | public String getUsername() { 73 | // TODO Auto-generated method stub 74 | return user.getUsername(); 75 | } 76 | 77 | @Override 78 | public boolean isAccountNonExpired() { 79 | // TODO Auto-generated method stub 80 | return true; 81 | } 82 | 83 | @Override 84 | public boolean isAccountNonLocked() { 85 | // TODO Auto-generated method stub 86 | return true; 87 | } 88 | 89 | @Override 90 | public boolean isCredentialsNonExpired() { 91 | // TODO Auto-generated method stub 92 | return true; 93 | } 94 | 95 | @Override 96 | public boolean isEnabled() { 97 | // TODO Auto-generated method stub 98 | return user.getStatus() == User.Status.enable; 99 | } 100 | 101 | @Override 102 | public int hashCode() { 103 | // TODO Auto-generated method stub 104 | return user.getUsername().hashCode(); 105 | } 106 | 107 | @Override 108 | public boolean equals(Object obj) { 109 | if(obj instanceof CustomUserDetails) { 110 | return user.getUsername().equals(((CustomUserDetails)obj).getUsername()); 111 | } 112 | else 113 | return false; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/DomainController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import static org.springframework.http.HttpHeaders.AUTHORIZATION; 4 | 5 | import java.util.List; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.validation.Valid; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.security.access.prepost.PreAuthorize; 12 | import org.springframework.validation.BindingResult; 13 | import org.springframework.web.bind.annotation.DeleteMapping; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.PatchMapping; 16 | import org.springframework.web.bind.annotation.PathVariable; 17 | import org.springframework.web.bind.annotation.PostMapping; 18 | import org.springframework.web.bind.annotation.RequestBody; 19 | import org.springframework.web.bind.annotation.RequestMapping; 20 | import org.springframework.web.bind.annotation.RestController; 21 | 22 | import top.microiot.domain.Domain; 23 | import top.microiot.domain.Token; 24 | import top.microiot.dto.DomainInfo; 25 | import top.microiot.dto.DomainRenameInfo; 26 | import top.microiot.service.DomainService; 27 | import top.microiot.service.TokenService; 28 | 29 | @RestController 30 | @RequestMapping("/domains") 31 | public class DomainController extends IoTController{ 32 | @Autowired 33 | private DomainService domainService; 34 | @Autowired 35 | private TokenService tokenService; 36 | 37 | @PreAuthorize("hasAuthority('SYSTEM')") 38 | @PostMapping("") 39 | public Domain add(@RequestBody @Valid DomainInfo info, BindingResult result) { 40 | throwError(result); 41 | return domainService.addDomain(info); 42 | } 43 | 44 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 45 | @PatchMapping("/{name}") 46 | public Token chooseDomain(HttpServletRequest request, @PathVariable String name){ 47 | String token = request.getHeader(AUTHORIZATION); 48 | return tokenService.updateToken(name, token); 49 | } 50 | 51 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 52 | @GetMapping("/name/{name}") 53 | public Domain getDomainByName(@PathVariable String name){ 54 | return domainService.getByName(name); 55 | } 56 | 57 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 58 | @GetMapping("/id/{id}") 59 | public Domain getDomainById(@PathVariable String id){ 60 | return domainService.getById(id); 61 | } 62 | 63 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 64 | @GetMapping("") 65 | public Domain getCurrentDomain(){ 66 | return domainService.getCurrentDomain(); 67 | } 68 | 69 | @PreAuthorize("hasAuthority('SYSTEM')") 70 | @PatchMapping("") 71 | public Domain renameDomain(@RequestBody @Valid DomainRenameInfo info, BindingResult result) { 72 | throwError(result); 73 | return domainService.renameDomain(info); 74 | } 75 | 76 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 77 | @GetMapping("/me") 78 | public List getMyDomain(){ 79 | return domainService.getMyDomain(); 80 | } 81 | 82 | @PreAuthorize("hasAuthority('SYSTEM')") 83 | @DeleteMapping("/{id}") 84 | public void deleteDomain(@PathVariable String id) { 85 | domainService.deleteDomain(id); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/EventService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.Map; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | import top.microiot.domain.Device; 12 | import top.microiot.domain.Domain; 13 | import top.microiot.domain.Event; 14 | import top.microiot.domain.attribute.AttValueInfo; 15 | import top.microiot.domain.attribute.DataType; 16 | import top.microiot.domain.attribute.DataValue; 17 | import top.microiot.domain.attribute.DeviceAttributeType; 18 | import top.microiot.dto.EventInfo; 19 | import top.microiot.dto.EventPageInfo; 20 | import top.microiot.dto.SubDeviceEventInfo; 21 | import top.microiot.exception.NotFoundException; 22 | import top.microiot.exception.StatusException; 23 | import top.microiot.exception.ValueException; 24 | import top.microiot.repository.DeviceRepository; 25 | import top.microiot.repository.EventRepository; 26 | 27 | @Service 28 | public class EventService extends IoTService{ 29 | @Autowired 30 | private EventRepository eventRepository; 31 | @Autowired 32 | private DeviceRepository deviceRepository; 33 | @Autowired 34 | private DeviceService deviceService; 35 | 36 | @Transactional 37 | public void report(EventInfo info) { 38 | Device device = getCurrentDevice(); 39 | reportEvent(info, device); 40 | } 41 | 42 | @Transactional 43 | public void report(SubDeviceEventInfo info) { 44 | Device subDevice = deviceRepository.findById(info.getDeviceId()).get(); 45 | if(deviceService.isChild(subDevice.getId())) 46 | reportEvent(info, subDevice); 47 | else 48 | throw new StatusException("device id error"); 49 | } 50 | 51 | private void reportEvent(EventInfo info, Device device) { 52 | Map values = info.getValues(); 53 | 54 | for (String name : values.keySet()) { 55 | AttValueInfo value = values.get(name); 56 | 57 | if (!device.getDeviceType().getAttDefinition().containsKey(name)) 58 | throw new NotFoundException("attribute: " + name); 59 | 60 | DeviceAttributeType p = (DeviceAttributeType) device.getDeviceType().getAttDefinition().get(name); 61 | if(!p.isReport()) 62 | throw new StatusException("attribute: "+ name + "can't be reported"); 63 | DataType dataType = p.getDataType(); 64 | if(!dataType.isValid(value)) 65 | throw new ValueException("attribute: "+ name + " is not valid value"); 66 | 67 | DataValue dataValue = DataValue.getDataValue(value, dataType); 68 | 69 | Event event = new Event(device, name, dataValue, info.getReportTime()); 70 | 71 | eventRepository.save(event); 72 | } 73 | } 74 | 75 | public Event listEvent(String id) { 76 | return eventRepository.findById(id).get(); 77 | } 78 | 79 | public Page listEvents(EventPageInfo info) { 80 | Pageable pageable = getPageable(info); 81 | Domain domain = getCurrentDomain(); 82 | 83 | return eventRepository.queryEvent(domain.getId(), info.getDeviceId(), info.getAttribute(), info.getReportFrom(), info.getReportTo(), info.getReceiveFrom(), info.getReceiveTo(), pageable); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/FavoriteService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.dao.DuplicateKeyException; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | import top.microiot.domain.Domain; 11 | import top.microiot.domain.Favorite; 12 | import top.microiot.domain.ManagedObject; 13 | import top.microiot.domain.User; 14 | import top.microiot.dto.FavoriteExistInfo; 15 | import top.microiot.dto.FavoriteInfo; 16 | import top.microiot.dto.FavoritePageInfo; 17 | import top.microiot.dto.FavoriteUpdateInfo; 18 | import top.microiot.exception.ConflictException; 19 | import top.microiot.exception.NotFoundException; 20 | import top.microiot.repository.FavoriteRepository; 21 | 22 | @Service 23 | public class FavoriteService extends IoTService{ 24 | @Autowired 25 | private FavoriteRepository favoriteRepository; 26 | @Autowired 27 | private MOService moService; 28 | 29 | @Transactional 30 | public Favorite add(FavoriteInfo info) { 31 | User user = getCurrentUser(); 32 | Domain domain = getCurrentDomain(); 33 | 34 | ManagedObject mo = moService.getLocation(info.getId()); 35 | if(!mo.getDomain().equals(domain)) 36 | throw new NotFoundException(info.getId()); 37 | 38 | Favorite favorite = new Favorite(info.getName(), mo, user, domain); 39 | try{ 40 | return favoriteRepository.save(favorite); 41 | }catch (DuplicateKeyException e) { 42 | throw new ConflictException("favorite name"); 43 | } 44 | } 45 | 46 | @Transactional 47 | public Favorite update(FavoriteUpdateInfo info) { 48 | Favorite favorite = favoriteRepository.findById(info.getId()).get(); 49 | User user = getCurrentUser(); 50 | 51 | if(favorite.getUser().getId().equals(user.getId())) 52 | favorite.setName(info.getNewName()); 53 | else 54 | throw new NotFoundException("favorite"); 55 | 56 | try{ 57 | return favoriteRepository.save(favorite); 58 | }catch (DuplicateKeyException e) { 59 | throw new ConflictException("favorite name"); 60 | } 61 | } 62 | 63 | @Transactional 64 | public void delete(String favoriteId) { 65 | Favorite favorite = favoriteRepository.findById(favoriteId).get(); 66 | User user = getCurrentUser(); 67 | 68 | if(favorite.getUser().getId().equals(user.getId())) 69 | favoriteRepository.delete(favorite); 70 | else 71 | throw new NotFoundException("favorite"); 72 | } 73 | 74 | public Favorite listFavorite(String favoriteId) { 75 | return favoriteRepository.findById(favoriteId).get(); 76 | } 77 | 78 | public Page listAll(FavoritePageInfo info) { 79 | User user = getCurrentUser(); 80 | Pageable pageable = getPageable(info); 81 | Domain domain = getCurrentDomain(); 82 | 83 | Page fs = favoriteRepository.queryFavorite(user.getId(), info.getName(), info.getType(), domain.getId(), pageable); 84 | return fs; 85 | } 86 | 87 | public Favorite get(FavoriteExistInfo info) { 88 | User user = getCurrentUser(); 89 | 90 | return favoriteRepository.getFavorite(user.getId(), info.getFavoriteId()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/AlarmService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.domain.Page; 5 | import org.springframework.data.domain.Pageable; 6 | import org.springframework.messaging.simp.SimpMessagingTemplate; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | import top.microiot.domain.Alarm; 11 | import top.microiot.domain.Device; 12 | import top.microiot.domain.Domain; 13 | import top.microiot.domain.Topic; 14 | import top.microiot.domain.attribute.AttributeType; 15 | import top.microiot.domain.attribute.DataValue; 16 | import top.microiot.dto.AlarmInfo; 17 | import top.microiot.dto.AlarmPageInfo; 18 | import top.microiot.dto.SubDeviceAlarmInfo; 19 | import top.microiot.exception.NotFoundException; 20 | import top.microiot.exception.StatusException; 21 | import top.microiot.repository.AlarmRepository; 22 | import top.microiot.repository.DeviceRepository; 23 | 24 | @Service 25 | public class AlarmService extends IoTService { 26 | @Autowired 27 | private AlarmRepository alarmRepository; 28 | @Autowired 29 | private DeviceRepository deviceRepository; 30 | @Autowired 31 | private DeviceService deviceService; 32 | @Autowired 33 | private SimpMessagingTemplate template; 34 | 35 | @Transactional 36 | public Alarm report(AlarmInfo info) { 37 | Device device = getCurrentDevice(); 38 | 39 | return reportAlarm(info, device); 40 | } 41 | 42 | @Transactional 43 | public Alarm report(SubDeviceAlarmInfo info) { 44 | Device subDevice = deviceRepository.findById(info.getDeviceId()).get(); 45 | if(deviceService.isChild(subDevice.getId())) 46 | return reportAlarm(info, subDevice); 47 | else 48 | throw new StatusException("device id error"); 49 | } 50 | 51 | private Alarm reportAlarm(AlarmInfo info, Device device) { 52 | if(device.getDeviceType().getAlarmTypes() == null || !device.getDeviceType().getAlarmTypes().containsKey(info.getAlarmType())) 53 | throw new NotFoundException("alarm type: " + info.getAlarmType() + " in this device: " + device.getName()); 54 | 55 | AttributeType alarmType = device.getDeviceType().getAlarmTypes().get(info.getAlarmType()); 56 | DataValue value = DataValue.getDataValue(info.getAlarmInfo(), alarmType.getDataType()); 57 | Alarm alarm = new Alarm(device, info.getAlarmType(), value, info.getReportTime()); 58 | 59 | alarm = alarmRepository.save(alarm); 60 | 61 | String destination = Topic.TOPIC_ALARM + device.getId(); 62 | template.convertAndSend(destination, alarm); 63 | return alarm; 64 | } 65 | 66 | public Alarm listAlarm(String id) { 67 | return alarmRepository.findById(id).get(); 68 | } 69 | 70 | public Page listAll() { 71 | Pageable pageable = getPageable(null); 72 | 73 | return alarmRepository.findAll(pageable); 74 | } 75 | 76 | public Page listAlarms(AlarmPageInfo info) { 77 | Pageable pageable = getPageable(info); 78 | Domain domain = getCurrentDomain(); 79 | 80 | return alarmRepository.queryAlarm(domain.getId(), info.getNotifyObjectId(), info.getAlarmType(), info.getReportFrom(), info.getReportTo(), info.getReceiveFrom(), info.getReceiveTo(), pageable); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import javax.validation.Valid; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.security.access.prepost.PreAuthorize; 8 | import org.springframework.validation.BindingResult; 9 | import org.springframework.web.bind.annotation.DeleteMapping; 10 | import org.springframework.web.bind.annotation.GetMapping; 11 | import org.springframework.web.bind.annotation.PatchMapping; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | import org.springframework.web.bind.annotation.PostMapping; 14 | import org.springframework.web.bind.annotation.RequestBody; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import top.microiot.domain.Role; 19 | import top.microiot.domain.User; 20 | import top.microiot.dto.PageInfo; 21 | import top.microiot.dto.PasswordUpdateInfo; 22 | import top.microiot.dto.RegisterInfo; 23 | import top.microiot.dto.UserInfo; 24 | import top.microiot.dto.UserUpdateInfo; 25 | import top.microiot.exception.ValueException; 26 | import top.microiot.service.UserService; 27 | 28 | @RestController 29 | @RequestMapping("/users") 30 | public class UserController extends IoTController{ 31 | @Autowired 32 | private UserService userService; 33 | 34 | @PreAuthorize("hasAuthority('SYSTEM')") 35 | @PostMapping("") 36 | public User add(@RequestBody @Valid UserInfo info, BindingResult result) { 37 | throwError(result); 38 | if(info.getRole() == Role.AREA) 39 | return userService.addUser(info.getUsername(), info.getPassword(), info.getEmail(), info.getArea()); 40 | else if(info.getRole() == Role.SYSTEM) 41 | return userService.addAdmin(info.getUsername(), info.getPassword(), info.getEmail()); 42 | throw new ValueException("error role"); 43 | } 44 | 45 | @PostMapping("/register") 46 | public User register(@RequestBody @Valid RegisterInfo info, BindingResult result) { 47 | throwError(result); 48 | return userService.register(info); 49 | } 50 | 51 | @PreAuthorize("hasAuthority('SYSTEM')") 52 | @PatchMapping("") 53 | public User update(@RequestBody @Valid UserUpdateInfo info, BindingResult result) { 54 | throwError(result); 55 | return userService.updateUser(info); 56 | } 57 | 58 | @PreAuthorize("hasAuthority('SYSTEM')") 59 | @DeleteMapping("/{id}") 60 | public void delete(@PathVariable String id) { 61 | userService.delete(id); 62 | } 63 | 64 | @PreAuthorize("hasAuthority('SYSTEM')") 65 | @GetMapping("/{username}") 66 | public User getUser(@PathVariable String username){ 67 | return userService.listUserByUsername(username); 68 | } 69 | 70 | @PreAuthorize("hasAuthority('SYSTEM')") 71 | @RequestMapping("") 72 | public Page getUsers(@Valid PageInfo info, BindingResult result){ 73 | throwError(result); 74 | return userService.listAll(info); 75 | } 76 | 77 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 78 | @GetMapping("/me") 79 | public User getUser(){ 80 | return userService.listCurrentUser(); 81 | } 82 | 83 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 84 | @PatchMapping("/password") 85 | public User updatePassword(@RequestBody @Valid PasswordUpdateInfo info, BindingResult result) { 86 | throwError(result); 87 | return userService.updatePassword(info.getPassword(), info.getOriginal()); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/MOService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.stereotype.Service; 9 | 10 | import top.microiot.domain.Device; 11 | import top.microiot.domain.Domain; 12 | import top.microiot.domain.ManagedObject; 13 | import top.microiot.domain.Site; 14 | import top.microiot.domain.User; 15 | import top.microiot.exception.NotFoundException; 16 | import top.microiot.exception.StatusException; 17 | import top.microiot.repository.DeviceRepository; 18 | import top.microiot.repository.DomainRepository; 19 | import top.microiot.repository.SiteRepository; 20 | import top.microiot.repository.UserRepository; 21 | 22 | @Service 23 | public class MOService extends IoTService{ 24 | @Autowired 25 | private SiteRepository siteRepository; 26 | @Autowired 27 | private DomainRepository domainRepository; 28 | @Autowired 29 | private DeviceRepository deviceRepository; 30 | @Autowired 31 | private UserRepository userRepository; 32 | 33 | public ManagedObject getLocation(String locationId) { 34 | Optional location1 = domainRepository.findById(locationId); 35 | Optional location2; 36 | Optional location3; 37 | if(!location1.isPresent()) { 38 | location2 = siteRepository.findById(locationId); 39 | if(!location2.isPresent()) { 40 | location3 = deviceRepository.findById(locationId); 41 | if(!location3.isPresent()) 42 | throw new NotFoundException("location id:" + locationId); 43 | else 44 | return location3.get(); 45 | } 46 | else 47 | return location2.get(); 48 | } 49 | else 50 | return location1.get(); 51 | } 52 | 53 | public ManagedObject getLocation1(String locationId) { 54 | Optional location1 = domainRepository.findById(locationId); 55 | Optional location2; 56 | if(!location1.isPresent()) { 57 | location2 = siteRepository.findById(locationId); 58 | if(!location2.isPresent()) 59 | throw new NotFoundException("location id:" + locationId); 60 | else 61 | return location2.get(); 62 | } 63 | else 64 | return location1.get(); 65 | } 66 | 67 | public boolean isMyMO(String moId) { 68 | ManagedObject mo = getLocation(moId); 69 | return isMyMO(mo); 70 | } 71 | 72 | public boolean isMyMO(ManagedObject mo) { 73 | User user = getCurrentUser(); 74 | 75 | if(user.isArea() && mo != null) { 76 | for(ManagedObject area: user.getArea()) { 77 | if(area.contain(mo)) 78 | return true; 79 | } 80 | return false; 81 | } 82 | else if(user.isArea() && mo == null) 83 | return false; 84 | else 85 | return true; 86 | } 87 | 88 | public void hasMOAccess(ManagedObject object) { 89 | List users = userRepository.findAll(); 90 | 91 | for(User user: users) { 92 | if(user.isArea()) { 93 | List areas = user.getArea(); 94 | for(ManagedObject mo: areas) { 95 | if(mo.equals(object)) 96 | throw new StatusException(user.getUsername() + " has this access, " + mo.getString() + " can't be deleted"); 97 | } 98 | } 99 | } 100 | } 101 | 102 | public Domain hasDomainAccess() { 103 | Domain domain = getCurrentDomain(); 104 | if(!isMyMO(domain)) 105 | throw new AccessDeniedException("domain"); 106 | return domain; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/SiteController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import java.util.List; 4 | 5 | import javax.validation.Valid; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.security.access.prepost.PreAuthorize; 10 | import org.springframework.validation.BindingResult; 11 | import org.springframework.web.bind.annotation.DeleteMapping; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.PatchMapping; 14 | import org.springframework.web.bind.annotation.PathVariable; 15 | import org.springframework.web.bind.annotation.PostMapping; 16 | import org.springframework.web.bind.annotation.RequestBody; 17 | import org.springframework.web.bind.annotation.RequestMapping; 18 | import org.springframework.web.bind.annotation.RestController; 19 | 20 | import top.microiot.domain.Site; 21 | import top.microiot.domain.attribute.AttValueInfo; 22 | import top.microiot.dto.SiteInfo; 23 | import top.microiot.dto.SitePageInfo; 24 | import top.microiot.dto.SiteRenameInfo; 25 | import top.microiot.dto.SiteUpdateInfo; 26 | import top.microiot.service.MOService; 27 | import top.microiot.service.SiteService; 28 | 29 | @RestController 30 | @RequestMapping("/sites") 31 | public class SiteController extends IoTController{ 32 | @Autowired 33 | private SiteService siteService; 34 | @Autowired 35 | private MOService moService; 36 | 37 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 38 | @PostMapping("") 39 | public Site add(@RequestBody @Valid SiteInfo info, BindingResult result) { 40 | throwError(result); 41 | return siteService.add(info); 42 | } 43 | 44 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 45 | @GetMapping("/{id}") 46 | public Site getSite(@PathVariable String id){ 47 | return siteService.listSite(id); 48 | } 49 | 50 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 51 | @DeleteMapping("/{id}") 52 | public void deleteSite(@PathVariable String id){ 53 | siteService.delete(id); 54 | } 55 | 56 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 57 | @GetMapping("") 58 | public Page getSites(@Valid SitePageInfo info, BindingResult result){ 59 | throwError(result); 60 | return siteService.listSite(info); 61 | } 62 | 63 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 64 | @GetMapping("/count") 65 | public long getCount(@Valid SitePageInfo info, BindingResult result) { 66 | throwError(result); 67 | return siteService.countSite(info); 68 | } 69 | 70 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 71 | @PatchMapping("/name") 72 | public Site renameSite(@RequestBody @Valid SiteRenameInfo info, BindingResult result) { 73 | throwError(result); 74 | return siteService.rename(info); 75 | } 76 | 77 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 78 | @PatchMapping("") 79 | public Site updateSite(@RequestBody @Valid SiteUpdateInfo info, BindingResult result) { 80 | throwError(result); 81 | return siteService.update(info); 82 | } 83 | 84 | @PreAuthorize("hasAuthority('AREA')") 85 | @GetMapping("/me") 86 | public List getMySites(){ 87 | return siteService.getMySites(); 88 | } 89 | 90 | @PreAuthorize("hasAuthority('AREA')") 91 | @GetMapping("/me/{siteId}") 92 | public boolean isMySite(@PathVariable String siteId){ 93 | return moService.isMyMO(siteId); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/ConfigService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.security.access.AccessDeniedException; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | import top.microiot.domain.Configuration; 14 | import top.microiot.domain.Device; 15 | import top.microiot.domain.Domain; 16 | import top.microiot.domain.ManagedObject; 17 | import top.microiot.domain.Site; 18 | import top.microiot.domain.User; 19 | import top.microiot.exception.NotFoundException; 20 | import top.microiot.repository.ConfigRepository; 21 | import top.microiot.repository.DeviceRepository; 22 | import top.microiot.repository.SiteRepository; 23 | 24 | @Service 25 | public class ConfigService extends IoTService { 26 | @Autowired 27 | private DeviceRepository deviceRepository; 28 | @Autowired 29 | private SiteRepository siteRepository; 30 | @Autowired 31 | private ConfigRepository configRepository; 32 | @Autowired 33 | private MOService moService; 34 | 35 | public List queryConfiguration(Boolean top, Boolean silent, Boolean subscribe){ 36 | User user = getCurrentUser(); 37 | Domain domain = getCurrentDomain(); 38 | 39 | return configRepository.queryConfiguration(domain.getId(), user.getId(), top, silent, subscribe); 40 | } 41 | 42 | public Page listAll() { 43 | Pageable pageable = getPageable(null); 44 | User user = getCurrentUser(); 45 | 46 | return configRepository.findByUserId(user.getId(), pageable); 47 | } 48 | 49 | public Configuration listOne(String objectId) { 50 | User u = getCurrentUser(); 51 | 52 | return configRepository.findByUserAndNotifyObject(u.getId(), objectId); 53 | } 54 | 55 | private Configuration getConfiguration(String objectId) { 56 | ManagedObject notifyObject = null; 57 | Optional device = deviceRepository.findById(objectId); 58 | if(device.isPresent()){ 59 | if(!moService.isMyMO(device.get())) 60 | throw new AccessDeniedException("device"); 61 | notifyObject = device.get(); 62 | }else { 63 | Optional site = siteRepository.findById(objectId); 64 | if(site.isPresent()) { 65 | if(!moService.isMyMO((Site)site.get())) 66 | throw new AccessDeniedException("site"); 67 | notifyObject = site.get(); 68 | } 69 | else 70 | throw new NotFoundException("object"); 71 | } 72 | User u = getCurrentUser(); 73 | 74 | Configuration configuration = configRepository.findByUserAndNotifyObject(u.getId(), objectId); 75 | if(configuration == null){ 76 | configuration = new Configuration(u, notifyObject); 77 | } 78 | return configuration; 79 | } 80 | 81 | @Transactional 82 | public Configuration configSilent(String objectId, boolean value) { 83 | Configuration configuration = getConfiguration(objectId); 84 | 85 | configuration.setSilent(value); 86 | 87 | return configRepository.save(configuration); 88 | } 89 | 90 | @Transactional 91 | public Configuration configTop(String objectId, boolean value) { 92 | Configuration configuration = getConfiguration(objectId); 93 | 94 | configuration.setTop(value); 95 | 96 | return configRepository.save(configuration); 97 | } 98 | 99 | @Transactional 100 | public Configuration configSubscribe(String objectId, boolean value) { 101 | Configuration configuration = getConfiguration(objectId); 102 | 103 | configuration.setSubscribe(value); 104 | 105 | return configRepository.save(configuration); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | top.microiot 8 | iotplatform 9 | 1.3.0 10 | jar 11 | 12 | IoTPlatform 13 | MicroIoT Platform project 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 2.1.11.RELEASE 19 | 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | microiot 26 | 1.8 27 | 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-security 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-data-mongodb 41 | 42 | 43 | org.springframework.security 44 | spring-security-messaging 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-websocket 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-reactor-netty 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-actuator 57 | 58 | 59 | io.jsonwebtoken 60 | jjwt 61 | 0.9.1 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-configuration-processor 66 | true 67 | 68 | 69 | top.microiot 70 | iotdomain 71 | 2.3.0 72 | 73 | 74 | 75 | org.springframework.boot 76 | spring-boot-starter-test 77 | test 78 | 79 | 80 | 81 | 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-maven-plugin 86 | 87 | 88 | com.spotify 89 | dockerfile-maven-plugin 90 | 1.4.9 91 | 92 | ${docker.image.prefix}/${project.artifactId} 93 | ${project.version} 94 | 95 | target/${project.build.finalName}.jar 96 | 97 | 98 | 99 | 100 | default 101 | install 102 | 103 | build 104 | push 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/IotPlatformApplication.java: -------------------------------------------------------------------------------- 1 | package top.microiot; 2 | 3 | import java.io.PrintStream; 4 | 5 | import org.springframework.boot.Banner; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.core.env.Environment; 9 | 10 | @SpringBootApplication 11 | public class IotPlatformApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication app = new SpringApplication(IotPlatformApplication.class); 15 | app.setBanner(new Banner() { 16 | 17 | @Override 18 | public void printBanner(Environment environment, Class sourceClass, PrintStream out) { 19 | out.print( 20 | "\n" + 21 | " \n" + 22 | " \n" + 23 | "MMMMMMMM MMMMMMMM iiii IIIIIIIIII TTTTTTTTTTTTTTTTTTTTTTT\n" + 24 | "M:::::::M M:::::::M i::::i I::::::::I T:::::::::::::::::::::T\n" + 25 | "M::::::::M M::::::::M iiii I::::::::I T:::::::::::::::::::::T\n" + 26 | "M:::::::::M M:::::::::M II::::::II T:::::TT:::::::TT:::::T\n" + 27 | "M::::::::::M M::::::::::Miiiiiii ccccccccccccccccrrrrr rrrrrrrrr ooooooooooo I::::I oooooooooooTTTTTT T:::::T TTTTTT\n" + 28 | "M:::::::::::M M:::::::::::Mi:::::i cc:::::::::::::::cr::::rrr:::::::::r oo:::::::::::oo I::::I oo:::::::::::oo T:::::T \n" + 29 | "M:::::::M::::M M::::M:::::::M i::::i c:::::::::::::::::cr:::::::::::::::::r o:::::::::::::::o I::::I o:::::::::::::::o T:::::T \n" + 30 | "M::::::M M::::M M::::M M::::::M i::::i c:::::::cccccc:::::crr::::::rrrrr::::::ro:::::ooooo:::::o I::::I o:::::ooooo:::::o T:::::T \n" + 31 | "M::::::M M::::M::::M M::::::M i::::i c::::::c ccccccc r:::::r r:::::ro::::o o::::o I::::I o::::o o::::o T:::::T \n" + 32 | "M::::::M M:::::::M M::::::M i::::i c:::::c r:::::r rrrrrrro::::o o::::o I::::I o::::o o::::o T:::::T \n" + 33 | "M::::::M M:::::M M::::::M i::::i c:::::c r:::::r o::::o o::::o I::::I o::::o o::::o T:::::T \n" + 34 | "M::::::M MMMMM M::::::M i::::i c::::::c ccccccc r:::::r o::::o o::::o I::::I o::::o o::::o T:::::T \n" + 35 | "M::::::M M::::::Mi::::::ic:::::::cccccc:::::c r:::::r o:::::ooooo:::::oII::::::IIo:::::ooooo:::::o TT:::::::TT \n" + 36 | "M::::::M M::::::Mi::::::i c:::::::::::::::::c r:::::r o:::::::::::::::oI::::::::Io:::::::::::::::o T:::::::::T \n" + 37 | "M::::::M M::::::Mi::::::i cc:::::::::::::::c r:::::r oo:::::::::::oo I::::::::I oo:::::::::::oo T:::::::::T \n" + 38 | "MMMMMMMM MMMMMMMMiiiiiiii cccccccccccccccc rrrrrrr ooooooooooo IIIIIIIIII ooooooooooo TTTTTTTTTTT \n" + 39 | " \n" + 40 | " \n" 41 | ); 42 | } 43 | 44 | }); 45 | app.run(args); 46 | } 47 | } -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/authentication/TokenFactory.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security.authentication; 2 | 3 | import java.util.Calendar; 4 | import java.util.Date; 5 | import java.util.UUID; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.authentication.BadCredentialsException; 9 | import org.springframework.stereotype.Component; 10 | 11 | import io.jsonwebtoken.Claims; 12 | import io.jsonwebtoken.ExpiredJwtException; 13 | import io.jsonwebtoken.Jws; 14 | import io.jsonwebtoken.Jwts; 15 | import io.jsonwebtoken.MalformedJwtException; 16 | import io.jsonwebtoken.SignatureAlgorithm; 17 | import io.jsonwebtoken.SignatureException; 18 | import io.jsonwebtoken.UnsupportedJwtException; 19 | import top.microiot.domain.Token; 20 | import top.microiot.exception.AuthenticationException; 21 | 22 | @Component 23 | public class TokenFactory { 24 | private static final String SCOPES = "scopes"; 25 | private final TokenSettings settings; 26 | 27 | @Autowired 28 | public TokenFactory(TokenSettings settings) { 29 | this.settings = settings; 30 | } 31 | 32 | public Token createToken(String username, String domain) { 33 | return new Token(token(username, domain), refreshToken(username, domain)); 34 | } 35 | 36 | private String token(String username, String domain) { 37 | Claims claims = Jwts.claims().setSubject(username); 38 | if(domain != null) 39 | claims.put(SCOPES, domain); 40 | 41 | Date currentTime = new Date(); 42 | Calendar cal = Calendar.getInstance(); 43 | cal.setTime(currentTime); 44 | cal.add(Calendar.HOUR_OF_DAY, settings.getExpirationTime()); 45 | 46 | String token = Jwts.builder() 47 | .setClaims(claims) 48 | .setIssuer(settings.getIssuer()) 49 | .setIssuedAt(currentTime) 50 | .setExpiration(cal.getTime()) 51 | .signWith(SignatureAlgorithm.HS512, settings.getSigningKey()) 52 | .compact(); 53 | 54 | return token; 55 | } 56 | 57 | private String refreshToken(String username, String domain) { 58 | Claims claims = Jwts.claims().setSubject(username); 59 | if(domain != null) 60 | claims.put(SCOPES, domain); 61 | 62 | Date currentTime = new Date(); 63 | Calendar cal = Calendar.getInstance(); 64 | cal.setTime(currentTime); 65 | cal.add(Calendar.HOUR_OF_DAY, settings.getRefreshExpTime()); 66 | 67 | String token = Jwts.builder() 68 | .setClaims(claims) 69 | .setIssuer(settings.getIssuer()) 70 | .setId(UUID.randomUUID().toString()) 71 | .setIssuedAt(currentTime) 72 | .setExpiration(cal.getTime()) 73 | .signWith(SignatureAlgorithm.HS512, settings.getSigningKey()) 74 | .compact(); 75 | 76 | return token; 77 | } 78 | 79 | public Jws parseClaims(String token) { 80 | try { 81 | return Jwts.parser().setSigningKey(settings.getSigningKey()).parseClaimsJws(token); 82 | } catch (UnsupportedJwtException | MalformedJwtException | IllegalArgumentException | SignatureException ex) { 83 | throw new BadCredentialsException("Invalid JWT token: " + ex.getMessage()); 84 | } catch (ExpiredJwtException expiredEx) { 85 | throw new AuthenticationException(AuthenticationException.TOKEN_EXPIRED); 86 | } 87 | } 88 | 89 | public String getScope(Jws claims) { 90 | return claims.getBody().get(SCOPES, String.class); 91 | } 92 | 93 | public String getUsername(Jws claims) { 94 | return claims.getBody().getSubject(); 95 | } 96 | 97 | public Date getExpire(String token) { 98 | return parseClaims(token).getBody().getExpiration(); 99 | } 100 | 101 | public String getJti(String token) { 102 | Jws jwsClaims = parseClaims(token); 103 | return jwsClaims.getBody().getId(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/DeviceGroupController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import java.util.List; 4 | 5 | import javax.validation.Valid; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.security.access.prepost.PreAuthorize; 10 | import org.springframework.security.core.Authentication; 11 | import org.springframework.security.core.context.SecurityContextHolder; 12 | import org.springframework.validation.BindingResult; 13 | import org.springframework.web.bind.annotation.DeleteMapping; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.PatchMapping; 16 | import org.springframework.web.bind.annotation.PathVariable; 17 | import org.springframework.web.bind.annotation.PostMapping; 18 | import org.springframework.web.bind.annotation.RequestBody; 19 | import org.springframework.web.bind.annotation.RequestMapping; 20 | import org.springframework.web.bind.annotation.RestController; 21 | 22 | import top.microiot.domain.DeviceGroup; 23 | import top.microiot.dto.DeviceGroupInfo; 24 | import top.microiot.dto.DeviceGroupRenameInfo; 25 | import top.microiot.dto.PageInfo; 26 | import top.microiot.security.CustomUserDetails; 27 | import top.microiot.service.DeviceGroupService; 28 | 29 | @RestController 30 | @RequestMapping("/devicegroups") 31 | public class DeviceGroupController extends IoTController{ 32 | @Autowired 33 | private DeviceGroupService deviceGroupService; 34 | 35 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 36 | @PostMapping("") 37 | public DeviceGroup addDeviceGroup(@RequestBody @Valid DeviceGroupInfo info, BindingResult result) { 38 | throwError(result); 39 | return deviceGroupService.addDeviceGroup(info); 40 | } 41 | 42 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA') or hasAuthority('DEVICE')") 43 | @GetMapping("/{id}") 44 | public DeviceGroup getDeviceGroup(@PathVariable String id) { 45 | Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 46 | CustomUserDetails user = (CustomUserDetails) auth.getPrincipal(); 47 | 48 | if(!user.isDevice()) 49 | return deviceGroupService.listDeviceGroup(id); 50 | else 51 | return deviceGroupService.listDeviceGroupByDevice(id); 52 | } 53 | 54 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 55 | @GetMapping("/page") 56 | public Page getDeviceGroups( @Valid PageInfo info, BindingResult result){ 57 | throwError(result); 58 | return deviceGroupService.listDeviceGroups(info); 59 | } 60 | 61 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 62 | @GetMapping("/list") 63 | public List getDeviceGroupsList(){ 64 | return deviceGroupService.listDeviceGroups(); 65 | } 66 | 67 | @PreAuthorize("hasAuthority('DEVICE')") 68 | @GetMapping("/me") 69 | public List getMyDeviceGroups(){ 70 | return deviceGroupService.listMyDeviceGroups(); 71 | } 72 | 73 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 74 | @PatchMapping("/name") 75 | public DeviceGroup updateDeviceGroup(@RequestBody @Valid DeviceGroupRenameInfo info, BindingResult result) { 76 | throwError(result); 77 | return deviceGroupService.rename(info); 78 | } 79 | 80 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 81 | @DeleteMapping("/{id}") 82 | public void deleteDeviceGroup(@PathVariable String id){ 83 | deviceGroupService.delete(id); 84 | } 85 | 86 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 87 | @PostMapping("/group/{groupId}/device/{deviceId}") 88 | public DeviceGroup addGroup(@PathVariable String groupId, @PathVariable String deviceId) { 89 | return deviceGroupService.addGroup(groupId, deviceId); 90 | } 91 | 92 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 93 | @DeleteMapping("/group/{groupId}/device/{deviceId}") 94 | public DeviceGroup removeGroup(@PathVariable String groupId, @PathVariable String deviceId) { 95 | return deviceGroupService.removeGroup(groupId, deviceId); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/SiteTypeService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.dao.DuplicateKeyException; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.data.domain.Pageable; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | import top.microiot.domain.Domain; 14 | import top.microiot.domain.SiteType; 15 | import top.microiot.domain.SiteTypeFile; 16 | import top.microiot.domain.attribute.AttTypeInfo; 17 | import top.microiot.domain.attribute.AttributeType; 18 | import top.microiot.domain.attribute.AttributeTypes; 19 | import top.microiot.dto.PageInfo; 20 | import top.microiot.dto.SiteTypeRenameInfo; 21 | import top.microiot.exception.ConflictException; 22 | import top.microiot.exception.NotFoundException; 23 | import top.microiot.exception.StatusException; 24 | import top.microiot.repository.SiteRepository; 25 | import top.microiot.repository.SiteTypeRepository; 26 | 27 | @Service 28 | public class SiteTypeService extends IoTService{ 29 | @Autowired 30 | private SiteTypeRepository siteTypeRepository; 31 | @Autowired 32 | private SiteRepository siteRepository; 33 | @Autowired 34 | private MOService moService; 35 | 36 | @Transactional 37 | public SiteType add(AttTypeInfo info ){ 38 | Domain domain = moService.hasDomainAccess(); 39 | AttributeTypes attributes = new AttributeTypes(info.getAdditional()); 40 | Map attTypes = attributes.getAttTypes(); 41 | 42 | SiteType siteType = new SiteType(info.getName(), info.getDescription(), domain, attTypes); 43 | try{ 44 | siteType = siteTypeRepository.save(siteType); 45 | } catch (DuplicateKeyException e) { 46 | throw new ConflictException("site type name"); 47 | } 48 | 49 | //deviceTypeService.createAttributeIndexs(siteType.getAttDefinition(), false); 50 | 51 | return siteType; 52 | } 53 | 54 | @Transactional 55 | public SiteType add(SiteTypeFile info ){ 56 | Domain domain = moService.hasDomainAccess(); 57 | 58 | Map attTypes = info.getAttDefinition(); 59 | 60 | SiteType siteType = new SiteType(info.getName(), info.getDescription(), domain, attTypes); 61 | try{ 62 | siteType = siteTypeRepository.save(siteType); 63 | } catch (DuplicateKeyException e) { 64 | throw new ConflictException("site type name"); 65 | } 66 | 67 | //deviceTypeService.createAttributeIndexs(siteType.getAttDefinition(), false); 68 | 69 | return siteType; 70 | } 71 | 72 | @Transactional 73 | public SiteType rename(SiteTypeRenameInfo info){ 74 | moService.hasDomainAccess(); 75 | 76 | SiteType type = siteTypeRepository.findById(info.getId()).get(); 77 | type.setName(info.getName()); 78 | 79 | try{ 80 | return siteTypeRepository.save(type); 81 | } catch (DuplicateKeyException e) { 82 | throw new ConflictException("site type name"); 83 | } 84 | } 85 | 86 | public SiteType listSiteType(String id){ 87 | SiteType type = siteTypeRepository.findById(id).get(); 88 | return type; 89 | } 90 | 91 | public Page listSiteType(PageInfo info){ 92 | Pageable pageable = getPageable(info); 93 | Domain domain = getCurrentDomain(); 94 | 95 | return siteTypeRepository.findByDomain(domain.getId(), pageable); 96 | } 97 | 98 | public List listSiteTypes(){ 99 | Domain domain = getCurrentDomain(); 100 | 101 | return siteTypeRepository.findByDomainId(domain.getId()); 102 | } 103 | 104 | @Transactional 105 | public void delete(String id) { 106 | moService.hasDomainAccess(); 107 | 108 | SiteType type = siteTypeRepository.findById(id).get(); 109 | if(type == null) 110 | throw new NotFoundException("site type"); 111 | int n = siteRepository.countBySiteType(id); 112 | 113 | if(n > 0){ 114 | throw new StatusException("site type used"); 115 | } 116 | else { 117 | siteTypeRepository.deleteById(id); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/security/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package top.microiot.security; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 13 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 14 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 15 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 16 | import org.springframework.security.config.http.SessionCreationPolicy; 17 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 18 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 19 | import org.springframework.web.cors.CorsConfiguration; 20 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 21 | import org.springframework.web.filter.CorsFilter; 22 | 23 | import top.microiot.security.authentication.SkipPathRequestMatcher; 24 | import top.microiot.security.authentication.TokenAuthenticationProcessingFilter; 25 | import top.microiot.security.authentication.TokenAuthenticationProvider; 26 | import top.microiot.service.TokenService; 27 | 28 | @Configuration 29 | @EnableWebSecurity 30 | @EnableGlobalMethodSecurity(prePostEnabled = true) 31 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 32 | @Autowired 33 | private TokenService tokenService; 34 | @Autowired 35 | private AuthenticationManager authenticationManager; 36 | @Autowired 37 | private AuthenticationFailureHandler failureHandler; 38 | @Autowired 39 | private TokenAuthenticationProvider tokenAuthenticationProvider; 40 | 41 | @Value("${microiot.websocket.endpoint}") 42 | private String ws; 43 | 44 | @Override 45 | protected void configure(HttpSecurity http) throws Exception { 46 | 47 | http 48 | .formLogin().disable() 49 | .logout().disable() 50 | .csrf().disable() 51 | .cors() 52 | .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 53 | .and().exceptionHandling() 54 | .and().authorizeRequests() 55 | .antMatchers(permitAll()).permitAll() 56 | .requestMatchers(EndpointRequest.toAnyEndpoint()).hasAuthority("SYSTEM") 57 | .anyRequest().authenticated() 58 | .and().authenticationProvider(tokenAuthenticationProvider).addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); 59 | } 60 | 61 | private String[] permitAll() { 62 | return new String[] { "/", "/"+ws, "/login", "/token", "/users/register", "/error" }; 63 | } 64 | 65 | @Bean 66 | public CorsFilter corsFilter() { 67 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 68 | CorsConfiguration config = new CorsConfiguration(); 69 | config.setAllowCredentials(true); 70 | config.addAllowedOrigin("*"); 71 | config.addAllowedHeader("*"); 72 | config.addAllowedMethod("OPTIONS"); 73 | config.addAllowedMethod("HEAD"); 74 | config.addAllowedMethod("GET"); 75 | config.addAllowedMethod("PUT"); 76 | config.addAllowedMethod("POST"); 77 | config.addAllowedMethod("DELETE"); 78 | config.addAllowedMethod("PATCH"); 79 | source.registerCorsConfiguration("/**", config); 80 | return new CorsFilter(source); 81 | } 82 | @Bean 83 | @Override 84 | public AuthenticationManager authenticationManagerBean() throws Exception { 85 | return super.authenticationManagerBean(); 86 | } 87 | 88 | private TokenAuthenticationProcessingFilter tokenAuthenticationFilter() { 89 | List permitAllList = Arrays.asList(permitAll()); 90 | SkipPathRequestMatcher matcher = new SkipPathRequestMatcher(permitAllList, "/**"); 91 | TokenAuthenticationProcessingFilter filter = new TokenAuthenticationProcessingFilter(tokenService, failureHandler, matcher); 92 | filter.setAuthenticationManager(authenticationManager); 93 | return filter; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/web/MyStompHeaderAccessor.java: -------------------------------------------------------------------------------- 1 | package top.microiot.web; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import org.springframework.lang.Nullable; 7 | import org.springframework.messaging.Message; 8 | import org.springframework.messaging.simp.SimpMessageHeaderAccessor; 9 | import org.springframework.messaging.simp.SimpMessageType; 10 | import org.springframework.messaging.simp.stomp.StompCommand; 11 | import org.springframework.util.MimeType; 12 | import org.springframework.util.MimeTypeUtils; 13 | 14 | public class MyStompHeaderAccessor extends SimpMessageHeaderAccessor { 15 | private static final String STOMP_ID_HEADER = "id"; 16 | 17 | private static final String STOMP_SUBSCRIPTION_HEADER = "subscription"; 18 | 19 | private static final String STOMP_PASSCODE_HEADER = "passcode"; 20 | 21 | private static final String STOMP_DESTINATION_HEADER = "destination"; 22 | 23 | private static final String STOMP_CONTENT_TYPE_HEADER = "content-type"; 24 | 25 | private static final String COMMAND_HEADER = "stompCommand"; 26 | 27 | private static final String CREDENTIALS_HEADER = "stompCredentials"; 28 | 29 | public MyStompHeaderAccessor(Message message) { 30 | super(message); 31 | updateStompHeadersFromSimpMessageHeaders(); 32 | } 33 | 34 | 35 | void updateSimpMessageHeadersFromStompHeaders() { 36 | if (getNativeHeaders() == null) { 37 | return; 38 | } 39 | String value = getFirstNativeHeader(STOMP_DESTINATION_HEADER); 40 | if (value != null) { 41 | super.setDestination(value); 42 | } 43 | value = getFirstNativeHeader(STOMP_CONTENT_TYPE_HEADER); 44 | if (value != null) { 45 | super.setContentType(MimeTypeUtils.parseMimeType(value)); 46 | } 47 | StompCommand command = getCommand(); 48 | if (StompCommand.MESSAGE.equals(command)) { 49 | value = getFirstNativeHeader(STOMP_SUBSCRIPTION_HEADER); 50 | if (value != null) { 51 | super.setSubscriptionId(value); 52 | } 53 | } 54 | else if (StompCommand.SUBSCRIBE.equals(command) || StompCommand.UNSUBSCRIBE.equals(command)) { 55 | value = getFirstNativeHeader(STOMP_ID_HEADER); 56 | if (value != null) { 57 | super.setSubscriptionId(value); 58 | } 59 | } 60 | else if (StompCommand.CONNECT.equals(command) || StompCommand.STOMP.equals(command)) { 61 | protectPasscode(); 62 | } 63 | } 64 | 65 | void updateStompHeadersFromSimpMessageHeaders() { 66 | String destination = getDestination(); 67 | if (destination != null) { 68 | setNativeHeader(STOMP_DESTINATION_HEADER, destination); 69 | } 70 | MimeType contentType = getContentType(); 71 | if (contentType != null) { 72 | setNativeHeader(STOMP_CONTENT_TYPE_HEADER, contentType.toString()); 73 | } 74 | trySetStompHeaderForSubscriptionId(); 75 | } 76 | 77 | // Redeclared for visibility within simp.stomp 78 | @Override 79 | @Nullable 80 | protected Map> getNativeHeaders() { 81 | return super.getNativeHeaders(); 82 | } 83 | 84 | /** 85 | * Return the STOMP command, or {@code null} if not yet set. 86 | */ 87 | @Nullable 88 | public StompCommand getCommand() { 89 | return (StompCommand) getHeader(COMMAND_HEADER); 90 | } 91 | 92 | private void trySetStompHeaderForSubscriptionId() { 93 | String subscriptionId = getSubscriptionId(); 94 | if (subscriptionId != null) { 95 | StompCommand command = getCommand(); 96 | if (command != null && StompCommand.MESSAGE.equals(command)) { 97 | setNativeHeader(STOMP_SUBSCRIPTION_HEADER, subscriptionId); 98 | } 99 | else { 100 | SimpMessageType messageType = getMessageType(); 101 | if (SimpMessageType.SUBSCRIBE.equals(messageType) || SimpMessageType.UNSUBSCRIBE.equals(messageType)) { 102 | setNativeHeader(STOMP_ID_HEADER, subscriptionId); 103 | } 104 | } 105 | } 106 | } 107 | 108 | private void protectPasscode() { 109 | String value = getFirstNativeHeader(STOMP_PASSCODE_HEADER); 110 | if (value != null && !"PROTECTED".equals(value)) { 111 | setHeader(CREDENTIALS_HEADER, new StompPasscode(value)); 112 | setNativeHeader(STOMP_PASSCODE_HEADER, "PROTECTED"); 113 | } 114 | } 115 | 116 | private static class StompPasscode { 117 | public StompPasscode(String passcode) { 118 | 119 | } 120 | 121 | @Override 122 | public String toString() { 123 | return "[PROTECTED]"; 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/DeviceService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.data.domain.Pageable; 10 | import org.springframework.security.access.AccessDeniedException; 11 | import org.springframework.stereotype.Service; 12 | 13 | import top.microiot.domain.Device; 14 | import top.microiot.domain.Domain; 15 | import top.microiot.domain.ManagedObject; 16 | import top.microiot.domain.Site; 17 | import top.microiot.domain.User; 18 | import top.microiot.domain.attribute.DeviceAttributeType; 19 | import top.microiot.dto.DevicePageInfo; 20 | import top.microiot.repository.DeviceRepository; 21 | import top.microiot.repository.SiteRepository; 22 | 23 | @Service 24 | public class DeviceService extends IoTService{ 25 | @Autowired 26 | private DeviceRepository deviceRepository; 27 | @Autowired 28 | private DeviceGroupService deviceGroupService; 29 | @Autowired 30 | private SiteRepository siteRepository; 31 | @Autowired 32 | private MOService moService; 33 | 34 | public Device getDevice(String id){ 35 | Device device = deviceRepository.findById(id).get(); 36 | 37 | if(!moService.isMyMO(device)) { 38 | Map map = device.getDeviceType().getAttDefinition(); 39 | for (String key : map.keySet()) { 40 | DeviceAttributeType type = map.get(key); 41 | type.setGet(false); 42 | type.setSet(false); 43 | type.setReport(false); 44 | } 45 | 46 | } 47 | 48 | return device; 49 | } 50 | 51 | public Device getDeviceByUsername(String username) { 52 | Device device = deviceRepository.findByDeviceAccountUsername(username); 53 | 54 | if(!moService.isMyMO(device)) { 55 | Map map = device.getDeviceType().getAttDefinition(); 56 | for (String key : map.keySet()) { 57 | DeviceAttributeType type = map.get(key); 58 | type.setGet(false); 59 | type.setSet(false); 60 | type.setReport(false); 61 | } 62 | 63 | } 64 | 65 | return device; 66 | } 67 | 68 | public Device listDeviceByDevice(String id){ 69 | if (deviceGroupService.isGroup(id) || isChild(id)) { 70 | Device device = deviceRepository.findById(id).get(); 71 | return device; 72 | } 73 | else 74 | throw new AccessDeniedException("device"); 75 | 76 | } 77 | 78 | public Device listCurrentDevice() { 79 | return getCurrentDevice(); 80 | } 81 | 82 | public Page listDevice(DevicePageInfo info){ 83 | Pageable pageable = getPageable(info); 84 | Domain domain = getCurrentDomain(); 85 | 86 | return deviceRepository.queryDevice(info.getLocationId(), domain.getId(), info.getName(), info.getDeviceTypeId(), pageable); 87 | } 88 | 89 | public long countDevice(DevicePageInfo info) { 90 | Domain domain = getCurrentDomain(); 91 | return deviceRepository.countDevice(info.getLocationId(), domain.getId(), info.getName(), info.getDeviceTypeId()); 92 | } 93 | 94 | public List getMyDevices(){ 95 | User user = getCurrentUser(); 96 | if(user.getArea() == null || user.getArea().isEmpty()) 97 | return null; 98 | 99 | List devices = new ArrayList(); 100 | for(ManagedObject site: user.getArea()) { 101 | if(site instanceof Device) 102 | devices.add((Device)site); 103 | else 104 | getSiteDevices(devices, site); 105 | } 106 | 107 | return devices; 108 | } 109 | 110 | private void getSiteDevices(List devices, ManagedObject site) { 111 | List ds = deviceRepository.listDevice(site.getId(), null, null, null); 112 | 113 | if(ds != null && !ds.isEmpty()) 114 | devices.addAll(ds); 115 | 116 | List ss = siteRepository.listSite(site.getId(), null, null, null); 117 | if(ss != null && !ss.isEmpty()) { 118 | for(Site s: ss) { 119 | getSiteDevices(devices, s); 120 | } 121 | } 122 | } 123 | 124 | public boolean isChild(String deviceId) { 125 | Device d = getCurrentDevice(); 126 | Device child = deviceRepository.findById(deviceId).get(); 127 | if(child.getGateway().equals(d)) 128 | return true; 129 | else 130 | return false; 131 | } 132 | 133 | public List getSubDevice(String id){ 134 | return deviceRepository.findByGatewayId(id); 135 | } 136 | 137 | public List getMySubDevice(){ 138 | Device d = getCurrentDevice(); 139 | return deviceRepository.findByGatewayId(d.getId()); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/SiteTypeController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.Reader; 8 | import java.io.UnsupportedEncodingException; 9 | import java.util.List; 10 | 11 | import javax.servlet.http.HttpServletResponse; 12 | import javax.validation.Valid; 13 | 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.data.domain.Page; 16 | import org.springframework.http.HttpHeaders; 17 | import org.springframework.security.access.prepost.PreAuthorize; 18 | import org.springframework.validation.BindingResult; 19 | import org.springframework.web.bind.annotation.DeleteMapping; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | import org.springframework.web.bind.annotation.PatchMapping; 22 | import org.springframework.web.bind.annotation.PathVariable; 23 | import org.springframework.web.bind.annotation.PostMapping; 24 | import org.springframework.web.bind.annotation.RequestBody; 25 | import org.springframework.web.bind.annotation.RequestMapping; 26 | import org.springframework.web.bind.annotation.RequestParam; 27 | import org.springframework.web.bind.annotation.RestController; 28 | import org.springframework.web.multipart.MultipartFile; 29 | 30 | import com.fasterxml.jackson.databind.ObjectMapper; 31 | 32 | import top.microiot.domain.SiteType; 33 | import top.microiot.domain.SiteTypeFile; 34 | import top.microiot.domain.attribute.AttTypeInfo; 35 | import top.microiot.dto.PageInfo; 36 | import top.microiot.dto.SiteTypeRenameInfo; 37 | import top.microiot.exception.StatusException; 38 | import top.microiot.service.SiteTypeService; 39 | 40 | @RestController 41 | @RequestMapping("/sitetypes") 42 | public class SiteTypeController extends IoTController{ 43 | @Autowired 44 | private SiteTypeService siteTypeService; 45 | 46 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 47 | @PostMapping("") 48 | public SiteType addSitetype(@RequestBody @Valid AttTypeInfo info, BindingResult result) { 49 | throwError(result); 50 | return siteTypeService.add(info); 51 | } 52 | 53 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 54 | @PostMapping("/import") 55 | public SiteType importSiteType(@RequestParam("file") MultipartFile file) { 56 | ObjectMapper mapper = new ObjectMapper(); 57 | try { 58 | InputStream inputStream = new BufferedInputStream(file.getInputStream()); 59 | Reader reader = new InputStreamReader(inputStream, "UTF-8"); 60 | SiteTypeFile siteType = mapper.readValue(reader, SiteTypeFile.class); 61 | return siteTypeService.add(siteType); 62 | } catch (IOException e) { 63 | throw new StatusException(e.getMessage()); 64 | } 65 | } 66 | 67 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 68 | @GetMapping("/{id}") 69 | public SiteType getSiteType(@PathVariable String id){ 70 | return siteTypeService.listSiteType(id); 71 | } 72 | 73 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 74 | @GetMapping("/export/{id}") 75 | public void exportSiteType(@PathVariable String id, HttpServletResponse response) throws UnsupportedEncodingException { 76 | SiteType siteType = siteTypeService.listSiteType(id); 77 | 78 | response.setContentType("text/json;charset=utf-8"); 79 | response.setHeader(HttpHeaders.CONTENT_DISPOSITION, 80 | "attachment; filename=sitetype.json"); 81 | 82 | SiteTypeFile file = new SiteTypeFile(siteType); 83 | ObjectMapper mapper = new ObjectMapper(); 84 | 85 | try { 86 | mapper.writeValue(response.getWriter(), file); 87 | } catch (IOException e) { 88 | throw new StatusException(e.getMessage()); 89 | } 90 | } 91 | 92 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 93 | @GetMapping("/page") 94 | public Page getSiteTypes(@Valid PageInfo info, BindingResult result){ 95 | throwError(result); 96 | return siteTypeService.listSiteType(info); 97 | } 98 | 99 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 100 | @GetMapping("/list") 101 | public List getSiteTypesList(){ 102 | return siteTypeService.listSiteTypes(); 103 | } 104 | 105 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 106 | @PatchMapping("/name") 107 | public SiteType updateSiteType(@RequestBody @Valid SiteTypeRenameInfo info, BindingResult result) { 108 | throwError(result); 109 | return siteTypeService.rename(info); 110 | } 111 | 112 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 113 | @DeleteMapping("/{id}") 114 | public void deleteSiteType(@PathVariable String id){ 115 | siteTypeService.delete(id); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/DomainService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.Set; 8 | 9 | import javax.validation.Valid; 10 | 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.dao.DuplicateKeyException; 13 | import org.springframework.security.access.AccessDeniedException; 14 | import org.springframework.stereotype.Service; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import top.microiot.domain.Domain; 18 | import top.microiot.domain.ManagedObject; 19 | import top.microiot.domain.User; 20 | import top.microiot.dto.DomainInfo; 21 | import top.microiot.dto.DomainRenameInfo; 22 | import top.microiot.exception.ConflictException; 23 | import top.microiot.exception.NotFoundException; 24 | import top.microiot.repository.AlarmRepository; 25 | import top.microiot.repository.ConfigRepository; 26 | import top.microiot.repository.DeviceRepository; 27 | import top.microiot.repository.DeviceTypeRepository; 28 | import top.microiot.repository.DomainRepository; 29 | import top.microiot.repository.EventRepository; 30 | import top.microiot.repository.FavoriteRepository; 31 | import top.microiot.repository.SiteRepository; 32 | import top.microiot.repository.SiteTypeRepository; 33 | 34 | @Service 35 | public class DomainService extends IoTService{ 36 | @Autowired 37 | private DomainRepository domainRepository; 38 | @Autowired 39 | private MOService moService; 40 | @Autowired 41 | private AlarmRepository alarmRepository; 42 | @Autowired 43 | private EventRepository eventRepository; 44 | @Autowired 45 | private FavoriteRepository favoriteRepository; 46 | @Autowired 47 | private ConfigRepository configRepository; 48 | @Autowired 49 | private DeviceRepository deviceRepository; 50 | @Autowired 51 | private SiteRepository siteRepository; 52 | @Autowired 53 | private DeviceTypeRepository deviceTypeRepository; 54 | @Autowired 55 | private SiteTypeRepository siteTypeRepository; 56 | 57 | @Transactional 58 | public Domain addDomain(DomainInfo info) { 59 | Domain domain = new Domain(info.getName()); 60 | 61 | try{ 62 | return domainRepository.save(domain); 63 | } catch (DuplicateKeyException e) { 64 | throw new ConflictException("domain:" + info.getName()); 65 | } 66 | } 67 | 68 | public Domain getByName(String name) { 69 | if(isMyDomain(name)) { 70 | Domain domain = domainRepository.findByName(name); 71 | if(domain == null) 72 | throw new NotFoundException("domain: " + name); 73 | return domain; 74 | } 75 | else 76 | throw new AccessDeniedException(name); 77 | } 78 | 79 | public Domain getById(String id) { 80 | Optional domain = domainRepository.findById(id); 81 | if(domain.isPresent()) { 82 | if(isMyDomain(domain.get().getName())) { 83 | return domain.get(); 84 | } 85 | else 86 | throw new AccessDeniedException(id); 87 | } 88 | else 89 | throw new NotFoundException(id); 90 | } 91 | 92 | @Transactional 93 | public Domain renameDomain(@Valid DomainRenameInfo info) { 94 | Domain domain = domainRepository.findById(info.getId()).get(); 95 | domain.setName(info.getName()); 96 | return domainRepository.save(domain); 97 | } 98 | 99 | public List getMyDomain() { 100 | User user = getCurrentUser(); 101 | 102 | if(user.isSystem()) 103 | return domainRepository.findAll(); 104 | else if(user.isArea()) { 105 | List mos = user.getArea(); 106 | Set domains = new HashSet(); 107 | List domainList = new ArrayList(); 108 | for(ManagedObject mo : mos) { 109 | Domain domain = mo.getDomain(); 110 | domains.add(domain); 111 | } 112 | domainList.addAll(domains); 113 | return domainList; 114 | } 115 | else 116 | return null; 117 | } 118 | 119 | public boolean isMyDomain(String domain) { 120 | User user = getCurrentUser(); 121 | 122 | return isMyDomain(domain, user); 123 | } 124 | 125 | public boolean isMyDomain(String domain, User user) { 126 | Domain dom = domainRepository.findByName(domain); 127 | if(dom == null) 128 | return false; 129 | if(user.isSystem()) 130 | return true; 131 | else if(user.isArea()) { 132 | List mos = user.getArea(); 133 | 134 | for(ManagedObject mo : mos) { 135 | Domain d = mo.getDomain(); 136 | if(d.equals(dom)) 137 | return true; 138 | } 139 | return false; 140 | } 141 | else 142 | return false; 143 | } 144 | 145 | @Transactional 146 | public void deleteDomain(String id) { 147 | Domain domain = domainRepository.findById(id).get(); 148 | 149 | moService.hasMOAccess(domain); 150 | 151 | alarmRepository.deleteByDomainId(id); 152 | eventRepository.deleteByDomainId(id); 153 | favoriteRepository.deleteByDomainId(id); 154 | configRepository.deleteByDomainId(id); 155 | deviceRepository.deleteByDomainId(id); 156 | siteRepository.deleteByDomainId(id); 157 | deviceTypeRepository.deleteByDomainId(id); 158 | siteTypeRepository.deleteByDomainId(id); 159 | domainRepository.deleteById(id); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/QueryController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import java.util.List; 4 | 5 | import javax.validation.Valid; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.data.geo.GeoResults; 10 | import org.springframework.security.access.prepost.PreAuthorize; 11 | import org.springframework.validation.BindingResult; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.PathVariable; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import top.microiot.domain.Alarm; 17 | import top.microiot.domain.Device; 18 | import top.microiot.domain.DeviceGroup; 19 | import top.microiot.domain.DeviceType; 20 | import top.microiot.domain.Event; 21 | import top.microiot.domain.IoTObject; 22 | import top.microiot.domain.Site; 23 | import top.microiot.domain.SiteType; 24 | import top.microiot.dto.DistinctInfo; 25 | import top.microiot.dto.QueryInfo; 26 | import top.microiot.dto.QueryNearPageInfo; 27 | import top.microiot.dto.QueryPageInfo; 28 | import top.microiot.exception.ValueException; 29 | import top.microiot.service.QueryService; 30 | 31 | @RestController 32 | public class QueryController extends IoTController{ 33 | @Autowired 34 | private QueryService queryService; 35 | 36 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 37 | @GetMapping("/{queryObject}/query/id/{id}") 38 | public Object queryObject(@PathVariable String queryObject, @PathVariable String id) { 39 | return queryService.findById(id, getClass(queryObject)); 40 | } 41 | 42 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 43 | @GetMapping("/{queryObject}/query/one") 44 | public Object queryObject(@PathVariable String queryObject, @Valid QueryInfo info, BindingResult result) { 45 | throwError(result); 46 | return queryService.findOne(info.getFilter(), info.getSort(), info.getCollation(), getClass(queryObject)); 47 | } 48 | 49 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 50 | @GetMapping("/{queryObject}/query/list") 51 | public List queryObjectList(@PathVariable String queryObject, @Valid QueryInfo info, BindingResult result) { 52 | throwError(result); 53 | return queryService.find(info.getFilter(), info.getSort(), info.getCollation(), getClass(queryObject)); 54 | } 55 | 56 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 57 | @GetMapping("/{queryObject}/query/page") 58 | public Page queryObjectPage(@PathVariable String queryObject, @Valid QueryPageInfo info, BindingResult result) { 59 | throwError(result); 60 | return queryService.findPage(info.getFilter(), info.getSort(), info.getCollation(), info.getPageNumber(), info.getPageSize(), getClass(queryObject)); 61 | } 62 | 63 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 64 | @GetMapping("/{queryObject}/query/geo") 65 | public GeoResults queryObjectGeo(@PathVariable String queryObject, @Valid QueryNearPageInfo info, BindingResult result) { 66 | throwError(result); 67 | return queryService.findGeo(info.getFilter(), info.getSort(), info.getCollation(), 68 | info.getX(), info.getY(), info.getMaxDistance(), info.getMetrics(), 69 | info.getPageNumber(), info.getPageSize(), getClass(queryObject)); 70 | } 71 | 72 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 73 | @GetMapping("/{queryObject}/query/aggregate") 74 | public List queryObjectAggregate(@PathVariable String queryObject, @Valid QueryInfo info, BindingResult result) { 75 | throwError(result); 76 | return queryService.aggregate(info.getFilter(), getClass(queryObject).getSimpleName().toLowerCase(), getClass(queryObject)); 77 | } 78 | 79 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 80 | @GetMapping("/{queryObject}/query/distinct") 81 | public List queryObjectDistinct(@PathVariable String queryObject, @Valid DistinctInfo info, BindingResult result) { 82 | throwError(result); 83 | return queryService.distinct(info.getFilter(), info.getSort(), info.getCollation(), info.getField(), getClass(queryObject), getClass(info.getReturnClass())); 84 | } 85 | 86 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 87 | @GetMapping("/{queryObject}/query/count") 88 | public long queryObjectCount(@PathVariable String queryObject, @Valid QueryInfo info, BindingResult result) { 89 | throwError(result); 90 | return queryService.count(info.getFilter(), getClass(queryObject)); 91 | } 92 | 93 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 94 | @GetMapping("/{queryObject}/query/exist") 95 | public boolean queryObjectExist(@PathVariable String queryObject, @Valid QueryInfo info, BindingResult result) { 96 | throwError(result); 97 | return queryService.exist(info.getFilter(), getClass(queryObject)); 98 | } 99 | 100 | private Class getClass(String className){ 101 | if(className.equals("sites")) 102 | return Site.class; 103 | else if(className.equals("devices")) 104 | return Device.class; 105 | else if(className.equals("devicegroups")) 106 | return DeviceGroup.class; 107 | else if(className.equals("sitetypes")) 108 | return SiteType.class; 109 | else if(className.equals("devicetypes")) 110 | return DeviceType.class; 111 | else if(className.equals("alarms")) 112 | return Alarm.class; 113 | else if(className.equals("events")) 114 | return Event.class; 115 | else 116 | throw new ValueException("illegal query object: " + className); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/DeviceGroupService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.dao.DuplicateKeyException; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.data.domain.Pageable; 10 | import org.springframework.security.access.AccessDeniedException; 11 | import org.springframework.stereotype.Service; 12 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | import top.microiot.domain.Device; 15 | import top.microiot.domain.DeviceGroup; 16 | import top.microiot.domain.Domain; 17 | import top.microiot.dto.DeviceGroupInfo; 18 | import top.microiot.dto.DeviceGroupRenameInfo; 19 | import top.microiot.dto.PageInfo; 20 | import top.microiot.exception.ConflictException; 21 | import top.microiot.exception.NotFoundException; 22 | import top.microiot.exception.ValueException; 23 | import top.microiot.repository.DeviceGroupRepository; 24 | import top.microiot.repository.DeviceRepository; 25 | 26 | @Service 27 | public class DeviceGroupService extends IoTService{ 28 | @Autowired 29 | private DeviceGroupRepository deviceGroupRepository; 30 | @Autowired 31 | private DeviceRepository deviceRepository; 32 | @Autowired 33 | private MOService moService; 34 | 35 | @Transactional 36 | public DeviceGroup addDeviceGroup(DeviceGroupInfo info) { 37 | Domain domain = moService.hasDomainAccess(); 38 | 39 | List devices = new ArrayList(); 40 | for(String deviceId : info.getDevices()) { 41 | Device device = deviceRepository.findById(deviceId).get(); 42 | if(!device.getDomain().equals(domain)) 43 | throw new NotFoundException("device: " + deviceId); 44 | devices.add(device); 45 | } 46 | 47 | DeviceGroup group = new DeviceGroup(info.getName(), devices, domain); 48 | return deviceGroupRepository.save(group); 49 | } 50 | 51 | @Transactional 52 | public DeviceGroup rename(DeviceGroupRenameInfo info){ 53 | moService.hasDomainAccess(); 54 | 55 | DeviceGroup group = deviceGroupRepository.findById(info.getId()).get(); 56 | group.setName(info.getName()); 57 | 58 | try{ 59 | return deviceGroupRepository.save(group); 60 | } catch (DuplicateKeyException e) { 61 | throw new ConflictException("device group name"); 62 | } 63 | } 64 | 65 | public DeviceGroup listDeviceGroup(String id){ 66 | DeviceGroup group = deviceGroupRepository.findById(id).get(); 67 | return group; 68 | } 69 | 70 | public Page listDeviceGroups(PageInfo info){ 71 | Pageable pageable = getPageable(info); 72 | Domain domain = moService.hasDomainAccess(); 73 | 74 | return deviceGroupRepository.findByDomain(domain.getId(), pageable); 75 | } 76 | 77 | public List listDeviceGroups(){ 78 | Domain domain = moService.hasDomainAccess(); 79 | return deviceGroupRepository.findByDomainId(domain.getId()); 80 | } 81 | 82 | @Transactional 83 | public void delete(String id) { 84 | Domain domain = moService.hasDomainAccess(); 85 | 86 | DeviceGroup group = deviceGroupRepository.findById(id).get(); 87 | if(group == null || !group.getDomain().equals(domain)) 88 | throw new NotFoundException("deivce group"); 89 | deviceGroupRepository.deleteById(id); 90 | } 91 | 92 | @Transactional 93 | public DeviceGroup addGroup(String groupId, String deviceId) { 94 | Domain domain = moService.hasDomainAccess(); 95 | 96 | Device device = deviceRepository.findById(deviceId).get(); 97 | if(!device.getDomain().equals(domain)) 98 | throw new NotFoundException("device: " + deviceId); 99 | 100 | DeviceGroup group = deviceGroupRepository.findById(groupId).get(); 101 | if(!group.getDomain().equals(domain)) 102 | throw new NotFoundException("device group: " + groupId); 103 | if(group.getDevices().contains(device)) 104 | throw new ValueException("device: " + deviceId + " in grooup: " + groupId); 105 | 106 | List devices = group.getDevices(); 107 | devices.add(device); 108 | 109 | return deviceGroupRepository.save(group); 110 | } 111 | 112 | @Transactional 113 | public DeviceGroup removeGroup(String groupId, String deviceId) { 114 | Domain domain = moService.hasDomainAccess(); 115 | Device device = deviceRepository.findById(deviceId).get(); 116 | if(!device.getDomain().equals(domain)) 117 | throw new NotFoundException("device: " + deviceId); 118 | 119 | DeviceGroup group = deviceGroupRepository.findById(groupId).get(); 120 | if(!group.getDomain().equals(domain)) 121 | throw new NotFoundException("device group: " + groupId); 122 | if(!group.getDevices().contains(device)) 123 | throw new ValueException("device: " + deviceId + " not in grooup: " + groupId); 124 | 125 | List devices = group.getDevices(); 126 | devices.remove(device); 127 | 128 | return deviceGroupRepository.save(group); 129 | } 130 | 131 | public boolean isGroup(String device) { 132 | Device d = getCurrentDevice(); 133 | if(!d.getId().equals(device)) { 134 | List devices = new ArrayList(); 135 | devices.add(d.getId()); 136 | devices.add(device); 137 | return deviceGroupRepository.existsByDevicesContaining(devices); 138 | } 139 | else 140 | throw new ValueException("device is same"); 141 | } 142 | 143 | public List listMyDeviceGroups() { 144 | Device device = getCurrentDevice(); 145 | return deviceGroupRepository.findByDevicesId(device.getId()); 146 | } 147 | 148 | public DeviceGroup listDeviceGroupByDevice(String id) { 149 | Device device = getCurrentDevice(); 150 | DeviceGroup group = deviceGroupRepository.findById(id).get(); 151 | for(Device d : group.getDevices()) { 152 | if(d.equals(device)) 153 | return group; 154 | } 155 | throw new AccessDeniedException(id); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/DeviceController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import java.util.List; 4 | 5 | import javax.validation.Valid; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.security.access.prepost.PreAuthorize; 10 | import org.springframework.security.core.Authentication; 11 | import org.springframework.security.core.context.SecurityContextHolder; 12 | import org.springframework.validation.BindingResult; 13 | import org.springframework.web.bind.annotation.DeleteMapping; 14 | import org.springframework.web.bind.annotation.GetMapping; 15 | import org.springframework.web.bind.annotation.PatchMapping; 16 | import org.springframework.web.bind.annotation.PathVariable; 17 | import org.springframework.web.bind.annotation.PostMapping; 18 | import org.springframework.web.bind.annotation.RequestBody; 19 | import org.springframework.web.bind.annotation.RequestMapping; 20 | import org.springframework.web.bind.annotation.RestController; 21 | 22 | import top.microiot.domain.Device; 23 | import top.microiot.domain.attribute.AttValueInfo; 24 | import top.microiot.dto.DeviceInfo; 25 | import top.microiot.dto.DeviceMoveInfo; 26 | import top.microiot.dto.DevicePageInfo; 27 | import top.microiot.dto.DeviceRenameInfo; 28 | import top.microiot.dto.DeviceUpdateInfo; 29 | import top.microiot.dto.SubDeviceInfo; 30 | import top.microiot.security.CustomUserDetails; 31 | import top.microiot.service.DeviceManageService; 32 | import top.microiot.service.DeviceService; 33 | import top.microiot.service.MOService; 34 | 35 | @RestController 36 | @RequestMapping("/devices") 37 | public class DeviceController extends IoTController{ 38 | @Autowired 39 | private DeviceService deviceService; 40 | @Autowired 41 | private MOService moService; 42 | @Autowired 43 | private DeviceManageService deviceManageService; 44 | 45 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 46 | @PostMapping("") 47 | public Device register(@RequestBody @Valid DeviceInfo info, BindingResult result) { 48 | throwError(result); 49 | return deviceManageService.register(info); 50 | } 51 | 52 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 53 | @PostMapping("/subdevice") 54 | public Device register(@RequestBody @Valid SubDeviceInfo info, BindingResult result) { 55 | throwError(result); 56 | return deviceManageService.register(info); 57 | } 58 | 59 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA') or hasAuthority('DEVICE')") 60 | @GetMapping("/{id}") 61 | public Device getDevice(@PathVariable String id){ 62 | Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 63 | CustomUserDetails user = (CustomUserDetails) auth.getPrincipal(); 64 | 65 | Device device; 66 | if(!user.isDevice()) 67 | device = deviceService.getDevice(id); 68 | else 69 | device = deviceService.listDeviceByDevice(id); 70 | return device; 71 | } 72 | 73 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA') or hasAuthority('DEVICE')") 74 | @GetMapping("/subdevice/{id}") 75 | public List getSubDevice(@PathVariable String id){ 76 | return deviceService.getSubDevice(id); 77 | } 78 | 79 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA') ") 80 | @GetMapping("/username/{username}") 81 | public Device getDeviceByUsername(@PathVariable String username){ 82 | Device device = deviceService.getDeviceByUsername(username); 83 | 84 | return device; 85 | } 86 | 87 | @PreAuthorize("hasAuthority('DEVICE')") 88 | @GetMapping("/me") 89 | public Device getDevice(){ 90 | return deviceService.listCurrentDevice(); 91 | } 92 | 93 | @PreAuthorize("hasAuthority('DEVICE')") 94 | @GetMapping("/subdevice") 95 | public List getMySubDevice(){ 96 | return deviceService.getMySubDevice(); 97 | } 98 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 99 | @GetMapping("") 100 | public Page getDevices(@Valid DevicePageInfo info, BindingResult result){ 101 | throwError(result); 102 | return deviceService.listDevice(info); 103 | } 104 | 105 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 106 | @GetMapping("/count") 107 | public long getCount(@Valid DevicePageInfo info, BindingResult result) { 108 | throwError(result); 109 | return deviceService.countDevice(info); 110 | } 111 | 112 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 113 | @PatchMapping("") 114 | public Device updateDevice(@RequestBody @Valid DeviceUpdateInfo info, BindingResult result) { 115 | throwError(result); 116 | return deviceManageService.updateDevice(info); 117 | } 118 | 119 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 120 | @PatchMapping("/site") 121 | public Device moveDevice(@RequestBody @Valid DeviceMoveInfo info, BindingResult result) { 122 | throwError(result); 123 | return deviceManageService.moveDevice(info); 124 | } 125 | 126 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 127 | @PatchMapping("/name") 128 | public Device renameDevice(@RequestBody @Valid DeviceRenameInfo info, BindingResult result) { 129 | throwError(result); 130 | return deviceManageService.renameDevice(info); 131 | } 132 | 133 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 134 | @DeleteMapping("/{id}") 135 | public void delete(@PathVariable String id){ 136 | deviceManageService.delete(id); 137 | } 138 | 139 | @PreAuthorize("hasAuthority('AREA')") 140 | @GetMapping("/area") 141 | public List getMyDevices(){ 142 | return deviceService.getMyDevices(); 143 | } 144 | 145 | @PreAuthorize("hasAuthority('AREA')") 146 | @GetMapping("/area/{deviceId}") 147 | public boolean isMyDevice(@PathVariable String deviceId){ 148 | return moService.isMyMO(deviceId); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/QueryService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.bson.Document; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.domain.Page; 9 | import org.springframework.data.domain.PageImpl; 10 | import org.springframework.data.domain.PageRequest; 11 | import org.springframework.data.domain.Pageable; 12 | import org.springframework.data.geo.GeoResult; 13 | import org.springframework.data.geo.GeoResults; 14 | import org.springframework.data.geo.Metrics; 15 | import org.springframework.data.mongodb.core.MongoTemplate; 16 | import org.springframework.data.mongodb.core.aggregation.Aggregation; 17 | import org.springframework.data.mongodb.core.aggregation.AggregationResults; 18 | import org.springframework.data.mongodb.core.query.BasicQuery; 19 | import org.springframework.data.mongodb.core.query.Collation; 20 | import org.springframework.data.mongodb.core.query.NearQuery; 21 | import org.springframework.security.access.AccessDeniedException; 22 | import org.springframework.stereotype.Service; 23 | 24 | import top.microiot.domain.DocumentAggregationOperation; 25 | import top.microiot.domain.Domain; 26 | import top.microiot.domain.IoTObject; 27 | 28 | @Service 29 | public class QueryService extends IoTService{ 30 | @Autowired 31 | private MongoTemplate mongoTemplate; 32 | 33 | public List find(String filter, String sort, String collation, Class entityClass) { 34 | BasicQuery query = getQuery(filter, sort, collation); 35 | 36 | List list = mongoTemplate.find(query, entityClass); 37 | valideList(filter, list); 38 | return list; 39 | } 40 | 41 | public Page findPage(String filter, String sort, String collation, int pageNumber, int pageSize, Class entityClass) { 42 | BasicQuery query = getQuery(filter, sort, collation); 43 | Pageable p = PageRequest.of(pageNumber, pageSize); 44 | query.with(p); 45 | 46 | List data = mongoTemplate.find(query, entityClass); 47 | long total = count(filter, entityClass); 48 | 49 | PageImpl page = new PageImpl(data, p, total); 50 | List list = page.getContent(); 51 | valideList(filter, list); 52 | return page; 53 | } 54 | 55 | public GeoResults findGeo(String filter, String sort, String collation, double x, double y, double max, Metrics metrics, int pageNumber, int pageSize, Class entityClass) { 56 | BasicQuery query = getQuery(filter, sort, collation); 57 | Pageable p = PageRequest.of(pageNumber, pageSize); 58 | 59 | NearQuery near = NearQuery.near(x, y, metrics).maxDistance(max); 60 | near.query(query); 61 | near.with(p); 62 | 63 | GeoResults geo = mongoTemplate.geoNear(near, entityClass); 64 | List> list = geo.getContent(); 65 | Domain domain = getCurrentDomain(); 66 | for(GeoResult t: list) { 67 | IoTObject object = (IoTObject) t.getContent(); 68 | if(!object.getDomain().equals(domain)) 69 | throw new AccessDeniedException(filter); 70 | } 71 | return geo; 72 | } 73 | 74 | public List distinct(String filter, String sort, String collation, String field, Class entityClass, Class resultClass){ 75 | BasicQuery query = getQuery(filter, sort, collation); 76 | 77 | List list = mongoTemplate.findDistinct(query, field, entityClass, resultClass); 78 | // valideList(filter, list); 79 | return list; 80 | } 81 | 82 | public List aggregate(String filter, String collectionName, Class outputType) { 83 | @SuppressWarnings("unchecked") 84 | List documents = (List) Document.parse("{\"json\":" + filter + "}").get("json"); 85 | List operations = new ArrayList(); 86 | for(Document document : documents) { 87 | operations.add(new DocumentAggregationOperation(document)); 88 | } 89 | Aggregation aggregation = Aggregation.newAggregation(operations); 90 | 91 | AggregationResults results = mongoTemplate.aggregate(aggregation, collectionName, outputType); 92 | List list = results.getMappedResults(); 93 | valideList(filter, list); 94 | return list; 95 | } 96 | 97 | public T findOne(String filter, String sort, String collation, Class entityClass) { 98 | BasicQuery query = getQuery(filter, sort, collation); 99 | T one = mongoTemplate.findOne(query, entityClass); 100 | valideOne(filter, one); 101 | return one; 102 | } 103 | 104 | public T findById(String id, Class entityClass) { 105 | T one = mongoTemplate.findById(id, entityClass); 106 | valideOne(id, one); 107 | return one; 108 | } 109 | 110 | public long count(String filter, Class entityClass) { 111 | BasicQuery query = new BasicQuery(filter); 112 | return mongoTemplate.count(query, entityClass); 113 | } 114 | 115 | public boolean exist(String filter, Class entityClass) { 116 | BasicQuery query = new BasicQuery(filter); 117 | return mongoTemplate.exists(query, entityClass); 118 | } 119 | 120 | private BasicQuery getQuery(String filter, String sort, String collation) { 121 | BasicQuery query = new BasicQuery(filter); 122 | if(sort != null && sort.length() > 0) 123 | query.setSortObject(Document.parse(sort)); 124 | if(collation != null && collation.length() > 0) 125 | query.collation(Collation.from(Document.parse(collation))); 126 | return query; 127 | } 128 | 129 | private void valideList(String filter, List list) { 130 | Domain domain = getCurrentDomain(); 131 | for(T t: list) { 132 | IoTObject object = (IoTObject) t; 133 | if(!object.getDomain().equals(domain)) 134 | throw new AccessDeniedException(filter); 135 | } 136 | } 137 | 138 | private void valideOne(String filter, T one) { 139 | IoTObject object = (IoTObject) one; 140 | Domain domain = getCurrentDomain(); 141 | if(!object.getDomain().equals(domain)) 142 | throw new AccessDeniedException(filter); 143 | } 144 | 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/UserService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.validation.Valid; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.dao.DuplicateKeyException; 10 | import org.springframework.data.domain.Page; 11 | import org.springframework.data.domain.Pageable; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import top.microiot.domain.Domain; 16 | import top.microiot.domain.ManagedObject; 17 | import top.microiot.domain.Role; 18 | import top.microiot.domain.User; 19 | import top.microiot.dto.DomainInfo; 20 | import top.microiot.dto.PageInfo; 21 | import top.microiot.dto.RegisterInfo; 22 | import top.microiot.dto.UserUpdateInfo; 23 | import top.microiot.exception.ConflictException; 24 | import top.microiot.exception.ValueException; 25 | import top.microiot.repository.ConfigRepository; 26 | import top.microiot.repository.FavoriteRepository; 27 | import top.microiot.repository.UserRepository; 28 | 29 | @Service 30 | public class UserService extends IoTService{ 31 | @Autowired 32 | private UserRepository userRepository; 33 | @Autowired 34 | private FavoriteRepository favoriteRepository; 35 | @Autowired 36 | private ConfigRepository configRepository; 37 | @Autowired 38 | private MOService moService; 39 | @Autowired 40 | private DomainService domainService; 41 | 42 | @Transactional 43 | public User addAdmin(String username, String password, String email ) { 44 | List roles = new ArrayList(); 45 | roles.add(Role.SYSTEM); 46 | 47 | User user = new User(username, password, email, roles); 48 | 49 | try{ 50 | userRepository.save(user); 51 | } catch (DuplicateKeyException e) { 52 | throw new ConflictException("user name:" + user.getUsername()); 53 | } 54 | 55 | return user; 56 | } 57 | 58 | @Transactional 59 | public User addUser(String username, String password, String email, List area) { 60 | List roles = new ArrayList(); 61 | roles.add(Role.AREA); 62 | List sites = getSites(area); 63 | 64 | User user = new User(username, password, email, roles, sites); 65 | 66 | try{ 67 | userRepository.save(user); 68 | } catch (DuplicateKeyException e) { 69 | throw new ConflictException("user name:" + username); 70 | } 71 | 72 | return user; 73 | } 74 | 75 | @Transactional 76 | public User register(RegisterInfo info) { 77 | DomainInfo d = new DomainInfo(); 78 | d.setName(info.getEmail()); 79 | Domain domain; 80 | try { 81 | domain = domainService.addDomain(d); 82 | } catch (ConflictException e) { 83 | throw new ValueException("email:" + info.getEmail() + " existed"); 84 | } 85 | 86 | List roles = new ArrayList(); 87 | roles.add(Role.AREA); 88 | List sites = new ArrayList(); 89 | sites.add(domain); 90 | 91 | User user = new User(info.getEmail(), info.getPassword(), info.getEmail(), roles, sites); 92 | 93 | try{ 94 | userRepository.save(user); 95 | } catch (DuplicateKeyException e) { 96 | throw new ConflictException("user name:" + info.getEmail()); 97 | } 98 | 99 | return user; 100 | } 101 | private List getSites(List areas) { 102 | if(areas == null || areas.isEmpty()) 103 | return null; 104 | List sites = new ArrayList(); 105 | 106 | for(int i = 0; i < areas.size(); i++) { 107 | String area = areas.get(i); 108 | 109 | ManagedObject a = moService.getLocation(area); 110 | 111 | for(int j = i+1; j < areas.size(); j++) { 112 | String location = areas.get(j); 113 | ManagedObject b = moService.getLocation(location); 114 | if (a.contain(b) || b.contain(a)) 115 | throw new ValueException("area: " + a.getString() + " area: " + b.getString() + " overlap"); 116 | } 117 | sites.add(a); 118 | } 119 | return sites; 120 | } 121 | 122 | @Transactional 123 | public User updateUser(@Valid UserUpdateInfo info) { 124 | User user = userRepository.findById(info.getUserId()).get(); 125 | if(!user.isArea()) 126 | throw new ValueException("user has no area role"); 127 | 128 | List sites = getSites(info.getArea()); 129 | user.setArea(sites); 130 | 131 | userRepository.save(user); 132 | return user; 133 | } 134 | 135 | @Transactional 136 | public void delete(String userId) { 137 | User user = userRepository.findById(userId).get(); 138 | User u = getCurrentUser(); 139 | 140 | if(user.getUsername().equals("admin")) 141 | throw new ValueException("admin can't be deleted"); 142 | 143 | if(user.getUsername().equals(u.getUsername())) 144 | throw new ValueException("can't delete self"); 145 | 146 | favoriteRepository.deleteByUserId(userId); 147 | configRepository.deleteByUserId(userId); 148 | userRepository.deleteById(userId); 149 | } 150 | 151 | public User listUser(String id){ 152 | User user = userRepository.findById(id).get(); 153 | return user; 154 | } 155 | 156 | public User listUserByUsername(String username) { 157 | return userRepository.findByUsername(username); 158 | } 159 | 160 | public User listCurrentUser(){ 161 | User user = getCurrentUser(); 162 | 163 | return user; 164 | } 165 | 166 | public Page listAll(PageInfo info){ 167 | Pageable pageable = getPageable(info); 168 | return userRepository.findAll(pageable); 169 | } 170 | 171 | @Transactional 172 | public User updatePassword(String password, String original) { 173 | User user = getCurrentUser(); 174 | 175 | // BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); 176 | // user.setPassword(encoder.encode(password)); 177 | if(user.getPassword().equals(original)) { 178 | user.setPassword(password); 179 | return userRepository.save(user); 180 | }else 181 | throw new ValueException("original password error"); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/SiteService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.dao.DuplicateKeyException; 9 | import org.springframework.data.domain.Page; 10 | import org.springframework.data.domain.Pageable; 11 | import org.springframework.security.access.AccessDeniedException; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import top.microiot.domain.Device; 16 | import top.microiot.domain.Domain; 17 | import top.microiot.domain.ManagedObject; 18 | import top.microiot.domain.Site; 19 | import top.microiot.domain.SiteType; 20 | import top.microiot.domain.User; 21 | import top.microiot.domain.attribute.AttValueInfo; 22 | import top.microiot.domain.attribute.AttributeValues; 23 | import top.microiot.domain.attribute.DataValue; 24 | import top.microiot.dto.SiteInfo; 25 | import top.microiot.dto.SitePageInfo; 26 | import top.microiot.dto.SiteRenameInfo; 27 | import top.microiot.dto.SiteUpdateInfo; 28 | import top.microiot.exception.ConflictException; 29 | import top.microiot.exception.NotFoundException; 30 | import top.microiot.exception.StatusException; 31 | import top.microiot.repository.AlarmRepository; 32 | import top.microiot.repository.ConfigRepository; 33 | import top.microiot.repository.DeviceRepository; 34 | import top.microiot.repository.EventRepository; 35 | import top.microiot.repository.FavoriteRepository; 36 | import top.microiot.repository.SiteRepository; 37 | import top.microiot.repository.SiteTypeRepository; 38 | 39 | @Service 40 | public class SiteService extends IoTService{ 41 | @Autowired 42 | private SiteTypeRepository siteTypeRepository; 43 | @Autowired 44 | private SiteRepository siteRepository; 45 | @Autowired 46 | private DeviceRepository deviceRepository; 47 | @Autowired 48 | private DeviceManageService deviceManageService; 49 | @Autowired 50 | private AlarmRepository alarmRepository; 51 | @Autowired 52 | private EventRepository eventRepository; 53 | @Autowired 54 | private FavoriteRepository favoriteRepository; 55 | @Autowired 56 | private ConfigRepository configRepository; 57 | @Autowired 58 | private MOService moService; 59 | 60 | @Transactional 61 | public Site add(SiteInfo info){ 62 | Domain domain = getCurrentDomain(); 63 | SiteType siteType = siteTypeRepository.findByNameAndDomain(info.getSiteType(), domain.getId()); 64 | if(siteType == null) 65 | throw new NotFoundException(info.getSiteType()); 66 | ManagedObject location = moService.getLocation1(info.getLocationId()); 67 | if(location == null || !location.getDomain().equals(domain)) 68 | throw new NotFoundException("location"); 69 | if(!moService.isMyMO(location)) 70 | throw new AccessDeniedException("location"); 71 | 72 | AttributeValues attributes = new AttributeValues(info.getAttInfos(), siteType.getAttDefinition()); 73 | Map attributeValues = attributes.getAttributes(); 74 | 75 | Site site = new Site(info.getName(), location, siteType, attributeValues); 76 | try{ 77 | return siteRepository.save(site); 78 | } catch (DuplicateKeyException e) { 79 | throw new ConflictException("site name"); 80 | } 81 | } 82 | 83 | @Transactional 84 | public Site rename(SiteRenameInfo info){ 85 | Site site = siteRepository.findById(info.getId()).get(); 86 | if(!moService.isMyMO(site)) 87 | throw new AccessDeniedException("device"); 88 | 89 | site.setName(info.getName()); 90 | try{ 91 | site = siteRepository.save(site); 92 | deviceManageService.reportAttributeChangedAlarm(site); 93 | 94 | return site; 95 | } catch (DuplicateKeyException e) { 96 | throw new ConflictException("site name"); 97 | } 98 | } 99 | 100 | @Transactional 101 | public Site update(SiteUpdateInfo info) { 102 | Site site = siteRepository.findById(info.getId()).get(); 103 | if(!moService.isMyMO(site)) 104 | throw new AccessDeniedException("device"); 105 | 106 | AttributeValues attributes = new AttributeValues(info.getAttInfos(), site.getSiteType().getAttDefinition()); 107 | Map attributeValues = attributes.getAttributes(); 108 | 109 | site.setAttributes(attributeValues); 110 | site = siteRepository.save(site); 111 | deviceManageService.reportAttributeChangedAlarm(site); 112 | 113 | return site; 114 | } 115 | 116 | @Transactional 117 | public void delete(String siteId) { 118 | Site site = siteRepository.findById(siteId).get(); 119 | if(!moService.isMyMO(site.getLocation())) 120 | throw new AccessDeniedException("device"); 121 | Domain domain = getCurrentDomain(); 122 | 123 | long n1 = siteRepository.countSite(siteId, domain.getId(), null, null); 124 | long n2 = deviceRepository.countDevice(siteId, domain.getId(), null, null); 125 | 126 | if((n1 + n2) > 0){ 127 | throw new StatusException("not empty in this site"); 128 | } 129 | 130 | moService.hasMOAccess(site); 131 | 132 | alarmRepository.deleteByNotifyObjectId(siteId); 133 | eventRepository.deleteByNotifyObjectId(siteId); 134 | favoriteRepository.deleteByMoId(siteId); 135 | configRepository.deleteByNotifyObjectId(siteId); 136 | siteRepository.deleteById(siteId); 137 | 138 | } 139 | 140 | public Site listSite(String id){ 141 | return siteRepository.findById(id).get(); 142 | } 143 | 144 | public Page listSite(SitePageInfo info){ 145 | Pageable pageable = getPageable(info); 146 | Domain domain = getCurrentDomain(); 147 | 148 | return siteRepository.querySite(info.getLocationId(), domain.getId(), info.getSiteTypeId(), info.getName(), pageable); 149 | } 150 | 151 | public long countSite(SitePageInfo info) { 152 | Domain domain = getCurrentDomain(); 153 | return siteRepository.countSite(info.getLocationId(), domain.getId(), info.getSiteTypeId(), info.getName()); 154 | } 155 | 156 | public List getMySites() { 157 | User user = getCurrentUser(); 158 | 159 | if(user.getArea() == null || user.getArea().isEmpty()) 160 | return null; 161 | 162 | List sites = new ArrayList(); 163 | for(ManagedObject site: user.getArea()) { 164 | if(!(site instanceof Device)) 165 | getSites(sites, site); 166 | } 167 | 168 | return sites; 169 | } 170 | 171 | private void getSites(List sites, ManagedObject site) { 172 | if(site instanceof Site) 173 | sites.add((Site)site); 174 | List ss = siteRepository.listSite(site.getId(), null, null, null); 175 | 176 | if(ss != null && !ss.isEmpty()) { 177 | for(Site s: ss) { 178 | getSites(sites, s); 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/TokenService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.dao.DuplicateKeyException; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.security.authentication.AuthenticationServiceException; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.stereotype.Service; 11 | 12 | import io.jsonwebtoken.Claims; 13 | import io.jsonwebtoken.Jws; 14 | import top.microiot.domain.Domain; 15 | import top.microiot.domain.LoginUser; 16 | import top.microiot.domain.Token; 17 | import top.microiot.domain.User; 18 | import top.microiot.dto.LoginInfo; 19 | import top.microiot.dto.LoginUserPageInfo; 20 | import top.microiot.exception.AuthenticationException; 21 | import top.microiot.exception.ConflictException; 22 | import top.microiot.exception.ValueException; 23 | import top.microiot.repository.DomainRepository; 24 | import top.microiot.repository.LoginUserRepository; 25 | import top.microiot.security.CustomUserDetails; 26 | import top.microiot.security.CustomUserService; 27 | import top.microiot.security.authentication.TokenFactory; 28 | 29 | @Service 30 | public class TokenService extends IoTService{ 31 | @Autowired 32 | private DomainService domainService; 33 | @Autowired 34 | private DomainRepository domainRepository; 35 | @Autowired 36 | private CustomUserService userService; 37 | @Autowired 38 | private TokenFactory tokenFactory; 39 | @Autowired 40 | private LoginUserRepository loginUserRepository; 41 | 42 | 43 | public Token login(LoginInfo info, String ip) { 44 | try{ 45 | CustomUserDetails user = (CustomUserDetails) userService.loadUserByUsername(info.getUsername()); 46 | if(info.getPassword().equals(user.getPassword())) { 47 | if(user.isDevice() && loginUserRepository.existLoginUserNotExpire(info.getUsername())) 48 | throw new AuthenticationException("device has login"); 49 | 50 | Token token = createToken((CustomUserDetails) user, info.getDomain()); 51 | loginUserRepository.removeLoginUserExpire(info.getUsername()); 52 | 53 | saveLoginUser(ip, token); 54 | return token; 55 | } 56 | else 57 | throw new AuthenticationException("Authentication Failed"); 58 | } catch (UsernameNotFoundException e) { 59 | throw new AuthenticationException("Authentication Failed"); 60 | } 61 | } 62 | 63 | private void saveLoginUser(String ip, Token token) { 64 | CustomUserDetails user = (CustomUserDetails) getUser(token.getToken()); 65 | LoginUser loginUser = new LoginUser(token.getToken(), token.getRefreshToken(), user.getUser().getUsername(), user.getUser().isDevice(), ip, tokenFactory.getExpire(token.getToken()), tokenFactory.getExpire(token.getRefreshToken())); 66 | 67 | try { 68 | loginUserRepository.save(loginUser); 69 | } catch (DuplicateKeyException e) { 70 | throw new ConflictException("same account login"); 71 | } 72 | } 73 | 74 | private Token createToken(CustomUserDetails u, String domain) { 75 | User user = u.getUser(); 76 | return createToken(domain, user); 77 | } 78 | 79 | public Token refreshToken(String tokenStr) { 80 | String token = extractToken(tokenStr); 81 | String jti = tokenFactory.getJti(token); 82 | if(jti == null) 83 | throw new ValueException("illegal token"); 84 | CustomUserDetails user = (CustomUserDetails) getUser(token); 85 | Token t; 86 | if(user.getDomain() == null) 87 | t = createToken(user, null); 88 | else 89 | t = createToken(user, user.getDomain().getName()); 90 | 91 | LoginUser loginUser = loginUserRepository.findByRefreshToken(token); 92 | updateLoginUser(loginUser, t); 93 | return t; 94 | } 95 | 96 | private void updateLoginUser(LoginUser loginUser, Token token) { 97 | if(loginUser != null) { 98 | loginUser.setToken(token.getToken()); 99 | loginUser.setRefreshToken(token.getRefreshToken()); 100 | loginUser.setExpire(tokenFactory.getExpire(token.getToken())); 101 | loginUser.setRefreshExpire(tokenFactory.getExpire(token.getRefreshToken())); 102 | 103 | loginUserRepository.save(loginUser); 104 | } 105 | } 106 | 107 | private Token createToken(String domain, User user) { 108 | if(domain != null && domain.length() > 0 && domainService.isMyDomain(domain, user)) 109 | return tokenFactory.createToken(user.getUsername(), domain); 110 | else if(domain == null || domain.length() == 0) 111 | return tokenFactory.createToken(user.getUsername(), null); 112 | else 113 | throw new ValueException(domain + " not exist or access denied."); 114 | } 115 | 116 | public Token updateToken(String domain, String tokenStr) { 117 | String token = extractToken(tokenStr); 118 | User user = this.getCurrentUser(); 119 | Token t = createToken(domain, user); 120 | 121 | LoginUser loginUser = loginUserRepository.findByToken(token); 122 | updateLoginUser(loginUser, t); 123 | return t; 124 | } 125 | 126 | public UserDetails getUser(String token) { 127 | Jws jwsClaims = tokenFactory.parseClaims(token); 128 | String username = tokenFactory.getUsername(jwsClaims); 129 | String domain =tokenFactory.getScope(jwsClaims); 130 | Domain d = null; 131 | if(domain != null) 132 | d = domainRepository.findByName(domain); 133 | 134 | CustomUserDetails user = (CustomUserDetails) userService.loadUserByUsername(username); 135 | user.setDomain(d); 136 | return user; 137 | } 138 | 139 | public UserDetails getCheckUser(String token) { 140 | UserDetails user = getUser(token); 141 | if(loginUserRepository.existsByToken(token)) 142 | return user; 143 | else 144 | throw new AuthenticationException(AuthenticationException.TOKEN_NOT_EXIST); 145 | } 146 | public String extractToken(String token) { 147 | if(token == null || token.length() == 0) 148 | throw new AuthenticationServiceException("Authorization header cannot be blank!"); 149 | if(!token.startsWith("Bearer")) 150 | throw new AuthenticationServiceException("Authorization header must start with Bearer!"); 151 | token = token.substring("Bearer ".length(), token.length()); 152 | return token; 153 | } 154 | 155 | public Page queryLoginUser(LoginUserPageInfo info){ 156 | Pageable pageable = getPageable(info); 157 | return loginUserRepository.queryLoginUser(info.getIsDevice(), info.getIsExpire(), pageable); 158 | } 159 | 160 | public void delete(String id) { 161 | LoginUser user = loginUserRepository.findById(id).get(); 162 | loginUserRepository.delete(user); 163 | } 164 | 165 | public LoginUser get(String id) { 166 | return loginUserRepository.findById(id).get(); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/controller/DeviceTypeController.java: -------------------------------------------------------------------------------- 1 | package top.microiot.controller; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.InputStreamReader; 7 | import java.io.Reader; 8 | import java.io.UnsupportedEncodingException; 9 | import java.util.List; 10 | 11 | import javax.servlet.http.HttpServletResponse; 12 | import javax.validation.Valid; 13 | 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.data.domain.Page; 16 | import org.springframework.http.HttpHeaders; 17 | import org.springframework.security.access.prepost.PreAuthorize; 18 | import org.springframework.validation.BindingResult; 19 | import org.springframework.web.bind.annotation.DeleteMapping; 20 | import org.springframework.web.bind.annotation.GetMapping; 21 | import org.springframework.web.bind.annotation.PatchMapping; 22 | import org.springframework.web.bind.annotation.PathVariable; 23 | import org.springframework.web.bind.annotation.PostMapping; 24 | import org.springframework.web.bind.annotation.RequestBody; 25 | import org.springframework.web.bind.annotation.RequestMapping; 26 | import org.springframework.web.bind.annotation.RequestParam; 27 | import org.springframework.web.bind.annotation.RestController; 28 | import org.springframework.web.multipart.MultipartFile; 29 | 30 | import com.fasterxml.jackson.databind.ObjectMapper; 31 | 32 | import top.microiot.domain.DeviceType; 33 | import top.microiot.domain.DeviceTypeFile; 34 | import top.microiot.domain.attribute.AttTypeInfo; 35 | import top.microiot.dto.ActionTypeInfo; 36 | import top.microiot.dto.DeviceTypeInfo; 37 | import top.microiot.dto.DeviceTypeRenameInfo; 38 | import top.microiot.dto.PageInfo; 39 | import top.microiot.exception.StatusException; 40 | import top.microiot.service.DeviceTypeService; 41 | 42 | @RestController 43 | @RequestMapping("/devicetypes") 44 | public class DeviceTypeController extends IoTController{ 45 | @Autowired 46 | private DeviceTypeService deviceTypeService; 47 | 48 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 49 | @PostMapping("") 50 | public DeviceType addDeviceType(@RequestBody @Valid DeviceTypeInfo info, BindingResult result) { 51 | throwError(result); 52 | return deviceTypeService.add(info); 53 | } 54 | 55 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 56 | @PostMapping("/import") 57 | public DeviceType importDeviceType(@RequestParam("file") MultipartFile file) { 58 | ObjectMapper mapper = new ObjectMapper(); 59 | try { 60 | InputStream inputStream = new BufferedInputStream(file.getInputStream()); 61 | Reader reader = new InputStreamReader(inputStream, "UTF-8"); 62 | DeviceTypeFile deviceType = mapper.readValue(reader, DeviceTypeFile.class); 63 | return deviceTypeService.add(deviceType); 64 | } catch (IOException e) { 65 | throw new StatusException(e.getMessage()); 66 | } 67 | } 68 | 69 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 70 | @GetMapping("/{id}") 71 | public DeviceType getDeviceType(@PathVariable String id) { 72 | return deviceTypeService.listDeviceType(id); 73 | } 74 | 75 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 76 | @GetMapping("/export/{id}") 77 | public void exportDeviceType(@PathVariable String id, HttpServletResponse response) throws UnsupportedEncodingException { 78 | DeviceType deviceType = deviceTypeService.listDeviceType(id); 79 | 80 | response.setContentType("text/json;charset=utf-8"); 81 | response.setHeader(HttpHeaders.CONTENT_DISPOSITION, 82 | "attachment; filename=devicetype.json"); 83 | 84 | DeviceTypeFile file = new DeviceTypeFile(deviceType); 85 | ObjectMapper mapper = new ObjectMapper(); 86 | 87 | try { 88 | mapper.writeValue(response.getWriter(), file); 89 | } catch (IOException e) { 90 | throw new StatusException(e.getMessage()); 91 | } 92 | } 93 | 94 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 95 | @GetMapping("/page") 96 | public Page getDeviceTypes( @Valid PageInfo info, BindingResult result){ 97 | throwError(result); 98 | return deviceTypeService.listDeviceType(info); 99 | } 100 | 101 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 102 | @GetMapping("/list") 103 | public List getDeviceTypesList(){ 104 | return deviceTypeService.listDeviceTypes(); 105 | } 106 | 107 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 108 | @PatchMapping("/name") 109 | public DeviceType updateDeviceType(@RequestBody @Valid DeviceTypeRenameInfo info, BindingResult result) { 110 | throwError(result); 111 | return deviceTypeService.rename(info); 112 | } 113 | 114 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 115 | @DeleteMapping("/{id}") 116 | public void deleteDeviceType(@PathVariable String id){ 117 | deviceTypeService.delete(id); 118 | } 119 | 120 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 121 | @PostMapping("/{id}/attribute") 122 | public DeviceType addAttribute(@PathVariable String id, @RequestBody @Valid AttTypeInfo info, BindingResult result) { 123 | throwError(result); 124 | return deviceTypeService.addAttribute(info, id); 125 | } 126 | 127 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 128 | @DeleteMapping("/{id}/attribute/{attribute}") 129 | public DeviceType delAttribute(@PathVariable String id, @PathVariable String attribute) { 130 | return deviceTypeService.delAttribute(attribute, id); 131 | } 132 | 133 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 134 | @PostMapping("/{id}/alarmtype") 135 | public DeviceType addAlarmType(@PathVariable String id, @RequestBody @Valid AttTypeInfo info, BindingResult result) { 136 | throwError(result); 137 | return deviceTypeService.addAlarmType(info, id); 138 | } 139 | 140 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 141 | @DeleteMapping("/{id}/alarmtype/{alarmtype}") 142 | public DeviceType delAlarmType(@PathVariable String id, @PathVariable String alarmtype) { 143 | return deviceTypeService.delAlarmType(alarmtype, id); 144 | } 145 | 146 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 147 | @PostMapping("/{id}/actiontype") 148 | public DeviceType addActionType(@PathVariable String id, @RequestBody @Valid ActionTypeInfo info, BindingResult result) { 149 | throwError(result); 150 | return deviceTypeService.addActionType(info, id); 151 | } 152 | 153 | @PreAuthorize("hasAuthority('SYSTEM') or hasAuthority('AREA')") 154 | @DeleteMapping("/{id}/actiontype/{actiontype}") 155 | public DeviceType delActionType(@PathVariable String id, @PathVariable String actiontype) { 156 | return deviceTypeService.delActionType(actiontype, id); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/web/WebsocketAuthorityInterceptor.java: -------------------------------------------------------------------------------- 1 | package top.microiot.web; 2 | 3 | import static org.springframework.http.HttpHeaders.AUTHORIZATION; 4 | 5 | import java.lang.reflect.Type; 6 | import java.security.Principal; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.core.ResolvableType; 12 | import org.springframework.messaging.Message; 13 | import org.springframework.messaging.MessageChannel; 14 | import org.springframework.messaging.converter.MappingJackson2MessageConverter; 15 | import org.springframework.messaging.converter.MessageConversionException; 16 | import org.springframework.messaging.converter.MessageConverter; 17 | import org.springframework.messaging.simp.stomp.StompCommand; 18 | import org.springframework.messaging.simp.stomp.StompHeaderAccessor; 19 | import org.springframework.messaging.support.ChannelInterceptor; 20 | import org.springframework.messaging.support.MessageHeaderAccessor; 21 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 22 | import org.springframework.security.core.Authentication; 23 | import org.springframework.security.core.userdetails.UserDetails; 24 | import org.springframework.stereotype.Component; 25 | 26 | import top.microiot.domain.Action; 27 | import top.microiot.domain.Device; 28 | import top.microiot.domain.Get; 29 | import top.microiot.domain.Request; 30 | import top.microiot.domain.Set; 31 | import top.microiot.domain.Topic; 32 | import top.microiot.domain.TopicType; 33 | import top.microiot.exception.StatusException; 34 | import top.microiot.security.CustomUserDetails; 35 | import top.microiot.service.DeviceGroupService; 36 | import top.microiot.service.DeviceService; 37 | import top.microiot.service.MOService; 38 | import top.microiot.service.TokenService; 39 | 40 | @Component 41 | public class WebsocketAuthorityInterceptor implements ChannelInterceptor { 42 | private Logger logger = LoggerFactory.getLogger(this.getClass()); 43 | 44 | @Autowired 45 | private DeviceService deviceService; 46 | @Autowired 47 | private DeviceGroupService deviceGroupService; 48 | @Autowired 49 | private MOService moService; 50 | @Autowired 51 | private TokenService tokenService; 52 | 53 | @Override 54 | public Message preSend(Message message, MessageChannel channel) { 55 | MyStompHeaderAccessor headerAccessor = new MyStompHeaderAccessor(message); 56 | if(StompCommand.CONNECT.equals(headerAccessor.getCommand())) { 57 | StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); 58 | String token = accessor.getFirstNativeHeader(AUTHORIZATION); 59 | UserDetails user = tokenService.getUser(tokenService.extractToken(token)); 60 | UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); 61 | accessor.setUser(userToken); 62 | } 63 | else if (StompCommand.SUBSCRIBE.equals(headerAccessor.getCommand())) { 64 | Principal userPrincipal = headerAccessor.getUser(); 65 | if (userPrincipal == null) { 66 | throw new IllegalArgumentException( 67 | "anonymous not allowed for this subscribe: " + headerAccessor.getDestination()); 68 | } 69 | CustomUserDetails user = (CustomUserDetails) ((Authentication) userPrincipal).getPrincipal(); 70 | 71 | if (!validateSubscription(user, headerAccessor.getDestination())) { 72 | throw new StatusException("user: " + user.getUsername() + " no permission for this subscribe: " 73 | + headerAccessor.getDestination()); 74 | } 75 | } else if (StompCommand.SEND.equals(headerAccessor.getCommand())) { 76 | Principal userPrincipal = headerAccessor.getUser(); 77 | if (userPrincipal == null) { 78 | throw new StatusException( 79 | "anonymous not allowed to send to: " + headerAccessor.getDestination()); 80 | } 81 | CustomUserDetails user = (CustomUserDetails) ((Authentication) userPrincipal).getPrincipal(); 82 | 83 | if (!validateSend(user, headerAccessor.getDestination())) { 84 | throw new StatusException("user: " + user.getUsername() + " no permission to send to: " 85 | + headerAccessor.getDestination()); 86 | } 87 | Topic topic = new Topic(headerAccessor.getDestination()); 88 | 89 | TopicType type = topic.getType(); 90 | 91 | if(type == TopicType.Operation) { 92 | TopicType operation = topic.getOperationType(); 93 | Type payloadType = null; 94 | if(operation == TopicType.GET) 95 | payloadType= Get.class; 96 | else if(operation == TopicType.SET) 97 | payloadType= Set.class; 98 | else if(operation == TopicType.ACTION) 99 | payloadType= Action.class; 100 | 101 | Class resolvedType = ResolvableType.forType(payloadType).resolve(); 102 | if (resolvedType == null) { 103 | throw new MessageConversionException("Unresolvable payload type [" + payloadType ); 104 | } 105 | MessageConverter converter = new MappingJackson2MessageConverter(); 106 | Request request = (Request) converter.fromMessage(message, resolvedType); 107 | request.setRequester(user.getUser()); 108 | headerAccessor.updateSimpMessageHeadersFromStompHeaders(); 109 | headerAccessor.setLeaveMutable(true); 110 | message = converter.toMessage(request, headerAccessor.getMessageHeaders()); 111 | headerAccessor.updateStompHeadersFromSimpMessageHeaders(); 112 | } 113 | 114 | } 115 | return message; 116 | } 117 | 118 | private boolean validateSubscription(CustomUserDetails user, String topicDestination) { 119 | logger.debug("user: " + user.getUsername() + " subscribe topic: " + topicDestination); 120 | Topic topic = new Topic(topicDestination); 121 | 122 | TopicType type = topic.getType(); 123 | switch(type) { 124 | case Alarm: 125 | if(user.getUser().isArea() && (isMyTopic(topic))) 126 | return true; 127 | else if(user.getUser().isSystem()) 128 | return true; 129 | else if(user.getUser().isDevice() && (isGroup(topic))) 130 | return true; 131 | else 132 | return false; 133 | case Result: 134 | if (user.getUser().isArea() && isMyTopic(topic)) 135 | return true; 136 | else if(user.getUser().isSystem()) 137 | return true; 138 | else if(user.getUser().isDevice() && (isGroup(topic))) 139 | return true; 140 | else 141 | return false; 142 | case Operation: 143 | if(user.getUser().isDevice() && isDeviceTopic(user, topic)) 144 | return true; 145 | else 146 | return false; 147 | default: 148 | return false; 149 | } 150 | } 151 | 152 | private boolean isGroup(Topic topic) { 153 | String deviceId = topic.getNotifyObjectId(); 154 | 155 | return deviceGroupService.isGroup(deviceId); 156 | } 157 | 158 | private boolean isMyTopic(Topic topic) { 159 | return moService.isMyMO(topic.getNotifyObjectId()); 160 | } 161 | 162 | private boolean isDeviceTopic(CustomUserDetails user, Topic topic) { 163 | Device device = deviceService.listCurrentDevice(); 164 | return device.getId().equals(topic.getNotifyObjectId()) || deviceService.isChild(topic.getNotifyObjectId()); 165 | } 166 | 167 | private boolean validateSend(CustomUserDetails user, String topicDestination) { 168 | logger.debug("user: " + user.getUsername() + " send to topic: " + topicDestination); 169 | Topic topic = new Topic(topicDestination); 170 | 171 | TopicType type = topic.getType(); 172 | switch(type) { 173 | case Alarm: 174 | if (user.getUser().isDevice() && isDeviceTopic(user, topic)) 175 | return true; 176 | else 177 | return false; 178 | case Result: 179 | if (user.getUser().isDevice() && isDeviceTopic(user, topic)) 180 | return true; 181 | else 182 | return false; 183 | case Operation: 184 | if(user.getUser().isArea() && isMyTopic(topic)) 185 | return true; 186 | else if(user.getUser().isSystem() ) 187 | return true; 188 | else if (user.getUser().isDevice() && (isGroup(topic))) 189 | return true; 190 | else 191 | return false; 192 | default: 193 | return false; 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/main/java/top/microiot/service/DeviceManageService.java: -------------------------------------------------------------------------------- 1 | package top.microiot.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.UUID; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.messaging.simp.SimpMessagingTemplate; 11 | import org.springframework.security.access.AccessDeniedException; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import top.microiot.domain.Alarm; 16 | import top.microiot.domain.AlarmType; 17 | import top.microiot.domain.Device; 18 | import top.microiot.domain.DeviceType; 19 | import top.microiot.domain.Domain; 20 | import top.microiot.domain.ManagedObject; 21 | import top.microiot.domain.Role; 22 | import top.microiot.domain.Topic; 23 | import top.microiot.domain.User; 24 | import top.microiot.domain.attribute.AttValueInfo; 25 | import top.microiot.domain.attribute.AttributeValues; 26 | import top.microiot.domain.attribute.DataValue; 27 | import top.microiot.dto.DeviceInfo; 28 | import top.microiot.dto.DeviceMoveInfo; 29 | import top.microiot.dto.DeviceRenameInfo; 30 | import top.microiot.dto.DeviceUpdateInfo; 31 | import top.microiot.dto.SubDeviceInfo; 32 | import top.microiot.exception.NotFoundException; 33 | import top.microiot.exception.ValueException; 34 | import top.microiot.repository.AlarmRepository; 35 | import top.microiot.repository.ConfigRepository; 36 | import top.microiot.repository.DeviceRepository; 37 | import top.microiot.repository.DeviceTypeRepository; 38 | import top.microiot.repository.EventRepository; 39 | import top.microiot.repository.FavoriteRepository; 40 | import top.microiot.repository.LoginUserRepository; 41 | 42 | @Service 43 | public class DeviceManageService extends IoTService{ 44 | @Autowired 45 | private DeviceRepository deviceRepository; 46 | @Autowired 47 | private DeviceTypeRepository typeRepository; 48 | @Autowired 49 | private SimpMessagingTemplate template; 50 | @Autowired 51 | private AlarmRepository alarmRepository; 52 | @Autowired 53 | private EventRepository eventRepository; 54 | @Autowired 55 | private FavoriteRepository favoriteRepository; 56 | @Autowired 57 | private ConfigRepository configRepository; 58 | @Autowired 59 | private LoginUserRepository loginUserRepository; 60 | @Autowired 61 | private MOService moService; 62 | 63 | @Transactional 64 | public Device register(DeviceInfo info) { 65 | Domain domain = getCurrentDomain(); 66 | DeviceType type = typeRepository.findByNameAndDomain(info.getDeviceType(), domain.getId()); 67 | if(type == null) 68 | throw new NotFoundException("device type"); 69 | 70 | ManagedObject location = moService.getLocation1(info.getLocationId()); 71 | if(location == null || !location.getDomain().equals(domain)) 72 | throw new NotFoundException("location"); 73 | if(!moService.isMyMO(location)) 74 | throw new AccessDeniedException(info.getLocationId()); 75 | 76 | return doRegister(info.getName(), type, info.getAttInfos(), location); 77 | } 78 | 79 | private Device doRegister(String name, DeviceType type, Map attValueInfos, ManagedObject location) { 80 | AttributeValues attributes = new AttributeValues(attValueInfos, type.getStaticAttDefinition()); 81 | Map attributeValues = attributes.getAttributes(); 82 | 83 | User user = getAccount(); 84 | user.setShowPassword(true); 85 | 86 | Device device = new Device(name, type, attributeValues, location, user); 87 | 88 | return deviceRepository.save(device); 89 | } 90 | 91 | @Transactional 92 | public Device register(SubDeviceInfo info) { 93 | Domain domain = getCurrentDomain(); 94 | DeviceType type = typeRepository.findByNameAndDomain(info.getDeviceType(), domain.getId()); 95 | if(type == null) 96 | throw new NotFoundException("device type"); 97 | 98 | ManagedObject location = moService.getLocation1(info.getLocationId()); 99 | if(location == null || !location.getDomain().equals(domain)) 100 | throw new NotFoundException("location"); 101 | if(!moService.isMyMO(location)) 102 | throw new AccessDeniedException(info.getLocationId()); 103 | 104 | Device gateway = deviceRepository.findById(info.getGatewayId()).get(); 105 | if(!gateway.getDomain().getId().equals(domain.getId())) 106 | throw new ValueException("gateway value error"); 107 | if(gateway.getDeviceAccount() == null) 108 | throw new ValueException("gateway has no account"); 109 | 110 | return doRegister(info.getName(), type, info.getAttInfos(), location, gateway); 111 | } 112 | 113 | private Device doRegister(String name, DeviceType type, Map attValueInfos, ManagedObject location, Device gateway) { 114 | AttributeValues attributes = new AttributeValues(attValueInfos, type.getStaticAttDefinition()); 115 | Map attributeValues = attributes.getAttributes(); 116 | 117 | Device device = new Device(name, type, attributeValues, location, gateway); 118 | 119 | return deviceRepository.save(device); 120 | } 121 | 122 | private User getAccount() { 123 | UUID id = UUID.randomUUID(); 124 | String password = String.valueOf((int)((Math.random()*9+1)*10000000)); 125 | 126 | List roles = new ArrayList(); 127 | 128 | roles.add(Role.DEVICE); 129 | 130 | User user = new User(id.toString(), password, null, roles); 131 | return user; 132 | } 133 | 134 | @Transactional 135 | public Device updateDevice(DeviceUpdateInfo info) { 136 | Device device = deviceRepository.findById(info.getId()).get(); 137 | 138 | if(!moService.isMyMO(device)) 139 | throw new AccessDeniedException("device"); 140 | 141 | Map attributeValues = null; 142 | if(device.getDeviceType().getStaticAttDefinition() != null && info.getAttInfos() != null) { 143 | AttributeValues attributes = new AttributeValues(info.getAttInfos(), device.getDeviceType().getStaticAttDefinition()); 144 | attributeValues = attributes.getAttributes(); 145 | } 146 | 147 | device.setAttributes(attributeValues); 148 | device = deviceRepository.save(device); 149 | reportAttributeChangedAlarm(device); 150 | 151 | return device; 152 | } 153 | 154 | public void reportAttributeChangedAlarm(ManagedObject notifyObject) { 155 | Alarm alarm = new Alarm(notifyObject, AlarmType.ATTRIBUTE_CHANGED_ALARM, null, new Date()); 156 | alarm = alarmRepository.save(alarm); 157 | String destination = Topic.TOPIC_ALARM + notifyObject.getId(); 158 | template.convertAndSend(destination, alarm); 159 | } 160 | 161 | @Transactional 162 | public Device moveDevice(DeviceMoveInfo info) { 163 | Device device = deviceRepository.findById(info.getId()).get(); 164 | 165 | if(!moService.isMyMO(device)) 166 | throw new AccessDeniedException("device"); 167 | 168 | ManagedObject site = moService.getLocation1(info.getLocationId()); 169 | 170 | if(!moService.isMyMO(site)) 171 | throw new AccessDeniedException("site moved to is not in my area"); 172 | 173 | device.setLocation(site); 174 | device = deviceRepository.save(device); 175 | reportAttributeChangedAlarm(device); 176 | return device; 177 | } 178 | 179 | @Transactional 180 | public Device renameDevice(DeviceRenameInfo info){ 181 | Device device = deviceRepository.findById(info.getId()).get(); 182 | 183 | if(!moService.isMyMO(device)) 184 | throw new AccessDeniedException("device"); 185 | 186 | device.setName(info.getName()); 187 | device = deviceRepository.save(device); 188 | reportAttributeChangedAlarm(device); 189 | 190 | return device; 191 | } 192 | 193 | @Transactional 194 | public void delete(String deviceId) { 195 | Device device = deviceRepository.findById(deviceId).get(); 196 | if(!moService.isMyMO(device.getLocation())) 197 | throw new AccessDeniedException("device"); 198 | moService.hasMOAccess(device); 199 | 200 | alarmRepository.deleteByNotifyObjectId(deviceId); 201 | eventRepository.deleteByNotifyObjectId(deviceId); 202 | favoriteRepository.deleteByMoId(deviceId); 203 | configRepository.deleteByNotifyObjectId(deviceId); 204 | deviceRepository.deleteById(deviceId); 205 | loginUserRepository.deleteByUsername(device.getDeviceAccount().getUsername()); 206 | } 207 | } 208 | --------------------------------------------------------------------------------