package bisq.core.grpc;

import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import io.grpc.StatusRuntimeException;

import lombok.extern.slf4j.Slf4j;

import static io.grpc.Metadata.ASCII_STRING_MARSHALLER;
import static io.grpc.Metadata.Key;
import static io.grpc.Status.UNAUTHENTICATED;

/**
 * Simple authentication interceptor to validate a cleartext token in username:password format.
 */
@Slf4j
public class AuthenticationInterceptor implements ServerInterceptor {

    private final String rpcUser;
    private final String rpcPassword;

    public AuthenticationInterceptor(String rpcUser, String rpcPassword) {
        this.rpcUser = rpcUser;
        this.rpcPassword = rpcPassword;
    }

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata,
                                                                 ServerCallHandler<ReqT, RespT> serverCallHandler) {
        authenticate(metadata);
        return serverCallHandler.startCall(serverCall, metadata);
    }

    private void authenticate(Metadata metadata) {
        String authToken = metadata.get(Key.of("bisqd-creds", ASCII_STRING_MARSHALLER));
        if (authToken == null) {
            throw new StatusRuntimeException(UNAUTHENTICATED.withDescription("Authentication token is missing"));
        } else {
            try {
                if (isValidToken(authToken)) {
                    log.info("Authenticated user {} with token {}", rpcUser, authToken);
                } else {
                    throw new StatusRuntimeException(UNAUTHENTICATED.withDescription("Invalid username or password"));
                }
            } catch (Exception e) {
                throw new StatusRuntimeException(UNAUTHENTICATED.withDescription(e.getMessage()).withCause(e));
            }
        }
    }

    private boolean isValidToken(String token) {
        String[] pair = token.split(":");
        return pair[0].equals(rpcUser) && pair[1].equals(rpcPassword);
    }
}

@@ -1037,24 +1037,76 @@
 ate(metadata
+.get(Key.of(%22bisqd-creds%22, ASCII_STRING_MARSHALLER))
 );%0A        r
@@ -1203,117 +1203,27 @@
 ate(
-Metadata metadata) %7B%0A        String authToken = metadata.get(Key.of(%22bisqd-creds%22, ASCII_STRING_MARSHALLER));
+String authToken) %7B
 %0A   
@@ -1249,18 +1249,16 @@
 == null)
- %7B
 %0A       
@@ -1368,51 +1368,9 @@
 ));%0A
-        %7D else %7B%0A            try %7B%0A        
+%0A
     
@@ -1377,16 +1377,17 @@
     if (
+!
 isValidT
@@ -1406,433 +1406,197 @@
 en))
- %7B%0A                    log.info(%22Authenticated user %7B%7D with token %7B%7D%22, rpcUser, authToken);%0A                %7D else %7B%0A                    throw new StatusRuntimeException(UNAUTHENTICATED.withDescription(%22Invalid username or password%22));%0A                %7D%0A            %7D catch (Exception e) %7B%0A                throw new StatusRuntimeException(UNAUTHENTICATED.withDescription(e.getMessage()).withCause(e));%0A            %7D%0A        %7D
+%0A            throw new StatusRuntimeException(UNAUTHENTICATED.withDescription(%22Invalid username or password%22));%0A%0A        log.info(%22Authenticated user %7B%7D with token %7B%7D%22, rpcUser, authToken);
 %0A   

Simplify implementation of authenticate method