fix: Details returned from OAuth client list endpoint (#10896)

This commit is contained in:
Tom Moor
2025-12-13 12:41:43 -05:00
committed by GitHub
parent 615cad5484
commit 5c37f0a91d
4 changed files with 41 additions and 8 deletions

View File

@@ -3,7 +3,7 @@ import { allow } from "./cancan";
import { or, isTeamModel, isTeamMutable, and, isTeamAdmin } from "./utils";
allow(User, "createOAuthClient", Team, (actor, team) =>
and(isTeamModel(actor, team), isTeamMutable(actor), actor.isAdmin)
and(isTeamAdmin(actor, team), isTeamMutable(actor))
);
allow(User, "listOAuthClients", Team, (actor, team) =>
@@ -15,5 +15,5 @@ allow(User, "read", OAuthClient, (actor, oauthClient) =>
);
allow(User, ["update", "delete"], OAuthClient, (actor, oauthClient) =>
and(isTeamModel(actor, oauthClient), isTeamMutable(actor), actor.isAdmin)
and(isTeamAdmin(actor, oauthClient), isTeamMutable(actor))
);

View File

@@ -1,7 +1,8 @@
import { OAuthClient } from "@server/models";
/**
* Presents the OAuth client to the user.
* Presents the OAuth client to the user, including the client secret.
* This should ONLY be used for admin users who need to manage the OAuth client.
*
* @param oauthClient The OAuth client to present
*/

View File

@@ -67,9 +67,9 @@ describe("oauthClients.info", () => {
expect(body).toMatchSnapshot();
});
it("should return information about an OAuth client when authorized", async () => {
it("should return confidential information about an OAuth client when admin", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const user = await buildAdmin({ teamId: team.id });
const client = await OAuthClient.create({
teamId: team.id,
@@ -90,9 +90,35 @@ describe("oauthClients.info", () => {
expect(body.data.id).toBeDefined();
expect(body.data.name).toEqual("Test Client");
expect(body.data.published).toBeFalsy();
expect(body.data.clientSecret).toBeDefined();
expect(body.data.redirectUris).toEqual(["https://example.com/callback"]);
});
it("should return basic information about an OAuth client when member", async () => {
const team = await buildTeam();
const user = await buildUser({ teamId: team.id });
const client = await OAuthClient.create({
teamId: team.id,
createdById: user.id,
name: "Test Client",
redirectUris: ["https://example.com/callback"],
});
const res = await server.post("/api/oauthClients.info", {
body: {
token: user.getJwtToken(),
id: client.id,
},
});
const body = await res.json();
expect(res.status).toEqual(200);
expect(body.data.id).toBeUndefined();
expect(body.data.name).toEqual("Test Client");
expect(body.data.clientSecret).toBeUndefined();
});
it("should return information about an OAuth client when published", async () => {
const team = await buildTeam();
const admin = await buildAdmin({ teamId: team.id });

View File

@@ -6,7 +6,7 @@ import { rateLimiter } from "@server/middlewares/rateLimiter";
import { transaction } from "@server/middlewares/transaction";
import validate from "@server/middlewares/validate";
import { OAuthClient } from "@server/models";
import { authorize } from "@server/policies";
import { authorize, can } from "@server/policies";
import {
presentPolicies,
presentOAuthClient,
@@ -27,6 +27,7 @@ router.post(
async (ctx: APIContext<T.OAuthClientsListReq>) => {
const { user } = ctx.state.auth;
const where = { teamId: user.teamId };
authorize(user, "listOAuthClients", user.team);
const [oauthClients, total] = await Promise.all([
OAuthClient.findAll({
@@ -40,7 +41,11 @@ router.post(
ctx.body = {
pagination: { ...ctx.state.pagination, total },
data: oauthClients.map(presentOAuthClient),
data: oauthClients.map((oauthClient) =>
can(user, "update", oauthClient)
? presentOAuthClient(oauthClient)
: presentPublishedOAuthClient(oauthClient)
),
policies: presentPolicies(user, oauthClients),
};
}
@@ -64,9 +69,10 @@ router.post(
}
const isInternalApp = oauthClient.teamId === user.teamId;
const canUpdate = can(user, "update", oauthClient);
ctx.body = {
data: isInternalApp
data: canUpdate
? presentOAuthClient(oauthClient)
: presentPublishedOAuthClient(oauthClient),
policies: isInternalApp ? presentPolicies(user, [oauthClient]) : [],