Skip to content

Commit

Permalink
Merge branch 'main' into update-deps
Browse files Browse the repository at this point in the history
  • Loading branch information
oscartbeaumont authored May 18, 2024
2 parents b8158df + f7b1cab commit 72df9b5
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 59 deletions.
5 changes: 2 additions & 3 deletions apps/web/src/api/rest/webhook/microsoft-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { and, eq } from "drizzle-orm";
import { Hono } from "hono";
import { z } from "zod";

import { isNotFoundGraphError } from "@mattrax/ms-graph";
import { msGraphClient } from "~/api/microsoft";
import { upsertEntraIdUser } from "~/api/trpc/routers/tenant/identityProvider";
import { getEmailDomain } from "~/api/utils";
Expand Down Expand Up @@ -152,8 +151,8 @@ async function handleUserChangeNotification(
identityProvider.tenantPk,
identityProvider.pk,
);
} catch (e) {
if (isNotFoundGraphError(e)) {
} catch (e: any) {
if ("code" in e && e.code === "Request_ResourceNotFound") {
await handleUserDeleted(userId, identityProvider.pk);
}
}
Expand Down
13 changes: 8 additions & 5 deletions apps/web/src/api/trpc/routers/tenant/identityProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { TRPCError } from "@trpc/server";
import { and, eq } from "drizzle-orm";
import { z } from "zod";

import { msGraphClient } from "~/api/microsoft";
import { getEmailDomain } from "~/api/utils";
import { domains, db, identityProviders, users } from "~/db";
import { createTRPCRouter, tenantProcedure } from "../../helpers";
Expand Down Expand Up @@ -45,6 +44,8 @@ export const identityProviderRouter = createTRPCRouter({

// We ignore any errors cleaning up the subscriptions cause it's a non vital error.
try {
const { msGraphClient } = await import("~/api/microsoft");

const subscriptions: { value: Array<MSGraph.Subscription> } =
await msGraphClient(provider.remoteId).api("/subscriptions").get();

Expand Down Expand Up @@ -84,7 +85,7 @@ export const identityProviderRouter = createTRPCRouter({
let identityProvider!: IdentityProvider;

if (provider.provider === "entraId")
identityProvider = createEntraIDUserProvider(provider.remoteId);
identityProvider = await createEntraIDUserProvider(provider.remoteId);

const [remoteDomains, connectedDomains] = await Promise.all([
identityProvider.getDomains(),
Expand All @@ -108,7 +109,7 @@ export const identityProviderRouter = createTRPCRouter({
let identityProvider!: IdentityProvider;

if (provider.provider === "entraId")
identityProvider = createEntraIDUserProvider(provider.remoteId);
identityProvider = await createEntraIDUserProvider(provider.remoteId);

const remoteDomains = await identityProvider.getDomains();
if (!remoteDomains.includes(input.domain))
Expand Down Expand Up @@ -224,9 +225,10 @@ async function ensureIdentityProvider(tenantPk: number) {
return provider;
}

export function createEntraIDUserProvider(
export async function createEntraIDUserProvider(
resourceId: string,
): IdentityProvider {
): Promise<IdentityProvider> {
const { msGraphClient } = await import("~/api/microsoft");
const client = msGraphClient(resourceId);

return {
Expand Down Expand Up @@ -282,6 +284,7 @@ export async function syncEntraUsersWithDomains(
entraTenantId: string,
domains: string[],
) {
const { msGraphClient } = await import("~/api/microsoft");
const graphClient = msGraphClient(entraTenantId);

let response: {
Expand Down
7 changes: 6 additions & 1 deletion apps/web/src/api/utils/jwt.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as jose from "jose";
import type * as jose from "jose";
import { env } from "~/env";

export async function signJWT<T extends jose.JWTPayload>(
Expand All @@ -9,6 +9,8 @@ export async function signJWT<T extends jose.JWTPayload>(
audience?: string;
},
) {
const jose = await import("jose");

const builder = new jose.SignJWT(payload)
.setAudience(opts?.audience ?? "mattrax.app")
.setNotBefore(new Date());
Expand All @@ -22,6 +24,7 @@ export async function signJWT<T extends jose.JWTPayload>(
}

export async function verifyJWT<T extends jose.JWTPayload>(jwt: string) {
const jose = await import("jose");
const result = await jose.jwtVerify<T>(jwt, createSecretKey());
return result.payload;
}
Expand All @@ -34,6 +37,7 @@ export async function encryptJWT<T extends jose.JWTPayload>(
audience?: string;
},
) {
const jose = await import("jose");
const builder = new jose.EncryptJWT(payload)
.setAudience(opts?.audience ?? "mattrax.app")
.setNotBefore(new Date());
Expand All @@ -56,6 +60,7 @@ export async function decryptJWT(
audience?: string;
},
) {
const jose = await import("jose");
return await jose.jwtDecrypt(jwt, createSecretKey(), {
keyManagementAlgorithms: ["PBES2-HS256+A128KW"],
});
Expand Down
12 changes: 7 additions & 5 deletions apps/web/src/app/(dash)/o.[orgSlug]/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { cache } from "@solidjs/router";
import { mattraxCache } from "~/cache";
import { getMattraxCache } from "~/cache";

export const cachedTenantsForOrg = cache(
(orgId: string) =>
mattraxCache.tenants
.orderBy("id")
.filter((o) => o.orgId === orgId)
.toArray(),
getMattraxCache().then((c) =>
c.tenants
.orderBy("id")
.filter((o) => o.orgId === orgId)
.toArray(),
),
"cachedTenantsForOrg",
);
4 changes: 2 additions & 2 deletions apps/web/src/app/(dash)/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { cache } from "@solidjs/router";
import { mattraxCache } from "~/cache";
import { getMattraxCache } from "~/cache";

// can't be in a route file that consumes it
export const cachedOrgs = cache(
() => mattraxCache.orgs.orderBy("id").toArray(),
() => getMattraxCache().then((c) => c.orgs.orderBy("id").toArray()),
"cachedOrgs",
);
34 changes: 34 additions & 0 deletions apps/web/src/cache/dexie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Dexie from "dexie";

export type TableNames = "orgs" | "tenants";

class MattraxCache
extends Dexie
implements Record<TableNames, Dexie.Table<any, string>>
{
orgs!: Dexie.Table<{ id: string; slug: string; name: string }, string>;
tenants!: Dexie.Table<
{ id: string; slug: string; name: string; orgId: string },
string
>;

VERSION = 1;

constructor() {
super("mattrax-cache");
this.version(this.VERSION).stores({
orgs: "id",
tenants: "id, orgId",
});
}
}

export type { MattraxCache };

export const mattraxCache = new MattraxCache();

export type TableData<TTable extends Dexie.Table> = TTable extends Dexie.Table<
infer T
>
? T
: never;
45 changes: 11 additions & 34 deletions apps/web/src/cache/index.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,16 @@
import { createAsync } from "@solidjs/router";
import type { CreateQueryResult } from "@tanstack/solid-query";
import Dexie from "dexie";
import { type Accessor, createEffect, untrack } from "solid-js";
import { MattraxCache, TableData, TableNames } from "./dexie";
export type { TableData, TableNames, MattraxCache } from "./dexie";

type TableNames = "orgs" | "tenants";

class MattraxCache
extends Dexie
implements Record<TableNames, Dexie.Table<any, string>>
{
orgs!: Dexie.Table<{ id: string; slug: string; name: string }, string>;
tenants!: Dexie.Table<
{ id: string; slug: string; name: string; orgId: string },
string
>;

VERSION = 1;

constructor() {
super("mattrax-cache");
this.version(this.VERSION).stores({
orgs: "id",
tenants: "id, orgId",
});
}
}

export type { MattraxCache };

export type TableData<TTable extends Dexie.Table> = TTable extends Dexie.Table<
infer T
>
? T
: never;

export const mattraxCache = new MattraxCache();
export const getMattraxCache = () =>
import("./dexie").then((m) => m.mattraxCache);

export async function resetMattraxCache() {
const mattraxCache = await getMattraxCache();
await mattraxCache.delete();

await mattraxCache.open();
}

Expand All @@ -46,9 +19,13 @@ export function createQueryCacher<TData, TTable extends TableNames>(
table: TTable,
transform: (data: TData) => TableData<MattraxCache[TTable]>,
) {
const mattraxCache = createAsync(() => getMattraxCache());

createEffect(() => {
if (!query.data) return;
mattraxCache[table].bulkPut(query.data.map(transform) as any);
const cache = mattraxCache();
if (!cache) return;
cache[table].bulkPut(query.data.map(transform) as any);
});
}

Expand Down
19 changes: 10 additions & 9 deletions packages/ms-graph/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Client, GraphError } from "@microsoft/microsoft-graph-client";
import { Client } from "@microsoft/microsoft-graph-client";
import { AuthProvider } from "./authProvider";

// Unused but makes TS happy.
Expand All @@ -8,14 +8,15 @@ export const initGraphClient = (
tenantId: string,
clientId: string,
clientSecret: string,
) =>
Client.initWithMiddleware({
) => {
return Client.initWithMiddleware({
authProvider: new AuthProvider(tenantId, clientId, clientSecret),
});
};

export function isGraphError(err: any): err is GraphError {
return err instanceof GraphError;
}
export function isNotFoundGraphError(err: any): err is GraphError {
return isGraphError(err) && err.code === "Request_ResourceNotFound";
}
// export function isGraphError(err: any): err is GraphError {
// return err instanceof GraphError;
// }
// export function isNotFoundGraphError(err: any): err is GraphError {
// return isGraphError(err) && err.code === "Request_ResourceNotFound";
// }

0 comments on commit 72df9b5

Please sign in to comment.