CFTunnels/src/main/java/com/hithomelabs/CFTunnels/Services/MappingRequestService.java

153 lines
5.5 KiB
Java

package com.hithomelabs.CFTunnels.Services;
import com.hithomelabs.CFTunnels.Entity.Mapping;
import com.hithomelabs.CFTunnels.Entity.Protocol;
import com.hithomelabs.CFTunnels.Entity.Request;
import com.hithomelabs.CFTunnels.Entity.Tunnel;
import com.hithomelabs.CFTunnels.Entity.User;
import com.hithomelabs.CFTunnels.Models.Ingress;
import com.hithomelabs.CFTunnels.Repositories.MappingRepository;
import com.hithomelabs.CFTunnels.Repositories.RequestRepository;
import com.hithomelabs.CFTunnels.Repositories.TunnelRepository;
import com.hithomelabs.CFTunnels.Repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.UUID;
@Service
public class MappingRequestService {
@Autowired
UserRepository userRepository;
@Autowired
MappingRepository mappingRepository;
@Autowired
RequestRepository requestRepository;
@Autowired
TunnelRepository tunnelRepository;
@Autowired
CloudflareAPIService cloudflareAPIService;
public Mapping createMapping(UUID tunnelId, Ingress ingress){
Tunnel tunnel = tunnelRepository.findById(tunnelId).orElseThrow(() -> new RuntimeException("Tunnel not found"));
Mapping mapping = createMappingFromTunnelIngress(tunnel, ingress);
return mappingRepository.save(mapping);
}
public Request createRequest(Mapping mapping, User user){
Request request = new Request();
request.setMapping(mapping);
request.setCreatedBy(user);
request.setStatus(Request.RequestStatus.PENDING);
return requestRepository.save(request);
}
public Request createMappingRequest(String tunnelId, Ingress ingress, OidcUser oidcUser){
User user = userRepository.findByEmail(oidcUser.getEmail()).orElseGet(()-> mapUser(oidcUser));
Mapping mapping = createMapping(UUID.fromString(tunnelId), ingress);
return createRequest(mapping, user);
}
@Transactional(readOnly = true)
public List<Request> getAllRequests() {
return requestRepository.findAllWithDetails();
}
public User mapUser(OidcUser oidcUser){
String email = oidcUser.getEmail();
String name = oidcUser.getNickName();
User user = new User();
user.setEmail(email);
user.setName(name);
userRepository.save(user);
return user;
}
public Mapping createMappingFromTunnelIngress(Tunnel tunnel, Ingress ingress){
Mapping mapping = new Mapping();
mapping.setTunnel(tunnel);
String serviceString = ingress.getService().toLowerCase();
Protocol protocol = parseProtocol(serviceString);
mapping.setProtocol(protocol);
mapping.setPort(Integer.parseInt(ingress.getService().split(":")[2]));
mapping.setSubdomain(ingress.getHostname().split("\\.")[0]);
return mapping;
}
private Protocol parseProtocol(String serviceString) {
if (serviceString.startsWith("https://")) {
return Protocol.HTTPS;
} else if (serviceString.startsWith("tcp://")) {
return Protocol.TCP;
} else if (serviceString.startsWith("ssh://")) {
return Protocol.SSH;
}
return Protocol.HTTP;
}
@Transactional
public Request approveRequest(UUID requestId, User approver) {
Request request = requestRepository.findByIdWithDetails(requestId)
.orElseThrow(() -> new NoSuchElementException("Request not found"));
if (request.getStatus() != Request.RequestStatus.PENDING) {
throw new IllegalStateException("Request is not in PENDING status");
}
Mapping mapping = request.getMapping();
Tunnel tunnel = mapping.getTunnel();
Ingress ingress = createIngressFromMapping(mapping);
ResponseEntity<?> response = cloudflareAPIService.addTunnelIngress(
tunnel.getId().toString(),
ingress
);
if (!response.getStatusCode().is2xxSuccessful()) {
throw new RuntimeException("Failed to add mapping to Cloudflare");
}
request.setStatus(Request.RequestStatus.APPROVED);
request.setAcceptedBy(approver);
return requestRepository.save(request);
}
@Transactional
public Request rejectRequest(UUID requestId, User rejecter) {
Request request = requestRepository.findByIdWithDetails(requestId)
.orElseThrow(() -> new NoSuchElementException("Request not found"));
if (request.getStatus() != Request.RequestStatus.PENDING) {
throw new IllegalStateException("Request is not in PENDING status");
}
request.setStatus(Request.RequestStatus.REJECTED);
request.setAcceptedBy(rejecter);
return requestRepository.save(request);
}
private static final String SERVER_IP = "192.168.0.100";
private Ingress createIngressFromMapping(Mapping mapping) {
Tunnel tunnel = mapping.getTunnel();
String protocol = mapping.getProtocol().name().toLowerCase();
String service = protocol + "://" + SERVER_IP + ":" + mapping.getPort();
String hostname = mapping.getSubdomain() + ".hithomelabs.com";
return new Ingress(service, hostname, null, null);
}
}