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

Add SynapseAdminApis.listAllUsers #183

Merged
merged 1 commit into from
May 2, 2022
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
57 changes: 57 additions & 0 deletions src/SynapseAdminApis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,34 @@ export enum SynapseRoomProperty {
NumStateEvents = "state_events",
}

export interface SynapseListUserOptions {
/**
* Filters to only return users with user IDs that contain this value. This parameter is ignored when using the name parameter.
*/
user_id?: string;
/**
* Filters to only return users with user ID localparts or displaynames that contain this value.
*/
name?: string;
/**
* If false will exclude guest users. Defaults to true to include guest users.
*/
guests?: boolean;
/**
* If true will include deactivated users. Defaults to false to exclude deactivated users.
*/
deactivated?: boolean;
/**
* The method by which to sort the returned list of users. If the ordered field has duplicates, the second order is always by ascending name, which guarantees a stable ordering.
* **Caution**: The database only has indexes on the columns `name` and `creation_ts`. This means that if a different sort order is used, it can cause a large load on the database.
*/
order_by?: "name"|"is_guest"|"admin"|"user_type"|"deactivated"|"shadow_banned"|"displayname"|"avatar_url"|"creation_ts";
/**
* The number of results to return at a time.
*/
limit?: number;
}

/**
* Access to various administrative APIs specifically available in Synapse.
* @category Admin APIs
Expand Down Expand Up @@ -216,6 +244,35 @@ export class SynapseAdminApis {
return this.client.doRequest("GET", "/_synapse/admin/v2/users", qs);
}

/**
* Get a list of all users registered with Synapse, optionally filtered by some criteria. The
* client making the request must be an admin user.
*
* This method returns an async generator that can be used to filter results.
* @param options Options to pass to the user listing function
* @example
* for await (const user of synapseAdminApis.listAllUsers()) {
* if (user.name === '@alice:example.com') {
* return user;
* }
* }
*/
public async *listAllUsers(options: SynapseListUserOptions = {}): AsyncGenerator<SynapseUserListing> {
let from: string|undefined = undefined;
let response: SynapseUserList;
do {
const qs = {
...options,
...(from && {from}),
};
response = await this.client.doRequest("GET", "/_synapse/admin/v2/users", qs);
for (const user of response.users) {
yield user;
}
from = response.next_token;
} while (from)
}

/**
* Determines if the given user is a Synapse server administrator for this homeserver. The
* client making the request must be an admin user themselves (check with `isSelfAdmin`)
Expand Down
61 changes: 61 additions & 0 deletions test/SynapseAdminApisTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,67 @@ describe('SynapseAdminApis', () => {
});
});

describe('listAllUsers', () => {
it('should call the right endpoint', async () => {
const {client, http, hsUrl} = createTestSynapseAdminClient();

const user1 = {
name: "@someone:example.org",
displayname: "foobar",
avatar_url: "mxc://example.org/animage",
admin: 1,
deactivated: 0,
is_guest: 0,
user_type: null,
password_hash: "$hashbrown"
};

const user2 = {
name: "@else:example.org",
displayname: "barbaz",
avatar_url: "mxc://example.org/animage2",
admin: 1,
deactivated: 0,
is_guest: 0,
user_type: null,
password_hash: "$mmmm-hashbrown"
};

const request = {
limit: 1,
name: "bar",
guests: true,
deactivated: false,
}

http.when("GET", "/_synapse/admin/v2/users").respond(200, (path, _content, req) => {
expect(path).toEqual(`${hsUrl}/_synapse/admin/v2/users`);
expect(req.opts.qs).toEqual(request);
return {
next_token: 'from-token',
total: 2,
users: [user1],
}
});
const iterable = await client.listAllUsers({ name: "bar", guests: true, deactivated: false, limit: 1});
http.flushAllExpected();
const resultUser1 = await iterable.next();
expect(resultUser1).toEqual({done: false, value: user1});

http.when("GET", "/_synapse/admin/v2/users").respond(200, (path, _content, req) => {
expect(path).toEqual(`${hsUrl}/_synapse/admin/v2/users`);
expect(req.opts.qs).toEqual({...request, from: 'from-token'});
return {
total: 2,
users: [user2],
}
});
const resultUser2 = await iterable.next();
expect(resultUser2).toEqual({done: false, value: user2});
expect(await iterable.next()).toEqual({done: true});
});
});

describe('listRooms', () => {
it('should call the right endpoint', async () => {
const {client, http, hsUrl} = createTestSynapseAdminClient();
Expand Down