Skip to content

Commit 2165e7c

Browse files
committed
Merge remote-tracking branch 'origin/RocketChat#821' into RocketChat#764
# Conflicts: # app/working-group/client/views/requests/formForSendingDocuments/steps/WorkingGroupRequestAnswerFileDownloadStep.js
2 parents b25e03d + e9860eb commit 2165e7c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3007
-627
lines changed

app/api/server/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@ import './v1/working-group-meetings';
4545
import './v1/upload-files';
4646
import './v1/protocols';
4747
import './v1/working-groups-requests';
48+
import './v1/persons';
4849

4950
export { API, APIClass, defaultRateLimiterOptions } from './api';

app/api/server/lib/persons.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Persons } from '../../../models/server/raw';
2+
3+
export async function findPersons({ query = {}, pagination: { offset, count, sort } }) {
4+
const cursor = await Persons.find(query, {
5+
sort: sort || { time: 1 },
6+
skip: offset,
7+
limit: count,
8+
});
9+
10+
const total = await cursor.count();
11+
12+
const persons = await cursor.toArray();
13+
14+
return {
15+
persons,
16+
count: persons.length,
17+
offset,
18+
total,
19+
};
20+
}
21+
22+
export async function findPerson(_id) {
23+
const cursor = await Persons.findOne({ _id });
24+
return cursor;
25+
}

app/api/server/v1/councils.js

+122-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
import { Meteor } from "meteor/meteor";
2+
13
import { API } from '../api';
24
import { findCouncils, findOneCouncil, findCouncil, findOneCouncilByInviteLink } from '../lib/councils';
35
import { hasPermission } from '../../../authorization';
6+
import { FileUpload } from '../../../file-upload';
47
import { Users } from '../../../models';
8+
import { Persons } from '../../../models';
9+
10+
import Busboy from 'busboy';
511

