Skip to content
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

Public API/SDK update for /me route to handle extension blacklisted domains. #9688

Merged
merged 4 commits into from
Jan 2, 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
5 changes: 4 additions & 1 deletion extension/app/src/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ const fetchMe = async (
token: string
): Promise<Result<{ user: UserTypeWithWorkspaces }, AuthError>> => {
const response = await fetch(`${process.env.DUST_DOMAIN}/api/v1/me`, {
headers: { Authorization: `Bearer ${token}` },
headers: {
Authorization: `Bearer ${token}`,
"X-Request-Origin": "extension",
},
});
const me = await response.json();
if (!response.ok) {
Expand Down
6 changes: 5 additions & 1 deletion front/lib/api/auth_wrappers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,11 @@ export function withAuth0TokenAuthentication<T>(
});
}

const userWithWorkspaces = await getUserWithWorkspaces(user);
const isFromExtension = req.headers["x-request-origin"] === "extension";
const userWithWorkspaces = await getUserWithWorkspaces(
user,
isFromExtension
);

return handler(req, res, userWithWorkspaces);
}
Expand Down
41 changes: 22 additions & 19 deletions front/lib/api/user.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type {
Result,
RoleType,
UserMetadataType,
UserType,
UserTypeWithExtensionWorkspaces,
UserTypeWithWorkspaces,
} from "@dust-tt/types";
import { Err, Ok } from "@dust-tt/types";

import type { Authenticator } from "@app/lib/auth";
import { Workspace } from "@app/lib/models/workspace";
import { ExtensionConfigurationResource } from "@app/lib/resources/extension";
import { UserMetadataModel } from "@app/lib/resources/storage/models/user";
import { UserResource } from "@app/lib/resources/user_resource";
import logger from "@app/logger/logger";
Expand Down Expand Up @@ -139,42 +140,44 @@ export async function fetchRevokedWorkspace(
return new Ok(workspace);
}

export async function getUserWithWorkspaces(
user: UserResource
): Promise<UserTypeWithWorkspaces> {
export async function getUserWithWorkspaces<T extends boolean>(
user: UserResource,
populateExtensionConfig: T = false as T
): Promise<
PopDaph marked this conversation as resolved.
Show resolved Hide resolved
T extends true ? UserTypeWithExtensionWorkspaces : UserTypeWithWorkspaces
> {
const { memberships } = await MembershipResource.getActiveMemberships({
users: [user],
});
const workspaceIds = memberships.map((m) => m.workspaceId);
const workspaces = await Workspace.findAll({
where: {
id: memberships.map((m) => m.workspaceId),
id: workspaceIds,
},
});

const configs = populateExtensionConfig
? await ExtensionConfigurationResource.internalFetchForWorkspaces(
workspaceIds
)
: [];
PopDaph marked this conversation as resolved.
Show resolved Hide resolved

return {
...user.toJSON(),
workspaces: workspaces.map((w) => {
const m = memberships.find((m) => m.workspaceId === w.id);
let role = "none" as RoleType;
if (m) {
switch (m.role) {
case "admin":
case "builder":
case "user":
role = m.role;
break;
default:
role = "none";
}
}
return {
id: w.id,
sId: w.sId,
name: w.name,
role,
role: memberships.find((m) => m.workspaceId === w.id)?.role ?? "none",
segmentation: w.segmentation || null,
whiteListedProviders: w.whiteListedProviders,
defaultEmbeddingProvider: w.defaultEmbeddingProvider,
...(populateExtensionConfig && {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a toJSON (to align with other resources) on the ExtensionConfigurationResource and return it instead of accessing property manually?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a toJson() but here I'd rather get the resources since I need to access workspaceId that I don't necessarily want to expose in the type. Also, here I only want to display the blacklistedDomains attribute, I don't want the full type. I can't just spread the type because it also has an id and sId and we don't want to conflict with the workspace.

I could put all that in a sub object with a config key but since the relation is 0-1 I like it flat with the workspace!

blacklistedDomains:
configs.find((c) => c.workspaceId === w.id)?.blacklistedDomains ??
null,
}),
};
}),
};
Expand Down
14 changes: 14 additions & 0 deletions front/lib/resources/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@ export class ExtensionConfigurationResource extends BaseResource<ExtensionConfig
return config ? new this(ExtensionConfigurationModel, config.get()) : null;
}

static async internalFetchForWorkspaces(
workspaceIds: ModelId[]
): Promise<ExtensionConfigurationResource[]> {
const configs = await this.model.findAll({
where: {
workspaceId: workspaceIds,
},
});

return configs.map(
(config) => new this(ExtensionConfigurationModel, config.get())
);
}

async updateBlacklistedDomains(
auth: Authenticator,
{
Expand Down
4 changes: 2 additions & 2 deletions sdks/js/package-lock.json

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

2 changes: 1 addition & 1 deletion sdks/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dust-tt/client",
"version": "1.0.16",
"version": "1.0.17",
"description": "Client for Dust API",
"repository": {
"type": "git",
Expand Down
10 changes: 9 additions & 1 deletion sdks/js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,10 @@ const WorkspaceSchema = LightWorkspaceSchema.extend({
ssoEnforced: z.boolean().optional(),
});

const ExtensionWorkspaceSchema = WorkspaceSchema.extend({
blacklistedDomains: z.array(z.string()).nullable(),
});

const UserProviderSchema = FlexibleEnumSchema<
"auth0" | "github" | "google" | "okta" | "samlp" | "waad"
>().nullable();
Expand Down Expand Up @@ -2199,7 +2203,11 @@ export type FileUploadedRequestResponseType = z.infer<
>;

export const MeResponseSchema = z.object({
user: UserSchema.and(z.object({ workspaces: LightWorkspaceSchema.array() })),
user: UserSchema.and(
z.object({
workspaces: WorkspaceSchema.array().or(ExtensionWorkspaceSchema.array()),
})
),
});

export type MeResponseType = z.infer<typeof MeResponseSchema>;
Expand Down
10 changes: 9 additions & 1 deletion types/src/front/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ export type WorkspaceType = LightWorkspaceType & {
ssoEnforced?: boolean;
};

export type ExtensionWorkspaceType = WorkspaceType & {
blacklistedDomains: string[] | null;
};

export type UserProviderType =
| "auth0"
| "github"
Expand All @@ -69,7 +73,11 @@ export type UserType = {
};

export type UserTypeWithWorkspaces = UserType & {
workspaces: LightWorkspaceType[];
workspaces: WorkspaceType[];
};

export type UserTypeWithExtensionWorkspaces = UserType & {
workspaces: ExtensionWorkspaceType[];
};

export type UserMetadataType = {
Expand Down
Loading