Skip to content

Commit 3c3480d

Browse files
committed
wip useAuthenticatedUser
1 parent cf91a83 commit 3c3480d

File tree

6 files changed

+220
-3
lines changed

6 files changed

+220
-3
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { useQuery } from "@tanstack/react-query";
8+
import { userClient } from "../../service/public-api";
9+
import { GetAuthenticatedUserRequest, User } from "@gitpod/public-api/lib/gitpod/v1/user_pb";
10+
11+
export const useAuthenticatedUser = () => {
12+
const query = useQuery<User>({
13+
queryKey: getAuthenticatedUserQueryKey(),
14+
queryFn: async () => {
15+
const params = new GetAuthenticatedUserRequest();
16+
const response = await userClient.getAuthenticatedUser(params);
17+
return response.user!;
18+
},
19+
});
20+
return query;
21+
};
22+
23+
export const getAuthenticatedUserQueryKey = () => ["authenticated-user", {}];

components/dashboard/src/data/setup.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@ import * as EnvVarClasses from "@gitpod/public-api/lib/gitpod/v1/envvar_pb";
2626
import * as PrebuildClasses from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb";
2727
import * as SCMClasses from "@gitpod/public-api/lib/gitpod/v1/scm_pb";
2828
import * as SSHClasses from "@gitpod/public-api/lib/gitpod/v1/ssh_pb";
29+
import * as UserClasses from "@gitpod/public-api/lib/gitpod/v1/user_pb";
2930

3031
// This is used to version the cache
3132
// If data we cache changes in a non-backwards compatible way, increment this version
3233
// That will bust any previous cache versions a client may have stored
33-
const CACHE_VERSION = "8";
34+
const CACHE_VERSION = "9";
3435

3536
export function noPersistence(queryKey: QueryKey): QueryKey {
3637
return [...queryKey, "no-persistence"];
@@ -154,6 +155,7 @@ function initializeMessages() {
154155
...Object.values(PrebuildClasses),
155156
...Object.values(SCMClasses),
156157
...Object.values(SSHClasses),
158+
...Object.values(UserClasses),
157159
];
158160
for (const c of constr) {
159161
if ((c as any).prototype instanceof Message) {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { UserService } from "@gitpod/public-api/lib/gitpod/v1/user_connect";
8+
9+
import { PromiseClient } from "@connectrpc/connect";
10+
import { PartialMessage } from "@bufbuild/protobuf";
11+
import { GetAuthenticatedUserRequest, GetAuthenticatedUserResponse } from "@gitpod/public-api/lib/gitpod/v1/user_pb";
12+
import { getGitpodService } from "./service";
13+
import { converter } from "./public-api";
14+
15+
export class JsonRpcUserClient implements PromiseClient<typeof UserService> {
16+
async getAuthenticatedUser(
17+
request: PartialMessage<GetAuthenticatedUserRequest>,
18+
): Promise<GetAuthenticatedUserResponse> {
19+
const user = await getGitpodService().server.getLoggedInUser();
20+
return new GetAuthenticatedUserResponse({
21+
user: converter.toUser(user),
22+
});
23+
}
24+
}

components/dashboard/src/service/public-api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ import { ApplicationError, ErrorCodes } from "@gitpod/gitpod-protocol/lib/messag
3535
import { JsonRpcScmClient } from "./json-rpc-scm-client";
3636
import { SCMService } from "@gitpod/public-api/lib/gitpod/v1/scm_connect";
3737
import { SSHService } from "@gitpod/public-api/lib/gitpod/v1/ssh_connect";
38+
import { UserService } from "@gitpod/public-api/lib/gitpod/v1/user_connect";
3839
import { JsonRpcSSHClient } from "./json-rpc-ssh-client";
40+
import { JsonRpcUserClient } from "./json-rpc-user-client";
3941

4042
const transport = createConnectTransport({
4143
baseUrl: `${window.location.protocol}//${window.location.host}/public-api`,
@@ -67,6 +69,8 @@ export const authProviderClient = createServiceClient(AuthProviderService, new J
6769

6870
export const scmClient = createServiceClient(SCMService, new JsonRpcScmClient());
6971

72+
export const userClient = createServiceClient(UserService, new JsonRpcUserClient());
73+
7074
export const envVarClient = createServiceClient(EnvironmentVariableService, new JsonRpcEnvvarClient());
7175

7276
export const sshClient = createServiceClient(SSHService, new JsonRpcSSHClient());

components/gitpod-protocol/src/protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ export interface AdditionalUserData extends Partial<WorkspaceTimeoutSetting> {
278278
workspaceAutostartOptions?: WorkspaceAutostartOption[];
279279
}
280280

281-
interface WorkspaceAutostartOption {
281+
export interface WorkspaceAutostartOption {
282282
cloneURL: string;
283283
organizationId: string;
284284
workspaceClass?: string;

components/gitpod-protocol/src/public-api-converter.ts

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* See License.AGPL.txt in the project root for license information.
55
*/
66

7-
import { Timestamp, toPlainMessage } from "@bufbuild/protobuf";
7+
import { Timestamp, toPlainMessage, Duration } from "@bufbuild/protobuf";
88
import { Code, ConnectError } from "@connectrpc/connect";
99
import {
1010
FailedPreconditionDetails,
@@ -25,6 +25,15 @@ import {
2525
AuthProviderType,
2626
OAuth2Config,
2727
} from "@gitpod/public-api/lib/gitpod/v1/authprovider_pb";
28+
import {
29+
Identity,
30+
User,
31+
User_EmailNotificationSettings,
32+
User_RoleOrPermission,
33+
User_UserFeatureFlag,
34+
User_WorkspaceAutostartOption,
35+
User_WorkspaceTimeoutSettings,
36+
} from "@gitpod/public-api/lib/gitpod/v1/user_pb";
2837
import {
2938
BranchMatchingStrategy,
3039
Configuration,
@@ -73,6 +82,8 @@ import {
7382
UnauthorizedRepositoryAccessError,
7483
} from "./messaging/error";
7584
import {
85+
User as UserProtocol,
86+
Identity as IdentityProtocol,
7687
AuthProviderEntry as AuthProviderProtocol,
7788
AuthProviderInfo,
7889
CommitContext,
@@ -89,6 +100,9 @@ import {
89100
Token,
90101
SuggestedRepository as SuggestedRepositoryProtocol,
91102
UserSSHPublicKeyValue,
103+
NamedWorkspaceFeatureFlag,
104+
WorkspaceAutostartOption,
105+
IDESettings,
92106
} from "./protocol";
93107
import {
94108
OrgMemberInfo,
@@ -109,6 +123,8 @@ import {
109123
} from "./workspace-instance";
110124
import { Author, Commit } from "@gitpod/public-api/lib/gitpod/v1/scm_pb";
111125
import type { DeepPartial } from "./util/deep-partial";
126+
import { RoleOrPermission } from "./permission";
127+
import { parseGoDurationToMs } from "./util/timeutil";
112128

113129
export type PartialConfiguration = DeepPartial<Configuration> & Pick<Configuration, "id">;
114130

@@ -910,4 +926,152 @@ export class PublicAPIConverter {
910926
result.lastUsedTime = Timestamp.fromDate(new Date(sshKey.lastUsedTime || sshKey.creationTime));
911927
return result;
912928
}
929+
930+
toUser(from: UserProtocol): User {
931+
const {
932+
id,
933+
name,
934+
creationDate,
935+
identities,
936+
additionalData,
937+
avatarUrl,
938+
featureFlags,
939+
organizationId,
940+
rolesOrPermissions,
941+
usageAttributionId,
942+
blocked,
943+
lastVerificationTime,
944+
verificationPhoneNumber,
945+
} = from;
946+
const {
947+
disabledClosedTimeout,
948+
dotfileRepo,
949+
emailNotificationSettings,
950+
ideSettings,
951+
profile,
952+
workspaceAutostartOptions,
953+
workspaceClasses,
954+
workspaceTimeout,
955+
} = additionalData || {};
956+
957+
return new User({
958+
id,
959+
name,
960+
createdAt: this.toTimestamp(creationDate),
961+
avatarUrl,
962+
organizationId,
963+
usageAttributionId,
964+
blocked,
965+
identities: identities?.map((i) => this.toIdentity(i)),
966+
rolesOrPermissions: rolesOrPermissions?.map((rp) => this.toRoleOrPermission(rp)),
967+
workspaceFeatureFlags: featureFlags?.permanentWSFeatureFlags?.map((ff) => this.toUserFeatureFlags(ff)),
968+
timeoutSettings: new User_WorkspaceTimeoutSettings({
969+
disabledDisconnected: disabledClosedTimeout,
970+
inactivity: this.toDuration(workspaceTimeout),
971+
// disconnected: this.toDuration(workspaceTimeout), // FIXME(at) how to map this properly?
972+
}),
973+
dotfileRepo,
974+
emailNotificationSettings: new User_EmailNotificationSettings({
975+
allowsChangelogMail: emailNotificationSettings?.allowsChangelogMail,
976+
allowsDevxMail: emailNotificationSettings?.allowsDevXMail,
977+
allowsOnboardingMail: emailNotificationSettings?.allowsOnboardingMail,
978+
}),
979+
editorSettings: this.toEditorReference(ideSettings),
980+
lastVerificationTime: this.toTimestamp(lastVerificationTime),
981+
verificationPhoneNumber,
982+
workspaceClass: workspaceClasses?.regular,
983+
workspaceAutostartOptions: workspaceAutostartOptions?.map((o) => this.toWorkspaceAutostartOption(o)),
984+
profile,
985+
});
986+
}
987+
988+
toDuration(from?: string): Duration | undefined {
989+
if (!from) {
990+
return undefined;
991+
}
992+
const millis = parseGoDurationToMs(from);
993+
const seconds = BigInt(Math.floor(millis / 1000));
994+
const nanos = (millis % 1000) * 1000000;
995+
return new Duration({
996+
seconds,
997+
nanos,
998+
});
999+
}
1000+
1001+
toTimestamp(from?: string | undefined): Timestamp | undefined {
1002+
return from ? Timestamp.fromDate(new Date(from)) : undefined;
1003+
}
1004+
1005+
toIdentity(from: IdentityProtocol): Identity {
1006+
const { authId, authName, authProviderId, lastSigninTime, primaryEmail } = from;
1007+
return new Identity({
1008+
authProviderId,
1009+
authId,
1010+
authName,
1011+
lastSigninTime: this.toTimestamp(lastSigninTime),
1012+
primaryEmail,
1013+
});
1014+
}
1015+
1016+
toRoleOrPermission(from: RoleOrPermission): User_RoleOrPermission {
1017+
switch (from) {
1018+
case "admin":
1019+
return User_RoleOrPermission.ADMIN;
1020+
case "devops":
1021+
return User_RoleOrPermission.DEVOPS;
1022+
case "viewer":
1023+
return User_RoleOrPermission.VIEWER;
1024+
case "developer":
1025+
return User_RoleOrPermission.DEVELOPER;
1026+
case "registry-access":
1027+
return User_RoleOrPermission.REGISTRY_ACCESS;
1028+
case "admin-permissions":
1029+
return User_RoleOrPermission.ADMIN_PERMISSIONS;
1030+
case "admin-users":
1031+
return User_RoleOrPermission.ADMIN_USERS;
1032+
case "admin-workspace-content":
1033+
return User_RoleOrPermission.ADMIN_WORKSPACE_CONTENT;
1034+
case "admin-workspaces":
1035+
return User_RoleOrPermission.ADMIN_WORKSPACES;
1036+
case "admin-projects":
1037+
return User_RoleOrPermission.ADMIN_PROJECTS;
1038+
case "new-workspace-cluster":
1039+
return User_RoleOrPermission.NEW_WORKSPACE_CLUSTER;
1040+
}
1041+
return User_RoleOrPermission.UNSPECIFIED;
1042+
}
1043+
1044+
toUserFeatureFlags(from: NamedWorkspaceFeatureFlag): User_UserFeatureFlag {
1045+
switch (from) {
1046+
case "full_workspace_backup":
1047+
return User_UserFeatureFlag.FULL_WORKSPACE_BACKUP;
1048+
case "workspace_class_limiting":
1049+
return User_UserFeatureFlag.WORKSPACE_CLASS_LIMITING;
1050+
case "workspace_connection_limiting":
1051+
return User_UserFeatureFlag.WORKSPACE_CONNECTION_LIMITING;
1052+
case "workspace_psi":
1053+
return User_UserFeatureFlag.WORKSPACE_PSI;
1054+
}
1055+
return User_UserFeatureFlag.UNSPECIFIED;
1056+
}
1057+
1058+
toEditorReference(from?: IDESettings): EditorReference | undefined {
1059+
if (!from) {
1060+
return undefined;
1061+
}
1062+
return new EditorReference({
1063+
name: from.defaultIde,
1064+
version: from.useLatestVersion ? "latest" : "stable",
1065+
});
1066+
}
1067+
1068+
toWorkspaceAutostartOption(from: WorkspaceAutostartOption): User_WorkspaceAutostartOption {
1069+
return new User_WorkspaceAutostartOption({
1070+
cloneUrl: from.cloneURL,
1071+
editorSettings: this.toEditorReference(from.ideSettings),
1072+
organizationId: from.organizationId,
1073+
region: from.region,
1074+
workspaceClass: from.workspaceClass,
1075+
});
1076+
}
9131077
}

0 commit comments

Comments
 (0)