Compare commits

...

6 Commits

56 changed files with 266 additions and 201 deletions

View File

@ -56,7 +56,7 @@ jobs:
username: hitanshu username: hitanshu
password: ${{ secrets.TOKEN }} password: ${{ secrets.TOKEN }}
- name: Gradle build - name: Gradle build
run: ./gradlew bootBuildImage --imageName=192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} run: ./gradlew :cftunnels-service:bootBuildImage --imageName=192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }}
- name: Tag image as test - name: Tag image as test
run: docker tag 192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} 192.168.0.100:8928/hithomelabs/cftunnels:test run: docker tag 192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }} 192.168.0.100:8928/hithomelabs/cftunnels:test
- name: Push to Gitea Registry - name: Push to Gitea Registry

View File

@ -1,4 +0,0 @@
FROM openjdk:17-jdk
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

View File

@ -1,62 +1,29 @@
plugins { plugins {
id 'java' id 'java'
id 'org.springframework.boot' version '3.4.5' id 'org.springframework.boot' version '3.4.5' apply false
id 'io.spring.dependency-management' version '1.1.7' id 'io.spring.dependency-management' version '1.1.7' apply false
} }
group = 'com.hithomelabs' subprojects {
version = '0.0.1-SNAPSHOT' apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'
java { group = 'com.hithomelabs'
version = '0.0.1-SNAPSHOT'
java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(17) languageVersion = JavaLanguageVersion.of(17)
} }
} }
test { repositories {
systemProperty 'spring.profiles.active', 'ci'
useJUnitPlatform {
excludeTags 'integration'
}
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
exceptionFormat "full" // shows full stack trace
showStandardStreams = true // shows println/log output
}
}
tasks.register('integrationTestOnly', Test) {
useJUnitPlatform {
includeTags 'integration'
}
description = 'Runs only integration tests tagged with @Tag("integration")'
group = 'verification'
testLogging {
events "passed", "skipped", "failed"
exceptionFormat "full"
showStandardStreams = true
}
}
repositories {
mavenCentral() mavenCentral()
} }
dependencies { dependencyManagement {
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.8.5' imports {
implementation group: 'org.springframework.boot', name:'spring-boot-starter-oauth2-client', version: '3.5.5' mavenBom "org.springframework.boot:spring-boot-dependencies:3.4.5"
implementation 'org.springframework.boot:spring-boot-starter-web' }
compileOnly 'org.projectlombok:lombok:1.18.30' }
annotationProcessor 'org.projectlombok:lombok:1.18.30'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql'
implementation 'org.hibernate.validator:hibernate-validator'
runtimeOnly 'com.h2database:h2'
}
tasks.named('test') {
useJUnitPlatform()
} }

View File

@ -0,0 +1,12 @@
FROM openjdk:17-jdk as build
WORKDIR /app
COPY gradlew settings.gradle build.gradle ./
COPY gradle ./gradle
COPY common ./common
COPY cftunnels-service ./cftunnels-service
COPY portainer-automation ./portainer-automation
RUN ./gradlew :cftunnels-service:bootJar
FROM openjdk:17-jdk-slim
COPY --from=build /app/cftunnels-service/build/libs/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

View File

