Skip to content

[server, dashboard] Map USER_DELETED properly through the API #20796

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 7, 2025
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,7 +4,7 @@
* See License.AGPL.txt in the project root for license information.
*/

import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
import { ApplicationError, ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
import { QueryErrorResetBoundary, useQueryClient } from "@tanstack/react-query";
import { FC } from "react";
import { ErrorBoundary, FallbackProps } from "react-error-boundary";
Expand Down Expand Up @@ -36,7 +36,7 @@ const ExpectedQueryErrorsFallback: FC<FallbackProps> = ({ error, resetErrorBound
const caughtError = error as CaughtError;

// user deleted needs a n explicit logout to destroy the session
if (caughtError.code === ErrorCodes.USER_DELETED) {
if (ApplicationError.isUserDeletedError(caughtError)) {
console.log("clearing query cache for deleted user");
client.clear();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Heading1, Subheading } from "../typography/headings";
import { reportError } from "../../service/metrics";
import { Button } from "@podkit/buttons/Button";

export type CaughtError = Error & { code?: number };
export type CaughtError = Error & { code?: number; data?: any };

// Catches any unexpected errors w/ a UI to reload the page. Also reports errors to api
export const ReloadPageErrorBoundary: FC = ({ children }) => {
Expand Down
7 changes: 4 additions & 3 deletions components/dashboard/src/hooks/use-user-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { UserContext } from "../user-context";
import { trackLocation } from "../Analytics";
import { useQuery } from "@tanstack/react-query";
import { noPersistence } from "../data/setup";
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
import { ErrorCodes, ApplicationError } from "@gitpod/gitpod-protocol/lib/messaging/error";
import { userClient } from "../service/public-api";

export const useUserLoader = () => {
Expand All @@ -28,10 +28,11 @@ export const useUserLoader = () => {
useErrorBoundary: true,
// It's important we don't retry as we want to show the login screen as quickly as possible if a 401
retry: (_failureCount: number, error: Error & { code?: number }) => {
const isUserDeletedError = ApplicationError.isUserDeletedError(error);
return (
error.code !== ErrorCodes.NOT_AUTHENTICATED &&
error.code !== ErrorCodes.USER_DELETED &&
error.code !== ErrorCodes.CELL_EXPIRED
error.code !== ErrorCodes.CELL_EXPIRED &&
!isUserDeletedError
);
},
// docs: https://tanstack.com/query/v4/docs/react/guides/query-retries
Expand Down
3 changes: 0 additions & 3 deletions components/gitpod-protocol/go/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ const (
// 470 User Blocked (custom status code)
USER_BLOCKED = 470

// 471 User Deleted (custom status code)
USER_DELETED = 471

// 472 Terms Acceptance Required (custom status code)
USER_TERMS_ACCEPTANCE_REQUIRED = 472

Expand Down
22 changes: 22 additions & 0 deletions components/gitpod-protocol/src/messaging/error.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Copyright (c) 2021 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License.AGPL.txt in the project root for license information.
*/

import { suite, test } from "@testdeck/mocha";
import { ApplicationError, ErrorCodes } from "./error";

import { expect } from "chai";

@suite
class TestApplicationError {
@test public async ApplicationError_isUserDeletedError() {
expect(
ApplicationError.isUserDeletedError(
new ApplicationError(ErrorCodes.NOT_FOUND, "not found", { userDeleted: true }),
),
).to.be.true;
}
}
module.exports = new TestApplicationError();
7 changes: 4 additions & 3 deletions components/gitpod-protocol/src/messaging/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export namespace ApplicationError {
throw e;
}
}

export function isUserDeletedError(e: any): boolean {
return hasErrorCode(e) && e.code === ErrorCodes.NOT_FOUND && e.data?.userDeleted === true;
}
}

export namespace ErrorCode {
Expand Down Expand Up @@ -98,9 +102,6 @@ export const ErrorCodes = {
// 470 User Blocked (custom status code)
USER_BLOCKED: 470 as const,

// 471 User Deleted (custom status code)
USER_DELETED: 471 as const,

// 472 Terms Acceptance Required (custom status code)
USER_TERMS_ACCEPTANCE_REQUIRED: 472 as const,

Expand Down
8 changes: 8 additions & 0 deletions components/public-api/gitpod/v1/error.proto
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ message ImageBuildLogsNotYetAvailableError {}

message CellDisabledError {}

message NotFoundDetails {
oneof reason {
UserDeletedError user_deleted = 1;
}
}

message UserDeletedError {}

/*
// details for INVALID_ARGUMENT status code
// TODO: this is not yet implemented in the backend
Expand Down
169 changes: 156 additions & 13 deletions components/public-api/go/v1/error.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading