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
13 changes: 8 additions & 5 deletions src/infrastructure/service-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ export class ServiceError {
return new ServiceError(ServiceErrorCode.NotFound, customMessage, {});
}
static unauthorizedWithHint(apiMessage: string | null): ServiceError {
const message = `${apiMessage ?? "You are not authorized to perform this action."} Please run ${f.cmdAlt(
"apimatic",
"auth",
"login"
)} to log in, or provide a valid auth key using the ${f.flag("auth-key")} flag.`;
// Both remedies name the full `auth login` command: the key is supplied to
// that command, not to whichever one hit the 401 — most of them don't accept
// an --auth-key flag at all.
const loginCommand = f.cmdAlt("apimatic", "auth", "login");
const message =
`${apiMessage ?? "Authorization has been denied for this request."} ` +
`Please run ${loginCommand} to log in via browser, ` +
`or provide a valid auth key using the ${loginCommand} ${f.flag("auth-key")}`;
return new ServiceError(ServiceErrorCode.UnAuthorized, message, {});
}

Expand Down
11 changes: 9 additions & 2 deletions src/prompts/auth/login.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { log } from "@clack/prompts";
import { ServiceError } from "../../infrastructure/service-error.js";
import { ServiceError, ServiceErrorCode } from "../../infrastructure/service-error.js";
import { SubscriptionInfo } from "../../types/api/account.js";
import { Result } from "neverthrow";
import { withSpinner } from "../prompt.js";
Expand All @@ -14,8 +14,15 @@ export class LoginPrompts {
}

public invalidKeyProvided(serviceError: ServiceError) {
// A rejected key is the failure this reports, so key off the 401 rather than
// the network error it was previously matching. Compared by code, not by
// reference: `unauthorizedWithHint` and friends build fresh instances, so an
// identity check silently stops matching. Anything else (unreachable server,
// server error) already describes itself accurately.
const message =
serviceError === ServiceError.NetworkError ? "Invalid API key provided." : serviceError.errorMessage;
serviceError.code === ServiceErrorCode.UnAuthorized
? ServiceError.unauthorizedWithHint("Invalid API key provided.").errorMessage
: serviceError.errorMessage;
log.error(message);
}

Expand Down
4 changes: 3 additions & 1 deletion src/prompts/auth/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export class StatusPrompts {
}

public notLoggedIn() {
log.error(`You are not logged in. Please run ${format.cmdAlt("apimatic", "auth", "login")} to log in.`);
// Same message as every 401 the services surface: the user isn't authorized
// to perform the action, whether that's caught locally or by the API.
log.error(ServiceError.unauthorizedWithHint(null).errorMessage);
}

public invalidKeyProvided(serviceError: ServiceError) {
Expand Down
Loading