From 000dec7b009d6036e58e059c07580c0061fd44f3 Mon Sep 17 00:00:00 2001
From: vynmera <39674991+vynmera@users.noreply.github.com>
Date: Fri, 1 Jun 2018 20:56:28 +0000
Subject: [PATCH 1/5] Implement permissions.list, permissions.update and add
tests
---
.../rocketchat-api/server/v1/permissions.js | 63 ++++++++++
packages/rocketchat-i18n/i18n/en.i18n.json | 18 +--
tests/end-to-end/api/11-permissions.js | 111 ++++++++++++++++++
3 files changed, 184 insertions(+), 8 deletions(-)
diff --git a/packages/rocketchat-api/server/v1/permissions.js b/packages/rocketchat-api/server/v1/permissions.js
index 68ccb81c01e78..fdc096701e00a 100644
--- a/packages/rocketchat-api/server/v1/permissions.js
+++ b/packages/rocketchat-api/server/v1/permissions.js
@@ -12,3 +12,66 @@ RocketChat.API.v1.addRoute('permissions', { authRequired: true }, {
return RocketChat.API.v1.success(result);
}
});
+
+RocketChat.API.v1.addRoute('permissions.list', { authRequired: true }, {
+ get() {
+ const result = Meteor.runAsUser(this.userId, () => Meteor.call('permissions/get'));
+
+ return RocketChat.API.v1.success({
+ permissions: result
+ });
+ }
+});
+
+RocketChat.API.v1.addRoute('permissions.update', { authRequired: true }, {
+ post() {
+ if (!RocketChat.authz.hasPermission(this.userId, 'access-permissions')) {
+ return RocketChat.API.v1.failure('Editing permissions is not allowed', 'error-edit-permissions-not-allowed');
+ }
+
+ check(this.bodyParams, {
+ permissions: [
+ Match.ObjectIncluding({
+ _id: String,
+ roles: [String]
+ })
+ ]
+ });
+
+ let permissionNotFound = false;
+ let roleNotFound = false;
+ Object.keys(this.bodyParams.permissions).forEach((key) => {
+ const element = this.bodyParams.permissions[key];
+
+ if (!RocketChat.models.Permissions.findOneById(element._id)) {
+ permissionNotFound = true;
+ }
+
+ Object.keys(element.roles).forEach((key) => {
+ const subelement = element.roles[key];
+
+ if (!RocketChat.models.Roles.findOneById(subelement)) {
+ roleNotFound = true;
+ }
+ });
+ });
+
+ if (permissionNotFound) {
+ return RocketChat.API.v1.failure('Invalid permission', 'error-invalid-permission');
+ } else if (roleNotFound) {
+ return RocketChat.API.v1.failure('Invalid role', 'error-invalid-role');
+ }
+
+ Object.keys(this.bodyParams.permissions).forEach((key) => {
+ const element = this.bodyParams.permissions[key];
+
+ RocketChat.models.Permissions.createOrUpdate(element._id, element.roles);
+ });
+
+ const result = Meteor.runAsUser(this.userId, () => Meteor.call('permissions/get'));
+
+ return RocketChat.API.v1.success({
+ permissions: result
+ });
+ }
+});
diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json
index 719eeb5b057c4..bf94b0132a6ad 100644
--- a/packages/rocketchat-i18n/i18n/en.i18n.json
+++ b/packages/rocketchat-i18n/i18n/en.i18n.json
@@ -38,7 +38,7 @@
"Accounts_BlockedDomainsList_Description": "Comma-separated list of blocked domains",
"Accounts_BlockedUsernameList": "Blocked Username List",
"Accounts_BlockedUsernameList_Description": "Comma-separated list of blocked usernames (case-insensitive)",
- "Accounts_CustomFields_Description": "Should be a valid JSON where keys are the field names containing a dictionary of field settings. Example:
{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_CustomFields_Description": "Should be a valid JSON where keys are the field names containing a dictionary of field settings. Example:
{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
"Accounts_CustomFieldsToShowInUserInfo": "Custom Fields to Show in User Info",
"Accounts_DefaultUsernamePrefixSuggestion": "Default Username Prefix Suggestion",
"Accounts_Default_User_Preferences": "Default User Preferences",
@@ -574,7 +574,7 @@
"Custom_Sound_Saved_Successfully": "Custom sound saved successfully",
"Custom_Sounds": "Custom Sounds",
"Custom_Translations": "Custom Translations",
- "Custom_Translations_Description": "Should be a valid JSON where keys are languages containing a dictionary of key and translations. Example:
{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n} ",
+ "Custom_Translations_Description": "Should be a valid JSON where keys are languages containing a dictionary of key and translations. Example:
{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n} ",
"Customize": "Customize",
"CustomSoundsFilesystem": "Custom Sounds Filesystem",
"Dashboard": "Dashboard",
@@ -740,6 +740,7 @@
"error-department-not-found": "Department not found",
"error-direct-message-file-upload-not-allowed": "File sharing not allowed in direct messages",
"error-duplicate-channel-name": "A channel with name '__channel_name__' exists",
+ "error-edit-permissions-not-allowed": "Editing permissions is not allowed",
"error-email-domain-blacklisted": "The email domain is blacklisted",
"error-email-send-failed": "Error trying to send email: __message__",
"error-field-unavailable": "__field__ is already in use :(",
@@ -767,6 +768,7 @@
"error-invalid-method": "Invalid method",
"error-invalid-name": "Invalid name",
"error-invalid-password": "Invalid password",
+ "error-invalid-permission": "Invalid permission",
"error-invalid-redirectUri": "Invalid redirectUri",
"error-invalid-role": "Invalid role",
"error-invalid-room": "Invalid room",
@@ -1959,11 +1961,11 @@
"SlackBridge_Out_Enabled_Description": "Choose whether SlackBridge should also send your messages back to Slack",
"SlackBridge_start": "@%s has started a SlackBridge import at `#%s`. We'll let you know when it's finished.",
"Slack_Users": "Slack's Users CSV",
- "Slash_Gimme_Description": "Displays ༼ つ ◕_◕ ༽つ before your message",
- "Slash_LennyFace_Description": "Displays ( ͡° ͜ʖ ͡°) after your message",
- "Slash_Shrug_Description": "Displays ¯\\_(ツ)_/¯ after your message",
- "Slash_Tableflip_Description": "Displays (╯°□°)╯︵ ┻━┻",
- "Slash_TableUnflip_Description": "Displays ┬─┬ ノ( ゜-゜ノ)",
+ "Slash_Gimme_Description": "Displays ? ? ?_? ?? before your message",
+ "Slash_LennyFace_Description": "Displays ( ?° ?? ?°) after your message",
+ "Slash_Shrug_Description": "Displays ¯\\_(?)_/¯ after your message",
+ "Slash_Tableflip_Description": "Displays (?°?°)?? ???",
+ "Slash_TableUnflip_Description": "Displays ---? ?( ?-??)",
"Slash_Topic_Description": "Set topic",
"Slash_Topic_Params": "Topic message",
"Smarsh_Email": "Smarsh Email",
@@ -2446,7 +2448,7 @@
"Your_password_is_wrong": "Your password is wrong!",
"Your_push_was_sent_to_s_devices": "Your push was sent to %s devices",
"Your_server_link": "Your server link",
- "Your_workspace_is_ready": "Your workspace is ready to use 🎉",
+ "Your_workspace_is_ready": "Your workspace is ready to use ??",
"Worldwide": "Worldwide",
"Country_Afghanistan": "Afghanistan",
"Country_Albania": "Albania",
diff --git a/tests/end-to-end/api/11-permissions.js b/tests/end-to-end/api/11-permissions.js
index 86b702342c011..41daefa3803ca 100644
--- a/tests/end-to-end/api/11-permissions.js
+++ b/tests/end-to-end/api/11-permissions.js
@@ -8,6 +8,8 @@ describe('[Permissions]', function() {
before(done => getCredentials(done));
+ //DEPRECATED
+ // TODO: Remove this after three versions have been released. That means at 0.69 this should be gone.
describe('[/permissions]', () => {
it('should return all permissions that exists on the server, with respective roles', (done) => {
request.get(api('permissions'))
@@ -30,4 +32,113 @@ describe('[Permissions]', function() {
.end(done);
});
});
+
+ describe('[/permissions.list]', () => {
+ it('should return all permissions that exists on the server, with respective roles', (done) => {
+ request.get(api('permissions.list'))
+ .set(credentials)
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.property('permissions');
+
+ const firstElement = res.body.permissions[0];
+ expect(firstElement).to.have.property('_id');
+ expect(firstElement).to.have.property('roles').and.to.be.a('array');
+ expect(firstElement).to.have.property('_updatedAt');
+ expect(firstElement).to.have.property('meta');
+ expect(firstElement.meta).to.have.property('revision');
+ expect(firstElement.meta).to.have.property('created');
+ expect(firstElement.meta).to.have.property('version');
+ expect(firstElement).to.have.property('$loki');
+ })
+ .end(done);
+ });
+ });
+
+ describe('[/permissions.update]', () => {
+ it('should change the permissions on the server', (done) => {
+ const permissions = [
+ {
+ "_id": "add-oauth-service",
+ "roles": ["admin", "user"]
+ }
+ ];
+ request.post(api('permissions.update'))
+ .set(credentials)
+ .send({
+ permissions: permissions
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ expect(res.body).to.have.property('permissions');
+
+ const firstElement = res.body.permissions[0];
+ expect(firstElement).to.have.property('_id');
+ expect(firstElement).to.have.property('roles').and.to.be.a('array');
+ expect(firstElement).to.have.property('_updatedAt');
+ expect(firstElement).to.have.property('meta');
+ expect(firstElement.meta).to.have.property('revision');
+ expect(firstElement.meta).to.have.property('created');
+ expect(firstElement.meta).to.have.property('version');
+ expect(firstElement).to.have.property('$loki');
+ })
+ .end(done);
+ });
+ it('should 400 when trying to set an unknown permission', (done) => {
+ const permissions = [
+ {
+ "_id": "this-permission-does-not-exist",
+ "roles": ["admin"]
+ }
+ ];
+ request.post(api('permissions.update'))
+ .set(credentials)
+ .send({
+ permissions: permissions
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(400)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', false);
+ })
+ .end(done);
+ });
+ it('should 400 when trying to assign a permission to an unknown role', (done) => {
+ const permissions = [
+ {
+ "_id": "add-oauth-service",
+ "roles": ["this-role-does-not-exist"]
+ }
+ ];
+ request.post(api('permissions.update'))
+ .set(credentials)
+ .send({
+ permissions: permissions
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(400)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', false);
+ })
+ .end(done);
+ });
+ it('should 400 when trying to set permissions to a string', (done) => {
+ const permissions = '';
+ request.post(api('permissions.update'))
+ .set(credentials)
+ .send({
+ permissions: permissions
+ })
+ .expect('Content-Type', 'application/json')
+ .expect(400)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', false);
+ })
+ .end(done);
+ });
+ });
});
From 347c27c3bf0ac96e39d084f0fcd626ace2ac3779 Mon Sep 17 00:00:00 2001
From: vynmera <39674991+vynmera@users.noreply.github.com>
Date: Fri, 1 Jun 2018 21:01:23 +0000
Subject: [PATCH 2/5] i18n fix
---
packages/rocketchat-i18n/i18n/en.i18n.json | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json
index bf94b0132a6ad..ed01ba365aded 100644
--- a/packages/rocketchat-i18n/i18n/en.i18n.json
+++ b/packages/rocketchat-i18n/i18n/en.i18n.json
@@ -38,7 +38,7 @@
"Accounts_BlockedDomainsList_Description": "Comma-separated list of blocked domains",
"Accounts_BlockedUsernameList": "Blocked Username List",
"Accounts_BlockedUsernameList_Description": "Comma-separated list of blocked usernames (case-insensitive)",
- "Accounts_CustomFields_Description": "Should be a valid JSON where keys are the field names containing a dictionary of field settings. Example:
{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
+ "Accounts_CustomFields_Description": "Should be a valid JSON where keys are the field names containing a dictionary of field settings. Example:
{\n \"role\": {\n \"type\": \"select\",\n \"defaultValue\": \"student\",\n \"options\": [\"teacher\", \"student\"],\n \"required\": true,\n \"modifyRecordField\": {\n \"array\": true,\n \"field\": \"roles\"\n }\n },\n \"twitter\": {\n \"type\": \"text\",\n \"required\": true,\n \"minLength\": 2,\n \"maxLength\": 10\n }\n} ",
"Accounts_CustomFieldsToShowInUserInfo": "Custom Fields to Show in User Info",
"Accounts_DefaultUsernamePrefixSuggestion": "Default Username Prefix Suggestion",
"Accounts_Default_User_Preferences": "Default User Preferences",
@@ -574,7 +574,7 @@
"Custom_Sound_Saved_Successfully": "Custom sound saved successfully",
"Custom_Sounds": "Custom Sounds",
"Custom_Translations": "Custom Translations",
- "Custom_Translations_Description": "Should be a valid JSON where keys are languages containing a dictionary of key and translations. Example:
{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n} ",
+ "Custom_Translations_Description": "Should be a valid JSON where keys are languages containing a dictionary of key and translations. Example:
{\n \"en\": {\n \"Channels\": \"Rooms\"\n },\n \"pt\": {\n \"Channels\": \"Salas\"\n }\n} ",
"Customize": "Customize",
"CustomSoundsFilesystem": "Custom Sounds Filesystem",
"Dashboard": "Dashboard",
@@ -1961,11 +1961,11 @@
"SlackBridge_Out_Enabled_Description": "Choose whether SlackBridge should also send your messages back to Slack",
"SlackBridge_start": "@%s has started a SlackBridge import at `#%s`. We'll let you know when it's finished.",
"Slack_Users": "Slack's Users CSV",
- "Slash_Gimme_Description": "Displays ? ? ?_? ?? before your message",
- "Slash_LennyFace_Description": "Displays ( ?° ?? ?°) after your message",
- "Slash_Shrug_Description": "Displays ¯\\_(?)_/¯ after your message",
- "Slash_Tableflip_Description": "Displays (?°?°)?? ???",
- "Slash_TableUnflip_Description": "Displays ---? ?( ?-??)",
+ "Slash_Gimme_Description": "Displays ༼ つ ◕_◕ ༽つ before your message",
+ "Slash_LennyFace_Description": "Displays ( ͡° ͜ʖ ͡°) after your message",
+ "Slash_Shrug_Description": "Displays ¯\\_(ツ)_/¯ after your message",
+ "Slash_Tableflip_Description": "Displays (╯°□°)╯︵ ┻━┻",
+ "Slash_TableUnflip_Description": "Displays ┬─┬ ノ( ゜-゜ノ)",
"Slash_Topic_Description": "Set topic",
"Slash_Topic_Params": "Topic message",
"Smarsh_Email": "Smarsh Email",
@@ -2448,7 +2448,7 @@
"Your_password_is_wrong": "Your password is wrong!",
"Your_push_was_sent_to_s_devices": "Your push was sent to %s devices",
"Your_server_link": "Your server link",
- "Your_workspace_is_ready": "Your workspace is ready to use ??",
+ "Your_workspace_is_ready": "Your workspace is ready to use 🎉",
"Worldwide": "Worldwide",
"Country_Afghanistan": "Afghanistan",
"Country_Albania": "Albania",
From 8ec0298c61d972cf5f903f786fc57fe8b1fdc24f Mon Sep 17 00:00:00 2001
From: vynmera <39674991+vynmera@users.noreply.github.com>
Date: Fri, 1 Jun 2018 21:11:37 +0000
Subject: [PATCH 3/5] Resolve linter issues
---
tests/end-to-end/api/11-permissions.js | 28 +++++++++-----------------
1 file changed, 10 insertions(+), 18 deletions(-)
diff --git a/tests/end-to-end/api/11-permissions.js b/tests/end-to-end/api/11-permissions.js
index 41daefa3803ca..c7bb2e890355e 100644
--- a/tests/end-to-end/api/11-permissions.js
+++ b/tests/end-to-end/api/11-permissions.js
@@ -61,15 +61,13 @@ describe('[Permissions]', function() {
it('should change the permissions on the server', (done) => {
const permissions = [
{
- "_id": "add-oauth-service",
- "roles": ["admin", "user"]
+ '_id': 'add-oauth-service',
+ 'roles': ['admin', 'user']
}
];
request.post(api('permissions.update'))
.set(credentials)
- .send({
- permissions: permissions
- })
+ .send({ permissions })
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
@@ -91,15 +89,13 @@ describe('[Permissions]', function() {
it('should 400 when trying to set an unknown permission', (done) => {
const permissions = [
{
- "_id": "this-permission-does-not-exist",
- "roles": ["admin"]
+ '_id': 'this-permission-does-not-exist',
+ 'roles': ['admin']
}
];
request.post(api('permissions.update'))
.set(credentials)
- .send({
- permissions: permissions
- })
+ .send({ permissions })
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
@@ -110,15 +106,13 @@ describe('[Permissions]', function() {
it('should 400 when trying to assign a permission to an unknown role', (done) => {
const permissions = [
{
- "_id": "add-oauth-service",
- "roles": ["this-role-does-not-exist"]
+ '_id': 'add-oauth-service',
+ 'roles': ['this-role-does-not-exist']
}
];
request.post(api('permissions.update'))
.set(credentials)
- .send({
- permissions: permissions
- })
+ .send({ permissions })
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
@@ -130,9 +124,7 @@ describe('[Permissions]', function() {
const permissions = '';
request.post(api('permissions.update'))
.set(credentials)
- .send({
- permissions: permissions
- })
+ .send({ permissions })
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
From db30fe2d7864cb1587aede6cdc84eacd4bb2412a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=B3=E3=83=A1=E3=83=A9?=
<39674991+vynmera@users.noreply.github.com>
Date: Fri, 8 Jun 2018 23:21:57 +0000
Subject: [PATCH 4/5] Add deprecation notice to old permissions
---
packages/rocketchat-api/server/v1/permissions.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/packages/rocketchat-api/server/v1/permissions.js b/packages/rocketchat-api/server/v1/permissions.js
index fdc096701e00a..2fbb1a8ea339c 100644
--- a/packages/rocketchat-api/server/v1/permissions.js
+++ b/packages/rocketchat-api/server/v1/permissions.js
@@ -7,6 +7,9 @@
*/
RocketChat.API.v1.addRoute('permissions', { authRequired: true }, {
get() {
+ const warningMessage = 'The endpoint "permissions" is deprecated and will be removed after version v0.69';
+ console.warn(warningMessage);
+
const result = Meteor.runAsUser(this.userId, () => Meteor.call('permissions/get'));
return RocketChat.API.v1.success(result);
From efaf52fd698b0158378fe132cf474f8d65896577 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=B3=E3=83=A1=E3=83=A9?=
<39674991+vynmera@users.noreply.github.com>
Date: Sat, 9 Jun 2018 01:28:00 +0200
Subject: [PATCH 5/5] not sure what I expected from phone editing
---
packages/rocketchat-api/server/v1/permissions.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/rocketchat-api/server/v1/permissions.js b/packages/rocketchat-api/server/v1/permissions.js
index 2fbb1a8ea339c..eb3f606ad0b4d 100644
--- a/packages/rocketchat-api/server/v1/permissions.js
+++ b/packages/rocketchat-api/server/v1/permissions.js
@@ -7,9 +7,9 @@
*/
RocketChat.API.v1.addRoute('permissions', { authRequired: true }, {
get() {
- const warningMessage = 'The endpoint "permissions" is deprecated and will be removed after version v0.69';
- console.warn(warningMessage);
-
+ const warningMessage = 'The endpoint "permissions" is deprecated and will be removed after version v0.69';
+ console.warn(warningMessage);
+
const result = Meteor.runAsUser(this.userId, () => Meteor.call('permissions/get'));
return RocketChat.API.v1.success(result);