Skip to content

Commit

Permalink
Merge pull request #21143 from RocketChat/new/teams-back
Browse files Browse the repository at this point in the history
Merge Backend
  • Loading branch information
tassoevan authored Mar 16, 2021
2 parents 0e5ec9f + 806c3f0 commit c3cd52f
Show file tree
Hide file tree
Showing 15 changed files with 495 additions and 27 deletions.
71 changes: 65 additions & 6 deletions app/api/server/v1/teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Promise } from 'meteor/promise';

import { API } from '../api';
import { Team } from '../../../../server/sdk';
import { hasPermission } from '../../../authorization/server';
import { hasAtLeastOnePermission, hasPermission } from '../../../authorization/server';

API.v1.addRoute('teams.list', { authRequired: true }, {
get() {
Expand Down Expand Up @@ -40,6 +40,9 @@ API.v1.addRoute('teams.listAll', { authRequired: true }, {

API.v1.addRoute('teams.create', { authRequired: true }, {
post() {
if (!hasPermission(this.userId, 'create-team')) {
return API.v1.unauthorized();
}
const { name, type, members, room, owner } = this.bodyParams;

if (!name) {
Expand All @@ -62,15 +65,71 @@ API.v1.addRoute('teams.create', { authRequired: true }, {

API.v1.addRoute('teams.members', { authRequired: true }, {
get() {
const { teamId } = this.queryParams;
const { offset, count } = this.getPaginationItems();
const { teamId, teamName } = this.queryParams;

const { records, total } = Promise.await(Team.members(teamId, teamName, { offset, count }));

return API.v1.success({
members: records,
total,
count: records.length,
offset,
});
},
});

API.v1.addRoute('teams.addMembers', { authRequired: true }, {
post() {
if (!hasAtLeastOnePermission(this.userId, ['add-team-member', 'edit-team-member'])) {
return API.v1.unauthorized();
}

const { teamId, teamName, members } = this.bodyParams;

Promise.await(Team.addMembers(this.userId, teamId, teamName, members));

return API.v1.success();
},
});

API.v1.addRoute('teams.updateMember', { authRequired: true }, {
post() {
if (!hasAtLeastOnePermission(this.userId, ['edit-team-member'])) {
return API.v1.unauthorized();
}

const { teamId, teamName, member } = this.bodyParams;

Promise.await(Team.updateMember(teamId, teamName, member));

return API.v1.success();
},
});

if (!teamId) {
return API.v1.failure('Team ID is required');
API.v1.addRoute('teams.removeMembers', { authRequired: true }, {
post() {
if (!hasAtLeastOnePermission(this.userId, ['edit-team-member'])) {
return API.v1.unauthorized();
}

const members = Promise.await(Team.members(this.userId, teamId));
const { teamId, teamName, members } = this.bodyParams;

Promise.await(Team.removeMembers(teamId, teamName, members));

return API.v1.success();
},
});

API.v1.addRoute('teams.leave', { authRequired: true }, {
post() {
const { teamId, teamName } = this.bodyParams;

Promise.await(Team.removeMembers(teamId, teamName, [{
userId: this.userId,
}]));

return API.v1.success({ members });
return API.v1.success();
},
});

Expand Down
6 changes: 6 additions & 0 deletions app/lib/server/functions/addUserToRoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Meteor } from 'meteor/meteor';
import { AppEvents, Apps } from '../../../apps/server';
import { callbacks } from '../../../callbacks';
import { Messages, Rooms, Subscriptions } from '../../../models';
import { Team } from '../../../../server/sdk';
import { RoomMemberActions, roomTypes } from '../../../utils/server';

export const addUserToRoom = function(rid, user, inviter, silenced) {
Expand Down Expand Up @@ -84,5 +85,10 @@ export const addUserToRoom = function(rid, user, inviter, silenced) {
});
}

if (room.teamMain && room.teamId) {
// if user is joining to main team channel, create a membership
Promise.await(Team.addMember(inviter, user._id, room.teamId));
}

return true;
};
16 changes: 15 additions & 1 deletion app/models/server/raw/Team.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Collection, FindOneOptions, Cursor } from 'mongodb';
import { Collection, FindOneOptions, Cursor, UpdateWriteOpResult } from 'mongodb';

import { BaseRaw } from './BaseRaw';
import { ITeam } from '../../../../definition/ITeam';
Expand All @@ -25,4 +25,18 @@ export class TeamRaw extends BaseRaw<T> {
findOneByName(name: string, options?: FindOneOptions<T>): Promise<T | null> {
return this.col.findOne({ name }, options);
}

findOneByMainRoomId(roomId: string, options?: FindOneOptions<T>): Promise<T | null> {
return this.col.findOne({ roomId }, options);
}

updateMainRoomForTeam(id: string, roomId: string): Promise<UpdateWriteOpResult> {
return this.col.updateOne({
_id: id,
}, {
$set: {
roomId,
},
});
}
}
39 changes: 38 additions & 1 deletion app/models/server/raw/TeamMember.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Collection, FindOneOptions, Cursor } from 'mongodb';
import { Collection, FindOneOptions, Cursor, InsertOneWriteOpResult, UpdateWriteOpResult } from 'mongodb';

import { BaseRaw } from './BaseRaw';
import { ITeamMember } from '../../../../definition/ITeam';
import { IUser } from '../../../../definition/IUser';

type T = ITeamMember;
export class TeamMemberRaw extends BaseRaw<T> {
Expand Down Expand Up @@ -30,4 +31,40 @@ export class TeamMemberRaw extends BaseRaw<T> {
findByTeamId(teamId: string, options?: FindOneOptions<T>): Cursor<T> {
return this.col.find({ teamId }, options);
}

updateOneByUserIdAndTeamId(userId: string, teamId: string, update: Partial<T>): Promise<UpdateWriteOpResult> {
return this.col.updateOne({ userId, teamId }, { $set: update });
}

createOneByTeamIdAndUserId(teamId: string, userId: string, createdBy: Pick<IUser, '_id' | 'username'>): Promise<InsertOneWriteOpResult<T>> {
return this.insertOne({
teamId,
userId,
createdAt: new Date(),
_updatedAt: new Date(),
createdBy,
});
}

updateRolesByTeamIdAndUserId(teamId: string, userId: string, roles: Array<string>): Promise<UpdateWriteOpResult> {
return this.col.updateOne({
teamId,
userId,
}, {
$addToSet: {
roles: { $each: roles },
},
});
}

removeRolesByTeamIdAndUserId(teamId: string, userId: string, roles: Array<string>): Promise<UpdateWriteOpResult> {
return this.col.updateOne({
teamId,
userId,
}, {
$pull: {
roles: { $in: roles },
},
});
}
}
1 change: 1 addition & 0 deletions definition/ITeam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export enum TEAM_TYPE {
export interface ITeam extends IRocketChatRecord {
name: string;
type: TEAM_TYPE;
roomId: string;
createdBy: Pick<IUser, '_id' | 'username' >;
createdAt: Date;
}
Expand Down
6 changes: 6 additions & 0 deletions server/methods/addRoomLeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { hasPermission } from '../../app/authorization';
import { Users, Subscriptions, Messages } from '../../app/models';
import { settings } from '../../app/settings';
import { api } from '../sdk/api';
import { Team } from '../sdk';

Meteor.methods({
addRoomLeader(rid, userId) {
Expand Down Expand Up @@ -57,6 +58,11 @@ Meteor.methods({
role: 'leader',
});

const team = Promise.await(Team.getOneByRoomId(rid));
if (team) {
Promise.await(Team.addRolesToMember(team._id, userId, ['leader']));
}

if (settings.get('UI_DisplayRoles')) {
api.broadcast('user.roleUpdate', {
type: 'added',
Expand Down
6 changes: 6 additions & 0 deletions server/methods/addRoomModerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { hasPermission } from '../../app/authorization';
import { Users, Subscriptions, Messages } from '../../app/models';
import { settings } from '../../app/settings';
import { api } from '../sdk/api';
import { Team } from '../sdk';

Meteor.methods({
addRoomModerator(rid, userId) {
Expand Down Expand Up @@ -57,6 +58,11 @@ Meteor.methods({
role: 'moderator',
});

const team = Promise.await(Team.getOneByRoomId(rid));
if (team) {
Promise.await(Team.addRolesToMember(team._id, userId, ['moderator']));
}

if (settings.get('UI_DisplayRoles')) {
api.broadcast('user.roleUpdate', {
type: 'added',
Expand Down
6 changes: 6 additions & 0 deletions server/methods/addRoomOwner.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { check } from 'meteor/check';

import { hasPermission } from '../../app/authorization';
import { Users, Subscriptions, Messages } from '../../app/models';
import { Team } from '../sdk';
import { settings } from '../../app/settings';
import { api } from '../sdk/api';

Expand Down Expand Up @@ -57,6 +58,11 @@ Meteor.methods({
role: 'owner',
});

const team = Promise.await(Team.getOneByRoomId(rid));
if (team) {
Promise.await(Team.addRolesToMember(team._id, userId, ['owner']));
}

if (settings.get('UI_DisplayRoles')) {
api.broadcast('user.roleUpdate', {
type: 'added',
Expand Down
6 changes: 6 additions & 0 deletions server/methods/removeRoomLeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { hasPermission } from '../../app/authorization';
import { Users, Subscriptions, Messages } from '../../app/models';
import { settings } from '../../app/settings';
import { api } from '../sdk/api';
import { Team } from '../sdk';

Meteor.methods({
removeRoomLeader(rid, userId) {
Expand Down Expand Up @@ -57,6 +58,11 @@ Meteor.methods({
role: 'leader',
});

const team = Promise.await(Team.getOneByRoomId(rid));
if (team) {
Promise.await(Team.removeRolesFromMember(team._id, userId, ['leader']));
}

if (settings.get('UI_DisplayRoles')) {
api.broadcast('user.roleUpdate', {
type: 'removed',
Expand Down
6 changes: 6 additions & 0 deletions server/methods/removeRoomModerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { hasPermission } from '../../app/authorization';
import { Users, Subscriptions, Messages } from '../../app/models';
import { settings } from '../../app/settings';
import { api } from '../sdk/api';
import { Team } from '../sdk';

Meteor.methods({
removeRoomModerator(rid, userId) {
Expand Down Expand Up @@ -57,6 +58,11 @@ Meteor.methods({
role: 'moderator',
});

const team = Promise.await(Team.getOneByRoomId(rid));
if (team) {
Promise.await(Team.removeRolesFromMember(team._id, userId, ['moderator']));
}

if (settings.get('UI_DisplayRoles')) {
api.broadcast('user.roleUpdate', {
type: 'removed',
Expand Down
6 changes: 6 additions & 0 deletions server/methods/removeRoomOwner.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { hasPermission, getUsersInRole } from '../../app/authorization';
import { Users, Subscriptions, Messages } from '../../app/models';
import { settings } from '../../app/settings';
import { api } from '../sdk/api';
import { Team } from '../sdk';

Meteor.methods({
removeRoomOwner(rid, userId) {
Expand Down Expand Up @@ -64,6 +65,11 @@ Meteor.methods({
role: 'owner',
});

const team = Promise.await(Team.getOneByRoomId(rid));
if (team) {
Promise.await(Team.removeRolesFromMember(team._id, userId, ['owner']));
}

if (settings.get('UI_DisplayRoles')) {
api.broadcast('user.roleUpdate', {
type: 'removed',
Expand Down
3 changes: 2 additions & 1 deletion server/sdk/types/IRoomService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ interface ICreateRoomOptions extends Partial<Record<string, string | ISubscripti
subscriptionExtra?: ISubscriptionExtraData;
}

interface ICreateRoomExtraData extends Record<string, string> {
interface ICreateRoomExtraData extends Record<string, string | boolean> {
teamId: string;
teamMain: boolean;
}

export interface ICreateRoomParams {
Expand Down
11 changes: 10 additions & 1 deletion server/sdk/types/ITeamService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,20 @@ export interface ITeamCreateParams {
owner?: string; // the team owner. If not present, owner = requester
}

export interface ITeamMemberParams {
userId?: string;
userName?: string;
roles?: Array<string>;
}

export interface ITeamService {
create(uid: string, params: ITeamCreateParams): Promise<ITeam>;
list(uid: string, options?: IPaginationOptions): Promise<IRecordsWithTotal<ITeam>>;
listAll(options?: IPaginationOptions): Promise<IRecordsWithTotal<ITeam>>;
members(uid: string, teamId: string): Promise<Array<ITeamMember>>;
members(teamId: string, teamName: string, options?: IPaginationOptions): Promise<IRecordsWithTotal<ITeamMember>>;
addMembers(uid: string, teamId: string, teamName: string, members: Array<ITeamMemberParams>): Promise<void>;
updateMember(teamId: string, teamName: string, members: ITeamMemberParams): Promise<void>;
removeMembers(teamId: string, teamName: string, members: Array<ITeamMemberParams>): Promise<void>;
getInfoByName(teamName: string): Promise<Partial<ITeam> | undefined>;
getInfoById(teamId: string): Promise<Partial<ITeam> | undefined>;
}
Loading

0 comments on commit c3cd52f

Please sign in to comment.