Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,35 @@ final class WatchAuthFailureMessage {
private static final String TOKEN_ENDPOINT_MISMATCH = "CONNECT_AUTH_TOKEN_ENDPOINT_MISMATCH:";
private static final String ENDPOINT_ORG_OWNED = "CONNECT_AUTH_ENDPOINT_ORG_OWNED:";

/**
* Both auth codes mean the same user-facing condition: the presented token does not match the token
* stored for this endpoint name. The Watch service reports {@code CONNECT_AUTH_ENDPOINT_ORG_OWNED} for
* ANY non-matching token when the endpoint name has an organization parent, so the wording must never
* send the user to fix their organization selection instead of their token.
*/
private static final String TOKEN_MISMATCH_GUIDANCE =
"WatchService rejected the endpoint token for this endpoint name: "
+ "it does not match the token currently stored for this endpoint. "
+ "If you reset the token in the Minekube dashboard, the previous token is invalidated; "
+ "put the new token byte-for-byte into the connector token file "
+ "(token.json in the connector data directory, or the CONNECT_TOKEN environment variable) "
+ "rather than into config.yml, which only holds the endpoint name, then restart the connector. "
+ "If you do not own this endpoint name, choose a different endpoint name.";

private static final String ORG_OWNED_CLAUSE =
" This endpoint name belongs to an organization, so only a token created for it inside that "
+ "organization is accepted; a different token cannot take the name over.";

private WatchAuthFailureMessage() {
}

static String format(String responseBody) {
String message = responseBody == null ? "" : responseBody.trim();
if (message.startsWith(TOKEN_ENDPOINT_MISMATCH)) {
return "WatchService rejected the endpoint token for this endpoint name. "
+ "Regenerate the token for this exact endpoint and organization in the Minekube dashboard, "
+ "replace the token in token.json or CONNECT_TOKEN, then restart the server. "
+ "If you do not own this endpoint name, choose a different endpoint name.";
return TOKEN_MISMATCH_GUIDANCE;
}
if (message.startsWith(ENDPOINT_ORG_OWNED)) {
return "WatchService rejected this endpoint because the endpoint name belongs to an organization. "
+ "Switch to the owning Minekube organization/team, regenerate or import the endpoint token there, "
+ "then restart the server.";
return TOKEN_MISMATCH_GUIDANCE + ORG_OWNED_CLAUSE;
}
return message;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,67 @@
package com.minekube.connect.watch;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class WatchAuthFailureMessageTest {
private static final String TOKEN_MISMATCH_GUIDANCE =
"WatchService rejected the endpoint token for this endpoint name: "
+ "it does not match the token currently stored for this endpoint. "
+ "If you reset the token in the Minekube dashboard, the previous token is invalidated; "
+ "put the new token byte-for-byte into the connector token file "
+ "(token.json in the connector data directory, or the CONNECT_TOKEN environment variable) "
+ "rather than into config.yml, which only holds the endpoint name, then restart the connector. "
+ "If you do not own this endpoint name, choose a different endpoint name.";

@Test
void explainsEndpointTokenMismatch() {
String message = WatchAuthFailureMessage.format(
"CONNECT_AUTH_TOKEN_ENDPOINT_MISMATCH: endpoint token does not match the existing endpoint name");

assertEquals(
"WatchService rejected the endpoint token for this endpoint name. "
+ "Regenerate the token for this exact endpoint and organization in the Minekube dashboard, "
+ "replace the token in token.json or CONNECT_TOKEN, then restart the server. "
+ "If you do not own this endpoint name, choose a different endpoint name.",
message);
assertEquals(TOKEN_MISMATCH_GUIDANCE, message);
}

@Test
void explainsOrganizationOwnedEndpoint() {
void explainsOrganizationOwnedEndpointAsTokenMismatch() {
String message = WatchAuthFailureMessage.format(
"CONNECT_AUTH_ENDPOINT_ORG_OWNED: endpoint name belongs to an organization");

// The org-owned code is returned for ANY non-matching token on an org-owned name, so the primary
// condition reported to the user must be the token mismatch, with the ownership as the secondary clause.
assertEquals(
"WatchService rejected this endpoint because the endpoint name belongs to an organization. "
+ "Switch to the owning Minekube organization/team, regenerate or import the endpoint token there, "
+ "then restart the server.",
TOKEN_MISMATCH_GUIDANCE
+ " This endpoint name belongs to an organization, so only a token created for it "
+ "inside that organization is accepted; a different token cannot take the name over.",
message);
}

@Test
void organizationOwnedMessageDoesNotSendUsersToOrgSwitching() {
String message = WatchAuthFailureMessage.format(
"CONNECT_AUTH_ENDPOINT_ORG_OWNED: endpoint name belongs to an organization");

assertTrue(message.startsWith("WatchService rejected the endpoint token for this endpoint name:"));
assertFalse(message.contains("Switch to the owning"));
assertFalse(message.contains("organization/team"));
}

@Test
void bothAuthMessagesDescribeTheTokenFileAndTheConfigSplit() {
for (String responseBody : new String[] {
"CONNECT_AUTH_TOKEN_ENDPOINT_MISMATCH: endpoint token does not match the existing endpoint name",
"CONNECT_AUTH_ENDPOINT_ORG_OWNED: endpoint name belongs to an organization"}) {
String message = WatchAuthFailureMessage.format(responseBody);

assertTrue(message.contains("token.json"), responseBody);
assertTrue(message.contains("CONNECT_TOKEN"), responseBody);
assertTrue(message.contains("rather than into config.yml"), responseBody);
assertTrue(message.contains("restart the connector"), responseBody);
}
}

@Test
void preservesUnknownServerMessages() {
assertEquals("Internal Server Error", WatchAuthFailureMessage.format("Internal Server Error"));
Expand Down
Loading