Skip to content

Commit

Permalink
feat(users): add api endpoint to list users in a team (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
ps-kwang authored Apr 9, 2024
1 parent 64cc947 commit f6e1d90
Show file tree
Hide file tree
Showing 4 changed files with 294 additions and 0 deletions.
185 changes: 185 additions & 0 deletions api/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,25 @@ export interface paths {
*/
patch: operations["teamSecrets-update"];
};
"/teams/{teamId}/users": {
/**
* List team members
* @description List team members
*/
get: operations["teamMemberships-listByTeamId"];
};
"/teams/{teamId}/users/{userId}": {
/**
* Update a team membership
* @description Update a team membership
*/
put: operations["teamMemberships-update"];
/**
* Remove a user from a team
* @description Remove a user from a team
*/
delete: operations["teamMemberships-removeUser"];
};
"/templates": {
/**
* List templates
Expand Down Expand Up @@ -15042,6 +15061,172 @@ export interface operations {
default: components["responses"]["error"];
};
};
/**
* List team members
* @description List team members
*/
"teamMemberships-listByTeamId": {
parameters: {
readonly query: {
/** @description Fetch the next page of results after this cursor. */
after?: string;
/** @description The number of items to fetch after this page. */
limit?: number;
/** @description Order results by one of these fields. */
orderBy?: "dtConfirmed";
/** @description The order to sort the results by. */
order?: "asc" | "desc";
/** @description Filter team members by their role on the team. */
role?: "member" | "admin" | "owner";
};
readonly path: {
/** @description The team's ID */
teamId: string;
};
};
responses: {
/** @description Successful response */
200: {
content: {
readonly "application/json": {
/** @description Whether there are more pages of results available. */
readonly hasMore: boolean;
/** @description The items on this page. */
readonly items: readonly ({
/**
* Format: date-time
* @description The date the user confirmed their membership
* @default null
*/
readonly dtConfirmed?: Date;
/** @description Whether the user is an admin of the team */
readonly isAdmin: boolean;
/** @description Whether the user is the owner of the team */
readonly isOwner: boolean;
readonly user: {
/** @description The email address of the user */
readonly email: string;
/**
* @description The first name of the user
* @default null
*/
readonly firstName?: string | null;
/** @description The ID of the user */
readonly id: string;
/**
* Format: date-time
* @description The date the user was last active.
* @default null
*/
readonly lastActive?: Date;
/**
* @description The last name of the user
* @default null
*/
readonly lastName?: string | null;
/**
* @description The URL of the team's profile image.
* @default null
*/
readonly publicProfileImageUrl?: string | null;
};
})[];
/** @description The cursor required to fetch the next page of results. i.e. `?after=nextPage`. This is `null` when there is no next page. */
readonly nextPage?: string;
};
};
};
default: components["responses"]["error"];
};
};
/**
* Update a team membership
* @description Update a team membership
*/
"teamMemberships-update": {
parameters: {
readonly path: {
/** @description The team's ID */
teamId: string;
/** @description The user's ID */
userId: string;
};
};
readonly requestBody: {
readonly content: {
readonly "application/json": {
/** @description Whether the user will gain admin access or not */
readonly isAdmin: boolean;
};
};
};
responses: {
/** @description Successful response */
200: {
content: {
readonly "application/json": {
/**
* Format: date-time
* @description The date the user confirmed their membership
* @default null
*/
readonly dtConfirmed?: Date;
/**
* Format: date-time
* @description The date the user was removed from the team
* @default null
*/
readonly dtDeleted?: Date;
/** @description Whether the user is an admin of the team */
readonly isAdmin: boolean;
/** @description Whether the user is the owner of the team */
readonly isOwner: boolean;
};
};
};
default: components["responses"]["error"];
};
};
/**
* Remove a user from a team
* @description Remove a user from a team
*/
"teamMemberships-removeUser": {
parameters: {
readonly path: {
/** @description The team's ID */
teamId: string;
/** @description The user's ID */
userId: string;
};
};
responses: {
/** @description Successful response */
200: {
content: {
readonly "application/json": {
/**
* Format: date-time
* @description The date the user confirmed their membership
* @default null
*/
readonly dtConfirmed?: Date;
/**
* Format: date-time
* @description The date the user was removed from the team
* @default null
*/
readonly dtDeleted?: Date;
/** @description Whether the user is an admin of the team */
readonly isAdmin: boolean;
/** @description Whether the user is the owner of the team */
readonly isOwner: boolean;
};
};
};
default: components["responses"]["error"];
};
};
/**
* List templates
* @description Fetches a list of templates.
Expand Down
4 changes: 4 additions & 0 deletions api/teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ export const teamSecrets = {
update: client("/teams/{id}/secrets/{name}").patch,
delete: client("/teams/{id}/secrets/{name}").delete,
};

export const teamUsers = {
list: client("/teams/{teamId}/users").get,
};
78 changes: 78 additions & 0 deletions commands/user/list/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { command, flag, flags } from "../../../zcli.ts";
import { asserts } from "../../../lib/asserts.ts";
import { dataTable } from "../../../lib/data-table.ts";
import { loading } from "../../../lib/loading.ts";
import * as psFlags from "../../../flags.ts";
import { pickJson } from "../../../lib/pick-json.ts";
import { config } from "../../../config.ts";
import { teamUsers } from "../../../api/teams.ts";
import { defaultFields } from "../mod.ts";

/**
* This variable is automatically generated by `zcli add`. Do not remove this
* or change its name unless you're no longer using `zcli add`.
*/
const subCommands: ReturnType<typeof command>[] = [];

export const list = command("list", {
short: "List users.",
long: ({ root }) => `
List users in your team.
Pick a subset of fields to display:
\`\`\`
${root.name} user list -F email -F dtCreated
\`\`\`
`,
commands: subCommands,
flags: psFlags.paginator.merge(flags({
"team-id": flag({
aliases: ["t"],
short: "The ID of the team to list users in",
long: `
The ID of the team to list users in. If not specified, the current team
will be used.
`,
}).ostring(),
})),
// We use command metadata in the `persistentPreRun` function to check if a
// command requires an API key. If it does, we'll check to see if one is
// set. If not, we'll throw an error.
meta: {
requireApiKey: true,
},
}).run(
async function* ({ flags }) {
let teamId = flags["team-id"];
if (!teamId) {
const team = await config.get("team");
asserts(team, "You must be in a team to list users.");
teamId = team;
}

const result = await loading(
teamUsers.list({
limit: flags.limit,
after: flags.after,
order: flags.asc ? "asc" : undefined,
teamId,
}),
{ enabled: !flags.json },
);

asserts(result.ok, result);

if (!flags.json) {
for await (
const line of dataTable(
result.data.items,
flags.fields ?? defaultFields,
)
) {
yield line;
}
} else {
yield pickJson(result.data, flags.fields);
}
},
);
27 changes: 27 additions & 0 deletions commands/user/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { command } from "../../zcli.ts";
import { list } from "./list/mod.ts";

export const defaultFields = [
"id",
"teamId",
];

/**
* This variable is automatically generated by `zcli add`. Do not remove this
* or change its name unless you're no longer using `zcli add`.
*/
const subCommands: ReturnType<typeof command>[] = [
list,
];

export const user = command("user", {
short: "Information about users",
long: `
Show information about users.
`,
commands: subCommands,
}).run(function* ({ ctx }) {
for (const line of user.help(ctx)) {
yield line;
}
});

0 comments on commit f6e1d90

Please sign in to comment.