Skip to content

Commit

Permalink
Merge pull request #403 from matrix-org/hs/allow-private-channels
Browse files Browse the repository at this point in the history
Allow bridging of private channels via the provisioner
  • Loading branch information
Half-Shot authored May 11, 2020
2 parents 7a56c1b + 6b0b37a commit 6021ee5
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 12 deletions.
1 change: 1 addition & 0 deletions changelog.d/403.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow bridging to private channels via the provisioner
2 changes: 2 additions & 0 deletions config/config.sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ provisioning:
enabled: true
# Should the bridge deny users bridging channels to private rooms.
require_public_room: true
# Should the bridge allow usesr to bridge private channels.
allow_private_channels: true
limits:
room_count: 20
team_count: 1
Expand Down
2 changes: 2 additions & 0 deletions config/slack-config-schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ properties:
type: boolean
require_public_room:
type: boolean
allow_private_channels:
type: boolean
limits:
type: object
properties:
Expand Down
1 change: 1 addition & 0 deletions src/IConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export interface IConfig {
provisioning?: {
enable: boolean;
require_public_room?: boolean;
allow_private_channels?: boolean;
limits?: {
team_count?: number;
room_count?: number;
Expand Down
36 changes: 26 additions & 10 deletions src/Provisioning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,21 @@ export class Provisioner {
return (currentCount >= this.main.config.provisioning?.limits?.room_count);
}

private async determineSlackIdForRequest(matrixUserId, teamId) {
const matrixUser = await this.main.datastore.getMatrixUser(matrixUserId);
if (!matrixUser) {
// No Slack user entry found for MXID
return null;
}
const accounts: {[userId: string]: {team_id: string}} = matrixUser.get("accounts");
for (const [key, value] of Object.entries(accounts)) {
if (value.team_id === teamId) {
return key;
}
}
return null;
}

@command()
private async getconfig(_, res) {
const hasRoomLimit = this.main.config.provisioning?.limits?.room_count;
Expand Down Expand Up @@ -150,25 +165,26 @@ export class Provisioner {
@command("user_id", "team_id")
private async channels(req, res, userId, teamId) {
log.debug(`${userId} for ${teamId} requested their channels`);
const matrixUser = await this.main.datastore.getMatrixUser(userId);
const isAllowed = matrixUser !== null &&
Object.values(matrixUser.get("accounts") as {[key: string]: {team_id: string}}).find((acct) =>
acct.team_id === teamId,
);
if (!isAllowed) {
res.status(HTTP_CODES.CLIENT_ERROR).json({error: "User is not part of this team!"});
throw undefined;
const slackUserId = await this.determineSlackIdForRequest(userId, teamId);
if (!slackUserId) {
return res.status(HTTP_CODES.CLIENT_ERROR).json({error: "User is not part of this team!"});
}
const team = await this.main.datastore.getTeam(teamId);
if (team === null) {
throw Error("No team token for this team_id");
}
const cli = await this.main.clientFactory.getTeamClient(teamId);
try {
const response = (await cli.conversations.list({
let types = "public_channel";
// Unless we *explicity* set this to false, allow it.
if (this.main.config.provisioning?.allow_private_channels !== false) {
types = `public_channel,private_channel`;
}
const response = (await cli.users.list({
exclude_archived: true,
limit: 1000, // TODO: Pagination
types: "public_channel", // TODO: In order to show private channels, we need the identity of the caller.
user: slackUserId, // In order to show private channels, we need the identity of the caller.
types,
})) as ConversationsListResponse;
if (!response.ok) {
throw Error(response.error);
Expand Down
4 changes: 2 additions & 2 deletions src/datastore/postgres/PgDatastore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ export class PgDatastore implements Datastore {
});
}

public async getUser(id: string): Promise<UserEntry | null> {
public async getUser(id: string): Promise<UserEntry|null> {
const dbEntry = await this.postgresDb.oneOrNone("SELECT * FROM users WHERE userId = ${id}", { id });
if (!dbEntry) {
return null;
}
return JSON.parse(dbEntry.json);
}

public async getMatrixUser(userId: string): Promise<MatrixUser|undefined> {
public async getMatrixUser(userId: string): Promise<MatrixUser|null> {
userId = new MatrixUser(userId).getId(); // Ensure ID correctness
const userData = await this.getUser(userId);
return userData !== null ? new MatrixUser(userId, userData) : null;
Expand Down

0 comments on commit 6021ee5

Please sign in to comment.