├── .env.example ├── .github ├── dependabot.yml └── workflows │ └── test-and-release.yaml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── amd64.openj9.Dockerfile ├── database.env.example ├── docker-compose.dockerhub.yml ├── docker-compose.yml ├── pom.xml ├── src ├── main │ ├── java │ │ └── com │ │ │ └── bompotis │ │ │ └── netcheck │ │ │ ├── NetcheckApplication.java │ │ │ ├── api │ │ │ ├── controller │ │ │ │ ├── AbstractStreamController.java │ │ │ │ ├── CheckController.java │ │ │ │ ├── DomainsController.java │ │ │ │ ├── NotificationTestController.java │ │ │ │ ├── ServerController.java │ │ │ │ └── StreamController.java │ │ │ ├── exception │ │ │ │ ├── ControllerAdvisor.java │ │ │ │ ├── EntityNotFoundException.java │ │ │ │ ├── InvalidAuthHeaders.java │ │ │ │ └── UnauthorizedStatusException.java │ │ │ ├── model │ │ │ │ ├── CertificateModel.java │ │ │ │ ├── DomainCheckModel.java │ │ │ │ ├── DomainRequest.java │ │ │ │ ├── DomainResponse.java │ │ │ │ ├── HttpCheckModel.java │ │ │ │ ├── MetricModel.java │ │ │ │ ├── PatchOperation.java │ │ │ │ ├── RegisterServerRequest.java │ │ │ │ ├── ServerDefinitionModel.java │ │ │ │ ├── ServerMetricModel.java │ │ │ │ ├── ServerMetricRequest.java │ │ │ │ ├── ServerModel.java │ │ │ │ ├── StateModel.java │ │ │ │ └── assembler │ │ │ │ │ ├── AbstractUpdateDtoAssembler.java │ │ │ │ │ ├── CertificateModelAssembler.java │ │ │ │ │ ├── DomainCheckModelAssembler.java │ │ │ │ │ ├── DomainModelAssembler.java │ │ │ │ │ ├── DomainUpdateDtoAssembler.java │ │ │ │ │ ├── HttpCheckModelAssembler.java │ │ │ │ │ ├── MetricModelAssembler.java │ │ │ │ │ ├── PaginatedRepresentationModelAssemblerSupport.java │ │ │ │ │ ├── ServerDefinitionAssembler.java │ │ │ │ │ ├── ServerMetricModelAssembler.java │ │ │ │ │ ├── ServerModelAssembler.java │ │ │ │ │ ├── ServerUpdateDtoAssembler.java │ │ │ │ │ └── StateModelAssembler.java │ │ │ └── security │ │ │ │ └── WebSecurityConfig.java │ │ │ ├── data │ │ │ ├── entity │ │ │ │ ├── AbstractTimestampable.java │ │ │ │ ├── AbstractTimestampablePersistable.java │ │ │ │ ├── CertificateEntity.java │ │ │ │ ├── DomainCheckEntity.java │ │ │ │ ├── DomainEntity.java │ │ │ │ ├── DomainMetricEntity.java │ │ │ │ ├── EntityBuilder.java │ │ │ │ ├── OperationUpdater.java │ │ │ │ ├── ProtocolCheckEntity.java │ │ │ │ ├── ServerEntity.java │ │ │ │ ├── ServerMetricDefinitionEntity.java │ │ │ │ └── ServerMetricEntity.java │ │ │ └── repository │ │ │ │ ├── DomainCheckRepository.java │ │ │ │ ├── DomainMetricRepository.java │ │ │ │ ├── DomainRepository.java │ │ │ │ ├── ServerMetricDefinitionRepository.java │ │ │ │ ├── ServerMetricRepository.java │ │ │ │ └── ServerRepository.java │ │ │ ├── scheduler │ │ │ ├── batch │ │ │ │ ├── BatchConfiguration.java │ │ │ │ ├── JobCompletionNotificationListener.java │ │ │ │ ├── notification │ │ │ │ │ ├── CheckEventDto.java │ │ │ │ │ ├── EventDto.java │ │ │ │ │ ├── NotificationDto.java │ │ │ │ │ ├── NotificationEventDto.java │ │ │ │ │ ├── NotificationEventService.java │ │ │ │ │ ├── NotificationService.java │ │ │ │ │ ├── PushoverService.java │ │ │ │ │ ├── ServerMetricEventDto.java │ │ │ │ │ ├── WebhookService.java │ │ │ │ │ ├── client │ │ │ │ │ │ ├── MessagePriority.java │ │ │ │ │ │ ├── PushoverMessage.java │ │ │ │ │ │ └── PushoverRestClient.java │ │ │ │ │ └── config │ │ │ │ │ │ ├── PushoverConfig.java │ │ │ │ │ │ └── WebhookConfig.java │ │ │ │ ├── processor │ │ │ │ │ ├── DomainCheckProcessor.java │ │ │ │ │ └── DomainMetricProcessor.java │ │ │ │ ├── reader │ │ │ │ │ └── OldDomainCheckItemReader.java │ │ │ │ └── writer │ │ │ │ │ ├── AbstractNotificationWriter.java │ │ │ │ │ ├── CheckEventItemWriter.java │ │ │ │ │ ├── DomainMetricListWriter.java │ │ │ │ │ └── NotificationItemWriter.java │ │ │ └── task │ │ │ │ └── CheckDomainTask.java │ │ │ └── service │ │ │ ├── AbstractService.java │ │ │ ├── DomainService.java │ │ │ ├── MetricService.java │ │ │ ├── ServerMetricsService.java │ │ │ └── dto │ │ │ ├── AbstractHttpChecker.java │ │ │ ├── AbstractPaginatedDto.java │ │ │ ├── CertificateDetailsDto.java │ │ │ ├── DomainCheckConfigDto.java │ │ │ ├── DomainCheckDto.java │ │ │ ├── DomainDto.java │ │ │ ├── DomainUpdateDto.java │ │ │ ├── DomainsOptionsDto.java │ │ │ ├── DtoBuilder.java │ │ │ ├── HttpCheckDto.java │ │ │ ├── HttpsCheckDto.java │ │ │ ├── MetricDto.java │ │ │ ├── Operation.java │ │ │ ├── PaginatedDto.java │ │ │ ├── PatchDtoBuilder.java │ │ │ ├── RequestOptionsDto.java │ │ │ ├── ServerDefinitionDto.java │ │ │ ├── ServerDto.java │ │ │ ├── ServerMetricDto.java │ │ │ ├── ServerUpdateDto.java │ │ │ └── StateDto.java │ └── resources │ │ ├── META-INF │ │ └── additional-spring-configuration-metadata.json │ │ ├── application.yaml │ │ ├── banner.txt │ │ └── db │ │ └── migration │ │ ├── V1_0_0__init_schema.sql │ │ ├── V1_1_0__init_spring_batch.sql │ │ ├── V1_2_0__add_domain_endpoint_column.sql │ │ ├── V1_3_0__add_domain_headers_column.sql │ │ ├── V1_3_1__add_domain_timeout_column.sql │ │ ├── V1_3_2__update_new_fields_to_defaults.sql │ │ ├── V1_4_0__add_server_tables.sql │ │ └── V1_5_0__spring_batch_5_migration.sql └── test │ ├── java │ └── com │ │ └── bompotis │ │ └── netcheck │ │ ├── NetcheckApplicationStartupTests.java │ │ └── api │ │ └── controller │ │ ├── CheckControllerTests.java │ │ └── DomainsControllerTests.java │ └── resources │ └── application.yaml ├── test-depedancies.docker-compose.yml ├── traefik.docker-compose.yml └── version.txt /.env.example: -------------------------------------------------------------------------------- 1 | POSTGRES_HOST=db 2 | POSTGRES_PORT=5432 3 | SETTINGS_NOTIFICATIONS_PUSHOVER_ENABLED=false 4 | SETTINGS_NOTIFICATIONS_PUSHOVER_APITOKEN= 5 | SETTINGS_NOTIFICATIONS_PUSHOVER_USERIDTOKEN= -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: maven 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "11:00" 8 | open-pull-requests-limit: 10 9 | ignore: 10 | - dependency-name: org.flywaydb:flyway-core 11 | versions: 12 | - 7.5.2 13 | - 7.5.3 14 | - 7.5.4 15 | - 7.7.0 16 | - 7.7.1 17 | - 7.7.2 18 | - 7.7.3 19 | - 7.8.0 20 | - 7.8.1 21 | - dependency-name: org.springdoc:springdoc-openapi-hateoas 22 | versions: 23 | - 1.5.3 24 | - 1.5.4 25 | - 1.5.6 26 | - 1.5.7 27 | - dependency-name: org.springdoc:springdoc-openapi-data-rest 28 | versions: 29 | - 1.5.3 30 | - 1.5.4 31 | - 1.5.6 32 | - 1.5.7 33 | - dependency-name: org.springdoc:springdoc-openapi-ui 34 | versions: 35 | - 1.5.3 36 | - 1.5.4 37 | - 1.5.6 38 | - 1.5.7 39 | - dependency-name: org.springframework.boot:spring-boot-starter-parent 40 | versions: 41 | - 2.4.4 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | database.env 3 | .env 4 | target/ 5 | !.mvn/wrapper/maven-wrapper.jar 6 | !**/src/main/** 7 | !**/src/test/** 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | .sts4-cache 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ${ARCH}eclipse-temurin:17 2 | WORKDIR /var/app/netcheck/ 3 | COPY ./target/netcheck.jar ./netcheck.jar 4 | RUN addgroup --system netcheck && adduser --no-create-home --gecos '' --ingroup netcheck --disabled-password netcheck 5 | USER netcheck 6 | VOLUME /tmp 7 | EXPOSE 8080 8081 8 | ENTRYPOINT ["java", "-Dhibernate.types.print.banner=false", "-noverify", "-jar", "/var/app/netcheck/netcheck.jar"] 9 | HEALTHCHECK --interval=60s --timeout=10s --retries=3 CMD curl -sSL "http://localhost:8080/api/v1/actuator/health" || exit 1 -------------------------------------------------------------------------------- /amd64.openj9.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ibm-semeru-runtimes:open-17-jre 2 | WORKDIR /var/app/netcheck/ 3 | COPY ./target/netcheck.jar ./netcheck.jar 4 | RUN addgroup --system netcheck && adduser --no-create-home --gecos '' --ingroup netcheck --disabled-password netcheck 5 | USER netcheck 6 | VOLUME /tmp 7 | EXPOSE 8080 8081 8 | ENTRYPOINT ["java", "-Dhibernate.types.print.banner=false", "-noverify", "-jar", "/var/app/netcheck/netcheck.jar"] 9 | HEALTHCHECK --interval=60s --timeout=10s --retries=3 CMD curl -sSL "http://localhost:8080/api/v1/actuator/health" || exit 1 -------------------------------------------------------------------------------- /database.env.example: -------------------------------------------------------------------------------- 1 | POSTGRES_USER=netcheck 2 | POSTGRES_PASSWORD=netcheck 3 | POSTGRES_DB=netcheck -------------------------------------------------------------------------------- /docker-compose.dockerhub.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | 5 | netcheck-backend: 6 | container_name: netcheck-backend 7 | env_file: 8 | - database.env 9 | - .env 10 | depends_on: 11 | - db 12 | image: memphisx/netcheck-api:latest 13 | ports: 14 | - "8080:8080" 15 | - "8081:8081" 16 | 17 | db: 18 | image: postgres 19 | env_file: 20 | - database.env 21 | volumes: 22 | - db-data:/var/lib/postgresql/data 23 | ports: 24 | - "4000:5432" 25 | 26 | volumes: 27 | db-data: 28 | driver: local -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | 5 | netcheck-backend: 6 | container_name: netcheck-backend 7 | env_file: 8 | - database.env 9 | - .env 10 | depends_on: 11 | - db 12 | build: 13 | context: ./ 14 | dockerfile: ./amd64.openj9.Dockerfile 15 | ports: 16 | - "8080:8080" 17 | - "8081:8081" 18 | 19 | db: 20 | image: postgres 21 | env_file: 22 | - database.env 23 | volumes: 24 | - db-data:/var/lib/postgresql/data 25 | ports: 26 | - "4000:5432" 27 | 28 | volumes: 29 | db-data: 30 | driver: local -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/NetcheckApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck; 19 | 20 | import com.bompotis.netcheck.scheduler.batch.notification.config.PushoverConfig; 21 | import com.bompotis.netcheck.scheduler.batch.notification.config.WebhookConfig; 22 | import io.swagger.v3.oas.annotations.OpenAPIDefinition; 23 | import io.swagger.v3.oas.annotations.info.Contact; 24 | import io.swagger.v3.oas.annotations.info.Info; 25 | import io.swagger.v3.oas.annotations.info.License; 26 | import org.springframework.boot.SpringApplication; 27 | import org.springframework.boot.autoconfigure.SpringBootApplication; 28 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 29 | import org.springframework.context.annotation.PropertySource; 30 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 31 | import org.springframework.scheduling.annotation.EnableScheduling; 32 | 33 | @OpenAPIDefinition(info = 34 | @Info( 35 | title = "${info.app.name}", 36 | version = "${build.version}", 37 | description = "${info.app.description}", 38 | license = @License(name = "GPL 3.0", url = "https://www.gnu.org/licenses/gpl-3.0.en.html"), 39 | contact = @Contact(url = "https://github.com/memphisx", name = "Kyriakos Bompotis") 40 | ) 41 | ) 42 | @SpringBootApplication 43 | @EnableJpaRepositories 44 | @EnableScheduling 45 | @EnableConfigurationProperties({PushoverConfig.class, WebhookConfig.class}) 46 | @PropertySource(value="classpath:META-INF/build-info.properties", ignoreResourceNotFound=true) 47 | public class NetcheckApplication { 48 | 49 | public static void main(String[] args) { 50 | SpringApplication.run(NetcheckApplication.class, args); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/controller/AbstractStreamController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.controller; 19 | 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 23 | 24 | import java.io.IOException; 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | import java.util.concurrent.CopyOnWriteArrayList; 28 | 29 | /** 30 | * Created by Kyriakos Bompotis on 26/8/20. 31 | */ 32 | public abstract class AbstractStreamController { 33 | private static final Logger logger = LoggerFactory.getLogger(AbstractStreamController.class); 34 | 35 | private final List emitters = new CopyOnWriteArrayList<>(); 36 | 37 | protected SseEmitter addSseEmitter() { 38 | return addSseEmitter(new SseEmitter(0L)); 39 | } 40 | 41 | protected SseEmitter addSseEmitter(SseEmitter emitter) { 42 | this.emitters.add(emitter); 43 | 44 | emitter.onCompletion(() -> { 45 | logger.info("Emitter completed: {}", emitter); 46 | this.emitters.remove(emitter); 47 | }); 48 | emitter.onTimeout(() -> { 49 | logger.info("Emitter timed out: {}", emitter); 50 | emitter.complete(); 51 | this.emitters.remove(emitter); 52 | }); 53 | 54 | return emitter; 55 | } 56 | 57 | protected void sendToSseEmitter(SseEmitter.SseEventBuilder builder) { 58 | send(emitter -> emitter.send(builder)); 59 | } 60 | 61 | protected void send(SseEmitterConsumer consumer) { 62 | List failedEmitters = new ArrayList<>(); 63 | 64 | this.emitters.forEach(emitter -> { 65 | try { 66 | consumer.accept(emitter); 67 | } catch (IOException e) { 68 | emitter.completeWithError(e); 69 | failedEmitters.add(emitter); 70 | logger.error("Emitter failed: {} - {}", emitter, e.getMessage()); 71 | } catch (Exception e) { 72 | emitter.completeWithError(e); 73 | failedEmitters.add(emitter); 74 | logger.error("Emitter failed: {}", emitter, e); 75 | } 76 | }); 77 | 78 | this.emitters.removeAll(failedEmitters); 79 | } 80 | 81 | @FunctionalInterface 82 | protected interface SseEmitterConsumer { 83 | void accept(T t) throws IOException; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/controller/NotificationTestController.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.api.controller; 2 | 3 | import com.bompotis.netcheck.api.model.DomainCheckModel; 4 | import com.bompotis.netcheck.scheduler.batch.notification.NotificationDto; 5 | import com.bompotis.netcheck.scheduler.batch.notification.NotificationService; 6 | import io.swagger.v3.oas.annotations.Operation; 7 | import io.swagger.v3.oas.annotations.media.Content; 8 | import io.swagger.v3.oas.annotations.responses.ApiResponse; 9 | import io.swagger.v3.oas.annotations.responses.ApiResponses; 10 | import io.swagger.v3.oas.annotations.tags.Tag; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.http.ResponseEntity; 13 | import org.springframework.web.bind.annotation.*; 14 | 15 | import java.util.ArrayList; 16 | import java.util.Date; 17 | import java.util.List; 18 | import java.util.Optional; 19 | 20 | import static org.springframework.http.ResponseEntity.*; 21 | 22 | @RestController 23 | @CrossOrigin(origins = {"${settings.cors.origin}"}) 24 | @RequestMapping(value = "/api/v1/notification") 25 | @Tag(name = "Notification Test", description = "Operations for testing notification providers") 26 | public class NotificationTestController { 27 | 28 | private final List notificationServices; 29 | 30 | @Autowired 31 | public NotificationTestController(List notificationServices) { 32 | this.notificationServices = notificationServices; 33 | } 34 | 35 | @Operation(summary = "Get available notification services") 36 | @GetMapping(produces={"application/hal+json"}) 37 | public ResponseEntity> getNotificationServices() { 38 | var services = new ArrayList<>(notificationServices.stream().map(NotificationService::name).toList()); 39 | return ok(services); 40 | } 41 | 42 | @Operation(summary = "Send test notification to service") 43 | @ApiResponses(value = { 44 | @ApiResponse(responseCode = "200", description = "Test Notification successfully sent"), 45 | @ApiResponse(responseCode = "400", description = "Notification service is disabled", content = @Content), 46 | @ApiResponse(responseCode = "404", description = "Notification service not found", content = @Content)}) 47 | @PostMapping(produces={"application/hal+json"}, path = "/{notificationServiceName}") 48 | public ResponseEntity sendTestNotificationTo( 49 | @PathVariable("notificationServiceName") String notificationServiceName 50 | ) throws Exception { 51 | Optional foundService = Optional.empty(); 52 | for (var service: notificationServices) { 53 | if (service.name().equals(notificationServiceName)) { 54 | foundService = Optional.of(service); 55 | break; 56 | } 57 | } 58 | if (foundService.isEmpty()) { 59 | return notFound().build(); 60 | } 61 | var notificationService = foundService.get(); 62 | if (!notificationService.isEnabled()) { 63 | return badRequest().build(); 64 | } 65 | notificationService.notify(new NotificationDto.Builder() 66 | .hostname("test") 67 | .connectionAccepted(true) 68 | .dnsResolves(true) 69 | .ipAddress("0.0.0.0") 70 | .redirectUri("") 71 | .responseTimeNs(0L) 72 | .statusCode(200) 73 | .timeCheckedOn(new Date()) 74 | .type(NotificationDto.Type.HTTP) 75 | .build()); 76 | return ok().build(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/controller/StreamController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.controller; 19 | 20 | import com.bompotis.netcheck.scheduler.batch.notification.CheckEventDto; 21 | import com.bompotis.netcheck.scheduler.batch.notification.NotificationEventDto; 22 | import com.bompotis.netcheck.scheduler.batch.notification.ServerMetricEventDto; 23 | import io.swagger.v3.oas.annotations.tags.Tag; 24 | import org.springframework.context.event.EventListener; 25 | import org.springframework.web.bind.annotation.CrossOrigin; 26 | import org.springframework.web.bind.annotation.GetMapping; 27 | import org.springframework.web.bind.annotation.RequestMapping; 28 | import org.springframework.web.bind.annotation.RestController; 29 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 30 | 31 | /** 32 | * Created by Kyriakos Bompotis on 25/8/20. 33 | */ 34 | @RestController 35 | @CrossOrigin(origins = {"${settings.cors.origin}"}) 36 | @RequestMapping(value = "/events") 37 | @Tag(name = "Check Events", description = "Server sent events endpoint") 38 | public class StreamController extends AbstractStreamController { 39 | @GetMapping 40 | public SseEmitter stream() { 41 | return addSseEmitter(); 42 | } 43 | 44 | @EventListener 45 | public void handleCheckEvent(CheckEventDto eventDto) { 46 | sendToSseEmitter(eventDto.getEvent()); 47 | } 48 | 49 | @EventListener 50 | public void handleNotificationEvent(NotificationEventDto eventDto) { 51 | sendToSseEmitter(eventDto.getEvent()); 52 | } 53 | 54 | @EventListener 55 | public void handleServerMetricsEvent(ServerMetricEventDto eventDto) { 56 | sendToSseEmitter(eventDto.getEvent()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/exception/ControllerAdvisor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.exception; 19 | 20 | import org.springframework.context.support.DefaultMessageSourceResolvable; 21 | import org.springframework.http.HttpHeaders; 22 | import org.springframework.http.HttpStatus; 23 | import org.springframework.http.HttpStatusCode; 24 | import org.springframework.http.ResponseEntity; 25 | import org.springframework.web.bind.MethodArgumentNotValidException; 26 | import org.springframework.web.bind.annotation.ControllerAdvice; 27 | import org.springframework.web.bind.annotation.ExceptionHandler; 28 | import org.springframework.web.context.request.WebRequest; 29 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 30 | import reactor.util.annotation.NonNull; 31 | 32 | import java.time.LocalDateTime; 33 | import java.time.format.DateTimeFormatter; 34 | import java.util.LinkedHashMap; 35 | import java.util.List; 36 | import java.util.Map; 37 | import java.util.stream.Collectors; 38 | 39 | /** 40 | * Created by Kyriakos Bompotis on 3/9/20. 41 | */ 42 | @ControllerAdvice 43 | public class ControllerAdvisor extends ResponseEntityExceptionHandler { 44 | 45 | @ExceptionHandler(IllegalArgumentException.class) 46 | public ResponseEntity handleIllegalArgumentException( 47 | IllegalArgumentException ex, WebRequest request) { 48 | 49 | Map body = new LinkedHashMap<>(); 50 | body.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)); 51 | body.put("message", ex.getMessage()); 52 | 53 | 54 | return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST); 55 | } 56 | 57 | @ExceptionHandler(InvalidAuthHeaders.class) 58 | public ResponseEntity handleInvalidAuthHeaders() { 59 | return handleUnauthorizedStatusException(); 60 | } 61 | 62 | @ExceptionHandler(UnauthorizedStatusException.class) 63 | public ResponseEntity handleUnauthorizedStatusException() { 64 | 65 | var headers = new HttpHeaders(); 66 | headers.add(HttpHeaders.WWW_AUTHENTICATE,"Basic realm=\"Server Realm\""); 67 | 68 | return new ResponseEntity<>(null, headers, HttpStatus.UNAUTHORIZED); 69 | } 70 | 71 | @ExceptionHandler(EntityNotFoundException.class) 72 | public ResponseEntity handleEntityNotFoundException(EntityNotFoundException ex, WebRequest request) { 73 | Map body = new LinkedHashMap<>(); 74 | body.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)); 75 | body.put("message", ex.getMessage()); 76 | 77 | return new ResponseEntity<>(body, HttpStatus.NOT_FOUND); 78 | } 79 | 80 | @Override 81 | protected ResponseEntity handleMethodArgumentNotValid( 82 | MethodArgumentNotValidException ex, 83 | @NonNull HttpHeaders headers, 84 | HttpStatusCode statusCode, 85 | @NonNull WebRequest request 86 | ) { 87 | 88 | Map body = new LinkedHashMap<>(); 89 | body.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)); 90 | body.put("status", statusCode.value()); 91 | 92 | List errors = ex.getBindingResult() 93 | .getFieldErrors() 94 | .stream() 95 | .map(DefaultMessageSourceResolvable::getDefaultMessage) 96 | .collect(Collectors.toList()); 97 | 98 | body.put("errors", errors); 99 | 100 | return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/exception/EntityNotFoundException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.exception; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 5/9/20. 22 | */ 23 | public class EntityNotFoundException extends Exception { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/exception/InvalidAuthHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.exception; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 6/9/20. 22 | */ 23 | public class InvalidAuthHeaders extends Exception{ 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/exception/UnauthorizedStatusException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.exception; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 6/9/20. 22 | */ 23 | public class UnauthorizedStatusException extends Exception{ 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/CertificateModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import org.springframework.hateoas.RepresentationModel; 22 | import org.springframework.hateoas.server.core.Relation; 23 | 24 | import javax.naming.InvalidNameException; 25 | import javax.naming.ldap.LdapName; 26 | import javax.naming.ldap.Rdn; 27 | import java.util.Date; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | import java.util.stream.Collectors; 31 | 32 | /** 33 | * Created by Kyriakos Bompotis on 11/6/20. 34 | */ 35 | @Relation(collectionRelation = "certificates", itemRelation = "certificate") 36 | public class CertificateModel extends RepresentationModel { 37 | private final String issuedBy; 38 | private final String issuedFor; 39 | private final Date notBefore; 40 | private final Date notAfter; 41 | private final Boolean isValid; 42 | private final Boolean expired; 43 | 44 | public CertificateModel( 45 | @JsonProperty("issuedBy") String issuedBy, 46 | @JsonProperty("issuedFor") String issuedFor, 47 | @JsonProperty("notBefore") Date notBefore, 48 | @JsonProperty("notAfter") Date notAfter, 49 | @JsonProperty("isValid") Boolean isValid, 50 | @JsonProperty("expired") Boolean expired) { 51 | this.issuedBy = issuedBy; 52 | this.issuedFor = issuedFor; 53 | this.notBefore = notBefore; 54 | this.notAfter = notAfter; 55 | this.isValid = isValid; 56 | this.expired = expired; 57 | } 58 | 59 | public Map getIssuedBy() throws InvalidNameException { 60 | return ldapNameToMap(issuedBy); 61 | } 62 | 63 | public Map getIssuedFor() throws InvalidNameException { 64 | return ldapNameToMap(issuedFor); 65 | } 66 | 67 | private Map ldapNameToMap(String ldapName) throws InvalidNameException { 68 | return new LdapName(ldapName) 69 | .getRdns() 70 | .stream() 71 | .collect(Collectors.toMap(Rdn::getType, Rdn::getValue, (a, b) -> b, HashMap::new)); 72 | } 73 | 74 | public Date getNotBefore() { 75 | return notBefore; 76 | } 77 | 78 | public Date getNotAfter() { 79 | return notAfter; 80 | } 81 | 82 | public Boolean getValid() { 83 | return isValid; 84 | } 85 | 86 | public Boolean getExpired() { 87 | return expired; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/DomainCheckModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonInclude; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import org.springframework.hateoas.RepresentationModel; 23 | import org.springframework.hateoas.server.core.Relation; 24 | 25 | import java.util.Collection; 26 | import java.util.List; 27 | 28 | /** 29 | * Created by Kyriakos Bompotis on 10/6/20. 30 | */ 31 | @Relation(collectionRelation = "domainChecks", itemRelation = "domainCheck") 32 | public class DomainCheckModel extends RepresentationModel { 33 | private final Collection httpChecks; 34 | private final CertificateModel issuerCertificate; 35 | private final List caCertificates; 36 | private final Boolean monitored; 37 | private final String domain; 38 | 39 | public DomainCheckModel(@JsonProperty("domain") String domain, 40 | @JsonProperty("monitored") Boolean monitored, 41 | @JsonProperty("httpChecks") Collection httpChecks, 42 | @JsonProperty("issuerCertificate") CertificateModel issuerCertificate, 43 | @JsonProperty("caCertificates") List caCertificates) { 44 | this.domain = domain; 45 | this.monitored = monitored; 46 | this.httpChecks = httpChecks; 47 | this.issuerCertificate = issuerCertificate; 48 | this.caCertificates = caCertificates; 49 | } 50 | 51 | public CertificateModel getIssuerCertificate() { 52 | return issuerCertificate; 53 | } 54 | 55 | public List getCaCertificates() { 56 | return caCertificates; 57 | } 58 | 59 | public Collection getHttpChecks() { 60 | return httpChecks; 61 | } 62 | 63 | public String getDomain() { 64 | return domain; 65 | } 66 | 67 | @JsonInclude(JsonInclude.Include.NON_NULL) 68 | public Boolean getMonitored() { 69 | return monitored; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/DomainRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import jakarta.validation.constraints.Max; 21 | import jakarta.validation.constraints.Min; 22 | import java.util.Map; 23 | 24 | /** 25 | * Created by Kyriakos Bompotis on 2/9/20. 26 | */ 27 | public record DomainRequest( 28 | @Min(value = 1, message = "checkFrequencyMinutes should not be less than 1") Integer checkFrequencyMinutes, 29 | String endpoint, 30 | @Min(value = 1, message = "port should not be less than 1") @Max(value = 65535, message = "port should be no more than 65535") Integer httpPort, 31 | @Min(value = 1, message = "port should not be less than 1") @Max(value = 65535, message = "port should be no more than 65535") Integer httpsPort, 32 | Map headers, 33 | @Min(value = 1, message = "timeoutMs should not be less than 1") Integer timeoutMs) { 34 | public DomainRequest(Integer checkFrequencyMinutes, String endpoint, Integer httpPort, Integer httpsPort, Map headers, Integer timeoutMs) { 35 | this.checkFrequencyMinutes = checkFrequencyMinutes; 36 | this.endpoint = endpoint; 37 | this.httpPort = httpPort; 38 | this.httpsPort = httpsPort; 39 | this.headers = headers; 40 | this.timeoutMs = timeoutMs; 41 | } 42 | 43 | @Override 44 | public Integer checkFrequencyMinutes() { 45 | return checkFrequencyMinutes; 46 | } 47 | 48 | @Override 49 | public Integer timeoutMs() { 50 | return timeoutMs; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/DomainResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | import org.springframework.hateoas.RepresentationModel; 24 | import org.springframework.hateoas.server.core.Relation; 25 | 26 | import java.util.Date; 27 | import java.util.Map; 28 | 29 | /** 30 | * Created by Kyriakos Bompotis on 9/6/20. 31 | */ 32 | @Relation(collectionRelation = "domains", itemRelation = "domain") 33 | public class DomainResponse extends RepresentationModel { 34 | private final String domain; 35 | 36 | private final DomainCheckModel lastDomainCheck; 37 | 38 | private final Integer checkFrequencyMinutes; 39 | 40 | private final Date dateAdded; 41 | 42 | private final String endpoint; 43 | 44 | private final Map headers; 45 | 46 | private final Integer timeoutMs; 47 | 48 | @JsonCreator 49 | public DomainResponse(@JsonProperty("domain") String domain, 50 | @JsonProperty("lastDomainCheck") DomainCheckModel lastDomainCheck, 51 | @JsonProperty("dateAdded") Date dateAdded, 52 | @JsonProperty("checkFrequencyMinutes") Integer checkFrequencyMinutes, 53 | @JsonProperty("endpoint") String endpoint, 54 | @JsonProperty("headers") Map headers, 55 | @JsonProperty("timeoutMs") Integer timeoutMs) { 56 | this.domain = domain; 57 | this.lastDomainCheck = lastDomainCheck; 58 | this.dateAdded = dateAdded; 59 | this.checkFrequencyMinutes = checkFrequencyMinutes; 60 | this.endpoint = endpoint; 61 | this.headers = headers; 62 | this.timeoutMs = timeoutMs; 63 | } 64 | 65 | public String getDomain() { 66 | return domain; 67 | } 68 | 69 | @JsonInclude(JsonInclude.Include.NON_NULL) 70 | public DomainCheckModel getLastChecks() { 71 | return lastDomainCheck; 72 | } 73 | 74 | public Date getDateAdded() { 75 | return dateAdded; 76 | } 77 | 78 | public Integer getCheckFrequencyMinutes() { 79 | return checkFrequencyMinutes; 80 | } 81 | 82 | public String getEndpoint() { 83 | return endpoint; 84 | } 85 | 86 | public Map getHeaders() { 87 | return headers; 88 | } 89 | 90 | public Integer getTimeoutMs() { 91 | return timeoutMs; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/HttpCheckModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | import org.springframework.hateoas.RepresentationModel; 24 | import org.springframework.hateoas.server.core.Relation; 25 | 26 | import java.util.Date; 27 | 28 | /** 29 | * Created by Kyriakos Bompotis on 15/6/20. 30 | */ 31 | @Relation(collectionRelation = "checks", itemRelation = "check") 32 | public class HttpCheckModel extends RepresentationModel { 33 | private final Boolean isUp; 34 | private final Integer statusCode; 35 | private final Date timeCheckedOn; 36 | private final Boolean dnsResolves; 37 | private final String hostname; 38 | private final String ipAddress; 39 | private final Long responseTimeNs; 40 | private final String protocol; 41 | private final String redirectUri; 42 | private final String errorMessage; 43 | 44 | @JsonCreator 45 | public HttpCheckModel( 46 | @JsonProperty("hostname") String hostname, 47 | @JsonProperty("statusCode") Integer statusCode, 48 | @JsonProperty("checkedOn") Date timeCheckedOn, 49 | @JsonProperty("responseTimeNs") Long responseTimeNs, 50 | @JsonProperty("dnsResolves") Boolean dnsResolves, 51 | @JsonProperty("ipAddress") String ipAddress, 52 | @JsonProperty("protocol") String protocol, 53 | @JsonProperty("redirectUri") String redirectUri, 54 | @JsonProperty("up") Boolean isUp, 55 | @JsonProperty("errorMessage") String errorMessage) { 56 | this.isUp = isUp; 57 | this.hostname = hostname; 58 | this.statusCode = statusCode; 59 | this.timeCheckedOn = timeCheckedOn; 60 | this.responseTimeNs = responseTimeNs; 61 | this.dnsResolves = dnsResolves; 62 | this.ipAddress = ipAddress; 63 | this.protocol = protocol; 64 | this.redirectUri = redirectUri; 65 | this.errorMessage = errorMessage; 66 | } 67 | 68 | public Integer getStatusCode() { 69 | return statusCode; 70 | } 71 | 72 | public Boolean getDnsResolves() { 73 | return dnsResolves; 74 | } 75 | 76 | public Date getTimeCheckedOn() { 77 | return timeCheckedOn; 78 | } 79 | 80 | public String getHostname() { 81 | return hostname; 82 | } 83 | 84 | public Long getResponseTimeNs() { 85 | return responseTimeNs; 86 | } 87 | 88 | public String getIpAddress() { 89 | return ipAddress; 90 | } 91 | 92 | public String getProtocol() { 93 | return protocol; 94 | } 95 | 96 | @JsonInclude(JsonInclude.Include.NON_NULL) 97 | public String getRedirectUri() { 98 | return redirectUri; 99 | } 100 | 101 | public Boolean getUp() { 102 | return isUp; 103 | } 104 | 105 | public String getErrorMessage() { 106 | return errorMessage; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/MetricModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import org.springframework.hateoas.RepresentationModel; 23 | import org.springframework.hateoas.server.core.Relation; 24 | 25 | import java.util.Date; 26 | 27 | /** 28 | * Created by Kyriakos Bompotis on 22/6/20. 29 | */ 30 | @Relation(collectionRelation = "metrics", itemRelation = "metric") 31 | public class MetricModel extends RepresentationModel { 32 | private final Date metricPeriodStart; 33 | private final Date metricPeriodEnd; 34 | private final Integer totalChecks; 35 | private final Integer successfulChecks; 36 | private final Long averageResponseTime; 37 | private final Long maxResponseTime; 38 | private final Long minResponseTime; 39 | private final String protocol; 40 | 41 | @JsonCreator 42 | public MetricModel( 43 | @JsonProperty("metricPeriodStart") Date metricPeriodStart, 44 | @JsonProperty("metricPeriodEnd") Date metricPeriodEnd, 45 | @JsonProperty("totalChecks") Integer totalChecks, 46 | @JsonProperty("successfulChecks") Integer successfulChecks, 47 | @JsonProperty("averageResponseTime") Long averageResponseTime, 48 | @JsonProperty("maxResponseTime") Long maxResponseTime, 49 | @JsonProperty("minResponseTime") Long minResponseTime, 50 | @JsonProperty("protocol") String protocol) { 51 | this.metricPeriodStart = metricPeriodStart; 52 | this.metricPeriodEnd = metricPeriodEnd; 53 | this.totalChecks = totalChecks; 54 | this.successfulChecks = successfulChecks; 55 | this.averageResponseTime = averageResponseTime; 56 | this.maxResponseTime = maxResponseTime; 57 | this.minResponseTime = minResponseTime; 58 | this.protocol = protocol; 59 | } 60 | 61 | public Date getMetricPeriodStart() { 62 | return metricPeriodStart; 63 | } 64 | 65 | public Date getMetricPeriodEnd() { 66 | return metricPeriodEnd; 67 | } 68 | 69 | public Integer getTotalChecks() { 70 | return totalChecks; 71 | } 72 | 73 | public Integer getSuccessfulChecks() { 74 | return successfulChecks; 75 | } 76 | 77 | public Long getAverageResponseTime() { 78 | return averageResponseTime; 79 | } 80 | 81 | public Long getMaxResponseTime() { 82 | return maxResponseTime; 83 | } 84 | 85 | public Long getMinResponseTime() { 86 | return minResponseTime; 87 | } 88 | 89 | public String getProtocol() { 90 | return protocol; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/PatchOperation.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.api.model; 2 | 3 | /** 4 | * Created by Kyriakos Bompotis on 2/9/20. 5 | */ 6 | public record PatchOperation(String op, String field, String value, String path) { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/RegisterServerRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import jakarta.validation.constraints.NotBlank; 21 | 22 | /** 23 | * Created by Kyriakos Bompotis on 4/9/20. 24 | */ 25 | public class RegisterServerRequest { 26 | @NotBlank(message = "serverName is mandatory") 27 | private String serverName; 28 | 29 | private String description; 30 | 31 | public RegisterServerRequest() {} 32 | 33 | public RegisterServerRequest(String serverName, String description) { 34 | this.serverName = serverName; 35 | this.description = description; 36 | } 37 | 38 | public String getServerName() { 39 | return serverName; 40 | } 41 | 42 | public String getDescription() { 43 | return description; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/ServerDefinitionModel.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import org.springframework.hateoas.RepresentationModel; 6 | 7 | import jakarta.validation.constraints.NotNull; 8 | 9 | /** 10 | * Created by Kyriakos Bompotis on 9/9/20. 11 | */ 12 | public class ServerDefinitionModel extends RepresentationModel { 13 | 14 | @NotNull(message = "label is mandatory") 15 | private String label; 16 | 17 | @NotNull(message = "fieldName is mandatory") 18 | private String fieldName; 19 | 20 | private String suffix; 21 | 22 | @NotNull(message = "valueType is mandatory") 23 | private String valueType; 24 | 25 | @NotNull(message = "metricKind is mandatory") 26 | private String metricKind; 27 | 28 | private String extendedType; 29 | 30 | private String minThreshold; 31 | 32 | private String maxThreshold; 33 | 34 | private Boolean notify; 35 | 36 | public ServerDefinitionModel() {} 37 | 38 | public ServerDefinitionModel(@JsonProperty("label") String label, 39 | @JsonProperty("fieldName") String fieldName, 40 | @JsonProperty("suffix") String suffix, 41 | @JsonProperty("valueType") String valueType, 42 | @JsonProperty("metricKind") String metricKind, 43 | @JsonProperty("extendedType") String extendedType, 44 | @JsonProperty("minThreshold") String minThreshold, 45 | @JsonProperty("maxThreshold") String maxThreshold, 46 | @JsonProperty("notify") Boolean notify) { 47 | this.label = label; 48 | this.fieldName = fieldName; 49 | this.suffix = suffix; 50 | this.valueType = valueType; 51 | this.metricKind = metricKind; 52 | this.extendedType = extendedType; 53 | this.minThreshold = minThreshold; 54 | this.maxThreshold = maxThreshold; 55 | this.notify = notify; 56 | } 57 | 58 | public String getLabel() { 59 | return label; 60 | } 61 | 62 | public String getFieldName() { 63 | return fieldName; 64 | } 65 | 66 | @JsonInclude(JsonInclude.Include.NON_NULL) 67 | public String getSuffix() { 68 | return suffix; 69 | } 70 | 71 | public String getValueType() { 72 | return valueType; 73 | } 74 | 75 | public String getMetricKind() { 76 | return metricKind; 77 | } 78 | 79 | @JsonInclude(JsonInclude.Include.NON_NULL) 80 | public String getExtendedType() { 81 | return extendedType; 82 | } 83 | 84 | @JsonInclude(JsonInclude.Include.NON_NULL) 85 | public String getMinThreshold() { 86 | return minThreshold; 87 | } 88 | 89 | @JsonInclude(JsonInclude.Include.NON_NULL) 90 | public String getMaxThreshold() { 91 | return maxThreshold; 92 | } 93 | 94 | public Boolean getNotify() { 95 | return notify; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/ServerMetricModel.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import org.springframework.hateoas.RepresentationModel; 5 | import org.springframework.hateoas.server.core.Relation; 6 | 7 | import jakarta.validation.constraints.NotNull; 8 | import java.util.Date; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by Kyriakos Bompotis on 6/9/20. 13 | */ 14 | @Relation(collectionRelation = "metrics", itemRelation = "metric") 15 | public class ServerMetricModel extends RepresentationModel { 16 | 17 | private final String id; 18 | 19 | @NotNull(message = "metrics are mandatory") 20 | private final Map metrics; 21 | 22 | @NotNull(message = "collectedAt Date is mandatory") 23 | private final Date collectedAt; 24 | 25 | public ServerMetricModel( 26 | @JsonProperty("id") String id, 27 | @JsonProperty("metrics") Map metrics, 28 | @JsonProperty("collectedAt") Date collectedAt) { 29 | this.metrics = metrics; 30 | this.collectedAt = collectedAt; 31 | this.id = id; 32 | } 33 | 34 | public Map getMetrics() { 35 | return metrics; 36 | } 37 | 38 | public Date getCollectedAt() { 39 | return collectedAt; 40 | } 41 | 42 | public String getId() { 43 | return id; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/ServerMetricRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import jakarta.validation.constraints.NotNull; 21 | import java.util.Date; 22 | import java.util.Map; 23 | 24 | /** 25 | * Created by Kyriakos Bompotis on 6/9/20. 26 | */ 27 | public class ServerMetricRequest { 28 | @NotNull(message = "metrics are mandatory") 29 | private Map metrics; 30 | 31 | @NotNull(message = "collectedAt Date is mandatory") 32 | private Date collectedAt; 33 | 34 | public ServerMetricRequest() {} 35 | 36 | public ServerMetricRequest(Map metrics, Date collectedAt) { 37 | this.metrics = metrics; 38 | this.collectedAt = collectedAt; 39 | } 40 | 41 | public Map getMetrics() { 42 | return metrics; 43 | } 44 | 45 | public Date getCollectedAt() { 46 | return collectedAt; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/ServerModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonInclude; 21 | import com.fasterxml.jackson.annotation.JsonProperty; 22 | import org.springframework.hateoas.RepresentationModel; 23 | import org.springframework.hateoas.server.core.Relation; 24 | 25 | import java.util.Date; 26 | import java.util.List; 27 | 28 | /** 29 | * Created by Kyriakos Bompotis on 4/9/20. 30 | */ 31 | @Relation(collectionRelation = "servers", itemRelation = "server") 32 | public class ServerModel extends RepresentationModel { 33 | private final String serverId; 34 | private final String serverName; 35 | private final String description; 36 | private final Date dateAdded; 37 | private final String password; 38 | private final List metricDefinitions; 39 | 40 | public ServerModel(@JsonProperty("serverId") String serverId, 41 | @JsonProperty("serverName") String serverName, 42 | @JsonProperty("description") String description, 43 | @JsonProperty("password") String password, 44 | @JsonProperty("dateAdded") Date dateAdded, 45 | @JsonProperty("metricDefinitions") List metricDefinitions) { 46 | this.serverId = serverId; 47 | this.serverName = serverName; 48 | this.description = description; 49 | this.password = password; 50 | this.dateAdded = dateAdded; 51 | this.metricDefinitions = metricDefinitions; 52 | } 53 | 54 | public String getServerId() { 55 | return serverId; 56 | } 57 | 58 | public String getServerName() { 59 | return serverName; 60 | } 61 | 62 | @JsonInclude(JsonInclude.Include.NON_NULL) 63 | public String getPassword() { 64 | return password; 65 | } 66 | 67 | public Date getDateAdded() { 68 | return dateAdded; 69 | } 70 | 71 | public String getDescription() { 72 | return description; 73 | } 74 | 75 | @JsonInclude(JsonInclude.Include.NON_NULL) 76 | public List getMetricDefinitions() { 77 | return metricDefinitions; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/StateModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonCreator; 21 | import com.fasterxml.jackson.annotation.JsonInclude; 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | import org.springframework.hateoas.RepresentationModel; 24 | import org.springframework.hateoas.server.core.Relation; 25 | 26 | import java.util.Date; 27 | 28 | /** 29 | * Created by Kyriakos Bompotis on 24/6/20. 30 | */ 31 | @Relation(collectionRelation = "states", itemRelation = "state") 32 | public class StateModel extends RepresentationModel { 33 | private final Boolean isUp; 34 | private final Integer statusCode; 35 | private final Date timeCheckedOn; 36 | private final Boolean dnsResolves; 37 | private final String hostname; 38 | private final String protocol; 39 | private final String redirectUri; 40 | private final String reason; 41 | private final Long durationSeconds; 42 | 43 | @JsonCreator 44 | public StateModel( 45 | @JsonProperty("hostname") String hostname, 46 | @JsonProperty("statusCode") Integer statusCode, 47 | @JsonProperty("checkedOn") Date timeCheckedOn, 48 | @JsonProperty("reason") String reason, 49 | @JsonProperty("dnsResolves") Boolean dnsResolves, 50 | @JsonProperty("protocol") String protocol, 51 | @JsonProperty("redirectUri") String redirectUri, 52 | @JsonProperty("isUp") Boolean isUp, 53 | @JsonProperty("durationSeconds") Long durationSeconds) { 54 | this.isUp = isUp; 55 | this.hostname = hostname; 56 | this.statusCode = statusCode; 57 | this.timeCheckedOn = timeCheckedOn; 58 | this.reason = reason; 59 | this.dnsResolves = dnsResolves; 60 | this.protocol = protocol; 61 | this.redirectUri = redirectUri; 62 | this.durationSeconds = durationSeconds; 63 | } 64 | 65 | public Integer getStatusCode() { 66 | return statusCode; 67 | } 68 | 69 | public Boolean getDnsResolves() { 70 | return dnsResolves; 71 | } 72 | 73 | public Date getTimeCheckedOn() { 74 | return timeCheckedOn; 75 | } 76 | 77 | public String getHostname() { 78 | return hostname; 79 | } 80 | 81 | public String getProtocol() { 82 | return protocol; 83 | } 84 | 85 | @JsonInclude(JsonInclude.Include.NON_NULL) 86 | public String getRedirectUri() { 87 | return redirectUri; 88 | } 89 | 90 | public Boolean getUp() { 91 | return isUp; 92 | } 93 | 94 | public String getReason() { 95 | return reason; 96 | } 97 | 98 | public Long getDurationSeconds() { 99 | return durationSeconds; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/AbstractUpdateDtoAssembler.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.api.model.assembler; 2 | 3 | import com.bompotis.netcheck.api.model.PatchOperation; 4 | import com.bompotis.netcheck.service.dto.Operation; 5 | import com.bompotis.netcheck.service.dto.PatchDtoBuilder; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Optional; 10 | import java.util.Set; 11 | import java.util.concurrent.atomic.AtomicReference; 12 | 13 | /** 14 | * Created by Kyriakos Bompotis on 7/9/20. 15 | */ 16 | public interface AbstractUpdateDtoAssembler > { 17 | 18 | Map getOperationsToActionMap(); 19 | 20 | Set getValidFields(); 21 | 22 | Set getRequiredFieldsForPath(); 23 | 24 | B getDtoBuilder(); 25 | 26 | default T validateObject(T object, String type) { 27 | var atomicObject = new AtomicReference(); 28 | Optional.ofNullable(object).ifPresentOrElse( 29 | atomicObject::set, 30 | () -> { 31 | throw new IllegalArgumentException("Property " + type + " cannot be empty or null"); 32 | } 33 | ); 34 | return atomicObject.get(); 35 | } 36 | 37 | default T validateValue(T object, Operation.Action action) { 38 | var errorMessage = "Property `value` cannot be empty or null when adding or updating a field"; 39 | return action.equals(Operation.Action.REMOVE) ? 40 | object : 41 | validateNonEmpty(object, errorMessage); 42 | } 43 | 44 | default T validatePath(T object, String field) { 45 | var errorMessage = "Property `path` cannot be empty or null when operating on a " + field; 46 | return getRequiredFieldsForPath().contains(field) ? 47 | validateNonEmpty(object, errorMessage) : 48 | object; 49 | } 50 | 51 | default T validateNonEmpty(T object, String message) { 52 | var atomicObject = new AtomicReference(); 53 | Optional.ofNullable(object).ifPresentOrElse( 54 | atomicObject::set, 55 | () -> { 56 | throw new IllegalArgumentException(message); 57 | } 58 | ); 59 | return atomicObject.get(); 60 | } 61 | 62 | default D toDto(List patchOperations) { 63 | var dto = getDtoBuilder(); 64 | for (var patchOperation : patchOperations) { 65 | var field = validateObject(patchOperation.field(), "field"); 66 | var path = validatePath(patchOperation.path(), field); 67 | var op = validateObject(patchOperation.op(), "op"); 68 | if (!getOperationsToActionMap().containsKey(op)) { 69 | throw new IllegalArgumentException("Invalid value for property `op`: " + op); 70 | } 71 | var action = getOperationsToActionMap().get(op); 72 | var value = validateValue(patchOperation.value(), action); 73 | if (!getValidFields().contains(field)) { 74 | throw new IllegalArgumentException("Invalid value for property `field`: " + field); 75 | } 76 | dto.addOperation(new Operation(field, action, value, path)); 77 | } 78 | return dto.build(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/CertificateModelAssembler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model.assembler; 19 | 20 | import com.bompotis.netcheck.api.controller.DomainsController; 21 | import com.bompotis.netcheck.api.model.CertificateModel; 22 | import com.bompotis.netcheck.service.dto.CertificateDetailsDto; 23 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 24 | import org.springframework.lang.NonNull; 25 | 26 | /** 27 | * Created by Kyriakos Bompotis on 17/6/20. 28 | */ 29 | public class CertificateModelAssembler extends RepresentationModelAssemblerSupport { 30 | 31 | public CertificateModelAssembler() { 32 | super(DomainsController.class, CertificateModel.class); 33 | } 34 | 35 | @NonNull 36 | @Override 37 | public CertificateModel toModel(CertificateDetailsDto certificateDetailsDto) { 38 | return new CertificateModel( 39 | certificateDetailsDto.getIssuedBy(), 40 | certificateDetailsDto.getIssuedFor(), 41 | certificateDetailsDto.getNotBefore(), 42 | certificateDetailsDto.getNotAfter(), 43 | certificateDetailsDto.isValid(), 44 | certificateDetailsDto.getExpired() 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/DomainUpdateDtoAssembler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model.assembler; 19 | 20 | import com.bompotis.netcheck.service.dto.DomainUpdateDto; 21 | import com.bompotis.netcheck.service.dto.Operation; 22 | 23 | import java.util.Map; 24 | import java.util.Set; 25 | 26 | /** 27 | * Created by Kyriakos Bompotis on 2/9/20. 28 | */ 29 | public class DomainUpdateDtoAssembler implements AbstractUpdateDtoAssembler{ 30 | private final String domain; 31 | 32 | private static final Map OPERATIONS_TO_ACTION_MAP = Map.of( 33 | "delete", Operation.Action.REMOVE, 34 | "replace", Operation.Action.UPDATE, 35 | "add", Operation.Action.ADD 36 | ); 37 | 38 | private static final Set VALID_FIELDS = Set.of( 39 | "frequency", 40 | "endpoint", 41 | "header", 42 | "headers", 43 | "timeout" 44 | ); 45 | 46 | private static final Set REQUIRED_FIELDS_FOR_PATH = Set.of( 47 | "header" 48 | ); 49 | 50 | public DomainUpdateDtoAssembler(String domain) { 51 | this.domain = domain; 52 | } 53 | 54 | @Override 55 | public Map getOperationsToActionMap() { 56 | return OPERATIONS_TO_ACTION_MAP; 57 | } 58 | 59 | @Override 60 | public Set getValidFields() { 61 | return VALID_FIELDS; 62 | } 63 | 64 | @Override 65 | public Set getRequiredFieldsForPath() { 66 | return REQUIRED_FIELDS_FOR_PATH; 67 | } 68 | 69 | @Override 70 | public DomainUpdateDto.Builder getDtoBuilder() { 71 | return new DomainUpdateDto.Builder(domain); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/HttpCheckModelAssembler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model.assembler; 19 | 20 | import com.bompotis.netcheck.api.controller.DomainsController; 21 | import com.bompotis.netcheck.api.model.HttpCheckModel; 22 | import com.bompotis.netcheck.service.dto.HttpCheckDto; 23 | import com.bompotis.netcheck.service.dto.PaginatedDto; 24 | import org.springframework.hateoas.CollectionModel; 25 | import org.springframework.hateoas.IanaLinkRelations; 26 | import org.springframework.hateoas.Link; 27 | import org.springframework.hateoas.PagedModel; 28 | import org.springframework.http.ResponseEntity; 29 | import org.springframework.lang.NonNull; 30 | 31 | import java.util.ArrayList; 32 | import java.util.stream.Collectors; 33 | 34 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; 35 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; 36 | 37 | /** 38 | * Created by Kyriakos Bompotis on 17/6/20. 39 | */ 40 | public class HttpCheckModelAssembler extends PaginatedRepresentationModelAssemblerSupport { 41 | 42 | public HttpCheckModelAssembler() { 43 | super(DomainsController.class, HttpCheckModel.class); 44 | } 45 | 46 | @NonNull 47 | @Override 48 | public HttpCheckModel toModel(HttpCheckDto httpCheckDto) { 49 | return new HttpCheckModel( 50 | httpCheckDto.getHostname(), 51 | httpCheckDto.getStatusCode(), 52 | httpCheckDto.getTimeCheckedOn(), 53 | httpCheckDto.getResponseTimeNs(), 54 | httpCheckDto.getDnsResolved(), 55 | httpCheckDto.getIpAddress(), 56 | httpCheckDto.getProtocol(), 57 | httpCheckDto.getRedirectUri(), 58 | httpCheckDto.isUp(), 59 | httpCheckDto.getErrorMessage()); 60 | } 61 | 62 | public CollectionModel toCollectionModel(PaginatedDto paginatedHttpCheckDto, String domain, String protocol) { 63 | var httpModels = paginatedHttpCheckDto.getDtoList().stream().map(this::toModel).collect(Collectors.toCollection(ArrayList::new)); 64 | ResponseEntity> method; 65 | var links = new ArrayList(); 66 | if (isValidPage(paginatedHttpCheckDto.getNumber(),paginatedHttpCheckDto.getTotalPages())) { 67 | if (protocol.equals("http")) { 68 | method = methodOn(DomainsController.class) 69 | .getHttpChecks(domain,paginatedHttpCheckDto.getNumber()+1, paginatedHttpCheckDto.getSize()); 70 | links.add(linkTo(methodOn(DomainsController.class) 71 | .getHttpChecks(domain, paginatedHttpCheckDto.getNumber(), paginatedHttpCheckDto.getSize())) 72 | .withSelfRel() 73 | ); 74 | } 75 | else { 76 | method = methodOn(DomainsController.class) 77 | .getHttpsChecks(domain,paginatedHttpCheckDto.getNumber()+1, paginatedHttpCheckDto.getSize()); 78 | links.add(linkTo(methodOn(DomainsController.class) 79 | .getHttpsChecks(domain, paginatedHttpCheckDto.getNumber(), paginatedHttpCheckDto.getSize())) 80 | .withSelfRel() 81 | ); 82 | } 83 | if (isNotLastPage(paginatedHttpCheckDto.getNumber(), paginatedHttpCheckDto.getTotalPages())) { 84 | links.add(linkTo(method).withRel(IanaLinkRelations.NEXT)); 85 | } 86 | if (isNotFirstPage(paginatedHttpCheckDto.getNumber())) { 87 | links.add(linkTo(method).withRel(IanaLinkRelations.PREVIOUS)); 88 | } 89 | } 90 | return PagedModel.of( 91 | httpModels, 92 | new PagedModel.PageMetadata( 93 | httpModels.size(), 94 | paginatedHttpCheckDto.getNumber(), 95 | paginatedHttpCheckDto.getTotalElements(), 96 | paginatedHttpCheckDto.getTotalPages() 97 | ), 98 | links 99 | ); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/MetricModelAssembler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model.assembler; 19 | 20 | import com.bompotis.netcheck.api.controller.DomainsController; 21 | import com.bompotis.netcheck.api.model.MetricModel; 22 | import com.bompotis.netcheck.service.dto.MetricDto; 23 | import com.bompotis.netcheck.service.dto.PaginatedDto; 24 | import org.springframework.hateoas.CollectionModel; 25 | import org.springframework.hateoas.IanaLinkRelations; 26 | import org.springframework.hateoas.Link; 27 | import org.springframework.hateoas.PagedModel; 28 | import org.springframework.lang.NonNull; 29 | 30 | import java.util.ArrayList; 31 | 32 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; 33 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; 34 | 35 | /** 36 | * Created by Kyriakos Bompotis on 22/6/20. 37 | */ 38 | public class MetricModelAssembler extends PaginatedRepresentationModelAssemblerSupport { 39 | public MetricModelAssembler() { 40 | super(DomainsController.class, MetricModel.class); 41 | } 42 | 43 | @NonNull 44 | @Override 45 | public MetricModel toModel(MetricDto entity) { 46 | return new MetricModel( 47 | entity.getMetricPeriodStart(), 48 | entity.getMetricPeriodEnd(), 49 | entity.getTotalChecks(), 50 | entity.getSuccessfulChecks(), 51 | entity.getAverageResponseTime(), 52 | entity.getMaxResponseTime(), 53 | entity.getMinResponseTime(), 54 | entity.getProtocol() 55 | ); 56 | } 57 | 58 | public CollectionModel toCollectionModel(PaginatedDto paginatedMetricsDto, String domain, String protocol, String period) { 59 | final var metricModels = this.toCollectionModel(paginatedMetricsDto.getDtoList()).getContent(); 60 | final var links = new ArrayList(); 61 | links.add(linkTo(methodOn(DomainsController.class) 62 | .getDomainsMetrics(domain, protocol, period, paginatedMetricsDto.getNumber(), paginatedMetricsDto.getSize())) 63 | .withSelfRel() 64 | ); 65 | if (isValidPage(paginatedMetricsDto.getNumber(),paginatedMetricsDto.getTotalPages())) { 66 | if (isNotLastPage(paginatedMetricsDto.getNumber(), paginatedMetricsDto.getTotalPages())) { 67 | links.add(linkTo(methodOn(DomainsController.class) 68 | .getDomainsMetrics(domain, protocol, period, paginatedMetricsDto.getNumber()+1, paginatedMetricsDto.getSize())) 69 | .withRel(IanaLinkRelations.NEXT) 70 | ); 71 | } 72 | if (isNotFirstPage(paginatedMetricsDto.getNumber())) { 73 | links.add(linkTo(methodOn(DomainsController.class) 74 | .getDomainsMetrics(domain, protocol, period, paginatedMetricsDto.getNumber()-1, paginatedMetricsDto.getSize())) 75 | .withRel(IanaLinkRelations.PREVIOUS) 76 | ); 77 | } 78 | } 79 | return PagedModel.of( 80 | metricModels, 81 | new PagedModel.PageMetadata( 82 | metricModels.size(), 83 | paginatedMetricsDto.getNumber(), 84 | paginatedMetricsDto.getTotalElements(), 85 | paginatedMetricsDto.getTotalPages() 86 | ), 87 | links 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/PaginatedRepresentationModelAssemblerSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model.assembler; 19 | 20 | import org.springframework.hateoas.RepresentationModel; 21 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 22 | 23 | /** 24 | * Created by Kyriakos Bompotis on 17/6/20. 25 | */ 26 | public abstract class PaginatedRepresentationModelAssemblerSupport> extends RepresentationModelAssemblerSupport { 27 | public PaginatedRepresentationModelAssemblerSupport(Class controllerClass, Class resourceType) { 28 | super(controllerClass, resourceType); 29 | } 30 | 31 | protected boolean isValidPage(int pageNumber, int totalPages) { 32 | return pageNumber+1 <= totalPages; 33 | } 34 | 35 | protected boolean isNotFirstPage(int pageNumber) { 36 | return pageNumber != 0; 37 | } 38 | 39 | protected boolean isNotLastPage(int pageNumber, int totalPages) { 40 | return (pageNumber + 1 != totalPages); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/ServerDefinitionAssembler.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.api.model.assembler; 2 | 3 | import com.bompotis.netcheck.api.controller.ServerController; 4 | import com.bompotis.netcheck.api.model.ServerDefinitionModel; 5 | import com.bompotis.netcheck.service.dto.ServerDefinitionDto; 6 | import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport; 7 | import org.springframework.lang.NonNull; 8 | 9 | /** 10 | * Created by Kyriakos Bompotis on 9/9/20. 11 | */ 12 | public class ServerDefinitionAssembler extends RepresentationModelAssemblerSupport { 13 | 14 | public ServerDefinitionAssembler() { 15 | super(ServerController.class, ServerDefinitionModel.class); 16 | } 17 | 18 | @NonNull 19 | @Override 20 | public ServerDefinitionModel toModel(ServerDefinitionDto entity) { 21 | return new ServerDefinitionModel( 22 | entity.getLabel(), 23 | entity.getFieldName(), 24 | entity.getSuffix(), 25 | entity.getValueType(), 26 | entity.getMetricKind(), 27 | entity.getExtendedType(), 28 | entity.getMinThreshold(), 29 | entity.getMaxThreshold(), 30 | entity.getNotify() 31 | ); 32 | } 33 | 34 | public ServerDefinitionDto toDto(ServerDefinitionModel model) { 35 | return new ServerDefinitionDto.Builder() 36 | .label(model.getLabel()) 37 | .fieldName(model.getFieldName()) 38 | .suffix(model.getSuffix()) 39 | .valueType(model.getValueType()) 40 | .metricKind(model.getMetricKind()) 41 | .extendedType(model.getExtendedType()) 42 | .maxThreshold(model.getMaxThreshold()) 43 | .minThreshold(model.getMinThreshold()) 44 | .notify(model.getNotify()) 45 | .build(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/ServerUpdateDtoAssembler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model.assembler; 19 | 20 | import com.bompotis.netcheck.service.dto.Operation; 21 | import com.bompotis.netcheck.service.dto.ServerUpdateDto; 22 | 23 | import java.util.Map; 24 | import java.util.Set; 25 | 26 | /** 27 | * Created by Kyriakos Bompotis on 2/9/20. 28 | */ 29 | public class ServerUpdateDtoAssembler implements AbstractUpdateDtoAssembler{ 30 | private final String domain; 31 | 32 | private static final Map OPERATIONS_TO_ACTION_MAP = Map.of( 33 | "delete", Operation.Action.REMOVE, 34 | "replace", Operation.Action.UPDATE, 35 | "add", Operation.Action.ADD 36 | ); 37 | 38 | private static final Set VALID_FIELDS = Set.of( 39 | "serverName", 40 | "description", 41 | "password" 42 | ); 43 | 44 | public ServerUpdateDtoAssembler(String domain) { 45 | this.domain = domain; 46 | } 47 | 48 | @Override 49 | public Map getOperationsToActionMap() { 50 | return OPERATIONS_TO_ACTION_MAP; 51 | } 52 | 53 | @Override 54 | public Set getValidFields() { 55 | return VALID_FIELDS; 56 | } 57 | 58 | @Override 59 | public Set getRequiredFieldsForPath() { 60 | return Set.of(); 61 | } 62 | 63 | @Override 64 | public ServerUpdateDto.Builder getDtoBuilder() { 65 | return new ServerUpdateDto.Builder(domain); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/model/assembler/StateModelAssembler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.model.assembler; 19 | 20 | import com.bompotis.netcheck.api.controller.DomainsController; 21 | import com.bompotis.netcheck.api.model.StateModel; 22 | import com.bompotis.netcheck.service.dto.PaginatedDto; 23 | import com.bompotis.netcheck.service.dto.StateDto; 24 | import org.springframework.hateoas.CollectionModel; 25 | import org.springframework.hateoas.IanaLinkRelations; 26 | import org.springframework.hateoas.Link; 27 | import org.springframework.hateoas.PagedModel; 28 | import org.springframework.lang.NonNull; 29 | 30 | import java.util.ArrayList; 31 | 32 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; 33 | import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; 34 | 35 | /** 36 | * Created by Kyriakos Bompotis on 24/6/20. 37 | */ 38 | public class StateModelAssembler extends PaginatedRepresentationModelAssemblerSupport { 39 | public StateModelAssembler() { 40 | super(DomainsController.class, StateModel.class); 41 | } 42 | 43 | @NonNull 44 | @Override 45 | public StateModel toModel(StateDto stateDto) { 46 | return new StateModel( 47 | stateDto.getHostname(), 48 | stateDto.getStatusCode(), 49 | stateDto.getTimeCheckedOn(), 50 | stateDto.getReason(), 51 | stateDto.getDnsResolves(), 52 | stateDto.getProtocol(), 53 | stateDto.getRedirectUri(), 54 | stateDto.isUp(), 55 | stateDto.getDuration().getSeconds()); 56 | } 57 | 58 | public CollectionModel toCollectionModel(PaginatedDto paginatedStatesDto, String domain, String protocol, Boolean includeCertificates) { 59 | final var stateModels = this.toCollectionModel(paginatedStatesDto.getDtoList()).getContent(); 60 | final var links = new ArrayList(); 61 | links.add(linkTo(methodOn(DomainsController.class) 62 | .getDomainsStates(domain, protocol, includeCertificates, paginatedStatesDto.getNumber(), paginatedStatesDto.getSize())) 63 | .withSelfRel() 64 | ); 65 | if (isValidPage(paginatedStatesDto.getNumber(),paginatedStatesDto.getTotalPages())) { 66 | if (isNotLastPage(paginatedStatesDto.getNumber(), paginatedStatesDto.getTotalPages())) { 67 | links.add(linkTo(methodOn(DomainsController.class) 68 | .getDomainsStates(domain, protocol, includeCertificates, paginatedStatesDto.getNumber()+1, paginatedStatesDto.getSize())) 69 | .withRel(IanaLinkRelations.NEXT) 70 | ); 71 | } 72 | if (isNotFirstPage(paginatedStatesDto.getNumber())) { 73 | links.add(linkTo(methodOn(DomainsController.class) 74 | .getDomainsStates(domain, protocol, includeCertificates,paginatedStatesDto.getNumber()-1, paginatedStatesDto.getSize())) 75 | .withRel(IanaLinkRelations.PREVIOUS) 76 | ); 77 | } 78 | } 79 | return PagedModel.of( 80 | stateModels, 81 | new PagedModel.PageMetadata( 82 | stateModels.size(), 83 | paginatedStatesDto.getNumber(), 84 | paginatedStatesDto.getTotalElements(), 85 | paginatedStatesDto.getTotalPages() 86 | ), 87 | links 88 | ); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/api/security/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.api.security; 19 | 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 23 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 24 | import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; 25 | import org.springframework.security.crypto.argon2.Argon2PasswordEncoder; 26 | import org.springframework.security.crypto.password.PasswordEncoder; 27 | import org.springframework.security.web.SecurityFilterChain; 28 | 29 | /** 30 | * Created by Kyriakos Bompotis on 4/9/20. 31 | */ 32 | @Configuration 33 | @EnableWebSecurity 34 | public class WebSecurityConfig { 35 | 36 | @Bean 37 | public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { 38 | return http.csrf(AbstractHttpConfigurer::disable) 39 | .authorizeHttpRequests(auth -> auth.anyRequest().permitAll()).build(); 40 | } 41 | 42 | @Bean 43 | public PasswordEncoder passwordEncoder() { 44 | return Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/entity/AbstractTimestampable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.entity; 19 | 20 | import org.springframework.data.annotation.CreatedDate; 21 | import org.springframework.data.annotation.LastModifiedDate; 22 | import org.springframework.data.domain.Persistable; 23 | 24 | import jakarta.persistence.MappedSuperclass; 25 | import jakarta.persistence.Column; 26 | import jakarta.persistence.PrePersist; 27 | import jakarta.persistence.PreUpdate; 28 | import jakarta.persistence.PreRemove; 29 | import java.io.Serializable; 30 | import java.util.Date; 31 | 32 | /** 33 | * Created by Kyriakos Bompotis on 16/6/20. 34 | */ 35 | @MappedSuperclass 36 | public abstract class AbstractTimestampable implements Persistable { 37 | @CreatedDate 38 | @Column(name = "created_at") 39 | protected Date createdAt; 40 | 41 | @LastModifiedDate 42 | @Column(name = "updated_at") 43 | private Date updatedAt; 44 | 45 | protected AbstractTimestampable() {} 46 | 47 | public Date getCreatedAt() { 48 | return createdAt; 49 | } 50 | 51 | public Date getUpdatedAt() { 52 | return updatedAt; 53 | } 54 | 55 | @PrePersist 56 | protected void prePersist() { 57 | if (this.createdAt == null) createdAt = new Date(); 58 | if (this.updatedAt == null) updatedAt = new Date(); 59 | } 60 | 61 | @PreUpdate 62 | protected void preUpdate() { 63 | if (this.createdAt == null) createdAt = new Date(); 64 | this.updatedAt = new Date(); 65 | } 66 | 67 | @PreRemove 68 | protected void preRemove() { 69 | this.updatedAt = new Date(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/entity/AbstractTimestampablePersistable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.entity; 19 | 20 | import org.hibernate.annotations.GenericGenerator; 21 | import org.springframework.data.annotation.CreatedDate; 22 | import org.springframework.data.annotation.LastModifiedDate; 23 | import org.springframework.data.annotation.Transient; 24 | import org.springframework.data.domain.Persistable; 25 | 26 | import jakarta.persistence.MappedSuperclass; 27 | import jakarta.persistence.Id; 28 | import jakarta.persistence.GeneratedValue; 29 | import jakarta.persistence.Column; 30 | import jakarta.persistence.PrePersist; 31 | import jakarta.persistence.PreUpdate; 32 | import jakarta.persistence.PreRemove; 33 | import java.io.Serializable; 34 | import java.util.Date; 35 | 36 | /** 37 | * Created by Kyriakos Bompotis on 16/6/20. 38 | */ 39 | @MappedSuperclass 40 | public abstract class AbstractTimestampablePersistable implements Persistable { 41 | 42 | @Id 43 | @GeneratedValue(generator="uuid") 44 | @GenericGenerator(name="uuid", strategy = "uuid2") 45 | @Column(name = "id") 46 | protected K id; 47 | 48 | @CreatedDate 49 | @Column(name = "created_at") 50 | protected Date createdAt; 51 | 52 | @LastModifiedDate 53 | @Column(name = "updated_at") 54 | private Date updatedAt; 55 | 56 | protected AbstractTimestampablePersistable() {} 57 | 58 | public K getId() { 59 | return this.id; 60 | } 61 | 62 | @Transient 63 | public boolean isNew() { 64 | return null == this.getId(); 65 | } 66 | 67 | public Date getCreatedAt() { 68 | return null == createdAt ? null : createdAt; 69 | } 70 | 71 | public Date getUpdatedAt() { 72 | return updatedAt; 73 | } 74 | 75 | @PrePersist 76 | protected void prePersist() { 77 | if (this.createdAt == null) createdAt = new Date(); 78 | if (this.updatedAt == null) updatedAt = new Date(); 79 | } 80 | 81 | @PreUpdate 82 | protected void preUpdate() { 83 | this.updatedAt = new Date(); 84 | } 85 | 86 | @PreRemove 87 | protected void preRemove() { 88 | this.updatedAt = new Date(); 89 | } 90 | 91 | public String toString() { 92 | return String.format("Entity of type %s with id: %s", this.getClass().getName(), this.getId()); 93 | } 94 | } -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/entity/EntityBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.entity; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 8/9/20. 22 | */ 23 | public interface EntityBuilder { 24 | T build(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/entity/OperationUpdater.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.entity; 19 | 20 | import com.bompotis.netcheck.service.dto.Operation; 21 | 22 | /** 23 | * Created by Kyriakos Bompotis on 8/9/20. 24 | */ 25 | public interface OperationUpdater extends EntityBuilder { 26 | void removeField(String field, String path); 27 | 28 | void updateField(String field, String path, String value); 29 | 30 | default void processOperation(Operation operation) { 31 | switch (operation.action()) { 32 | case REMOVE -> removeField(operation.field(), operation.path()); 33 | case ADD, UPDATE -> updateField(operation.field(), operation.path(), operation.value()); 34 | default -> throw new IllegalArgumentException("Invalid operation"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/entity/ServerMetricEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.entity; 19 | 20 | import io.hypersistence.utils.hibernate.type.json.JsonBinaryType; 21 | import jakarta.persistence.*; 22 | import org.hibernate.annotations.Type; 23 | import org.springframework.lang.NonNull; 24 | 25 | import java.util.Date; 26 | import java.util.Map; 27 | import java.util.Objects; 28 | 29 | /** 30 | * Created by Kyriakos Bompotis on 5/9/20. 31 | */ 32 | @Entity 33 | @Table(name = "server_metric", indexes = { 34 | @Index(name = "server_metrics__server_created_idx", columnList = "server_id, created_at") 35 | }) 36 | public class ServerMetricEntity extends AbstractTimestampablePersistable{ 37 | 38 | @NonNull 39 | @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) 40 | @JoinColumn(name = "server_id") 41 | private ServerEntity serverEntity; 42 | 43 | @NonNull 44 | @Type(JsonBinaryType.class) 45 | @Column(columnDefinition = "jsonb", name = "metrics") 46 | private Map metrics; 47 | 48 | @NonNull 49 | @Column(name = "collected_at") 50 | private Date collectedAt; 51 | 52 | @NonNull 53 | public ServerEntity getServerEntity() { 54 | return serverEntity; 55 | } 56 | 57 | @NonNull 58 | public Map getMetrics() { 59 | return metrics; 60 | } 61 | 62 | @NonNull 63 | public Date getCollectedAt() { 64 | return collectedAt; 65 | } 66 | 67 | protected ServerMetricEntity() {} 68 | 69 | public static class Builder { 70 | private ServerEntity serverEntity; 71 | private Map metrics; 72 | private Date collectedAt; 73 | 74 | public Builder metrics(Map metrics) { 75 | this.metrics = metrics; 76 | return this; 77 | } 78 | 79 | public Builder serverEntity(ServerEntity serverEntity) { 80 | this.serverEntity = serverEntity; 81 | return this; 82 | } 83 | 84 | public Builder collectedAt(Date collectedAt) { 85 | this.collectedAt = collectedAt; 86 | return this; 87 | } 88 | 89 | public ServerMetricEntity build() { 90 | return new ServerMetricEntity(this); 91 | } 92 | } 93 | 94 | private ServerMetricEntity(Builder b) { 95 | this.metrics = b.metrics; 96 | this.serverEntity = b.serverEntity; 97 | this.collectedAt = b.collectedAt; 98 | } 99 | 100 | 101 | @Override 102 | public boolean equals(Object o) { 103 | if (this == o) return true; 104 | if (o == null || getClass() != o.getClass()) return false; 105 | ServerMetricEntity that = (ServerMetricEntity) o; 106 | return serverEntity.equals(that.serverEntity) && 107 | metrics.equals(that.metrics); 108 | } 109 | 110 | @Override 111 | public int hashCode() { 112 | return Objects.hash(serverEntity, metrics); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/repository/DomainMetricRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.repository; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainMetricEntity; 21 | import org.springframework.data.domain.Page; 22 | import org.springframework.data.domain.Pageable; 23 | import org.springframework.data.jpa.repository.JpaRepository; 24 | import org.springframework.data.jpa.repository.Query; 25 | import org.springframework.stereotype.Repository; 26 | 27 | import java.util.Date; 28 | import java.util.Set; 29 | 30 | /** 31 | * Domain Metric specific extension of {@link org.springframework.data.jpa.repository.JpaRepository}. 32 | * 33 | * @author Kyriakos Bompotis 34 | */ 35 | @Repository 36 | public interface DomainMetricRepository extends JpaRepository { 37 | @Query("select d from DomainMetricEntity d where d.domain = ?1 " + 38 | "and d.periodType = ?2 and d.createdAt >= ?3 and d.createdAt < ?4") 39 | Set findAllBetweenDates(String domain, String period, Date startDate, Date endDate); 40 | 41 | Page findAllByDomainAndProtocolAndPeriodType(String domain, DomainMetricEntity.Protocol protocol, DomainMetricEntity.Period periodType, Pageable pageable); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/repository/DomainRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.repository; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainEntity; 21 | import org.springframework.data.domain.Page; 22 | import org.springframework.data.domain.Pageable; 23 | import org.springframework.data.jpa.repository.JpaRepository; 24 | import org.springframework.data.jpa.repository.Query; 25 | import org.springframework.stereotype.Repository; 26 | 27 | /** 28 | * Domain specific extension of {@link org.springframework.data.jpa.repository.JpaRepository}. 29 | * 30 | * @author Kyriakos Bompotis 31 | */ 32 | @Repository 33 | public interface DomainRepository extends JpaRepository { 34 | @Query("select d from DomainEntity d where d.domain like %?1%") 35 | Page findAllFiltered(String filter, Pageable pageable); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/repository/ServerMetricDefinitionRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.repository; 19 | 20 | import com.bompotis.netcheck.data.entity.ServerMetricDefinitionEntity; 21 | import org.springframework.data.jpa.repository.JpaRepository; 22 | import org.springframework.stereotype.Repository; 23 | 24 | /** 25 | * Server Metric Definition specific extension of {@link org.springframework.data.jpa.repository.JpaRepository}. 26 | * 27 | * @author Kyriakos Bompotis 28 | */ 29 | @Repository 30 | public interface ServerMetricDefinitionRepository extends JpaRepository { 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/repository/ServerMetricRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.repository; 19 | 20 | import com.bompotis.netcheck.data.entity.ServerMetricEntity; 21 | import org.springframework.data.jpa.repository.JpaRepository; 22 | 23 | /** 24 | * Server Metric specific extension of {@link org.springframework.data.jpa.repository.JpaRepository}. 25 | * 26 | * @author Kyriakos Bompotis 27 | */ 28 | public interface ServerMetricRepository extends JpaRepository { 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/data/repository/ServerRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.data.repository; 19 | 20 | import com.bompotis.netcheck.data.entity.ServerEntity; 21 | import org.springframework.data.domain.Page; 22 | import org.springframework.data.domain.Pageable; 23 | import org.springframework.data.jpa.repository.JpaRepository; 24 | import org.springframework.data.jpa.repository.Query; 25 | import org.springframework.stereotype.Repository; 26 | 27 | /** 28 | * Server specific extension of {@link org.springframework.data.jpa.repository.JpaRepository}. 29 | * 30 | * @author Kyriakos Bompotis 31 | */ 32 | @Repository 33 | public interface ServerRepository extends JpaRepository { 34 | @Query("select s from ServerEntity s where s.serverName like %?1%") 35 | Page findAllFiltered(String filter, Pageable pageable); 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/JobCompletionNotificationListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch; 19 | 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.batch.core.BatchStatus; 23 | import org.springframework.batch.core.JobExecution; 24 | import org.springframework.batch.core.listener.JobExecutionListenerSupport; 25 | import org.springframework.stereotype.Component; 26 | 27 | /** 28 | * Created by Kyriakos Bompotis on 10/6/20. 29 | */ 30 | @Component 31 | public class JobCompletionNotificationListener extends JobExecutionListenerSupport { 32 | 33 | private static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class); 34 | 35 | @Override 36 | public void afterJob(JobExecution jobExecution) { 37 | if(jobExecution.getStatus() == BatchStatus.COMPLETED) { 38 | log.info("!!! JOB FINISHED!"); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/CheckEventDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainCheckEntity; 21 | import com.google.gson.Gson; 22 | import org.springframework.context.ApplicationEvent; 23 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 24 | 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | 28 | import static org.springframework.http.MediaType.APPLICATION_JSON; 29 | 30 | /** 31 | * Created by Kyriakos Bompotis on 25/8/20. 32 | */ 33 | public class CheckEventDto extends ApplicationEvent implements EventDto { 34 | 35 | private final SseEmitter.SseEventBuilder event; 36 | 37 | public CheckEventDto(Object source, DomainCheckEntity domainCheckEntity) { 38 | super(source); 39 | Map messageMap = new HashMap<>(); 40 | messageMap.put("domain",domainCheckEntity.getDomain()); 41 | messageMap.put("timeCheckedOn", domainCheckEntity.getTimeCheckedOn()); 42 | messageMap.put("changeType", domainCheckEntity.getChangeType()); 43 | event = SseEmitter.event() 44 | .data(new Gson().toJson(messageMap), APPLICATION_JSON) 45 | .reconnectTime(1000L) 46 | .name("DomainCheck_"+domainCheckEntity.getDomain()); 47 | } 48 | 49 | public SseEmitter.SseEventBuilder getEvent() { 50 | return event; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/EventDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification; 19 | 20 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 21 | 22 | /** 23 | * Created by Kyriakos Bompotis on 26/8/20. 24 | */ 25 | public interface EventDto { 26 | SseEmitter.SseEventBuilder getEvent(); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/NotificationEventDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification; 19 | 20 | import com.google.gson.Gson; 21 | import org.springframework.context.ApplicationEvent; 22 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 23 | 24 | import static org.springframework.http.MediaType.APPLICATION_JSON; 25 | 26 | /** 27 | * Created by Kyriakos Bompotis on 25/8/20. 28 | */ 29 | public class NotificationEventDto extends ApplicationEvent implements EventDto { 30 | 31 | private final SseEmitter.SseEventBuilder event; 32 | 33 | public NotificationEventDto(Object source, NotificationDto notificationDto) { 34 | super(source); 35 | event = SseEmitter.event() 36 | .data(new Gson().toJson(notificationDto), APPLICATION_JSON) 37 | .reconnectTime(1000L) 38 | .name("Notification"); 39 | } 40 | 41 | public SseEmitter.SseEventBuilder getEvent() { 42 | return event; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/NotificationEventService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification; 19 | 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.context.ApplicationEventPublisher; 22 | import org.springframework.stereotype.Service; 23 | 24 | /** 25 | * Created by Kyriakos Bompotis on 25/8/20. 26 | */ 27 | @Service 28 | public class NotificationEventService implements NotificationService { 29 | 30 | private final ApplicationEventPublisher eventPublisher; 31 | 32 | @Autowired 33 | public NotificationEventService(ApplicationEventPublisher eventPublisher) { 34 | this.eventPublisher = eventPublisher; 35 | } 36 | 37 | @Override 38 | public boolean isEnabled() { 39 | return true; 40 | } 41 | 42 | @Override 43 | public String name() { 44 | return "NotificationEvent"; 45 | } 46 | 47 | @Override 48 | public void notify(NotificationDto notification) { 49 | eventPublisher.publishEvent(new NotificationEventDto(this, notification)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/NotificationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 1/7/20. 22 | */ 23 | public interface NotificationService { 24 | boolean isEnabled(); 25 | String name(); 26 | void notify(NotificationDto notification); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/PushoverService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification; 19 | 20 | import com.bompotis.netcheck.scheduler.batch.notification.client.PushoverMessage; 21 | import com.bompotis.netcheck.scheduler.batch.notification.client.PushoverRestClient; 22 | import com.bompotis.netcheck.scheduler.batch.notification.config.PushoverConfig; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.stereotype.Service; 27 | 28 | import java.util.Optional; 29 | import java.util.Set; 30 | 31 | /** 32 | * Created by Kyriakos Bompotis on 1/7/20. 33 | */ 34 | @Service 35 | public class PushoverService implements NotificationService { 36 | 37 | private final PushoverConfig pushoverConfig; 38 | 39 | private static final Logger log = LoggerFactory.getLogger(PushoverService.class); 40 | 41 | @Autowired 42 | public PushoverService(PushoverConfig pushoverConfig) { 43 | this.pushoverConfig = pushoverConfig; 44 | } 45 | 46 | @Override 47 | public boolean isEnabled() { 48 | return Optional.ofNullable(pushoverConfig.getEnabled()).orElse(false); 49 | } 50 | 51 | @Override 52 | public String name() { 53 | return "Pushover"; 54 | } 55 | 56 | @Override 57 | public void notify(NotificationDto notification) { 58 | var protocols = pushoverConfig.getNotifyOnlyFor().isEmpty() 59 | ? Set.of("HTTP","HTTPS","CERTIFICATE") 60 | : Set.copyOf(pushoverConfig.getNotifyOnlyFor()); 61 | if (protocols.contains(notification.getType().name())) { 62 | new PushoverRestClient().pushMessage(PushoverMessage 63 | .builderWithApiToken(pushoverConfig.getApiToken()) 64 | .setUserId(pushoverConfig.getUserIdToken()) 65 | .setMessage(notification.getMessage()) 66 | .build() 67 | ); 68 | } else { 69 | log.info("Pushover notifications for type {} are disabled. Skipping!", notification.getType().name()); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/ServerMetricEventDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification; 19 | 20 | import com.bompotis.netcheck.service.dto.ServerMetricDto; 21 | import com.google.gson.Gson; 22 | import org.springframework.context.ApplicationEvent; 23 | import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; 24 | 25 | import static org.springframework.http.MediaType.APPLICATION_JSON; 26 | 27 | 28 | public class ServerMetricEventDto extends ApplicationEvent implements EventDto { 29 | 30 | private final SseEmitter.SseEventBuilder event; 31 | 32 | public ServerMetricEventDto(Object source, ServerMetricDto.ServerMetricEvent serverMetricEvent) { 33 | super(source); 34 | event = SseEmitter.event() 35 | .data(new Gson().toJson(serverMetricEvent), APPLICATION_JSON) 36 | .reconnectTime(1000L) 37 | .name("ServerMetrics_" + serverMetricEvent.getServerId()); 38 | } 39 | 40 | public SseEmitter.SseEventBuilder getEvent() { 41 | return event; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/WebhookService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification; 19 | 20 | import com.bompotis.netcheck.scheduler.batch.notification.config.WebhookConfig; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.http.HttpHeaders; 25 | import org.springframework.http.MediaType; 26 | import org.springframework.stereotype.Service; 27 | import org.springframework.web.reactive.function.BodyInserters; 28 | import org.springframework.web.reactive.function.client.WebClient; 29 | 30 | import java.time.Duration; 31 | import java.util.Collections; 32 | import java.util.Objects; 33 | import java.util.Optional; 34 | import java.util.Set; 35 | 36 | /** 37 | * Created by Kyriakos Bompotis on 10/8/20. 38 | */ 39 | @Service 40 | public class WebhookService implements NotificationService { 41 | 42 | private final WebhookConfig webhookConfig; 43 | 44 | private static final Logger log = LoggerFactory.getLogger(WebhookService.class); 45 | 46 | @Autowired 47 | public WebhookService(WebhookConfig webhookConfig) { 48 | this.webhookConfig = webhookConfig; 49 | } 50 | 51 | @Override 52 | public boolean isEnabled() { 53 | return Optional.ofNullable(webhookConfig.getEnabled()).orElse(false); 54 | } 55 | 56 | @Override 57 | public String name() { 58 | return "Webhook"; 59 | } 60 | 61 | @Override 62 | public void notify(NotificationDto notification) { 63 | Set protocols = webhookConfig.getNotifyOnlyFor().isEmpty() ? Set.of("HTTP","HTTPS","CERTIFICATE") : Set.copyOf(webhookConfig.getNotifyOnlyFor()); 64 | if (protocols.contains(notification.getType().name())) { 65 | log.info("Preparing client for domain {}", webhookConfig.getBaseUrl()); 66 | var client = WebClient 67 | .builder() 68 | .baseUrl(webhookConfig.getBaseUrl()) 69 | .defaultCookie("cookieKey", "cookieValue") 70 | .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) 71 | .defaultUriVariables(Collections.singletonMap("url", webhookConfig.getBaseUrl())) 72 | .build(); 73 | log.info("Sending notification to {}", webhookConfig.getEndpoint()); 74 | var response = Objects.requireNonNull(client.post() 75 | .uri(webhookConfig.getEndpoint()) 76 | .body(BodyInserters.fromValue(notification)) 77 | .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) 78 | .exchange() 79 | .block(Duration.ofSeconds(30))) 80 | .rawStatusCode(); 81 | log.info("Webhook response code: {}", response); 82 | } else { 83 | log.info("Webhook notifications for type {} are disabled. Skipping!", notification.getType().name()); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/client/MessagePriority.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.scheduler.batch.notification.client; 2 | 3 | public enum MessagePriority { 4 | LOWEST(-2), LOW(-1), QUIET(-1), NORMAL(0), HIGH(1), EMERGENCY(2); 5 | private final int priority; 6 | 7 | MessagePriority(int priority) { 8 | this.priority = priority; 9 | } 10 | 11 | public int getPriority() { 12 | return priority; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return String.valueOf(this.priority); 18 | } 19 | } -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/client/PushoverMessage.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.scheduler.batch.notification.client; 2 | 3 | public class PushoverMessage { 4 | 5 | private String apiToken; 6 | private String userId; 7 | private String message; 8 | private String htmlMessage; 9 | private String device; 10 | private String title; 11 | private String url; 12 | private String titleForURL; 13 | private MessagePriority priority = MessagePriority.NORMAL; 14 | private Long timestamp; 15 | private String sound; 16 | private PushoverMessage() {} 17 | public static Builder builderWithApiToken(String token) { 18 | return new Builder().setApiToken(token); 19 | } 20 | public static class Builder { 21 | private final PushoverMessage msg; 22 | 23 | public Builder() { 24 | msg = new PushoverMessage(); 25 | } 26 | 27 | public PushoverMessage build() { 28 | return msg; 29 | } 30 | 31 | /** 32 | * (required) - your application's API token 33 | */ 34 | public Builder setApiToken(String apiToken) { 35 | msg.apiToken = apiToken; 36 | return this; 37 | } 38 | 39 | /** 40 | * (required) - the user key (not e-mail address) of your user (or you), 41 | * viewable when logged into the dashboard 42 | */ 43 | public Builder setUserId(String userId) { 44 | msg.userId = userId; 45 | return this; 46 | } 47 | 48 | /** 49 | * (required) - your message 50 | */ 51 | public Builder setMessage(String message) { 52 | msg.message = message; 53 | return this; 54 | } 55 | 56 | public Builder setHtmlMessage(String htmlMessage) { 57 | msg.htmlMessage = htmlMessage; 58 | return this; 59 | } 60 | 61 | /** 62 | * (optional) - your user's device identifier to send the message 63 | * directly to that device, rather than all of the user's devices 64 | */ 65 | public Builder setDevice(String device) { 66 | msg.device = device; 67 | return this; 68 | } 69 | 70 | /** 71 | * (optional) - your message's title, otherwise uses your app's name 72 | */ 73 | public Builder setTitle(String title) { 74 | msg.title = title; 75 | return this; 76 | } 77 | 78 | /** 79 | * (optional) - a supplementary URL to show with your message 80 | */ 81 | public Builder setUrl(String url) { 82 | msg.url = url; 83 | return this; 84 | } 85 | 86 | /** 87 | * (optional) - a title for your supplementary URL 88 | */ 89 | public Builder setTitleForURL(String titleForURL) { 90 | msg.titleForURL = titleForURL; 91 | return this; 92 | } 93 | 94 | /** 95 | * (optional) - set to MessagePriority.HIGH to display as high-priority 96 | * and bypass quiet hours, or MessagePriority.QUIET to always send as a 97 | * quiet notification 98 | */ 99 | public Builder setPriority(MessagePriority priority) { 100 | msg.priority = priority; 101 | return this; 102 | } 103 | 104 | /** 105 | * (optional) - set to a Unix timestamp to have your message show with a 106 | * particular time, rather than now 107 | */ 108 | public Builder setTimestamp(Long timestamp) { 109 | msg.timestamp = timestamp; 110 | return this; 111 | } 112 | 113 | /** 114 | * (optional) - set to the name of one of the sounds supported by device 115 | * clients to override the user's default sound choice 116 | */ 117 | public Builder setSound(String sound) { 118 | msg.sound = sound; 119 | return this; 120 | } 121 | } 122 | 123 | public String getApiToken() { 124 | return apiToken; 125 | } 126 | 127 | public String getUserId() { 128 | return userId; 129 | } 130 | 131 | public String getMessage() { 132 | return message; 133 | } 134 | 135 | public String getDevice() { 136 | return device; 137 | } 138 | 139 | public String getTitle() { 140 | return title; 141 | } 142 | 143 | public String getUrl() { 144 | return url; 145 | } 146 | 147 | public String getTitleForURL() { 148 | return titleForURL; 149 | } 150 | 151 | public MessagePriority getPriority() { 152 | return priority; 153 | } 154 | 155 | public Long getTimestamp() { 156 | return timestamp; 157 | } 158 | 159 | public String getSound() { 160 | return sound; 161 | } 162 | 163 | public String getHtmlMessage() { 164 | return htmlMessage; 165 | } 166 | 167 | } -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/client/PushoverRestClient.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.scheduler.batch.notification.client; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.HttpStatusCode; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.util.LinkedMultiValueMap; 9 | import org.springframework.util.MultiValueMap; 10 | import org.springframework.web.reactive.function.BodyInserters; 11 | import org.springframework.web.reactive.function.client.WebClient; 12 | import reactor.core.publisher.Mono; 13 | 14 | public class PushoverRestClient { 15 | 16 | private record PushoverErrorResponse(HttpStatusCode statusCode) {} 17 | 18 | public static final String PUSH_MESSAGE_URL = "https://api.pushover.net/1/messages.json"; 19 | 20 | public static final String REQUEST_ID_HEADER = "X-Request-Id"; 21 | 22 | private static final Logger log = LoggerFactory.getLogger(PushoverRestClient.class); 23 | 24 | public void pushMessage(PushoverMessage msg) { 25 | 26 | final var post = WebClient.create().post().uri(PUSH_MESSAGE_URL) 27 | .contentType(MediaType.APPLICATION_FORM_URLENCODED); 28 | 29 | final var valueMap = new LinkedMultiValueMap(); 30 | 31 | valueMap.add("token", msg.getApiToken()); 32 | valueMap.add("user", msg.getUserId()); 33 | if (msg.getHtmlMessage() != null && !msg.getHtmlMessage().trim().isEmpty()) { 34 | valueMap.add("message", msg.getHtmlMessage()); 35 | } else { 36 | valueMap.add("message", msg.getMessage()); 37 | } 38 | 39 | addPairIfNotNull(valueMap, "title", msg.getTitle()); 40 | 41 | addPairIfNotNull(valueMap, "url", msg.getUrl()); 42 | addPairIfNotNull(valueMap, "url_title", msg.getTitleForURL()); 43 | 44 | addPairIfNotNull(valueMap, "device", msg.getDevice()); 45 | addPairIfNotNull(valueMap, "timestamp", msg.getTimestamp()); 46 | addPairIfNotNull(valueMap, "sound", msg.getSound()); 47 | 48 | if (msg.getHtmlMessage() != null && !msg.getHtmlMessage().trim().isEmpty()) { 49 | addPairIfNotNull(valueMap, "html", "1"); 50 | } 51 | 52 | if (!MessagePriority.NORMAL.equals(msg.getPriority())) { 53 | addPairIfNotNull(valueMap, "priority", msg.getPriority()); 54 | } 55 | 56 | var ref = new Object() { 57 | String requestId; 58 | }; 59 | post.body(BodyInserters.fromFormData(valueMap)).exchangeToMono(response -> { 60 | var statusCode = response.statusCode(); 61 | if (statusCode.equals(HttpStatus.OK)) { 62 | ref.requestId = response.headers().header(REQUEST_ID_HEADER).get(0); 63 | return response.bodyToMono(PushoverResponse.class); 64 | } 65 | return Mono.just(new PushoverErrorResponse(statusCode)); 66 | }).single().subscribe(result -> { 67 | if (result.getClass().equals(PushoverResponse.class)) { 68 | var r = (PushoverResponse) result; 69 | log.info("Pushover notification response: status {}, requestId {}.",r.status, ref.requestId); 70 | } else if (result.getClass().equals(PushoverErrorResponse.class)) { 71 | var r = (PushoverErrorResponse) result; 72 | log.error("Pushover request failed with status code {}.",r.statusCode.value()); 73 | } 74 | }); 75 | } 76 | 77 | 78 | private void addPairIfNotNull(MultiValueMap multiValueMap, String key, Object value) { 79 | if (value != null) { 80 | multiValueMap.add(key, value.toString()); 81 | } 82 | } 83 | 84 | public static class PushoverResponse { 85 | int status; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/config/PushoverConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification.config; 19 | 20 | import org.springframework.boot.context.properties.ConfigurationProperties; 21 | 22 | import java.util.HashSet; 23 | import java.util.Optional; 24 | import java.util.Set; 25 | 26 | /** 27 | * Created by Kyriakos Bompotis on 15/7/20. 28 | */ 29 | @ConfigurationProperties(prefix = "settings.notifications.pushover") 30 | public class PushoverConfig { 31 | 32 | private final boolean enabled; 33 | 34 | private final String userIdToken; 35 | 36 | private final String apiToken; 37 | 38 | private final Set notifyOnlyFor; 39 | 40 | public PushoverConfig(Boolean enabled, String userIdToken, String apiToken, Set notifyOnlyFor) { 41 | this.enabled = Optional.ofNullable(enabled).orElse(false); 42 | this.userIdToken = userIdToken; 43 | this.apiToken = apiToken; 44 | var acceptableEntries = Set.of("HTTP","HTTPS","CERTIFICATE"); 45 | if (Optional.ofNullable(notifyOnlyFor).isEmpty() || notifyOnlyFor.isEmpty()) { 46 | this.notifyOnlyFor = acceptableEntries; 47 | } else { 48 | var finalSet = new HashSet(); 49 | for (var entry: notifyOnlyFor) { 50 | if (acceptableEntries.contains(entry.toUpperCase())) { 51 | finalSet.add(entry.toUpperCase()); 52 | } 53 | else { 54 | throw new IllegalArgumentException("No such type of notification:" + entry); 55 | } 56 | } 57 | this.notifyOnlyFor = finalSet; 58 | } 59 | } 60 | 61 | public Boolean getEnabled() { 62 | return enabled; 63 | } 64 | 65 | public String getUserIdToken() { 66 | return userIdToken; 67 | } 68 | 69 | public String getApiToken() { 70 | return apiToken; 71 | } 72 | 73 | public Set getNotifyOnlyFor() { 74 | return notifyOnlyFor; 75 | } 76 | } -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/notification/config/WebhookConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.notification.config; 19 | 20 | import org.springframework.boot.context.properties.ConfigurationProperties; 21 | 22 | import java.util.HashSet; 23 | import java.util.Optional; 24 | import java.util.Set; 25 | 26 | /** 27 | * Created by Kyriakos Bompotis on 10/8/20. 28 | */ 29 | @ConfigurationProperties(prefix = "settings.notifications.webhook") 30 | public class WebhookConfig { 31 | private final Boolean enabled; 32 | 33 | private final String baseUrl; 34 | 35 | private final String endpoint; 36 | 37 | private final Set notifyOnlyFor; 38 | 39 | public WebhookConfig(Boolean enabled, String baseUrl, String endpoint, Set notifyOnlyFor) { 40 | this.enabled = Optional.ofNullable(enabled).orElse(false); 41 | this.baseUrl = baseUrl; 42 | this.endpoint = endpoint; 43 | var acceptableEntries = Set.of("HTTP","HTTPS","CERTIFICATE"); 44 | if (Optional.ofNullable(notifyOnlyFor).isEmpty() || notifyOnlyFor.isEmpty()) { 45 | this.notifyOnlyFor = acceptableEntries; 46 | } else { 47 | var finalSet = new HashSet(); 48 | for (var entry: notifyOnlyFor) { 49 | if (acceptableEntries.contains(entry.toUpperCase())) { 50 | finalSet.add(entry.toUpperCase()); 51 | } 52 | else { 53 | throw new IllegalArgumentException("No such type of notification:" + entry); 54 | } 55 | } 56 | this.notifyOnlyFor = finalSet; 57 | } 58 | } 59 | 60 | public Boolean getEnabled() { 61 | return enabled; 62 | } 63 | 64 | public String getBaseUrl() { 65 | return baseUrl; 66 | } 67 | 68 | public Set getNotifyOnlyFor() { 69 | return notifyOnlyFor; 70 | } 71 | 72 | public String getEndpoint() { 73 | return endpoint; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/processor/DomainCheckProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.processor; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainCheckEntity; 21 | import com.bompotis.netcheck.data.entity.DomainEntity; 22 | import com.bompotis.netcheck.service.DomainService; 23 | import com.bompotis.netcheck.service.dto.DomainDto; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.springframework.batch.item.ItemProcessor; 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.lang.NonNull; 29 | import org.springframework.stereotype.Component; 30 | import org.springframework.transaction.annotation.Transactional; 31 | 32 | import java.io.IOException; 33 | import java.security.KeyManagementException; 34 | import java.security.NoSuchAlgorithmException; 35 | import java.time.ZoneOffset; 36 | import java.util.Date; 37 | 38 | /** 39 | * Created by Kyriakos Bompotis on 10/6/20. 40 | */ 41 | @Component 42 | @Transactional 43 | public class DomainCheckProcessor implements ItemProcessor { 44 | 45 | private final DomainService domainService; 46 | 47 | private static final Logger log = LoggerFactory.getLogger(DomainCheckProcessor.class); 48 | 49 | @Autowired 50 | public DomainCheckProcessor(DomainService domainService) { 51 | this.domainService = domainService; 52 | } 53 | 54 | @Override 55 | public DomainCheckEntity process(@NonNull DomainEntity domainEntity) { 56 | DomainCheckEntity domainCheckEntity = null; 57 | try { 58 | log.info("Processing {}", domainEntity.getDomain()); 59 | if (isEligibleForCheck(domainEntity.getDomain())) { 60 | log.info("Domain {} is eligible for check", domainEntity.getDomain()); 61 | domainCheckEntity = check(domainEntity); 62 | log.info("Successfully checked {}. Passing to writer", domainEntity.getDomain()); 63 | } else { 64 | log.info("Skipping check for domain {}.", domainEntity.getDomain()); 65 | } 66 | } catch (Exception e) { 67 | log.error("Failed to check {}", domainEntity.getDomain(), e); 68 | } 69 | return domainCheckEntity; 70 | } 71 | 72 | private DomainCheckEntity check(DomainEntity domainEntity) throws NoSuchAlgorithmException, IOException, KeyManagementException { 73 | log.info("Checking {}", domainEntity.getDomain()); 74 | var domainDto = new DomainDto.Builder() 75 | .domain(domainEntity.getDomain()) 76 | .endpoint(domainEntity.getEndpoint()) 77 | .withHeaders(domainEntity.getHeaders()) 78 | .timeoutMs(domainEntity.getTimeoutMs()) 79 | .build(); 80 | var status = domainService.check(domainDto); 81 | return domainService.convertToDomainCheckEntity(status, domainEntity); 82 | } 83 | 84 | private boolean isEligibleForCheck(String domain) { 85 | var optionalDomainWithLastChecks = domainService.getDomain(domain); 86 | if (optionalDomainWithLastChecks.isEmpty()) { 87 | log.info("No checks found for {}", domain); 88 | return true; 89 | } 90 | var domainWithLastChecks = optionalDomainWithLastChecks.get(); 91 | var lastCheckDate = domainWithLastChecks 92 | .getLastDomainCheck() 93 | .getHttpCheckDto() 94 | .getTimeCheckedOn() 95 | .toInstant() 96 | .atZone(ZoneOffset.UTC) 97 | .toLocalDateTime() 98 | .withSecond(0); 99 | log.info("Last check for domain {} was triggered on {}", domain, lastCheckDate); 100 | var now = new Date().toInstant().atZone(ZoneOffset.UTC).toLocalDateTime(); 101 | var nextExpectedCheck = lastCheckDate.plusMinutes(domainWithLastChecks.getCheckFrequencyMinutes()); 102 | return nextExpectedCheck.isBefore(now); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/processor/DomainMetricProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.processor; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainEntity; 21 | import com.bompotis.netcheck.data.entity.DomainMetricEntity; 22 | import com.bompotis.netcheck.service.MetricService; 23 | import org.springframework.batch.item.ItemProcessor; 24 | import org.springframework.lang.NonNull; 25 | 26 | import java.util.List; 27 | 28 | /** 29 | * Created by Kyriakos Bompotis on 29/6/20. 30 | */ 31 | public class DomainMetricProcessor implements ItemProcessor> { 32 | 33 | private final MetricService metricService; 34 | 35 | private final MetricService.ScheduledPeriod period; 36 | 37 | public DomainMetricProcessor(MetricService.ScheduledPeriod period, 38 | MetricService metricService) { 39 | this.period = period; 40 | this.metricService = metricService; 41 | } 42 | 43 | @Override 44 | public List process(@NonNull DomainEntity domainEntity) { 45 | return metricService.generateMetric(domainEntity,new MetricService.TimeFrame(this.period)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/reader/OldDomainCheckItemReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.reader; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainCheckEntity; 21 | import com.bompotis.netcheck.data.repository.DomainCheckRepository; 22 | import org.springframework.batch.item.data.RepositoryItemReader; 23 | import org.springframework.data.domain.Sort; 24 | import org.springframework.lang.NonNull; 25 | 26 | import java.time.LocalDateTime; 27 | import java.time.ZoneOffset; 28 | import java.util.Date; 29 | import java.util.List; 30 | import java.util.Map; 31 | 32 | /** 33 | * Created by Kyriakos Bompotis on 13/7/20. 34 | */ 35 | public class OldDomainCheckItemReader extends RepositoryItemReader { 36 | 37 | private final int threshold; 38 | 39 | public OldDomainCheckItemReader(DomainCheckRepository domainCheckRepository, Integer threshold) { 40 | this.setRepository(domainCheckRepository); 41 | this.setMethodName("findAllNonFirstCheckedBeforeDate"); 42 | this.setPageSize(10); 43 | this.setSort(Map.of("createdAt", Sort.Direction.ASC)); 44 | if (threshold > 0) { 45 | this.threshold = threshold; 46 | } 47 | else { 48 | this.threshold = 3; 49 | } 50 | } 51 | 52 | @NonNull 53 | @Override 54 | protected List doPageRead() throws Exception { 55 | this.setArguments(List.of(Date.from(LocalDateTime.now().minusDays(1).minusMonths(threshold).toInstant(ZoneOffset.UTC)))); 56 | return super.doPageRead(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/writer/CheckEventItemWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.writer; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainCheckEntity; 21 | import com.bompotis.netcheck.scheduler.batch.notification.CheckEventDto; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.springframework.batch.item.Chunk; 25 | import org.springframework.batch.item.ItemWriter; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.context.ApplicationEventPublisher; 28 | import org.springframework.stereotype.Component; 29 | 30 | /** 31 | * Created by Kyriakos Bompotis on 25/8/20. 32 | */ 33 | @Component 34 | public class CheckEventItemWriter implements ItemWriter { 35 | 36 | private static final Logger logger = LoggerFactory.getLogger(CheckEventItemWriter.class); 37 | 38 | private final ApplicationEventPublisher eventPublisher; 39 | 40 | @Autowired 41 | public CheckEventItemWriter(ApplicationEventPublisher eventPublisher) { 42 | this.eventPublisher = eventPublisher; 43 | } 44 | 45 | @Override 46 | public void write(Chunk chunk) { 47 | logger.info("Publishing {} events", chunk.size()); 48 | chunk.forEach((check) -> eventPublisher.publishEvent(new CheckEventDto(this,check))); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/writer/DomainMetricListWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.writer; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainMetricEntity; 21 | import jakarta.persistence.EntityManagerFactory; 22 | import org.apache.commons.logging.Log; 23 | import org.apache.commons.logging.LogFactory; 24 | import org.springframework.batch.item.Chunk; 25 | import org.springframework.batch.item.ItemWriter; 26 | import org.springframework.batch.item.database.JpaItemWriter; 27 | 28 | import java.util.List; 29 | 30 | /** 31 | * Created by Kyriakos Bompotis on 30/6/20. 32 | */ 33 | public class DomainMetricListWriter implements ItemWriter> { 34 | protected static final Log logger = LogFactory.getLog(DomainMetricListWriter.class); 35 | private final JpaItemWriter jpaItemWriter; 36 | 37 | public DomainMetricListWriter() { 38 | this.jpaItemWriter = new JpaItemWriter<>(); 39 | } 40 | 41 | public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) { 42 | jpaItemWriter.setEntityManagerFactory(entityManagerFactory); 43 | } 44 | 45 | public void afterPropertiesSet() throws Exception { 46 | this.jpaItemWriter.afterPropertiesSet(); 47 | } 48 | 49 | public void setUsePersist(boolean usePersist) { 50 | this.jpaItemWriter.setUsePersist(usePersist); 51 | } 52 | 53 | @Override 54 | public void write(Chunk> chunk) { 55 | Chunk metricEntities = new Chunk<>(); 56 | chunk.forEach(metricEntities::addAll); 57 | jpaItemWriter.write(metricEntities); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/scheduler/batch/writer/NotificationItemWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.scheduler.batch.writer; 19 | 20 | import com.bompotis.netcheck.data.entity.DomainCheckEntity; 21 | import com.bompotis.netcheck.scheduler.batch.notification.NotificationDto; 22 | import com.bompotis.netcheck.scheduler.batch.notification.NotificationService; 23 | import com.bompotis.netcheck.scheduler.batch.processor.DomainMetricProcessor; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.springframework.batch.item.Chunk; 27 | import org.springframework.batch.item.ItemWriter; 28 | import org.springframework.beans.factory.annotation.Autowired; 29 | import org.springframework.lang.NonNull; 30 | import org.springframework.stereotype.Component; 31 | 32 | import java.util.ArrayList; 33 | import java.util.Collections; 34 | import java.util.List; 35 | 36 | /** 37 | * Created by Kyriakos Bompotis on 1/7/20. 38 | */ 39 | @Component 40 | public class NotificationItemWriter extends AbstractNotificationWriter implements ItemWriter { 41 | 42 | private static final Logger log = LoggerFactory.getLogger(DomainMetricProcessor.class); 43 | 44 | private final List notificationServices; 45 | 46 | @Autowired 47 | public NotificationItemWriter(List notificationServices) { 48 | var enabledNotificationServices = new ArrayList(); 49 | for (var notificationService : notificationServices) { 50 | log.info("Notification provider: {} - Enabled: {}", notificationService.getClass(), notificationService.isEnabled()); 51 | if (notificationService.isEnabled()) { 52 | enabledNotificationServices.add(notificationService); 53 | } 54 | } 55 | this.notificationServices = Collections.unmodifiableList(enabledNotificationServices); 56 | } 57 | 58 | public boolean isEnabled() { 59 | return !notificationServices.isEmpty(); 60 | } 61 | 62 | private void send(List notifications) { 63 | notifications.forEach(this::send); 64 | } 65 | 66 | private void send(NotificationDto notification){ 67 | for (NotificationService service : notificationServices) { 68 | try { 69 | service.notify(notification); 70 | } catch (Exception e) { 71 | log.error("Failure to send notification for service {}. Failed notification message: {}", service.getClass(), notification.getMessage(), e); 72 | } 73 | } 74 | } 75 | 76 | @Override 77 | public void write(@NonNull Chunk chunk) { 78 | var notifications = generateNotifications(chunk); 79 | send(notifications); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/AbstractService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service; 19 | 20 | import org.springframework.data.domain.PageRequest; 21 | import org.springframework.data.domain.Sort; 22 | 23 | import java.util.Optional; 24 | 25 | /** 26 | * Created by Kyriakos Bompotis on 13/7/20. 27 | */ 28 | public abstract class AbstractService { 29 | 30 | protected PageRequest getDefaultPageRequest(Integer page, Integer size) { 31 | return PageRequest.of( 32 | Optional.ofNullable(page).orElse(0), 33 | Optional.ofNullable(size).orElse(10), 34 | Sort.by("createdAt").descending() 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/AbstractPaginatedDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 12/6/20. 22 | */ 23 | public abstract class AbstractPaginatedDto { 24 | 25 | private final long totalElements; 26 | private final int totalPages; 27 | private final int number; 28 | private final int size; 29 | 30 | public AbstractPaginatedDto(long totalElements, 31 | int totalPages, 32 | int number, 33 | int size) { 34 | this.totalElements = totalElements; 35 | this.totalPages = totalPages; 36 | this.number = number; 37 | this.size = size; 38 | } 39 | 40 | public long getTotalElements() { 41 | return totalElements; 42 | } 43 | 44 | public int getTotalPages() { 45 | return totalPages; 46 | } 47 | 48 | public int getNumber() { 49 | return number; 50 | } 51 | 52 | public int getSize() { 53 | return size; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/DomainCheckConfigDto.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck.service.dto; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Optional; 6 | 7 | /** 8 | * Created by Kyriakos Bompotis on 2/9/20. 9 | */ 10 | public class DomainCheckConfigDto { 11 | private final String domain; 12 | private final String endpoint; 13 | private final Map headers; 14 | private final int timeoutMs; 15 | 16 | public String getDomain() { 17 | return domain; 18 | } 19 | 20 | public String getEndpoint() { 21 | return endpoint; 22 | } 23 | 24 | public Map getHeaders() { 25 | return headers; 26 | } 27 | 28 | public int getTimeoutMs() { 29 | return timeoutMs; 30 | } 31 | 32 | public static class Builder implements DtoBuilder{ 33 | private String domain; 34 | private String endpoint = ""; 35 | private int timeoutMs = 30000; 36 | private final Map headers = new HashMap<>(); 37 | 38 | public Builder domain(String domain) { 39 | this.domain = domain; 40 | return this; 41 | } 42 | 43 | public Builder endpoint(String endpoint) { 44 | this.endpoint = Optional.ofNullable(endpoint).orElse(""); 45 | return this; 46 | } 47 | 48 | public Builder timeoutMs(Integer timeoutMs) { 49 | this.timeoutMs = Optional.ofNullable(timeoutMs).orElse(30000); 50 | return this; 51 | } 52 | 53 | public Builder withHeader(String key, String value) { 54 | this.headers.put(key,value); 55 | return this; 56 | } 57 | 58 | public Builder withHeaders(Map headers) { 59 | if (Optional.ofNullable(headers).isPresent()) { 60 | this.headers.putAll(headers); 61 | } 62 | return this; 63 | } 64 | 65 | public DomainCheckConfigDto build() { 66 | return new DomainCheckConfigDto(this); 67 | } 68 | } 69 | 70 | private DomainCheckConfigDto(Builder b) { 71 | this.domain = b.domain; 72 | this.endpoint = b.endpoint; 73 | this.timeoutMs = b.timeoutMs; 74 | this.headers = Map.copyOf(b.headers); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/DomainCheckDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import java.io.IOException; 21 | import java.security.KeyManagementException; 22 | import java.security.NoSuchAlgorithmException; 23 | 24 | /** 25 | * Created by Kyriakos Bompotis on 10/6/20. 26 | */ 27 | public class DomainCheckDto { 28 | private final HttpCheckDto httpCheckDto; 29 | private final HttpsCheckDto httpsCheckDto; 30 | private final Boolean monitored; 31 | private final String domain; 32 | private final String id; 33 | 34 | public HttpCheckDto getHttpCheckDto() { 35 | return httpCheckDto; 36 | } 37 | 38 | public HttpsCheckDto getHttpsCheckDto() { 39 | return httpsCheckDto; 40 | } 41 | 42 | public String getDomain() { 43 | return domain; 44 | } 45 | 46 | public String getId() { 47 | return id; 48 | } 49 | 50 | public Boolean getMonitored() { 51 | return monitored; 52 | } 53 | 54 | public static class Builder extends AbstractHttpChecker implements DtoBuilder{ 55 | private HttpCheckDto httpCheckDto; 56 | private HttpsCheckDto httpsCheckDto; 57 | private final String domain; 58 | private Boolean monitored; 59 | private String id; 60 | 61 | public Builder(String domain) { 62 | this.domain = domain; 63 | } 64 | 65 | public Builder monitored(Boolean monitored) { 66 | this.monitored = monitored; 67 | return this; 68 | } 69 | 70 | public Builder httpCheck(HttpCheckDto httpCheckDto) { 71 | this.httpCheckDto = httpCheckDto; 72 | return this; 73 | } 74 | 75 | public Builder httpsCheckDto(HttpsCheckDto httpsCheckDto) { 76 | this.httpsCheckDto = httpsCheckDto; 77 | return this; 78 | } 79 | 80 | public Builder withCurrentHttpCheck(DomainCheckConfigDto config, int port) { 81 | this.httpCheckDto = checkHttp(config, port); 82 | return this; 83 | } 84 | 85 | public Builder withCurrentHttpsCheck(DomainCheckConfigDto config, int port) { 86 | this.httpsCheckDto = checkHttps(config, port); 87 | return this; 88 | } 89 | 90 | public Builder id(String id) { 91 | this.id = id; 92 | return this; 93 | } 94 | 95 | public DomainCheckDto build() { 96 | return new DomainCheckDto(this); 97 | } 98 | } 99 | 100 | private DomainCheckDto(Builder b) { 101 | this.httpCheckDto = b.httpCheckDto; 102 | this.domain = b.domain; 103 | this.httpsCheckDto = b.httpsCheckDto; 104 | this.monitored = b.monitored; 105 | this.id = b.id; 106 | } 107 | } -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/DomainUpdateDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import java.util.*; 21 | 22 | /** 23 | * Created by Kyriakos Bompotis on 2/9/20. 24 | */ 25 | public class DomainUpdateDto { 26 | private final String domain; 27 | private final List operations; 28 | 29 | public String getDomain() { 30 | return domain; 31 | } 32 | 33 | public List getOperations() { 34 | return operations; 35 | } 36 | 37 | public static class Builder implements PatchDtoBuilder { 38 | private final String domain; 39 | private final List operations = new ArrayList<>(); 40 | 41 | public Builder(String domain) { 42 | this.domain = domain; 43 | } 44 | 45 | public Builder addOperation(Operation operation) { 46 | this.operations.add(operation); 47 | return this; 48 | } 49 | 50 | public DomainUpdateDto build() { 51 | return new DomainUpdateDto(this); 52 | } 53 | } 54 | 55 | private DomainUpdateDto(Builder b) { 56 | this.domain = b.domain; 57 | this.operations = b.operations; 58 | } 59 | } -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/DomainsOptionsDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import org.springframework.data.domain.PageRequest; 21 | import org.springframework.data.domain.Sort; 22 | 23 | import java.util.Optional; 24 | 25 | /** 26 | * Created by Kyriakos Bompotis on 31/8/20. 27 | */ 28 | public class DomainsOptionsDto { 29 | private final Integer page; 30 | private final Integer size; 31 | private final boolean showLastChecks; 32 | private final String filter; 33 | private final String sortBy; 34 | private final boolean desc; 35 | 36 | public Boolean getDesc() { 37 | return desc; 38 | } 39 | 40 | public String getSortBy() { 41 | return sortBy; 42 | } 43 | 44 | public String getFilter() { 45 | return filter; 46 | } 47 | 48 | public Boolean getShowLastChecks() { 49 | return showLastChecks; 50 | } 51 | 52 | public Integer getSize() { 53 | return size; 54 | } 55 | 56 | public Integer getPage() { 57 | return page; 58 | } 59 | 60 | public PageRequest getPageRequest() { 61 | var sort = desc ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending(); 62 | return PageRequest.of(page, size, sort); 63 | } 64 | 65 | public static class Builder implements DtoBuilder{ 66 | private Integer page; 67 | private Integer size; 68 | private boolean showLastChecks; 69 | private String filter; 70 | private String sortBy; 71 | private boolean desc; 72 | 73 | public Builder page(Integer page) { 74 | this.page = Optional.ofNullable(page).orElse(0); 75 | return this; 76 | } 77 | 78 | public Builder size(Integer size) { 79 | this.size = Optional.ofNullable(size).orElse(10); 80 | return this; 81 | } 82 | 83 | public Builder showLastChecks(Boolean showLastChecks) { 84 | this.showLastChecks = Optional.ofNullable(showLastChecks).orElse(true); 85 | return this; 86 | } 87 | 88 | public Builder filter(String filter) { 89 | this.filter = Optional.ofNullable(filter).orElse(""); 90 | return this; 91 | } 92 | 93 | public Builder sortBy(String sortBy) { 94 | this.sortBy = Optional.ofNullable(sortBy).orElse("createdAt"); 95 | return this; 96 | } 97 | 98 | public Builder desc(Boolean desc) { 99 | this.desc = Optional.ofNullable(desc).orElse(true); 100 | return this; 101 | } 102 | 103 | public DomainsOptionsDto build() { 104 | return new DomainsOptionsDto(this); 105 | } 106 | } 107 | 108 | private DomainsOptionsDto(Builder b) { 109 | this.page = b.page; 110 | this.size = b.size; 111 | this.showLastChecks = b.showLastChecks; 112 | this.filter = b.filter; 113 | this.sortBy = b.sortBy; 114 | this.desc = b.desc; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/DtoBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 7/9/20. 22 | */ 23 | public interface DtoBuilder { 24 | T build(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/HttpsCheckDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import java.util.ArrayList; 21 | import java.util.Collections; 22 | import java.util.List; 23 | 24 | /** 25 | * Created by Kyriakos Bompotis on 15/6/20. 26 | */ 27 | public class HttpsCheckDto { 28 | private final HttpCheckDto httpCheckDto; 29 | private final List caCertificates; 30 | private final CertificateDetailsDto issuerCertificate; 31 | 32 | public List getCaCertificates() { 33 | return caCertificates; 34 | } 35 | 36 | public CertificateDetailsDto getIssuerCertificate() { 37 | return issuerCertificate; 38 | } 39 | 40 | public HttpCheckDto getHttpCheckDto() { 41 | return httpCheckDto; 42 | } 43 | 44 | public static class Builder implements DtoBuilder { 45 | private final List caCertificates = new ArrayList<>(); 46 | private CertificateDetailsDto issuerCertificate; 47 | private HttpCheckDto httpCheckDto; 48 | 49 | public HttpsCheckDto.Builder httpCheckDto(HttpCheckDto httpCheckDto) { 50 | this.httpCheckDto = httpCheckDto; 51 | return this; 52 | } 53 | 54 | public HttpsCheckDto.Builder certificate(CertificateDetailsDto cert) { 55 | if (cert.getBasicConstraints() < 0) { 56 | this.issuerCertificate = cert; 57 | } else { 58 | this.caCertificates.add(cert); 59 | } 60 | return this; 61 | } 62 | 63 | public HttpsCheckDto build() { 64 | return new HttpsCheckDto(this); 65 | } 66 | } 67 | 68 | private HttpsCheckDto(HttpsCheckDto.Builder b) { 69 | this.caCertificates = Collections.unmodifiableList(b.caCertificates); 70 | this.issuerCertificate = b.issuerCertificate; 71 | this.httpCheckDto = b.httpCheckDto; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/MetricDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import java.util.Date; 21 | 22 | /** 23 | * Created by Kyriakos Bompotis on 22/6/20. 24 | */ 25 | public class MetricDto { 26 | private final Date metricPeriodStart; 27 | private final Date metricPeriodEnd; 28 | private final Integer totalChecks; 29 | private final Integer successfulChecks; 30 | private final Long averageResponseTime; 31 | private final Long maxResponseTime; 32 | private final Long minResponseTime; 33 | private final String protocol; 34 | 35 | public Long getAverageResponseTime() { 36 | return averageResponseTime; 37 | } 38 | 39 | public Date getMetricPeriodStart() { 40 | return metricPeriodStart; 41 | } 42 | 43 | public Date getMetricPeriodEnd() { 44 | return metricPeriodEnd; 45 | } 46 | 47 | public Long getMaxResponseTime() { 48 | return maxResponseTime; 49 | } 50 | 51 | public Long getMinResponseTime() { 52 | return minResponseTime; 53 | } 54 | 55 | public String getProtocol() { 56 | return protocol; 57 | } 58 | 59 | public Integer getTotalChecks() { 60 | return totalChecks; 61 | } 62 | 63 | public Integer getSuccessfulChecks() { 64 | return successfulChecks; 65 | } 66 | 67 | public static class Builder implements DtoBuilder{ 68 | private Date metricPeriodStart; 69 | private Date metricPeriodEnd; 70 | private Integer totalChecks; 71 | private Integer successfulChecks; 72 | private Long averageResponseTime; 73 | private Long maxResponseTime; 74 | private Long minResponseTime; 75 | private String protocol; 76 | 77 | public Builder metricPeriodStart(Date metricPeriodStart) { 78 | this.metricPeriodStart = metricPeriodStart; 79 | return this; 80 | } 81 | 82 | public Builder metricPeriodEnd(Date metricPeriodEnd) { 83 | this.metricPeriodEnd = metricPeriodEnd; 84 | return this; 85 | } 86 | 87 | public Builder totalChecks(Integer totalChecks) { 88 | this.totalChecks = totalChecks; 89 | return this; 90 | } 91 | 92 | public Builder successfulChecks(Integer successfulChecks) { 93 | this.successfulChecks = successfulChecks; 94 | return this; 95 | } 96 | 97 | public Builder maxResponseTime(Long maxResponseTime) { 98 | this.maxResponseTime = maxResponseTime; 99 | return this; 100 | } 101 | 102 | public Builder minResponseTime(Long minResponseTime) { 103 | this.minResponseTime = minResponseTime; 104 | return this; 105 | } 106 | 107 | public Builder protocol(String protocol) { 108 | this.protocol = protocol; 109 | return this; 110 | } 111 | 112 | public Builder averageResponseTime(Long averageResponseTime) { 113 | this.averageResponseTime = averageResponseTime; 114 | return this; 115 | } 116 | 117 | public MetricDto build() { 118 | return new MetricDto(this); 119 | } 120 | } 121 | 122 | private MetricDto(Builder b) { 123 | this.metricPeriodStart = b.metricPeriodStart; 124 | this.metricPeriodEnd = b.metricPeriodEnd; 125 | this.totalChecks = b.totalChecks; 126 | this.successfulChecks = b.successfulChecks; 127 | this.averageResponseTime = b.averageResponseTime; 128 | this.maxResponseTime = b.maxResponseTime; 129 | this.minResponseTime = b.minResponseTime; 130 | this.protocol = b.protocol; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/Operation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 2/9/20. 22 | */ 23 | 24 | public record Operation(String field, Action action, String value, String path) { 25 | public enum Action { 26 | REMOVE, 27 | UPDATE, 28 | ADD 29 | } 30 | } -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/PaginatedDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Created by Kyriakos Bompotis on 22/6/20. 24 | */ 25 | public class PaginatedDto extends AbstractPaginatedDto { 26 | private final List dtoList; 27 | 28 | public PaginatedDto(List dtoList, 29 | long totalElements, 30 | int totalPages, 31 | int number, 32 | int size) { 33 | super(totalElements, totalPages, number, size); 34 | this.dtoList = dtoList; 35 | } 36 | 37 | public List getDtoList() { 38 | return dtoList; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/PatchDtoBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 7/9/20. 22 | */ 23 | public interface PatchDtoBuilder extends DtoBuilder { 24 | DtoBuilder addOperation(Operation operation); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/RequestOptionsDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import org.springframework.data.domain.PageRequest; 21 | import org.springframework.data.domain.Sort; 22 | 23 | import java.util.Optional; 24 | 25 | /** 26 | * Created by Kyriakos Bompotis on 7/9/20. 27 | */ 28 | public class RequestOptionsDto { 29 | private final Integer page; 30 | private final Integer size; 31 | private final String filter; 32 | private final String sortBy; 33 | private final boolean desc; 34 | 35 | public Boolean getDesc() { 36 | return desc; 37 | } 38 | 39 | public String getSortBy() { 40 | return sortBy; 41 | } 42 | 43 | public String getFilter() { 44 | return filter; 45 | } 46 | 47 | public Integer getSize() { 48 | return size; 49 | } 50 | 51 | public Integer getPage() { 52 | return page; 53 | } 54 | 55 | public PageRequest getPageRequest() { 56 | var sort = desc ? Sort.by(sortBy).descending() : Sort.by(sortBy).ascending(); 57 | return PageRequest.of(page, size, sort); 58 | } 59 | 60 | public static class Builder implements DtoBuilder{ 61 | private Integer page; 62 | private Integer size; 63 | private String filter; 64 | private String sortBy; 65 | private boolean desc; 66 | 67 | public Builder page(Integer page) { 68 | this.page = Optional.ofNullable(page).orElse(0); 69 | return this; 70 | } 71 | 72 | public Builder size(Integer size) { 73 | this.size = Optional.ofNullable(size).orElse(10); 74 | return this; 75 | } 76 | 77 | public Builder filter(String filter) { 78 | this.filter = Optional.ofNullable(filter).orElse(""); 79 | return this; 80 | } 81 | 82 | public Builder sortBy(String sortBy) { 83 | this.sortBy = Optional.ofNullable(sortBy).orElse("createdAt"); 84 | return this; 85 | } 86 | 87 | public Builder desc(Boolean desc) { 88 | this.desc = Optional.ofNullable(desc).orElse(true); 89 | return this; 90 | } 91 | 92 | public RequestOptionsDto build() { 93 | return new RequestOptionsDto(this); 94 | } 95 | } 96 | 97 | private RequestOptionsDto(Builder b) { 98 | this.page = b.page; 99 | this.size = b.size; 100 | this.filter = b.filter; 101 | this.sortBy = b.sortBy; 102 | this.desc = b.desc; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/ServerDefinitionDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | /** 21 | * Created by Kyriakos Bompotis on 9/9/20. 22 | */ 23 | public class ServerDefinitionDto { 24 | private final String label; 25 | private final String fieldName; 26 | private final String suffix; 27 | private final String valueType; 28 | private final String metricKind; 29 | private final String extendedType; 30 | private final String minThreshold; 31 | private final String maxThreshold; 32 | private final Boolean notify; 33 | 34 | public String getLabel() { 35 | return label; 36 | } 37 | 38 | public String getFieldName() { 39 | return fieldName; 40 | } 41 | 42 | public String getSuffix() { 43 | return suffix; 44 | } 45 | 46 | public String getValueType() { 47 | return valueType; 48 | } 49 | 50 | public String getMetricKind() { 51 | return metricKind; 52 | } 53 | 54 | public String getExtendedType() { 55 | return extendedType; 56 | } 57 | 58 | public String getMinThreshold() { 59 | return minThreshold; 60 | } 61 | 62 | public String getMaxThreshold() { 63 | return maxThreshold; 64 | } 65 | 66 | public Boolean getNotify() { 67 | return notify; 68 | } 69 | 70 | public static class Builder implements DtoBuilder { 71 | private String label; 72 | private String fieldName; 73 | private String suffix; 74 | private String valueType; 75 | private String metricKind; 76 | private String extendedType; 77 | private String minThreshold; 78 | private String maxThreshold; 79 | private Boolean notify; 80 | 81 | public Builder label(String label) { 82 | this.label = label; 83 | return this; 84 | } 85 | 86 | public Builder fieldName(String fieldName) { 87 | this.fieldName = fieldName; 88 | return this; 89 | } 90 | 91 | public Builder suffix(String suffix) { 92 | this.suffix = suffix; 93 | return this; 94 | } 95 | 96 | public Builder valueType(String valueType) { 97 | this.valueType = valueType; 98 | return this; 99 | } 100 | 101 | public Builder metricKind(String metricKind) { 102 | this.metricKind = metricKind; 103 | return this; 104 | } 105 | 106 | public Builder extendedType(String extendedType) { 107 | this.extendedType = extendedType; 108 | return this; 109 | } 110 | 111 | public Builder minThreshold(String minThreshold) { 112 | this.minThreshold = minThreshold; 113 | return this; 114 | } 115 | 116 | public Builder maxThreshold(String maxThreshold) { 117 | this.maxThreshold = maxThreshold; 118 | return this; 119 | } 120 | 121 | public Builder notify(Boolean notify) { 122 | this.notify = notify; 123 | return this; 124 | } 125 | 126 | @Override 127 | public ServerDefinitionDto build() { 128 | return new ServerDefinitionDto(this); 129 | } 130 | } 131 | 132 | private ServerDefinitionDto(Builder builder) { 133 | this.label = builder.label; 134 | this.fieldName = builder.fieldName; 135 | this.suffix = builder.suffix; 136 | this.valueType = builder.valueType; 137 | this.metricKind = builder.metricKind; 138 | this.extendedType = builder.extendedType; 139 | this.minThreshold = builder.minThreshold; 140 | this.maxThreshold = builder.maxThreshold; 141 | this.notify = builder.notify; 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/ServerDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import java.util.Date; 21 | import java.util.List; 22 | 23 | /** 24 | * Created by Kyriakos Bompotis on 4/9/20. 25 | */ 26 | public class ServerDto { 27 | 28 | private final String serverId; 29 | private final String serverName; 30 | private final String password; 31 | private final Date dateAdded; 32 | private final String description; 33 | private final List serverDefinitionDtos; 34 | 35 | public String getServerId() { 36 | return serverId; 37 | } 38 | 39 | public String getServerName() { 40 | return serverName; 41 | } 42 | 43 | public String getPassword() { 44 | return password; 45 | } 46 | 47 | public Date getDateAdded() { 48 | return dateAdded; 49 | } 50 | 51 | public String getDescription() { 52 | return description; 53 | } 54 | 55 | public List getServerDefinitionDtos() { 56 | return serverDefinitionDtos; 57 | } 58 | 59 | public static class Builder implements DtoBuilder { 60 | private String serverId; 61 | private String serverName; 62 | private String description; 63 | private String password; 64 | private Date dateAdded; 65 | private List serverDefinitionDtos = List.of(); 66 | 67 | public Builder serverId(String serverId) { 68 | this.serverId = serverId; 69 | return this; 70 | } 71 | 72 | public Builder description(String description) { 73 | this.description = description; 74 | return this; 75 | } 76 | 77 | public Builder serverName(String serverName) { 78 | this.serverName = serverName; 79 | return this; 80 | } 81 | 82 | public Builder password(String password) { 83 | this.password = password; 84 | return this; 85 | } 86 | 87 | public Builder dateAdded(Date dateAdded) { 88 | this.dateAdded = dateAdded; 89 | return this; 90 | } 91 | 92 | public Builder serverDefinitionDtos(List serverDefinitionDtos) { 93 | this.serverDefinitionDtos = List.copyOf(serverDefinitionDtos); 94 | return this; 95 | } 96 | 97 | public ServerDto build() { 98 | return new ServerDto(this); 99 | } 100 | } 101 | 102 | private ServerDto(Builder b) { 103 | this.serverId = b.serverId; 104 | this.serverName = b.serverName; 105 | this.password = b.password; 106 | this.dateAdded = b.dateAdded; 107 | this.description = b.description; 108 | this.serverDefinitionDtos = b.serverDefinitionDtos; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/bompotis/netcheck/service/dto/ServerUpdateDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 | * 5 | * This code is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This code is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | package com.bompotis.netcheck.service.dto; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | /** 24 | * Created by Kyriakos Bompotis on 2/9/20. 25 | */ 26 | public class ServerUpdateDto { 27 | private final String serverId; 28 | private final List operations; 29 | 30 | public String getServerId() { 31 | return serverId; 32 | } 33 | 34 | public List getOperations() { 35 | return operations; 36 | } 37 | 38 | public static class Builder implements PatchDtoBuilder{ 39 | private final String serverId; 40 | private final List operations = new ArrayList<>(); 41 | 42 | public Builder(String serverId) { 43 | this.serverId = serverId; 44 | } 45 | 46 | public Builder addOperation(Operation operation) { 47 | this.operations.add(operation); 48 | return this; 49 | } 50 | 51 | public ServerUpdateDto build() { 52 | return new ServerUpdateDto(this); 53 | } 54 | } 55 | 56 | private ServerUpdateDto(Builder b) { 57 | this.serverId = b.serverId; 58 | this.operations = b.operations; 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "settings.cors.origin", 5 | "type": "java.lang.String", 6 | "description": "CORS Permitted Domains." 7 | }, 8 | { 9 | "name": "settings.notifications.pushover.enabled", 10 | "type": "java.lang.String", 11 | "description": "Enable or disable Pushover notifications." 12 | }, 13 | { 14 | "name": "settings.notifications.pushover.apiToken", 15 | "type": "java.lang.String", 16 | "description": "Pushover API Token." 17 | }, 18 | { 19 | "name": "settings.notifications.pushover.userIdToken", 20 | "type": "java.lang.String", 21 | "description": "Pushover User ID token." 22 | }, 23 | { 24 | "name": "settings.notifications.pushover.notifyOnlyFor", 25 | "type": "java.util.List", 26 | "description": "Filter for only sending specific type of notifications." 27 | }, 28 | { 29 | "name": "settings.schedulers.cleanup.enabled", 30 | "type": "java.lang.String", 31 | "description": "Enable or disable deletion of older checks every month." 32 | }, 33 | { 34 | "name": "settings.schedulers.cleanup.deleteOlderThan", 35 | "type": "java.lang.String", 36 | "description": "Minimum amount of months a check should be consider old enough to be deleted." 37 | }, 38 | { 39 | "name": "settings.notifications.webhook.enabled", 40 | "type": "java.lang.String", 41 | "description": "Enable or disable notifications through a Webhook." 42 | }, 43 | { 44 | "name": "settings.notifications.webhook.url", 45 | "type": "java.lang.String", 46 | "description": "Url of the webhook." 47 | }, 48 | { 49 | "name": "settings.notifications.webhook.notifyOnlyFor", 50 | "type": "java.util.List", 51 | "description": "Filter for only sending specific type of notifications." 52 | } 53 | ] 54 | } -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | info: 2 | app: 3 | name: NetCheck API 4 | description: Website performance and availability monitoring app 5 | java: 6 | vendor: ${java.specification.vendor} 7 | version: ${java.version} 8 | vm-name: ${java.vm.name} 9 | vm-version: ${java.vm.version} 10 | version-date: ${java.version.date} 11 | os: 12 | name: ${os.name} 13 | springdoc: 14 | api-docs: 15 | path: "/docs/v1/OpenAPIv3" 16 | show-actuator: true 17 | swagger-ui: 18 | operationsSorter: method 19 | path: "/docs/v1/" 20 | spring: 21 | autoconfigure: 22 | exclude: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration 23 | jmx: 24 | enabled: false 25 | datasource: 26 | hikari: 27 | connectionTimeout: 20000 28 | maximumPoolSize: 20 29 | url: jdbc:postgresql://${postgres.host}:${postgres.port}/${postgres.db} 30 | username: ${postgres.user} 31 | password: ${postgres.password} 32 | batch: 33 | job: 34 | enabled: false 35 | jdbc: 36 | initialize-schema: never 37 | jpa: 38 | open-in-view: true 39 | hibernate: 40 | ddl-auto: validate 41 | settings: 42 | cors: 43 | origin: "*" 44 | schedulers: 45 | cleanup: 46 | enabled: false 47 | deleteOlderThan: 3 48 | management: 49 | info: 50 | env: 51 | enabled: true 52 | endpoints: 53 | enabled-by-default: false 54 | web: 55 | base-path: "/api/v1/actuator" 56 | exposure: 57 | include: "*" 58 | cors: 59 | allowed-origins: ${settings.cors.origin} 60 | allowed-methods: "GET" 61 | endpoint: 62 | info: 63 | enabled: true 64 | metrics: 65 | enabled: true 66 | health: 67 | enabled: true 68 | show-details: always 69 | show-components: always 70 | server: 71 | forward-headers-strategy: native 72 | compression: 73 | enabled: true 74 | port: 8080 75 | http2: 76 | enabled: true -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | _____ __ _____ _______________ ______ 2 | ___ | / /_____ __ /___ ____/___ /_ _____ __________ /__ 3 | __ |/ / _ _ \_ __/_ / __ __ \_ _ \_ ___/__ //_/ 4 | _ /| / / __// /_ / /___ _ / / // __// /__ _ ,< 5 | /_/ |_/ \___/ \__/ \____/ /_/ /_/ \___/ \___/ /_/|_| 6 | Application Version: ${application.version} 7 | Spring Boot Version: ${spring-boot.version} -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_0_0__init_schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.certificate ( 2 | id varchar(255) NOT NULL, 3 | created_at timestamp NULL, 4 | updated_at timestamp NULL, 5 | basic_constraints int4 NULL, 6 | expired bool NULL, 7 | is_valid bool NULL, 8 | issued_by varchar(255) NULL, 9 | issued_for varchar(255) NULL, 10 | not_after timestamp NULL, 11 | not_before timestamp NULL, 12 | not_yet_valid bool NULL, 13 | CONSTRAINT certificate_pkey PRIMARY KEY (id) 14 | ); 15 | 16 | CREATE TABLE public."domain" ( 17 | "domain" varchar(255) NOT NULL, 18 | created_at timestamp NULL, 19 | updated_at timestamp NULL, 20 | check_frequency_minutes int4 NULL, 21 | CONSTRAINT domain_pkey PRIMARY KEY (domain) 22 | ); 23 | 24 | CREATE TABLE public.protocol_check ( 25 | id varchar(255) NOT NULL, 26 | created_at timestamp NULL, 27 | updated_at timestamp NULL, 28 | connection_accepted bool NULL, 29 | dns_resolves bool NULL, 30 | hostname varchar(255) NULL, 31 | protocol varchar(255) NULL, 32 | redirect_uri varchar(255) NULL, 33 | status_code int4 NULL, 34 | CONSTRAINT protocol_check_pkey PRIMARY KEY (id) 35 | ); 36 | 37 | CREATE TABLE public.domain_check ( 38 | id varchar(255) NOT NULL, 39 | created_at timestamp NULL, 40 | updated_at timestamp NULL, 41 | change_type varchar(255) NULL, 42 | "domain" varchar(255) NULL, 43 | http_ip_address varchar(255) NULL, 44 | http_response_time_ns int8 NULL, 45 | https_ip_address varchar(255) NULL, 46 | https_response_time_ns int8 NULL, 47 | check_date timestamp NULL, 48 | CONSTRAINT domain_check_pkey PRIMARY KEY (id), 49 | CONSTRAINT domain_check_domain_fk FOREIGN KEY (domain) REFERENCES domain(domain) 50 | ); 51 | CREATE INDEX domain_check__domain_change_type_idx ON public.domain_check USING btree (domain, change_type); 52 | CREATE INDEX domain_check__domain_check_date_idx ON public.domain_check USING btree (domain, check_date); 53 | CREATE INDEX domain_check__domain_created_idx ON public.domain_check USING btree (domain, created_at); 54 | 55 | CREATE TABLE public.domain_metric ( 56 | id varchar(255) NOT NULL, 57 | created_at timestamp NULL, 58 | updated_at timestamp NULL, 59 | avg_response_time_ns int8 NULL, 60 | "domain" varchar(255) NULL, 61 | end_period timestamp NULL, 62 | max_response_time_ns int8 NULL, 63 | min_response_time_ns int8 NULL, 64 | period_type varchar(255) NULL, 65 | protocol varchar(255) NULL, 66 | start_period timestamp NULL, 67 | successful_checks int4 NULL, 68 | total_checks int4 NULL, 69 | CONSTRAINT domain_metric_pkey PRIMARY KEY (id), 70 | CONSTRAINT domain_metric_domain_fk FOREIGN KEY (domain) REFERENCES domain(domain) 71 | ); 72 | CREATE INDEX domain_metric__domain_period_created_idx ON public.domain_metric USING btree (domain, period_type, created_at); 73 | CREATE INDEX domain_metric__domain_period_protocol_idx ON public.domain_metric USING btree (domain, period_type, protocol); 74 | 75 | CREATE TABLE public.previous_check_certificate ( 76 | domain_check_id varchar(255) NOT NULL, 77 | certificate_id varchar(255) NOT NULL, 78 | CONSTRAINT previous_check_certificate_pkey PRIMARY KEY (domain_check_id, certificate_id), 79 | CONSTRAINT previous_check_certificate_fk FOREIGN KEY (certificate_id) REFERENCES certificate(id), 80 | CONSTRAINT previous_check_domain_check_fk FOREIGN KEY (domain_check_id) REFERENCES domain_check(id) 81 | ); 82 | 83 | CREATE TABLE public.previous_check_protocol ( 84 | domain_check_id varchar(255) NOT NULL, 85 | protocol_check_id varchar(255) NOT NULL, 86 | CONSTRAINT previous_check_protocol_pkey PRIMARY KEY (domain_check_id, protocol_check_id), 87 | CONSTRAINT previous_check_protocol_fk FOREIGN KEY (protocol_check_id) REFERENCES protocol_check(id), 88 | CONSTRAINT previous_check_domain_check_fk FOREIGN KEY (domain_check_id) REFERENCES domain_check(id) 89 | ); 90 | 91 | CREATE TABLE public.check_certificate ( 92 | domain_check_id varchar(255) NOT NULL, 93 | certificate_id varchar(255) NOT NULL, 94 | CONSTRAINT check_certificate_pkey PRIMARY KEY (domain_check_id, certificate_id), 95 | CONSTRAINT check_certificate_domain_check_fk FOREIGN KEY (domain_check_id) REFERENCES domain_check(id), 96 | CONSTRAINT check_certificate_certificate_fk FOREIGN KEY (certificate_id) REFERENCES certificate(id) 97 | ); 98 | 99 | CREATE TABLE public.check_protocol ( 100 | domain_check_id varchar(255) NOT NULL, 101 | protocol_check_id varchar(255) NOT NULL, 102 | CONSTRAINT check_protocol_pkey PRIMARY KEY (domain_check_id, protocol_check_id), 103 | CONSTRAINT check_protocol_domain_check_fk FOREIGN KEY (domain_check_id) REFERENCES domain_check(id), 104 | CONSTRAINT check_protocol_protocol_check_fk FOREIGN KEY (protocol_check_id) REFERENCES protocol_check(id) 105 | ); -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_1_0__init_spring_batch.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.BATCH_JOB_INSTANCE ( 2 | JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY , 3 | VERSION BIGINT , 4 | JOB_NAME VARCHAR(100) NOT NULL, 5 | JOB_KEY VARCHAR(32) NOT NULL, 6 | constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY) 7 | ) ; 8 | 9 | CREATE TABLE public.BATCH_JOB_EXECUTION ( 10 | JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY , 11 | VERSION BIGINT , 12 | JOB_INSTANCE_ID BIGINT NOT NULL, 13 | CREATE_TIME TIMESTAMP NOT NULL, 14 | START_TIME TIMESTAMP DEFAULT NULL , 15 | END_TIME TIMESTAMP DEFAULT NULL , 16 | STATUS VARCHAR(10) , 17 | EXIT_CODE VARCHAR(2500) , 18 | EXIT_MESSAGE VARCHAR(2500) , 19 | LAST_UPDATED TIMESTAMP, 20 | JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL, 21 | constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID) 22 | references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID) 23 | ) ; 24 | 25 | CREATE TABLE public.BATCH_JOB_EXECUTION_PARAMS ( 26 | JOB_EXECUTION_ID BIGINT NOT NULL , 27 | TYPE_CD VARCHAR(6) NOT NULL , 28 | KEY_NAME VARCHAR(100) NOT NULL , 29 | STRING_VAL VARCHAR(250) , 30 | DATE_VAL TIMESTAMP DEFAULT NULL , 31 | LONG_VAL BIGINT , 32 | DOUBLE_VAL DOUBLE PRECISION , 33 | IDENTIFYING CHAR(1) NOT NULL , 34 | constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID) 35 | references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) 36 | ) ; 37 | 38 | CREATE TABLE public.BATCH_STEP_EXECUTION ( 39 | STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY , 40 | VERSION BIGINT NOT NULL, 41 | STEP_NAME VARCHAR(100) NOT NULL, 42 | JOB_EXECUTION_ID BIGINT NOT NULL, 43 | START_TIME TIMESTAMP NOT NULL , 44 | END_TIME TIMESTAMP DEFAULT NULL , 45 | STATUS VARCHAR(10) , 46 | COMMIT_COUNT BIGINT , 47 | READ_COUNT BIGINT , 48 | FILTER_COUNT BIGINT , 49 | WRITE_COUNT BIGINT , 50 | READ_SKIP_COUNT BIGINT , 51 | WRITE_SKIP_COUNT BIGINT , 52 | PROCESS_SKIP_COUNT BIGINT , 53 | ROLLBACK_COUNT BIGINT , 54 | EXIT_CODE VARCHAR(2500) , 55 | EXIT_MESSAGE VARCHAR(2500) , 56 | LAST_UPDATED TIMESTAMP, 57 | constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID) 58 | references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) 59 | ) ; 60 | 61 | CREATE TABLE public.BATCH_STEP_EXECUTION_CONTEXT ( 62 | STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, 63 | SHORT_CONTEXT VARCHAR(2500) NOT NULL, 64 | SERIALIZED_CONTEXT TEXT , 65 | constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) 66 | references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) 67 | ) ; 68 | 69 | CREATE TABLE public.BATCH_JOB_EXECUTION_CONTEXT ( 70 | JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, 71 | SHORT_CONTEXT VARCHAR(2500) NOT NULL, 72 | SERIALIZED_CONTEXT TEXT , 73 | constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) 74 | references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) 75 | ) ; 76 | 77 | CREATE SEQUENCE BATCH_STEP_EXECUTION_SEQ MAXVALUE 9223372036854775807 NO CYCLE; 78 | CREATE SEQUENCE BATCH_JOB_EXECUTION_SEQ MAXVALUE 9223372036854775807 NO CYCLE; 79 | CREATE SEQUENCE BATCH_JOB_SEQ MAXVALUE 9223372036854775807 NO CYCLE; 80 | -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_2_0__add_domain_endpoint_column.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE public."domain" ADD COLUMN endpoint VARCHAR; -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_3_0__add_domain_headers_column.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE public."domain" ADD COLUMN headers jsonb; -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_3_1__add_domain_timeout_column.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE public."domain" ADD COLUMN timeout_ms int4; -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_3_2__update_new_fields_to_defaults.sql: -------------------------------------------------------------------------------- 1 | UPDATE public."domain" SET endpoint='' WHERE endpoint IS NULL; 2 | UPDATE public."domain" SET timeout_ms=30000 WHERE timeout_ms IS NULL; -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_4_0__add_server_tables.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE public.server ( 2 | id varchar(255) NOT NULL, 3 | created_at timestamp NOT NULL, 4 | updated_at timestamp NOT NULL, 5 | server_name varchar(255) NOT NULL, 6 | description varchar(255) NULL, 7 | password varchar(255) NOT NULL, 8 | CONSTRAINT server_pkey PRIMARY KEY (id) 9 | ); 10 | 11 | CREATE TABLE public.server_metric ( 12 | id varchar(255) NOT NULL, 13 | created_at timestamp NOT NULL, 14 | updated_at timestamp NOT NULL, 15 | collected_at timestamp NOT NULL, 16 | server_id varchar(255) NOT NULL, 17 | metrics jsonb NOT NULL, 18 | CONSTRAINT server_metric_pkey PRIMARY KEY (id), 19 | CONSTRAINT server_metric_server_fk FOREIGN KEY (server_id) REFERENCES server(id) 20 | ); 21 | 22 | CREATE TABLE public.server_metric_definition ( 23 | field_name varchar(255) NOT NULL, 24 | server_id varchar(255) NOT NULL, 25 | created_at timestamp NOT NULL, 26 | updated_at timestamp NOT NULL, 27 | label varchar(255) NOT NULL, 28 | suffix varchar(255) NULL, 29 | max_threshold varchar(255) NULL, 30 | min_threshold varchar(255) NULL, 31 | notify bool NOT NULL DEFAULT FALSE, 32 | value_type varchar(255) NOT NULL, 33 | extended_type varchar(255) NULL, 34 | metric_kind varchar(255) NOT NULL, 35 | CONSTRAINT server_metric_definition_pkey PRIMARY KEY (field_name), 36 | CONSTRAINT server_metric_definition_server_fk FOREIGN KEY (server_id) REFERENCES server(id) 37 | ); 38 | 39 | CREATE TABLE public.server_domain ( 40 | server_id varchar(255) NOT NULL, 41 | domain varchar(255) NOT NULL, 42 | CONSTRAINT server_domain_pkey PRIMARY KEY (server_id, domain), 43 | CONSTRAINT server_domain_server_fk FOREIGN KEY (server_id) REFERENCES server(id), 44 | CONSTRAINT server_domain_domain_fk FOREIGN KEY (domain) REFERENCES domain(domain) 45 | ); 46 | 47 | CREATE INDEX server__id_password_idx ON public.server USING btree (id, password); 48 | CREATE INDEX server_metric__server_created_idx ON public.server_metric USING btree (server_id, created_at); 49 | CREATE INDEX server_metric__server_collected_idx ON public.server_metric USING btree (server_id, collected_at); 50 | CREATE INDEX server_metric_definition__server_created_idx ON public.server_metric_definition USING btree (server_id, created_at); -------------------------------------------------------------------------------- /src/main/resources/db/migration/V1_5_0__spring_batch_5_migration.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE BATCH_STEP_EXECUTION ADD CREATE_TIME TIMESTAMP NOT NULL DEFAULT '1970-01-01 00:00:00'; 2 | 3 | ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME DROP NOT NULL; 4 | 5 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL; 6 | 7 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL; 8 | 9 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL; 10 | 11 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN TYPE_CD TYPE VARCHAR(100); 12 | 13 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS RENAME TYPE_CD TO PARAMETER_TYPE; 14 | 15 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN KEY_NAME TYPE VARCHAR(100); 16 | 17 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS RENAME KEY_NAME TO PARAMETER_NAME; 18 | 19 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN STRING_VAL TYPE VARCHAR(2500); 20 | 21 | ALTER TABLE BATCH_JOB_EXECUTION_PARAMS RENAME STRING_VAL TO PARAMETER_VALUE; -------------------------------------------------------------------------------- /src/test/java/com/bompotis/netcheck/NetcheckApplicationStartupTests.java: -------------------------------------------------------------------------------- 1 | package com.bompotis.netcheck; 2 | 3 | import com.bompotis.netcheck.scheduler.batch.notification.config.PushoverConfig; 4 | import com.bompotis.netcheck.scheduler.batch.notification.config.WebhookConfig; 5 | import org.junit.jupiter.api.Test; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | @SpringBootTest 12 | class NetcheckApplicationStartupTests { 13 | 14 | @Autowired 15 | private WebhookConfig webhookConfig; 16 | 17 | @Autowired 18 | private PushoverConfig pushoverConfig; 19 | 20 | @Test 21 | void contextLoads() { 22 | assertThat(webhookConfig.getEnabled()).isFalse(); 23 | assertThat(pushoverConfig.getEnabled()).isFalse(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/resources/application.yaml: -------------------------------------------------------------------------------- 1 | spring: 2 | datasource: 3 | url: jdbc:postgresql://${postgres.host:localhost}:${postgres.port:5432}/${postgres.db:test_db} 4 | username: ${postgres.user:postgresql} 5 | password: ${postgres.password:letmein} 6 | batch: 7 | jdbc: 8 | initialize-schema: always 9 | job: 10 | enabled: false 11 | jpa: 12 | hibernate: 13 | ddl-auto: create-drop 14 | settings: 15 | cors: 16 | origin: "*" -------------------------------------------------------------------------------- /test-depedancies.docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | test-db: 5 | image: postgres 6 | environment: 7 | POSTGRES_USER: postgresql 8 | POSTGRES_PASSWORD: letmein 9 | POSTGRES_DB: test_db 10 | volumes: 11 | - db-test-data:/var/lib/postgresql/data 12 | ports: 13 | - "5432:5432" 14 | 15 | volumes: 16 | db-test-data: 17 | driver: local -------------------------------------------------------------------------------- /traefik.docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | 3 | services: 4 | db: 5 | image: postgres 6 | env_file: 7 | - database.env 8 | volumes: 9 | - db-data:/var/lib/postgresql/data 10 | 11 | traefik: 12 | image: "traefik" 13 | command: 14 | - "--api.insecure=true" 15 | - "--providers.docker=true" 16 | - "--providers.docker.exposedbydefault=false" 17 | - "--entrypoints.web.address=:80" 18 | - "--entrypoints.web.http.redirections.entryPoint.to=websecure" 19 | - "--entrypoints.web.http.redirections.entryPoint.scheme=https" 20 | - "--entrypoints.web.http.redirections.entrypoint.permanent=true" 21 | - "--entrypoints.websecure.address=:443" 22 | - "--certificatesresolvers.mainresolver.acme.httpchallenge=true" 23 | - "--certificatesresolvers.mainresolver.acme.httpchallenge.entrypoint=web" 24 | - "--certificatesresolvers.mainresolver.acme.email=" 25 | - "--certificatesresolvers.mainresolver.acme.storage=/letsencrypt/acme.json" 26 | ports: 27 | - "80:80" 28 | - "443:443" 29 | volumes: 30 | - letsencrypt:/letsencrypt 31 | - "/var/run/docker.sock:/var/run/docker.sock:ro" 32 | 33 | api: 34 | image: memphisx/netcheck-api:latest 35 | env_file: 36 | - database.env 37 | - .env 38 | depends_on: 39 | - db 40 | labels: 41 | - "traefik.enable=true" 42 | - "traefik.http.routers.netcheck-api.rule=Host(``) && PathPrefix(`/api`,`/docs`,`/events`)" 43 | - "traefik.http.routers.netcheck-api.entrypoints=websecure" 44 | - "traefik.http.routers.netcheck-api.service=netcheck-api" 45 | - "traefik.http.routers.netcheck-api.tls.certresolver=mainresolver" 46 | - "traefik.http.services.netcheck-api.loadbalancer.server.port=8080" 47 | 48 | 49 | 50 | frontend: 51 | image: memphisx/netcheck-frontend:latest 52 | depends_on: 53 | - api 54 | labels: 55 | - "traefik.enable=true" 56 | - "traefik.http.services.netcheck-frontend.loadbalancer.server.port=80" 57 | - "traefik.http.routers.netcheck-frontend.service=netcheck-frontend" 58 | - "traefik.http.routers.netcheck-frontend.rule=Host(``)" 59 | - "traefik.http.routers.netcheck-frontend.entrypoints=websecure" 60 | - "traefik.http.routers.netcheck-frontend.tls.certresolver=mainresolver" 61 | 62 | 63 | volumes: 64 | db-data: 65 | driver: local 66 | letsencrypt: 67 | driver: local -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 0.11.4 --------------------------------------------------------------------------------