forked from Hithomelabs/CFTunnels
153 lines
5.5 KiB
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);
|
|
}
|
|
}
|