Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28b003a066 | ||
|
|
1f892e449f | ||
|
|
9817d77e7f | ||
|
|
02dc401224 | ||
|
|
6047471ff8 | ||
|
|
e2b2cc3ead | ||
|
|
ccfe79f7f1 | ||
|
|
a40865e989 | ||
| 5ea76dab56 | |||
| 4c7f0dad4b | |||
| 82244741ed | |||
| 7d450e0023 | |||
| 4377b437d1 | |||
| 54320b8085 | |||
| 39b3c0bb48 | |||
| 2f67dbfbca | |||
| 0130ee364a | |||
| 9e5af51cf9 | |||
| 22d5310223 | |||
| 24beaf678b | |||
| 38a0bd9659 | |||
| 667f7c81dd | |||
| 4d7a52b0ba | |||
| 77f8395837 | |||
| 5cc342462c | |||
| 3b572787f8 | |||
| ecf87ad1e3 | |||
| dd67fe89c9 | |||
| c6af4cf227 | |||
| 4a0c4dba52 | |||
| 4a545d8a30 | |||
| f9c8d9fcca | |||
| b4112eb005 | |||
| 2f61047255 | |||
| c380f8da10 | |||
| 8efa0e495e | |||
| 9561772b9c | |||
| 35e83eed48 | |||
| a239a7e143 | |||
| eaaa1f7cc3 | |||
| af51165e49 | |||
| 8b90815f69 | |||
| df63ab652f | |||
| ce2f83106c | |||
| b5886c4eca | |||
| 770da7d675 | |||
| af7adec1cb | |||
| 19ef13d8f7 | |||
| 58d8f2fed0 | |||
| 089c7facee | |||
| 5a179ae287 | |||
| 8146145be5 | |||
| a3ca19d48a | |||
| 014cac1fc0 | |||
| b02a334dbe | |||
| 60711270c4 | |||
| 431b4ff0c7 | |||
| 889e29d82e | |||
| 611fe50a25 | |||
| a72d751951 | |||
| c09615d066 | |||
| d3456b5efd | |||
| 1dd7b9143d | |||
| 926feca855 | |||
| babd86e063 | |||
| c3fddb29dd | |||
| 07f9f2f479 | |||
| 475ac22f79 | |||
| 9423178737 | |||
| e16548b54a | |||
| e40bcce202 | |||
| c45df6867f | |||
| 2a242df197 | |||
| baef77d389 | |||
| 50d2fc099b | |||
| f10c52adcb | |||
| c0b881974b | |||
| 524be544bc | |||
| 72ada2d0dd | |||
| 507fd17539 | |||
| f64579e393 | |||
| 89f6620214 | |||
| c90756ebe3 | |||
| 558b570121 | |||
| 75eb408980 | |||
| 5d74960c7f | |||
| cef7dd18e2 | |||
| 6d115abb95 |
@ -64,4 +64,23 @@ jobs:
|
||||
run: |
|
||||
docker push 192.168.0.100:8928/hithomelabs/cftunnels:test
|
||||
docker push 192.168.0.100:8928/hithomelabs/cftunnels:${{ needs.tag.outputs.new_version }}
|
||||
|
||||
sync_forks:
|
||||
name: Sync All Forks
|
||||
runs-on: ubuntu-latest
|
||||
needs: build_tag_push
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Sync all forks via Gitea API
|
||||
run: |
|
||||
echo "Fetching forks for Hithomelabs/CFTunnels..."
|
||||
response=$(curl -s -X GET "https://gitea.hithomelabs.com/api/v1/repos/Hithomelabs/CFTunnels/forks" -H "Authorization: token ${{secrets.TOKEN}}")
|
||||
filtered=$(echo "$response" | grep -o '"clone_url":"[^"]*"' | sed 's/"clone_url":"\([^"]*\)"/\1/' | grep -v "/Hithomelabs")
|
||||
echo "Detected forks:"
|
||||
echo "$filtered"
|
||||
readarray -t forks <<< "$filtered"
|
||||
for fork_url in "${forks[@]}"; do
|
||||
echo "🔄 Syncing fork: $fork_url"
|
||||
authed_url=$(echo "$fork_url" | sed "s#https://#https://${{secrets.TOKEN}}@#")
|
||||
git push "$authed_url" test &
|
||||
done
|
||||
|
||||
@ -14,7 +14,7 @@ java {
|
||||
}
|
||||
|
||||
test {
|
||||
systemProperty 'spring.profiles.active', 'ci'
|
||||
systemProperty 'spring.profiles.active', 'test'
|
||||
useJUnitPlatform {
|
||||
excludeTags 'integration'
|
||||
}
|
||||
|
||||
@ -14,7 +14,6 @@ services:
|
||||
- HOST_PORT=${HOST_PORT}
|
||||
- POSTGRES_USER=${POSTGRES_USERNAME}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- SWAGGER_OAUTH_CLIENT_ID=${SWAGGER_OAUTH_CLIENT_ID}
|
||||
env_file:
|
||||
- stack.env
|
||||
restart: unless-stopped
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
package com.hithomelabs.CFTunnels.Config;
|
||||
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.security.*;
|
||||
import io.swagger.v3.oas.models.servers.Server;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -18,12 +16,6 @@ public class OpenApiConfig {
|
||||
@Value("${api.baseUrl}")
|
||||
private String baseUrl;
|
||||
|
||||
@Value("${springdoc.swagger-ui.oauth.authorization-url}")
|
||||
private String authorizationUri;
|
||||
|
||||
@Value("${springdoc.swagger-ui.oauth.token-url}")
|
||||
private String tokenUri;
|
||||
|
||||
@Bean
|
||||
public OpenAPI openAPI(){
|
||||
Server httpsServer = new Server().url(baseUrl);
|
||||
@ -31,24 +23,6 @@ public class OpenApiConfig {
|
||||
ArrayList<Server> servers = new ArrayList<>();
|
||||
servers.add(httpsServer);
|
||||
openApi.setServers(servers);
|
||||
openApi.addSecurityItem(new SecurityRequirement().addList("oidcAuth"))
|
||||
.components(new Components()
|
||||
.addSecuritySchemes("oidcAuth",
|
||||
new SecurityScheme()
|
||||
.type(SecurityScheme.Type.OAUTH2)
|
||||
.flows(new OAuthFlows()
|
||||
.authorizationCode(new OAuthFlow()
|
||||
.authorizationUrl(authorizationUri)
|
||||
.tokenUrl(tokenUri)
|
||||
.scopes(new Scopes()
|
||||
.addString("openid", "OpenID scope")
|
||||
.addString("profile", "OpenID profile")
|
||||
.addString("email", "OpenID email"))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.addSecurityItem(new SecurityRequirement().addList("oidcAuth"));
|
||||
return openApi;
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,6 @@ public class SecuirtyConfig {
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
//.requestMatchers( "/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html" ).permitAll()
|
||||
.anyRequest().authenticated()
|
||||
).csrf(csrf -> csrf.disable())
|
||||
.with(new OAuth2LoginConfigurer<>(),
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
package com.hithomelabs.CFTunnels.Controllers;
|
||||
|
||||
|
||||
import org.springframework.boot.web.servlet.error.ErrorController;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class HomeController implements ErrorController {
|
||||
|
||||
private static final String ERROR_PATH = "/error";
|
||||
|
||||
/**
|
||||
* Redirects the root (including any query params like ?continue=…)
|
||||
* straight into Swagger UI.
|
||||
*/
|
||||
@GetMapping("/")
|
||||
public String rootRedirect() {
|
||||
return "redirect:/swagger-ui/index.html";
|
||||
}
|
||||
|
||||
/**
|
||||
* Catches any errors (404s, unhandled paths) and punts them
|
||||
* into the same Swagger UI page.
|
||||
*/
|
||||
@RequestMapping(ERROR_PATH)
|
||||
public String onError() {
|
||||
return "redirect:/swagger-ui/index.html";
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,8 +11,6 @@ import com.hithomelabs.CFTunnels.Models.Ingress;
|
||||
import com.hithomelabs.CFTunnels.Models.TunnelResponse;
|
||||
import com.hithomelabs.CFTunnels.Services.CloudflareAPIService;
|
||||
import com.hithomelabs.CFTunnels.Services.MappingRequestService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.web.servlet.error.ErrorController;
|
||||
import org.springframework.http.*;
|
||||
@ -66,7 +64,6 @@ public class TunnelController implements ErrorController {
|
||||
|
||||
@PreAuthorize("hasAnyRole('USER')")
|
||||
@GetMapping("/tunnels")
|
||||
@Operation( security = { @SecurityRequirement(name = "oidcAuth") } )
|
||||
public ResponseEntity<Map<String,Object>> getTunnels(){
|
||||
|
||||
ResponseEntity<Map> responseEntity = cloudflareAPIService.getCloudflareTunnels();
|
||||
@ -78,7 +75,7 @@ public class TunnelController implements ErrorController {
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('DEVELOPER')")
|
||||
@GetMapping("/tunnel/{tunnelId}/mappings")
|
||||
@GetMapping("/tunnel/{tunnelId}")
|
||||
public ResponseEntity<Map<String,Object>> getTunnelConfigurations(@PathVariable String tunnelId) {
|
||||
|
||||
ResponseEntity<Map> responseEntity = cloudflareAPIService.getCloudflareTunnelConfigurations(tunnelId, restTemplate, Map.class);
|
||||
@ -91,7 +88,7 @@ public class TunnelController implements ErrorController {
|
||||
|
||||
// 50df9101-f625-4618-b7c5-100338a57124
|
||||
@PreAuthorize("hasAnyRole('ADMIN')")
|
||||
@PostMapping("/tunnel/{tunnelId}/mappings")
|
||||
@PutMapping("/tunnel/{tunnelId}/add")
|
||||
public ResponseEntity<Map<String, Object>> addTunnelconfiguration(@PathVariable String tunnelId, @RequestBody Ingress ingress) throws JsonProcessingException {
|
||||
|
||||
ResponseEntity<TunnelResponse> responseEntity = cloudflareAPIService.getCloudflareTunnelConfigurations(tunnelId, restTemplateConfig.restTemplate(), TunnelResponse.class);
|
||||
@ -113,7 +110,7 @@ public class TunnelController implements ErrorController {
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('DEVELOPER')")
|
||||
@DeleteMapping("/tunnel/{tunnelId}/mappings")
|
||||
@PutMapping("/tunnel/{tunnelId}/delete")
|
||||
public ResponseEntity<Map<String, Object>> deleteTunnelConfiguration(@PathVariable String tunnelId, @RequestBody Ingress ingress) throws JsonProcessingException {
|
||||
|
||||
ResponseEntity<TunnelResponse> responseEntity = cloudflareAPIService.getCloudflareTunnelConfigurations(tunnelId, restTemplateConfig.restTemplate(), TunnelResponse.class);
|
||||
@ -142,7 +139,7 @@ public class TunnelController implements ErrorController {
|
||||
}
|
||||
|
||||
@PreAuthorize("hasAnyRole('DEVELOPER')")
|
||||
@PostMapping("/tunnel/{tunnelId}/requests")
|
||||
@PutMapping("/tunnel/{tunnelId}/request")
|
||||
public ResponseEntity<Request> createTunnelMappingRequest(@PathVariable String tunnelId, @AuthenticationPrincipal OidcUser oidcUser, @RequestBody Ingress ingess){
|
||||
Request request = mappingRequestService.createMappingRequest(tunnelId, ingess, oidcUser);
|
||||
if(request.getId() != null)
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
api.baseUrl=https://testcf.hithomelabs.com
|
||||
|
||||
spring.datasource.url=jdbc:h2:mem:testdb
|
||||
spring.datasource.driver-class-name=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
@ -1,9 +1,3 @@
|
||||
cloudflare.accountId=${CLOUDFLARE_ACCOUNT_ID}
|
||||
cloudflare.apiKey=${CLOUDFLARE_API_KEY}
|
||||
cloudflare.email=${CLOUDFLARE_EMAIL}
|
||||
|
||||
spring.datasource.url=jdbc:h2:mem:testdb
|
||||
spring.datasource.driver-class-name=org.h2.Driver
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.jpa.hibernate.ddl-auto=none
|
||||
@ -1,12 +1 @@
|
||||
api.baseUrl=https://cftunnels.hithomelabs.com
|
||||
|
||||
# Production Database Configuration
|
||||
spring.datasource.url=jdbc:postgresql://postgres:5432/cftunnel
|
||||
spring.datasource.username=${POSTGRES_USERNAME}
|
||||
spring.datasource.password=${POSTGRES_PASSWORD}
|
||||
spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
|
||||
# JPA Configuration
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=false
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
|
||||
@ -1,12 +1,7 @@
|
||||
api.baseUrl=https://testcf.hithomelabs.com
|
||||
|
||||
# Test Database Configuration - Same as Production
|
||||
spring.datasource.url=jdbc:postgresql://postgres:5432/cftunnel
|
||||
spring.datasource.username=${POSTGRES_USERNAME}
|
||||
spring.datasource.password=${POSTGRES_PASSWORD}
|
||||
spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
|
||||
# JPA Configuration
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
|
||||
spring.datasource.url: jdbc:h2:mem:testdb
|
||||
spring.datasource.driver-class-name: org.h2.Driver
|
||||
spring.datasource.username: sa
|
||||
spring.datasource.password:
|
||||
spring.datasource.jpa.hibernate.ddl-auto: none
|
||||
@ -18,13 +18,6 @@ spring.security.oauth2.client.provider.cftunnels.user-info-uri=https://auth.hith
|
||||
spring.security.oauth2.client.provider.cftunnels.jwk-set-uri=https://auth.hithomelabs.com/application/o/cftunnels/jwks/
|
||||
spring.security.oauth2.client.provider.cftunnels.issuer-uri=https://auth.hithomelabs.com/application/o/cftunnels/
|
||||
|
||||
springdoc.swagger-ui.oauth.client-id=${SWAGGER_OAUTH_CLIENT_ID}
|
||||
springdoc.swagger-ui.oauth.client-secret= # leave empty for public client
|
||||
springdoc.swagger-ui.oauth.use-pkce=true
|
||||
springdoc.swagger-ui.oauth.scopes=openid,profile,email
|
||||
springdoc.swagger-ui.oauth.authorization-url=https://auth.hithomelabs.com/application/o/authorize/
|
||||
springdoc.swagger-ui.oauth.token-url=https://auth.hithomelabs.com/application/o/token/
|
||||
|
||||
spring.datasource.url=jdbc:postgresql://192.168.0.100:5432/cftunnel
|
||||
spring.datasource.username=${POSTGRES_USERNAME}
|
||||
spring.datasource.password=${POSTGRES_PASSWORD}
|
||||
|
||||
@ -36,7 +36,8 @@ import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
@ -161,7 +162,7 @@ class TunnelControllerTest {
|
||||
|
||||
when(cloudflareAPIService.getCloudflareTunnelConfigurations(eq("sampleTunnelId"), any(RestTemplate.class), eq(Map.class))).thenReturn(mockResponse);
|
||||
|
||||
mockMvc.perform(get("/cloudflare/tunnel/{tunnelId}/mappings", "sampleTunnelId")
|
||||
mockMvc.perform(get("/cloudflare/tunnel/{tunnelId}", "sampleTunnelId")
|
||||
.with(oauth2Login().oauth2User(buildOidcUser("username", Groups.HOMELAB_DEVELOPER))))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
|
||||
@ -183,7 +184,7 @@ class TunnelControllerTest {
|
||||
ResponseEntity<TunnelResponse> expectedHttpTunnelResponse = new ResponseEntity<>(expectedTunnelConfig, HttpStatus.OK);
|
||||
when(cloudflareAPIService.putCloudflareTunnelConfigurations(eq("sampleTunnelId"), any(RestTemplate.class), eq(TunnelResponse.class), any(Config.class))).thenReturn(expectedHttpTunnelResponse);
|
||||
|
||||
mockMvc.perform(post("/cloudflare/tunnel/{tunnelId}/mappings", "sampleTunnelId")
|
||||
mockMvc.perform(put("/cloudflare/tunnel/{tunnelId}/add", "sampleTunnelId")
|
||||
.with(oauth2Login().oauth2User(buildOidcUser("admin", Groups.SYSTEM_ADMIN)))
|
||||
.with(csrf())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
@ -208,7 +209,7 @@ class TunnelControllerTest {
|
||||
ResponseEntity<TunnelResponse> expectedHttpTunnelResponse = new ResponseEntity<>(expectedTunnelConfig, HttpStatus.OK);
|
||||
when(cloudflareAPIService.putCloudflareTunnelConfigurations(eq("sampleTunnelId"), any(RestTemplate.class), eq(TunnelResponse.class), any(Config.class))).thenReturn(expectedHttpTunnelResponse);
|
||||
|
||||
mockMvc.perform(delete("/cloudflare/tunnel/{tunnelId}/mappings", "sampleTunnelId")
|
||||
mockMvc.perform(put("/cloudflare/tunnel/{tunnelId}/delete", "sampleTunnelId")
|
||||
.with(oauth2Login().oauth2User(buildOidcUser("admin", Groups.SYSTEM_ADMIN)))
|
||||
.with(csrf())
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user