Compare commits

...

3 Commits

Author SHA1 Message Date
3b43039a29 Add Request import and simplify createTestRequest method
All checks were successful
sample gradle build and test / build (pull_request) Successful in 2m2s
sample gradle build and test / tag (push) Successful in 8s
sample gradle build and test / build_tag_push (push) Successful in 2m4s
2026-02-15 22:37:19 +05:30
09e631c871 Restore removed tests for approve/reject endpoints 2026-02-15 22:34:21 +05:30
9a25495d9c Remove pagination and filtering from /requests endpoint 2026-02-15 22:06:07 +05:30
12 changed files with 20 additions and 148 deletions

View File

@ -1,11 +0,0 @@
meta {
name: Get tunnels
type: http
seq: 4
}
get {
url: {{base_url}}/cloudflare/tunnels
body: none
auth: none
}

View File

@ -1,11 +0,0 @@
meta {
name: Tunnel
type: http
seq: 5
}
get {
url: {{base_url}}/cloudflare/tunnel/{{tunnel_id}}
body: none
auth: none
}

View File

@ -1,19 +0,0 @@
meta {
name: Write ingress
type: http
seq: 2
}
put {
url: {{base_url}}/cloudflare/tunnel/{{tunnel_id}}/add
body: json
auth: none
}
body:json {
{
"service": "http://192.168.0.100:3457",
"hostname": "random.hithomelabs.com",
"originRequest": {}
}
}

View File

@ -1,9 +0,0 @@
{
"version": "1",
"name": "CFTunnels",
"type": "collection",
"ignore": [
"node_modules",
".git"
]
}

View File

@ -1,19 +0,0 @@
meta {
name: delete mapping
type: http
seq: 3
}
put {
url: {{base_url}}/cloudflare/tunnel/{{tunnel_id}}/delete
body: json
auth: none
}
body:json {
{
"service": "http://192.168.0.100:6000",
"hostname": "random.hithomelabs.com",
"originRequest": {}
}
}

View File

@ -1,4 +0,0 @@
vars {
tunnel_id: 50df9101-f625-4618-b7c5-100338a57124
base_url: http://localhost:8080
}

View File

@ -1,4 +0,0 @@
vars {
tunnel_id: 50df9101-f625-4618-b7c5-100338a57124
base_url: https://testcf.hithomelabs.com
}

View File