612
API.v1.addRoute('councils.list', { authRequired: true }, {
713
get() {
@@ -44,7 +50,7 @@ API.v1.addRoute('councils.findOne', { authRequired: true }, {
4450
},
4551
});
4652

47-
API.v1.addRoute('councils.invitedUsers', { authRequired: true }, {
53+
API.v1.addRoute('councils.invitedPersons', { authRequired: true }, {
4854
get() {
4955
if (!hasPermission(this.userId, 'view-c-room')) {
5056
return API.v1.unauthorized();
@@ -55,12 +61,58 @@ API.v1.addRoute('councils.invitedUsers', { authRequired: true }, {
5561

5662
const council = Promise.await(findCouncil(query._id));
5763

58-
const users = Users.find({ _id: { $in: council.invitedUsers } }, {
64+
const persons = Persons.find({ _id: { $in: council.invitedPersons.map((user) => user._id ) } }, {
65+
sort: sort || { surname: 1, name: 1, patronymic: 1 },
66+
skip: offset,
67+
limit: count,
68+
fields: { _id: 1, surname: 1, name: 1, patronymic: 1, phone: 1, email: 1 },
69+
}).fetch().map((user) => {
70+
const iUser = council.invitedPersons.find((iUser) => iUser._id === user._id);
71+
if (!iUser) { return; }
72+
if (!iUser.ts) {
73+
user.ts = new Date('January 1, 2021 00:00:00');
74+
} else {
75+
user.ts = iUser.ts;
76+
}
77+
return user;
78+
});
79+
80+
return API.v1.success({
81+
persons,
82+
count: persons.length,
83+
offset,
84+
total: Persons.find({ _id: { $in: council.invitedPersons.map((iPerson) => iPerson._id) } }).count(),
85+
});
86+
},
87+
});
88+
89+
API.v1.addRoute('councils.invitedUsers', { authRequired: true }, {
90+
get() {
91+
if (!hasPermission(this.userId, 'view-c-room')) {
92+
return API.v1.unauthorized();
93+
}
94+
95+
const { offset, count } = this.getPaginationItems();
96+
const { sort, fields, query } = this.parseJsonQuery();
97+
98+
const council = Promise.await(findCouncil(query.$and[1]._id));
99+
100+
const users = Users.find({ _id: { $in: council.invitedUsers.map((user) => typeof user === typeof {} ? user._id : user ) } }, {
101+
// const users = Users.find({ _id: { $in: council.invitedUsers } }, {
59102
sort: sort || { username: 1 },
60103
skip: offset,
61104
limit: count,
62105
fields,
63-
}).fetch();
106+
}).fetch().map((user) => {
107+
const iUser = council.invitedUsers.find((iUser) => (typeof iUser === typeof {} && iUser._id === user._id) || (typeof iUser === typeof '' && iUser === user._id));
108+
if (!iUser) { return; }
109+
if (!iUser.ts) {
110+
user.ts = new Date('January 1, 2021 00:00:00');
111+
} else {
112+
user.ts = iUser.ts;
113+
}
114+
return user;
115+
});
64116

65117
return API.v1.success({
66118
invitedUsers: users,
@@ -70,3 +122,70 @@ API.v1.addRoute('councils.invitedUsers', { authRequired: true }, {
70122
});
71123
},
72124
});
125+
126+
const getFiles = Meteor.wrapAsync(({ request }, callback) => {
127+
const busboy = new Busboy({ headers: request.headers });
128+
const files = [];
129+
130+
const fields = {};
131+
132+
133+
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
134+
if (fieldname !== 'file') {
135+
return callback(new Meteor.Error('invalid-field'));
136+
}
137+
138+
const fileDate = [];
139+
file.on('data', (data) => fileDate.push(data));
140+
141+
file.on('end', () => {
142+
files.push({ fieldname, file, filename, encoding, mimetype, fileBuffer: Buffer.concat(fileDate) });
143+
});
144+
});
145+
146+
busboy.on('field', (fieldname, value) => { fields[fieldname] = value; });
147+
148+
busboy.on('finish', Meteor.bindEnvironment(() => callback(null, { files, fields })));
149+
150+
request.pipe(busboy);
151+
});
152+
153+
API.v1.addRoute('councils.upload/:id', { authRequired: true }, {
154+
post() {
155+
const { files, fields } = getFiles({
156+
request: this.request,
157+
});
158+
159+
if (files.length === 0) {
160+
console.log('api.v1.route file required');
161+
return API.v1.failure('File required');
162+
}
163+
164+
if (files.length > 1) {
165+
console.log('api.v1.route just 1 file is allowed');
166+
return API.v1.failure('Just 1 file is allowed');
167+
}
168+
169+
const file = files[0];
170+
171+
const details = {
172+
name: file.filename,
173+
size: file.fileBuffer.length,
174+
type: file.mimetype,
175+
workingGroupMeetingId: this.urlParams.id,
176+
userId: this.userId,
177+
};
178+
179+
const fileData = Meteor.runAsUser(this.userId, () => {
180+
const fileStore = FileUpload.getStore('Uploads');
181+
const uploadedFile = fileStore.insertSync(details, file.fileBuffer);
182+
183+
uploadedFile.description = fields.description;
184+
185+
Meteor.call('sendFileCouncil', this.urlParams.id, uploadedFile);
186+
187+
return uploadedFile;
188+
});
189+
return API.v1.success({ _id: fileData._id });
190+
},
191+
});

app/api/server/v1/persons.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { API } from '../api';
2+
import { findPersons, findPerson } from '../lib/persons';
3+
4+
API.v1.addRoute('persons.list', { authRequired: true }, {
5+
get() {
6+
const { offset, count } = this.getPaginationItems();
7+
const { sort, query } = this.parseJsonQuery();
8+
9+
return API.v1.success(Promise.await(findPersons({
10+
query,
11+
pagination: {
12+
offset,
13+
count,
14+
sort,
15+
},
16+
})));
17+
},
18+
});
19+
20+
API.v1.addRoute('persons.findOne', { authRequired: true }, {
21+
get() {
22+
const { query } = this.parseJsonQuery();
23+
return API.v1.success(Promise.await(findPerson(query._id)));
24+
},
25+
});
26+
27+
// API.v1.addRoute('persons.createParticipant', { authRequired: true }, {
28+
// post() {
29+
// console.log('users.createParticipant start');
30+
// console.log(this.bodyParams);
31+
// // check(this.bodyParams, {
32+
// // email: String,
33+
// // name: String,
34+
// // surname: String,
35+
// // patronymic: String,
36+
// // organization: Match.Maybe(String),
37+
// // position: Match.Maybe(String),
38+
// // phone: Match.Maybe(String),
39+
// // // workingGroup: Match.Maybe(String),
40+
// // });
41+
42+
// const newUserId = saveParticipant(this.userId, this.bodyParams);
43+
44+
// const { fields } = this.parseJsonQuery();
45+
46+
// console.log(newUserId);
47+
// console.log('users.createParticipant end');
48+
// return API.v1.success({ user: Users.findOneById(newUserId, { fields }) });
49+
// },
50+
// });

app/api/server/v1/users.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ API.v1.addRoute('users.all', { authRequired: true }, {
286286
}).fetch();
287287

288288
return API.v1.success({
289-
users
289+
items: users
290290
});
291291
},
292292
});

app/authorization/server/startup.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Meteor.startup(function() {
5252
{ _id: 'leave-c', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] },
5353
{ _id: 'leave-p', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] },
5454
{ _id: 'manage-assets', roles: ['admin'] },
55-
{ _id: 'manage-councils', roles: ['admin', 'secretary'] },
55+
{ _id: 'manage-councils', roles: ['admin', 'secretary', 'working-group-member', 'working-group-leader'] },
5656
{ _id: 'manage-emoji', roles: ['admin'] },
5757
{ _id: 'manage-user-status', roles: ['admin'] },
5858
{ _id: 'manage-outgoing-integrations', roles: ['admin'] },
@@ -63,7 +63,7 @@ Meteor.startup(function() {
6363
{ _id: 'manage-protocols', roles: ['admin', 'secretary'] },
6464
{ _id: 'manage-selected-settings', roles: ['admin'] },
6565
{ _id: 'manage-tags', roles: ['admin'] },
66-
{ _id: 'manage-working-group', roles: ['admin', 'secretary'] },
66+
{ _id: 'manage-working-group', roles: ['admin', 'secretary', 'working-group-member', 'working-group-leader'] },
6767
{ _id: 'mention-all', roles: ['admin', 'owner', 'moderator', 'user'] },
6868
{ _id: 'mention-here', roles: ['admin', 'owner', 'moderator', 'user'] },
6969
{ _id: 'mute-user', roles: ['admin', 'owner', 'moderator'] },
@@ -124,6 +124,9 @@ Meteor.startup(function() {
124124
{ _id: 'edit-livechat-room-customfields', roles: ['livechat-manager', 'livechat-agent', 'admin'] },
125125
{ _id: 'send-omnichannel-chat-transcript', roles: ['livechat-manager', 'admin'] },
126126
{ _id: 'mail-messages', roles: ['admin'] },
127+
{ _id: 'handbooks-home-page', roles: ['admin, secretary'] },
128+
{ _id: 'administration-home-page', roles: ['admin, secretary'] },
129+
{ _id: 'manage-persons', roles: ['admin, secretary'] },
127130
];
128131

129132
for (const permission of permissions) {
@@ -141,6 +144,8 @@ Meteor.startup(function() {
141144
{ name: 'app', scope: 'Users', description: '' },
142145
{ name: 'guest', scope: 'Users', description: '' },
143146
{ name: 'anonymous', scope: 'Users', description: '' },
147+
{ name: 'working-group-member', scope: 'Users', description: '' },
148+
{ name: 'working-group-leader', scope: 'Users', description: '' },
144149
{ name: 'livechat-agent', scope: 'Users', description: 'Livechat Agent' },
145150
{ name: 'livechat-manager', scope: 'Users', description: 'Livechat Manager' },
146151
];

app/councils/client/views/AddCouncil.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,17 @@ function AddCouncilWithNewData({ users, setUsers, onChange, workingGroupOptions
8282
const [description, setDescription] = useState('');
8383
const [invitedUsersIds, setInvitedUsersIds] = useState([]);
8484

85-
// TODO: maybe
86-
const invitedUsers = useMemo(() => users.filter((user) => invitedUsersIds.findIndex((iUser) => iUser === user._id) > -1), [invitedUsersIds, users]);
85+
const invitedUsers = useMemo(() => users.filter((user) => {
86+
const iUser = invitedUsersIds.find((iUser) => iUser._id === user._id);
87+
if (!iUser) { return; }
88+
89+
if (!iUser.ts) {
90+
user.ts = new Date('January 1, 2021 00:00:00');
91+
} else {
92+
user.ts = iUser.ts;
93+
}
94+
return user;
95+
}), [invitedUsersIds, users]);
8796

8897
const insertOrUpdateCouncil = useMethod('insertOrUpdateCouncil');
8998

@@ -100,7 +109,7 @@ function AddCouncilWithNewData({ users, setUsers, onChange, workingGroupOptions
100109
};
101110

102111
const onCreateParticipantClick = useCallback((user) => () => {
103-
setInvitedUsersIds(invitedUsersIds.concat(user._id));
112+
setInvitedUsersIds(invitedUsersIds.concat({ _id: user._id, ts: new Date() }));
104113
setUsers(users.concat(user));
105114
onChange();
106115
setContext('participants');

0 commit comments

Comments
 (0)