@ -0,0 +1,46 @@
apply plugin: 'org.springframework.boot'
dependencies {
implementation project(':common')
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.5'
implementation 'org.hibernate.validator:hibernate-validator'
runtimeOnly 'org.postgresql:postgresql'
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}
test {
systemProperty 'spring.profiles.active', 'ci'
useJUnitPlatform {
excludeTags 'integration'
}
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
exceptionFormat "full"
showStandardStreams = true
}
}
tasks.register('integrationTestOnly', Test) {
useJUnitPlatform {
includeTags 'integration'
}
description = 'Runs only integration tests tagged with @Tag("integration")'
group = 'verification'
testLogging {
events "passed", "skipped", "failed"
exceptionFormat "full"
showStandardStreams = true
}
}

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels; package com.hithomelabs.cftunnels;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -32,7 +32,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @see <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-negative">Cloudflare Tunnel Documentation</a> * @see <a href="https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-negative">Cloudflare Tunnel Documentation</a>
* @since 1.0.0 * @since 1.0.0
*/ */
@SpringBootApplication @SpringBootApplication(scanBasePackages = "com.hithomelabs")
public class CfTunnelsApplication { public class CfTunnelsApplication {
/** /**

View File

@ -1,7 +1,7 @@
package com.hithomelabs.CFTunnels.Config; package com.hithomelabs.cftunnels.Config;
import com.hithomelabs.CFTunnels.Models.Authorities; import com.hithomelabs.cftunnels.Models.Authorities;
import com.hithomelabs.CFTunnels.Models.Groups; import com.hithomelabs.cftunnels.Models.Groups;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Config; package com.hithomelabs.cftunnels.Config;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Config; package com.hithomelabs.cftunnels.Config;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Config; package com.hithomelabs.cftunnels.Config;
import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.OpenAPI;

View File

@ -1,6 +1,6 @@
package com.hithomelabs.CFTunnels.Config.Security; package com.hithomelabs.cftunnels.Config.Security;
import com.hithomelabs.CFTunnels.Config.CustomOidcUserConfiguration; import com.hithomelabs.cftunnels.Config.CustomOidcUserConfiguration;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -1,20 +1,20 @@
package com.hithomelabs.CFTunnels.Controllers; package com.hithomelabs.cftunnels.Controllers;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.hithomelabs.CFTunnels.Config.AuthoritiesToGroupMapping; import com.hithomelabs.cftunnels.Config.AuthoritiesToGroupMapping;
import com.hithomelabs.CFTunnels.Config.CloudflareConfig; import com.hithomelabs.cftunnels.Config.CloudflareConfig;
import com.hithomelabs.CFTunnels.Config.RestTemplateConfig; import com.hithomelabs.common.config.RestTemplateConfig;
import com.hithomelabs.CFTunnels.Entity.Request; import com.hithomelabs.cftunnels.Entity.Request;
import com.hithomelabs.CFTunnels.Entity.Tunnel; import com.hithomelabs.cftunnels.Entity.Tunnel;
import com.hithomelabs.CFTunnels.Entity.User; import com.hithomelabs.cftunnels.Entity.User;
import com.hithomelabs.CFTunnels.Headers.AuthKeyEmailHeader; import com.hithomelabs.cftunnels.Headers.AuthKeyEmailHeader;
import com.hithomelabs.CFTunnels.Models.Config; import com.hithomelabs.cftunnels.Models.Config;
import com.hithomelabs.CFTunnels.Models.Ingress; import com.hithomelabs.cftunnels.Models.Ingress;
import com.hithomelabs.CFTunnels.Models.TunnelResponse; import com.hithomelabs.cftunnels.Models.TunnelResponse;
import com.hithomelabs.CFTunnels.Models.TunnelsResponse; import com.hithomelabs.cftunnels.Models.TunnelsResponse;
import com.hithomelabs.CFTunnels.Repositories.UserRepository; import com.hithomelabs.cftunnels.Repositories.UserRepository;
import com.hithomelabs.CFTunnels.Services.CloudflareAPIService; import com.hithomelabs.cftunnels.Services.CloudflareAPIService;
import com.hithomelabs.CFTunnels.Services.MappingRequestService; import com.hithomelabs.cftunnels.Services.MappingRequestService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Entity; package com.hithomelabs.cftunnels.Entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Entity; package com.hithomelabs.cftunnels.Entity;
/** /**
* Enum representing supported protocols for Cloudflare Tunnel ingress mappings. * Enum representing supported protocols for Cloudflare Tunnel ingress mappings.

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Entity; package com.hithomelabs.cftunnels.Entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Entity; package com.hithomelabs.cftunnels.Entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Entity; package com.hithomelabs.cftunnels.Entity;
import jakarta.persistence.*; import jakarta.persistence.*;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Exceptions; package com.hithomelabs.cftunnels.Exceptions;
public class ExternalServiceException extends RuntimeException { public class ExternalServiceException extends RuntimeException {
public ExternalServiceException(String message) { super(message); } public ExternalServiceException(String message) { super(message); }

View File

@ -1,6 +1,6 @@
package com.hithomelabs.CFTunnels.Headers; package com.hithomelabs.cftunnels.Headers;
import com.hithomelabs.CFTunnels.Config.CloudflareConfig; import com.hithomelabs.cftunnels.Config.CloudflareConfig;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Models; package com.hithomelabs.cftunnels.Models;
public class Authorities { public class Authorities {

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Models; package com.hithomelabs.cftunnels.Models;
import com.fasterxml.jackson.annotation.*; import com.fasterxml.jackson.annotation.*;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Models; package com.hithomelabs.cftunnels.Models;
public class Groups { public class Groups {

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Models; package com.hithomelabs.cftunnels.Models;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Models; package com.hithomelabs.cftunnels.Models;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Models; package com.hithomelabs.cftunnels.Models;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Models; package com.hithomelabs.cftunnels.Models;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Models; package com.hithomelabs.cftunnels.Models;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -1,6 +1,6 @@
package com.hithomelabs.CFTunnels.Repositories; package com.hithomelabs.cftunnels.Repositories;
import com.hithomelabs.CFTunnels.Entity.Mapping; import com.hithomelabs.cftunnels.Entity.Mapping;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;

View File

@ -1,6 +1,6 @@
package com.hithomelabs.CFTunnels.Repositories; package com.hithomelabs.cftunnels.Repositories;
import com.hithomelabs.CFTunnels.Entity.Request; import com.hithomelabs.cftunnels.Entity.Request;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;

View File

@ -1,6 +1,6 @@
package com.hithomelabs.CFTunnels.Repositories; package com.hithomelabs.cftunnels.Repositories;
import com.hithomelabs.CFTunnels.Entity.Tunnel; import com.hithomelabs.cftunnels.Entity.Tunnel;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;

View File

@ -1,6 +1,6 @@
package com.hithomelabs.CFTunnels.Repositories; package com.hithomelabs.cftunnels.Repositories;
import com.hithomelabs.CFTunnels.Entity.User; import com.hithomelabs.cftunnels.Entity.User;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;

View File

@ -1,15 +1,15 @@
package com.hithomelabs.CFTunnels.Services; package com.hithomelabs.cftunnels.Services;
import com.hithomelabs.CFTunnels.Config.CloudflareConfig; import com.hithomelabs.cftunnels.Config.CloudflareConfig;
import com.hithomelabs.CFTunnels.Entity.Tunnel; import com.hithomelabs.cftunnels.Entity.Tunnel;
import com.hithomelabs.CFTunnels.Exceptions.ExternalServiceException; import com.hithomelabs.cftunnels.Exceptions.ExternalServiceException;
import com.hithomelabs.CFTunnels.Headers.AuthKeyEmailHeader; import com.hithomelabs.cftunnels.Headers.AuthKeyEmailHeader;
import com.hithomelabs.CFTunnels.Models.Config; import com.hithomelabs.cftunnels.Models.Config;
import com.hithomelabs.CFTunnels.Models.Ingress; import com.hithomelabs.cftunnels.Models.Ingress;
import com.hithomelabs.CFTunnels.Models.TunnelResponse; import com.hithomelabs.cftunnels.Models.TunnelResponse;
import com.hithomelabs.CFTunnels.Models.TunnelResult; import com.hithomelabs.cftunnels.Models.TunnelResult;
import com.hithomelabs.CFTunnels.Models.TunnelsResponse; import com.hithomelabs.cftunnels.Models.TunnelsResponse;
import com.hithomelabs.CFTunnels.Repositories.TunnelRepository; import com.hithomelabs.cftunnels.Repositories.TunnelRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.http.*; import org.springframework.http.*;

View File

@ -1,15 +1,15 @@
package com.hithomelabs.CFTunnels.Services; package com.hithomelabs.cftunnels.Services;
import com.hithomelabs.CFTunnels.Entity.Mapping; import com.hithomelabs.cftunnels.Entity.Mapping;
import com.hithomelabs.CFTunnels.Entity.Protocol; import com.hithomelabs.cftunnels.Entity.Protocol;
import com.hithomelabs.CFTunnels.Entity.Request; import com.hithomelabs.cftunnels.Entity.Request;
import com.hithomelabs.CFTunnels.Entity.Tunnel; import com.hithomelabs.cftunnels.Entity.Tunnel;
import com.hithomelabs.CFTunnels.Entity.User; import com.hithomelabs.cftunnels.Entity.User;
import com.hithomelabs.CFTunnels.Models.Ingress; import com.hithomelabs.cftunnels.Models.Ingress;
import com.hithomelabs.CFTunnels.Repositories.MappingRepository; import com.hithomelabs.cftunnels.Repositories.MappingRepository;
import com.hithomelabs.CFTunnels.Repositories.RequestRepository; import com.hithomelabs.cftunnels.Repositories.RequestRepository;
import com.hithomelabs.CFTunnels.Repositories.TunnelRepository; import com.hithomelabs.cftunnels.Repositories.TunnelRepository;
import com.hithomelabs.CFTunnels.Repositories.UserRepository; import com.hithomelabs.cftunnels.Repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.core.oidc.user.OidcUser; import org.springframework.security.oauth2.core.oidc.user.OidcUser;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels; package com.hithomelabs.cftunnels;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;

View File

@ -1,21 +1,21 @@
package com.hithomelabs.CFTunnels.Controllers; package com.hithomelabs.cftunnels.Controllers;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.hithomelabs.CFTunnels.Config.AuthoritiesToGroupMapping; import com.hithomelabs.cftunnels.Config.AuthoritiesToGroupMapping;
import com.hithomelabs.CFTunnels.Config.CloudflareConfig; import com.hithomelabs.cftunnels.Config.CloudflareConfig;
import com.hithomelabs.CFTunnels.Config.RestTemplateConfig; import com.hithomelabs.common.config.RestTemplateConfig;
import com.hithomelabs.CFTunnels.Headers.AuthKeyEmailHeader; import com.hithomelabs.cftunnels.Headers.AuthKeyEmailHeader;
import com.hithomelabs.CFTunnels.Entity.Request; import com.hithomelabs.cftunnels.Entity.Request;
import com.hithomelabs.CFTunnels.Entity.Tunnel; import com.hithomelabs.cftunnels.Entity.Tunnel;
import com.hithomelabs.CFTunnels.Models.Authorities; import com.hithomelabs.cftunnels.Models.Authorities;
import com.hithomelabs.CFTunnels.Models.Config; import com.hithomelabs.cftunnels.Models.Config;
import com.hithomelabs.CFTunnels.Models.Groups; import com.hithomelabs.cftunnels.Models.Groups;
import com.hithomelabs.CFTunnels.Models.TunnelResponse; import com.hithomelabs.cftunnels.Models.TunnelResponse;
import com.hithomelabs.CFTunnels.Models.TunnelResult; import com.hithomelabs.cftunnels.Models.TunnelResult;
import com.hithomelabs.CFTunnels.Models.TunnelsResponse; import com.hithomelabs.cftunnels.Models.TunnelsResponse;
import com.hithomelabs.CFTunnels.Repositories.UserRepository; import com.hithomelabs.cftunnels.Repositories.UserRepository;
import com.hithomelabs.CFTunnels.Services.CloudflareAPIService; import com.hithomelabs.cftunnels.Services.CloudflareAPIService;
import com.hithomelabs.CFTunnels.Services.MappingRequestService; import com.hithomelabs.cftunnels.Services.MappingRequestService;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -38,7 +38,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import static com.hithomelabs.CFTunnels.TestUtils.Util.getClassPathDataResource; import static com.hithomelabs.cftunnels.TestUtils.Util.getClassPathDataResource;
import static org.hamcrest.core.IsIterableContaining.hasItem; import static org.hamcrest.core.IsIterableContaining.hasItem;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
@ -207,9 +207,9 @@ class TunnelControllerTest {
@Test @Test
@DisplayName("should return list of requests") @DisplayName("should return list of requests")
void getAllRequests_Success() throws Exception { void getAllRequests_Success() throws Exception {
List<com.hithomelabs.CFTunnels.Entity.Request> requests = Arrays.asList( List<com.hithomelabs.cftunnels.Entity.Request> requests = Arrays.asList(
createTestRequest(UUID.randomUUID(), com.hithomelabs.CFTunnels.Entity.Request.RequestStatus.PENDING), createTestRequest(UUID.randomUUID(), com.hithomelabs.cftunnels.Entity.Request.RequestStatus.PENDING),
createTestRequest(UUID.randomUUID(), com.hithomelabs.CFTunnels.Entity.Request.RequestStatus.APPROVED) createTestRequest(UUID.randomUUID(), com.hithomelabs.cftunnels.Entity.Request.RequestStatus.APPROVED)
); );
when(mappingRequestService.getAllRequests()).thenReturn(requests); when(mappingRequestService.getAllRequests()).thenReturn(requests);
@ -227,11 +227,11 @@ class TunnelControllerTest {
@DisplayName("should create mapping request successfully") @DisplayName("should create mapping request successfully")
void createTunnelMappingRequest_Success() throws Exception { void createTunnelMappingRequest_Success() throws Exception {
UUID tunnelId = UUID.randomUUID(); UUID tunnelId = UUID.randomUUID();
com.hithomelabs.CFTunnels.Entity.Request createdRequest = new com.hithomelabs.CFTunnels.Entity.Request(); com.hithomelabs.cftunnels.Entity.Request createdRequest = new com.hithomelabs.cftunnels.Entity.Request();
createdRequest.setId(UUID.randomUUID()); createdRequest.setId(UUID.randomUUID());
createdRequest.setStatus(com.hithomelabs.CFTunnels.Entity.Request.RequestStatus.PENDING); createdRequest.setStatus(com.hithomelabs.cftunnels.Entity.Request.RequestStatus.PENDING);
when(mappingRequestService.createMappingRequest(any(String.class), any(com.hithomelabs.CFTunnels.Models.Ingress.class), any())).thenReturn(createdRequest); when(mappingRequestService.createMappingRequest(any(String.class), any(com.hithomelabs.cftunnels.Models.Ingress.class), any())).thenReturn(createdRequest);
mockMvc.perform(post("/cloudflare/tunnels/configure/{tunnelId}/requests", tunnelId.toString()) mockMvc.perform(post("/cloudflare/tunnels/configure/{tunnelId}/requests", tunnelId.toString())
.with(oauth2Login().oauth2User(buildOidcUser("developer", Groups.HOMELAB_DEVELOPER))) .with(oauth2Login().oauth2User(buildOidcUser("developer", Groups.HOMELAB_DEVELOPER)))
@ -247,15 +247,15 @@ class TunnelControllerTest {
@DisplayName("should approve mapping request successfully") @DisplayName("should approve mapping request successfully")
void approveMappingRequest_Success() throws Exception { void approveMappingRequest_Success() throws Exception {
UUID requestId = UUID.randomUUID(); UUID requestId = UUID.randomUUID();
com.hithomelabs.CFTunnels.Entity.User approverUser = new com.hithomelabs.CFTunnels.Entity.User(); com.hithomelabs.cftunnels.Entity.User approverUser = new com.hithomelabs.cftunnels.Entity.User();
approverUser.setEmail("approver@example.com"); approverUser.setEmail("approver@example.com");
approverUser.setName("Approver"); approverUser.setName("Approver");
com.hithomelabs.CFTunnels.Entity.Request approvedRequest = new com.hithomelabs.CFTunnels.Entity.Request(); com.hithomelabs.cftunnels.Entity.Request approvedRequest = new com.hithomelabs.cftunnels.Entity.Request();
approvedRequest.setId(requestId); approvedRequest.setId(requestId);
approvedRequest.setStatus(com.hithomelabs.CFTunnels.Entity.Request.RequestStatus.APPROVED); approvedRequest.setStatus(com.hithomelabs.cftunnels.Entity.Request.RequestStatus.APPROVED);
when(mappingRequestService.approveRequest(eq(requestId), any(com.hithomelabs.CFTunnels.Entity.User.class))) when(mappingRequestService.approveRequest(eq(requestId), any(com.hithomelabs.cftunnels.Entity.User.class)))
.thenReturn(approvedRequest); .thenReturn(approvedRequest);
when(userRepository.findByEmail("approver@example.com")) when(userRepository.findByEmail("approver@example.com"))
.thenReturn(java.util.Optional.of(approverUser)); .thenReturn(java.util.Optional.of(approverUser));
@ -272,11 +272,11 @@ class TunnelControllerTest {
@DisplayName("should return 404 when request not found") @DisplayName("should return 404 when request not found")
void approveMappingRequest_NotFound() throws Exception { void approveMappingRequest_NotFound() throws Exception {
UUID requestId = UUID.randomUUID(); UUID requestId = UUID.randomUUID();
com.hithomelabs.CFTunnels.Entity.User approverUser = new com.hithomelabs.CFTunnels.Entity.User(); com.hithomelabs.cftunnels.Entity.User approverUser = new com.hithomelabs.cftunnels.Entity.User();
approverUser.setEmail("approver@example.com"); approverUser.setEmail("approver@example.com");
approverUser.setName("Approver"); approverUser.setName("Approver");
when(mappingRequestService.approveRequest(eq(requestId), any(com.hithomelabs.CFTunnels.Entity.User.class))) when(mappingRequestService.approveRequest(eq(requestId), any(com.hithomelabs.cftunnels.Entity.User.class)))
.thenThrow(new NoSuchElementException("Request not found")); .thenThrow(new NoSuchElementException("Request not found"));
when(userRepository.findByEmail("approver@example.com")) when(userRepository.findByEmail("approver@example.com"))
.thenReturn(java.util.Optional.of(approverUser)); .thenReturn(java.util.Optional.of(approverUser));
@ -291,11 +291,11 @@ class TunnelControllerTest {
@DisplayName("should return 500 when mapping creation fails") @DisplayName("should return 500 when mapping creation fails")
void approveMappingRequest_InternalServerError() throws Exception { void approveMappingRequest_InternalServerError() throws Exception {
UUID requestId = UUID.randomUUID(); UUID requestId = UUID.randomUUID();
com.hithomelabs.CFTunnels.Entity.User approverUser = new com.hithomelabs.CFTunnels.Entity.User(); com.hithomelabs.cftunnels.Entity.User approverUser = new com.hithomelabs.cftunnels.Entity.User();
approverUser.setEmail("approver@example.com"); approverUser.setEmail("approver@example.com");
approverUser.setName("Approver"); approverUser.setName("Approver");
when(mappingRequestService.approveRequest(eq(requestId), any(com.hithomelabs.CFTunnels.Entity.User.class))) when(mappingRequestService.approveRequest(eq(requestId), any(com.hithomelabs.cftunnels.Entity.User.class)))
.thenThrow(new RuntimeException("Failed to add mapping to Cloudflare")); .thenThrow(new RuntimeException("Failed to add mapping to Cloudflare"));
when(userRepository.findByEmail("approver@example.com")) when(userRepository.findByEmail("approver@example.com"))
.thenReturn(java.util.Optional.of(approverUser)); .thenReturn(java.util.Optional.of(approverUser));
@ -310,15 +310,15 @@ class TunnelControllerTest {
@DisplayName("should reject mapping request successfully") @DisplayName("should reject mapping request successfully")
void rejectMappingRequest_Success() throws Exception { void rejectMappingRequest_Success() throws Exception {
UUID requestId = UUID.randomUUID(); UUID requestId = UUID.randomUUID();
com.hithomelabs.CFTunnels.Entity.User rejecterUser = new com.hithomelabs.CFTunnels.Entity.User(); com.hithomelabs.cftunnels.Entity.User rejecterUser = new com.hithomelabs.cftunnels.Entity.User();
rejecterUser.setEmail("rejecter@example.com"); rejecterUser.setEmail("rejecter@example.com");
rejecterUser.setName("Rejecter"); rejecterUser.setName("Rejecter");
com.hithomelabs.CFTunnels.Entity.Request rejectedRequest = new com.hithomelabs.CFTunnels.Entity.Request(); com.hithomelabs.cftunnels.Entity.Request rejectedRequest = new com.hithomelabs.cftunnels.Entity.Request();
rejectedRequest.setId(requestId); rejectedRequest.setId(requestId);
rejectedRequest.setStatus(com.hithomelabs.CFTunnels.Entity.Request.RequestStatus.REJECTED); rejectedRequest.setStatus(com.hithomelabs.cftunnels.Entity.Request.RequestStatus.REJECTED);
when(mappingRequestService.rejectRequest(eq(requestId), any(com.hithomelabs.CFTunnels.Entity.User.class))) when(mappingRequestService.rejectRequest(eq(requestId), any(com.hithomelabs.cftunnels.Entity.User.class)))
.thenReturn(rejectedRequest); .thenReturn(rejectedRequest);
when(userRepository.findByEmail("rejecter@example.com")) when(userRepository.findByEmail("rejecter@example.com"))
.thenReturn(java.util.Optional.of(rejecterUser)); .thenReturn(java.util.Optional.of(rejecterUser));
@ -335,11 +335,11 @@ class TunnelControllerTest {
@DisplayName("should return 404 when rejecting non-existent request") @DisplayName("should return 404 when rejecting non-existent request")
void rejectMappingRequest_NotFound() throws Exception { void rejectMappingRequest_NotFound() throws Exception {
UUID requestId = UUID.randomUUID(); UUID requestId = UUID.randomUUID();
com.hithomelabs.CFTunnels.Entity.User rejecterUser = new com.hithomelabs.CFTunnels.Entity.User(); com.hithomelabs.cftunnels.Entity.User rejecterUser = new com.hithomelabs.cftunnels.Entity.User();
rejecterUser.setEmail("rejecter@example.com"); rejecterUser.setEmail("rejecter@example.com");
rejecterUser.setName("Rejecter"); rejecterUser.setName("Rejecter");
when(mappingRequestService.rejectRequest(eq(requestId), any(com.hithomelabs.CFTunnels.Entity.User.class))) when(mappingRequestService.rejectRequest(eq(requestId), any(com.hithomelabs.cftunnels.Entity.User.class)))
.thenThrow(new NoSuchElementException("Request not found")); .thenThrow(new NoSuchElementException("Request not found"));
when(userRepository.findByEmail("rejecter@example.com")) when(userRepository.findByEmail("rejecter@example.com"))
.thenReturn(java.util.Optional.of(rejecterUser)); .thenReturn(java.util.Optional.of(rejecterUser));
@ -354,11 +354,11 @@ class TunnelControllerTest {
@DisplayName("should return 409 when rejecting already processed request") @DisplayName("should return 409 when rejecting already processed request")
void rejectMappingRequest_Conflict() throws Exception { void rejectMappingRequest_Conflict() throws Exception {
UUID requestId = UUID.randomUUID(); UUID requestId = UUID.randomUUID();
com.hithomelabs.CFTunnels.Entity.User rejecterUser = new com.hithomelabs.CFTunnels.Entity.User(); com.hithomelabs.cftunnels.Entity.User rejecterUser = new com.hithomelabs.cftunnels.Entity.User();
rejecterUser.setEmail("rejecter@example.com"); rejecterUser.setEmail("rejecter@example.com");
rejecterUser.setName("Rejecter"); rejecterUser.setName("Rejecter");
when(mappingRequestService.rejectRequest(eq(requestId), any(com.hithomelabs.CFTunnels.Entity.User.class))) when(mappingRequestService.rejectRequest(eq(requestId), any(com.hithomelabs.cftunnels.Entity.User.class)))
.thenThrow(new IllegalStateException("Request is not in PENDING status")); .thenThrow(new IllegalStateException("Request is not in PENDING status"));
when(userRepository.findByEmail("rejecter@example.com")) when(userRepository.findByEmail("rejecter@example.com"))
.thenReturn(java.util.Optional.of(rejecterUser)); .thenReturn(java.util.Optional.of(rejecterUser));

View File

@ -1,13 +1,13 @@
package com.hithomelabs.CFTunnels.Integration; package com.hithomelabs.cftunnels.Integration;
import com.hithomelabs.CFTunnels.Config.CloudflareConfig; import com.hithomelabs.cftunnels.Config.CloudflareConfig;
import com.hithomelabs.CFTunnels.Headers.AuthKeyEmailHeader; import com.hithomelabs.cftunnels.Headers.AuthKeyEmailHeader;
import com.hithomelabs.CFTunnels.Models.Config; import com.hithomelabs.cftunnels.Models.Config;
import com.hithomelabs.CFTunnels.Models.Ingress; import com.hithomelabs.cftunnels.Models.Ingress;
import com.hithomelabs.CFTunnels.Models.TunnelResponse; import com.hithomelabs.cftunnels.Models.TunnelResponse;
import com.hithomelabs.CFTunnels.Models.TunnelResult; import com.hithomelabs.cftunnels.Models.TunnelResult;
import com.hithomelabs.CFTunnels.Models.TunnelsResponse; import com.hithomelabs.cftunnels.Models.TunnelsResponse;
import com.hithomelabs.CFTunnels.Services.CloudflareAPIService; import com.hithomelabs.cftunnels.Services.CloudflareAPIService;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -1,10 +1,10 @@
package com.hithomelabs.CFTunnels.Repositories; package com.hithomelabs.cftunnels.Repositories;
import com.hithomelabs.CFTunnels.Entity.Mapping; import com.hithomelabs.cftunnels.Entity.Mapping;
import com.hithomelabs.CFTunnels.Entity.Protocol; import com.hithomelabs.cftunnels.Entity.Protocol;
import com.hithomelabs.CFTunnels.Entity.Request; import com.hithomelabs.cftunnels.Entity.Request;
import com.hithomelabs.CFTunnels.Entity.Tunnel; import com.hithomelabs.cftunnels.Entity.Tunnel;
import com.hithomelabs.CFTunnels.Entity.User; import com.hithomelabs.cftunnels.Entity.User;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;

View File

@ -1,17 +1,17 @@
package com.hithomelabs.CFTunnels.Services; package com.hithomelabs.cftunnels.Services;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.hithomelabs.CFTunnels.Config.CloudflareConfig; import com.hithomelabs.cftunnels.Config.CloudflareConfig;
import com.hithomelabs.CFTunnels.Entity.Tunnel; import com.hithomelabs.cftunnels.Entity.Tunnel;
import com.hithomelabs.CFTunnels.Exceptions.ExternalServiceException; import com.hithomelabs.cftunnels.Exceptions.ExternalServiceException;
import com.hithomelabs.CFTunnels.Headers.AuthKeyEmailHeader; import com.hithomelabs.cftunnels.Headers.AuthKeyEmailHeader;
import com.hithomelabs.CFTunnels.Models.Config; import com.hithomelabs.cftunnels.Models.Config;
import com.hithomelabs.CFTunnels.Models.Ingress; import com.hithomelabs.cftunnels.Models.Ingress;
import com.hithomelabs.CFTunnels.Models.TunnelResponse; import com.hithomelabs.cftunnels.Models.TunnelResponse;
import com.hithomelabs.CFTunnels.Models.TunnelResult; import com.hithomelabs.cftunnels.Models.TunnelResult;
import com.hithomelabs.CFTunnels.Models.TunnelsResponse; import com.hithomelabs.cftunnels.Models.TunnelsResponse;
import com.hithomelabs.CFTunnels.Repositories.TunnelRepository; import com.hithomelabs.cftunnels.Repositories.TunnelRepository;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
@ -26,7 +26,7 @@ import java.util.NoSuchElementException;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static com.hithomelabs.CFTunnels.TestUtils.Util.getClassPathDataResource; import static com.hithomelabs.cftunnels.TestUtils.Util.getClassPathDataResource;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.TestUtils; package com.hithomelabs.cftunnels.TestUtils;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;

11
common/build.gradle Normal file
View File

@ -0,0 +1,11 @@
dependencies {
implementation 'org.springframework:spring-context'
implementation 'org.springframework:spring-web'
implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'org.apache.httpcomponents.client5:httpclient5'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.junit.jupiter:junit-jupiter'
}

View File

@ -1,4 +1,4 @@
package com.hithomelabs.CFTunnels.Config; package com.hithomelabs.common.config;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;

2
gradle.properties Normal file
View File

@ -0,0 +1,2 @@
version=0.0.1-SNAPSHOT
group=com.hithomelabs

View File

@ -0,0 +1,14 @@
apply plugin: 'org.springframework.boot'
dependencies {
implementation project(':common')
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

View File

@ -0,0 +1,12 @@
package com.hithomelabs.portainer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PortainerAutomationApplication {
public static void main(String[] args) {
SpringApplication.run(PortainerAutomationApplication.class, args);
}
}

View File

@ -0,0 +1 @@
server.port=8081

4
settings.gradle Normal file
View File

@ -0,0 +1,4 @@
rootProject.name = 'cftunnels'
include 'common'
include 'cftunnels-service'
include 'portainer-automation'