@ -10,7 +10,6 @@ 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.PaginationRequest;
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;
@ -22,10 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.data.domain.Page; import org.springframework.http.*;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.*; import org.springframework.http.*;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
@ -112,21 +108,12 @@ public class TunnelController implements ErrorController {
@PreAuthorize("hasAnyRole('USER')") @PreAuthorize("hasAnyRole('USER')")
@GetMapping("/requests") @GetMapping("/requests")
public ResponseEntity<Map<String,Object>> getAllRequests( public ResponseEntity<Map<String,Object>> getAllRequests() {
@RequestParam(required = false) Request.RequestStatus status,
@ModelAttribute PaginationRequest paginationRequest) {
try { try {
Sort sort = paginationRequest.getSort() != null && paginationRequest.getSort().length > 0 List<Request> requests = mappingRequestService.getAllRequests();
? Sort.by(paginationRequest.getSort())
: Sort.by("id");
Pageable pageable = PageRequest.of(paginationRequest.getPage(), paginationRequest.getSize(), sort);
Page<Request> requests = mappingRequestService.getAllRequests(status, pageable);
Map<String, Object> jsonResponse = new HashMap<>(); Map<String, Object> jsonResponse = new HashMap<>();
jsonResponse.put("status", "success"); jsonResponse.put("status", "success");
jsonResponse.put("data", requests.getContent()); jsonResponse.put("data", requests);
jsonResponse.put("currentPage", requests.getNumber());
jsonResponse.put("totalItems", requests.getTotalElements());
jsonResponse.put("totalPages", requests.getTotalPages());
return ResponseEntity.ok(jsonResponse); return ResponseEntity.ok(jsonResponse);
} catch (DataAccessException e) { } catch (DataAccessException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();

View File

@ -1,14 +0,0 @@
package com.hithomelabs.CFTunnels.Models;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PaginationRequest {
private int page = 0;
private int size = 10;
private String[] sort = {"id"};
}

View File

@ -11,8 +11,6 @@ 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.data.domain.Page;
import org.springframework.data.domain.Pageable;
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;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -61,11 +59,8 @@ public class MappingRequestService {
return createRequest(mapping, user); return createRequest(mapping, user);
} }
public Page<Request> getAllRequests(Request.RequestStatus status, Pageable pageable) { public List<Request> getAllRequests() {
if (status != null) { return requestRepository.findAll();
return requestRepository.findByStatus(status, pageable);
}
return requestRepository.findAll(pageable);
} }
public User mapUser(OidcUser oidcUser){ public User mapUser(OidcUser oidcUser){

View File

@ -7,4 +7,6 @@ management.endpoint.health.show-details=always
logging.level.org.hibernate.SQL=DEBUG logging.level.org.hibernate.SQL=DEBUG
debug=true debug=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.datasource.url=jdbc:postgresql://localhost:5432/cftunnel spring.datasource.url=jdbc:postgresql://localhost:5432/cftunnel

View File

@ -5,6 +5,7 @@ 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.CFTunnels.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.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;
@ -204,44 +205,22 @@ class TunnelControllerTest {
} }
@Test @Test
@DisplayName("should return list of requests with pagination") @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)
); );
Page<com.hithomelabs.CFTunnels.Entity.Request> page = new PageImpl<>(requests, PageRequest.of(0, 10), 2);
when(mappingRequestService.getAllRequests(any(), any(PageRequest.class))).thenReturn(page); when(mappingRequestService.getAllRequests()).thenReturn(requests);
mockMvc.perform(get("/cloudflare/requests") mockMvc.perform(get("/cloudflare/requests")
.with(oauth2Login().oauth2User(buildOidcUser("username", Groups.GITEA_USER))) .with(oauth2Login().oauth2User(buildOidcUser("username", Groups.GITEA_USER))))
.param("page", "0")
.param("size", "10"))
.andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON)) .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.status").value("success")) .andExpect(jsonPath("$.status").value("success"))
.andExpect(jsonPath("$.data").isArray()) .andExpect(jsonPath("$.data").isArray())
.andExpect(jsonPath("$.totalItems").value(2)) .andExpect(jsonPath("$.data.length()").value(2));
.andExpect(jsonPath("$.totalPages").value(1));
}
@Test
@DisplayName("should filter requests by status")
void getAllRequests_WithStatusFilter() throws Exception {
List<com.hithomelabs.CFTunnels.Entity.Request> requests = List.of(
createTestRequest(UUID.randomUUID(), com.hithomelabs.CFTunnels.Entity.Request.RequestStatus.PENDING)
);
Page<com.hithomelabs.CFTunnels.Entity.Request> page = new PageImpl<>(requests, PageRequest.of(0, 10), 1);
when(mappingRequestService.getAllRequests(eq(com.hithomelabs.CFTunnels.Entity.Request.RequestStatus.PENDING), any(PageRequest.class))).thenReturn(page);
mockMvc.perform(get("/cloudflare/requests")
.with(oauth2Login().oauth2User(buildOidcUser("username", Groups.GITEA_USER)))
.param("status", "PENDING"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value("success"))
.andExpect(jsonPath("$.data[0].status").value("PENDING"));
} }
@Test @Test
@ -264,13 +243,6 @@ class TunnelControllerTest {
.andExpect(jsonPath("$.status").value("PENDING")); .andExpect(jsonPath("$.status").value("PENDING"));
} }
private com.hithomelabs.CFTunnels.Entity.Request createTestRequest(UUID id, com.hithomelabs.CFTunnels.Entity.Request.RequestStatus status) {
com.hithomelabs.CFTunnels.Entity.Request request = new com.hithomelabs.CFTunnels.Entity.Request();
request.setId(id);
request.setStatus(status);
return request;
}
@Test @Test
@DisplayName("should approve mapping request successfully") @DisplayName("should approve mapping request successfully")
void approveMappingRequest_Success() throws Exception { void approveMappingRequest_Success() throws Exception {
@ -437,6 +409,13 @@ class TunnelControllerTest {
.andExpect(jsonPath("$.data.result.config.ingress[*].hostname", hasItem("random.hithomelabs.com"))); .andExpect(jsonPath("$.data.result.config.ingress[*].hostname", hasItem("random.hithomelabs.com")));
} }
private Request createTestRequest(UUID id, Request.RequestStatus status) {
Request request = new Request();
request.setId(id);
request.setStatus(status);
return request;
}
@Test @Test
void deleteTunnelConfiguration() throws Exception { void deleteTunnelConfiguration() throws Exception {