From d4495b3459d0e82efbf2184a7cdbf5a72a877f41 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Wed, 24 May 2017 23:45:52 -0300 Subject: [PATCH 001/801] Changes for issue #976. Still need some work --- packages/rocketchat-i18n/i18n/en.i18n.json | 3 ++- server/lib/accounts.js | 26 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 0be9c641d9cf..093ec21e9127 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1106,6 +1106,7 @@ "Office_hours_updated": "Office hours updated", "Offline": "Offline", "Offline_DM_Email": "You have been direct messaged by __user__", + "User_Needs_Approval": "A new user registered and needs approval", "Offline_form": "Offline form", "Offline_form_unavailable_message": "Offline form unavailable message", "Offline_Link_Message": "GO TO MESSAGE", @@ -1724,4 +1725,4 @@ "your_message_optional": "your message (optional)", "Your_password_is_wrong": "Your password is wrong!", "Your_push_was_sent_to_s_devices": "Your push was sent to %s devices" -} \ No newline at end of file +} diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 1cffa6d39a00..9b708eee8f82 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -91,6 +91,32 @@ Accounts.onCreateUser(function(options, user = {}) { } } + if (!user.active) { + user.emails.some((email) => { + + const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || ''); + const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); + const divisorMessage = '
'; + const siteName = RocketChat.settings.get('Site_Name'); + const messageHTML = `

A user with email ${options.email} has been registered.
Please check Administration -> Users to activate or delete it.`; + + emailSubject = TAPi18n.__('User_Needs_Approval'); + + RocketChat.models.Roles.findUsersInRole('admin').forEach(function (adminUser) { + email = { + to: adminUser.emails[0].address, + from: RocketChat.settings.get('From_Email'), + subject: `[${ siteName }] ${ emailSubject }`, + html: header + messageHTML + divisorMessage + footer + }; + }); + + Meteor.defer(() => { + Email.send(email); + }); + }); + } + return user; }); From 0255a9ebef9857a19976703ffaa5483b165a8b9c Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 25 May 2017 00:02:34 -0300 Subject: [PATCH 002/801] Moved email strings to propper indexes on i18n --- packages/rocketchat-i18n/i18n/en.i18n.json | 3 ++- server/lib/accounts.js | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 093ec21e9127..aa76e5fdcc75 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -44,6 +44,8 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", + "Accounts_Enrollment_Email_Approval_Needed_Default": "

A user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Enrollment_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", "Accounts_Iframe_api_url": "API URL", @@ -1106,7 +1108,6 @@ "Office_hours_updated": "Office hours updated", "Offline": "Offline", "Offline_DM_Email": "You have been direct messaged by __user__", - "User_Needs_Approval": "A new user registered and needs approval", "Offline_form": "Offline form", "Offline_form_unavailable_message": "Offline form unavailable message", "Offline_Link_Message": "GO TO MESSAGE", diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 9b708eee8f82..31a1cda075cb 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -98,9 +98,11 @@ Accounts.onCreateUser(function(options, user = {}) { const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); const divisorMessage = '


'; const siteName = RocketChat.settings.get('Site_Name'); - const messageHTML = `

A user with email ${options.email} has been registered.
Please check Administration -> Users to activate or delete it.`; + const messageHTML = RocketChat.placeholders.replace(TAPi18n.__('Accounts_Enrollment_Email_Approval_Needed_Default'), { + email: options.email + }); - emailSubject = TAPi18n.__('User_Needs_Approval'); + emailSubject = TAPi18n.__('Accounts_Enrollment_Email_Approval_Needed_Subject_Default'); RocketChat.models.Roles.findUsersInRole('admin').forEach(function (adminUser) { email = { From b90b3b7ab78de470ce244e3f2630c1e963836430 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 25 May 2017 01:18:16 -0300 Subject: [PATCH 003/801] Created templates for subject and mail body --- packages/rocketchat-i18n/i18n/en.i18n.json | 4 +- server/lib/accounts.js | 48 ++++++++++++++-------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index aa76e5fdcc75..191acdcba41e 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -44,8 +44,8 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", - "Accounts_Enrollment_Email_Approval_Needed_Default": "

A user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", - "Accounts_Enrollment_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", + "Accounts_Admin_Email_Approval_Needed_Default": "

A user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Admin_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", "Accounts_Iframe_api_url": "API URL", diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 31a1cda075cb..b946bf60a8bc 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -9,6 +9,8 @@ Accounts.emailTemplates.siteName = RocketChat.settings.get('Site_Name'); Accounts.emailTemplates.from = `${ RocketChat.settings.get('Site_Name') } <${ RocketChat.settings.get('From_Email') }>`; +Accounts.emailTemplates.notifyAdmin = {}; + const verifyEmailHtml = Accounts.emailTemplates.verifyEmail.text; Accounts.emailTemplates.verifyEmail.html = function(user, url) { @@ -56,6 +58,31 @@ Accounts.emailTemplates.enrollAccount.html = function(user = {}/*, url*/) { return header + html + footer; }; +Accounts.emailTemplates.notifyAdmin.subject = function() { + let subject, siteName; + + subject = TAPi18n.__('Accounts_Admin_Email_Approval_Needed_Subject_Default'); + siteName = RocketChat.settings.get('Site_Name'); + + return `[${ siteName }] ${ subject }`; +}; + +Accounts.emailTemplates.notifyAdmin.html = function(user = {}) { + + let html; + + html = TAPi18n.__('Accounts_Admin_Email_Approval_Needed_Default'); + + const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || ''); + const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); + + html = RocketChat.placeholders.replace(html, { + email: user.emails[0].address + }); + + return header + html + footer; +}; + Accounts.onCreateUser(function(options, user = {}) { RocketChat.callbacks.run('beforeCreateUser', options, user); @@ -93,28 +120,17 @@ Accounts.onCreateUser(function(options, user = {}) { if (!user.active) { user.emails.some((email) => { - - const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || ''); - const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); - const divisorMessage = '


'; - const siteName = RocketChat.settings.get('Site_Name'); - const messageHTML = RocketChat.placeholders.replace(TAPi18n.__('Accounts_Enrollment_Email_Approval_Needed_Default'), { - email: options.email - }); - - emailSubject = TAPi18n.__('Accounts_Enrollment_Email_Approval_Needed_Subject_Default'); - RocketChat.models.Roles.findUsersInRole('admin').forEach(function (adminUser) { email = { to: adminUser.emails[0].address, from: RocketChat.settings.get('From_Email'), - subject: `[${ siteName }] ${ emailSubject }`, - html: header + messageHTML + divisorMessage + footer + subject: Accounts.emailTemplates.notifyAdmin.subject(), + html: Accounts.emailTemplates.notifyAdmin.html(user) }; - }); - Meteor.defer(() => { - Email.send(email); + Meteor.defer(() => { + Email.send(email); + }); }); }); } From 7a9337901a09d5d2f73dc23831aa2032ce347965 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 25 May 2017 09:25:08 -0300 Subject: [PATCH 004/801] Fix typo and code standards --- packages/rocketchat-i18n/i18n/en.i18n.json | 2 +- server/lib/accounts.js | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 191acdcba41e..04fe30137942 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -44,7 +44,7 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", - "Accounts_Admin_Email_Approval_Needed_Default": "

A user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Admin_Email_Approval_Needed_Default": "

An user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", "Accounts_Admin_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", diff --git a/server/lib/accounts.js b/server/lib/accounts.js index b946bf60a8bc..b67a283033f2 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -59,10 +59,8 @@ Accounts.emailTemplates.enrollAccount.html = function(user = {}/*, url*/) { }; Accounts.emailTemplates.notifyAdmin.subject = function() { - let subject, siteName; - - subject = TAPi18n.__('Accounts_Admin_Email_Approval_Needed_Subject_Default'); - siteName = RocketChat.settings.get('Site_Name'); + const subject = TAPi18n.__('Accounts_Admin_Email_Approval_Needed_Subject_Default'); + const siteName = RocketChat.settings.get('Site_Name'); return `[${ siteName }] ${ subject }`; }; @@ -120,7 +118,7 @@ Accounts.onCreateUser(function(options, user = {}) { if (!user.active) { user.emails.some((email) => { - RocketChat.models.Roles.findUsersInRole('admin').forEach(function (adminUser) { + RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { email = { to: adminUser.emails[0].address, from: RocketChat.settings.get('From_Email'), From a8776038a562df4409c303542c1f6dff203f2b34 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 25 May 2017 22:29:29 -0300 Subject: [PATCH 005/801] Modified to change email to all admins at once --- server/lib/accounts.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/server/lib/accounts.js b/server/lib/accounts.js index b67a283033f2..155e15cc3651 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -118,17 +118,21 @@ Accounts.onCreateUser(function(options, user = {}) { if (!user.active) { user.emails.some((email) => { + const destinations = []; + RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { - email = { - to: adminUser.emails[0].address, - from: RocketChat.settings.get('From_Email'), - subject: Accounts.emailTemplates.notifyAdmin.subject(), - html: Accounts.emailTemplates.notifyAdmin.html(user) - }; - - Meteor.defer(() => { - Email.send(email); - }); + destinations.push(`${ adminUser.name }<${ adminUser.emails[0].address }>`); + }); + + email = { + to: destinations, + from: RocketChat.settings.get('From_Email'), + subject: Accounts.emailTemplates.notifyAdmin.subject(), + html: Accounts.emailTemplates.notifyAdmin.html(user) + }; + + Meteor.defer(() => { + Email.send(email); }); }); } From 21dcb152b4a2b5ca98e6ec46e8f1f5bfb089082f Mon Sep 17 00:00:00 2001 From: Fernando Nascimento Date: Fri, 26 May 2017 19:11:35 -0300 Subject: [PATCH 006/801] Added reason field into register screen --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-ui-login/client/login/form.html | 9 +++++++++ packages/rocketchat-ui-login/client/login/form.js | 3 +++ 3 files changed, 13 insertions(+) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 04fe30137942..6635e40491a6 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1227,6 +1227,7 @@ "Read_only_changed_successfully": "Read only changed successfully", "Read_only_channel": "Read Only Channel", "Read_only_group": "Read Only Group", + "Reason_To_Join": "Reason to Join", "Record": "Record", "Redirect_URI": "Redirect URI", "Refresh_oauth_services": "Refresh OAuth Services", diff --git a/packages/rocketchat-ui-login/client/login/form.html b/packages/rocketchat-ui-login/client/login/form.html index c124177edc63..46f37802e5d8 100644 --- a/packages/rocketchat-ui-login/client/login/form.html +++ b/packages/rocketchat-ui-login/client/login/form.html @@ -73,6 +73,15 @@

{{{_ "Registration_Succeeded"}}}

{{/if}} + {{#if manuallyApproveNewUsers}} +
+ +
+ +
+
+
+ {{/if}} {{/if}} {{#if state 'forgot-password' 'email-verification'}}
diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index fa6d28a19a5b..cee2e76937d5 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -58,6 +58,9 @@ Template.loginForm.helpers({ }, hasOnePassword() { return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; + }, + manuallyApproveNewUsers() { + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); } }); From 8701eb09469989cccf4f387bbdc42410ac8c9a75 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 00:37:32 -0300 Subject: [PATCH 007/801] - Added error message for invalid reason - Added method to save reason into user object - Added validation to display field but setting Accounts_ManuallyApproveNewUsers is not working :( --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-lib/server/models/Users.js | 10 ++++++++++ packages/rocketchat-ui-login/client/login/form.js | 7 ++++++- server/methods/registerUser.js | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 6635e40491a6..bfa95e070463 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -764,6 +764,7 @@ "Invalid_name": "The name must not be empty", "Invalid_notification_setting_s": "Invalid notification setting: %s", "Invalid_pass": "The password must not be empty", + "Invalid_reason": "The reason to join must not be empty", "Invalid_room_name": "%s is not a valid room name,
use only letters, numbers, hyphens and underscores", "Invalid_secret_URL_message": "The URL provided is invalid.", "Invalid_setting_s": "Invalid setting: %s", diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 941416475c6e..a492a5b75f7a 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -313,6 +313,16 @@ class ModelUsers extends RocketChat.models._Base { return this.update(_id, update); } + setReason(_id, reason) { + const update = { + $set: { + reason + } + }; + + return this.update(_id, update); + } + setCustomFields(_id, fields) { const values = {}; Object.keys(fields).reduce(key => { diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index cee2e76937d5..ebcd82c2ba37 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -60,7 +60,9 @@ Template.loginForm.helpers({ return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; }, manuallyApproveNewUsers() { - return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); + //TODO verify why it' s not getting this setting + //return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); + return true; } }); @@ -253,6 +255,9 @@ Template.loginForm.onCreated(function() { if (RocketChat.settings.get('Accounts_RequirePasswordConfirmation') && formObj['confirm-pass'] !== formObj['pass']) { validationObj['confirm-pass'] = t('Invalid_confirm_pass'); } + if (true && !formObj['reason']) { + validationObj['reason'] = t('Invalid_reason'); + } validateCustomFields(formObj, validationObj); } $('#login-card h2').removeClass('error'); diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 17c0ceb71b14..55c7f79ea945 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -17,6 +17,7 @@ Meteor.methods({ email: String, pass: String, name: String, + reason: String, secretURL: Match.Optional(String) })); } @@ -45,6 +46,7 @@ Meteor.methods({ } RocketChat.models.Users.setName(userId, s.trim(formData.name)); + RocketChat.models.Users.setReason(userId, s.trim(formData.reason)); RocketChat.saveCustomFields(userId, formData); From 7f5e498fa7ea703a091627933c4ca46d867f7b97 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 00:54:16 -0300 Subject: [PATCH 008/801] - Changed to use the correct setting --- packages/rocketchat-ui-login/client/login/form.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index ebcd82c2ba37..6f1fee80919f 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -60,9 +60,7 @@ Template.loginForm.helpers({ return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; }, manuallyApproveNewUsers() { - //TODO verify why it' s not getting this setting - //return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); - return true; + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); } }); @@ -255,7 +253,7 @@ Template.loginForm.onCreated(function() { if (RocketChat.settings.get('Accounts_RequirePasswordConfirmation') && formObj['confirm-pass'] !== formObj['pass']) { validationObj['confirm-pass'] = t('Invalid_confirm_pass'); } - if (true && !formObj['reason']) { + if (RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && !formObj['reason']) { validationObj['reason'] = t('Invalid_reason'); } validateCustomFields(formObj, validationObj); From c92d2b0f9cea56e215ac7fe2a733426512bd056f Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 13:43:43 -0300 Subject: [PATCH 009/801] - Modified admin message to contain reason and user name - Modified function placeholders to replace reason as well - Modified email template on accounts.js --- packages/rocketchat-i18n/i18n/en.i18n.json | 2 +- packages/rocketchat-lib/lib/placeholders.js | 1 + server/lib/accounts.js | 8 +++++--- server/methods/registerUser.js | 4 +++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index bfa95e070463..c7b2bee5b7b6 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -44,7 +44,7 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
  • [name], [fname], [lname] for the user's full name, first name or last name, respectively.
  • [email] for the user's email.
  • [Site_Name] and [Site_URL] for the Application Name and URL respectively.
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", - "Accounts_Admin_Email_Approval_Needed_Default": "

An user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Admin_Email_Approval_Needed_Default": "

The user [name] ([email]) has been registered.

Reason: [reason]

Please check Administration -> Users to activate or delete it.

", "Accounts_Admin_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", diff --git a/packages/rocketchat-lib/lib/placeholders.js b/packages/rocketchat-lib/lib/placeholders.js index 82fb613d050a..26eca737afdf 100644 --- a/packages/rocketchat-lib/lib/placeholders.js +++ b/packages/rocketchat-lib/lib/placeholders.js @@ -14,6 +14,7 @@ RocketChat.placeholders.replace = function(str, data) { str = str.replace(/\[lname\]/g, _.strRightBack(data.name, ' ') || ''); str = str.replace(/\[email\]/g, data.email || ''); str = str.replace(/\[password\]/g, data.password || ''); + str = str.replace(/\[reason\]/g, data.reason || ''); if (data.unsubscribe) { str = str.replace(/\[unsubscribe\]/g, data.unsubscribe); diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 155e15cc3651..8d69eacb8ba4 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -65,7 +65,7 @@ Accounts.emailTemplates.notifyAdmin.subject = function() { return `[${ siteName }] ${ subject }`; }; -Accounts.emailTemplates.notifyAdmin.html = function(user = {}) { +Accounts.emailTemplates.notifyAdmin.html = function(options = {}) { let html; @@ -75,7 +75,9 @@ Accounts.emailTemplates.notifyAdmin.html = function(user = {}) { const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); html = RocketChat.placeholders.replace(html, { - email: user.emails[0].address + name: options.name, + email: options.email, + reason: options.reason }); return header + html + footer; @@ -128,7 +130,7 @@ Accounts.onCreateUser(function(options, user = {}) { to: destinations, from: RocketChat.settings.get('From_Email'), subject: Accounts.emailTemplates.notifyAdmin.subject(), - html: Accounts.emailTemplates.notifyAdmin.html(user) + html: Accounts.emailTemplates.notifyAdmin.html(options) }; Meteor.defer(() => { diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 55c7f79ea945..bd1250188028 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -32,7 +32,9 @@ Meteor.methods({ const userData = { email: s.trim(formData.email.toLowerCase()), - password: formData.pass + password: formData.pass, + name: formData.name, + reason: formData.reason }; // Check if user has already been imported and never logged in. If so, set password and let it through From eae8aa37440ccd1cbf52c468085cc420a32c09ed Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 14:56:10 -0300 Subject: [PATCH 010/801] - Added public key to use Accounts_ManuallyApproveNewUsers on frontend --- packages/rocketchat-lib/server/startup/settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index bd77f407b7d7..b17408fc4cac 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -95,6 +95,7 @@ RocketChat.settings.addGroup('Accounts', function() { } }); this.add('Accounts_ManuallyApproveNewUsers', false, { + 'public': true, type: 'boolean' }); this.add('Accounts_AllowedDomainsList', '', { From 16a58b50155602f07f99ecddb6e732390df07d78 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 15:49:09 -0300 Subject: [PATCH 011/801] - Displaying reason on user info - Reason displayed only if setting is active and user is not active - Added reason to getFullUserData --- .../rocketchat-lib/server/functions/getFullUserData.js | 3 ++- packages/rocketchat-lib/server/models/Users.js | 1 + packages/rocketchat-ui-flextab/client/tabs/userInfo.html | 7 ++++++- packages/rocketchat-ui-flextab/client/tabs/userInfo.js | 5 +++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-lib/server/functions/getFullUserData.js b/packages/rocketchat-lib/server/functions/getFullUserData.js index 0b5290b3b3e8..cbeb1e7f11c6 100644 --- a/packages/rocketchat-lib/server/functions/getFullUserData.js +++ b/packages/rocketchat-lib/server/functions/getFullUserData.js @@ -6,7 +6,8 @@ RocketChat.getFullUserData = function({userId, filter, limit}) { status: 1, utcOffset: 1, type: 1, - active: 1 + active: 1, + reason: 1 }; if (RocketChat.authz.hasPermission(userId, 'view-full-other-user-info')) { diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index a492a5b75f7a..184789c2a1cc 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -9,6 +9,7 @@ class ModelUsers extends RocketChat.models._Base { this.tryEnsureIndex({ 'active': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'statusConnection': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'type': 1 }); + this.tryEnsureIndex({ 'reason': 1 }); this.cache.ensureIndex('username', 'unique'); } diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.html b/packages/rocketchat-ui-flextab/client/tabs/userInfo.html index 4b1dfaffa3c5..6d70b7b581d7 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.html +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.html @@ -26,7 +26,7 @@

{{name}}

{{#if hasPhone}} {{#each phone}}

{{phoneNumber}}

{{/each}} {{/if}} - {{#if lastLogin}}

{{_ "Created_at"}}: {{createdAt}}

{{/if}} + {{#if createdAt}}

{{_ "Created_at"}}: {{createdAt}}

{{/if}} {{#if lastLogin}}

{{_ "Last_login"}}: {{lastLogin}}

{{/if}} {{#if services.facebook.id}}

{{services.facebook.name}}

{{/if}} {{#if services.github.id}}

{{services.github.username}}

{{/if}} @@ -37,6 +37,11 @@

{{name}}

{{#if services.twitter.id}}

{{services.twitter.screenName}}

{{/if}} {{#if services.wordpress.id}}

{{services.wordpress.user_login}}

{{/if}} {{/if}} + {{#if shouldDisplayReason}} +

+ {{_ "Reason_To_Join"}}: {{user.reason}} +

+ {{/if}}
{{/with}} diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index e64f60b0e5fc..ede5cb950e26 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -180,6 +180,11 @@ Template.userInfo.helpers({ isBlocker() { const subscription = ChatSubscription.findOne({rid:Session.get('openedRoom'), 'u._id': Meteor.userId()}, { fields: { blocker: 1 } }); return subscription.blocker; + }, + + shouldDisplayReason() { + const user = Template.instance().user.get(); + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false; } }); From 3925e8917a4f22911dc4daa102d7cb85a76515a2 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 17:45:38 -0300 Subject: [PATCH 012/801] Added logic to remove user reason once user gets activated --- client/methods/unsetUserReason.js | 6 ++++ .../rocketchat-lib/server/models/Users.js | 30 ++++++++++++------- .../client/tabs/userInfo.js | 5 +++- server/methods/unsetUserReason.js | 27 +++++++++++++++++ 4 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 client/methods/unsetUserReason.js create mode 100644 server/methods/unsetUserReason.js diff --git a/client/methods/unsetUserReason.js b/client/methods/unsetUserReason.js new file mode 100644 index 000000000000..245eb587dfbb --- /dev/null +++ b/client/methods/unsetUserReason.js @@ -0,0 +1,6 @@ +Meteor.methods({ + unsetUserReason(userId) { + Meteor.users.update(userId, { $unset: { 'reason' : 1 } }); + return true; + } +}); diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 184789c2a1cc..ce21729643aa 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -314,16 +314,6 @@ class ModelUsers extends RocketChat.models._Base { return this.update(_id, update); } - setReason(_id, reason) { - const update = { - $set: { - reason - } - }; - - return this.update(_id, update); - } - setCustomFields(_id, fields) { const values = {}; Object.keys(fields).reduce(key => { @@ -504,6 +494,26 @@ class ModelUsers extends RocketChat.models._Base { return this.update({ _id }, update); } + setReason(_id, reason) { + const update = { + $set: { + reason + } + }; + + return this.update(_id, update); + } + + unsetReason(_id) { + const update = { + $unset: { + 'reason' : true, + } + }; + + return this.update(_id, update); + } + // INSERT create(data) { const user = { diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index ede5cb950e26..883751232fe7 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -184,7 +184,7 @@ Template.userInfo.helpers({ shouldDisplayReason() { const user = Template.instance().user.get(); - return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false; + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false && user.reason; } }); @@ -395,6 +395,9 @@ Template.userInfo.events({ if (user) { return Meteor.call('setUserActiveStatus', user._id, true, function(error, result) { if (result) { + + Meteor.call('unsetUserReason', user._id); + toastr.success(t('User_has_been_activated')); } if (error) { diff --git a/server/methods/unsetUserReason.js b/server/methods/unsetUserReason.js new file mode 100644 index 000000000000..b2740a145bf8 --- /dev/null +++ b/server/methods/unsetUserReason.js @@ -0,0 +1,27 @@ +Meteor.methods({ + unsetUserReason(userId) { + check(userId, String); + + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'unsetUserReason' + }); + } + + if (RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-active-status') !== true) { + throw new Meteor.Error('error-not-allowed', 'Not allowed', { + method: 'unsetUserReason' + }); + } + + const user = RocketChat.models.Users.findOneById(userId); + + if (user) { + RocketChat.models.Users.unsetReason(userId); + + return true; + } + + return false; + } +}); From f001a4cd373bd5329e63f79d4f17cef863bfdff0 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Fri, 26 May 2017 19:11:35 -0300 Subject: [PATCH 013/801] Added reason field into register screen --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-ui-login/client/login/form.html | 9 +++++++++ packages/rocketchat-ui-login/client/login/form.js | 3 +++ 3 files changed, 13 insertions(+) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 04fe30137942..6635e40491a6 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1227,6 +1227,7 @@ "Read_only_changed_successfully": "Read only changed successfully", "Read_only_channel": "Read Only Channel", "Read_only_group": "Read Only Group", + "Reason_To_Join": "Reason to Join", "Record": "Record", "Redirect_URI": "Redirect URI", "Refresh_oauth_services": "Refresh OAuth Services", diff --git a/packages/rocketchat-ui-login/client/login/form.html b/packages/rocketchat-ui-login/client/login/form.html index c124177edc63..46f37802e5d8 100644 --- a/packages/rocketchat-ui-login/client/login/form.html +++ b/packages/rocketchat-ui-login/client/login/form.html @@ -73,6 +73,15 @@

{{{_ "Registration_Succeeded"}}}

{{/if}} + {{#if manuallyApproveNewUsers}} +
+ +
+ +
+
+
+ {{/if}} {{/if}} {{#if state 'forgot-password' 'email-verification'}}
diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index fa6d28a19a5b..cee2e76937d5 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -58,6 +58,9 @@ Template.loginForm.helpers({ }, hasOnePassword() { return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; + }, + manuallyApproveNewUsers() { + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); } }); From 21c6c73a976986c83caeae5c3d8afd323941944e Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 00:37:32 -0300 Subject: [PATCH 014/801] - Added error message for invalid reason - Added method to save reason into user object - Added validation to display field but setting Accounts_ManuallyApproveNewUsers is not working :( --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-lib/server/models/Users.js | 10 ++++++++++ packages/rocketchat-ui-login/client/login/form.js | 7 ++++++- server/methods/registerUser.js | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 6635e40491a6..bfa95e070463 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -764,6 +764,7 @@ "Invalid_name": "The name must not be empty", "Invalid_notification_setting_s": "Invalid notification setting: %s", "Invalid_pass": "The password must not be empty", + "Invalid_reason": "The reason to join must not be empty", "Invalid_room_name": "%s is not a valid room name,
use only letters, numbers, hyphens and underscores", "Invalid_secret_URL_message": "The URL provided is invalid.", "Invalid_setting_s": "Invalid setting: %s", diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 941416475c6e..a492a5b75f7a 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -313,6 +313,16 @@ class ModelUsers extends RocketChat.models._Base { return this.update(_id, update); } + setReason(_id, reason) { + const update = { + $set: { + reason + } + }; + + return this.update(_id, update); + } + setCustomFields(_id, fields) { const values = {}; Object.keys(fields).reduce(key => { diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index cee2e76937d5..ebcd82c2ba37 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -60,7 +60,9 @@ Template.loginForm.helpers({ return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; }, manuallyApproveNewUsers() { - return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); + //TODO verify why it' s not getting this setting + //return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); + return true; } }); @@ -253,6 +255,9 @@ Template.loginForm.onCreated(function() { if (RocketChat.settings.get('Accounts_RequirePasswordConfirmation') && formObj['confirm-pass'] !== formObj['pass']) { validationObj['confirm-pass'] = t('Invalid_confirm_pass'); } + if (true && !formObj['reason']) { + validationObj['reason'] = t('Invalid_reason'); + } validateCustomFields(formObj, validationObj); } $('#login-card h2').removeClass('error'); diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 17c0ceb71b14..55c7f79ea945 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -17,6 +17,7 @@ Meteor.methods({ email: String, pass: String, name: String, + reason: String, secretURL: Match.Optional(String) })); } @@ -45,6 +46,7 @@ Meteor.methods({ } RocketChat.models.Users.setName(userId, s.trim(formData.name)); + RocketChat.models.Users.setReason(userId, s.trim(formData.reason)); RocketChat.saveCustomFields(userId, formData); From fad9497a1fb305160b6f8c937b4e181822a21692 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 00:54:16 -0300 Subject: [PATCH 015/801] - Changed to use the correct setting --- packages/rocketchat-ui-login/client/login/form.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index ebcd82c2ba37..6f1fee80919f 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -60,9 +60,7 @@ Template.loginForm.helpers({ return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; }, manuallyApproveNewUsers() { - //TODO verify why it' s not getting this setting - //return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); - return true; + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); } }); @@ -255,7 +253,7 @@ Template.loginForm.onCreated(function() { if (RocketChat.settings.get('Accounts_RequirePasswordConfirmation') && formObj['confirm-pass'] !== formObj['pass']) { validationObj['confirm-pass'] = t('Invalid_confirm_pass'); } - if (true && !formObj['reason']) { + if (RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && !formObj['reason']) { validationObj['reason'] = t('Invalid_reason'); } validateCustomFields(formObj, validationObj); From 17ad773bf8020b2b1ca9185e8d0690f89b536fdb Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 13:43:43 -0300 Subject: [PATCH 016/801] - Modified admin message to contain reason and user name - Modified function placeholders to replace reason as well - Modified email template on accounts.js --- packages/rocketchat-i18n/i18n/en.i18n.json | 2 +- packages/rocketchat-lib/lib/placeholders.js | 1 + server/lib/accounts.js | 8 +++++--- server/methods/registerUser.js | 4 +++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index bfa95e070463..c7b2bee5b7b6 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -44,7 +44,7 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
  • [name], [fname], [lname] for the user's full name, first name or last name, respectively.
  • [email] for the user's email.
  • [Site_Name] and [Site_URL] for the Application Name and URL respectively.
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", - "Accounts_Admin_Email_Approval_Needed_Default": "

An user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Admin_Email_Approval_Needed_Default": "

The user [name] ([email]) has been registered.

Reason: [reason]

Please check Administration -> Users to activate or delete it.

", "Accounts_Admin_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", diff --git a/packages/rocketchat-lib/lib/placeholders.js b/packages/rocketchat-lib/lib/placeholders.js index 82fb613d050a..26eca737afdf 100644 --- a/packages/rocketchat-lib/lib/placeholders.js +++ b/packages/rocketchat-lib/lib/placeholders.js @@ -14,6 +14,7 @@ RocketChat.placeholders.replace = function(str, data) { str = str.replace(/\[lname\]/g, _.strRightBack(data.name, ' ') || ''); str = str.replace(/\[email\]/g, data.email || ''); str = str.replace(/\[password\]/g, data.password || ''); + str = str.replace(/\[reason\]/g, data.reason || ''); if (data.unsubscribe) { str = str.replace(/\[unsubscribe\]/g, data.unsubscribe); diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 155e15cc3651..8d69eacb8ba4 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -65,7 +65,7 @@ Accounts.emailTemplates.notifyAdmin.subject = function() { return `[${ siteName }] ${ subject }`; }; -Accounts.emailTemplates.notifyAdmin.html = function(user = {}) { +Accounts.emailTemplates.notifyAdmin.html = function(options = {}) { let html; @@ -75,7 +75,9 @@ Accounts.emailTemplates.notifyAdmin.html = function(user = {}) { const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); html = RocketChat.placeholders.replace(html, { - email: user.emails[0].address + name: options.name, + email: options.email, + reason: options.reason }); return header + html + footer; @@ -128,7 +130,7 @@ Accounts.onCreateUser(function(options, user = {}) { to: destinations, from: RocketChat.settings.get('From_Email'), subject: Accounts.emailTemplates.notifyAdmin.subject(), - html: Accounts.emailTemplates.notifyAdmin.html(user) + html: Accounts.emailTemplates.notifyAdmin.html(options) }; Meteor.defer(() => { diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 55c7f79ea945..bd1250188028 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -32,7 +32,9 @@ Meteor.methods({ const userData = { email: s.trim(formData.email.toLowerCase()), - password: formData.pass + password: formData.pass, + name: formData.name, + reason: formData.reason }; // Check if user has already been imported and never logged in. If so, set password and let it through From db7d777dbc87f0c66097c49d1acde839035cbfb0 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 14:56:10 -0300 Subject: [PATCH 017/801] - Added public key to use Accounts_ManuallyApproveNewUsers on frontend --- packages/rocketchat-lib/server/startup/settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index bd77f407b7d7..b17408fc4cac 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -95,6 +95,7 @@ RocketChat.settings.addGroup('Accounts', function() { } }); this.add('Accounts_ManuallyApproveNewUsers', false, { + 'public': true, type: 'boolean' }); this.add('Accounts_AllowedDomainsList', '', { From 0f9962200d11cbf26e6a7bd50dcf6e25e51ce5e1 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 15:49:09 -0300 Subject: [PATCH 018/801] - Displaying reason on user info - Reason displayed only if setting is active and user is not active - Added reason to getFullUserData --- .../rocketchat-lib/server/functions/getFullUserData.js | 3 ++- packages/rocketchat-lib/server/models/Users.js | 1 + packages/rocketchat-ui-flextab/client/tabs/userInfo.html | 7 ++++++- packages/rocketchat-ui-flextab/client/tabs/userInfo.js | 5 +++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-lib/server/functions/getFullUserData.js b/packages/rocketchat-lib/server/functions/getFullUserData.js index 0b5290b3b3e8..cbeb1e7f11c6 100644 --- a/packages/rocketchat-lib/server/functions/getFullUserData.js +++ b/packages/rocketchat-lib/server/functions/getFullUserData.js @@ -6,7 +6,8 @@ RocketChat.getFullUserData = function({userId, filter, limit}) { status: 1, utcOffset: 1, type: 1, - active: 1 + active: 1, + reason: 1 }; if (RocketChat.authz.hasPermission(userId, 'view-full-other-user-info')) { diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index a492a5b75f7a..184789c2a1cc 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -9,6 +9,7 @@ class ModelUsers extends RocketChat.models._Base { this.tryEnsureIndex({ 'active': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'statusConnection': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'type': 1 }); + this.tryEnsureIndex({ 'reason': 1 }); this.cache.ensureIndex('username', 'unique'); } diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.html b/packages/rocketchat-ui-flextab/client/tabs/userInfo.html index 4b1dfaffa3c5..6d70b7b581d7 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.html +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.html @@ -26,7 +26,7 @@

{{name}}

{{#if hasPhone}} {{#each phone}}

{{phoneNumber}}

{{/each}} {{/if}} - {{#if lastLogin}}

{{_ "Created_at"}}: {{createdAt}}

{{/if}} + {{#if createdAt}}

{{_ "Created_at"}}: {{createdAt}}

{{/if}} {{#if lastLogin}}

{{_ "Last_login"}}: {{lastLogin}}

{{/if}} {{#if services.facebook.id}}

{{services.facebook.name}}

{{/if}} {{#if services.github.id}}

{{services.github.username}}

{{/if}} @@ -37,6 +37,11 @@

{{name}}

{{#if services.twitter.id}}

{{services.twitter.screenName}}

{{/if}} {{#if services.wordpress.id}}

{{services.wordpress.user_login}}

{{/if}} {{/if}} + {{#if shouldDisplayReason}} +

+ {{_ "Reason_To_Join"}}: {{user.reason}} +

+ {{/if}}
{{/with}} diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index e64f60b0e5fc..ede5cb950e26 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -180,6 +180,11 @@ Template.userInfo.helpers({ isBlocker() { const subscription = ChatSubscription.findOne({rid:Session.get('openedRoom'), 'u._id': Meteor.userId()}, { fields: { blocker: 1 } }); return subscription.blocker; + }, + + shouldDisplayReason() { + const user = Template.instance().user.get(); + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false; } }); From e6fff42c8f00cbf2afc1d1749dc51bca68f61b59 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 17:45:38 -0300 Subject: [PATCH 019/801] Added logic to remove user reason once user gets activated --- client/methods/unsetUserReason.js | 6 ++++ .../rocketchat-lib/server/models/Users.js | 30 ++++++++++++------- .../client/tabs/userInfo.js | 5 +++- server/methods/unsetUserReason.js | 27 +++++++++++++++++ 4 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 client/methods/unsetUserReason.js create mode 100644 server/methods/unsetUserReason.js diff --git a/client/methods/unsetUserReason.js b/client/methods/unsetUserReason.js new file mode 100644 index 000000000000..245eb587dfbb --- /dev/null +++ b/client/methods/unsetUserReason.js @@ -0,0 +1,6 @@ +Meteor.methods({ + unsetUserReason(userId) { + Meteor.users.update(userId, { $unset: { 'reason' : 1 } }); + return true; + } +}); diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 184789c2a1cc..ce21729643aa 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -314,16 +314,6 @@ class ModelUsers extends RocketChat.models._Base { return this.update(_id, update); } - setReason(_id, reason) { - const update = { - $set: { - reason - } - }; - - return this.update(_id, update); - } - setCustomFields(_id, fields) { const values = {}; Object.keys(fields).reduce(key => { @@ -504,6 +494,26 @@ class ModelUsers extends RocketChat.models._Base { return this.update({ _id }, update); } + setReason(_id, reason) { + const update = { + $set: { + reason + } + }; + + return this.update(_id, update); + } + + unsetReason(_id) { + const update = { + $unset: { + 'reason' : true, + } + }; + + return this.update(_id, update); + } + // INSERT create(data) { const user = { diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index ede5cb950e26..883751232fe7 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -184,7 +184,7 @@ Template.userInfo.helpers({ shouldDisplayReason() { const user = Template.instance().user.get(); - return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false; + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false && user.reason; } }); @@ -395,6 +395,9 @@ Template.userInfo.events({ if (user) { return Meteor.call('setUserActiveStatus', user._id, true, function(error, result) { if (result) { + + Meteor.call('unsetUserReason', user._id); + toastr.success(t('User_has_been_activated')); } if (error) { diff --git a/server/methods/unsetUserReason.js b/server/methods/unsetUserReason.js new file mode 100644 index 000000000000..b2740a145bf8 --- /dev/null +++ b/server/methods/unsetUserReason.js @@ -0,0 +1,27 @@ +Meteor.methods({ + unsetUserReason(userId) { + check(userId, String); + + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'unsetUserReason' + }); + } + + if (RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-active-status') !== true) { + throw new Meteor.Error('error-not-allowed', 'Not allowed', { + method: 'unsetUserReason' + }); + } + + const user = RocketChat.models.Users.findOneById(userId); + + if (user) { + RocketChat.models.Users.unsetReason(userId); + + return true; + } + + return false; + } +}); From 12988c459592637f77a4487ee505bb1f161ec57f Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 18:08:20 -0300 Subject: [PATCH 020/801] Removing unneeded comma --- packages/rocketchat-lib/server/models/Users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index ce21729643aa..1c119f79aaf1 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -507,7 +507,7 @@ class ModelUsers extends RocketChat.models._Base { unsetReason(_id) { const update = { $unset: { - 'reason' : true, + 'reason' : true } }; From 7538f007b62cbd69910b2a0edefcc43928fce175 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 20:36:41 -0300 Subject: [PATCH 021/801] Added conditionals to check and use reason field --- server/methods/registerUser.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index bd1250188028..cfe086c0bc92 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -2,6 +2,7 @@ Meteor.methods({ registerUser(formData) { const AllowAnonymousRead = RocketChat.settings.get('Accounts_AllowAnonymousRead'); const AllowAnonymousWrite = RocketChat.settings.get('Accounts_AllowAnonymousWrite'); + const manuallyApproveNewUsers = RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); if (AllowAnonymousRead === true && AllowAnonymousWrite === true && formData.email == null) { const userId = Accounts.insertUserDoc({}, { globalRoles: [ @@ -17,9 +18,14 @@ Meteor.methods({ email: String, pass: String, name: String, - reason: String, secretURL: Match.Optional(String) })); + + if (manuallyApproveNewUsers) { + check(formData, Match.ObjectIncluding({ + reason: String + })); + } } if (RocketChat.settings.get('Accounts_RegistrationForm') === 'Disabled') { @@ -33,10 +39,13 @@ Meteor.methods({ const userData = { email: s.trim(formData.email.toLowerCase()), password: formData.pass, - name: formData.name, - reason: formData.reason + name: formData.name }; + if (manuallyApproveNewUsers) { + userData.reason = formData.reason; + } + // Check if user has already been imported and never logged in. If so, set password and let it through const importedUser = RocketChat.models.Users.findOneByEmailAddress(s.trim(formData.email.toLowerCase())); let userId; @@ -48,7 +57,10 @@ Meteor.methods({ } RocketChat.models.Users.setName(userId, s.trim(formData.name)); - RocketChat.models.Users.setReason(userId, s.trim(formData.reason)); + + if (manuallyApproveNewUsers) { + RocketChat.models.Users.setReason(userId, s.trim(formData.reason)); + } RocketChat.saveCustomFields(userId, formData); From e7cd5eb599477cf7637dce423232e882c80c980e Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 21:10:03 -0300 Subject: [PATCH 022/801] Trying to fix user creation tests --- tests/data/user.js | 1 + tests/end-to-end/ui/03-user-creation.js | 4 ++-- tests/pageobjects/login.page.js | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/data/user.js b/tests/data/user.js index 92294f99dfcf..f9d51e8ba46b 100644 --- a/tests/data/user.js +++ b/tests/data/user.js @@ -1,6 +1,7 @@ export const username = `user.test.${ Date.now() }`; export const email = `${ username }@rocket.chat`; export const password = 'rocket.chat'; +export const reason = 'rocket.chat.reason'; export const adminUsername = 'rocketchat.internal.admin.test'; export const adminEmail = `${ adminUsername }@rocket.chat`; diff --git a/tests/end-to-end/ui/03-user-creation.js b/tests/end-to-end/ui/03-user-creation.js index fe93c69caa34..47b4eeb2b812 100644 --- a/tests/end-to-end/ui/03-user-creation.js +++ b/tests/end-to-end/ui/03-user-creation.js @@ -5,7 +5,7 @@ import loginPage from '../../pageobjects/login.page'; import mainContent from '../../pageobjects/main-content.page'; //test data imports -import {username, email, password} from '../../data/user.js'; +import {username, email, password, reason} from '../../data/user.js'; @@ -22,7 +22,7 @@ describe('[User Creation]', function() { it('it should create user', () => { loginPage.gotToRegister(); - loginPage.registerNewUser({username, email, password}); + loginPage.registerNewUser({username, email, password, reason}); loginPage.inputUsername.waitForExist(5000); diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js index e0150d40a15a..15020173df95 100644 --- a/tests/pageobjects/login.page.js +++ b/tests/pageobjects/login.page.js @@ -11,6 +11,7 @@ class LoginPage extends Page { get emailField() { return browser.element('[name=email]'); } get passwordField() { return browser.element('[name=pass]'); } get confirmPasswordField() { return browser.element('[name=confirm-pass]'); } + get reasonField() { return browser.element('[reason]'); } get inputUsername() { return browser.element('form#login-card input#username'); } get emailOrUsernameInvalidText() { return browser.element('[name=emailOrUsername]~.input-error'); } @@ -18,6 +19,7 @@ class LoginPage extends Page { get emailInvalidText() { return browser.element('[name=email]~.input-error'); } get passwordInvalidText() { return browser.element('[name=pass]~.input-error'); } get confirmPasswordInvalidText() { return browser.element('[name=confirm-pass]~.input-error'); } + get reasonInvalidText() { return browser.element('[name=reason]~.input-error'); } get registrationSucceededCard() { return browser.element('#login-card h2'); } open() { @@ -38,12 +40,13 @@ class LoginPage extends Page { this.emailField.waitForVisible(15000); } - registerNewUser({username, email, password}) { + registerNewUser({username, email, password, reason}) { this.nameField.waitForVisible(5000); this.nameField.setValue(username); this.emailField.setValue(email); this.passwordField.setValue(password); this.confirmPasswordField.setValue(password); + this.reasonField.setValue(reason); this.submit(); } From 777441e7a3f2c1190c5358eb26cad721e42486cc Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 21:27:33 -0300 Subject: [PATCH 023/801] Trying to fix user creation tests(2) --- tests/pageobjects/login.page.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js index 15020173df95..3f03a4c3d80d 100644 --- a/tests/pageobjects/login.page.js +++ b/tests/pageobjects/login.page.js @@ -46,7 +46,6 @@ class LoginPage extends Page { this.emailField.setValue(email); this.passwordField.setValue(password); this.confirmPasswordField.setValue(password); - this.reasonField.setValue(reason); this.submit(); } From c0edb09975e18008adc03b0f0ea59012b7e4f4e4 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Mon, 29 May 2017 23:52:52 -0300 Subject: [PATCH 024/801] Applying last suggestions --- client/methods/unsetUserReason.js | 6 ---- .../rocketchat-lib/server/models/Users.js | 1 - .../client/tabs/userInfo.js | 3 -- server/lib/accounts.js | 31 ++++++++++--------- server/methods/setUserActiveStatus.js | 2 ++ server/methods/unsetUserReason.js | 27 ---------------- 6 files changed, 18 insertions(+), 52 deletions(-) delete mode 100644 client/methods/unsetUserReason.js delete mode 100644 server/methods/unsetUserReason.js diff --git a/client/methods/unsetUserReason.js b/client/methods/unsetUserReason.js deleted file mode 100644 index 245eb587dfbb..000000000000 --- a/client/methods/unsetUserReason.js +++ /dev/null @@ -1,6 +0,0 @@ -Meteor.methods({ - unsetUserReason(userId) { - Meteor.users.update(userId, { $unset: { 'reason' : 1 } }); - return true; - } -}); diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 1c119f79aaf1..7224cd4d2a97 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -9,7 +9,6 @@ class ModelUsers extends RocketChat.models._Base { this.tryEnsureIndex({ 'active': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'statusConnection': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'type': 1 }); - this.tryEnsureIndex({ 'reason': 1 }); this.cache.ensureIndex('username', 'unique'); } diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index 883751232fe7..cd540249fb0f 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -395,9 +395,6 @@ Template.userInfo.events({ if (user) { return Meteor.call('setUserActiveStatus', user._id, true, function(error, result) { if (result) { - - Meteor.call('unsetUserReason', user._id); - toastr.success(t('User_has_been_activated')); } if (error) { diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 8d69eacb8ba4..c59ca905cb42 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -119,23 +119,24 @@ Accounts.onCreateUser(function(options, user = {}) { } if (!user.active) { - user.emails.some((email) => { - const destinations = []; + const destinations = []; + let email = {}; - RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { + RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { + if (adminUser.emails[0]) { destinations.push(`${ adminUser.name }<${ adminUser.emails[0].address }>`); - }); - - email = { - to: destinations, - from: RocketChat.settings.get('From_Email'), - subject: Accounts.emailTemplates.notifyAdmin.subject(), - html: Accounts.emailTemplates.notifyAdmin.html(options) - }; - - Meteor.defer(() => { - Email.send(email); - }); + } + }); + + email = { + to: destinations, + from: RocketChat.settings.get('From_Email'), + subject: Accounts.emailTemplates.notifyAdmin.subject(), + html: Accounts.emailTemplates.notifyAdmin.html(options) + }; + + Meteor.defer(() => { + Email.send(email); }); } diff --git a/server/methods/setUserActiveStatus.js b/server/methods/setUserActiveStatus.js index f4a2eea9d1ea..47ad26b2f68f 100644 --- a/server/methods/setUserActiveStatus.js +++ b/server/methods/setUserActiveStatus.js @@ -26,6 +26,8 @@ Meteor.methods({ if (active === false) { RocketChat.models.Users.unsetLoginTokens(userId); + } else { + RocketChat.models.Users.unsetReason(userId); } return true; diff --git a/server/methods/unsetUserReason.js b/server/methods/unsetUserReason.js deleted file mode 100644 index b2740a145bf8..000000000000 --- a/server/methods/unsetUserReason.js +++ /dev/null @@ -1,27 +0,0 @@ -Meteor.methods({ - unsetUserReason(userId) { - check(userId, String); - - if (!Meteor.userId()) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'unsetUserReason' - }); - } - - if (RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-active-status') !== true) { - throw new Meteor.Error('error-not-allowed', 'Not allowed', { - method: 'unsetUserReason' - }); - } - - const user = RocketChat.models.Users.findOneById(userId); - - if (user) { - RocketChat.models.Users.unsetReason(userId); - - return true; - } - - return false; - } -}); From c04184849b16a9238c08112217d550c19fc486d2 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Tue, 30 May 2017 23:10:17 -0300 Subject: [PATCH 025/801] Moving reason tests to right file --- tests/end-to-end/ui/03-user-creation.js | 2 +- tests/end-to-end/ui/12-settings.js | 1 + tests/pageobjects/login.page.js | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/end-to-end/ui/03-user-creation.js b/tests/end-to-end/ui/03-user-creation.js index 47b4eeb2b812..3076b6cc4fa5 100644 --- a/tests/end-to-end/ui/03-user-creation.js +++ b/tests/end-to-end/ui/03-user-creation.js @@ -22,7 +22,7 @@ describe('[User Creation]', function() { it('it should create user', () => { loginPage.gotToRegister(); - loginPage.registerNewUser({username, email, password, reason}); + loginPage.registerNewUser({username, email, password}); loginPage.inputUsername.waitForExist(5000); diff --git a/tests/end-to-end/ui/12-settings.js b/tests/end-to-end/ui/12-settings.js index 381a305b3112..809a06f24307 100644 --- a/tests/end-to-end/ui/12-settings.js +++ b/tests/end-to-end/ui/12-settings.js @@ -458,6 +458,7 @@ describe('[Api Settings Change]', () => { loginPage.emailField.setValue(`setting${ email }`); loginPage.passwordField.setValue(password); loginPage.confirmPasswordField.setValue(password); + loginPage.reasonField.setValue(password); loginPage.submit(); diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js index 3f03a4c3d80d..6c9ee1862983 100644 --- a/tests/pageobjects/login.page.js +++ b/tests/pageobjects/login.page.js @@ -19,7 +19,6 @@ class LoginPage extends Page { get emailInvalidText() { return browser.element('[name=email]~.input-error'); } get passwordInvalidText() { return browser.element('[name=pass]~.input-error'); } get confirmPasswordInvalidText() { return browser.element('[name=confirm-pass]~.input-error'); } - get reasonInvalidText() { return browser.element('[name=reason]~.input-error'); } get registrationSucceededCard() { return browser.element('#login-card h2'); } open() { @@ -40,7 +39,7 @@ class LoginPage extends Page { this.emailField.waitForVisible(15000); } - registerNewUser({username, email, password, reason}) { + registerNewUser({username, email, password}) { this.nameField.waitForVisible(5000); this.nameField.setValue(username); this.emailField.setValue(email); From 206c86845fcf8ea8d2ae0ac178ad1f9bd8488a65 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Tue, 30 May 2017 23:20:54 -0300 Subject: [PATCH 026/801] Moving reason tests to right file (2) --- tests/end-to-end/ui/03-user-creation.js | 2 +- tests/end-to-end/ui/12-settings.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/end-to-end/ui/03-user-creation.js b/tests/end-to-end/ui/03-user-creation.js index 3076b6cc4fa5..fe93c69caa34 100644 --- a/tests/end-to-end/ui/03-user-creation.js +++ b/tests/end-to-end/ui/03-user-creation.js @@ -5,7 +5,7 @@ import loginPage from '../../pageobjects/login.page'; import mainContent from '../../pageobjects/main-content.page'; //test data imports -import {username, email, password, reason} from '../../data/user.js'; +import {username, email, password} from '../../data/user.js'; diff --git a/tests/end-to-end/ui/12-settings.js b/tests/end-to-end/ui/12-settings.js index 809a06f24307..0bb9c19506d7 100644 --- a/tests/end-to-end/ui/12-settings.js +++ b/tests/end-to-end/ui/12-settings.js @@ -16,7 +16,7 @@ import admin from '../../pageobjects/administration.page'; import {checkIfUserIsValid, checkIfUserIsAdmin} from '../../data/checks'; import {targetUser, imgURL} from '../../data/interactions.js'; -import {adminUsername, adminEmail, adminPassword, username, email, password} from '../../data/user.js'; +import {adminUsername, adminEmail, adminPassword, username, email, password, reason} from '../../data/user.js'; function api(path) { return prefix + path; @@ -458,7 +458,7 @@ describe('[Api Settings Change]', () => { loginPage.emailField.setValue(`setting${ email }`); loginPage.passwordField.setValue(password); loginPage.confirmPasswordField.setValue(password); - loginPage.reasonField.setValue(password); + loginPage.reasonField.setValue(reason); loginPage.submit(); From 72d83355de28da6cc40d8f7daf2ac95086a393bf Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Wed, 31 May 2017 00:16:29 -0300 Subject: [PATCH 027/801] Fixing test where field was not found --- tests/pageobjects/login.page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js index 6c9ee1862983..d049f31c9cac 100644 --- a/tests/pageobjects/login.page.js +++ b/tests/pageobjects/login.page.js @@ -11,7 +11,7 @@ class LoginPage extends Page { get emailField() { return browser.element('[name=email]'); } get passwordField() { return browser.element('[name=pass]'); } get confirmPasswordField() { return browser.element('[name=confirm-pass]'); } - get reasonField() { return browser.element('[reason]'); } + get reasonField() { return browser.element('[name=reason]'); } get inputUsername() { return browser.element('form#login-card input#username'); } get emailOrUsernameInvalidText() { return browser.element('[name=emailOrUsername]~.input-error'); } From 14825360cae71f9935eda38c331b911f4fc703d7 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Wed, 24 May 2017 23:45:52 -0300 Subject: [PATCH 028/801] Changes for issue #976. Still need some work --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + server/lib/accounts.js | 26 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 1b2888536b9a..8bd722e7a087 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1106,6 +1106,7 @@ "Office_hours_updated": "Office hours updated", "Offline": "Offline", "Offline_DM_Email": "You have been direct messaged by __user__", + "User_Needs_Approval": "A new user registered and needs approval", "Offline_form": "Offline form", "Offline_form_unavailable_message": "Offline form unavailable message", "Offline_Link_Message": "GO TO MESSAGE", diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 1cffa6d39a00..9b708eee8f82 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -91,6 +91,32 @@ Accounts.onCreateUser(function(options, user = {}) { } } + if (!user.active) { + user.emails.some((email) => { + + const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || ''); + const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); + const divisorMessage = '
'; + const siteName = RocketChat.settings.get('Site_Name'); + const messageHTML = `

A user with email ${options.email} has been registered.
Please check Administration -> Users to activate or delete it.`; + + emailSubject = TAPi18n.__('User_Needs_Approval'); + + RocketChat.models.Roles.findUsersInRole('admin').forEach(function (adminUser) { + email = { + to: adminUser.emails[0].address, + from: RocketChat.settings.get('From_Email'), + subject: `[${ siteName }] ${ emailSubject }`, + html: header + messageHTML + divisorMessage + footer + }; + }); + + Meteor.defer(() => { + Email.send(email); + }); + }); + } + return user; }); From 1ebd3712fe30962b8bdd4f71ef44facaaf264bc1 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 25 May 2017 00:02:34 -0300 Subject: [PATCH 029/801] Moved email strings to propper indexes on i18n --- packages/rocketchat-i18n/i18n/en.i18n.json | 3 ++- server/lib/accounts.js | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8bd722e7a087..ef42f5dfac0c 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -42,6 +42,8 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
  • [name], [fname], [lname] for the user's full name, first name or last name, respectively.
  • [email] for the user's email.
  • [Site_Name] and [Site_URL] for the Application Name and URL respectively.
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", + "Accounts_Enrollment_Email_Approval_Needed_Default": "

A user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Enrollment_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", "Accounts_Iframe_api_url": "API URL", @@ -1106,7 +1108,6 @@ "Office_hours_updated": "Office hours updated", "Offline": "Offline", "Offline_DM_Email": "You have been direct messaged by __user__", - "User_Needs_Approval": "A new user registered and needs approval", "Offline_form": "Offline form", "Offline_form_unavailable_message": "Offline form unavailable message", "Offline_Link_Message": "GO TO MESSAGE", diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 9b708eee8f82..31a1cda075cb 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -98,9 +98,11 @@ Accounts.onCreateUser(function(options, user = {}) { const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); const divisorMessage = '


'; const siteName = RocketChat.settings.get('Site_Name'); - const messageHTML = `

A user with email ${options.email} has been registered.
Please check Administration -> Users to activate or delete it.`; + const messageHTML = RocketChat.placeholders.replace(TAPi18n.__('Accounts_Enrollment_Email_Approval_Needed_Default'), { + email: options.email + }); - emailSubject = TAPi18n.__('User_Needs_Approval'); + emailSubject = TAPi18n.__('Accounts_Enrollment_Email_Approval_Needed_Subject_Default'); RocketChat.models.Roles.findUsersInRole('admin').forEach(function (adminUser) { email = { From 073dd0be110ab51a94d8c615e41bc7716f8e6217 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 25 May 2017 01:18:16 -0300 Subject: [PATCH 030/801] Created templates for subject and mail body --- packages/rocketchat-i18n/i18n/en.i18n.json | 4 +- server/lib/accounts.js | 48 ++++++++++++++-------- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index ef42f5dfac0c..52c2f6d3bc3d 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -42,8 +42,8 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
  • [name], [fname], [lname] for the user's full name, first name or last name, respectively.
  • [email] for the user's email.
  • [Site_Name] and [Site_URL] for the Application Name and URL respectively.
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", - "Accounts_Enrollment_Email_Approval_Needed_Default": "

A user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", - "Accounts_Enrollment_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", + "Accounts_Admin_Email_Approval_Needed_Default": "

A user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Admin_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", "Accounts_Iframe_api_url": "API URL", diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 31a1cda075cb..b946bf60a8bc 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -9,6 +9,8 @@ Accounts.emailTemplates.siteName = RocketChat.settings.get('Site_Name'); Accounts.emailTemplates.from = `${ RocketChat.settings.get('Site_Name') } <${ RocketChat.settings.get('From_Email') }>`; +Accounts.emailTemplates.notifyAdmin = {}; + const verifyEmailHtml = Accounts.emailTemplates.verifyEmail.text; Accounts.emailTemplates.verifyEmail.html = function(user, url) { @@ -56,6 +58,31 @@ Accounts.emailTemplates.enrollAccount.html = function(user = {}/*, url*/) { return header + html + footer; }; +Accounts.emailTemplates.notifyAdmin.subject = function() { + let subject, siteName; + + subject = TAPi18n.__('Accounts_Admin_Email_Approval_Needed_Subject_Default'); + siteName = RocketChat.settings.get('Site_Name'); + + return `[${ siteName }] ${ subject }`; +}; + +Accounts.emailTemplates.notifyAdmin.html = function(user = {}) { + + let html; + + html = TAPi18n.__('Accounts_Admin_Email_Approval_Needed_Default'); + + const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || ''); + const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); + + html = RocketChat.placeholders.replace(html, { + email: user.emails[0].address + }); + + return header + html + footer; +}; + Accounts.onCreateUser(function(options, user = {}) { RocketChat.callbacks.run('beforeCreateUser', options, user); @@ -93,28 +120,17 @@ Accounts.onCreateUser(function(options, user = {}) { if (!user.active) { user.emails.some((email) => { - - const header = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Header') || ''); - const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); - const divisorMessage = '


'; - const siteName = RocketChat.settings.get('Site_Name'); - const messageHTML = RocketChat.placeholders.replace(TAPi18n.__('Accounts_Enrollment_Email_Approval_Needed_Default'), { - email: options.email - }); - - emailSubject = TAPi18n.__('Accounts_Enrollment_Email_Approval_Needed_Subject_Default'); - RocketChat.models.Roles.findUsersInRole('admin').forEach(function (adminUser) { email = { to: adminUser.emails[0].address, from: RocketChat.settings.get('From_Email'), - subject: `[${ siteName }] ${ emailSubject }`, - html: header + messageHTML + divisorMessage + footer + subject: Accounts.emailTemplates.notifyAdmin.subject(), + html: Accounts.emailTemplates.notifyAdmin.html(user) }; - }); - Meteor.defer(() => { - Email.send(email); + Meteor.defer(() => { + Email.send(email); + }); }); }); } From 42201cf2c66a69b46f609bdb268dfbfb7542aa48 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 25 May 2017 09:25:08 -0300 Subject: [PATCH 031/801] Fix typo and code standards --- packages/rocketchat-i18n/i18n/en.i18n.json | 2 +- server/lib/accounts.js | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 52c2f6d3bc3d..5a368896b9ff 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -42,7 +42,7 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
  • [name], [fname], [lname] for the user's full name, first name or last name, respectively.
  • [email] for the user's email.
  • [Site_Name] and [Site_URL] for the Application Name and URL respectively.
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", - "Accounts_Admin_Email_Approval_Needed_Default": "

A user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Admin_Email_Approval_Needed_Default": "

An user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", "Accounts_Admin_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", diff --git a/server/lib/accounts.js b/server/lib/accounts.js index b946bf60a8bc..b67a283033f2 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -59,10 +59,8 @@ Accounts.emailTemplates.enrollAccount.html = function(user = {}/*, url*/) { }; Accounts.emailTemplates.notifyAdmin.subject = function() { - let subject, siteName; - - subject = TAPi18n.__('Accounts_Admin_Email_Approval_Needed_Subject_Default'); - siteName = RocketChat.settings.get('Site_Name'); + const subject = TAPi18n.__('Accounts_Admin_Email_Approval_Needed_Subject_Default'); + const siteName = RocketChat.settings.get('Site_Name'); return `[${ siteName }] ${ subject }`; }; @@ -120,7 +118,7 @@ Accounts.onCreateUser(function(options, user = {}) { if (!user.active) { user.emails.some((email) => { - RocketChat.models.Roles.findUsersInRole('admin').forEach(function (adminUser) { + RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { email = { to: adminUser.emails[0].address, from: RocketChat.settings.get('From_Email'), From 4952eb1ec8919fbcb95d11d9d6ccac99eee1ce08 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 25 May 2017 22:29:29 -0300 Subject: [PATCH 032/801] Modified to change email to all admins at once --- server/lib/accounts.js | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/server/lib/accounts.js b/server/lib/accounts.js index b67a283033f2..155e15cc3651 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -118,17 +118,21 @@ Accounts.onCreateUser(function(options, user = {}) { if (!user.active) { user.emails.some((email) => { + const destinations = []; + RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { - email = { - to: adminUser.emails[0].address, - from: RocketChat.settings.get('From_Email'), - subject: Accounts.emailTemplates.notifyAdmin.subject(), - html: Accounts.emailTemplates.notifyAdmin.html(user) - }; - - Meteor.defer(() => { - Email.send(email); - }); + destinations.push(`${ adminUser.name }<${ adminUser.emails[0].address }>`); + }); + + email = { + to: destinations, + from: RocketChat.settings.get('From_Email'), + subject: Accounts.emailTemplates.notifyAdmin.subject(), + html: Accounts.emailTemplates.notifyAdmin.html(user) + }; + + Meteor.defer(() => { + Email.send(email); }); }); } From b9f983a1b58476b01f7a206cb2ba07849529ed5c Mon Sep 17 00:00:00 2001 From: Fernando Nascimento Date: Fri, 26 May 2017 19:11:35 -0300 Subject: [PATCH 033/801] Added reason field into register screen --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-ui-login/client/login/form.html | 9 +++++++++ packages/rocketchat-ui-login/client/login/form.js | 3 +++ 3 files changed, 13 insertions(+) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 5a368896b9ff..83f837a928ab 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1227,6 +1227,7 @@ "Read_only_changed_successfully": "Read only changed successfully", "Read_only_channel": "Read Only Channel", "Read_only_group": "Read Only Group", + "Reason_To_Join": "Reason to Join", "Record": "Record", "Redirect_URI": "Redirect URI", "Refresh_oauth_services": "Refresh OAuth Services", diff --git a/packages/rocketchat-ui-login/client/login/form.html b/packages/rocketchat-ui-login/client/login/form.html index c124177edc63..46f37802e5d8 100644 --- a/packages/rocketchat-ui-login/client/login/form.html +++ b/packages/rocketchat-ui-login/client/login/form.html @@ -73,6 +73,15 @@

{{{_ "Registration_Succeeded"}}}

{{/if}} + {{#if manuallyApproveNewUsers}} +
+ +
+ +
+
+
+ {{/if}} {{/if}} {{#if state 'forgot-password' 'email-verification'}}
diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index fa6d28a19a5b..cee2e76937d5 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -58,6 +58,9 @@ Template.loginForm.helpers({ }, hasOnePassword() { return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; + }, + manuallyApproveNewUsers() { + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); } }); From dbcba5634b18285e6e8a109bd0f19368c630f438 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 00:37:32 -0300 Subject: [PATCH 034/801] - Added error message for invalid reason - Added method to save reason into user object - Added validation to display field but setting Accounts_ManuallyApproveNewUsers is not working :( --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-lib/server/models/Users.js | 10 ++++++++++ packages/rocketchat-ui-login/client/login/form.js | 7 ++++++- server/methods/registerUser.js | 2 ++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 83f837a928ab..8e275ae18a8f 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -764,6 +764,7 @@ "Invalid_name": "The name must not be empty", "Invalid_notification_setting_s": "Invalid notification setting: %s", "Invalid_pass": "The password must not be empty", + "Invalid_reason": "The reason to join must not be empty", "Invalid_room_name": "%s is not a valid room name,
use only letters, numbers, hyphens and underscores", "Invalid_secret_URL_message": "The URL provided is invalid.", "Invalid_setting_s": "Invalid setting: %s", diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 941416475c6e..a492a5b75f7a 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -313,6 +313,16 @@ class ModelUsers extends RocketChat.models._Base { return this.update(_id, update); } + setReason(_id, reason) { + const update = { + $set: { + reason + } + }; + + return this.update(_id, update); + } + setCustomFields(_id, fields) { const values = {}; Object.keys(fields).reduce(key => { diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index cee2e76937d5..ebcd82c2ba37 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -60,7 +60,9 @@ Template.loginForm.helpers({ return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; }, manuallyApproveNewUsers() { - return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); + //TODO verify why it' s not getting this setting + //return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); + return true; } }); @@ -253,6 +255,9 @@ Template.loginForm.onCreated(function() { if (RocketChat.settings.get('Accounts_RequirePasswordConfirmation') && formObj['confirm-pass'] !== formObj['pass']) { validationObj['confirm-pass'] = t('Invalid_confirm_pass'); } + if (true && !formObj['reason']) { + validationObj['reason'] = t('Invalid_reason'); + } validateCustomFields(formObj, validationObj); } $('#login-card h2').removeClass('error'); diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 17c0ceb71b14..55c7f79ea945 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -17,6 +17,7 @@ Meteor.methods({ email: String, pass: String, name: String, + reason: String, secretURL: Match.Optional(String) })); } @@ -45,6 +46,7 @@ Meteor.methods({ } RocketChat.models.Users.setName(userId, s.trim(formData.name)); + RocketChat.models.Users.setReason(userId, s.trim(formData.reason)); RocketChat.saveCustomFields(userId, formData); From b10b887a93acab0fb0a321a5e7dc377e75d60c20 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 00:54:16 -0300 Subject: [PATCH 035/801] - Changed to use the correct setting --- packages/rocketchat-ui-login/client/login/form.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index ebcd82c2ba37..6f1fee80919f 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -60,9 +60,7 @@ Template.loginForm.helpers({ return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; }, manuallyApproveNewUsers() { - //TODO verify why it' s not getting this setting - //return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); - return true; + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); } }); @@ -255,7 +253,7 @@ Template.loginForm.onCreated(function() { if (RocketChat.settings.get('Accounts_RequirePasswordConfirmation') && formObj['confirm-pass'] !== formObj['pass']) { validationObj['confirm-pass'] = t('Invalid_confirm_pass'); } - if (true && !formObj['reason']) { + if (RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && !formObj['reason']) { validationObj['reason'] = t('Invalid_reason'); } validateCustomFields(formObj, validationObj); From 4248273f244709e182d219b7ab5b1156deace286 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 13:43:43 -0300 Subject: [PATCH 036/801] - Modified admin message to contain reason and user name - Modified function placeholders to replace reason as well - Modified email template on accounts.js --- packages/rocketchat-i18n/i18n/en.i18n.json | 2 +- packages/rocketchat-lib/lib/placeholders.js | 1 + server/lib/accounts.js | 8 +++++--- server/methods/registerUser.js | 4 +++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8e275ae18a8f..5a0dd4ca20ca 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -42,7 +42,7 @@ "Accounts_Enrollment_Email_Default": "

Welcome to

[Site_Name]

Go to [Site_URL] and try the best open source chat solution available today!

", "Accounts_Enrollment_Email_Description": "You may use the following placeholders:
  • [name], [fname], [lname] for the user's full name, first name or last name, respectively.
  • [email] for the user's email.
  • [Site_Name] and [Site_URL] for the Application Name and URL respectively.
", "Accounts_Enrollment_Email_Subject_Default": "Welcome to [Site_Name]", - "Accounts_Admin_Email_Approval_Needed_Default": "

An user with email [email] has been registered.
Please check Administration -> Users to activate or delete it.", + "Accounts_Admin_Email_Approval_Needed_Default": "

The user [name] ([email]) has been registered.

Reason: [reason]

Please check Administration -> Users to activate or delete it.

", "Accounts_Admin_Email_Approval_Needed_Subject_Default": "A new user registered and needs approval", "Accounts_ForgetUserSessionOnWindowClose": "Forget user session on window close", "Accounts_Iframe_api_method": "Api Method", diff --git a/packages/rocketchat-lib/lib/placeholders.js b/packages/rocketchat-lib/lib/placeholders.js index 82fb613d050a..26eca737afdf 100644 --- a/packages/rocketchat-lib/lib/placeholders.js +++ b/packages/rocketchat-lib/lib/placeholders.js @@ -14,6 +14,7 @@ RocketChat.placeholders.replace = function(str, data) { str = str.replace(/\[lname\]/g, _.strRightBack(data.name, ' ') || ''); str = str.replace(/\[email\]/g, data.email || ''); str = str.replace(/\[password\]/g, data.password || ''); + str = str.replace(/\[reason\]/g, data.reason || ''); if (data.unsubscribe) { str = str.replace(/\[unsubscribe\]/g, data.unsubscribe); diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 155e15cc3651..8d69eacb8ba4 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -65,7 +65,7 @@ Accounts.emailTemplates.notifyAdmin.subject = function() { return `[${ siteName }] ${ subject }`; }; -Accounts.emailTemplates.notifyAdmin.html = function(user = {}) { +Accounts.emailTemplates.notifyAdmin.html = function(options = {}) { let html; @@ -75,7 +75,9 @@ Accounts.emailTemplates.notifyAdmin.html = function(user = {}) { const footer = RocketChat.placeholders.replace(RocketChat.settings.get('Email_Footer') || ''); html = RocketChat.placeholders.replace(html, { - email: user.emails[0].address + name: options.name, + email: options.email, + reason: options.reason }); return header + html + footer; @@ -128,7 +130,7 @@ Accounts.onCreateUser(function(options, user = {}) { to: destinations, from: RocketChat.settings.get('From_Email'), subject: Accounts.emailTemplates.notifyAdmin.subject(), - html: Accounts.emailTemplates.notifyAdmin.html(user) + html: Accounts.emailTemplates.notifyAdmin.html(options) }; Meteor.defer(() => { diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index 55c7f79ea945..bd1250188028 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -32,7 +32,9 @@ Meteor.methods({ const userData = { email: s.trim(formData.email.toLowerCase()), - password: formData.pass + password: formData.pass, + name: formData.name, + reason: formData.reason }; // Check if user has already been imported and never logged in. If so, set password and let it through From 87b51d044feca568d800d405367453ba8ca4c740 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 14:56:10 -0300 Subject: [PATCH 037/801] - Added public key to use Accounts_ManuallyApproveNewUsers on frontend --- packages/rocketchat-lib/server/startup/settings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index 1671d5185bee..ab74bc3e7350 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -95,6 +95,7 @@ RocketChat.settings.addGroup('Accounts', function() { } }); this.add('Accounts_ManuallyApproveNewUsers', false, { + 'public': true, type: 'boolean' }); this.add('Accounts_AllowedDomainsList', '', { From 195d56bbee0a6ccd6cd81b3cbcd1de85d9bbf20c Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 15:49:09 -0300 Subject: [PATCH 038/801] - Displaying reason on user info - Reason displayed only if setting is active and user is not active - Added reason to getFullUserData --- .../rocketchat-lib/server/functions/getFullUserData.js | 3 ++- packages/rocketchat-lib/server/models/Users.js | 1 + packages/rocketchat-ui-flextab/client/tabs/userInfo.html | 7 ++++++- packages/rocketchat-ui-flextab/client/tabs/userInfo.js | 5 +++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-lib/server/functions/getFullUserData.js b/packages/rocketchat-lib/server/functions/getFullUserData.js index 0b5290b3b3e8..cbeb1e7f11c6 100644 --- a/packages/rocketchat-lib/server/functions/getFullUserData.js +++ b/packages/rocketchat-lib/server/functions/getFullUserData.js @@ -6,7 +6,8 @@ RocketChat.getFullUserData = function({userId, filter, limit}) { status: 1, utcOffset: 1, type: 1, - active: 1 + active: 1, + reason: 1 }; if (RocketChat.authz.hasPermission(userId, 'view-full-other-user-info')) { diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index a492a5b75f7a..184789c2a1cc 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -9,6 +9,7 @@ class ModelUsers extends RocketChat.models._Base { this.tryEnsureIndex({ 'active': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'statusConnection': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'type': 1 }); + this.tryEnsureIndex({ 'reason': 1 }); this.cache.ensureIndex('username', 'unique'); } diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.html b/packages/rocketchat-ui-flextab/client/tabs/userInfo.html index 4b1dfaffa3c5..6d70b7b581d7 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.html +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.html @@ -26,7 +26,7 @@

{{name}}

{{#if hasPhone}} {{#each phone}}

{{phoneNumber}}

{{/each}} {{/if}} - {{#if lastLogin}}

{{_ "Created_at"}}: {{createdAt}}

{{/if}} + {{#if createdAt}}

{{_ "Created_at"}}: {{createdAt}}

{{/if}} {{#if lastLogin}}

{{_ "Last_login"}}: {{lastLogin}}

{{/if}} {{#if services.facebook.id}}

{{services.facebook.name}}

{{/if}} {{#if services.github.id}}

{{services.github.username}}

{{/if}} @@ -37,6 +37,11 @@

{{name}}

{{#if services.twitter.id}}

{{services.twitter.screenName}}

{{/if}} {{#if services.wordpress.id}}

{{services.wordpress.user_login}}

{{/if}} {{/if}} + {{#if shouldDisplayReason}} +

+ {{_ "Reason_To_Join"}}: {{user.reason}} +

+ {{/if}}
{{/with}} diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index e64f60b0e5fc..ede5cb950e26 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -180,6 +180,11 @@ Template.userInfo.helpers({ isBlocker() { const subscription = ChatSubscription.findOne({rid:Session.get('openedRoom'), 'u._id': Meteor.userId()}, { fields: { blocker: 1 } }); return subscription.blocker; + }, + + shouldDisplayReason() { + const user = Template.instance().user.get(); + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false; } }); From 24f0618a8c4fcf8b28b91306d65b4c418e111291 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 17:45:38 -0300 Subject: [PATCH 039/801] Added logic to remove user reason once user gets activated --- client/methods/unsetUserReason.js | 6 ++++ .../rocketchat-lib/server/models/Users.js | 30 ++++++++++++------- .../client/tabs/userInfo.js | 5 +++- server/methods/unsetUserReason.js | 27 +++++++++++++++++ 4 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 client/methods/unsetUserReason.js create mode 100644 server/methods/unsetUserReason.js diff --git a/client/methods/unsetUserReason.js b/client/methods/unsetUserReason.js new file mode 100644 index 000000000000..245eb587dfbb --- /dev/null +++ b/client/methods/unsetUserReason.js @@ -0,0 +1,6 @@ +Meteor.methods({ + unsetUserReason(userId) { + Meteor.users.update(userId, { $unset: { 'reason' : 1 } }); + return true; + } +}); diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 184789c2a1cc..ce21729643aa 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -314,16 +314,6 @@ class ModelUsers extends RocketChat.models._Base { return this.update(_id, update); } - setReason(_id, reason) { - const update = { - $set: { - reason - } - }; - - return this.update(_id, update); - } - setCustomFields(_id, fields) { const values = {}; Object.keys(fields).reduce(key => { @@ -504,6 +494,26 @@ class ModelUsers extends RocketChat.models._Base { return this.update({ _id }, update); } + setReason(_id, reason) { + const update = { + $set: { + reason + } + }; + + return this.update(_id, update); + } + + unsetReason(_id) { + const update = { + $unset: { + 'reason' : true, + } + }; + + return this.update(_id, update); + } + // INSERT create(data) { const user = { diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index ede5cb950e26..883751232fe7 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -184,7 +184,7 @@ Template.userInfo.helpers({ shouldDisplayReason() { const user = Template.instance().user.get(); - return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false; + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers') && user.active === false && user.reason; } }); @@ -395,6 +395,9 @@ Template.userInfo.events({ if (user) { return Meteor.call('setUserActiveStatus', user._id, true, function(error, result) { if (result) { + + Meteor.call('unsetUserReason', user._id); + toastr.success(t('User_has_been_activated')); } if (error) { diff --git a/server/methods/unsetUserReason.js b/server/methods/unsetUserReason.js new file mode 100644 index 000000000000..b2740a145bf8 --- /dev/null +++ b/server/methods/unsetUserReason.js @@ -0,0 +1,27 @@ +Meteor.methods({ + unsetUserReason(userId) { + check(userId, String); + + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'unsetUserReason' + }); + } + + if (RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-active-status') !== true) { + throw new Meteor.Error('error-not-allowed', 'Not allowed', { + method: 'unsetUserReason' + }); + } + + const user = RocketChat.models.Users.findOneById(userId); + + if (user) { + RocketChat.models.Users.unsetReason(userId); + + return true; + } + + return false; + } +}); From f9d736390832eb69d9870b12696c0ed911441fda Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 00:37:32 -0300 Subject: [PATCH 040/801] - Added error message for invalid reason - Added method to save reason into user object - Added validation to display field but setting Accounts_ManuallyApproveNewUsers is not working :( --- packages/rocketchat-lib/server/models/Users.js | 1 - packages/rocketchat-ui-login/client/login/form.js | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index ce21729643aa..257ae573aa2f 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -9,7 +9,6 @@ class ModelUsers extends RocketChat.models._Base { this.tryEnsureIndex({ 'active': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'statusConnection': 1 }, { sparse: 1 }); this.tryEnsureIndex({ 'type': 1 }); - this.tryEnsureIndex({ 'reason': 1 }); this.cache.ensureIndex('username', 'unique'); } diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index 6f1fee80919f..e5a8746734a5 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -60,7 +60,9 @@ Template.loginForm.helpers({ return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; }, manuallyApproveNewUsers() { - return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); + //TODO verify why it' s not getting this setting + //return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); + return true; } }); From a54af9bff514d141435d6b12d4e3d241ad424133 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sat, 27 May 2017 00:54:16 -0300 Subject: [PATCH 041/801] - Changed to use the correct setting --- packages/rocketchat-ui-login/client/login/form.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/rocketchat-ui-login/client/login/form.js b/packages/rocketchat-ui-login/client/login/form.js index e5a8746734a5..6f1fee80919f 100644 --- a/packages/rocketchat-ui-login/client/login/form.js +++ b/packages/rocketchat-ui-login/client/login/form.js @@ -60,9 +60,7 @@ Template.loginForm.helpers({ return typeof OnePassword !== 'undefined' && OnePassword.findLoginForUrl && typeof device !== 'undefined' && device.platform && device.platform.toLocaleLowerCase() === 'ios'; }, manuallyApproveNewUsers() { - //TODO verify why it' s not getting this setting - //return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); - return true; + return RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); } }); From e04387af1d8f729500f1fbde43291fe9eb4b45dc Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 18:08:20 -0300 Subject: [PATCH 042/801] Removing unneeded comma --- packages/rocketchat-lib/server/models/Users.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-lib/server/models/Users.js b/packages/rocketchat-lib/server/models/Users.js index 257ae573aa2f..7224cd4d2a97 100644 --- a/packages/rocketchat-lib/server/models/Users.js +++ b/packages/rocketchat-lib/server/models/Users.js @@ -506,7 +506,7 @@ class ModelUsers extends RocketChat.models._Base { unsetReason(_id) { const update = { $unset: { - 'reason' : true, + 'reason' : true } }; From 920f928c4f36d677119cba55fd76e361ccf10311 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 20:36:41 -0300 Subject: [PATCH 043/801] Added conditionals to check and use reason field --- server/methods/registerUser.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/server/methods/registerUser.js b/server/methods/registerUser.js index bd1250188028..cfe086c0bc92 100644 --- a/server/methods/registerUser.js +++ b/server/methods/registerUser.js @@ -2,6 +2,7 @@ Meteor.methods({ registerUser(formData) { const AllowAnonymousRead = RocketChat.settings.get('Accounts_AllowAnonymousRead'); const AllowAnonymousWrite = RocketChat.settings.get('Accounts_AllowAnonymousWrite'); + const manuallyApproveNewUsers = RocketChat.settings.get('Accounts_ManuallyApproveNewUsers'); if (AllowAnonymousRead === true && AllowAnonymousWrite === true && formData.email == null) { const userId = Accounts.insertUserDoc({}, { globalRoles: [ @@ -17,9 +18,14 @@ Meteor.methods({ email: String, pass: String, name: String, - reason: String, secretURL: Match.Optional(String) })); + + if (manuallyApproveNewUsers) { + check(formData, Match.ObjectIncluding({ + reason: String + })); + } } if (RocketChat.settings.get('Accounts_RegistrationForm') === 'Disabled') { @@ -33,10 +39,13 @@ Meteor.methods({ const userData = { email: s.trim(formData.email.toLowerCase()), password: formData.pass, - name: formData.name, - reason: formData.reason + name: formData.name }; + if (manuallyApproveNewUsers) { + userData.reason = formData.reason; + } + // Check if user has already been imported and never logged in. If so, set password and let it through const importedUser = RocketChat.models.Users.findOneByEmailAddress(s.trim(formData.email.toLowerCase())); let userId; @@ -48,7 +57,10 @@ Meteor.methods({ } RocketChat.models.Users.setName(userId, s.trim(formData.name)); - RocketChat.models.Users.setReason(userId, s.trim(formData.reason)); + + if (manuallyApproveNewUsers) { + RocketChat.models.Users.setReason(userId, s.trim(formData.reason)); + } RocketChat.saveCustomFields(userId, formData); From 6069e02f0ec5563472aa64db8f6f9d928d5cdfb7 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 21:10:03 -0300 Subject: [PATCH 044/801] Trying to fix user creation tests --- tests/data/user.js | 1 + tests/end-to-end/ui/03-user-creation.js | 4 ++-- tests/pageobjects/login.page.js | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/data/user.js b/tests/data/user.js index 92294f99dfcf..f9d51e8ba46b 100644 --- a/tests/data/user.js +++ b/tests/data/user.js @@ -1,6 +1,7 @@ export const username = `user.test.${ Date.now() }`; export const email = `${ username }@rocket.chat`; export const password = 'rocket.chat'; +export const reason = 'rocket.chat.reason'; export const adminUsername = 'rocketchat.internal.admin.test'; export const adminEmail = `${ adminUsername }@rocket.chat`; diff --git a/tests/end-to-end/ui/03-user-creation.js b/tests/end-to-end/ui/03-user-creation.js index fe93c69caa34..47b4eeb2b812 100644 --- a/tests/end-to-end/ui/03-user-creation.js +++ b/tests/end-to-end/ui/03-user-creation.js @@ -5,7 +5,7 @@ import loginPage from '../../pageobjects/login.page'; import mainContent from '../../pageobjects/main-content.page'; //test data imports -import {username, email, password} from '../../data/user.js'; +import {username, email, password, reason} from '../../data/user.js'; @@ -22,7 +22,7 @@ describe('[User Creation]', function() { it('it should create user', () => { loginPage.gotToRegister(); - loginPage.registerNewUser({username, email, password}); + loginPage.registerNewUser({username, email, password, reason}); loginPage.inputUsername.waitForExist(5000); diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js index e0150d40a15a..15020173df95 100644 --- a/tests/pageobjects/login.page.js +++ b/tests/pageobjects/login.page.js @@ -11,6 +11,7 @@ class LoginPage extends Page { get emailField() { return browser.element('[name=email]'); } get passwordField() { return browser.element('[name=pass]'); } get confirmPasswordField() { return browser.element('[name=confirm-pass]'); } + get reasonField() { return browser.element('[reason]'); } get inputUsername() { return browser.element('form#login-card input#username'); } get emailOrUsernameInvalidText() { return browser.element('[name=emailOrUsername]~.input-error'); } @@ -18,6 +19,7 @@ class LoginPage extends Page { get emailInvalidText() { return browser.element('[name=email]~.input-error'); } get passwordInvalidText() { return browser.element('[name=pass]~.input-error'); } get confirmPasswordInvalidText() { return browser.element('[name=confirm-pass]~.input-error'); } + get reasonInvalidText() { return browser.element('[name=reason]~.input-error'); } get registrationSucceededCard() { return browser.element('#login-card h2'); } open() { @@ -38,12 +40,13 @@ class LoginPage extends Page { this.emailField.waitForVisible(15000); } - registerNewUser({username, email, password}) { + registerNewUser({username, email, password, reason}) { this.nameField.waitForVisible(5000); this.nameField.setValue(username); this.emailField.setValue(email); this.passwordField.setValue(password); this.confirmPasswordField.setValue(password); + this.reasonField.setValue(reason); this.submit(); } From 26c255ed55040d447bed9bc100f684b27603be08 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Sun, 28 May 2017 21:27:33 -0300 Subject: [PATCH 045/801] Trying to fix user creation tests(2) --- tests/pageobjects/login.page.js | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js index 15020173df95..3f03a4c3d80d 100644 --- a/tests/pageobjects/login.page.js +++ b/tests/pageobjects/login.page.js @@ -46,7 +46,6 @@ class LoginPage extends Page { this.emailField.setValue(email); this.passwordField.setValue(password); this.confirmPasswordField.setValue(password); - this.reasonField.setValue(reason); this.submit(); } From 23219cd686c3e2adacfc5c445ffa4ced15bcefca Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Mon, 29 May 2017 23:52:52 -0300 Subject: [PATCH 046/801] Applying last suggestions --- client/methods/unsetUserReason.js | 6 ---- .../client/tabs/userInfo.js | 3 -- server/lib/accounts.js | 31 ++++++++++--------- server/methods/setUserActiveStatus.js | 2 ++ server/methods/unsetUserReason.js | 27 ---------------- 5 files changed, 18 insertions(+), 51 deletions(-) delete mode 100644 client/methods/unsetUserReason.js delete mode 100644 server/methods/unsetUserReason.js diff --git a/client/methods/unsetUserReason.js b/client/methods/unsetUserReason.js deleted file mode 100644 index 245eb587dfbb..000000000000 --- a/client/methods/unsetUserReason.js +++ /dev/null @@ -1,6 +0,0 @@ -Meteor.methods({ - unsetUserReason(userId) { - Meteor.users.update(userId, { $unset: { 'reason' : 1 } }); - return true; - } -}); diff --git a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js index 883751232fe7..cd540249fb0f 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/userInfo.js +++ b/packages/rocketchat-ui-flextab/client/tabs/userInfo.js @@ -395,9 +395,6 @@ Template.userInfo.events({ if (user) { return Meteor.call('setUserActiveStatus', user._id, true, function(error, result) { if (result) { - - Meteor.call('unsetUserReason', user._id); - toastr.success(t('User_has_been_activated')); } if (error) { diff --git a/server/lib/accounts.js b/server/lib/accounts.js index 8d69eacb8ba4..c59ca905cb42 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -119,23 +119,24 @@ Accounts.onCreateUser(function(options, user = {}) { } if (!user.active) { - user.emails.some((email) => { - const destinations = []; + const destinations = []; + let email = {}; - RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { + RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { + if (adminUser.emails[0]) { destinations.push(`${ adminUser.name }<${ adminUser.emails[0].address }>`); - }); - - email = { - to: destinations, - from: RocketChat.settings.get('From_Email'), - subject: Accounts.emailTemplates.notifyAdmin.subject(), - html: Accounts.emailTemplates.notifyAdmin.html(options) - }; - - Meteor.defer(() => { - Email.send(email); - }); + } + }); + + email = { + to: destinations, + from: RocketChat.settings.get('From_Email'), + subject: Accounts.emailTemplates.notifyAdmin.subject(), + html: Accounts.emailTemplates.notifyAdmin.html(options) + }; + + Meteor.defer(() => { + Email.send(email); }); } diff --git a/server/methods/setUserActiveStatus.js b/server/methods/setUserActiveStatus.js index f4a2eea9d1ea..47ad26b2f68f 100644 --- a/server/methods/setUserActiveStatus.js +++ b/server/methods/setUserActiveStatus.js @@ -26,6 +26,8 @@ Meteor.methods({ if (active === false) { RocketChat.models.Users.unsetLoginTokens(userId); + } else { + RocketChat.models.Users.unsetReason(userId); } return true; diff --git a/server/methods/unsetUserReason.js b/server/methods/unsetUserReason.js deleted file mode 100644 index b2740a145bf8..000000000000 --- a/server/methods/unsetUserReason.js +++ /dev/null @@ -1,27 +0,0 @@ -Meteor.methods({ - unsetUserReason(userId) { - check(userId, String); - - if (!Meteor.userId()) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'unsetUserReason' - }); - } - - if (RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-active-status') !== true) { - throw new Meteor.Error('error-not-allowed', 'Not allowed', { - method: 'unsetUserReason' - }); - } - - const user = RocketChat.models.Users.findOneById(userId); - - if (user) { - RocketChat.models.Users.unsetReason(userId); - - return true; - } - - return false; - } -}); From dfff89ed13218db3718af09930476b6d76aeb653 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Tue, 30 May 2017 23:10:17 -0300 Subject: [PATCH 047/801] Moving reason tests to right file --- tests/end-to-end/ui/03-user-creation.js | 2 +- tests/end-to-end/ui/12-settings.js | 1 + tests/pageobjects/login.page.js | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/end-to-end/ui/03-user-creation.js b/tests/end-to-end/ui/03-user-creation.js index 47b4eeb2b812..3076b6cc4fa5 100644 --- a/tests/end-to-end/ui/03-user-creation.js +++ b/tests/end-to-end/ui/03-user-creation.js @@ -22,7 +22,7 @@ describe('[User Creation]', function() { it('it should create user', () => { loginPage.gotToRegister(); - loginPage.registerNewUser({username, email, password, reason}); + loginPage.registerNewUser({username, email, password}); loginPage.inputUsername.waitForExist(5000); diff --git a/tests/end-to-end/ui/12-settings.js b/tests/end-to-end/ui/12-settings.js index 11e9181fd513..f2f22f4aa2b0 100644 --- a/tests/end-to-end/ui/12-settings.js +++ b/tests/end-to-end/ui/12-settings.js @@ -459,6 +459,7 @@ describe('[Api Settings Change]', () => { loginPage.emailField.setValue(`setting${ email }`); loginPage.passwordField.setValue(password); loginPage.confirmPasswordField.setValue(password); + loginPage.reasonField.setValue(password); loginPage.submit(); diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js index 3f03a4c3d80d..6c9ee1862983 100644 --- a/tests/pageobjects/login.page.js +++ b/tests/pageobjects/login.page.js @@ -19,7 +19,6 @@ class LoginPage extends Page { get emailInvalidText() { return browser.element('[name=email]~.input-error'); } get passwordInvalidText() { return browser.element('[name=pass]~.input-error'); } get confirmPasswordInvalidText() { return browser.element('[name=confirm-pass]~.input-error'); } - get reasonInvalidText() { return browser.element('[name=reason]~.input-error'); } get registrationSucceededCard() { return browser.element('#login-card h2'); } open() { @@ -40,7 +39,7 @@ class LoginPage extends Page { this.emailField.waitForVisible(15000); } - registerNewUser({username, email, password, reason}) { + registerNewUser({username, email, password}) { this.nameField.waitForVisible(5000); this.nameField.setValue(username); this.emailField.setValue(email); From 128116db92a2ea75e48d1e153e99993388ff9a50 Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Tue, 30 May 2017 23:20:54 -0300 Subject: [PATCH 048/801] Moving reason tests to right file (2) --- tests/end-to-end/ui/03-user-creation.js | 2 +- tests/end-to-end/ui/12-settings.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/end-to-end/ui/03-user-creation.js b/tests/end-to-end/ui/03-user-creation.js index 3076b6cc4fa5..fe93c69caa34 100644 --- a/tests/end-to-end/ui/03-user-creation.js +++ b/tests/end-to-end/ui/03-user-creation.js @@ -5,7 +5,7 @@ import loginPage from '../../pageobjects/login.page'; import mainContent from '../../pageobjects/main-content.page'; //test data imports -import {username, email, password, reason} from '../../data/user.js'; +import {username, email, password} from '../../data/user.js'; diff --git a/tests/end-to-end/ui/12-settings.js b/tests/end-to-end/ui/12-settings.js index f2f22f4aa2b0..5f49dbafde6d 100644 --- a/tests/end-to-end/ui/12-settings.js +++ b/tests/end-to-end/ui/12-settings.js @@ -16,7 +16,7 @@ import admin from '../../pageobjects/administration.page'; import {checkIfUserIsValid, checkIfUserIsAdmin} from '../../data/checks'; import {targetUser, imgURL} from '../../data/interactions.js'; -import {adminUsername, adminEmail, adminPassword, username, email, password} from '../../data/user.js'; +import {adminUsername, adminEmail, adminPassword, username, email, password, reason} from '../../data/user.js'; function api(path) { return prefix + path; @@ -459,7 +459,7 @@ describe('[Api Settings Change]', () => { loginPage.emailField.setValue(`setting${ email }`); loginPage.passwordField.setValue(password); loginPage.confirmPasswordField.setValue(password); - loginPage.reasonField.setValue(password); + loginPage.reasonField.setValue(reason); loginPage.submit(); From 645943abe0d556742e055df9858061fa13fe832a Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Wed, 31 May 2017 00:16:29 -0300 Subject: [PATCH 049/801] Fixing test where field was not found --- tests/pageobjects/login.page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pageobjects/login.page.js b/tests/pageobjects/login.page.js index 6c9ee1862983..d049f31c9cac 100644 --- a/tests/pageobjects/login.page.js +++ b/tests/pageobjects/login.page.js @@ -11,7 +11,7 @@ class LoginPage extends Page { get emailField() { return browser.element('[name=email]'); } get passwordField() { return browser.element('[name=pass]'); } get confirmPasswordField() { return browser.element('[name=confirm-pass]'); } - get reasonField() { return browser.element('[reason]'); } + get reasonField() { return browser.element('[name=reason]'); } get inputUsername() { return browser.element('form#login-card input#username'); } get emailOrUsernameInvalidText() { return browser.element('[name=emailOrUsername]~.input-error'); } From d5f141b5f71aef49d8a50165bfc752e7525991aa Mon Sep 17 00:00:00 2001 From: Luis Fernando do Nascimento Date: Thu, 1 Jun 2017 00:27:54 -0300 Subject: [PATCH 050/801] Rebasing with develop and applied code suggestion --- server/lib/accounts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/lib/accounts.js b/server/lib/accounts.js index c59ca905cb42..d3b0045ce2c8 100644 --- a/server/lib/accounts.js +++ b/server/lib/accounts.js @@ -123,7 +123,7 @@ Accounts.onCreateUser(function(options, user = {}) { let email = {}; RocketChat.models.Roles.findUsersInRole('admin').forEach(function(adminUser) { - if (adminUser.emails[0]) { + if (adminUser.emails && adminUser.emails[0] && adminUser.emails[0].address) { destinations.push(`${ adminUser.name }<${ adminUser.emails[0].address }>`); } }); From 1b564f409835b73af8ffbafc8afccbfba6d24e02 Mon Sep 17 00:00:00 2001 From: Martin Schoeler Date: Fri, 2 Jun 2017 11:28:51 -0300 Subject: [PATCH 051/801] Fix the tests --- tests/end-to-end/ui/12-settings.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/end-to-end/ui/12-settings.js b/tests/end-to-end/ui/12-settings.js index 5f49dbafde6d..667b749718ec 100644 --- a/tests/end-to-end/ui/12-settings.js +++ b/tests/end-to-end/ui/12-settings.js @@ -452,6 +452,7 @@ describe('[Api Settings Change]', () => { }); it('register the user', () => { + browser.refresh(); loginPage.registerButton.waitForVisible(5000); loginPage.registerButton.click(); loginPage.nameField.waitForVisible(5000); @@ -459,6 +460,7 @@ describe('[Api Settings Change]', () => { loginPage.emailField.setValue(`setting${ email }`); loginPage.passwordField.setValue(password); loginPage.confirmPasswordField.setValue(password); + loginPage.reasonField.waitForVisible(5000) loginPage.reasonField.setValue(reason); loginPage.submit(); From 244cb4cd73b34e4747bef4a8850014ee8aa800bf Mon Sep 17 00:00:00 2001 From: Martin Schoeler Date: Fri, 2 Jun 2017 11:38:24 -0300 Subject: [PATCH 052/801] fix error --- tests/end-to-end/ui/12-settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/end-to-end/ui/12-settings.js b/tests/end-to-end/ui/12-settings.js index 667b749718ec..8eba2c5da2a4 100644 --- a/tests/end-to-end/ui/12-settings.js +++ b/tests/end-to-end/ui/12-settings.js @@ -460,7 +460,7 @@ describe('[Api Settings Change]', () => { loginPage.emailField.setValue(`setting${ email }`); loginPage.passwordField.setValue(password); loginPage.confirmPasswordField.setValue(password); - loginPage.reasonField.waitForVisible(5000) + loginPage.reasonField.waitForVisible(5000); loginPage.reasonField.setValue(reason); loginPage.submit(); From 472ba850f4ca76be61c7cc12df453641fc979f94 Mon Sep 17 00:00:00 2001 From: Nishchal Gautam Date: Sat, 17 Jun 2017 09:58:20 +0700 Subject: [PATCH 053/801] feat: add global search while searching message closes # 1615 --- .../client/tabs/messageSearch.js | 16 +++++++++--- server/methods/messageSearch.js | 25 +++++++++++-------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js b/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js index e62719d4d32d..41f225c0a45b 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js +++ b/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js @@ -8,8 +8,16 @@ Meteor.startup(function() { ], action() { const message = this._arguments[1]; + if (Session.get('openedRoom') === message.rid) { + return RoomHistoryManager.getSurroundingMessages(message, 50); + } + FlowRouter.goToRoomById(message.rid); RocketChat.MessageAction.hideDropDown(); - return RoomHistoryManager.getSurroundingMessages(message, 50); + window.setTimeout(() => { + RoomHistoryManager.getSurroundingMessages(message, 50); + }, 400); + // 400ms is popular among game devs as a good delay before transition starts + // ie. 50, 100, 200, 400, 800 are the favored timings }, order: 100 }); @@ -65,7 +73,7 @@ Template.messageSearch.events({ t.hasMore.set(true); t.limit.set(20); - return t.search(); + return t.search(true); } , 500), @@ -108,11 +116,11 @@ Template.messageSearch.onCreated(function() { this.limit = new ReactiveVar(20); this.ready = new ReactiveVar(true); - return this.search = () => { + return this.search = (globalSearch = false) => { this.ready.set(false); const value = this.$('#message-search').val(); return Tracker.nonreactive(() => { - return Meteor.call('messageSearch', value, Session.get('openedRoom'), this.limit.get(), (error, result) => { + return Meteor.call('messageSearch', value, (globalSearch) ? undefined: Session.get('openedRoom'), this.limit.get(), (error, result) => { this.currentSearchTerm.set(value); this.ready.set(true); if ((result != null) && (((result.messages != null ? result.messages.length : undefined) > 0) || ((result.users != null ? result.users.length : undefined) > 0) || ((result.channels != null ? result.channels.length : undefined) > 0))) { diff --git a/server/methods/messageSearch.js b/server/methods/messageSearch.js index 69d130fa564d..5a04b540cb91 100644 --- a/server/methods/messageSearch.js +++ b/server/methods/messageSearch.js @@ -14,7 +14,7 @@ Meteor.methods({ }; check(text, String); - check(rid, String); + check(rid, Match.Maybe(String)); check(limit, Match.Optional(Number)); const currentUserId = Meteor.userId(); @@ -182,17 +182,22 @@ Meteor.methods({ query._hidden = { $ne: true // don't return _hidden messages }; - if (rid != null) { + if (rid) { query.rid = rid; - if (Meteor.call('canAccessRoom', rid, currentUserId) !== false) { - if (!RocketChat.settings.get('Message_ShowEditedStatus')) { - options.fields = { - 'editedAt': 0 - }; - } - result.messages = RocketChat.models.Messages.find(query, options).fetch(); - } + // check if user can access rid room + } else { + query.rid = { + $in : RocketChat.models.Rooms.findByContainingUsername(currentUserName) + .fetch() + .map(room => room._id) + }; + } + if (!RocketChat.settings.get('Message_ShowEditedStatus')) { + options.fields = { + 'editedAt': 0 + }; } + result.messages = RocketChat.models.Messages.find(query, options).fetch(); } return result; From 83dc18473e3f2bcdd49fa6655e82c26b00471895 Mon Sep 17 00:00:00 2001 From: Nishchal Gautam Date: Sat, 17 Jun 2017 10:08:25 +0700 Subject: [PATCH 054/801] check user permission to access the room --- server/methods/messageSearch.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/methods/messageSearch.js b/server/methods/messageSearch.js index 5a04b540cb91..6acd7f7671b6 100644 --- a/server/methods/messageSearch.js +++ b/server/methods/messageSearch.js @@ -185,6 +185,9 @@ Meteor.methods({ if (rid) { query.rid = rid; // check if user can access rid room + if (Meteor.call('canAccessRoom', rid, currentUserId) !== false) { + return result; + } } else { query.rid = { $in : RocketChat.models.Rooms.findByContainingUsername(currentUserName) From 5b7594f606f49b3d11fece8db791d31667043934 Mon Sep 17 00:00:00 2001 From: Thomas Clayton Date: Tue, 1 Aug 2017 20:12:37 +0300 Subject: [PATCH 055/801] add translations for global search --- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-i18n/i18n/fi.i18n.json | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 8f89a01f3d01..12c5338cf6e1 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -641,6 +641,7 @@ "Give_a_unique_name_for_the_custom_oauth": "Give a unique name for the custom oauth", "Give_the_application_a_name_This_will_be_seen_by_your_users": "Give the application a name. This will be seen by your users.", "Global": "Global", + "Global_Search": "Global search", "GoogleCloudStorage": "Google Cloud Storage", "GoogleNaturalLanguage_ServiceAccount_Description": "Service account key JSON file. More information can be found [here](https://cloud.google.com/natural-language/docs/common/auth#set_up_a_service_account)", "GoogleTagManager_id": "Google Tag Manager Id", diff --git a/packages/rocketchat-i18n/i18n/fi.i18n.json b/packages/rocketchat-i18n/i18n/fi.i18n.json index 8dffc605cc79..ab600d9a5f9c 100644 --- a/packages/rocketchat-i18n/i18n/fi.i18n.json +++ b/packages/rocketchat-i18n/i18n/fi.i18n.json @@ -466,6 +466,7 @@ "Give_a_unique_name_for_the_custom_oauth": "Anna yksilöllinen nimi mukautettua oauth varten", "Give_the_application_a_name_This_will_be_seen_by_your_users": "Anna sovelluksen nimi. Käyttäjät näkevät tämän.", "Global": "Yleinen", + "Global_Search": "Hae kaikilta kanavilta", "GoogleTagManager_id": "Google Tag Manager Id", "Guest_Pool": "Vieraspooli", "Hash": "Hash", From e5e0e8e46d420dd4a99180c0aece6f10f47244ed Mon Sep 17 00:00:00 2001 From: Tommi Savikko Date: Tue, 1 Aug 2017 22:18:13 +0300 Subject: [PATCH 056/801] add channel names to search results --- .../client/tabs/messageSearch.html | 1 + .../client/tabs/messageSearch.js | 21 +++++++++---------- .../rocketchat-ui-message/client/message.html | 5 +++++ .../rocketchat-ui-message/client/message.js | 9 ++++++++ 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/packages/rocketchat-ui-flextab/client/tabs/messageSearch.html b/packages/rocketchat-ui-flextab/client/tabs/messageSearch.html index 6d5dea5c72db..fec79ce64d67 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/messageSearch.html +++ b/packages/rocketchat-ui-flextab/client/tabs/messageSearch.html @@ -9,6 +9,7 @@

{{_ "Search_Messages"}}

diff --git a/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js b/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js index ceb7cb291655..29bcb451a468 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js +++ b/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js @@ -16,7 +16,11 @@ Meteor.startup(function() { if (window.matchMedia('(max-width: 500px)').matches) { Template.instance().tabBar.close(); } - return RoomHistoryManager.getSurroundingMessages(message, 50); + window.setTimeout(() => { + RoomHistoryManager.getSurroundingMessages(message, 50); + }, 400); + // 400ms is popular among game devs as a good delay before transition starts + // ie. 50, 100, 200, 400, 800 are the favored timings }, order: 100 }); @@ -50,6 +54,7 @@ Template.messageSearch.helpers({ message() { return _.extend(this, { customClass: 'search' }); } + }); Template.messageSearch.events({ @@ -69,17 +74,12 @@ Template.messageSearch.events({ } else if (value === t.currentSearchTerm.get()) { return; } - + const globalSearch = $('#global-search').is(':checked'); t.hasMore.set(true); t.limit.set(20); -<<<<<<< HEAD - return t.search(true); + return t.search(globalSearch); } , 500), -======= - return t.search(); - }, 500), ->>>>>>> 00fd6a8bf3b911055d1f53629d56baab01bfca10 'click .message-cog'(e, t) { e.stopPropagation(); @@ -113,8 +113,7 @@ Template.messageSearch.events({ Template.messageSearch.onCreated(function() { this.currentSearchTerm = new ReactiveVar(''); - this.searchResult = new ReactiveVar; - + this.searchResult = new ReactiveVar(); this.hasMore = new ReactiveVar(true); this.limit = new ReactiveVar(20); this.ready = new ReactiveVar(true); @@ -126,7 +125,7 @@ Template.messageSearch.onCreated(function() { return Meteor.call('messageSearch', value, (globalSearch) ? undefined: Session.get('openedRoom'), this.limit.get(), (error, result) => { this.currentSearchTerm.set(value); this.ready.set(true); - if ((result != null) && (((result.messages != null ? result.messages.length : undefined) > 0) || ((result.users != null ? result.users.length : undefined) > 0) || ((result.channels != null ? result.channels.length : undefined) > 0))) { + if ((result != null) && (((result.messages !== null ? result.messages.length : undefined) > 0) || ((result.users != null ? result.users.length : undefined) > 0) || ((result.channels != null ? result.channels.length : undefined) > 0))) { this.searchResult.set(result); if (((result.messages != null ? result.messages.length : undefined) + (result.users != null ? result.users.length : undefined) + (result.channels != null ? result.channels.length : undefined)) < this.limit.get()) { return this.hasMore.set(false); diff --git a/packages/rocketchat-ui-message/client/message.html b/packages/rocketchat-ui-message/client/message.html index 3a02fa4d14b6..b214930a4c54 100644 --- a/packages/rocketchat-ui-message/client/message.html +++ b/packages/rocketchat-ui-message/client/message.html @@ -22,6 +22,11 @@ {{/if}} {{/if}} + {{#if fromSearch}} + + {{channelName}} + + {{/if}} {{#each roleTags}} {{description}} diff --git a/packages/rocketchat-ui-message/client/message.js b/packages/rocketchat-ui-message/client/message.js index 40def8559037..6d8658f3eea0 100644 --- a/packages/rocketchat-ui-message/client/message.js +++ b/packages/rocketchat-ui-message/client/message.js @@ -264,6 +264,15 @@ Template.message.helpers({ if (subscription == null) { return 'hidden'; } + }, + channelName() { + return Session.get(`roomData${ this.rid }`).name; + }, + roomIcon() { + return RocketChat.roomTypes.getIcon(Session.get(`roomData${ this.rid }`).t); + }, + fromSearch() { + return (this.customClass==='search'); } }); From da26796a28f794ccf9fffe3d1060ffe48409ed87 Mon Sep 17 00:00:00 2001 From: Tommi Savikko Date: Tue, 1 Aug 2017 22:27:14 +0300 Subject: [PATCH 057/801] fix eslint --- .../client/tabs/messageSearch.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js b/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js index 29bcb451a468..0fc3d236ecec 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js +++ b/packages/rocketchat-ui-flextab/client/tabs/messageSearch.js @@ -17,10 +17,10 @@ Meteor.startup(function() { Template.instance().tabBar.close(); } window.setTimeout(() => { - RoomHistoryManager.getSurroundingMessages(message, 50); - }, 400); - // 400ms is popular among game devs as a good delay before transition starts - // ie. 50, 100, 200, 400, 800 are the favored timings + RoomHistoryManager.getSurroundingMessages(message, 50); + }, 400); + // 400ms is popular among game devs as a good delay before transition starts + // ie. 50, 100, 200, 400, 800 are the favored timings }, order: 100 }); @@ -78,8 +78,7 @@ Template.messageSearch.events({ t.hasMore.set(true); t.limit.set(20); return t.search(globalSearch); - } - , 500), + }, 500), 'click .message-cog'(e, t) { e.stopPropagation(); From 7e36607ed2ca641a371519e13097577c13d4947a Mon Sep 17 00:00:00 2001 From: Tommi Savikko Date: Sun, 13 Aug 2017 19:14:54 +0300 Subject: [PATCH 058/801] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a1de201ca5ae..224f0dc2cb33 100644 --- a/README.md +++ b/README.md @@ -267,6 +267,7 @@ It is a great solution for communities and companies wanting to privately host t - File Upload / Sharing - Scalable file sharing - S3 uploads with CDN downloads - Full text search +- Global search (from all channels/rooms at once) - Live chat / Messaging call center - LDAP Authentication - CAS 1.0, 2.0 support for education institutions and hosting providers worldwide From 2678365dfeab99f8bde4dbc1a2cb7d12e7a20aa0 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Tue, 15 Aug 2017 19:10:33 -0500 Subject: [PATCH 059/801] Rocketlets: Initial structure for the rocketlets package inside of Rocket.Chat. --- .eslintrc | 1 + .meteor/packages | 1 + .meteor/versions | 1 + packages/rocketchat-api/package.js | 1 + packages/rocketchat-api/server/api.js | 6 +- packages/rocketchat-api/server/v1/commands.js | 85 +++++++++++++++++++ packages/rocketchat-lib/lib/slashCommand.js | 1 + packages/rocketchat-rocketlets/.gitignore | 1 + .../client/communication/websockets.js | 12 +++ .../rocketchat-rocketlets/lib/Rocketlets.js | 2 + packages/rocketchat-rocketlets/package.js | 41 +++++++++ .../server/bridges/commands.js | 84 ++++++++++++++++++ .../server/bridges/index.js | 3 + .../server/communication/index.js | 5 ++ .../server/communication/rest.js | 8 ++ .../server/communication/websockets.js | 16 ++++ .../server/converters/index.js | 9 ++ .../server/converters/messages.js | 21 +++++ .../server/converters/rooms.js | 13 +++ .../server/converters/users.js | 13 +++ .../server/models/Rocketlets.js | 5 ++ .../server/orchestrator.js | 42 +++++++++ .../server.js | 5 +- .../rocketchat-slashcommands-create/server.js | 5 +- .../rocketchat-slashcommands-help/server.js | 2 + .../rocketchat-slashcommands-invite/server.js | 7 +- .../server.js | 10 ++- .../rocketchat-slashcommands-join/server.js | 3 + .../rocketchat-slashcommands-kick/server.js | 5 +- .../rocketchat-slashcommands-leave/leave.js | 15 +--- 30 files changed, 403 insertions(+), 20 deletions(-) create mode 100644 packages/rocketchat-api/server/v1/commands.js create mode 100644 packages/rocketchat-rocketlets/.gitignore create mode 100644 packages/rocketchat-rocketlets/client/communication/websockets.js create mode 100644 packages/rocketchat-rocketlets/lib/Rocketlets.js create mode 100644 packages/rocketchat-rocketlets/package.js create mode 100644 packages/rocketchat-rocketlets/server/bridges/commands.js create mode 100644 packages/rocketchat-rocketlets/server/bridges/index.js create mode 100644 packages/rocketchat-rocketlets/server/communication/index.js create mode 100644 packages/rocketchat-rocketlets/server/communication/rest.js create mode 100644 packages/rocketchat-rocketlets/server/communication/websockets.js create mode 100644 packages/rocketchat-rocketlets/server/converters/index.js create mode 100644 packages/rocketchat-rocketlets/server/converters/messages.js create mode 100644 packages/rocketchat-rocketlets/server/converters/rooms.js create mode 100644 packages/rocketchat-rocketlets/server/converters/users.js create mode 100644 packages/rocketchat-rocketlets/server/models/Rocketlets.js create mode 100644 packages/rocketchat-rocketlets/server/orchestrator.js diff --git a/.eslintrc b/.eslintrc index 6e652c53b845..df4bec84696c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -133,6 +133,7 @@ "ReactiveVar" : false, "RocketChat" : true, "RocketChatFile" : false, + "Rocketlets" : false, "RoomHistoryManager" : false, "RoomManager" : false, "s" : false, diff --git a/.meteor/packages b/.meteor/packages index 16aacf8c6ca3..cc549ff64a58 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -93,6 +93,7 @@ rocketchat:oembed rocketchat:otr rocketchat:push-notifications rocketchat:reactions +rocketchat:rocketlets rocketchat:sandstorm rocketchat:slackbridge rocketchat:slashcommands-archive diff --git a/.meteor/versions b/.meteor/versions index 08ec0c6b51f0..76740ca513da 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -185,6 +185,7 @@ rocketchat:otr@0.0.1 rocketchat:postcss@1.0.0 rocketchat:push-notifications@0.0.1 rocketchat:reactions@0.0.1 +rocketchat:rocketlets@1.0.0 rocketchat:sandstorm@0.0.1 rocketchat:slackbridge@0.0.1 rocketchat:slashcommands-archive@0.0.1 diff --git a/packages/rocketchat-api/package.js b/packages/rocketchat-api/package.js index 16d34b948044..9068cdeac457 100644 --- a/packages/rocketchat-api/package.js +++ b/packages/rocketchat-api/package.js @@ -34,6 +34,7 @@ Package.onUse(function(api) { //Add v1 routes api.addFiles('server/v1/channels.js', 'server'); api.addFiles('server/v1/chat.js', 'server'); + api.addFiles('server/v1/commands.js', 'server'); api.addFiles('server/v1/groups.js', 'server'); api.addFiles('server/v1/im.js', 'server'); api.addFiles('server/v1/integrations.js', 'server'); diff --git a/packages/rocketchat-api/server/api.js b/packages/rocketchat-api/server/api.js index a8ee3da879d6..033e3d679861 100644 --- a/packages/rocketchat-api/server/api.js +++ b/packages/rocketchat-api/server/api.js @@ -125,7 +125,6 @@ class API extends Restivus { } } -RocketChat.API = {}; const getUserAuth = function _getUserAuth() { const invalidResults = [undefined, null, false]; @@ -160,6 +159,11 @@ const getUserAuth = function _getUserAuth() { }; }; +RocketChat.API = { + getUserAuth, + ApiClass: API +}; + RocketChat.API.v1 = new API({ version: 'v1', useDefaultAuth: true, diff --git a/packages/rocketchat-api/server/v1/commands.js b/packages/rocketchat-api/server/v1/commands.js new file mode 100644 index 000000000000..eeda89444260 --- /dev/null +++ b/packages/rocketchat-api/server/v1/commands.js @@ -0,0 +1,85 @@ +RocketChat.API.v1.addRoute('commands.getOne', { authRequired: true }, { + get() { + const params = this.queryParams; + + if (typeof params.command !== 'string') { + return RocketChat.API.v1.failure('The query param "command" must be provided.'); + } + + const cmd = RocketChat.slashCommands.commands[params.command.toLowerCase()]; + + if (!cmd) { + return RocketChat.API.v1.failure(`There is no command in the system by the name of: ${ params.command }`); + } + + return RocketChat.API.v1.success({ command: cmd }); + } +}); + +RocketChat.API.v1.addRoute('commands.list', { authRequired: true }, { + get() { + const { offset, count } = this.getPaginationItems(); + const { sort, fields, query } = this.parseJsonQuery(); + + let commands = Object.values(RocketChat.slashCommands.commands); + + if (query.command) { + commands = commands.filter((command) => command.command === query.command); + } + + const totalCount = commands.length; + commands = RocketChat.models.Rooms.processQueryOptionsOnResult(commands, { + sort: sort ? sort : { name: 1 }, + skip: offset, + limit: count, + fields: Object.assign({}, fields, RocketChat.API.v1.defaultFieldsToExclude) + }); + + return RocketChat.API.v1.success({ + commands, + offset, + count: commands.length, + total: totalCount + }); + } +}); + +// Expects a body of: { command: 'gimme', params: 'any string value', roomId: 'value' } +RocketChat.API.v1.addRoute('commands.run', { authRequired: true }, { + post() { + const body = this.bodyParams; + const user = this.getLoggedInUser(); + + if (typeof body.command !== 'string') { + return RocketChat.API.v1.failure('You must provide a command to run.'); + } + + if (body.params && typeof body.params !== 'string') { + return RocketChat.API.v1.failure('The parameters for the command must be a single string.'); + } + const params = body.params ? body.params : ''; + + if (typeof body.roomId !== 'string') { + return RocketChat.API.v1.failure('The room\'s id where to execute this command must provided and be a string.'); + } + + const cmd = body.command.toLowerCase(); + if (!RocketChat.slashCommands.commands[body.command.toLowerCase()]) { + return RocketChat.API.v1.failure('The command provided does not exist (or is disabled).'); + } + + // This will throw an error if they can't or the room is invalid + Meteor.call('canAccessRoom', body.roomId, user._id); + + let result; + Meteor.runAsUser(user._id, () => { + result = RocketChat.slashCommands.run(cmd, params, { + _id: Random.id(), + rid: body.roomId, + msg: `/${ cmd } ${ params }` + }); + }); + + return RocketChat.API.v1.success({ result }); + } +}); diff --git a/packages/rocketchat-lib/lib/slashCommand.js b/packages/rocketchat-lib/lib/slashCommand.js index 0a07065a15dc..7f37a7933adc 100644 --- a/packages/rocketchat-lib/lib/slashCommand.js +++ b/packages/rocketchat-lib/lib/slashCommand.js @@ -26,6 +26,7 @@ Meteor.methods({ method: 'slashCommand' }); } + return RocketChat.slashCommands.run(command.cmd, command.params, command.msg); } }); diff --git a/packages/rocketchat-rocketlets/.gitignore b/packages/rocketchat-rocketlets/.gitignore new file mode 100644 index 000000000000..918ef5d781a1 --- /dev/null +++ b/packages/rocketchat-rocketlets/.gitignore @@ -0,0 +1 @@ +.npm diff --git a/packages/rocketchat-rocketlets/client/communication/websockets.js b/packages/rocketchat-rocketlets/client/communication/websockets.js new file mode 100644 index 000000000000..2a783649a3b6 --- /dev/null +++ b/packages/rocketchat-rocketlets/client/communication/websockets.js @@ -0,0 +1,12 @@ +export class RocketletWebsocketReceiver { + constructor(restApi) { + this.rest = restApi; + this.streamer = new Meteor.Streamer('rocketlets'); + + this.streamer.on('command/added', this.onCommandAdded); + } + + onCommandAdded(command) { + console.log('Added:', command); + } +} diff --git a/packages/rocketchat-rocketlets/lib/Rocketlets.js b/packages/rocketchat-rocketlets/lib/Rocketlets.js new file mode 100644 index 000000000000..44fa4fc44330 --- /dev/null +++ b/packages/rocketchat-rocketlets/lib/Rocketlets.js @@ -0,0 +1,2 @@ +// Please see both server and client's repsective "orchestrator" file for the contents +Rocketlets = {}; diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js new file mode 100644 index 000000000000..127b469b9e53 --- /dev/null +++ b/packages/rocketchat-rocketlets/package.js @@ -0,0 +1,41 @@ +Package.describe({ + name: 'rocketchat:rocketlets', + version: '1.0.0' +}); + +Package.onUse(function(api) { + api.use([ + 'ecmascript', + 'rocketchat:lib', + 'rocketchat:api' + ]); + + api.addFiles('lib/Rocketlets.js', ['client', 'server']); + + api.addFiles('server/orchestrator.js', 'server'); + + api.addFiles('server/models/Rocketlets.js', 'server'); + + // Bridges + api.addFiles([ + 'server/bridges/commands.js' + ], 'server'); + + // Communication pieces + api.addFiles([ + 'server/communication/rest.js', + 'server/communication/websockets.js' + ], 'server'); + + // Client communication pieces + api.addFiles([ + 'client/communication/websockets.js' + ], 'client'); + + api.export('Rocketlets'); +}); + +Npm.depends({ + 'temporary-rocketlets-server': '0.1.11', + 'temporary-rocketlets-ts-definition': '0.6.2' +}); diff --git a/packages/rocketchat-rocketlets/server/bridges/commands.js b/packages/rocketchat-rocketlets/server/bridges/commands.js new file mode 100644 index 000000000000..99169f96c5f2 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/commands.js @@ -0,0 +1,84 @@ +export class RocketletCommandsBridge { + constructor(converters) { + console.log('CommandsBridge constructor'); + this.converters = converters; + this.disabledCommands = new Map(); + } + + doesCommandExist(command, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is check if "${ command }" command exists.`); + + if (typeof command !== 'string') { + return false; + } + + return typeof RocketChat.slashCommands.commands[command.toLowerCase()] === 'object'; + } + + disableCommand(command, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is attempting to disable the command: "${ command }"`); + + if (typeof command !== 'string' || command.trim().length === 0) { + throw new Error('Invalid command parameter provided, must be a string.'); + } + + const cmd = command.toLowerCase(); + if (typeof RocketChat.slashCommands.commands[cmd] === 'undefined') { + throw new Error(`Command does not exist in the system currently (or it is disabled): ${ cmd }`); + } + + this.disabledCommands.set(cmd, RocketChat.slashCommands.commands[cmd]); + delete RocketChat.slashCommands.commands[cmd]; + + Rocketlets.getNotifier().commandDisabled(cmd); + } + + // command: { command, paramsExample, i18nDescription, executor: function } + modifyCommand(command, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is attempting to modify the command: "${ command }"`); + + this._verifyCommand(command); + + const cmd = command.toLowerCase(); + if (typeof RocketChat.slashCommands.commands[cmd] === 'undefined') { + throw new Error(`Command does not exist in the system currently (or it is disabled): ${ cmd }`); + } + + const item = RocketChat.slashCommands.commands[cmd]; + item.params = command.paramsExample ? command.paramsExample : item.params; + item.description = command.i18nDescription ? command.i18nDescription : item.params; + item.callback = this._executorWrapper(command.executor); + + } + + _verifyCommand(command) { + if (typeof command !== 'object') { + throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); + } + + if (typeof command.command !== 'string') { + throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); + } + + if (command.paramsExample && typeof command.paramsExample !== 'string') { + throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); + } + + if (command.i18nDescription && typeof command.i18nDescription !== 'string') { + throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); + } + + if (typeof command.executor !== 'function') { + throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); + } + } + + _executorWrapper(executor) { + return function _wrappedExecutor(command, params, message) { + // TODO: Converters + this.converters.get('messages').translate(message); + + executor(command); + }; + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/index.js b/packages/rocketchat-rocketlets/server/bridges/index.js new file mode 100644 index 000000000000..82cad72f3770 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/index.js @@ -0,0 +1,3 @@ +import { RocketletCommandsBridge } from './commands'; + +export { RocketletCommandsBridge }; diff --git a/packages/rocketchat-rocketlets/server/communication/index.js b/packages/rocketchat-rocketlets/server/communication/index.js new file mode 100644 index 000000000000..8781d1737c41 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/communication/index.js @@ -0,0 +1,5 @@ +import { RocketletWebsocketNotifier } from './websockets'; + +export { + RocketletWebsocketNotifier +}; diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js new file mode 100644 index 000000000000..c463e1e60c7a --- /dev/null +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -0,0 +1,8 @@ +/* Rocketlets.API = new RocketChat.API.ApiClass({ + version: 'rocketlets', + useDefaultAuth: true, + prettyJson: true, + enableCors: false, + auth: RocketChat.API.getUserAuth() +}); +*/ diff --git a/packages/rocketchat-rocketlets/server/communication/websockets.js b/packages/rocketchat-rocketlets/server/communication/websockets.js new file mode 100644 index 000000000000..8fda659d65c8 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/communication/websockets.js @@ -0,0 +1,16 @@ +export class RocketletWebsocketNotifier { + constructor() { + this.streamer = new Meteor.Streamer('rocketlets', { retransmit: false }); + this.streamer.allowRead('all'); + this.streamer.allowEmit('all'); + this.streamer.allowWrite('none'); + } + + commandAdded(command) { + this.streamer.emit('command/added', command); + } + + commandDisabled(command) { + this.streamer.emit('command/disabled', command); + } +} diff --git a/packages/rocketchat-rocketlets/server/converters/index.js b/packages/rocketchat-rocketlets/server/converters/index.js new file mode 100644 index 000000000000..2a402be1b351 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/converters/index.js @@ -0,0 +1,9 @@ +import { RocketletMessagesConverter } from './messages'; +import { RocketletRoomsConverter } from './rooms'; +import { RocketletUsersConverter } from './users'; + +export { + RocketletMessagesConverter, + RocketletRoomsConverter, + RocketletUsersConverter +}; diff --git a/packages/rocketchat-rocketlets/server/converters/messages.js b/packages/rocketchat-rocketlets/server/converters/messages.js new file mode 100644 index 000000000000..80a745a0ea74 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/converters/messages.js @@ -0,0 +1,21 @@ +export class RocketletMessagesConverter { + constructor(converters) { + this.converters = converters; + } + + convertById(msgId) { + const msg = RocketChat.models.Messages.getOneById(msgId); + + return { + id: msg._id, + text: msg.msg + }; + } + + convertMessage(msgObj) { + return { + id: msgObj._id, + text: msgObj.msg + }; + } +} diff --git a/packages/rocketchat-rocketlets/server/converters/rooms.js b/packages/rocketchat-rocketlets/server/converters/rooms.js new file mode 100644 index 000000000000..23481dda5ef1 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/converters/rooms.js @@ -0,0 +1,13 @@ +export class RocketletRoomsConverter { + constructor(converters) { + this.converters = converters; + } + + convertById(roomId) { + const room = RocketChat.models.Rooms.findOneById(roomId); + + return { + id: room._id + }; + } +} diff --git a/packages/rocketchat-rocketlets/server/converters/users.js b/packages/rocketchat-rocketlets/server/converters/users.js new file mode 100644 index 000000000000..0eea353ffb95 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/converters/users.js @@ -0,0 +1,13 @@ +export class RocketletUsersConverter { + constructor(converters) { + this.converters = converters; + } + + convertById(userId) { + const user = RocketChat.models.Users.findOneById(userId); + + return { + id: user._id + }; + } +} diff --git a/packages/rocketchat-rocketlets/server/models/Rocketlets.js b/packages/rocketchat-rocketlets/server/models/Rocketlets.js new file mode 100644 index 000000000000..a4e4a89eb4e1 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/models/Rocketlets.js @@ -0,0 +1,5 @@ +export class RocketletsModel extends RocketChat.models._Base { + constructor() { + super('rocketlets'); + } +} diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js new file mode 100644 index 000000000000..2f030bbfd347 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -0,0 +1,42 @@ +import { RocketletCommandsBridge } from './bridges'; +import { RocketletWebsocketNotifier } from './communication'; +import { RocketletMessagesConverter, RocketletRoomsConverter } from './converters'; +import { RocketletsModel } from './models/Rocketlets'; + +class RocketletServerOrchestrator { + constructor() { + this._model = new RocketletsModel(); + + this._converters = new Map(); + this._converters.set('messages', new RocketletMessagesConverter(this._converters)); + this._converters.set('rooms', new RocketletRoomsConverter(this._converters)); + + this._bridges = new Map(); + this._bridges.set('commands', new RocketletCommandsBridge(this._converters)); + + this._communicators = new Map(); + this._communicators.set('notifier', new RocketletWebsocketNotifier()); + } + + getModel() { + return this._model; + } + + getConverters() { + return this._converters; + } + + getBridges() { + return this._bridges; + } + + getNotifier() { + return this._communicators.get('notifier'); + } +} + +Meteor.startup(function _rocketletServerOrchestrator() { + console.log('Orchestrating the rocketlet piece...'); + Rocketlets = new RocketletServerOrchestrator(); + console.log('...done! :)'); +}); diff --git a/packages/rocketchat-slashcommands-archiveroom/server.js b/packages/rocketchat-slashcommands-archiveroom/server.js index 3d382cc25cb7..b8d54600bb2a 100644 --- a/packages/rocketchat-slashcommands-archiveroom/server.js +++ b/packages/rocketchat-slashcommands-archiveroom/server.js @@ -49,4 +49,7 @@ function Archive(command, params, item) { return Archive; } -RocketChat.slashCommands.add('archive', Archive); +RocketChat.slashCommands.add('archive', Archive, { + description: 'Archive', + params: '#channel' +}); diff --git a/packages/rocketchat-slashcommands-create/server.js b/packages/rocketchat-slashcommands-create/server.js index a64262065c95..3a33fa5c5443 100644 --- a/packages/rocketchat-slashcommands-create/server.js +++ b/packages/rocketchat-slashcommands-create/server.js @@ -45,4 +45,7 @@ function Create(command, params, item) { Meteor.call('createChannel', channel, []); } -RocketChat.slashCommands.add('create', Create); +RocketChat.slashCommands.add('create', Create, { + description: 'Create_A_New_Channel', + params: '#channel' +}); diff --git a/packages/rocketchat-slashcommands-help/server.js b/packages/rocketchat-slashcommands-help/server.js index ff7e61af5d00..f8aefcd869cb 100644 --- a/packages/rocketchat-slashcommands-help/server.js +++ b/packages/rocketchat-slashcommands-help/server.js @@ -45,4 +45,6 @@ RocketChat.slashCommands.add('help', function Help(command, params, item) { }); }); +}, { + description: 'Show_the_keyboard_shortcut_list' }); diff --git a/packages/rocketchat-slashcommands-invite/server.js b/packages/rocketchat-slashcommands-invite/server.js index a379762496fd..2dcd6923c5d2 100644 --- a/packages/rocketchat-slashcommands-invite/server.js +++ b/packages/rocketchat-slashcommands-invite/server.js @@ -77,6 +77,7 @@ function Invite(command, params, item) { }); } -RocketChat.slashCommands.add('invite', Invite); - -export {Invite}; +RocketChat.slashCommands.add('invite', Invite, { + description: 'Invite_user_to_join_channel', + params: '@username' +}); diff --git a/packages/rocketchat-slashcommands-inviteall/server.js b/packages/rocketchat-slashcommands-inviteall/server.js index 4d32c55697ad..a80cc3b04d08 100644 --- a/packages/rocketchat-slashcommands-inviteall/server.js +++ b/packages/rocketchat-slashcommands-inviteall/server.js @@ -76,6 +76,12 @@ function inviteAll(type) { } }; } -RocketChat.slashCommands.add('invite-all-to', inviteAll('to')); -RocketChat.slashCommands.add('invite-all-from', inviteAll('from')); +RocketChat.slashCommands.add('invite-all-to', inviteAll('to'), { + description: 'Invite_user_to_join_channel_all_to', + params: '#room' +}); +RocketChat.slashCommands.add('invite-all-from', inviteAll('from'), { + description: 'Invite_user_to_join_channel_all_from', + params: '#room' +}); module.exports = inviteAll; diff --git a/packages/rocketchat-slashcommands-join/server.js b/packages/rocketchat-slashcommands-join/server.js index 65f2294ec6fe..1cabe1e1a307 100644 --- a/packages/rocketchat-slashcommands-join/server.js +++ b/packages/rocketchat-slashcommands-join/server.js @@ -34,4 +34,7 @@ RocketChat.slashCommands.add('join', function Join(command, params, item) { }); } Meteor.call('joinRoom', room._id); +}, { + description: 'Join_the_given_channel', + params: '#channel' }); diff --git a/packages/rocketchat-slashcommands-kick/server.js b/packages/rocketchat-slashcommands-kick/server.js index aec3a5118733..ff484022fe54 100644 --- a/packages/rocketchat-slashcommands-kick/server.js +++ b/packages/rocketchat-slashcommands-kick/server.js @@ -37,4 +37,7 @@ const Kick = function(command, params, {rid}) { Meteor.call('removeUserFromRoom', {rid, username}); }; -RocketChat.slashCommands.add('kick', Kick); +RocketChat.slashCommands.add('kick', Kick, { + description: 'Remove_someone_from_room', + params: '@username' +}); diff --git a/packages/rocketchat-slashcommands-leave/leave.js b/packages/rocketchat-slashcommands-leave/leave.js index c58dfdf4f3b8..a6dd74fa82e1 100644 --- a/packages/rocketchat-slashcommands-leave/leave.js +++ b/packages/rocketchat-slashcommands-leave/leave.js @@ -7,6 +7,7 @@ function Leave(command, params, item) { if (command !== 'leave' && command !== 'part') { return; } + try { Meteor.call('leaveRoom', item.rid); } catch ({error}) { @@ -18,14 +19,6 @@ function Leave(command, params, item) { }); } } -if (Meteor.isClient) { - RocketChat.slashCommands.add('leave', undefined, { - description: 'Leave_the_current_channel' - }); - RocketChat.slashCommands.add('part', undefined, { - description: 'Leave_the_current_channel' - }); -} else { - RocketChat.slashCommands.add('leave', Leave); - RocketChat.slashCommands.add('part', Leave); -} + +RocketChat.slashCommands.add('leave', Meteor.isClient ? undefined : Leave, { description: 'Leave_the_current_channel' }); +RocketChat.slashCommands.add('part', Meteor.isClient ? undefined : Leave, { description: 'Leave_the_current_channel' }); From a16d5eaf017a58f7a81b7a70e17339350a97da2a Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Tue, 22 Aug 2017 15:18:41 -0500 Subject: [PATCH 060/801] RocketletManager is now loaded. --- packages/rocketchat-rocketlets/package.js | 26 ++++- .../server/bridges/bridges.js | 26 +++++ .../server/bridges/commands.js | 3 +- .../server/bridges/environmental.js | 20 ++++ .../server/bridges/index.js | 5 +- .../server/bridges/settings.js | 35 +++++++ .../server/converters/index.js | 2 + .../server/converters/settings.js | 13 +++ .../server/orchestrator.js | 31 ++++-- .../server/storage/index.js | 4 + .../Rocketlets.js => storage/rl-model.js} | 0 .../server/storage/storage.js | 96 +++++++++++++++++++ 12 files changed, 247 insertions(+), 14 deletions(-) create mode 100644 packages/rocketchat-rocketlets/server/bridges/bridges.js create mode 100644 packages/rocketchat-rocketlets/server/bridges/environmental.js create mode 100644 packages/rocketchat-rocketlets/server/bridges/settings.js create mode 100644 packages/rocketchat-rocketlets/server/converters/settings.js create mode 100644 packages/rocketchat-rocketlets/server/storage/index.js rename packages/rocketchat-rocketlets/server/{models/Rocketlets.js => storage/rl-model.js} (100%) create mode 100644 packages/rocketchat-rocketlets/server/storage/storage.js diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index 127b469b9e53..c654c4775ac0 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -14,17 +14,35 @@ Package.onUse(function(api) { api.addFiles('server/orchestrator.js', 'server'); - api.addFiles('server/models/Rocketlets.js', 'server'); + // Storage + api.addFiles([ + 'server/storage/rl-model.js', + 'server/storage/storage.js', + 'server/storage/index.js' + ], 'server'); // Bridges api.addFiles([ - 'server/bridges/commands.js' + 'server/bridges/bridges.js', + 'server/bridges/commands.js', + 'server/bridges/environmental.js', + 'server/bridges/settings.js', + 'server/bridges/index.js' ], 'server'); // Communication pieces api.addFiles([ 'server/communication/rest.js', - 'server/communication/websockets.js' + 'server/communication/websockets.js', + 'server/communication/index.js' + ], 'server'); + + api.addFiles([ + 'server/converters/messages.js', + 'server/converters/rooms.js', + 'server/converters/settings.js', + 'server/converters/users.js', + 'server/converters/index.js' ], 'server'); // Client communication pieces @@ -36,6 +54,6 @@ Package.onUse(function(api) { }); Npm.depends({ - 'temporary-rocketlets-server': '0.1.11', + 'temporary-rocketlets-server': '0.1.12', 'temporary-rocketlets-ts-definition': '0.6.2' }); diff --git a/packages/rocketchat-rocketlets/server/bridges/bridges.js b/packages/rocketchat-rocketlets/server/bridges/bridges.js new file mode 100644 index 000000000000..85acb7d0143f --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/bridges.js @@ -0,0 +1,26 @@ +import { RocketletBridges } from 'temporary-rocketlets-server/server/bridges'; +import { RocketletCommandsBridge } from './commands'; +import { RocketletEnvironmentalVariableBridge } from './environmental'; +import { RocketletSettingBridge } from './settings'; + +export class RealRocketletBridges extends RocketletBridges { + constructor(converters) { + super(); + + this._cmdBridge = new RocketletCommandsBridge(converters); + this._envBridge = new RocketletEnvironmentalVariableBridge(converters); + this._setsBridge = new RocketletSettingBridge(converters); + } + + getCommandBridge() { + return this._cmdBridge; + } + + getEnvironmentalVariableBridge() { + return this._envBridge; + } + + getServerSettingBridge() { + return this._setsBridge; + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/commands.js b/packages/rocketchat-rocketlets/server/bridges/commands.js index 99169f96c5f2..cefc56a7836f 100644 --- a/packages/rocketchat-rocketlets/server/bridges/commands.js +++ b/packages/rocketchat-rocketlets/server/bridges/commands.js @@ -1,12 +1,11 @@ export class RocketletCommandsBridge { constructor(converters) { - console.log('CommandsBridge constructor'); this.converters = converters; this.disabledCommands = new Map(); } doesCommandExist(command, rocketletId) { - console.log(`The Rocketlet ${ rocketletId } is check if "${ command }" command exists.`); + console.log(`The Rocketlet ${ rocketletId } is checking if "${ command }" command exists.`); if (typeof command !== 'string') { return false; diff --git a/packages/rocketchat-rocketlets/server/bridges/environmental.js b/packages/rocketchat-rocketlets/server/bridges/environmental.js new file mode 100644 index 000000000000..731fb3e798e0 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/environmental.js @@ -0,0 +1,20 @@ +export class RocketletEnvironmentalVariableBridge { + constructor(converters) { + this.converters = converters; + } + + getValueByName(envVarName, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is getting the environmental variable value ${ envVarName }.`); + throw new Error('Method not implemented.'); + } + + isReadable(envVarName, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is checking if the environmental variable is readable ${ envVarName }.`); + throw new Error('Method not implemented.'); + } + + isSet(envVarName, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is checking if the environmental variable is set ${ envVarName }.`); + throw new Error('Method not implemented.'); + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/index.js b/packages/rocketchat-rocketlets/server/bridges/index.js index 82cad72f3770..bab289eac933 100644 --- a/packages/rocketchat-rocketlets/server/bridges/index.js +++ b/packages/rocketchat-rocketlets/server/bridges/index.js @@ -1,3 +1,6 @@ +import { RealRocketletBridges } from './bridges'; import { RocketletCommandsBridge } from './commands'; +import { RocketletEnvironmentalVariableBridge } from './environmental'; +import { RocketletSettingBridge } from './settings'; -export { RocketletCommandsBridge }; +export { RealRocketletBridges, RocketletCommandsBridge, RocketletEnvironmentalVariableBridge, RocketletSettingBridge }; diff --git a/packages/rocketchat-rocketlets/server/bridges/settings.js b/packages/rocketchat-rocketlets/server/bridges/settings.js new file mode 100644 index 000000000000..b27d2be634f4 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/settings.js @@ -0,0 +1,35 @@ +export class RocketletSettingBridge { + constructor(converters) { + this.converters = converters; + } + + getAll(rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is getting all the settings.`); + throw new Error('Method not implemented.'); + } + + getOneById(id, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is getting the setting by id ${ id }.`); + throw new Error('Method not implemented.'); + } + + hideGroup(name, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is hidding the group ${ name }.`); + throw new Error('Method not implemented.'); + } + + hideSetting(id, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is hidding the setting ${ id }.`); + throw new Error('Method not implemented.'); + } + + isReadableById(id, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is checking if they can read the setting ${ id }.`); + throw new Error('Method not implemented.'); + } + + updateOne(setting, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is updating the setting ${ setting.id } .`); + throw new Error('Method not implemented.'); + } +} diff --git a/packages/rocketchat-rocketlets/server/converters/index.js b/packages/rocketchat-rocketlets/server/converters/index.js index 2a402be1b351..0713f78dd5fb 100644 --- a/packages/rocketchat-rocketlets/server/converters/index.js +++ b/packages/rocketchat-rocketlets/server/converters/index.js @@ -1,9 +1,11 @@ import { RocketletMessagesConverter } from './messages'; import { RocketletRoomsConverter } from './rooms'; +import { RocketletSettingsConverter } from './settings'; import { RocketletUsersConverter } from './users'; export { RocketletMessagesConverter, RocketletRoomsConverter, + RocketletSettingsConverter, RocketletUsersConverter }; diff --git a/packages/rocketchat-rocketlets/server/converters/settings.js b/packages/rocketchat-rocketlets/server/converters/settings.js new file mode 100644 index 000000000000..6421e7989217 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/converters/settings.js @@ -0,0 +1,13 @@ +export class RocketletSettingsConverter { + constructor(converters) { + this.converters = converters; + } + + convertById(settingId) { + const setting = RocketChat.models.Settings.findOneById(settingId); + + return { + id: setting._id + }; + } +} diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js index 2f030bbfd347..dbb6cf068a17 100644 --- a/packages/rocketchat-rocketlets/server/orchestrator.js +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -1,27 +1,37 @@ -import { RocketletCommandsBridge } from './bridges'; +import { RealRocketletBridges } from './bridges'; import { RocketletWebsocketNotifier } from './communication'; -import { RocketletMessagesConverter, RocketletRoomsConverter } from './converters'; -import { RocketletsModel } from './models/Rocketlets'; +import { RocketletMessagesConverter, RocketletRoomsConverter, RocketletSettingsConverter, RocketletUsersConverter } from './converters'; +import { RocketletsModel, RocketletRealStorage } from './storage'; + +import { RocketletManager } from 'temporary-rocketlets-server/server/RocketletManager'; class RocketletServerOrchestrator { constructor() { this._model = new RocketletsModel(); + this._storage = new RocketletRealStorage(this._model); this._converters = new Map(); this._converters.set('messages', new RocketletMessagesConverter(this._converters)); this._converters.set('rooms', new RocketletRoomsConverter(this._converters)); + this._converters.set('settings', new RocketletSettingsConverter(this._converters)); + this._converters.set('users', new RocketletUsersConverter(this._converters)); - this._bridges = new Map(); - this._bridges.set('commands', new RocketletCommandsBridge(this._converters)); + this._bridges = new RealRocketletBridges(this._converters); this._communicators = new Map(); this._communicators.set('notifier', new RocketletWebsocketNotifier()); + + this._manager = new RocketletManager(this._storage, this._bridges); } getModel() { return this._model; } + getStorage() { + return this._storage; + } + getConverters() { return this._converters; } @@ -33,10 +43,17 @@ class RocketletServerOrchestrator { getNotifier() { return this._communicators.get('notifier'); } + + getManager() { + return this._manager; + } } Meteor.startup(function _rocketletServerOrchestrator() { console.log('Orchestrating the rocketlet piece...'); - Rocketlets = new RocketletServerOrchestrator(); - console.log('...done! :)'); + global.Rocketlets = new RocketletServerOrchestrator(); + + global.Rocketlets.getManager().load() + .then(() => console.log('...done! ;)')) + .catch((err) => console.warn('...failed!', err)); }); diff --git a/packages/rocketchat-rocketlets/server/storage/index.js b/packages/rocketchat-rocketlets/server/storage/index.js new file mode 100644 index 000000000000..45a5e19e9c46 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/storage/index.js @@ -0,0 +1,4 @@ +import { RocketletsModel } from './rl-model'; +import { RocketletRealStorage } from './storage'; + +export { RocketletsModel, RocketletRealStorage }; diff --git a/packages/rocketchat-rocketlets/server/models/Rocketlets.js b/packages/rocketchat-rocketlets/server/storage/rl-model.js similarity index 100% rename from packages/rocketchat-rocketlets/server/models/Rocketlets.js rename to packages/rocketchat-rocketlets/server/storage/rl-model.js diff --git a/packages/rocketchat-rocketlets/server/storage/storage.js b/packages/rocketchat-rocketlets/server/storage/storage.js new file mode 100644 index 000000000000..0ac51c5e0a48 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/storage/storage.js @@ -0,0 +1,96 @@ +import { RocketletStorage } from 'temporary-rocketlets-server/server/storage'; + +export class RocketletRealStorage extends RocketletStorage { + constructor(data) { + super('mongodb'); + this.db = data; + } + + create(item) { + return new Promise((resolve, reject) => { + item.createdAt = new Date(); + item.updatedAt = new Date(); + + let doc; + + try { + doc = this.db.findOne({ $or: [{ id: item.id }, { 'info.nameSlug': item.info.nameSlug }] }); + } catch (e) { + return reject(e); + } + + if (doc) { + return reject(new Error('Rocketlet already exists.')); + } + + try { + const id = this.db.insert(item); + item._id = id; + + resolve(item); + } catch (e) { + reject(e); + } + }); + } + + retrieveOne(id) { + return new Promise((resolve, reject) => { + let doc; + + try { + doc = this.db.findOneById(id); + } catch (e) { + return reject(e); + } + + if (doc) { + resolve(doc); + } else { + reject(new Error(`Nothing found by the id: ${ id }`)); + } + }); + } + + retrieveAll() { + return new Promise((resolve, reject) => { + let docs; + + try { + docs = this.db.find({}).fetch(); + } catch (e) { + return reject(e); + } + + const items = new Map(); + + docs.forEach((i) => items.set(i.id, i)); + + resolve(items); + }); + } + + update(item) { + return new Promise((resolve, reject) => { + try { + this.db.update({ id: item.id }, item); + } catch (e) { + return reject(e); + } + + this.retrieveOne(item.id).then((updated) => resolve(updated)).catch((err) => reject(err)); + }); + } + + remove(id) { + return new Promise((resolve, reject) => { + try { + this.db.remove({ id }); + } catch (e) { + return reject(e); + } + + resolve({ success: true }); + }); + } +} From f65ca7a63a9de74a5f81b4c52a64e12917babdaa Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Wed, 23 Aug 2017 17:22:28 -0500 Subject: [PATCH 061/801] Rocketlet commands are now loaded onto the client and server --- .meteor/packages | 1 - .meteor/versions | 1 - packages/rocketchat-api/server/v1/commands.js | 2 +- .../client/lib/RestApiClient.js | 41 +++++++++ .../client/lib/startup/commands.js | 11 +++ packages/rocketchat-lib/package.js | 4 + .../client/communication/index.js | 4 + .../client/communication/restclient.js | 30 +++++++ .../client/communication/websockets.js | 22 ++++- .../client/orchestrator.js | 20 +++++ packages/rocketchat-rocketlets/package.js | 14 ++- .../server/bridges/bridges.js | 8 +- .../server/bridges/commands.js | 39 +++++--- .../server/communication/index.js | 2 + .../server/communication/rest.js | 88 +++++++++++++++++-- .../server/communication/websockets.js | 16 ++++ .../server/converters/messages.js | 4 +- .../server/converters/rooms.js | 4 +- .../server/converters/settings.js | 4 +- .../server/converters/users.js | 4 +- .../server/orchestrator.js | 17 ++-- .../gimme.js | 18 ---- .../lenny.js | 18 ---- .../package.js | 20 ----- .../shrug.js | 18 ---- .../tableflip.js | 18 ---- .../unflip.js | 18 ---- 27 files changed, 287 insertions(+), 159 deletions(-) create mode 100644 packages/rocketchat-lib/client/lib/RestApiClient.js create mode 100644 packages/rocketchat-lib/client/lib/startup/commands.js create mode 100644 packages/rocketchat-rocketlets/client/communication/index.js create mode 100644 packages/rocketchat-rocketlets/client/communication/restclient.js create mode 100644 packages/rocketchat-rocketlets/client/orchestrator.js delete mode 100644 packages/rocketchat-slashcommand-asciiarts/gimme.js delete mode 100644 packages/rocketchat-slashcommand-asciiarts/lenny.js delete mode 100644 packages/rocketchat-slashcommand-asciiarts/package.js delete mode 100644 packages/rocketchat-slashcommand-asciiarts/shrug.js delete mode 100644 packages/rocketchat-slashcommand-asciiarts/tableflip.js delete mode 100644 packages/rocketchat-slashcommand-asciiarts/unflip.js diff --git a/.meteor/packages b/.meteor/packages index cc549ff64a58..c3655aff0d37 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -97,7 +97,6 @@ rocketchat:rocketlets rocketchat:sandstorm rocketchat:slackbridge rocketchat:slashcommands-archive -rocketchat:slashcommands-asciiarts rocketchat:slashcommands-create rocketchat:slashcommands-help rocketchat:slashcommands-invite diff --git a/.meteor/versions b/.meteor/versions index 76740ca513da..cc64980c9840 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -189,7 +189,6 @@ rocketchat:rocketlets@1.0.0 rocketchat:sandstorm@0.0.1 rocketchat:slackbridge@0.0.1 rocketchat:slashcommands-archive@0.0.1 -rocketchat:slashcommands-asciiarts@0.0.1 rocketchat:slashcommands-create@0.0.1 rocketchat:slashcommands-help@0.0.1 rocketchat:slashcommands-invite@0.0.1 diff --git a/packages/rocketchat-api/server/v1/commands.js b/packages/rocketchat-api/server/v1/commands.js index eeda89444260..e903e0f8dc13 100644 --- a/packages/rocketchat-api/server/v1/commands.js +++ b/packages/rocketchat-api/server/v1/commands.js @@ -23,7 +23,7 @@ RocketChat.API.v1.addRoute('commands.list', { authRequired: true }, { let commands = Object.values(RocketChat.slashCommands.commands); - if (query.command) { + if (query && query.command) { commands = commands.filter((command) => command.command === query.command); } diff --git a/packages/rocketchat-lib/client/lib/RestApiClient.js b/packages/rocketchat-lib/client/lib/RestApiClient.js new file mode 100644 index 000000000000..ab353e69cb12 --- /dev/null +++ b/packages/rocketchat-lib/client/lib/RestApiClient.js @@ -0,0 +1,41 @@ +RocketChat.API = { + get(endpoint, params) { + return RocketChat.API._jqueryCall('GET', endpoint, params); + }, + + _jqueryCall(method, endpoint, params, body) { + let query = ''; + if (params) { + Object.keys(params).forEach((key) => { + query += query === '' ? '?' : '&'; + + query += `${ key }=${ params[key] }`; + }); + } + + return new Promise(function _rlRestApiGet(resolve, reject) { + jQuery.ajax({ + method, + url: `${ Meteor.absoluteUrl() }api/${ endpoint }${ query }`, + headers: { + 'Content-Type': 'application/json', + 'X-User-Id': localStorage['Meteor.userId'], + 'X-Auth-Token': localStorage['Meteor.loginToken'] + }, + data: body, + success: function _rlGetSuccess(result) { + resolve(result); + }, + error: function _rlGetFailure(xhr, status, errorThrown) { + reject(new Error(errorThrown)); + } + }); + }); + }, + + v1: { + get(endpoint, params) { + return RocketChat.API.get(`v1/${ endpoint }`, params); + } + } +}; diff --git a/packages/rocketchat-lib/client/lib/startup/commands.js b/packages/rocketchat-lib/client/lib/startup/commands.js new file mode 100644 index 000000000000..01d97477c1fa --- /dev/null +++ b/packages/rocketchat-lib/client/lib/startup/commands.js @@ -0,0 +1,11 @@ +Meteor.startup(function _loadDynamicallyDefinedCommands() { + // The reason there is a 500 millisecond delay is so that we are + // a little "easier" on the server during start up + setTimeout(() => { + RocketChat.API.v1.get('commands.list').then(function _loadedCommands(result) { + result.commands.forEach((command) => { + RocketChat.slashCommands.commands[command.command] = command; + }); + }); + }, 500); +}); diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index 88eab2cb0557..47e7c8bb7b5d 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -182,6 +182,7 @@ Package.onUse(function(api) { // CLIENT LIB api.addFiles('client/Notifications.js', 'client'); api.addFiles('client/OAuthProxy.js', 'client'); + api.addFiles('client/lib/RestApiClient.js', 'client'); api.addFiles('client/lib/TabBar.js', 'client'); api.addFiles('client/lib/RocketChatTabBar.js', 'client'); api.addFiles('client/lib/cachedCollection.js', 'client'); @@ -192,6 +193,9 @@ Package.onUse(function(api) { api.addFiles('client/lib/userRoles.js', 'client'); api.addFiles('client/lib/Layout.js', 'client'); + // CLIENT LIB STARTUP + api.addFiles('client/lib/startup/commands.js', 'client'); + // CLIENT METHODS api.addFiles('client/methods/sendMessage.js', 'client'); api.addFiles('client/AdminBox.js', 'client'); diff --git a/packages/rocketchat-rocketlets/client/communication/index.js b/packages/rocketchat-rocketlets/client/communication/index.js new file mode 100644 index 000000000000..8f92c01d21b7 --- /dev/null +++ b/packages/rocketchat-rocketlets/client/communication/index.js @@ -0,0 +1,4 @@ +import { RocketletRestApiClient } from './restclient'; +import { RocketletWebsocketReceiver } from './websockets'; + +export { RocketletRestApiClient, RocketletWebsocketReceiver }; diff --git a/packages/rocketchat-rocketlets/client/communication/restclient.js b/packages/rocketchat-rocketlets/client/communication/restclient.js new file mode 100644 index 000000000000..0a09c49074fc --- /dev/null +++ b/packages/rocketchat-rocketlets/client/communication/restclient.js @@ -0,0 +1,30 @@ +export class RocketletRestApiClient { + constructor(orch) { + this.orch = orch; + } + + get(endpoint, params) { + return this._jqueryCall('GET', endpoint, params); + } + + _jqueryCall(method, endpoint, params) { + return new Promise(function _rlRestApiGet(resolve, reject) { + jQuery.ajax({ + method, + url: `${ Meteor.absoluteUrl() }api/${ endpoint }`, + headers: { + 'Content-Type': 'application/json', + 'X-User-Id': localStorage['Meteor.userId'], + 'X-Auth-Token': localStorage['Meteor.loginToken'] + }, + data: params, + success: function _rlGetSuccess(result) { + resolve(result); + }, + error: function _rlGetFailure(xhr, status, errorThrown) { + reject(new Error(errorThrown)); + } + }); + }); + } +} diff --git a/packages/rocketchat-rocketlets/client/communication/websockets.js b/packages/rocketchat-rocketlets/client/communication/websockets.js index 2a783649a3b6..d661600d5acf 100644 --- a/packages/rocketchat-rocketlets/client/communication/websockets.js +++ b/packages/rocketchat-rocketlets/client/communication/websockets.js @@ -1,12 +1,26 @@ export class RocketletWebsocketReceiver { - constructor(restApi) { - this.rest = restApi; + constructor(orch) { + this.orch = orch; this.streamer = new Meteor.Streamer('rocketlets'); - this.streamer.on('command/added', this.onCommandAdded); + this.streamer.on('command/added', this.onCommandAdded.bind(this)); + this.streamer.on('command/disabled', this.onCommandDisabled.bind(this)); + this.streamer.on('command/updated', this.onCommandUpdated.bind(this)); } onCommandAdded(command) { - console.log('Added:', command); + RocketChat.API.v1.get('commands.getOne', { command }).then((result) => { + RocketChat.slashCommands.commands[command] = result.command; + }); + } + + onCommandDisabled(command) { + delete RocketChat.slashCommands.commands[command]; + } + + onCommandUpdated(command) { + RocketChat.API.v1.get('commands.getOne', { command }).then((result) => { + RocketChat.slashCommands.commands[command] = result.command; + }); } } diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js new file mode 100644 index 000000000000..7fc1f4bf3e78 --- /dev/null +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -0,0 +1,20 @@ +import { RocketletRestApiClient, RocketletWebsocketReceiver } from './communication'; + +class RocketletClientOrchestrator { + constructor() { + this.ws = new RocketletWebsocketReceiver(this); + this.rest = new RocketletRestApiClient(this); + } + + getWsListener() { + return this.ws; + } + + getRestApiClient() { + return this.rest; + } +} + +Meteor.startup(function _rlClientOrch() { + window.Rocketlets = new RocketletClientOrchestrator(); +}); diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index c654c4775ac0..bc7473b8e7af 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -12,8 +12,6 @@ Package.onUse(function(api) { api.addFiles('lib/Rocketlets.js', ['client', 'server']); - api.addFiles('server/orchestrator.js', 'server'); - // Storage api.addFiles([ 'server/storage/rl-model.js', @@ -45,15 +43,23 @@ Package.onUse(function(api) { 'server/converters/index.js' ], 'server'); + // Server Orchestrator + api.addFiles('server/orchestrator.js', 'server'); + // Client communication pieces api.addFiles([ - 'client/communication/websockets.js' + 'client/communication/websockets.js', + 'client/communication/index.js' ], 'client'); + // Client orchestrator + api.addFiles('client/orchestrator.js', 'client'); + api.export('Rocketlets'); }); Npm.depends({ - 'temporary-rocketlets-server': '0.1.12', + 'busboy': '0.2.13', + 'temporary-rocketlets-server': '0.1.16', 'temporary-rocketlets-ts-definition': '0.6.2' }); diff --git a/packages/rocketchat-rocketlets/server/bridges/bridges.js b/packages/rocketchat-rocketlets/server/bridges/bridges.js index 85acb7d0143f..713987341246 100644 --- a/packages/rocketchat-rocketlets/server/bridges/bridges.js +++ b/packages/rocketchat-rocketlets/server/bridges/bridges.js @@ -4,12 +4,12 @@ import { RocketletEnvironmentalVariableBridge } from './environmental'; import { RocketletSettingBridge } from './settings'; export class RealRocketletBridges extends RocketletBridges { - constructor(converters) { + constructor(orch) { super(); - this._cmdBridge = new RocketletCommandsBridge(converters); - this._envBridge = new RocketletEnvironmentalVariableBridge(converters); - this._setsBridge = new RocketletSettingBridge(converters); + this._cmdBridge = new RocketletCommandsBridge(orch); + this._envBridge = new RocketletEnvironmentalVariableBridge(orch); + this._setsBridge = new RocketletSettingBridge(orch); } getCommandBridge() { diff --git a/packages/rocketchat-rocketlets/server/bridges/commands.js b/packages/rocketchat-rocketlets/server/bridges/commands.js index cefc56a7836f..3bf584ecbd59 100644 --- a/packages/rocketchat-rocketlets/server/bridges/commands.js +++ b/packages/rocketchat-rocketlets/server/bridges/commands.js @@ -1,6 +1,8 @@ +import { SlashCommandContext } from 'temporary-rocketlets-ts-definition/slashcommands'; + export class RocketletCommandsBridge { - constructor(converters) { - this.converters = converters; + constructor(orch) { + this.orch = orch; this.disabledCommands = new Map(); } @@ -29,7 +31,7 @@ export class RocketletCommandsBridge { this.disabledCommands.set(cmd, RocketChat.slashCommands.commands[cmd]); delete RocketChat.slashCommands.commands[cmd]; - Rocketlets.getNotifier().commandDisabled(cmd); + this.orch.getNotifier().commandDisabled(cmd); } // command: { command, paramsExample, i18nDescription, executor: function } @@ -46,8 +48,26 @@ export class RocketletCommandsBridge { const item = RocketChat.slashCommands.commands[cmd]; item.params = command.paramsExample ? command.paramsExample : item.params; item.description = command.i18nDescription ? command.i18nDescription : item.params; - item.callback = this._executorWrapper(command.executor); + item.callback = this._rocketletCommandExecutor.bind(this); + RocketChat.slashCommands.commands[cmd] = item; + this.orch.getNotifier().commandUpdated(cmd); + } + + registerCommand(command, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is registering the command: "${ command.command }"`); + + this._verifyCommand(command); + + const item = { + command: command.command.toLowerCase(), + params: command.paramsExample, + description: command.i18nDescription, + callback: this._rocketletCommandExecutor.bind(this) + }; + + RocketChat.slashCommands.commands[command.command.toLowerCase()] = item; + this.orch.getNotifier().commandAdded(command.command.toLowerCase()); } _verifyCommand(command) { @@ -72,12 +92,11 @@ export class RocketletCommandsBridge { } } - _executorWrapper(executor) { - return function _wrappedExecutor(command, params, message) { - // TODO: Converters - this.converters.get('messages').translate(message); + _rocketletCommandExecutor(command, parameters, message) { + const user = this.orch.getConverters().get('users').convertById(Meteor.userId()); + const room = this.orch.getConverters().get('rooms').convertById(message.rid); + const params = parameters.length === 0 || parameters === ' ' ? [] : parameters.split(' '); - executor(command); - }; + this.orch.getManager().getCommandManager().executeCommand(command, new SlashCommandContext(user, room, params)); } } diff --git a/packages/rocketchat-rocketlets/server/communication/index.js b/packages/rocketchat-rocketlets/server/communication/index.js index 8781d1737c41..870a5316c06e 100644 --- a/packages/rocketchat-rocketlets/server/communication/index.js +++ b/packages/rocketchat-rocketlets/server/communication/index.js @@ -1,5 +1,7 @@ +import { RocketletsRestApi } from './rest'; import { RocketletWebsocketNotifier } from './websockets'; export { + RocketletsRestApi, RocketletWebsocketNotifier }; diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js index c463e1e60c7a..d8b58d47f9c4 100644 --- a/packages/rocketchat-rocketlets/server/communication/rest.js +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -1,8 +1,80 @@ -/* Rocketlets.API = new RocketChat.API.ApiClass({ - version: 'rocketlets', - useDefaultAuth: true, - prettyJson: true, - enableCors: false, - auth: RocketChat.API.getUserAuth() -}); -*/ +export class RocketletsRestApi { + constructor(manager) { + this._manager = manager; + this.api = new RocketChat.API.ApiClass({ + version: 'rocketlets', + useDefaultAuth: true, + prettyJson: true, + enableCors: false, + auth: RocketChat.API.getUserAuth() + }); + + this.addManagementRoutes(); + } + + _handleFile(request, fileField) { + const Busboy = Npm.require('busboy'); + const busboy = new Busboy({ headers: request.headers }); + + return Meteor.wrapAsync((callback) => { + busboy.on('file', Meteor.bindEnvironment((fieldname, file) => { + if (fieldname !== fileField) { + return callback(new Meteor.Error('invalid-field', `Expected the field "${ fileField }" but got "${ fieldname }" instead.`)); + } + + const fileData = []; + file.on('data', Meteor.bindEnvironment((data) => { + fileData.push(data); + })); + + file.on('end', Meteor.bindEnvironment(() => callback(undefined, Buffer.concat(fileData)))); + })); + + request.pipe(busboy); + })(); + } + + addManagementRoutes() { + const manager = this._manager; + const fileHandler = this._handleFile; + + this.api.addRoute('', { authRequired: true }, { + post() { + console.log('Creating a new Rocketlet via the rest api'); + + const buff = fileHandler(this.request, 'rocketlet'); + const item = Meteor.wrapAsync((callback) => { + manager.add(buff.toString('base64')).then((rl) => { + console.log('Success?'); + callback(undefined, rl); + }).catch((e) => { + console.warn('Error!', e); + callback(e); + }); + })(); + + console.log('result:', item.rocketlet.info); + + return { success: true, rocketlet: item.rocketlet.info }; + } + }); + + this.api.addRoute(':id', { authRequired: true }, { + get() { + console.log('Getting:', this.urlParams.id); + return { success: false }; + }, + post() { + console.log('Updating:', this.urlParams.id); + // TODO: Verify permissions + + const buff = fileHandler(this.request, 'rocketlet'); + const item = Meteor.wrapAsync((callback) => { + manager.update(buff.toString('base64')).then((rl) => callback(rl)).catch((e) => callback(e)); + }); + + return { success: false, item }; + } + }); + } +} diff --git a/packages/rocketchat-rocketlets/server/communication/websockets.js b/packages/rocketchat-rocketlets/server/communication/websockets.js index 8fda659d65c8..d92da25cae44 100644 --- a/packages/rocketchat-rocketlets/server/communication/websockets.js +++ b/packages/rocketchat-rocketlets/server/communication/websockets.js @@ -6,6 +6,18 @@ export class RocketletWebsocketNotifier { this.streamer.allowWrite('none'); } + rocketletAdded(rocketletId) { + this.streamer.emit('rocketlet/added', rocketletId); + } + + rockletRemoved(rocketletId) { + this.streamer.emit('rocketlet/removed', rocketletId); + } + + rockletUpdated(rocketletId) { + this.streamer.emit('rocketlet/updated', rocketletId); + } + commandAdded(command) { this.streamer.emit('command/added', command); } @@ -13,4 +25,8 @@ export class RocketletWebsocketNotifier { commandDisabled(command) { this.streamer.emit('command/disabled', command); } + + commandUpdated(command) { + this.streamer.emit('command/updated', command); + } } diff --git a/packages/rocketchat-rocketlets/server/converters/messages.js b/packages/rocketchat-rocketlets/server/converters/messages.js index 80a745a0ea74..3b6892da346f 100644 --- a/packages/rocketchat-rocketlets/server/converters/messages.js +++ b/packages/rocketchat-rocketlets/server/converters/messages.js @@ -1,6 +1,6 @@ export class RocketletMessagesConverter { - constructor(converters) { - this.converters = converters; + constructor(orch) { + this.orch = orch; } convertById(msgId) { diff --git a/packages/rocketchat-rocketlets/server/converters/rooms.js b/packages/rocketchat-rocketlets/server/converters/rooms.js index 23481dda5ef1..d198482bb595 100644 --- a/packages/rocketchat-rocketlets/server/converters/rooms.js +++ b/packages/rocketchat-rocketlets/server/converters/rooms.js @@ -1,6 +1,6 @@ export class RocketletRoomsConverter { - constructor(converters) { - this.converters = converters; + constructor(orch) { + this.orch = orch; } convertById(roomId) { diff --git a/packages/rocketchat-rocketlets/server/converters/settings.js b/packages/rocketchat-rocketlets/server/converters/settings.js index 6421e7989217..eec1f01984f2 100644 --- a/packages/rocketchat-rocketlets/server/converters/settings.js +++ b/packages/rocketchat-rocketlets/server/converters/settings.js @@ -1,6 +1,6 @@ export class RocketletSettingsConverter { - constructor(converters) { - this.converters = converters; + constructor(orch) { + this.orch = orch; } convertById(settingId) { diff --git a/packages/rocketchat-rocketlets/server/converters/users.js b/packages/rocketchat-rocketlets/server/converters/users.js index 0eea353ffb95..6f52033f096b 100644 --- a/packages/rocketchat-rocketlets/server/converters/users.js +++ b/packages/rocketchat-rocketlets/server/converters/users.js @@ -1,6 +1,6 @@ export class RocketletUsersConverter { - constructor(converters) { - this.converters = converters; + constructor(orch) { + this.orch = orch; } convertById(userId) { diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js index dbb6cf068a17..f35d9cfbb5dd 100644 --- a/packages/rocketchat-rocketlets/server/orchestrator.js +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -1,5 +1,5 @@ import { RealRocketletBridges } from './bridges'; -import { RocketletWebsocketNotifier } from './communication'; +import { RocketletsRestApi, RocketletWebsocketNotifier } from './communication'; import { RocketletMessagesConverter, RocketletRoomsConverter, RocketletSettingsConverter, RocketletUsersConverter } from './converters'; import { RocketletsModel, RocketletRealStorage } from './storage'; @@ -11,17 +11,18 @@ class RocketletServerOrchestrator { this._storage = new RocketletRealStorage(this._model); this._converters = new Map(); - this._converters.set('messages', new RocketletMessagesConverter(this._converters)); - this._converters.set('rooms', new RocketletRoomsConverter(this._converters)); - this._converters.set('settings', new RocketletSettingsConverter(this._converters)); - this._converters.set('users', new RocketletUsersConverter(this._converters)); + this._converters.set('messages', new RocketletMessagesConverter(this)); + this._converters.set('rooms', new RocketletRoomsConverter(this)); + this._converters.set('settings', new RocketletSettingsConverter(this)); + this._converters.set('users', new RocketletUsersConverter(this)); - this._bridges = new RealRocketletBridges(this._converters); + this._bridges = new RealRocketletBridges(this); + + this._manager = new RocketletManager(this._storage, this._bridges); this._communicators = new Map(); + this._communicators.set('restapi', new RocketletsRestApi(this._manager)); this._communicators.set('notifier', new RocketletWebsocketNotifier()); - - this._manager = new RocketletManager(this._storage, this._bridges); } getModel() { diff --git a/packages/rocketchat-slashcommand-asciiarts/gimme.js b/packages/rocketchat-slashcommand-asciiarts/gimme.js deleted file mode 100644 index f8997115d321..000000000000 --- a/packages/rocketchat-slashcommand-asciiarts/gimme.js +++ /dev/null @@ -1,18 +0,0 @@ -/* -* Gimme is a named function that will replace /gimme commands -* @param {Object} message - The message object -*/ - - -function Gimme(command, params, item) { - if (command === 'gimme') { - const msg = item; - msg.msg = `༼ つ ◕_◕ ༽つ ${ params }`; - Meteor.call('sendMessage', msg); - } -} - -RocketChat.slashCommands.add('gimme', Gimme, { - description: 'Slash_Gimme_Description', - params: 'your_message_optional' -}); diff --git a/packages/rocketchat-slashcommand-asciiarts/lenny.js b/packages/rocketchat-slashcommand-asciiarts/lenny.js deleted file mode 100644 index 5272a7b67867..000000000000 --- a/packages/rocketchat-slashcommand-asciiarts/lenny.js +++ /dev/null @@ -1,18 +0,0 @@ -/* -* Lenny is a named function that will replace /lenny commands -* @param {Object} message - The message object -*/ - - -function LennyFace(command, params, item) { - if (command === 'lennyface') { - const msg = item; - msg.msg = `${ params } ( ͡° ͜ʖ ͡°)`; - Meteor.call('sendMessage', msg); - } -} - -RocketChat.slashCommands.add('lennyface', LennyFace, { - description: 'Slash_LennyFace_Description', - params: 'your_message_optional' -}); diff --git a/packages/rocketchat-slashcommand-asciiarts/package.js b/packages/rocketchat-slashcommand-asciiarts/package.js deleted file mode 100644 index 703d6cca492f..000000000000 --- a/packages/rocketchat-slashcommand-asciiarts/package.js +++ /dev/null @@ -1,20 +0,0 @@ -Package.describe({ - name: 'rocketchat:slashcommands-asciiarts', - version: '0.0.1', - summary: 'Message pre-processor that will add ascii arts to messages', - git: '' -}); - -Package.onUse(function(api) { - api.use([ - 'rocketchat:lib' - ]); - - api.use('ecmascript'); - - api.addFiles('gimme.js', ['server', 'client']); - api.addFiles('lenny.js', ['server', 'client']); - api.addFiles('shrug.js', ['server', 'client']); - api.addFiles('tableflip.js', ['server', 'client']); - api.addFiles('unflip.js', ['server', 'client']); -}); diff --git a/packages/rocketchat-slashcommand-asciiarts/shrug.js b/packages/rocketchat-slashcommand-asciiarts/shrug.js deleted file mode 100644 index 656c739e354a..000000000000 --- a/packages/rocketchat-slashcommand-asciiarts/shrug.js +++ /dev/null @@ -1,18 +0,0 @@ -/* -* Shrug is a named function that will replace /shrug commands -* @param {Object} message - The message object -*/ - - -function Shrug(command, params, item) { - if (command === 'shrug') { - const msg = item; - msg.msg = `${ params } ¯\\_(ツ)_/¯`; - Meteor.call('sendMessage', msg); - } -} - -RocketChat.slashCommands.add('shrug', Shrug, { - description: 'Slash_Shrug_Description', - params: 'your_message_optional' -}); diff --git a/packages/rocketchat-slashcommand-asciiarts/tableflip.js b/packages/rocketchat-slashcommand-asciiarts/tableflip.js deleted file mode 100644 index 1d7d172c6286..000000000000 --- a/packages/rocketchat-slashcommand-asciiarts/tableflip.js +++ /dev/null @@ -1,18 +0,0 @@ -/* -* Tableflip is a named function that will replace /Tableflip commands -* @param {Object} message - The message object -*/ - - -function Tableflip(command, params, item) { - if (command === 'tableflip') { - const msg = item; - msg.msg = `${ params } (╯°□°)╯︵ ┻━┻`; - Meteor.call('sendMessage', msg); - } -} - -RocketChat.slashCommands.add('tableflip', Tableflip, { - description: 'Slash_Tableflip_Description', - params: 'your_message_optional' -}); diff --git a/packages/rocketchat-slashcommand-asciiarts/unflip.js b/packages/rocketchat-slashcommand-asciiarts/unflip.js deleted file mode 100644 index 3df04e43d6c5..000000000000 --- a/packages/rocketchat-slashcommand-asciiarts/unflip.js +++ /dev/null @@ -1,18 +0,0 @@ -/* -* Unflip is a named function that will replace /unflip commands -* @param {Object} message - The message object -*/ - - -function Unflip(command, params, item) { - if (command === 'unflip') { - const msg = item; - msg.msg = `${ params } ┬─┬ ノ( ゜-゜ノ)`; - Meteor.call('sendMessage', msg); - } -} - -RocketChat.slashCommands.add('unflip', Unflip, { - description: 'Slash_TableUnflip_Description', - params: 'your_message_optional' -}); From 9a609bf6d6e6ec16896ff96e3b8ff489f5dde9db Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Thu, 24 Aug 2017 13:21:48 -0500 Subject: [PATCH 062/801] Improve the commands and add permission nodes to the commands --- packages/rocketchat-lib/lib/slashCommand.js | 1 + .../client/communication/index.js | 3 +- .../client/communication/restclient.js | 30 ------------------- .../client/orchestrator.js | 7 +---- .../server/orchestrator.js | 3 +- .../client.js | 4 --- .../package.js | 5 +--- .../rocketchat-slashcommands-create/client.js | 4 --- .../package.js | 2 -- .../rocketchat-slashcommands-help/client.js | 3 -- .../rocketchat-slashcommands-help/package.js | 1 - .../rocketchat-slashcommands-help/server.js | 4 --- .../rocketchat-slashcommands-invite/client.js | 4 --- .../package.js | 2 -- .../client.js | 8 ----- .../package.js | 1 - .../server.js | 2 +- .../rocketchat-slashcommands-kick/client.js | 10 ------- .../rocketchat-slashcommands-kick/package.js | 2 -- .../rocketchat-slashcommands-kick/server.js | 3 +- .../rocketchat-slashcommands-leave/leave.js | 4 +-- .../rocketchat-slashcommands-leave/package.js | 3 +- packages/rocketchat-slashcommands-me/me.js | 1 + .../rocketchat-slashcommands-me/package.js | 2 +- .../rocketchat-slashcommands-msg/client.js | 4 --- .../rocketchat-slashcommands-msg/package.js | 2 -- .../rocketchat-slashcommands-msg/server.js | 5 +++- .../client/mute.js | 4 --- .../client/unmute.js | 4 --- .../rocketchat-slashcommands-mute/package.js | 8 +---- .../server/mute.js | 3 ++ .../server/unmute.js | 3 ++ .../client.js | 4 --- .../package.js | 6 +--- .../server.js | 5 +++- .../client/popup/messagePopupConfig.js | 22 +++++++++----- .../rocketchat-ui/client/lib/chatMessages.js | 15 ++++++---- 37 files changed, 55 insertions(+), 139 deletions(-) delete mode 100644 packages/rocketchat-rocketlets/client/communication/restclient.js delete mode 100644 packages/rocketchat-slashcommands-archiveroom/client.js delete mode 100644 packages/rocketchat-slashcommands-create/client.js delete mode 100644 packages/rocketchat-slashcommands-help/client.js delete mode 100644 packages/rocketchat-slashcommands-invite/client.js delete mode 100644 packages/rocketchat-slashcommands-inviteall/client.js delete mode 100644 packages/rocketchat-slashcommands-kick/client.js delete mode 100644 packages/rocketchat-slashcommands-msg/client.js delete mode 100644 packages/rocketchat-slashcommands-mute/client/mute.js delete mode 100644 packages/rocketchat-slashcommands-mute/client/unmute.js delete mode 100644 packages/rocketchat-slashcommands-unarchiveroom/client.js diff --git a/packages/rocketchat-lib/lib/slashCommand.js b/packages/rocketchat-lib/lib/slashCommand.js index 7f37a7933adc..69bb56b56b48 100644 --- a/packages/rocketchat-lib/lib/slashCommand.js +++ b/packages/rocketchat-lib/lib/slashCommand.js @@ -8,6 +8,7 @@ RocketChat.slashCommands.add = function(command, callback, options = {}, result) callback, params: options.params, description: options.description, + permission: options.permission, clientOnly: options.clientOnly || false, result }; diff --git a/packages/rocketchat-rocketlets/client/communication/index.js b/packages/rocketchat-rocketlets/client/communication/index.js index 8f92c01d21b7..7ee19cdf2081 100644 --- a/packages/rocketchat-rocketlets/client/communication/index.js +++ b/packages/rocketchat-rocketlets/client/communication/index.js @@ -1,4 +1,3 @@ -import { RocketletRestApiClient } from './restclient'; import { RocketletWebsocketReceiver } from './websockets'; -export { RocketletRestApiClient, RocketletWebsocketReceiver }; +export { RocketletWebsocketReceiver }; diff --git a/packages/rocketchat-rocketlets/client/communication/restclient.js b/packages/rocketchat-rocketlets/client/communication/restclient.js deleted file mode 100644 index 0a09c49074fc..000000000000 --- a/packages/rocketchat-rocketlets/client/communication/restclient.js +++ /dev/null @@ -1,30 +0,0 @@ -export class RocketletRestApiClient { - constructor(orch) { - this.orch = orch; - } - - get(endpoint, params) { - return this._jqueryCall('GET', endpoint, params); - } - - _jqueryCall(method, endpoint, params) { - return new Promise(function _rlRestApiGet(resolve, reject) { - jQuery.ajax({ - method, - url: `${ Meteor.absoluteUrl() }api/${ endpoint }`, - headers: { - 'Content-Type': 'application/json', - 'X-User-Id': localStorage['Meteor.userId'], - 'X-Auth-Token': localStorage['Meteor.loginToken'] - }, - data: params, - success: function _rlGetSuccess(result) { - resolve(result); - }, - error: function _rlGetFailure(xhr, status, errorThrown) { - reject(new Error(errorThrown)); - } - }); - }); - } -} diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js index 7fc1f4bf3e78..d65a626290fb 100644 --- a/packages/rocketchat-rocketlets/client/orchestrator.js +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -1,18 +1,13 @@ -import { RocketletRestApiClient, RocketletWebsocketReceiver } from './communication'; +import { RocketletWebsocketReceiver } from './communication'; class RocketletClientOrchestrator { constructor() { this.ws = new RocketletWebsocketReceiver(this); - this.rest = new RocketletRestApiClient(this); } getWsListener() { return this.ws; } - - getRestApiClient() { - return this.rest; - } } Meteor.startup(function _rlClientOrch() { diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js index f35d9cfbb5dd..7d6c7d73f12b 100644 --- a/packages/rocketchat-rocketlets/server/orchestrator.js +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -1,5 +1,5 @@ import { RealRocketletBridges } from './bridges'; -import { RocketletsRestApi, RocketletWebsocketNotifier } from './communication'; +import { RocketletWebsocketNotifier } from './communication'; import { RocketletMessagesConverter, RocketletRoomsConverter, RocketletSettingsConverter, RocketletUsersConverter } from './converters'; import { RocketletsModel, RocketletRealStorage } from './storage'; @@ -21,7 +21,6 @@ class RocketletServerOrchestrator { this._manager = new RocketletManager(this._storage, this._bridges); this._communicators = new Map(); - this._communicators.set('restapi', new RocketletsRestApi(this._manager)); this._communicators.set('notifier', new RocketletWebsocketNotifier()); } diff --git a/packages/rocketchat-slashcommands-archiveroom/client.js b/packages/rocketchat-slashcommands-archiveroom/client.js deleted file mode 100644 index 200e172e43fc..000000000000 --- a/packages/rocketchat-slashcommands-archiveroom/client.js +++ /dev/null @@ -1,4 +0,0 @@ -RocketChat.slashCommands.add('archive', null, { - description: 'Archive', - params: '#channel' -}); diff --git a/packages/rocketchat-slashcommands-archiveroom/package.js b/packages/rocketchat-slashcommands-archiveroom/package.js index 1d14abd954e7..4c287ba87cdf 100644 --- a/packages/rocketchat-slashcommands-archiveroom/package.js +++ b/packages/rocketchat-slashcommands-archiveroom/package.js @@ -6,7 +6,6 @@ Package.describe({ }); Package.onUse(function(api) { - api.use([ 'ecmascript', 'check', @@ -15,7 +14,5 @@ Package.onUse(function(api) { api.use('templating', 'client'); - api.addFiles('client.js', 'client'); - api.addFiles('messages.js', 'server'); - api.addFiles('server.js', 'server'); + api.addFiles(['messages.js', 'server.js'], 'server'); }); diff --git a/packages/rocketchat-slashcommands-create/client.js b/packages/rocketchat-slashcommands-create/client.js deleted file mode 100644 index 54d6aa95d601..000000000000 --- a/packages/rocketchat-slashcommands-create/client.js +++ /dev/null @@ -1,4 +0,0 @@ -RocketChat.slashCommands.add('create', null, { - description: 'Create_A_New_Channel', - params: '#channel' -}); diff --git a/packages/rocketchat-slashcommands-create/package.js b/packages/rocketchat-slashcommands-create/package.js index 3f47398d6216..112be0d49e1e 100644 --- a/packages/rocketchat-slashcommands-create/package.js +++ b/packages/rocketchat-slashcommands-create/package.js @@ -6,7 +6,6 @@ Package.describe({ }); Package.onUse(function(api) { - api.use([ 'ecmascript', 'check', @@ -15,6 +14,5 @@ Package.onUse(function(api) { api.use('templating', 'client'); - api.addFiles('client.js', 'client'); api.addFiles('server.js', 'server'); }); diff --git a/packages/rocketchat-slashcommands-help/client.js b/packages/rocketchat-slashcommands-help/client.js deleted file mode 100644 index 5f26f43b21b1..000000000000 --- a/packages/rocketchat-slashcommands-help/client.js +++ /dev/null @@ -1,3 +0,0 @@ -RocketChat.slashCommands.add('help', undefined, { - description: 'Show_the_keyboard_shortcut_list' -}); diff --git a/packages/rocketchat-slashcommands-help/package.js b/packages/rocketchat-slashcommands-help/package.js index f8cdabea9deb..f9a6529b5ff7 100644 --- a/packages/rocketchat-slashcommands-help/package.js +++ b/packages/rocketchat-slashcommands-help/package.js @@ -15,6 +15,5 @@ Package.onUse(function(api) { api.use('templating', 'client'); - api.addFiles('client.js', 'client'); api.addFiles('server.js', 'server'); }); diff --git a/packages/rocketchat-slashcommands-help/server.js b/packages/rocketchat-slashcommands-help/server.js index f8aefcd869cb..490c7020692d 100644 --- a/packages/rocketchat-slashcommands-help/server.js +++ b/packages/rocketchat-slashcommands-help/server.js @@ -6,10 +6,6 @@ RocketChat.slashCommands.add('help', function Help(command, params, item) { - - if (command !== 'help') { - return; - } const user = Meteor.users.findOne(Meteor.userId()); const keys = [{ 'Open_channel_user_search': 'Command (or Ctrl) + p OR Command (or Ctrl) + k' diff --git a/packages/rocketchat-slashcommands-invite/client.js b/packages/rocketchat-slashcommands-invite/client.js deleted file mode 100644 index c5440a78d065..000000000000 --- a/packages/rocketchat-slashcommands-invite/client.js +++ /dev/null @@ -1,4 +0,0 @@ -RocketChat.slashCommands.add('invite', undefined, { - description: 'Invite_user_to_join_channel', - params: '@username' -}); diff --git a/packages/rocketchat-slashcommands-invite/package.js b/packages/rocketchat-slashcommands-invite/package.js index 1a410fa17800..bd92d1165df0 100644 --- a/packages/rocketchat-slashcommands-invite/package.js +++ b/packages/rocketchat-slashcommands-invite/package.js @@ -6,7 +6,6 @@ Package.describe({ }); Package.onUse(function(api) { - api.use([ 'ecmascript', 'check', @@ -15,6 +14,5 @@ Package.onUse(function(api) { api.use('templating', 'client'); - api.addFiles('client.js', 'client'); api.addFiles('server.js', 'server'); }); diff --git a/packages/rocketchat-slashcommands-inviteall/client.js b/packages/rocketchat-slashcommands-inviteall/client.js deleted file mode 100644 index 1e6bd4917e88..000000000000 --- a/packages/rocketchat-slashcommands-inviteall/client.js +++ /dev/null @@ -1,8 +0,0 @@ -RocketChat.slashCommands.add('invite-all-to', undefined, { - description: 'Invite_user_to_join_channel_all_to', - params: '#room' -}); -RocketChat.slashCommands.add('invite-all-from', undefined, { - description: 'Invite_user_to_join_channel_all_from', - params: '#room' -}); diff --git a/packages/rocketchat-slashcommands-inviteall/package.js b/packages/rocketchat-slashcommands-inviteall/package.js index e44deba52141..92b40866f3bd 100644 --- a/packages/rocketchat-slashcommands-inviteall/package.js +++ b/packages/rocketchat-slashcommands-inviteall/package.js @@ -15,6 +15,5 @@ Package.onUse(function(api) { api.use('templating', 'client'); - api.addFiles('client.js', 'client'); api.addFiles('server.js', 'server'); }); diff --git a/packages/rocketchat-slashcommands-inviteall/server.js b/packages/rocketchat-slashcommands-inviteall/server.js index a80cc3b04d08..133c8200ef18 100644 --- a/packages/rocketchat-slashcommands-inviteall/server.js +++ b/packages/rocketchat-slashcommands-inviteall/server.js @@ -4,7 +4,6 @@ */ function inviteAll(type) { - return function inviteAll(command, params, item) { if (!/invite\-all-(to|from)/.test(command) || !Match.test(params, String)) { @@ -76,6 +75,7 @@ function inviteAll(type) { } }; } + RocketChat.slashCommands.add('invite-all-to', inviteAll('to'), { description: 'Invite_user_to_join_channel_all_to', params: '#room' diff --git a/packages/rocketchat-slashcommands-kick/client.js b/packages/rocketchat-slashcommands-kick/client.js deleted file mode 100644 index 7b1d001c6f6e..000000000000 --- a/packages/rocketchat-slashcommands-kick/client.js +++ /dev/null @@ -1,10 +0,0 @@ -RocketChat.slashCommands.add('kick', function(command, params) { - const username = params.trim(); - if (username === '') { - return; - } - return username.replace('@', ''); -}, { - description: 'Remove_someone_from_room', - params: '@username' -}); diff --git a/packages/rocketchat-slashcommands-kick/package.js b/packages/rocketchat-slashcommands-kick/package.js index d73a92fca71e..32d102a112be 100644 --- a/packages/rocketchat-slashcommands-kick/package.js +++ b/packages/rocketchat-slashcommands-kick/package.js @@ -6,7 +6,6 @@ Package.describe({ }); Package.onUse(function(api) { - api.use([ 'ecmascript', 'check', @@ -15,6 +14,5 @@ Package.onUse(function(api) { api.use('templating', 'client'); - api.addFiles('client.js', 'client'); api.addFiles('server.js', 'server'); }); diff --git a/packages/rocketchat-slashcommands-kick/server.js b/packages/rocketchat-slashcommands-kick/server.js index ff484022fe54..8b6a298838cf 100644 --- a/packages/rocketchat-slashcommands-kick/server.js +++ b/packages/rocketchat-slashcommands-kick/server.js @@ -39,5 +39,6 @@ const Kick = function(command, params, {rid}) { RocketChat.slashCommands.add('kick', Kick, { description: 'Remove_someone_from_room', - params: '@username' + params: '@username', + permission: 'remove-user' }); diff --git a/packages/rocketchat-slashcommands-leave/leave.js b/packages/rocketchat-slashcommands-leave/leave.js index a6dd74fa82e1..6b748eb9eb01 100644 --- a/packages/rocketchat-slashcommands-leave/leave.js +++ b/packages/rocketchat-slashcommands-leave/leave.js @@ -20,5 +20,5 @@ function Leave(command, params, item) { } } -RocketChat.slashCommands.add('leave', Meteor.isClient ? undefined : Leave, { description: 'Leave_the_current_channel' }); -RocketChat.slashCommands.add('part', Meteor.isClient ? undefined : Leave, { description: 'Leave_the_current_channel' }); +RocketChat.slashCommands.add('leave', Leave, { description: 'Leave_the_current_channel' }); +RocketChat.slashCommands.add('part', Leave, { description: 'Leave_the_current_channel' }); diff --git a/packages/rocketchat-slashcommands-leave/package.js b/packages/rocketchat-slashcommands-leave/package.js index c5260f9dee8d..1bbd3a6e037a 100644 --- a/packages/rocketchat-slashcommands-leave/package.js +++ b/packages/rocketchat-slashcommands-leave/package.js @@ -10,5 +10,6 @@ Package.onUse(function(api) { 'ecmascript', 'rocketchat:lib' ]); - api.addFiles('leave.js'); + + api.addFiles('leave.js', 'server'); }); diff --git a/packages/rocketchat-slashcommands-me/me.js b/packages/rocketchat-slashcommands-me/me.js index 97d0e9e6b0cd..c2e51a03c6d2 100644 --- a/packages/rocketchat-slashcommands-me/me.js +++ b/packages/rocketchat-slashcommands-me/me.js @@ -7,6 +7,7 @@ RocketChat.slashCommands.add('me', function Me(command, params, item) { if (command !== 'me') { return; } + if (_.trim(params)) { const msg = item; msg.msg = `_${ params }_`; diff --git a/packages/rocketchat-slashcommands-me/package.js b/packages/rocketchat-slashcommands-me/package.js index eb2f4a5e6c08..0a164dc9544e 100644 --- a/packages/rocketchat-slashcommands-me/package.js +++ b/packages/rocketchat-slashcommands-me/package.js @@ -11,5 +11,5 @@ Package.onUse(function(api) { 'rocketchat:lib' ]); - api.addFiles('me.js', ['server', 'client']); + api.addFiles('me.js', 'server'); }); diff --git a/packages/rocketchat-slashcommands-msg/client.js b/packages/rocketchat-slashcommands-msg/client.js deleted file mode 100644 index 81b75c2c9d87..000000000000 --- a/packages/rocketchat-slashcommands-msg/client.js +++ /dev/null @@ -1,4 +0,0 @@ -RocketChat.slashCommands.add('msg', undefined, { - description: 'Direct_message_someone', - params: '@username ' -}); diff --git a/packages/rocketchat-slashcommands-msg/package.js b/packages/rocketchat-slashcommands-msg/package.js index bafb90f1c42d..366686a6cc3c 100644 --- a/packages/rocketchat-slashcommands-msg/package.js +++ b/packages/rocketchat-slashcommands-msg/package.js @@ -6,7 +6,6 @@ Package.describe({ }); Package.onUse(function(api) { - api.use([ 'ecmascript', 'check', @@ -15,6 +14,5 @@ Package.onUse(function(api) { api.use('templating', 'client'); - api.addFiles('client.js', 'client'); api.addFiles('server.js', 'server'); }); diff --git a/packages/rocketchat-slashcommands-msg/server.js b/packages/rocketchat-slashcommands-msg/server.js index 3e546c8526fc..2fbc8d512748 100644 --- a/packages/rocketchat-slashcommands-msg/server.js +++ b/packages/rocketchat-slashcommands-msg/server.js @@ -43,4 +43,7 @@ function Msg(command, params, item) { Meteor.call('sendMessage', msgObject); } -RocketChat.slashCommands.add('msg', Msg); +RocketChat.slashCommands.add('msg', Msg, { + description: 'Direct_message_someone', + params: '@username ' +}); diff --git a/packages/rocketchat-slashcommands-mute/client/mute.js b/packages/rocketchat-slashcommands-mute/client/mute.js deleted file mode 100644 index 14735ce70ae9..000000000000 --- a/packages/rocketchat-slashcommands-mute/client/mute.js +++ /dev/null @@ -1,4 +0,0 @@ -RocketChat.slashCommands.add('mute', undefined, { - description: 'Mute_someone_in_room', - params: '@username' -}); diff --git a/packages/rocketchat-slashcommands-mute/client/unmute.js b/packages/rocketchat-slashcommands-mute/client/unmute.js deleted file mode 100644 index 447e02cec79b..000000000000 --- a/packages/rocketchat-slashcommands-mute/client/unmute.js +++ /dev/null @@ -1,4 +0,0 @@ -RocketChat.slashCommands.add('unmute', undefined, { - description: 'Unmute_someone_in_room', - params: '@username' -}); diff --git a/packages/rocketchat-slashcommands-mute/package.js b/packages/rocketchat-slashcommands-mute/package.js index aee8058a6f7b..4c0c8a5c9d07 100644 --- a/packages/rocketchat-slashcommands-mute/package.js +++ b/packages/rocketchat-slashcommands-mute/package.js @@ -6,17 +6,11 @@ Package.describe({ }); Package.onUse(function(api) { - api.use([ 'ecmascript', 'check', 'rocketchat:lib' ]); - api.use('templating', 'client'); - - api.addFiles('client/mute.js', 'client'); - api.addFiles('client/unmute.js', 'client'); - api.addFiles('server/mute.js', 'server'); - api.addFiles('server/unmute.js', 'server'); + api.addFiles(['server/mute.js', 'server/unmute.js'], 'server'); }); diff --git a/packages/rocketchat-slashcommands-mute/server/mute.js b/packages/rocketchat-slashcommands-mute/server/mute.js index 21601cebe080..2c477609d797 100644 --- a/packages/rocketchat-slashcommands-mute/server/mute.js +++ b/packages/rocketchat-slashcommands-mute/server/mute.js @@ -42,4 +42,7 @@ RocketChat.slashCommands.add('mute', function Mute(command, params, item) { rid: item.rid, username }); +}, { + description: 'Mute_someone_in_room', + params: '@username' }); diff --git a/packages/rocketchat-slashcommands-mute/server/unmute.js b/packages/rocketchat-slashcommands-mute/server/unmute.js index 0d5d6a93e12e..1a864ab63f89 100644 --- a/packages/rocketchat-slashcommands-mute/server/unmute.js +++ b/packages/rocketchat-slashcommands-mute/server/unmute.js @@ -41,4 +41,7 @@ RocketChat.slashCommands.add('unmute', function Unmute(command, params, item) { rid: item.rid, username }); +}, { + description: 'Unmute_someone_in_room', + params: '@username' }); diff --git a/packages/rocketchat-slashcommands-unarchiveroom/client.js b/packages/rocketchat-slashcommands-unarchiveroom/client.js deleted file mode 100644 index 25be36519e8a..000000000000 --- a/packages/rocketchat-slashcommands-unarchiveroom/client.js +++ /dev/null @@ -1,4 +0,0 @@ -RocketChat.slashCommands.add('unarchive', null, { - description: 'Unarchive', - params: '#channel' -}); diff --git a/packages/rocketchat-slashcommands-unarchiveroom/package.js b/packages/rocketchat-slashcommands-unarchiveroom/package.js index 0b3120438385..7667a15c0b9a 100644 --- a/packages/rocketchat-slashcommands-unarchiveroom/package.js +++ b/packages/rocketchat-slashcommands-unarchiveroom/package.js @@ -13,9 +13,5 @@ Package.onUse(function(api) { 'rocketchat:lib' ]); - api.use('templating', 'client'); - - api.addFiles('client.js', 'client'); - api.addFiles('messages.js', 'server'); - api.addFiles('server.js', 'server'); + api.addFiles(['messages.js', 'server.js'], 'server'); }); diff --git a/packages/rocketchat-slashcommands-unarchiveroom/server.js b/packages/rocketchat-slashcommands-unarchiveroom/server.js index a9884b870755..968dde2444d4 100644 --- a/packages/rocketchat-slashcommands-unarchiveroom/server.js +++ b/packages/rocketchat-slashcommands-unarchiveroom/server.js @@ -50,4 +50,7 @@ function Unarchive(command, params, item) { return Unarchive; } -RocketChat.slashCommands.add('unarchive', Unarchive); +RocketChat.slashCommands.add('unarchive', Unarchive, { + description: 'Unarchive', + params: '#channel' +}); diff --git a/packages/rocketchat-ui-message/client/popup/messagePopupConfig.js b/packages/rocketchat-ui-message/client/popup/messagePopupConfig.js index 4293d3e1c90c..e8fadcee5dd3 100644 --- a/packages/rocketchat-ui-message/client/popup/messagePopupConfig.js +++ b/packages/rocketchat-ui-message/client/popup/messagePopupConfig.js @@ -236,14 +236,22 @@ Template.messagePopupConfig.helpers({ return { _id: command, params: item.params ? TAPi18n.__(item.params) : '', - description: TAPi18n.__(item.description) + description: TAPi18n.__(item.description), + permission: item.permission }; - }) - .filter(command => command._id.indexOf(filter) > -1) - .sort(function(a, b) { - return a._id > b._id; - }) - .slice(0, 11); + }).filter(command => { + const isMatch = command._id.indexOf(filter) > -1; + + if (!isMatch) { + return false; + } + + if (!command.permission) { + return true; + } + + return RocketChat.authz.hasAtLeastOnePermission(command.permission, Session.get('openedRoom')); + }).sort((a, b) => a._id > b._id).slice(0, 11); } }; return config; diff --git a/packages/rocketchat-ui/client/lib/chatMessages.js b/packages/rocketchat-ui/client/lib/chatMessages.js index f0046e918df9..a3f006ddda20 100644 --- a/packages/rocketchat-ui/client/lib/chatMessages.js +++ b/packages/rocketchat-ui/client/lib/chatMessages.js @@ -217,12 +217,16 @@ this.ChatMessages = class ChatMessages { const commandOptions = RocketChat.slashCommands.commands[match[1]]; command = match[1]; const param = match[2] || ''; - if (commandOptions.clientOnly) { - commandOptions.callback(command, param, msgObject); - } else { - Meteor.call('slashCommand', {cmd: command, params: param, msg: msgObject }, (err, result) => typeof commandOptions.result === 'function' && commandOptions.result(err, result, {cmd: command, params: param, msg: msgObject })); + + if (!commandOptions.permission || RocketChat.authz.hasAtLeastOnePermission(commandOptions.permission, Session.get('openedRoom'))) { + if (commandOptions.clientOnly) { + commandOptions.callback(command, param, msgObject); + } else { + Meteor.call('slashCommand', {cmd: command, params: param, msg: msgObject }, (err, result) => typeof commandOptions.result === 'function' && commandOptions.result(err, result, {cmd: command, params: param, msg: msgObject })); + } + + return; } - return; } if (!RocketChat.settings.get('Message_AllowUnrecognizedSlashCommand')) { @@ -236,6 +240,7 @@ this.ChatMessages = class ChatMessages { }, private: true }; + ChatMessage.upsert({ _id: invalidCommandMsg._id }, invalidCommandMsg); return; } From f7e34cf69c1a3e5dd3b2225c38aae1a320be43d2 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Wed, 30 Aug 2017 12:41:59 -0500 Subject: [PATCH 063/801] Work on bridges and saving of data, basic messages are now sent :tada: --- packages/rocketchat-rocketlets/package.js | 10 ++- .../server/bridges/bridges.js | 24 +++++++ .../server/bridges/commands.js | 3 +- .../server/bridges/environmental.js | 4 +- .../server/bridges/index.js | 15 +++- .../server/bridges/messages.js | 23 ++++++ .../server/bridges/persistence.js | 19 +++++ .../server/bridges/rooms.js | 45 ++++++++++++ .../server/bridges/settings.js | 4 +- .../server/bridges/users.js | 17 +++++ .../server/communication/rest.js | 18 ++--- .../server/converters/messages.js | 27 +++++++ .../server/converters/rooms.js | 71 ++++++++++++++++++- .../server/converters/users.js | 60 +++++++++++++++- .../server/orchestrator.js | 10 ++- .../server/storage/index.js | 3 +- .../server/storage/rl-persistence-model.js | 5 ++ 17 files changed, 336 insertions(+), 22 deletions(-) create mode 100644 packages/rocketchat-rocketlets/server/bridges/messages.js create mode 100644 packages/rocketchat-rocketlets/server/bridges/persistence.js create mode 100644 packages/rocketchat-rocketlets/server/bridges/rooms.js create mode 100644 packages/rocketchat-rocketlets/server/bridges/users.js create mode 100644 packages/rocketchat-rocketlets/server/storage/rl-persistence-model.js diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index bc7473b8e7af..cebcc6ef2f5f 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -15,6 +15,7 @@ Package.onUse(function(api) { // Storage api.addFiles([ 'server/storage/rl-model.js', + 'server/storage/rl-persistence-model.js', 'server/storage/storage.js', 'server/storage/index.js' ], 'server'); @@ -24,7 +25,11 @@ Package.onUse(function(api) { 'server/bridges/bridges.js', 'server/bridges/commands.js', 'server/bridges/environmental.js', + 'server/bridges/messages.js', + 'server/bridges/persistence.js', + 'server/bridges/rooms.js', 'server/bridges/settings.js', + 'server/bridges/users.js', 'server/bridges/index.js' ], 'server'); @@ -35,6 +40,7 @@ Package.onUse(function(api) { 'server/communication/index.js' ], 'server'); + // RocketChat <-> Rocketlet Data Converters api.addFiles([ 'server/converters/messages.js', 'server/converters/rooms.js', @@ -60,6 +66,6 @@ Package.onUse(function(api) { Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.16', - 'temporary-rocketlets-ts-definition': '0.6.2' + 'temporary-rocketlets-server': '0.1.20', + 'temporary-rocketlets-ts-definition': '0.6.11' }); diff --git a/packages/rocketchat-rocketlets/server/bridges/bridges.js b/packages/rocketchat-rocketlets/server/bridges/bridges.js index 713987341246..37d83623f62a 100644 --- a/packages/rocketchat-rocketlets/server/bridges/bridges.js +++ b/packages/rocketchat-rocketlets/server/bridges/bridges.js @@ -1,7 +1,11 @@ import { RocketletBridges } from 'temporary-rocketlets-server/server/bridges'; import { RocketletCommandsBridge } from './commands'; import { RocketletEnvironmentalVariableBridge } from './environmental'; +import { RocketletMessageBridge } from './messages'; +import { RocketletPersistenceBridge } from './persistence'; +import { RocketletRoomBridge } from './rooms'; import { RocketletSettingBridge } from './settings'; +import { RocketletUserBridge } from './users'; export class RealRocketletBridges extends RocketletBridges { constructor(orch) { @@ -9,7 +13,11 @@ export class RealRocketletBridges extends RocketletBridges { this._cmdBridge = new RocketletCommandsBridge(orch); this._envBridge = new RocketletEnvironmentalVariableBridge(orch); + this._msgBridge = new RocketletMessageBridge(orch); + this._persistBridge = new RocketletPersistenceBridge(orch); + this._roomBridge = new RocketletRoomBridge(orch); this._setsBridge = new RocketletSettingBridge(orch); + this._userBridge = new RocketletUserBridge(orch); } getCommandBridge() { @@ -20,7 +28,23 @@ export class RealRocketletBridges extends RocketletBridges { return this._envBridge; } + getMessageBridge() { + return this._msgBridge; + } + + getPersistenceBridge() { + return this._persistBridge; + } + + getRoomBridge() { + return this._roomBridge; + } + getServerSettingBridge() { return this._setsBridge; } + + getUserBridge() { + return this._userBridge; + } } diff --git a/packages/rocketchat-rocketlets/server/bridges/commands.js b/packages/rocketchat-rocketlets/server/bridges/commands.js index 3bf584ecbd59..5a15730ed1d3 100644 --- a/packages/rocketchat-rocketlets/server/bridges/commands.js +++ b/packages/rocketchat-rocketlets/server/bridges/commands.js @@ -97,6 +97,7 @@ export class RocketletCommandsBridge { const room = this.orch.getConverters().get('rooms').convertById(message.rid); const params = parameters.length === 0 || parameters === ' ' ? [] : parameters.split(' '); - this.orch.getManager().getCommandManager().executeCommand(command, new SlashCommandContext(user, room, params)); + const context = new SlashCommandContext(Object.freeze(user), Object.freeze(room), Object.freeze(params)); + this.orch.getManager().getCommandManager().executeCommand(command, context); } } diff --git a/packages/rocketchat-rocketlets/server/bridges/environmental.js b/packages/rocketchat-rocketlets/server/bridges/environmental.js index 731fb3e798e0..9b4188e75a85 100644 --- a/packages/rocketchat-rocketlets/server/bridges/environmental.js +++ b/packages/rocketchat-rocketlets/server/bridges/environmental.js @@ -1,6 +1,6 @@ export class RocketletEnvironmentalVariableBridge { - constructor(converters) { - this.converters = converters; + constructor(orch) { + this.orch = orch; } getValueByName(envVarName, rocketletId) { diff --git a/packages/rocketchat-rocketlets/server/bridges/index.js b/packages/rocketchat-rocketlets/server/bridges/index.js index bab289eac933..0e3881bb49e1 100644 --- a/packages/rocketchat-rocketlets/server/bridges/index.js +++ b/packages/rocketchat-rocketlets/server/bridges/index.js @@ -1,6 +1,19 @@ import { RealRocketletBridges } from './bridges'; import { RocketletCommandsBridge } from './commands'; import { RocketletEnvironmentalVariableBridge } from './environmental'; +import { RocketletMessageBridge } from './messages'; +import { RocketletPersistenceBridge } from './persistence'; +import { RocketletRoomBridge } from './rooms'; import { RocketletSettingBridge } from './settings'; +import { RocketletUserBridge } from './users'; -export { RealRocketletBridges, RocketletCommandsBridge, RocketletEnvironmentalVariableBridge, RocketletSettingBridge }; +export { + RealRocketletBridges, + RocketletCommandsBridge, + RocketletEnvironmentalVariableBridge, + RocketletMessageBridge, + RocketletPersistenceBridge, + RocketletRoomBridge, + RocketletSettingBridge, + RocketletUserBridge +}; diff --git a/packages/rocketchat-rocketlets/server/bridges/messages.js b/packages/rocketchat-rocketlets/server/bridges/messages.js new file mode 100644 index 000000000000..812e930dc429 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/messages.js @@ -0,0 +1,23 @@ +export class RocketletMessageBridge { + constructor(orch) { + this.orch = orch; + } + + create(message, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is creating a new message.`, message); + + let msg = this.orch.getConverters().get('messages').convertRocketletMessage(message); + + Meteor.runAsUser(msg.u._id, () => { + msg = Meteor.call('sendMessage', msg); + }); + + return msg._id; + } + + getById(messageId, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is getting the message: "${ messageId }"`); + + return this.orch.getConverters().get('messages').convertById(messageId); + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/persistence.js b/packages/rocketchat-rocketlets/server/bridges/persistence.js new file mode 100644 index 000000000000..01661d342645 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/persistence.js @@ -0,0 +1,19 @@ +export class RocketletPersistenceBridge { + constructor(orch) { + this.orch = orch; + } + + create(data, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is storing a new object in their persistence.`, data); + + return this.orch.getPersistenceModel().insert({ rocketletId, data }); + } + + readById(id, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is reading their data in their persistence with the id: "${ id }"`); + + const record = this.orch.getPersistenceModel().findOneById(id); + + return record.data; + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/rooms.js b/packages/rocketchat-rocketlets/server/bridges/rooms.js new file mode 100644 index 000000000000..c6e8db60ae0f --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/rooms.js @@ -0,0 +1,45 @@ +import { RoomType } from 'temporary-rocketlets-ts-definition/rooms'; + +export class RocketletRoomBridge { + constructor(orch) { + this.orch = orch; + } + + create(room, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is creating a new room.`, room); + + const rcRoom = this.orch.getConverters().get('rooms').convertRocketletRoom(room); + let method; + + switch (room.type) { + case RoomType.CHANNEL: + method = 'createChannel'; + break; + case RoomType.PRIVATE_GROUP: + method = 'createPrivateGroup'; + break; + default: + throw new Error('Only channels and private groups can be created.'); + } + + let rid; + Meteor.runAsUser(room.creator.id, () => { + const info = Meteor.call(method, rcRoom.usernames); + rid = info.rid; + }); + + return rid; + } + + getById(roomId, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is getting the roomById: "${ roomId }"`); + + return this.orch.getConverters().get('rooms').convertById(roomId); + } + + getByName(roomName, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is getting the roomByName: "${ roomName }"`); + + return this.orch.getConverters().get('rooms').convertByName(roomName); + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/settings.js b/packages/rocketchat-rocketlets/server/bridges/settings.js index b27d2be634f4..c997bc7f5746 100644 --- a/packages/rocketchat-rocketlets/server/bridges/settings.js +++ b/packages/rocketchat-rocketlets/server/bridges/settings.js @@ -1,6 +1,6 @@ export class RocketletSettingBridge { - constructor(converters) { - this.converters = converters; + constructor(orch) { + this.orch = orch; } getAll(rocketletId) { diff --git a/packages/rocketchat-rocketlets/server/bridges/users.js b/packages/rocketchat-rocketlets/server/bridges/users.js new file mode 100644 index 000000000000..6652b1ee285b --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/users.js @@ -0,0 +1,17 @@ +export class RocketletUserBridge { + constructor(orch) { + this.orch = orch; + } + + getById(userId, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is getting the userId: "${ userId }"`); + + return this.orch.getConverters().get('users').convertById(userId); + } + + getByUsername(username, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is getting the username: "${ username }"`); + + return this.orch.getConverters().get('users').convertByUsername(username); + } +} diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js index d8b58d47f9c4..0b6bc5153796 100644 --- a/packages/rocketchat-rocketlets/server/communication/rest.js +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -39,22 +39,20 @@ export class RocketletsRestApi { const fileHandler = this._handleFile; this.api.addRoute('', { authRequired: true }, { - post() { - console.log('Creating a new Rocketlet via the rest api'); + get() { + const rocketlets = manager.get().map(prl => prl.getInfo()); + return { success: true, rocketlets }; + }, + post() { const buff = fileHandler(this.request, 'rocketlet'); const item = Meteor.wrapAsync((callback) => { - manager.add(buff.toString('base64')).then((rl) => { - console.log('Success?'); - callback(undefined, rl); - }).catch((e) => { + manager.add(buff.toString('base64')).then((rl) => callback(undefined, rl)).catch((e) => { console.warn('Error!', e); callback(e); }); })(); - console.log('result:', item.rocketlet.info); - return { success: true, rocketlet: item.rocketlet.info }; } }); @@ -62,7 +60,9 @@ export class RocketletsRestApi { this.api.addRoute(':id', { authRequired: true }, { get() { console.log('Getting:', this.urlParams.id); - return { success: false }; + const rocketlet = manager.getOneById(this.urlParams.id).getInfo(); + + return { success: true, rocketlet }; }, post() { console.log('Updating:', this.urlParams.id); diff --git a/packages/rocketchat-rocketlets/server/converters/messages.js b/packages/rocketchat-rocketlets/server/converters/messages.js index 3b6892da346f..12c8d80234ae 100644 --- a/packages/rocketchat-rocketlets/server/converters/messages.js +++ b/packages/rocketchat-rocketlets/server/converters/messages.js @@ -6,6 +6,10 @@ export class RocketletMessagesConverter { convertById(msgId) { const msg = RocketChat.models.Messages.getOneById(msgId); + if (!msg) { + return undefined; + } + return { id: msg._id, text: msg.msg @@ -18,4 +22,27 @@ export class RocketletMessagesConverter { text: msgObj.msg }; } + + convertRocketletMessage(message) { + if (!message) { + return undefined; + } + + const room = RocketChat.models.Rooms.findOneById(message.room.id); + const user = RocketChat.models.Users.findOneById(message.sender.id); + + if (!room || !user) { + throw new Error('Invalid user or room provided on the message.'); + } + + return { + _id: message.id || Random.id(), + msg: message.text, + rid: room._id, + u: { + _id: user._id, + username: user.username + } + }; + } } diff --git a/packages/rocketchat-rocketlets/server/converters/rooms.js b/packages/rocketchat-rocketlets/server/converters/rooms.js index d198482bb595..d9b98f2a718e 100644 --- a/packages/rocketchat-rocketlets/server/converters/rooms.js +++ b/packages/rocketchat-rocketlets/server/converters/rooms.js @@ -1,3 +1,5 @@ +import { RoomType } from 'temporary-rocketlets-ts-definition/rooms'; + export class RocketletRoomsConverter { constructor(orch) { this.orch = orch; @@ -6,8 +8,75 @@ export class RocketletRoomsConverter { convertById(roomId) { const room = RocketChat.models.Rooms.findOneById(roomId); + return this._convertToRocketlet(room); + } + + convertByName(roomName) { + const room = RocketChat.models.Rooms.findOneByName(roomName); + + return this._convertToRocketlet(room); + } + + convertRocketletRoom(room) { + if (!room) { + return undefined; + } + + const creator = RocketChat.models.Users.findOneById(room.creator.id); + return { - id: room._id + _id: room.id, + u: { + _id: creator._id, + username: creator.username + }, + ts: room.createdAt, + t: room.type, + name: room.name, + msgs: room.messageCount || 0, + default: typeof room.isDefault === 'undefined' ? false : room.isDefault, + _updatedAt: room.updatedAt, + lm: room.lastModifiedAt, + usernames: room.usernames }; } + + _convertToRocketlet(room) { + if (!room) { + return undefined; + } + + let creator; + if (room.u) { + creator = this.orch.getConverters().get('users').convertById(room.u._id); + } + + return { + id: room._id, + name: room.name, + type: this._convertTypeToRocketlet(room.t), + creator, + usernames: room.usernames, + isDefault: typeof room.default === 'undefined' ? false : room.default, + messageCount: room.msgs, + createdAt: room.ts, + updatedAt: room._updatedAt, + lastModifiedAt: room.lm + }; + } + + _convertTypeToRocketlet(typeChar) { + switch (typeChar) { + case 'c': + return RoomType.CHANNEL; + case 'p': + return RoomType.PRIVATE_GROUP; + case 'd': + return RoomType.DIRECT_MESSAGE; + case 'lc': + return RoomType.LIVE_CHAT; + default: + throw new Error(`Unknown room type of: "${ typeChar }"`); + } + } } diff --git a/packages/rocketchat-rocketlets/server/converters/users.js b/packages/rocketchat-rocketlets/server/converters/users.js index 6f52033f096b..4cd1a1d65deb 100644 --- a/packages/rocketchat-rocketlets/server/converters/users.js +++ b/packages/rocketchat-rocketlets/server/converters/users.js @@ -1,3 +1,5 @@ +import { UserStatusConnection, UserType } from 'temporary-rocketlets-ts-definition/users'; + export class RocketletUsersConverter { constructor(orch) { this.orch = orch; @@ -6,8 +8,64 @@ export class RocketletUsersConverter { convertById(userId) { const user = RocketChat.models.Users.findOneById(userId); + return this._convertToRocketlet(user); + } + + convertByUsername(username) { + const user = RocketChat.models.Users.findOneByUsername(username); + + return this._convertToRocketlet(user); + } + + _convertToRocketlet(user) { + if (!user) { + return undefined; + } + + const type = this._convertUserTypeToEnum(user.type); + const status = this._convertStatusConnectionToEnum(user.status); + const statusConnection = this._convertStatusConnectionToEnum(user.statusConnection); + return { - id: user._id + id: user._id, + username: user.username, + emails: user.emails, + type, + isEnabled: user.active, + name: user.name, + roles: user.roles, + status, + statusConnection, + utcOffset: user.utcOffset, + createdAt: user.createdAt, + updatedAt: user._updatedAt, + lastLoginAt: user.lastLogin }; } + + _convertUserTypeToEnum(type) { + switch (type) { + case 'user': + return UserType.USER; + case 'bot': + return UserType.BOT; + default: + throw new Error('Unknown user type of:', type); + } + } + + _convertStatusConnectionToEnum(status) { + switch (status) { + case 'offline': + return UserStatusConnection.OFFLINE; + case 'online': + return UserStatusConnection.ONLINE; + case 'away': + return UserStatusConnection.AWAY; + case 'busy': + return UserStatusConnection.BUSY; + default: + throw new Error('Unknown status type of:', status); + } + } } diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js index 7d6c7d73f12b..7bc44068928c 100644 --- a/packages/rocketchat-rocketlets/server/orchestrator.js +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -1,13 +1,14 @@ import { RealRocketletBridges } from './bridges'; -import { RocketletWebsocketNotifier } from './communication'; +import { RocketletsRestApi, RocketletWebsocketNotifier } from './communication'; import { RocketletMessagesConverter, RocketletRoomsConverter, RocketletSettingsConverter, RocketletUsersConverter } from './converters'; -import { RocketletsModel, RocketletRealStorage } from './storage'; +import { RocketletsModel, RocketletsPersistenceModel, RocketletRealStorage } from './storage'; import { RocketletManager } from 'temporary-rocketlets-server/server/RocketletManager'; class RocketletServerOrchestrator { constructor() { this._model = new RocketletsModel(); + this._persistModel = new RocketletsPersistenceModel(); this._storage = new RocketletRealStorage(this._model); this._converters = new Map(); @@ -22,12 +23,17 @@ class RocketletServerOrchestrator { this._communicators = new Map(); this._communicators.set('notifier', new RocketletWebsocketNotifier()); + this._communicators.set('restapi', new RocketletsRestApi(this._manager)); } getModel() { return this._model; } + getPersistenceModel() { + return this._persistModel; + } + getStorage() { return this._storage; } diff --git a/packages/rocketchat-rocketlets/server/storage/index.js b/packages/rocketchat-rocketlets/server/storage/index.js index 45a5e19e9c46..d47a7b1962ca 100644 --- a/packages/rocketchat-rocketlets/server/storage/index.js +++ b/packages/rocketchat-rocketlets/server/storage/index.js @@ -1,4 +1,5 @@ import { RocketletsModel } from './rl-model'; +import { RocketletsPersistenceModel } from './rl-persistence-model'; import { RocketletRealStorage } from './storage'; -export { RocketletsModel, RocketletRealStorage }; +export { RocketletsModel, RocketletsPersistenceModel, RocketletRealStorage }; diff --git a/packages/rocketchat-rocketlets/server/storage/rl-persistence-model.js b/packages/rocketchat-rocketlets/server/storage/rl-persistence-model.js new file mode 100644 index 000000000000..7b70e407c813 --- /dev/null +++ b/packages/rocketchat-rocketlets/server/storage/rl-persistence-model.js @@ -0,0 +1,5 @@ +export class RocketletsPersistenceModel extends RocketChat.models._Base { + constructor() { + super('rocketlets_persistence'); + } +} From 2cf9e5b6b835ce7b4be3a43e692c45a120a8415b Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Thu, 31 Aug 2017 23:59:45 -0500 Subject: [PATCH 064/801] Very basic start of the web interface for the rocketlets, not much done --- .../.npm/package/npm-shrinkwrap.json | 1301 +++++++---------- .../client/orchestrator.js | 19 + .../server/orchestrator.js | 4 + 3 files changed, 592 insertions(+), 732 deletions(-) diff --git a/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json index 1b48096650dc..788d7c87977a 100644 --- a/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json @@ -329,744 +329,581 @@ "from": "graceful-fs@>=4.1.2 <5.0.0" }, "grpc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.4.1.tgz", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/grpc/-/grpc-1.6.0.tgz", "from": "grpc@>=1.3.1 <2.0.0", "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "from": "abbrev@1" + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "from": "ajv@^4.9.1" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "from": "ansi-regex@^2.0.0" + }, + "aproba": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", + "from": "aproba@^1.0.3" + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "from": "are-we-there-yet@~1.1.2" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "from": "asn1@~0.2.3" + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "from": "assert-plus@^0.2.0" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "from": "asynckit@^0.4.0" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "from": "aws-sign2@~0.6.0" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "from": "aws4@^1.2.1" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "from": "balanced-match@^1.0.0" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "from": "bcrypt-pbkdf@^1.0.0" + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "from": "block-stream@*" + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "from": "boom@2.x.x" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "from": "brace-expansion@^1.1.7" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "from": "caseless@~0.12.0" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "from": "co@^4.6.0" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "from": "code-point-at@^1.0.0" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "from": "combined-stream@~1.0.5" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "from": "concat-map@0.0.1" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "from": "console-control-strings@~1.1.0" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "from": "core-util-is@~1.0.0" + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "from": "cryptiles@2.x.x" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "from": "dashdash@^1.12.0", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@^1.0.0" + } + } + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "from": "debug@^2.2.0" + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "from": "deep-extend@~0.4.0" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "from": "delayed-stream@~1.0.0" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "from": "delegates@^1.0.0" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "from": "ecc-jsbn@~0.1.1" + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "from": "extend@~3.0.0" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "from": "extsprintf@1.3.0" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "from": "forever-agent@~0.6.1" + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "from": "form-data@~2.1.1" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "from": "fs.realpath@^1.0.0" + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "from": "fstream@^1.0.2" + }, + "fstream-ignore": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", + "from": "fstream-ignore@^1.0.5" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "from": "gauge@~2.7.3" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "from": "getpass@^0.1.1", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@^1.0.0" + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "from": "glob@^7.0.5" + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "from": "graceful-fs@^4.1.2" + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "from": "har-schema@^1.0.5" + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "from": "har-validator@~4.2.1" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "from": "has-unicode@^2.0.0" + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "from": "hawk@~3.1.3" + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "from": "hoek@2.x.x" + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "from": "http-signature@~1.1.0" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "from": "inflight@^1.0.4" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "from": "inherits@~2.0.3" + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "from": "ini@~1.3.0" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "from": "is-fullwidth-code-point@^1.0.0" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "from": "is-typedarray@~1.0.0" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "from": "isarray@~1.0.0" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "from": "isstream@~0.1.2" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "from": "jsbn@~0.1.0" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "from": "json-schema@0.2.3" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "from": "json-stable-stringify@^1.0.1" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "from": "json-stringify-safe@~5.0.1" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "from": "jsonify@~0.0.0" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "from": "jsprim@^1.2.2", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@1.0.0" + } + } + }, + "mime-db": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", + "from": "mime-db@~1.29.0" + }, + "mime-types": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "from": "mime-types@~2.1.7" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "from": "minimatch@^3.0.4" + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "from": "minimist@^1.2.0" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "from": "mkdirp@^0.5.1", + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "from": "minimist@0.0.8" + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "from": "ms@2.0.0" + }, "node-pre-gyp": { "version": "0.6.36", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz", - "from": "node-pre-gyp@0.6.36", + "from": "node-pre-gyp@0.6.36" + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "from": "nopt@^4.0.1" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "from": "npmlog@^4.0.2" + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "from": "number-is-nan@^1.0.0" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "from": "oauth-sign@~0.8.1" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "from": "object-assign@^4.1.0" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "from": "once@^1.3.0" + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "from": "os-homedir@^1.0.0" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "from": "os-tmpdir@^1.0.0" + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "from": "osenv@^0.1.4" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "from": "path-is-absolute@^1.0.0" + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "from": "performance-now@^0.2.0" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "from": "process-nextick-args@~1.0.6" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "from": "punycode@^1.4.1" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "from": "qs@~6.4.0" + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "from": "rc@^1.1.7" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "from": "readable-stream@^2.0.6" + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "from": "request@^2.81.0" + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "from": "rimraf@^2.6.1" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "from": "safe-buffer@~5.1.1" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "from": "semver@^5.3.0" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "from": "set-blocking@~2.0.0" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "from": "signal-exit@^3.0.0" + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "from": "sntp@1.x.x" + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "from": "sshpk@^1.7.0", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@^1.0.0" + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "from": "string-width@^1.0.1" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "from": "string_decoder@~1.0.3" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "from": "stringstream@~0.0.4" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "from": "strip-ansi@^3.0.1" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "from": "strip-json-comments@~2.0.1" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "from": "tar@^2.2.1" + }, + "tar-pack": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", + "from": "tar-pack@^3.4.0" + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "from": "tough-cookie@~2.3.0" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "from": "tunnel-agent@^0.6.0" + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "from": "tweetnacl@~0.14.0" + }, + "uid-number": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", + "from": "uid-number@^0.0.6" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "from": "util-deprecate@~1.0.1" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "from": "uuid@^3.0.0" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "from": "verror@1.10.0", "dependencies": { - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "from": "mkdirp@>=0.5.1 <0.6.0", - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "from": "minimist@0.0.8" - } - } - }, - "nopt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "from": "nopt@>=4.0.1 <5.0.0", - "dependencies": { - "abbrev": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", - "from": "abbrev@>=1.0.0 <2.0.0" - }, - "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "from": "osenv@>=0.1.4 <0.2.0", - "dependencies": { - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "from": "os-homedir@>=1.0.0 <2.0.0" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "from": "os-tmpdir@>=1.0.0 <2.0.0" - } - } - } - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "from": "npmlog@>=4.0.2 <5.0.0", - "dependencies": { - "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "from": "are-we-there-yet@>=1.1.2 <1.2.0", - "dependencies": { - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "from": "delegates@>=1.0.0 <2.0.0" - }, - "readable-stream": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.2.tgz", - "from": "readable-stream@>=2.0.6 <3.0.0", - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "from": "core-util-is@>=1.0.0 <1.1.0" - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "from": "inherits@>=2.0.3 <2.1.0" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "from": "isarray@>=1.0.0 <1.1.0" - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "from": "process-nextick-args@>=1.0.6 <1.1.0" - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "from": "safe-buffer@>=5.1.0 <5.2.0" - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "from": "string_decoder@>=1.0.0 <1.1.0" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "from": "util-deprecate@>=1.0.1 <1.1.0" - } - } - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "from": "console-control-strings@>=1.1.0 <1.2.0" - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "from": "gauge@>=2.7.3 <2.8.0", - "dependencies": { - "aproba": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", - "from": "aproba@>=1.0.3 <2.0.0" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "from": "has-unicode@>=2.0.0 <3.0.0" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "from": "object-assign@>=4.1.0 <5.0.0" - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "from": "signal-exit@>=3.0.0 <4.0.0" - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "from": "string-width@>=1.0.1 <2.0.0", - "dependencies": { - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "from": "code-point-at@>=1.0.0 <2.0.0" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "from": "is-fullwidth-code-point@>=1.0.0 <2.0.0", - "dependencies": { - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "from": "number-is-nan@>=1.0.0 <2.0.0" - } - } - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "from": "strip-ansi@>=3.0.1 <4.0.0", - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "from": "ansi-regex@>=2.0.0 <3.0.0" - } - } - }, - "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "from": "wide-align@>=1.1.0 <2.0.0" - } - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "from": "set-blocking@>=2.0.0 <2.1.0" - } - } - }, - "rc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "from": "rc@>=1.1.7 <2.0.0", - "dependencies": { - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "from": "deep-extend@>=0.4.0 <0.5.0" - }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "from": "ini@>=1.3.0 <1.4.0" - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "from": "minimist@>=1.2.0 <2.0.0" - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "from": "strip-json-comments@>=2.0.1 <2.1.0" - } - } - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "from": "request@>=2.81.0 <3.0.0", - "dependencies": { - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "from": "aws-sign2@>=0.6.0 <0.7.0" - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "from": "aws4@>=1.2.1 <2.0.0" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "from": "caseless@>=0.12.0 <0.13.0" - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "from": "combined-stream@>=1.0.5 <1.1.0", - "dependencies": { - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "from": "delayed-stream@>=1.0.0 <1.1.0" - } - } - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "from": "extend@>=3.0.0 <3.1.0" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "from": "forever-agent@>=0.6.1 <0.7.0" - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "from": "form-data@>=2.1.1 <2.2.0", - "dependencies": { - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "from": "asynckit@>=0.4.0 <0.5.0" - } - } - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "from": "har-validator@>=4.2.1 <4.3.0", - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "from": "ajv@>=4.9.1 <5.0.0", - "dependencies": { - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "from": "co@>=4.6.0 <5.0.0" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "from": "json-stable-stringify@>=1.0.1 <2.0.0", - "dependencies": { - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "from": "jsonify@>=0.0.0 <0.1.0" - } - } - } - } - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "from": "har-schema@>=1.0.5 <2.0.0" - } - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "from": "hawk@>=3.1.3 <3.2.0", - "dependencies": { - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "from": "boom@>=2.0.0 <3.0.0" - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "from": "cryptiles@>=2.0.0 <3.0.0" - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "from": "hoek@>=2.0.0 <3.0.0" - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "from": "sntp@>=1.0.0 <2.0.0" - } - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "from": "http-signature@>=1.1.0 <1.2.0", - "dependencies": { - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "from": "assert-plus@>=0.2.0 <0.3.0" - }, - "jsprim": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", - "from": "jsprim@>=1.2.2 <2.0.0", - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "from": "assert-plus@1.0.0" - }, - "extsprintf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "from": "extsprintf@1.0.2" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "from": "json-schema@0.2.3" - }, - "verror": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", - "from": "verror@1.3.6" - } - } - }, - "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "from": "sshpk@>=1.7.0 <2.0.0", - "dependencies": { - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "from": "asn1@>=0.2.3 <0.3.0" - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "from": "assert-plus@>=1.0.0 <2.0.0" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "from": "bcrypt-pbkdf@>=1.0.0 <2.0.0" - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "from": "dashdash@>=1.12.0 <2.0.0" - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "from": "ecc-jsbn@>=0.1.1 <0.2.0" - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "from": "getpass@>=0.1.1 <0.2.0" - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "from": "jsbn@>=0.1.0 <0.2.0" - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "from": "tweetnacl@>=0.14.0 <0.15.0" - } - } - } - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "from": "is-typedarray@>=1.0.0 <1.1.0" - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "from": "isstream@>=0.1.2 <0.2.0" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "from": "json-stringify-safe@>=5.0.1 <5.1.0" - }, - "mime-types": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", - "from": "mime-types@>=2.1.7 <2.2.0", - "dependencies": { - "mime-db": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "from": "mime-db@>=1.27.0 <1.28.0" - } - } - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "from": "oauth-sign@>=0.8.1 <0.9.0" - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "from": "performance-now@>=0.2.0 <0.3.0" - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "from": "qs@>=6.4.0 <6.5.0" - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "from": "safe-buffer@>=5.0.1 <6.0.0" - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "from": "stringstream@>=0.0.4 <0.1.0" - }, - "tough-cookie": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "from": "tough-cookie@>=2.3.0 <2.4.0", - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "from": "punycode@>=1.4.1 <2.0.0" - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "from": "tunnel-agent@>=0.6.0 <0.7.0" - }, - "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "from": "uuid@>=3.0.0 <4.0.0" - } - } - }, - "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "from": "rimraf@>=2.6.1 <3.0.0", - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "from": "glob@>=7.0.5 <8.0.0", - "dependencies": { - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "from": "fs.realpath@>=1.0.0 <2.0.0" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "from": "inflight@>=1.0.4 <2.0.0", - "dependencies": { - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "from": "wrappy@>=1.0.0 <2.0.0" - } - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "from": "inherits@>=2.0.0 <3.0.0" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "from": "minimatch@>=3.0.0 <4.0.0", - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "from": "brace-expansion@>=1.1.7 <2.0.0", - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "from": "balanced-match@>=1.0.0 <2.0.0" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "from": "concat-map@0.0.1" - } - } - } - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "from": "once@>=1.3.0 <2.0.0", - "dependencies": { - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "from": "wrappy@>=1.0.0 <2.0.0" - } - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "from": "path-is-absolute@>=1.0.0 <2.0.0" - } - } - } - } - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "from": "semver@>=5.3.0 <6.0.0" - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "from": "tar@>=2.2.1 <3.0.0", - "dependencies": { - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "from": "block-stream@*" - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "from": "fstream@>=1.0.2 <2.0.0", - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "from": "graceful-fs@>=4.1.2 <5.0.0" - } - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "from": "inherits@>=2.0.0 <3.0.0" - } - } - }, - "tar-pack": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", - "from": "tar-pack@>=3.4.0 <4.0.0", - "dependencies": { - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "from": "debug@>=2.2.0 <3.0.0", - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "from": "ms@2.0.0" - } - } - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "from": "fstream@>=1.0.10 <2.0.0", - "dependencies": { - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "from": "graceful-fs@>=4.1.2 <5.0.0" - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "from": "inherits@>=2.0.0 <2.1.0" - } - } - }, - "fstream-ignore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "from": "fstream-ignore@>=1.0.5 <2.0.0", - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "from": "inherits@>=2.0.0 <3.0.0" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "from": "minimatch@>=3.0.0 <4.0.0", - "dependencies": { - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "from": "brace-expansion@>=1.1.7 <2.0.0", - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "from": "balanced-match@>=1.0.0 <2.0.0" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "from": "concat-map@0.0.1" - } - } - } - } - } - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "from": "once@>=1.0.0 <2.0.0", - "dependencies": { - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "from": "wrappy@>=1.0.0 <2.0.0" - } - } - }, - "readable-stream": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.2.tgz", - "from": "readable-stream@>=2.1.4 <3.0.0", - "dependencies": { - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "from": "core-util-is@>=1.0.0 <1.1.0" - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "from": "inherits@>=2.0.3 <2.1.0" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "from": "isarray@>=1.0.0 <1.1.0" - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "from": "process-nextick-args@>=1.0.6 <1.1.0" - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "from": "safe-buffer@>=5.1.0 <5.2.0" - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "from": "string_decoder@>=1.0.0 <1.1.0" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "from": "util-deprecate@>=1.0.1 <1.1.0" - } - } - }, - "uid-number": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "from": "uid-number@>=0.0.6 <0.0.7" - } - } + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@^1.0.0" } } + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "from": "wide-align@^1.1.0" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "from": "wrappy@1" } } }, @@ -1270,7 +1107,7 @@ "nan": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", - "from": "nan@>=2.0.0 <3.0.0" + "from": "nan@>=2.6.2 <3.0.0" }, "node-forge": { "version": "0.7.1", @@ -1340,7 +1177,7 @@ "protobufjs": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.2.tgz", - "from": "protobufjs@>=5.0.0 <6.0.0" + "from": "protobufjs@>=5.0.2 <6.0.0" }, "pump": { "version": "1.0.2", diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js index d65a626290fb..3d4010345145 100644 --- a/packages/rocketchat-rocketlets/client/orchestrator.js +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -3,11 +3,30 @@ import { RocketletWebsocketReceiver } from './communication'; class RocketletClientOrchestrator { constructor() { this.ws = new RocketletWebsocketReceiver(this); + + this._addAdminMenuOption(); } getWsListener() { return this.ws; } + + _addAdminMenuOption() { + FlowRouter.route('/admin/rocketlets', { + name: 'rocketlets', + action() { + BlazeLayout.render('main', { center: 'rocketlets' }); + } + }); + + RocketChat.AdminBox.addOption({ + href: 'rocketlets', + i18nLabel: 'rocketlets', + permissionGranted() { + return RocketChat.authz.hasAtLeastOnePermission(['manage-rocketlets']); + } + }); + } } Meteor.startup(function _rlClientOrch() { diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js index 7bc44068928c..c9a79eb7af14 100644 --- a/packages/rocketchat-rocketlets/server/orchestrator.js +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -7,6 +7,10 @@ import { RocketletManager } from 'temporary-rocketlets-server/server/RocketletMa class RocketletServerOrchestrator { constructor() { + if (RocketChat.models && RocketChat.models.Permissions) { + RocketChat.models.Permissions.createOrUpdate('manage-rocketlets', ['admin']); + } + this._model = new RocketletsModel(); this._persistModel = new RocketletsPersistenceModel(); this._storage = new RocketletRealStorage(this._model); From 423065cb76efd27b7c8f1b896dbe1a5ecda48e27 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Thu, 7 Sep 2017 11:47:05 -0500 Subject: [PATCH 065/801] Flush out the rocketlet message converters and implement the http accessor --- packages/rocketchat-i18n/i18n/en.i18n.json | 2 + .../server/lib/sendNotificationsOnMessage.js | 2 +- .../client/admin/rocketlets.html | 20 +++ .../client/admin/rocketlets.js | 3 + .../client/orchestrator.js | 17 +-- packages/rocketchat-rocketlets/package.js | 15 ++- .../server/bridges/bridges.js | 6 + .../server/bridges/http.js | 14 ++ .../server/bridges/index.js | 2 + .../server/bridges/messages.js | 2 +- .../server/converters/messages.js | 126 ++++++++++++++++-- .../server/orchestrator.js | 2 +- 12 files changed, 187 insertions(+), 24 deletions(-) create mode 100644 packages/rocketchat-rocketlets/client/admin/rocketlets.html create mode 100644 packages/rocketchat-rocketlets/client/admin/rocketlets.js create mode 100644 packages/rocketchat-rocketlets/server/bridges/http.js diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 9413c0c42a0e..19b5d6bbf61b 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1339,6 +1339,7 @@ "manage-own-integrations_description": "Permition to allow users to create and edit their own integration or webhooks", "manage-sounds": "Manage Sounds", "manage-sounds_description": "Permission to manage the server sounds", + "Manage_Rocketlets": "Manage Rocketlets", "mention-all": "Mention All", "mention-all_description": "Permission to use the @all mention", "mute-user": "Mute User", @@ -1523,6 +1524,7 @@ "Restart": "Restart", "Restart_the_server": "Restart the server", "Retry_Count": "Retry Count", + "Rocketlets": "Rocketlets", "Role": "Role", "Role_Editing": "Role Editing", "Role_removed": "Role removed", diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js index 1083d18d76ec..ddda8b880de7 100644 --- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js +++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js @@ -31,7 +31,7 @@ function parseMessageText(message, userId) { const user = RocketChat.models.Users.findOneById(userId); const lng = user && user.language || RocketChat.settings.get('language') || 'en'; - if (!message.msg && message.attachments[0]) { + if (!message.msg && message.attachments && message.attachments[0]) { message.msg = message.attachments[0].image_type ? TAPi18n.__('User_uploaded_image', {lng}) : TAPi18n.__('User_uploaded_file', {lng}); } message.msg = RocketChat.callbacks.run('beforeNotifyUser', message.msg); diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html new file mode 100644 index 000000000000..62c73ba09a99 --- /dev/null +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -0,0 +1,20 @@ + diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.js b/packages/rocketchat-rocketlets/client/admin/rocketlets.js new file mode 100644 index 000000000000..bf10e3895b27 --- /dev/null +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.js @@ -0,0 +1,3 @@ +Template.rocketlets.onCreated(function() { + console.log('hello'); +}); diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js index 3d4010345145..4bedcc9e56b0 100644 --- a/packages/rocketchat-rocketlets/client/orchestrator.js +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -12,16 +12,9 @@ class RocketletClientOrchestrator { } _addAdminMenuOption() { - FlowRouter.route('/admin/rocketlets', { - name: 'rocketlets', - action() { - BlazeLayout.render('main', { center: 'rocketlets' }); - } - }); - RocketChat.AdminBox.addOption({ href: 'rocketlets', - i18nLabel: 'rocketlets', + i18nLabel: 'Rocketlets', permissionGranted() { return RocketChat.authz.hasAtLeastOnePermission(['manage-rocketlets']); } @@ -32,3 +25,11 @@ class RocketletClientOrchestrator { Meteor.startup(function _rlClientOrch() { window.Rocketlets = new RocketletClientOrchestrator(); }); + +// Bah, this has to be done *before* `Meteor.startup` +FlowRouter.route('/admin/rocketlets', { + name: 'rocketlets', + action() { + BlazeLayout.render('main', { center: 'rocketlets' }); + } +}); diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index cebcc6ef2f5f..c1db788185ed 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -7,9 +7,12 @@ Package.onUse(function(api) { api.use([ 'ecmascript', 'rocketchat:lib', - 'rocketchat:api' + 'rocketchat:api', + 'templating' ]); + api.use(['reactive-var', 'kadira:flow-router'], 'client'); + api.addFiles('lib/Rocketlets.js', ['client', 'server']); // Storage @@ -58,6 +61,12 @@ Package.onUse(function(api) { 'client/communication/index.js' ], 'client'); + // Client Admin Management + api.addFiles([ + 'client/admin/rocketlets.html', + 'client/admin/rocketlets.js' + ], 'client'); + // Client orchestrator api.addFiles('client/orchestrator.js', 'client'); @@ -66,6 +75,6 @@ Package.onUse(function(api) { Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.20', - 'temporary-rocketlets-ts-definition': '0.6.11' + 'temporary-rocketlets-server': '0.1.22', + 'temporary-rocketlets-ts-definition': '0.6.24' }); diff --git a/packages/rocketchat-rocketlets/server/bridges/bridges.js b/packages/rocketchat-rocketlets/server/bridges/bridges.js index 37d83623f62a..07f5d182a9dc 100644 --- a/packages/rocketchat-rocketlets/server/bridges/bridges.js +++ b/packages/rocketchat-rocketlets/server/bridges/bridges.js @@ -1,6 +1,7 @@ import { RocketletBridges } from 'temporary-rocketlets-server/server/bridges'; import { RocketletCommandsBridge } from './commands'; import { RocketletEnvironmentalVariableBridge } from './environmental'; +import { RocketletHttpBridge } from './http'; import { RocketletMessageBridge } from './messages'; import { RocketletPersistenceBridge } from './persistence'; import { RocketletRoomBridge } from './rooms'; @@ -13,6 +14,7 @@ export class RealRocketletBridges extends RocketletBridges { this._cmdBridge = new RocketletCommandsBridge(orch); this._envBridge = new RocketletEnvironmentalVariableBridge(orch); + this._httpBridge = new RocketletHttpBridge(); this._msgBridge = new RocketletMessageBridge(orch); this._persistBridge = new RocketletPersistenceBridge(orch); this._roomBridge = new RocketletRoomBridge(orch); @@ -28,6 +30,10 @@ export class RealRocketletBridges extends RocketletBridges { return this._envBridge; } + getHttpBridge() { + return this._httpBridge; + } + getMessageBridge() { return this._msgBridge; } diff --git a/packages/rocketchat-rocketlets/server/bridges/http.js b/packages/rocketchat-rocketlets/server/bridges/http.js new file mode 100644 index 000000000000..a8bd452765ca --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/http.js @@ -0,0 +1,14 @@ +export class RocketletHttpBridge { + call(info) { + if (!info.request.content && typeof info.request.data === 'object') { + info.request.content = JSON.stringify(info.request.data); + } + + console.log(`The Rocketlet ${ info.rocketletId } is requesting from the outter webs:`, info); + const result = HTTP.call(info.method, info.url, info.request); + + console.log('The result is:', result); + + return result; + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/index.js b/packages/rocketchat-rocketlets/server/bridges/index.js index 0e3881bb49e1..6f6662360c7b 100644 --- a/packages/rocketchat-rocketlets/server/bridges/index.js +++ b/packages/rocketchat-rocketlets/server/bridges/index.js @@ -1,6 +1,7 @@ import { RealRocketletBridges } from './bridges'; import { RocketletCommandsBridge } from './commands'; import { RocketletEnvironmentalVariableBridge } from './environmental'; +import { RocketletHttpBridge } from './http'; import { RocketletMessageBridge } from './messages'; import { RocketletPersistenceBridge } from './persistence'; import { RocketletRoomBridge } from './rooms'; @@ -11,6 +12,7 @@ export { RealRocketletBridges, RocketletCommandsBridge, RocketletEnvironmentalVariableBridge, + RocketletHttpBridge, RocketletMessageBridge, RocketletPersistenceBridge, RocketletRoomBridge, diff --git a/packages/rocketchat-rocketlets/server/bridges/messages.js b/packages/rocketchat-rocketlets/server/bridges/messages.js index 812e930dc429..84ea8104d7be 100644 --- a/packages/rocketchat-rocketlets/server/bridges/messages.js +++ b/packages/rocketchat-rocketlets/server/bridges/messages.js @@ -4,7 +4,7 @@ export class RocketletMessageBridge { } create(message, rocketletId) { - console.log(`The Rocketlet ${ rocketletId } is creating a new message.`, message); + console.log(`The Rocketlet ${ rocketletId } is creating a new message.`); let msg = this.orch.getConverters().get('messages').convertRocketletMessage(message); diff --git a/packages/rocketchat-rocketlets/server/converters/messages.js b/packages/rocketchat-rocketlets/server/converters/messages.js index 12c8d80234ae..4858e4c18258 100644 --- a/packages/rocketchat-rocketlets/server/converters/messages.js +++ b/packages/rocketchat-rocketlets/server/converters/messages.js @@ -6,20 +6,38 @@ export class RocketletMessagesConverter { convertById(msgId) { const msg = RocketChat.models.Messages.getOneById(msgId); - if (!msg) { + return this.convertMessage(msg); + } + + convertMessage(msgObj) { + if (!msgObj) { return undefined; } - return { - id: msg._id, - text: msg.msg - }; - } + const room = this.orch.getConverters().get('rooms').convertById(msgObj.rid); + const sender = this.orch.getConverters().get('users').convertById(msgObj.u._id); + + let editor; + if (msgObj.editedBy) { + editor = this.orch.getConverters().get('users').convertById(msgObj.editedBy._id); + } + + const attachments = this._convertAttachmentsToRocketlet(msgObj.attachments); - convertMessage(msgObj) { return { id: msgObj._id, - text: msgObj.msg + room, + sender, + text: msgObj.msg, + createdAt: msgObj.ts, + updatedAt: msgObj._updatedAt, + editor, + editedAt: msgObj.editedAt, + emoji: msgObj.emoji, + avatarUrl: msgObj.avatar, + alias: msgObj.alias, + customFields: msgObj.customFields, + attachments }; } @@ -35,14 +53,102 @@ export class RocketletMessagesConverter { throw new Error('Invalid user or room provided on the message.'); } + let editedBy; + if (message.editor) { + const editor = RocketChat.models.Users.findOneById(message.editor.id); + editedBy = { + _id: editor._id, + username: editor.username + }; + } + + const attachments = this._convertRocketletAttachments(message.attachments); + return { _id: message.id || Random.id(), - msg: message.text, rid: room._id, u: { _id: user._id, username: user.username - } + }, + msg: message.text, + ts: message.createdAt || new Date(), + _updatedAt: message.updatedAt || new Date(), + editedBy, + editedAt: message.editedAt, + emoji: message.emoji, + avatar: message.avatarUrl, + alias: message.alias, + customFields: message.customFields, + attachments }; } + + _convertRocketletAttachments(attachments) { + if (typeof attachments === 'undefined' || !Array.isArray(attachments)) { + return undefined; + } + + return attachments.map((attachment) => { + return { + collapsed: attachment.collapsed, + color: attachment.color, + text: attachment.text, + ts: attachment.timestamp, + message_link: attachment.timestampLink, + thumb_url: attachment.thumbnailUrl, + author_name: attachment.author ? attachment.author.name : undefined, + author_link: attachment.author ? attachment.author.link : undefined, + author_icon: attachment.author ? attachment.author.icon : undefined, + title: attachment.title ? attachment.title.value : undefined, + title_link: attachment.title ? attachment.title.link : undefined, + title_link_download: attachment.title ? attachment.title.downloadLink : undefined, + image_url: attachment.imageUrl, + audio_url: attachment.audioUrl, + video_url: attachment.videoUrl, + fields: attachment.fields + }; + }); + } + + _convertAttachmentsToRocketlet(attachments) { + if (typeof attachments === 'undefined' || !Array.isArray(attachments)) { + return undefined; + } + + return attachments.map((attachment) => { + let author; + if (attachment.author_name || attachment.author_link || attachment.author_icon) { + author = { + name: attachment.author_name, + link: attachment.author_link, + icon: attachment.author_icon + }; + } + + let title; + if (attachment.title || attachment.title_link || attachment.title_link_download) { + title = { + value: attachment.title, + link: attachment.title_link, + downloadLink: attachment.title_link_download + }; + } + + return { + collapsed: attachment.collapsed, + color: attachment.color, + text: attachment.text, + timestamp: attachment.ts, + timestampLink: attachment.message_link, + thumbnailUrl: attachment.thumb_url, + author, + title, + imageUrl: attachment.image_url, + audioUrl: attachment.audio_url, + videoUrl: attachment.video_url, + fields: attachment.fields + }; + }); + } } diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js index c9a79eb7af14..42a4b2f6f1b3 100644 --- a/packages/rocketchat-rocketlets/server/orchestrator.js +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -64,6 +64,6 @@ Meteor.startup(function _rocketletServerOrchestrator() { global.Rocketlets = new RocketletServerOrchestrator(); global.Rocketlets.getManager().load() - .then(() => console.log('...done! ;)')) + .then(() => console.log('...done! :)')) .catch((err) => console.warn('...failed!', err)); }); From a74db27644b9490bd8c2071d36bc264f2a9601b4 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Fri, 8 Sep 2017 10:44:39 -0500 Subject: [PATCH 066/801] Implement more logic on the rocketlet bridges --- .../server/lib/sendNotificationsOnMessage.js | 2 +- .../client/communication/websockets.js | 1 + packages/rocketchat-rocketlets/package.js | 5 +-- .../server/bridges/commands.js | 18 ++++++++++ .../server/bridges/environmental.js | 18 ++++++++-- .../server/bridges/http.js | 2 +- .../server/bridges/messages.js | 17 +++++++++ .../server/bridges/rooms.js | 12 +++++++ .../server/bridges/settings.js | 22 ++++++++++-- .../server/communication/websockets.js | 4 +++ .../server/converters/settings.js | 36 ++++++++++++++++++- 11 files changed, 127 insertions(+), 10 deletions(-) diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js index ddda8b880de7..01929f3aaa77 100644 --- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js +++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js @@ -31,7 +31,7 @@ function parseMessageText(message, userId) { const user = RocketChat.models.Users.findOneById(userId); const lng = user && user.language || RocketChat.settings.get('language') || 'en'; - if (!message.msg && message.attachments && message.attachments[0]) { + if (!message.msg && Array.isArray(message.attachments) && message.attachments[0]) { message.msg = message.attachments[0].image_type ? TAPi18n.__('User_uploaded_image', {lng}) : TAPi18n.__('User_uploaded_file', {lng}); } message.msg = RocketChat.callbacks.run('beforeNotifyUser', message.msg); diff --git a/packages/rocketchat-rocketlets/client/communication/websockets.js b/packages/rocketchat-rocketlets/client/communication/websockets.js index d661600d5acf..5288636a3d06 100644 --- a/packages/rocketchat-rocketlets/client/communication/websockets.js +++ b/packages/rocketchat-rocketlets/client/communication/websockets.js @@ -6,6 +6,7 @@ export class RocketletWebsocketReceiver { this.streamer.on('command/added', this.onCommandAdded.bind(this)); this.streamer.on('command/disabled', this.onCommandDisabled.bind(this)); this.streamer.on('command/updated', this.onCommandUpdated.bind(this)); + this.streamer.on('command/removed', this.onCommandDisabled.bind(this)); } onCommandAdded(command) { diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index c1db788185ed..0071297ed1a1 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -70,11 +70,12 @@ Package.onUse(function(api) { // Client orchestrator api.addFiles('client/orchestrator.js', 'client'); + // Add what this package actually does export api.export('Rocketlets'); }); Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.22', - 'temporary-rocketlets-ts-definition': '0.6.24' + 'temporary-rocketlets-server': '0.1.23', + 'temporary-rocketlets-ts-definition': '0.6.25' }); diff --git a/packages/rocketchat-rocketlets/server/bridges/commands.js b/packages/rocketchat-rocketlets/server/bridges/commands.js index 5a15730ed1d3..d1a6728e4af4 100644 --- a/packages/rocketchat-rocketlets/server/bridges/commands.js +++ b/packages/rocketchat-rocketlets/server/bridges/commands.js @@ -70,6 +70,24 @@ export class RocketletCommandsBridge { this.orch.getNotifier().commandAdded(command.command.toLowerCase()); } + unregisterCommand(command, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is unregistering the command: "${ command }"`); + + if (typeof command !== 'string' || command.trim().length === 0) { + throw new Error('Invalid command parameter provided, must be a string.'); + } + + const cmd = command.toLowerCase(); + if (typeof RocketChat.slashCommands.commands[cmd] === 'undefined' || !this.disabledCommands.has(cmd)) { + throw new Error(`Command does not exist in the system currently: ${ cmd }`); + } + + this.disabledCommands.delete(cmd); + delete RocketChat.slashCommands.commands[cmd]; + + this.orch.getNotifier().commandRemoved(cmd); + } + _verifyCommand(command) { if (typeof command !== 'object') { throw new Error('Invalid Slash Command parameter provided, it must be a valid ISlashCommand object.'); diff --git a/packages/rocketchat-rocketlets/server/bridges/environmental.js b/packages/rocketchat-rocketlets/server/bridges/environmental.js index 9b4188e75a85..19b6d34bd490 100644 --- a/packages/rocketchat-rocketlets/server/bridges/environmental.js +++ b/packages/rocketchat-rocketlets/server/bridges/environmental.js @@ -1,20 +1,32 @@ export class RocketletEnvironmentalVariableBridge { constructor(orch) { this.orch = orch; + this.allowed = ['NODE_ENV', 'ROOT_URL', 'INSTANCE_IP']; } getValueByName(envVarName, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is getting the environmental variable value ${ envVarName }.`); - throw new Error('Method not implemented.'); + + if (this.isReadable(envVarName, rocketletId)) { + return process.env[envVarName]; + } + + throw new Error(`The environmental variable "${ envVarName }" is not readable.`); } isReadable(envVarName, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is checking if the environmental variable is readable ${ envVarName }.`); - throw new Error('Method not implemented.'); + + return this.allowed.includes(envVarName.toUpperCase()); } isSet(envVarName, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is checking if the environmental variable is set ${ envVarName }.`); - throw new Error('Method not implemented.'); + + if (this.isReadable(envVarName, rocketletId)) { + return typeof process.env[envVarName] !== 'undefined'; + } + + throw new Error(`The environmental variable "${ envVarName }" is not readable.`); } } diff --git a/packages/rocketchat-rocketlets/server/bridges/http.js b/packages/rocketchat-rocketlets/server/bridges/http.js index a8bd452765ca..3622f4603924 100644 --- a/packages/rocketchat-rocketlets/server/bridges/http.js +++ b/packages/rocketchat-rocketlets/server/bridges/http.js @@ -7,7 +7,7 @@ export class RocketletHttpBridge { console.log(`The Rocketlet ${ info.rocketletId } is requesting from the outter webs:`, info); const result = HTTP.call(info.method, info.url, info.request); - console.log('The result is:', result); + // TODO: Maybe modify the resulting object? :thinking: return result; } diff --git a/packages/rocketchat-rocketlets/server/bridges/messages.js b/packages/rocketchat-rocketlets/server/bridges/messages.js index 84ea8104d7be..63269f3b67a1 100644 --- a/packages/rocketchat-rocketlets/server/bridges/messages.js +++ b/packages/rocketchat-rocketlets/server/bridges/messages.js @@ -20,4 +20,21 @@ export class RocketletMessageBridge { return this.orch.getConverters().get('messages').convertById(messageId); } + + update(message, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is updating a message.`); + + if (!message.editor) { + throw new Error('Invalid editor assigned to the message for the update.'); + } + + if (!message.id || !RocketChat.models.Messages.findOneById(message.id)) { + throw new Error('A message must exist to update.'); + } + + const msg = this.orch.getConverters().get('messages').convertRocketletMessage(message); + const editor = RocketChat.models.Users.findOneById(message.editor.id); + + RocketChat.updateMessage(msg, editor); + } } diff --git a/packages/rocketchat-rocketlets/server/bridges/rooms.js b/packages/rocketchat-rocketlets/server/bridges/rooms.js index c6e8db60ae0f..11108c7d7b55 100644 --- a/packages/rocketchat-rocketlets/server/bridges/rooms.js +++ b/packages/rocketchat-rocketlets/server/bridges/rooms.js @@ -42,4 +42,16 @@ export class RocketletRoomBridge { return this.orch.getConverters().get('rooms').convertByName(roomName); } + + update(room, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is updating a room.`); + + if (!room.id || RocketChat.models.Rooms.findOneById(room.id)) { + throw new Error('A room must exist to update.'); + } + + const rm = this.orch.getConverters().get('rooms').convertRocketletRoom(room); + + RocketChat.models.Rooms.update(rm._id, rm); + } } diff --git a/packages/rocketchat-rocketlets/server/bridges/settings.js b/packages/rocketchat-rocketlets/server/bridges/settings.js index c997bc7f5746..25ea83df39f0 100644 --- a/packages/rocketchat-rocketlets/server/bridges/settings.js +++ b/packages/rocketchat-rocketlets/server/bridges/settings.js @@ -1,6 +1,8 @@ export class RocketletSettingBridge { constructor(orch) { this.orch = orch; + this.allowedGroups = []; + this.allowedSettings = []; } getAll(rocketletId) { @@ -10,7 +12,12 @@ export class RocketletSettingBridge { getOneById(id, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is getting the setting by id ${ id }.`); - throw new Error('Method not implemented.'); + + if (!this.isReadableById(id, rocketletId)) { + throw new Error(`The setting "${ id }" is not readable.`); + } + + return this.orch.getConverters().get('settings').convertById(id); } hideGroup(name, rocketletId) { @@ -20,16 +27,27 @@ export class RocketletSettingBridge { hideSetting(id, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is hidding the setting ${ id }.`); + + if (!this.isReadableById(id, rocketletId)) { + throw new Error(`The setting "${ id }" is not readable.`); + } + throw new Error('Method not implemented.'); } isReadableById(id, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is checking if they can read the setting ${ id }.`); - throw new Error('Method not implemented.'); + + return this.allowedSettings.includes(id); } updateOne(setting, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is updating the setting ${ setting.id } .`); + + if (!this.isReadableById(setting.id, rocketletId)) { + throw new Error(`The setting "${ setting.id }" is not readable.`); + } + throw new Error('Method not implemented.'); } } diff --git a/packages/rocketchat-rocketlets/server/communication/websockets.js b/packages/rocketchat-rocketlets/server/communication/websockets.js index d92da25cae44..5c706c2fb3d0 100644 --- a/packages/rocketchat-rocketlets/server/communication/websockets.js +++ b/packages/rocketchat-rocketlets/server/communication/websockets.js @@ -29,4 +29,8 @@ export class RocketletWebsocketNotifier { commandUpdated(command) { this.streamer.emit('command/updated', command); } + + commandRemoved(command) { + this.streamer.emit('command/removed', command); + } } diff --git a/packages/rocketchat-rocketlets/server/converters/settings.js b/packages/rocketchat-rocketlets/server/converters/settings.js index eec1f01984f2..edce911c6cf5 100644 --- a/packages/rocketchat-rocketlets/server/converters/settings.js +++ b/packages/rocketchat-rocketlets/server/converters/settings.js @@ -1,3 +1,5 @@ +import { SettingType } from 'temporary-rocketlets-ts-definition/settings'; + export class RocketletSettingsConverter { constructor(orch) { this.orch = orch; @@ -7,7 +9,39 @@ export class RocketletSettingsConverter { const setting = RocketChat.models.Settings.findOneById(settingId); return { - id: setting._id + id: setting._id, + type: this._convertTypeToRocketlet(setting.type), + packageValue: setting.packageValue, + values: setting.values, + value: setting.value, + public: setting.public, + hidden: setting.hidden, + group: setting.group, + i18nLabel: setting.i18nLabel, + i18nDescription: setting.i18nDescription, + createdAt: setting.ts, + updatedAt: setting._updatedAt }; } + + _convertTypeToRocketlet(type) { + switch (type) { + case 'boolean': + return SettingType.BOOLEAN; + case 'code': + return SettingType.CODE; + case 'color': + return SettingType.COLOR; + case 'font': + return SettingType.FONT; + case 'int': + return SettingType.NUMBER; + case 'select': + return SettingType.SELECT; + case 'string': + return SettingType.STRING; + default: + return type; + } + } } From 8ddb0905263a2d0bce433207427273254a1dcec3 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Mon, 11 Sep 2017 16:02:30 -0500 Subject: [PATCH 067/801] i18n is now provided via the rocketlets and load them when a rocketlet is added --- packages/rocketchat-api/server/api.js | 9 +++++ .../.npm/package/npm-shrinkwrap.json | 10 +++--- .../client/lib/startup/commands.js | 26 ++++++++------ .../assets/stylesheets/rocketlets.css | 0 .../client/admin/rocketlets.html | 6 +++- .../client/admin/rocketlets.js | 21 ++++++++++- .../client/communication/websockets.js | 7 ++++ .../client/orchestrator.js | 23 ++++++++++++ packages/rocketchat-rocketlets/package.js | 7 ++-- .../server/bridges/activation.js | 35 +++++++++++++++++++ .../server/bridges/bridges.js | 7 ++++ .../server/bridges/index.js | 2 ++ .../server/bridges/settings.js | 23 ++++++++++-- .../server/communication/rest.js | 25 +++++++++++-- .../server/converters/settings.js | 4 +++ 15 files changed, 180 insertions(+), 25 deletions(-) create mode 100644 packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css create mode 100644 packages/rocketchat-rocketlets/server/bridges/activation.js diff --git a/packages/rocketchat-api/server/api.js b/packages/rocketchat-api/server/api.js index c7816e0afade..d53bd9b6e63e 100644 --- a/packages/rocketchat-api/server/api.js +++ b/packages/rocketchat-api/server/api.js @@ -66,6 +66,15 @@ class API extends Restivus { }; } + notFound(msg) { + return { + statusCode: 404, + body: { + success: false, + error: msg ? msg : 'Resource not found' + } + }; + } unauthorized(msg) { return { diff --git a/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json index 788d7c87977a..00561635dcdb 100644 --- a/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json @@ -1085,13 +1085,13 @@ "from": "mime@>=1.2.11 <2.0.0" }, "mime-db": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", - "from": "mime-db@>=1.29.0 <1.30.0" + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "from": "mime-db@>=1.30.0 <1.31.0" }, "mime-types": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", "from": "mime-types@>=2.0.8 <3.0.0" }, "minimatch": { diff --git a/packages/rocketchat-lib/client/lib/startup/commands.js b/packages/rocketchat-lib/client/lib/startup/commands.js index 01d97477c1fa..91456a9eed65 100644 --- a/packages/rocketchat-lib/client/lib/startup/commands.js +++ b/packages/rocketchat-lib/client/lib/startup/commands.js @@ -1,11 +1,17 @@ -Meteor.startup(function _loadDynamicallyDefinedCommands() { - // The reason there is a 500 millisecond delay is so that we are - // a little "easier" on the server during start up - setTimeout(() => { - RocketChat.API.v1.get('commands.list').then(function _loadedCommands(result) { - result.commands.forEach((command) => { - RocketChat.slashCommands.commands[command.command] = command; +//Track logins and when they login, get the commands +(() => { + let oldUserId = null; + + Meteor.autorun(() => { + const newUserId = Meteor.userId(); + if (oldUserId === null && newUserId) { + RocketChat.API.v1.get('commands.list').then(function _loadedCommands(result) { + result.commands.forEach((command) => { + RocketChat.slashCommands.commands[command.command] = command; + }); }); - }); - }, 500); -}); + } + + oldUserId = Meteor.userId(); + }); +})(); diff --git a/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css b/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html index 62c73ba09a99..74fbb58e9f44 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.html +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -9,7 +9,11 @@

{{#requiresPermission 'manage-rocketlets'}} -

Hello

+ {{#each rocketlets}} + + {{/each}} {{/requiresPermission}}
diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.js b/packages/rocketchat-rocketlets/client/admin/rocketlets.js index bf10e3895b27..a869c96ec1c8 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.js +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.js @@ -1,3 +1,22 @@ Template.rocketlets.onCreated(function() { - console.log('hello'); + const instance = this; + this.ready = new ReactiveVar(false); + this.rocketlets = new ReactiveVar([]); + + RocketChat.API.get('rocketlets').then((result) => { + instance.rocketlets.set(result.rocketlets); + }); +}); + +Template.rocketlets.helpers({ + isReady() { + if (Template.instance().ready != null) { + return Template.instance().ready.get(); + } + + return false; + }, + rocketlets() { + return Template.instance().rocketlets.get(); + } }); diff --git a/packages/rocketchat-rocketlets/client/communication/websockets.js b/packages/rocketchat-rocketlets/client/communication/websockets.js index 5288636a3d06..b7aef6dc1dfc 100644 --- a/packages/rocketchat-rocketlets/client/communication/websockets.js +++ b/packages/rocketchat-rocketlets/client/communication/websockets.js @@ -3,12 +3,19 @@ export class RocketletWebsocketReceiver { this.orch = orch; this.streamer = new Meteor.Streamer('rocketlets'); + this.streamer.on('rocketlet/added', this.onRocketletAdded.bind(this)); this.streamer.on('command/added', this.onCommandAdded.bind(this)); this.streamer.on('command/disabled', this.onCommandDisabled.bind(this)); this.streamer.on('command/updated', this.onCommandUpdated.bind(this)); this.streamer.on('command/removed', this.onCommandDisabled.bind(this)); } + onRocketletAdded(rocketletId) { + RocketChat.API.get(`rocketlets/${ rocketletId }`).then((result) => { + this.orch.parseAndLoadLanguages(result.rocketlet.languages); + }); + } + onCommandAdded(command) { RocketChat.API.v1.get('commands.getOne', { command }).then((result) => { RocketChat.slashCommands.commands[command] = result.command; diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js index 4bedcc9e56b0..d2ff6dd02113 100644 --- a/packages/rocketchat-rocketlets/client/orchestrator.js +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -5,6 +5,7 @@ class RocketletClientOrchestrator { this.ws = new RocketletWebsocketReceiver(this); this._addAdminMenuOption(); + setTimeout(() => this._loadLanguages(), 500); } getWsListener() { @@ -20,6 +21,28 @@ class RocketletClientOrchestrator { } }); } + + _loadLanguages() { + if (!Meteor.user()) { + return; + } + + RocketChat.API.get('rocketlets?languagesOnly=true').then((info) => { + info.rocketlets.forEach((rlInfo) => this.parseAndLoadLanguages(rlInfo.languages)); + }); + } + + parseAndLoadLanguages(languages) { + Object.keys(languages).forEach((key) => { + try { + const json = JSON.parse(languages[key]); + + TAPi18next.addResourceBundle(key, 'project', json); + } catch (e) { + // Failed to parse the json + } + }); + } } Meteor.startup(function _rlClientOrch() { diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index 0071297ed1a1..5ea4ba27e3e2 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -25,6 +25,7 @@ Package.onUse(function(api) { // Bridges api.addFiles([ + 'server/bridges/activation.js', 'server/bridges/bridges.js', 'server/bridges/commands.js', 'server/bridges/environmental.js', @@ -67,6 +68,8 @@ Package.onUse(function(api) { 'client/admin/rocketlets.js' ], 'client'); + api.addFiles('assets/stylesheets/rocketlets.css', 'client'); + // Client orchestrator api.addFiles('client/orchestrator.js', 'client'); @@ -76,6 +79,6 @@ Package.onUse(function(api) { Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.23', - 'temporary-rocketlets-ts-definition': '0.6.25' + 'temporary-rocketlets-server': '0.1.26', + 'temporary-rocketlets-ts-definition': '0.6.26' }); diff --git a/packages/rocketchat-rocketlets/server/bridges/activation.js b/packages/rocketchat-rocketlets/server/bridges/activation.js new file mode 100644 index 000000000000..6833622fbece --- /dev/null +++ b/packages/rocketchat-rocketlets/server/bridges/activation.js @@ -0,0 +1,35 @@ +export class RocketletActivationBridge { + constructor(orch) { + this.orch = orch; + } + + rocketletEnabled(rocketlet) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been enabled.`); + } + + rocketletDisabled(rocketlet) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been disabled.`); + } + + rocketletLoaded(rocketlet, enabled) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been loaded and enabled? ${ enabled }`); + + if (enabled) { + this.orch.getNotifier().rocketletAdded(rocketlet.getID()); + } + } + + rocketletUpdated(rocketlet, enabled) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been updated and enabled? ${ enabled }`); + + if (enabled) { + this.orch.getNotifier().rocketletUpdated(rocketlet.getID()); + } + } + + rocketletRemoved(rocketlet) { + console.log(`The Rocketlet ${ rocketlet.getName() } (${ rocketlet.getID() }) has been removed.`); + + this.orch.getNotifier().rocketletRemoved(rocketlet.getID()); + } +} diff --git a/packages/rocketchat-rocketlets/server/bridges/bridges.js b/packages/rocketchat-rocketlets/server/bridges/bridges.js index 07f5d182a9dc..3afa40d44a97 100644 --- a/packages/rocketchat-rocketlets/server/bridges/bridges.js +++ b/packages/rocketchat-rocketlets/server/bridges/bridges.js @@ -1,4 +1,6 @@ import { RocketletBridges } from 'temporary-rocketlets-server/server/bridges'; + +import { RocketletActivationBridge } from './activation'; import { RocketletCommandsBridge } from './commands'; import { RocketletEnvironmentalVariableBridge } from './environmental'; import { RocketletHttpBridge } from './http'; @@ -12,6 +14,7 @@ export class RealRocketletBridges extends RocketletBridges { constructor(orch) { super(); + this._actBridge = new RocketletActivationBridge(orch); this._cmdBridge = new RocketletCommandsBridge(orch); this._envBridge = new RocketletEnvironmentalVariableBridge(orch); this._httpBridge = new RocketletHttpBridge(); @@ -42,6 +45,10 @@ export class RealRocketletBridges extends RocketletBridges { return this._persistBridge; } + getRocketletActivationBridge() { + return this._actBridge; + } + getRoomBridge() { return this._roomBridge; } diff --git a/packages/rocketchat-rocketlets/server/bridges/index.js b/packages/rocketchat-rocketlets/server/bridges/index.js index 6f6662360c7b..f464cffcb328 100644 --- a/packages/rocketchat-rocketlets/server/bridges/index.js +++ b/packages/rocketchat-rocketlets/server/bridges/index.js @@ -1,4 +1,5 @@ import { RealRocketletBridges } from './bridges'; +import { RocketletActivationBridge } from './activation'; import { RocketletCommandsBridge } from './commands'; import { RocketletEnvironmentalVariableBridge } from './environmental'; import { RocketletHttpBridge } from './http'; @@ -10,6 +11,7 @@ import { RocketletUserBridge } from './users'; export { RealRocketletBridges, + RocketletActivationBridge, RocketletCommandsBridge, RocketletEnvironmentalVariableBridge, RocketletHttpBridge, diff --git a/packages/rocketchat-rocketlets/server/bridges/settings.js b/packages/rocketchat-rocketlets/server/bridges/settings.js index 25ea83df39f0..0971e0cb9e21 100644 --- a/packages/rocketchat-rocketlets/server/bridges/settings.js +++ b/packages/rocketchat-rocketlets/server/bridges/settings.js @@ -2,12 +2,29 @@ export class RocketletSettingBridge { constructor(orch) { this.orch = orch; this.allowedGroups = []; - this.allowedSettings = []; + this.disallowedSettings = [ + 'Accounts_RegistrationForm_SecretURL', 'CROWD_APP_USERNAME', 'CROWD_APP_PASSWORD', 'Direct_Reply_Username', + 'Direct_Reply_Password', 'SMTP_Username', 'SMTP_Password', 'FileUpload_S3_AWSAccessKeyId', 'FileUpload_S3_AWSSecretAccessKey', + 'FileUpload_S3_BucketURL', 'FileUpload_GoogleStorage_Bucket', 'FileUpload_GoogleStorage_AccessId', + 'FileUpload_GoogleStorage_Secret', 'GoogleVision_ServiceAccount', 'Allow_Invalid_SelfSigned_Certs', 'GoogleTagManager_id', + 'Bugsnag_api_key', 'LDAP_CA_Cert', 'LDAP_Reject_Unauthorized', 'LDAP_Domain_Search_User', 'LDAP_Domain_Search_Password', + 'Livechat_secret_token', 'Livechat_Knowledge_Apiai_Key', 'AutoTranslate_GoogleAPIKey', 'MapView_GMapsAPIKey', + 'Meta_fb_app_id', 'Meta_google-site-verification', 'Meta_msvalidate01', 'Accounts_OAuth_Dolphin_secret', + 'Accounts_OAuth_Drupal_secret', 'Accounts_OAuth_Facebook_secret', 'Accounts_OAuth_Github_secret', 'API_GitHub_Enterprise_URL', + 'Accounts_OAuth_GitHub_Enterprise_secret', 'API_Gitlab_URL', 'Accounts_OAuth_Gitlab_secret', 'Accounts_OAuth_Google_secret', + 'Accounts_OAuth_Linkedin_secret', 'Accounts_OAuth_Meteor_secret', 'Accounts_OAuth_Twitter_secret', 'API_Wordpress_URL', + 'Accounts_OAuth_Wordpress_secret', 'Push_apn_passphrase', 'Push_apn_key', 'Push_apn_cert', 'Push_apn_dev_passphrase', + 'Push_apn_dev_key', 'Push_apn_dev_cert', 'Push_gcm_api_key', 'Push_gcm_project_number', 'SAML_Custom_Default_cert', + 'SAML_Custom_Default_private_key', 'SlackBridge_APIToken', 'Smarsh_Email', 'SMS_Twilio_Account_SID', 'SMS_Twilio_authToken' + ]; } getAll(rocketletId) { console.log(`The Rocketlet ${ rocketletId } is getting all the settings.`); - throw new Error('Method not implemented.'); + + return RocketChat.models.Settings.find({ _id: { $nin: this.disallowedSettings } }).fetch().map((s) => { + this.orch.getConverters().get('settings').convertToRocketlet(s); + }); } getOneById(id, rocketletId) { @@ -38,7 +55,7 @@ export class RocketletSettingBridge { isReadableById(id, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is checking if they can read the setting ${ id }.`); - return this.allowedSettings.includes(id); + return !this.disallowedSettings.includes(id); } updateOne(setting, rocketletId) { diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js index 0b6bc5153796..50aff66c52b9 100644 --- a/packages/rocketchat-rocketlets/server/communication/rest.js +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -40,7 +40,19 @@ export class RocketletsRestApi { this.api.addRoute('', { authRequired: true }, { get() { - const rocketlets = manager.get().map(prl => prl.getInfo()); + const rocketlets = manager.get().map(prl => { + if (this.queryParams.languagesOnly) { + return { + id: prl.getID(), + languages: prl.getStorageItem().languageFiles + }; + } else { + const info = prl.getInfo(); + info.languages = prl.getStorageItem().languageFiles; + + return info; + } + }); return { success: true, rocketlets }; }, @@ -60,9 +72,16 @@ export class RocketletsRestApi { this.api.addRoute(':id', { authRequired: true }, { get() { console.log('Getting:', this.urlParams.id); - const rocketlet = manager.getOneById(this.urlParams.id).getInfo(); + const prl = manager.getOneById(this.urlParams.id); - return { success: true, rocketlet }; + if (prl) { + const info = prl.getInfo(); + info.languages = prl.getStorageItem().languageFiles; + + return { success: true, rocketlet: info }; + } else { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } }, post() { console.log('Updating:', this.urlParams.id); diff --git a/packages/rocketchat-rocketlets/server/converters/settings.js b/packages/rocketchat-rocketlets/server/converters/settings.js index edce911c6cf5..f6a6d3dabdda 100644 --- a/packages/rocketchat-rocketlets/server/converters/settings.js +++ b/packages/rocketchat-rocketlets/server/converters/settings.js @@ -8,6 +8,10 @@ export class RocketletSettingsConverter { convertById(settingId) { const setting = RocketChat.models.Settings.findOneById(settingId); + return this.convertToRocketlet(setting); + } + + convertToRocketlet(setting) { return { id: setting._id, type: this._convertTypeToRocketlet(setting.type), From 361a645ed33a7f95cc917b200ebd5bc8a77bb97b Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Thu, 14 Sep 2017 11:54:59 -0500 Subject: [PATCH 068/801] Add a manage page and add the initial settings to be managed, needs more work --- packages/rocketchat-i18n/i18n/en.i18n.json | 7 + .../client/lib/RestApiClient.js | 6 +- .../assets/stylesheets/rocketlets.css | 4 + .../client/admin/rocketletManage.html | 230 ++++++++++++++++++ .../client/admin/rocketletManage.js | 111 +++++++++ .../client/admin/rocketlets.html | 2 +- .../client/admin/rocketlets.js | 12 + .../client/communication/websockets.js | 4 +- .../client/orchestrator.js | 15 +- packages/rocketchat-rocketlets/package.js | 10 +- .../server/communication/rest.js | 106 +++++++- .../server/orchestrator.js | 2 +- 12 files changed, 498 insertions(+), 11 deletions(-) create mode 100644 packages/rocketchat-rocketlets/client/admin/rocketletManage.html create mode 100644 packages/rocketchat-rocketlets/client/admin/rocketletManage.js diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 19b5d6bbf61b..996f1c24dc84 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -227,6 +227,7 @@ "Audio_message": "Audio message", "Auth_Token": "Auth Token", "Author": "Author", + "Author_Information": "Author Information", "Authorization_URL": "Authorization URL", "Authorize": "Authorize", "Auto_Load_Images": "Auto Load Images", @@ -263,6 +264,7 @@ "Back_to_integrations": "Back to integrations", "Back_to_integration_detail": "Back to the integration detail", "Back_to_login": "Back to login", + "Back_to_Manage_Rocketlets": "Back to Manage Rocketlets", "Back_to_permissions": "Back to permissions", "Backup_codes": "Backup codes", "Beta_feature_Depends_on_Video_Conference_to_be_enabled": "Beta feature. Depends on Video Conference to be enabled.", @@ -1340,6 +1342,7 @@ "manage-sounds": "Manage Sounds", "manage-sounds_description": "Permission to manage the server sounds", "Manage_Rocketlets": "Manage Rocketlets", + "Manage_the_Rocketlet": "Manage the Rocketlet", "mention-all": "Mention All", "mention-all_description": "Permission to use the @all mention", "mute-user": "Mute User", @@ -1525,6 +1528,8 @@ "Restart_the_server": "Restart the server", "Retry_Count": "Retry Count", "Rocketlets": "Rocketlets", + "Rocketlet_Information": "Rocketlet Information", + "Rocketlets_Settings": "Rocketlet's Settings", "Role": "Role", "Role_Editing": "Role Editing", "Role_removed": "Role removed", @@ -1726,6 +1731,7 @@ "Success": "Success", "Success_message": "Success message", "Sunday": "Sunday", + "Support": "Support", "Survey": "Survey", "Survey_instructions": "Rate each question according to your satisfaction, 1 meaning you are completely unsatisfied and 5 meaning you are completely satisfied.", "Symbols": "Symbols", @@ -1960,6 +1966,7 @@ "WebRTC_Enable_Private": "Enable for Private Channels", "WebRTC_Servers": "STUN/TURN Servers", "WebRTC_Servers_Description": "A list of STUN and TURN servers separated by comma.
Username, password and port are allowed in the format `username:password@stun:host:port` or `username:password@turn:host:port`.", + "Website": "Website", "Wednesday": "Wednesday", "Welcome": "Welcome %s.", "Welcome_to_the": "Welcome to the", diff --git a/packages/rocketchat-lib/client/lib/RestApiClient.js b/packages/rocketchat-lib/client/lib/RestApiClient.js index ab353e69cb12..f19c49b84d66 100644 --- a/packages/rocketchat-lib/client/lib/RestApiClient.js +++ b/packages/rocketchat-lib/client/lib/RestApiClient.js @@ -3,6 +3,10 @@ RocketChat.API = { return RocketChat.API._jqueryCall('GET', endpoint, params); }, + post(endpoint, params, body) { + return RocketChat.API._jqueryCall('POST', endpoint, params, body); + }, + _jqueryCall(method, endpoint, params, body) { let query = ''; if (params) { @@ -22,7 +26,7 @@ RocketChat.API = { 'X-User-Id': localStorage['Meteor.userId'], 'X-Auth-Token': localStorage['Meteor.loginToken'] }, - data: body, + data: JSON.stringify(body), success: function _rlGetSuccess(result) { resolve(result); }, diff --git a/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css b/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css index e69de29bb2d1..09e0ffc6fb2d 100644 --- a/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css +++ b/packages/rocketchat-rocketlets/assets/stylesheets/rocketlets.css @@ -0,0 +1,4 @@ +input.rocketlet-author-name { + width: auto !important; + display: inline-block !important; +} diff --git a/packages/rocketchat-rocketlets/client/admin/rocketletManage.html b/packages/rocketchat-rocketlets/client/admin/rocketletManage.html new file mode 100644 index 000000000000..608a4b5e836c --- /dev/null +++ b/packages/rocketchat-rocketlets/client/admin/rocketletManage.html @@ -0,0 +1,230 @@ + diff --git a/packages/rocketchat-rocketlets/client/admin/rocketletManage.js b/packages/rocketchat-rocketlets/client/admin/rocketletManage.js new file mode 100644 index 000000000000..4203dc91d588 --- /dev/null +++ b/packages/rocketchat-rocketlets/client/admin/rocketletManage.js @@ -0,0 +1,111 @@ +Template.rocketletManage.onCreated(function() { + const instance = this; + this.ready = new ReactiveVar(false); + this.rocketlet = new ReactiveVar({}); + this.settings = new ReactiveVar({}); + + const id = FlowRouter.getParam('rocketletId'); + + console.log(id); + + const got = { info: false, settings: false }; + + RocketChat.API.get(`rocketlets/${ id }`).then((result) => { + instance.rocketlet.set(result.rocketlet); + console.log(result.rocketlet); + + got.info = true; + if (got.info && got.settings) { + this.ready.set(true); + } + }); + + RocketChat.API.get(`rocketlets/${ id }/settings`).then((result) => { + Object.keys(result.settings).forEach((k) => { + result.settings[k].oldValue = result.settings[k].value; + }); + + instance.settings.set(result.settings); + console.log(instance.settings.get()); + + got.settings = true; + if (got.info && got.settings) { + this.ready.set(true); + } + }); +}); + +Template.rocketletManage.helpers({ + isReady() { + if (Template.instance().ready != null) { + return Template.instance().ready.get(); + } + + return false; + }, + rocketlet() { + return Template.instance().rocketlet.get(); + }, + settings() { + return Object.values(Template.instance().settings.get()); + }, + parseDescription(i18nDescription) { + const item = RocketChat.Markdown.parseNotEscaped({ html: t(i18nDescription) }); + + item.tokens.forEach((t) => item.html = item.html.replace(t.token, t.text)); + + return item.html; + } +}); + +Template.rocketletManage.events({ + 'click .expand': (e) => { + $(e.currentTarget).closest('.section').removeClass('section-collapsed'); + $(e.currentTarget).closest('button').removeClass('expand').addClass('collapse').find('span').text(TAPi18n.__('Collapse')); + $('.CodeMirror').each((index, codeMirror) => codeMirror.CodeMirror.refresh()); + }, + + 'click .collapse': (e) => { + $(e.currentTarget).closest('.section').addClass('section-collapsed'); + $(e.currentTarget).closest('button').addClass('expand').removeClass('collapse').find('span').text(TAPi18n.__('Expand')); + }, + + 'click .save': (e, t) => { + const toSave = []; + + Object.keys(t.settings.get()).forEach((k) => { + const setting = t.settings.get()[k]; + if (setting.hasChanged) { + toSave.push(setting); + } + }); + + if (toSave.length === 0) { + console.log('Nothing to save..'); + return; + } + + const rocketletId = FlowRouter.getParam('rocketletId'); + RocketChat.API.post(`rocketlets/${ rocketletId }/settings`, undefined, { settings: toSave }).then((result) => { + console.log('Updating results:', result); + }); + }, + + 'change .input-monitor, keyup .input-monitor': _.throttle(function(e, t) { + let value = _.trim($(e.target).val()); + switch (this.type) { + case 'int': + value = parseInt(value); + break; + case 'boolean': + value = value === '1'; + } + + const setting = t.settings.get()[this.id]; + setting.value = value; + + if (setting.oldValue !== setting.value) { + t.settings.get()[this.id].hasChanged = true; + } + }, 500) +}); diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html index 74fbb58e9f44..29be20cdabed 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.html +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -11,7 +11,7 @@

{{#requiresPermission 'manage-rocketlets'}} {{#each rocketlets}} {{/each}} {{/requiresPermission}} diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.js b/packages/rocketchat-rocketlets/client/admin/rocketlets.js index a869c96ec1c8..1aabdf0d8bb1 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.js +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.js @@ -20,3 +20,15 @@ Template.rocketlets.helpers({ return Template.instance().rocketlets.get(); } }); + +Template.rocketlets.events({ + 'click .manage'() { + const rl = this; + + if (rl && rl.id) { + FlowRouter.go(`/admin/rocketlets/${ rl.id }`); + } else { + // show an error ? I don't think this should ever happen + } + } +}); diff --git a/packages/rocketchat-rocketlets/client/communication/websockets.js b/packages/rocketchat-rocketlets/client/communication/websockets.js index b7aef6dc1dfc..0cffd616287f 100644 --- a/packages/rocketchat-rocketlets/client/communication/websockets.js +++ b/packages/rocketchat-rocketlets/client/communication/websockets.js @@ -11,8 +11,8 @@ export class RocketletWebsocketReceiver { } onRocketletAdded(rocketletId) { - RocketChat.API.get(`rocketlets/${ rocketletId }`).then((result) => { - this.orch.parseAndLoadLanguages(result.rocketlet.languages); + RocketChat.API.get(`rocketlets/${ rocketletId }/languages`).then((result) => { + this.orch.parseAndLoadLanguages(result.languages); }); } diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js index d2ff6dd02113..4c702c0fad2a 100644 --- a/packages/rocketchat-rocketlets/client/orchestrator.js +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -5,7 +5,13 @@ class RocketletClientOrchestrator { this.ws = new RocketletWebsocketReceiver(this); this._addAdminMenuOption(); - setTimeout(() => this._loadLanguages(), 500); + + const loadLangs = setInterval(() => { + if (Meteor.user()) { + clearInterval(loadLangs); + this._loadLanguages(); + } + }, 50); } getWsListener() { @@ -56,3 +62,10 @@ FlowRouter.route('/admin/rocketlets', { BlazeLayout.render('main', { center: 'rocketlets' }); } }); + +FlowRouter.route('/admin/rocketlets/:rocketletId', { + name: 'rocketlet-manage', + action() { + BlazeLayout.render('main', { center: 'rocketletManage' }); + } +}); diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index 5ea4ba27e3e2..46de00cdc6bd 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -11,7 +11,7 @@ Package.onUse(function(api) { 'templating' ]); - api.use(['reactive-var', 'kadira:flow-router'], 'client'); + api.use(['reactive-var', 'kadira:flow-router', 'underscore'], 'client'); api.addFiles('lib/Rocketlets.js', ['client', 'server']); @@ -65,7 +65,9 @@ Package.onUse(function(api) { // Client Admin Management api.addFiles([ 'client/admin/rocketlets.html', - 'client/admin/rocketlets.js' + 'client/admin/rocketlets.js', + 'client/admin/rocketletManage.html', + 'client/admin/rocketletManage.js' ], 'client'); api.addFiles('assets/stylesheets/rocketlets.css', 'client'); @@ -79,6 +81,6 @@ Package.onUse(function(api) { Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.26', - 'temporary-rocketlets-ts-definition': '0.6.26' + 'temporary-rocketlets-server': '0.1.27', + 'temporary-rocketlets-ts-definition': '0.6.27' }); diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js index 50aff66c52b9..29efe7eed749 100644 --- a/packages/rocketchat-rocketlets/server/communication/rest.js +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -76,7 +76,6 @@ export class RocketletsRestApi { if (prl) { const info = prl.getInfo(); - info.languages = prl.getStorageItem().languageFiles; return { success: true, rocketlet: info }; } else { @@ -95,5 +94,110 @@ export class RocketletsRestApi { return { success: false, item }; } }); + + this.api.addRoute(':id/languages', { authRequired: true }, { + get() { + console.log(`Getting ${ this.urlParams.id }'s languages..`); + const prl = manager.getOneById(this.urlParams.id); + + if (prl) { + const languages = prl.getStorageItem().languageFiles || {}; + + return { success: true, languages }; + } else { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } + } + }); + + this.api.addRoute(':id/settings', { authRequired: true }, { + get() { + console.log(`Getting ${ this.urlParams.id }'s settings..`); + const prl = manager.getOneById(this.urlParams.id); + + if (prl) { + const settings = Object.assign({}, prl.getStorageItem().settings); + + Object.keys(settings).forEach((k) => { + if (settings[k].hidden) { + delete settings[k]; + } + }); + + return { success: true, settings }; + } else { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } + }, + post() { + console.log(`Updating ${ this.urlParams.id }'s settings..`); + if (!this.bodyParams || !this.bodyParams.settings) { + return RocketChat.API.v1.failure('The settings to update must be present.'); + } + + const prl = manager.getOneById(this.urlParams.id); + + if (!prl) { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } + + const settings = prl.getStorageItem().settings; + + const updated = []; + this.bodyParams.settings.forEach((s) => { + if (settings[s.id]) { + Promise.await(manager.getSettingsManager().updateRocketletSetting(this.urlParams.id, s)); + // Updating? + updated.push(s); + } + }); + + return { success: true, updated }; + } + }); + + this.api.addRoute(':id/settings/:settingId', { authRequired: true }, { + get() { + console.log(`Getting the Rocketlet ${ this.urlParams.id }'s setting ${ this.urlParams.settingId }`); + + try { + const setting = manager.getSettingsManager().getRocketletSetting(this.urlParams.id, this.urlParams.settingId); + + return { + success: true, + setting + }; + } catch (e) { + if (e.message.includes('No setting found')) { + return RocketChat.API.v1.notFound(`No Setting found on the Rocketlet by the id of: "${ this.urlParams.settingId }"`); + } else if (e.message.includes('No Rocketlet found')) { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } else { + return RocketChat.API.v1.failure(e.message); + } + } + }, + post() { + console.log(`Updating the Rocketlet ${ this.urlParams.id }'s setting ${ this.urlParams.settingId }`); + + if (!this.bodyParams.setting) { + return RocketChat.API.v1.failure('Setting to update to must be present on the posted body.'); + } + + try { + Promise.await(manager.getSettingsManager().updateRocketletSetting(this.urlParams.id, this.bodyParams.setting)); + + return { success: true }; + } catch (e) { + if (e.message.includes('No setting found')) { + return RocketChat.API.v1.notFound(`No Setting found on the Rocketlet by the id of: "${ this.urlParams.settingId }"`); + } else if (e.message.includes('No Rocketlet found')) { + return RocketChat.API.v1.notFound(`No Rocketlet found by the id of: ${ this.urlParams.id }`); + } else { + return RocketChat.API.v1.failure(e.message); + } + } + } + }); } } diff --git a/packages/rocketchat-rocketlets/server/orchestrator.js b/packages/rocketchat-rocketlets/server/orchestrator.js index 42a4b2f6f1b3..c9a79eb7af14 100644 --- a/packages/rocketchat-rocketlets/server/orchestrator.js +++ b/packages/rocketchat-rocketlets/server/orchestrator.js @@ -64,6 +64,6 @@ Meteor.startup(function _rocketletServerOrchestrator() { global.Rocketlets = new RocketletServerOrchestrator(); global.Rocketlets.getManager().load() - .then(() => console.log('...done! :)')) + .then(() => console.log('...done! ;)')) .catch((err) => console.warn('...failed!', err)); }); From 5d86782786ebac7727c49b3442792a60938efb91 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Fri, 15 Sep 2017 10:09:27 -0500 Subject: [PATCH 069/801] Update to the new internal translations structure --- .../rocketchat-rocketlets/client/admin/rocketletManage.js | 2 +- packages/rocketchat-rocketlets/client/orchestrator.js | 4 +--- packages/rocketchat-rocketlets/server/communication/rest.js | 6 +++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/rocketchat-rocketlets/client/admin/rocketletManage.js b/packages/rocketchat-rocketlets/client/admin/rocketletManage.js index 4203dc91d588..bc57b50e23ec 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketletManage.js +++ b/packages/rocketchat-rocketlets/client/admin/rocketletManage.js @@ -50,7 +50,7 @@ Template.rocketletManage.helpers({ return Object.values(Template.instance().settings.get()); }, parseDescription(i18nDescription) { - const item = RocketChat.Markdown.parseNotEscaped({ html: t(i18nDescription) }); + const item = RocketChat.Markdown.parseMessageNotEscaped({ html: t(i18nDescription) }); item.tokens.forEach((t) => item.html = item.html.replace(t.token, t.text)); diff --git a/packages/rocketchat-rocketlets/client/orchestrator.js b/packages/rocketchat-rocketlets/client/orchestrator.js index 4c702c0fad2a..611b4013d96c 100644 --- a/packages/rocketchat-rocketlets/client/orchestrator.js +++ b/packages/rocketchat-rocketlets/client/orchestrator.js @@ -41,9 +41,7 @@ class RocketletClientOrchestrator { parseAndLoadLanguages(languages) { Object.keys(languages).forEach((key) => { try { - const json = JSON.parse(languages[key]); - - TAPi18next.addResourceBundle(key, 'project', json); + TAPi18next.addResourceBundle(key, 'project', languages[key]); } catch (e) { // Failed to parse the json } diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js index 29efe7eed749..6ce815a68102 100644 --- a/packages/rocketchat-rocketlets/server/communication/rest.js +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -44,11 +44,11 @@ export class RocketletsRestApi { if (this.queryParams.languagesOnly) { return { id: prl.getID(), - languages: prl.getStorageItem().languageFiles + languages: prl.getStorageItem().languageContent }; } else { const info = prl.getInfo(); - info.languages = prl.getStorageItem().languageFiles; + info.languages = prl.getStorageItem().languageContent; return info; } @@ -101,7 +101,7 @@ export class RocketletsRestApi { const prl = manager.getOneById(this.urlParams.id); if (prl) { - const languages = prl.getStorageItem().languageFiles || {}; + const languages = prl.getStorageItem().languageContent || {}; return { success: true, languages }; } else { From 23e9a607353a21e5094a0165fafc8c92d36fe899 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Wed, 28 Jun 2017 15:41:19 +0100 Subject: [PATCH 070/801] WIP --- .meteor/packages | 1 + .meteor/versions | 1 + .../.npm/package/.gitignore | 1 + .../rocketchat-graphql/.npm/package/README | 7 + .../.npm/package/npm-shrinkwrap.json | 334 ++++++++++++++++++ packages/rocketchat-graphql/package.js | 27 ++ packages/rocketchat-graphql/server/api.js | 36 ++ .../server/helpers/findChannelByIdAndUser.js | 8 + .../server/helpers/property.js | 3 + packages/rocketchat-graphql/server/schema.js | 179 ++++++++++ 10 files changed, 597 insertions(+) create mode 100644 packages/rocketchat-graphql/.npm/package/.gitignore create mode 100644 packages/rocketchat-graphql/.npm/package/README create mode 100644 packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json create mode 100644 packages/rocketchat-graphql/package.js create mode 100644 packages/rocketchat-graphql/server/api.js create mode 100644 packages/rocketchat-graphql/server/helpers/findChannelByIdAndUser.js create mode 100644 packages/rocketchat-graphql/server/helpers/property.js create mode 100644 packages/rocketchat-graphql/server/schema.js diff --git a/.meteor/packages b/.meteor/packages index 1baeab932dec..53fb9389b819 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -63,6 +63,7 @@ rocketchat:file-upload rocketchat:github-enterprise rocketchat:gitlab rocketchat:google-vision +rocketchat:graphql rocketchat:highlight-words rocketchat:iframe-login rocketchat:importer diff --git a/.meteor/versions b/.meteor/versions index 56584e33d724..5ceb7cee121a 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -151,6 +151,7 @@ rocketchat:file-upload@0.0.1 rocketchat:github-enterprise@0.0.1 rocketchat:gitlab@0.0.1 rocketchat:google-vision@0.0.1 +rocketchat:graphql@0.0.1 rocketchat:highlight-words@0.0.1 rocketchat:i18n@0.0.1 rocketchat:iframe-login@1.0.0 diff --git a/packages/rocketchat-graphql/.npm/package/.gitignore b/packages/rocketchat-graphql/.npm/package/.gitignore new file mode 100644 index 000000000000..3c3629e647f5 --- /dev/null +++ b/packages/rocketchat-graphql/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/rocketchat-graphql/.npm/package/README b/packages/rocketchat-graphql/.npm/package/README new file mode 100644 index 000000000000..3d492553a438 --- /dev/null +++ b/packages/rocketchat-graphql/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json new file mode 100644 index 000000000000..99bd39438b7f --- /dev/null +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,334 @@ +{ + "dependencies": { + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "from": "accepts@>=1.3.3 <1.4.0" + }, + "apollo-client": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-1.6.0.tgz", + "from": "apollo-client@1.6.0" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "from": "array-flatten@1.1.1" + }, + "body-parser": { + "version": "1.17.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", + "from": "body-parser@1.17.2" + }, + "bytes": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", + "from": "bytes@2.4.0" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "from": "content-disposition@0.5.2" + }, + "content-type": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "from": "content-type@>=1.0.2 <1.1.0" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "from": "cookie@0.3.1" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "from": "cookie-signature@1.0.6" + }, + "cors": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.3.tgz", + "from": "cors@2.8.3" + }, + "debug": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "from": "debug@2.6.7" + }, + "depd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "from": "depd@>=1.1.0 <1.2.0" + }, + "deprecated-decorator": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", + "from": "deprecated-decorator@>=0.1.6 <0.2.0" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "from": "destroy@>=1.0.4 <1.1.0" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "from": "ee-first@1.1.1" + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "from": "encodeurl@>=1.0.1 <1.1.0" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "from": "escape-html@>=1.0.3 <1.1.0" + }, + "etag": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", + "from": "etag@>=1.8.0 <1.9.0" + }, + "express": { + "version": "4.15.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", + "from": "express@4.15.3" + }, + "finalhandler": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", + "from": "finalhandler@>=1.0.3 <1.1.0" + }, + "forwarded": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", + "from": "forwarded@>=0.1.0 <0.2.0" + }, + "fresh": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", + "from": "fresh@0.5.0" + }, + "graphql": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.10.3.tgz", + "from": "graphql@0.10.3" + }, + "graphql-anywhere": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz", + "from": "graphql-anywhere@>=3.0.1 <4.0.0" + }, + "graphql-server-core": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/graphql-server-core/-/graphql-server-core-0.9.0.tgz", + "from": "graphql-server-core@>=0.9.0 <0.10.0" + }, + "graphql-server-express": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/graphql-server-express/-/graphql-server-express-0.9.0.tgz", + "from": "graphql-server-express@0.9.0" + }, + "graphql-server-module-graphiql": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/graphql-server-module-graphiql/-/graphql-server-module-graphiql-0.9.0.tgz", + "from": "graphql-server-module-graphiql@>=0.9.0 <0.10.0" + }, + "graphql-tag": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.4.2.tgz", + "from": "graphql-tag@>=2.0.0 <3.0.0" + }, + "graphql-tools": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.0.0.tgz", + "from": "graphql-tools@1.0.0" + }, + "http-errors": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", + "from": "http-errors@>=1.6.1 <1.7.0" + }, + "iconv-lite": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", + "from": "iconv-lite@0.4.15" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "from": "inherits@2.0.3" + }, + "ipaddr.js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", + "from": "ipaddr.js@1.3.0" + }, + "iterall": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.1.tgz", + "from": "iterall@>=1.1.0 <2.0.0" + }, + "js-tokens": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "from": "js-tokens@>=3.0.0 <4.0.0" + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "from": "lodash@>=4.2.1 <5.0.0" + }, + "lodash-es": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", + "from": "lodash-es@>=4.2.1 <5.0.0" + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "from": "loose-envify@>=1.1.0 <2.0.0" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "from": "media-typer@0.3.0" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "from": "merge-descriptors@1.0.1" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "from": "methods@>=1.1.2 <1.2.0" + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "from": "mime@1.3.4" + }, + "mime-db": { + "version": "1.27.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", + "from": "mime-db@>=1.27.0 <1.28.0" + }, + "mime-types": { + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "from": "mime-types@>=2.1.11 <2.2.0" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "from": "ms@2.0.0" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "from": "negotiator@0.6.1" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "from": "object-assign@>=4.0.0 <5.0.0" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "from": "on-finished@>=2.3.0 <2.4.0" + }, + "parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "from": "parseurl@>=1.3.1 <1.4.0" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "from": "path-to-regexp@0.1.7" + }, + "proxy-addr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz", + "from": "proxy-addr@>=1.1.4 <1.2.0" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "from": "qs@6.4.0" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "from": "range-parser@>=1.2.0 <1.3.0" + }, + "raw-body": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", + "from": "raw-body@>=2.2.0 <2.3.0" + }, + "redux": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.1.tgz", + "from": "redux@>=3.4.0 <4.0.0" + }, + "send": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", + "from": "send@0.15.3" + }, + "serve-static": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz", + "from": "serve-static@1.12.3" + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "from": "setprototypeof@1.0.3" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "from": "statuses@>=1.3.1 <1.4.0" + }, + "symbol-observable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", + "from": "symbol-observable@>=1.0.2 <2.0.0" + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "from": "type-is@>=1.6.15 <1.7.0" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "from": "unpipe@>=1.0.0 <1.1.0" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "from": "utils-merge@1.0.0" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "from": "uuid@>=3.0.1 <4.0.0" + }, + "vary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", + "from": "vary@>=1.0.0 <2.0.0" + }, + "whatwg-fetch": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", + "from": "whatwg-fetch@>=2.0.0 <3.0.0" + } + } +} diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js new file mode 100644 index 000000000000..37791a9b9c39 --- /dev/null +++ b/packages/rocketchat-graphql/package.js @@ -0,0 +1,27 @@ +Package.describe({ + name: 'rocketchat:graphql', + version: '0.0.1', + summary: 'GraphQL API', + git: '' +}); + +Package.onUse(function(api) { + api.use([ + 'underscore', + 'ecmascript', + 'rocketchat:lib', + 'rocketchat:api' + ]); + + api.addFiles('server/api.js', 'server'); +}); + +Npm.depends({ + 'apollo-client': '1.6.0', + cors: '2.8.3', + express: '4.15.3', + graphql: '0.10.3', + 'graphql-server-express': '0.9.0', + 'graphql-tools': '1.0.0', + 'body-parser': '1.17.2' +}); diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js new file mode 100644 index 000000000000..295b777518cc --- /dev/null +++ b/packages/rocketchat-graphql/server/api.js @@ -0,0 +1,36 @@ +import { graphqlExpress, graphiqlExpress } from 'graphql-server-express'; +import bodyParser from 'body-parser'; +import express from 'express'; +import cors from 'cors'; +import { Meteor } from 'meteor/meteor'; +import { WebApp } from 'meteor/webapp'; + +import { executableSchema } from './schema'; + +// the Meteor GraphQL server is an Express server +const graphQLServer = express(); + +graphQLServer.use(cors()); +graphQLServer.use(bodyParser.urlencoded({ extended: true })); + +graphQLServer.use( + '/graphql', + bodyParser.json(), + graphqlExpress(() => ({ + schema: executableSchema, + context: {}, + formatError: e => ({ + message: e.message, + locations: e.locations, + path: e.path + }), + debug: Meteor.isDevelopment + }))); + +graphQLServer.use('/graphiql', graphiqlExpress({ + endpointURL: '/graphql' +})); + + +// this binds the specified paths to the Express server running Apollo + GraphiQL +WebApp.connectHandlers.use(graphQLServer); diff --git a/packages/rocketchat-graphql/server/helpers/findChannelByIdAndUser.js b/packages/rocketchat-graphql/server/helpers/findChannelByIdAndUser.js new file mode 100644 index 000000000000..b36f972203e6 --- /dev/null +++ b/packages/rocketchat-graphql/server/helpers/findChannelByIdAndUser.js @@ -0,0 +1,8 @@ +export function findChannelByIdAndUser({ params, options = {} }) { + const sub = RocketChat.models.Subscriptions.findOne({ + rid: params.roomId, + 'u._id': params.userId + }, options); + + return sub; +} diff --git a/packages/rocketchat-graphql/server/helpers/property.js b/packages/rocketchat-graphql/server/helpers/property.js new file mode 100644 index 000000000000..65485cae9868 --- /dev/null +++ b/packages/rocketchat-graphql/server/helpers/property.js @@ -0,0 +1,3 @@ +export function property(key) { + return (object) => object == null ? undefined : object[key]; +} diff --git a/packages/rocketchat-graphql/server/schema.js b/packages/rocketchat-graphql/server/schema.js new file mode 100644 index 000000000000..8bf5a3bb1dda --- /dev/null +++ b/packages/rocketchat-graphql/server/schema.js @@ -0,0 +1,179 @@ +import { + makeExecutableSchema +} from 'graphql-tools'; + +import { + property +} from './helpers/property'; + +import { + findChannelByIdAndUser +} from './helpers/findChannelByIdAndUser'; + +// mys:admin +const testUser = 'fnw4B4suFsTXf8rZq'; + +const schema = ` + type schema { + query: Query + } + + type Query { + channels(filter: ChannelFilter = { + privacy: ALL, + joinedChannels: false, + sortBy: NAME + }): [Channel] + } + + type Channel { + id: String! + name: String + description: String + announcement: String + topic: String + members: [Member] + owners: [Member] + numberOfMembers: Int + numberOfMessages: Int + readOnly: Boolean + direct: Boolean + privateChannel: Boolean + favourite: Boolean + unseenMessages: Int + } + + enum Privacy { + PRIVATE + PUBLIC + ALL + } + + enum ChannelSort { + NAME + NUMBER_OF_MESSAGES + } + + input ChannelFilter { + nameFilter: String + privacy: Privacy + joinedChannels: Boolean + sortBy: ChannelSort + } + + type Member { + id: String! + name: String + } +`; + +const resolvers = { + Query: { + channels: (root, args) => { + const query = {}; + const options = { + sort: { + name: 1 + }, + fields: { + t: 1, + name: 1, + description: 1, + announcement: 1, + topic: 1, + usernames: 1, + msgs: 1, + ro: 1, + u: 1, + archived: 1 + } + }; + + // Filter + if (typeof args.filter !== 'undefined') { + // sortBy + if (args.filter.sortBy === 'NUMBER_OF_MESSAGES') { + options.sort = { + msgs: -1 + }; + } + + // privacy + switch (args.filter.privacy) { + case 'PRIVATE': + query.t = 'p'; + break; + case 'PUBLIC': + query.t = { + $ne: 'p' + }; + break; + } + } + + return RocketChat.models.Rooms.find(query, options).fetch(); + } + }, + Channel: { + id: property('_id'), + members: (root) => { + return root.usernames.map( + username => RocketChat.models.Users.findOneByUsername(username, { + fields: { + name: 1 + } + }) + ); + }, + owners: (root) => { + // there might be no owner + if (!root.u) { + return []; + } + + return [RocketChat.models.Users.findOneByUsername(root.u.username, { + fields: { + name: 1 + } + })]; + }, + numberOfMembers: (root) => (root.usernames || []).length, + numberOfMessages: property('msgs'), + readOnly: (root) => root.ro === true, + direct: (root) => root.t === 'd', + privateChannel: (root) => root.t === 'p', + favourite: (root) => { + const room = findChannelByIdAndUser({ + params: { + roomId: root._id, + userId: testUser + }, + options: { fields: { f: 1 }} + }); + + return room && room.f === true; + }, + unseenMessages: (root) => { + const room = findChannelByIdAndUser({ + params: { + roomId: root._id, + userId: testUser + }, + options: { fields: { unread: 1 }} + }); + + return (room || {}).unread; + } + }, + Member: { + id: property('_id') + } +}; + +export const executableSchema = makeExecutableSchema({ + typeDefs: [schema], + resolvers, + logger: { + log: (e) => console.log(e) + } +}); From 42ed8a429328ecd2bff82a260b77267454378439 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Thu, 29 Jun 2017 17:40:24 +0100 Subject: [PATCH 071/801] WIP --- packages/rocketchat-graphql/server/api.js | 4 +- .../server/mocks/accounts/graphql-api.js | 9 + .../server/mocks/accounts/server.js | 14 ++ packages/rocketchat-graphql/server/schema.js | 227 +++++++++++++++--- 4 files changed, 217 insertions(+), 37 deletions(-) create mode 100644 packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js create mode 100644 packages/rocketchat-graphql/server/mocks/accounts/server.js diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index 295b777518cc..040845247a44 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -18,7 +18,9 @@ graphQLServer.use( bodyParser.json(), graphqlExpress(() => ({ schema: executableSchema, - context: {}, + context: { + models: RocketChat.models + }, formatError: e => ({ message: e.message, locations: e.locations, diff --git a/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js new file mode 100644 index 000000000000..ac01fd1b681a --- /dev/null +++ b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js @@ -0,0 +1,9 @@ +export const authenticated = (Accounts, func) => (async(root, args, context, info) => { + const userObject = await Accounts.resumeSession(); + + if (userObject === null) { + throw new Error('Invalid or expired token!'); + } + + return await func(root, args, Object.assign(context, { user: userObject }), info); +}); diff --git a/packages/rocketchat-graphql/server/mocks/accounts/server.js b/packages/rocketchat-graphql/server/mocks/accounts/server.js new file mode 100644 index 000000000000..2d472b58e125 --- /dev/null +++ b/packages/rocketchat-graphql/server/mocks/accounts/server.js @@ -0,0 +1,14 @@ +const loggedOut = false; + +const AccountsServer = { + async resumeSession() { + if (loggedOut) { + throw new Error('User not found'); + } + // User credentials + // mys:admin + return RocketChat.models.Users.findOneById('fnw4B4suFsTXf8rZq'); + } +}; + +export default AccountsServer; diff --git a/packages/rocketchat-graphql/server/schema.js b/packages/rocketchat-graphql/server/schema.js index 8bf5a3bb1dda..d60196d79faf 100644 --- a/packages/rocketchat-graphql/server/schema.js +++ b/packages/rocketchat-graphql/server/schema.js @@ -1,7 +1,12 @@ +/* global processWebhookMessage */ + import { makeExecutableSchema } from 'graphql-tools'; +import { authenticated } from './mocks/accounts/graphql-api'; +import AccountsServer from './mocks/accounts/server'; + import { property } from './helpers/property'; @@ -10,12 +15,11 @@ import { findChannelByIdAndUser } from './helpers/findChannelByIdAndUser'; -// mys:admin -const testUser = 'fnw4B4suFsTXf8rZq'; const schema = ` type schema { query: Query + mutation: Mutation } type Query { @@ -24,11 +28,18 @@ const schema = ` joinedChannels: false, sortBy: NAME }): [Channel] + channelByName(name: String!, isDirect: Boolean!): Channel + channelsByUser(userId: String!): [Channel] + messages(channelId: String): MessagesWithCursor + } + + type Mutation { + sendMessage(channelId: String!, content: String!): Message } type Channel { id: String! - name: String + name: String description: String announcement: String topic: String @@ -44,7 +55,7 @@ const schema = ` } enum Privacy { - PRIVATE + PRIVATE PUBLIC ALL } @@ -65,28 +76,54 @@ const schema = ` id: String! name: String } + + type MessagesWithCursor { + cursor: String + channel: Channel + messagesArray: [Message] + } + + type Message { + id: String + author: Member + content: String + creationTime: String + fromServer: Boolean + userRef: [Member] + channelRef: [Channel] + reactions: [Reaction] + # TODO + tags: [String] + } + + type Reaction { + username: String + icon: String + } `; +const roomPublicFields = { + t: 1, + name: 1, + description: 1, + announcement: 1, + topic: 1, + usernames: 1, + msgs: 1, + ro: 1, + u: 1, + archived: 1 +}; + const resolvers = { Query: { - channels: (root, args) => { + channels: authenticated(AccountsServer, (root, args, { models }) => { const query = {}; const options = { sort: { name: 1 }, - fields: { - t: 1, - name: 1, - description: 1, - announcement: 1, - topic: 1, - usernames: 1, - msgs: 1, - ro: 1, - u: 1, - archived: 1 - } + fields: roomPublicFields }; // Filter @@ -111,53 +148,112 @@ const resolvers = { } } - return RocketChat.models.Rooms.find(query, options).fetch(); - } + return models.Rooms.find(query, options).fetch(); + }), + channelByName: authenticated(AccountsServer, (root, { name, isDirect }, { models }) => { + const query = { + name + }; + + if (isDirect === true) { + query.c = 'd'; + } + + return models.Rooms.findOne(query, { + fields: roomPublicFields + }); + }), + channelsByUser: authenticated(AccountsServer, (root, { userId }, { models }) => { + const user = models.Users.findOneById(userId); + + if (!user) { + // TODO: + throw new Error('No user'); + } + + return models.Rooms.find({ + 'usernames': { + $in: user.username + } + }, { + sort: { + name: 1 + }, + fields: roomPublicFields + }).fetch(); + }), + messages: authenticated(AccountsServer, (root, args, { models }) => { + if (!args.channelId) { + console.error('messages query must be called with channelId'); + return null; + } + + const query = {}; + + if (args.channelId) { + query.rid = args.channelId; + } + + const messagesArray = models.Messages.find(query).fetch(); + const channel = models.Rooms.findOne(args.channelId); + + return { + cursor: 'CURSOR', + channel, + messagesArray + }; + }) + }, + Mutation: { + sendMessage: authenticated(AccountsServer, (root, { channelId, content }, { user }) => { + const messageReturn = processWebhookMessage({ + roomId: channelId, + text: content + }, user)[0]; + + if (!messageReturn) { + throw new Error('Unknown error'); + } + + return messageReturn.message; + }) }, Channel: { id: property('_id'), - members: (root) => { + members: (root, args, { models }) => { return root.usernames.map( - username => RocketChat.models.Users.findOneByUsername(username, { - fields: { - name: 1 - } - }) + username => models.Users.findOneByUsername(username) ); }, - owners: (root) => { + owners: (root, args, { models }) => { // there might be no owner if (!root.u) { - return []; + return; } - return [RocketChat.models.Users.findOneByUsername(root.u.username, { - fields: { - name: 1 - } - })]; + return [models.Users.findOneByUsername(root.u.username)]; }, numberOfMembers: (root) => (root.usernames || []).length, numberOfMessages: property('msgs'), readOnly: (root) => root.ro === true, direct: (root) => root.t === 'd', privateChannel: (root) => root.t === 'p', - favourite: (root) => { + favourite: (root, args, { user }) => { const room = findChannelByIdAndUser({ params: { roomId: root._id, - userId: testUser + userId: user._id }, options: { fields: { f: 1 }} }); return room && room.f === true; }, - unseenMessages: (root) => { + unseenMessages: (root, args, { user }) => { const room = findChannelByIdAndUser({ params: { roomId: root._id, - userId: testUser + userId: user._id }, options: { fields: { unread: 1 }} }); @@ -167,6 +263,65 @@ const resolvers = { }, Member: { id: property('_id') + }, + Message: { + id: property('_id'), + content: property('msg'), + creationTime: property('ts'), + author: (root, args, { models }) => { + return models.Users.findOne(root.u._id); + }, + fromServer: (root) => typeof root.t !== 'undefined', // on a message sent by user `true` otherwise `false` + channelRef: (root, args, { models }) => { + if (!root.channels) { + return; + } + + return models.Rooms.find({ + _id: { + $in: root.channels.map(c => c._id) + } + }, { + sort: { + name: 1 + } + }).fetch(); + }, + userRef: (root, args, { models }) => { + if (!root.mentions) { + return; + } + + return models.Users.find({ + _id: { + $in: root.mentions.map(c => c._id) + } + }, { + sort: { + username: 1 + } + }).fetch(); + }, + reactions: (root) => { + if (!root.reactions || Object.keys(root.reactions).length === 0) { + return; + } + + const reactions = []; + + Object.keys(root.reactions).forEach(icon => { + root.reactions[icon].usernames.forEach(username => { + reactions.push({ + icon, + username + }); + }); + }); + + return reactions; + }, + // TODO + tags: () => {} } }; From b8687217af6242a8aa4466ca73b0a91406966a42 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Thu, 29 Jun 2017 20:17:49 +0100 Subject: [PATCH 072/801] WIP --- packages/rocketchat-graphql/server/schema.js | 98 +++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-graphql/server/schema.js b/packages/rocketchat-graphql/server/schema.js index d60196d79faf..c89d5521ee52 100644 --- a/packages/rocketchat-graphql/server/schema.js +++ b/packages/rocketchat-graphql/server/schema.js @@ -4,7 +4,10 @@ import { makeExecutableSchema } from 'graphql-tools'; +import { Meteor } from 'meteor/meteor'; + import { authenticated } from './mocks/accounts/graphql-api'; + import AccountsServer from './mocks/accounts/server'; import { @@ -34,7 +37,11 @@ const schema = ` } type Mutation { + setStatus(status: UserStatus!): Member sendMessage(channelId: String!, content: String!): Message + editMessage(id: MessageIdentifier!, content: String!): Message + deleteMessage(id: MessageIdentifier!): Message + createChannel(name: String!, private: Boolean = false, readOnly: Boolean = false, membersId: [String!]): Channel } type Channel { @@ -72,9 +79,18 @@ const schema = ` sortBy: ChannelSort } + enum UserStatus { + ONLINE + AWAY + BUSY + INVISIBLE + } + type Member { id: String! name: String + # TODO: change to UserStatus + status: String } type MessagesWithCursor { @@ -83,10 +99,16 @@ const schema = ` messagesArray: [Message] } + input MessageIdentifier { + channelId: String! + messageId: String! + } + type Message { id: String author: Member content: String + channel: Channel creationTime: String fromServer: Boolean userRef: [Member] @@ -216,6 +238,76 @@ const resolvers = { } return messageReturn.message; + }), + editMessage: authenticated(AccountsServer, (root, { id, content }, { user, models }) => { + const msg = models.Messages.findOneById(id.messageId); + + //Ensure the message exists + if (!msg) { + throw new Error(`No message found with the id of "${ id.messageId }".`); + } + + if (id.channelId !== msg.rid) { + throw new Error('The channel id provided does not match where the message is from.'); + } + + //Permission checks are already done in the updateMessage method, so no need to duplicate them + Meteor.runAsUser(user._id, () => { + Meteor.call('updateMessage', { _id: msg._id, msg: content, rid: msg.rid }); + }); + + return models.Messages.findOneById(msg._id); + }), + deleteMessage: authenticated(AccountsServer, (root, { id }, { models, user }) => { + const msg = models.Messages.findOneById(id.messageId, { fields: { u: 1, rid: 1 }}); + + if (!msg) { + throw new Error(`No message found with the id of "${ id.messageId }".`); + } + + if (id.channelId !== msg.rid) { + throw new Error('The room id provided does not match where the message is from.'); + } + + Meteor.runAsUser(user._id, () => { + Meteor.call('deleteMessage', { _id: msg._id }); + }); + + return msg; + }), + setStatus: authenticated(AccountsServer, (root, { status }, { models, user }) => { + models.Users.update(user._id, { + $set: { + status: status.toLowerCase() + } + }); + + return models.Users.findOne(user._id); + }), + createChannel: authenticated(AccountsServer, (root, args, { models, user }) => { + if (!RocketChat.authz.hasPermission(user._id, 'create-c')) { + return RocketChat.API.v1.unauthorized(); + } + + if (!args.name) { + throw new Error('Param "name" is required'); + } + + if (args.membersId && !_.isArray(args.membersId)) { + throw new Error('Param "membersId" must be an array if provided'); + } + + let readOnly = false; + if (typeof args.readOnly !== 'undefined') { + readOnly = args.readOnly; + } + + let id; + Meteor.runAsUser(user._id, () => { + id = Meteor.call('createChannel', args.name, args.membersId ? args.membersId : [], readOnly); + }); + + return models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude }); }) }, Channel: { @@ -262,7 +354,8 @@ const resolvers = { } }, Member: { - id: property('_id') + id: property('_id'), + status: ({status}) => status.toUpperCase() }, Message: { id: property('_id'), @@ -271,6 +364,9 @@ const resolvers = { author: (root, args, { models }) => { return models.Users.findOne(root.u._id); }, + channel: (root, args, { models }) => { + return models.Rooms.findOne(root.rid); + }, fromServer: (root) => typeof root.t !== 'undefined', // on a message sent by user `true` otherwise `false` channelRef: (root, args, { models }) => { if (!root.channels) { From c195f46ad570d96a208666a29993c5b86cafe8e8 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Fri, 30 Jun 2017 17:32:16 +0100 Subject: [PATCH 073/801] Separate features --- .../.npm/package/npm-shrinkwrap.json | 20 +- packages/rocketchat-graphql/package.js | 5 +- packages/rocketchat-graphql/server/schema.js | 390 +----------------- .../server/schemas/channels/Channel-type.js | 67 +++ .../schemas/channels/ChannelFilter-input.js | 8 + .../schemas/channels/ChannelSort-enum.js | 6 + .../server/schemas/channels/Privacy-enum.js | 7 + .../server/schemas/channels/channelByName.js | 27 ++ .../server/schemas/channels/channels.js | 51 +++ .../server/schemas/channels/channelsByUser.js | 33 ++ .../server/schemas/channels/createChannel.js | 41 ++ .../server/schemas/channels/index.js | 38 ++ .../server/schemas/channels/settings.js | 12 + .../server/schemas/messages/Message-type.js | 82 ++++ .../messages/MessageIdentifier-input.js | 6 + .../messages/MessagesWithCursor-type.js | 7 + .../server/schemas/messages/Reaction-type.js | 6 + .../server/schemas/messages/deleteMessage.js | 32 ++ .../server/schemas/messages/editMessage.js | 34 ++ .../server/schemas/messages/index.js | 38 ++ .../server/schemas/messages/messages.js | 34 ++ .../server/schemas/messages/sendMessage.js | 27 ++ 22 files changed, 591 insertions(+), 380 deletions(-) create mode 100644 packages/rocketchat-graphql/server/schemas/channels/Channel-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/channelByName.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/channels.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/createChannel.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/index.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/settings.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/Message-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/Reaction-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/editMessage.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/index.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/messages.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/sendMessage.js diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json index 99bd39438b7f..1c663c3f6914 100644 --- a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -55,6 +55,11 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", "from": "debug@2.6.7" }, + "deepmerge": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.4.4.tgz", + "from": "deepmerge@>=1.3.2 <2.0.0" + }, "depd": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", @@ -141,9 +146,9 @@ "from": "graphql-tag@>=2.0.0 <3.0.0" }, "graphql-tools": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.0.0.tgz", - "from": "graphql-tools@1.0.0" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.1.0.tgz", + "from": "graphql-tools@1.1.0" }, "http-errors": { "version": "1.6.1", @@ -171,8 +176,8 @@ "from": "iterall@>=1.1.0 <2.0.0" }, "js-tokens": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", "from": "js-tokens@>=3.0.0 <4.0.0" }, "lodash": { @@ -200,6 +205,11 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "from": "merge-descriptors@1.0.1" }, + "merge-graphql-schemas": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-graphql-schemas/-/merge-graphql-schemas-1.1.0.tgz", + "from": "merge-graphql-schemas@1.1.0" + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js index 37791a9b9c39..3c29cdb70911 100644 --- a/packages/rocketchat-graphql/package.js +++ b/packages/rocketchat-graphql/package.js @@ -22,6 +22,7 @@ Npm.depends({ express: '4.15.3', graphql: '0.10.3', 'graphql-server-express': '0.9.0', - 'graphql-tools': '1.0.0', - 'body-parser': '1.17.2' + 'graphql-tools': '1.1.0', + 'body-parser': '1.17.2', + 'merge-graphql-schemas': '1.1.0' }); diff --git a/packages/rocketchat-graphql/server/schema.js b/packages/rocketchat-graphql/server/schema.js index c89d5521ee52..dd1fbb53097f 100644 --- a/packages/rocketchat-graphql/server/schema.js +++ b/packages/rocketchat-graphql/server/schema.js @@ -1,10 +1,8 @@ -/* global processWebhookMessage */ - import { makeExecutableSchema } from 'graphql-tools'; -import { Meteor } from 'meteor/meteor'; +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; import { authenticated } from './mocks/accounts/graphql-api'; @@ -14,69 +12,12 @@ import { property } from './helpers/property'; -import { - findChannelByIdAndUser -} from './helpers/findChannelByIdAndUser'; - - -const schema = ` - type schema { - query: Query - mutation: Mutation - } - - type Query { - channels(filter: ChannelFilter = { - privacy: ALL, - joinedChannels: false, - sortBy: NAME - }): [Channel] - channelByName(name: String!, isDirect: Boolean!): Channel - channelsByUser(userId: String!): [Channel] - messages(channelId: String): MessagesWithCursor - } +import * as channels from './schemas/channels'; +import * as messages from './schemas/messages'; +const rootSchema = ` type Mutation { setStatus(status: UserStatus!): Member - sendMessage(channelId: String!, content: String!): Message - editMessage(id: MessageIdentifier!, content: String!): Message - deleteMessage(id: MessageIdentifier!): Message - createChannel(name: String!, private: Boolean = false, readOnly: Boolean = false, membersId: [String!]): Channel - } - - type Channel { - id: String! - name: String - description: String - announcement: String - topic: String - members: [Member] - owners: [Member] - numberOfMembers: Int - numberOfMessages: Int - readOnly: Boolean - direct: Boolean - privateChannel: Boolean - favourite: Boolean - unseenMessages: Int - } - - enum Privacy { - PRIVATE - PUBLIC - ALL - } - - enum ChannelSort { - NAME - NUMBER_OF_MESSAGES - } - - input ChannelFilter { - nameFilter: String - privacy: Privacy - joinedChannels: Boolean - sortBy: ChannelSort } enum UserStatus { @@ -92,189 +33,10 @@ const schema = ` # TODO: change to UserStatus status: String } - - type MessagesWithCursor { - cursor: String - channel: Channel - messagesArray: [Message] - } - - input MessageIdentifier { - channelId: String! - messageId: String! - } - - type Message { - id: String - author: Member - content: String - channel: Channel - creationTime: String - fromServer: Boolean - userRef: [Member] - channelRef: [Channel] - reactions: [Reaction] - # TODO - tags: [String] - } - - type Reaction { - username: String - icon: String - } `; -const roomPublicFields = { - t: 1, - name: 1, - description: 1, - announcement: 1, - topic: 1, - usernames: 1, - msgs: 1, - ro: 1, - u: 1, - archived: 1 -}; - -const resolvers = { - Query: { - channels: authenticated(AccountsServer, (root, args, { models }) => { - const query = {}; - const options = { - sort: { - name: 1 - }, - fields: roomPublicFields - }; - - // Filter - if (typeof args.filter !== 'undefined') { - // sortBy - if (args.filter.sortBy === 'NUMBER_OF_MESSAGES') { - options.sort = { - msgs: -1 - }; - } - - // privacy - switch (args.filter.privacy) { - case 'PRIVATE': - query.t = 'p'; - break; - case 'PUBLIC': - query.t = { - $ne: 'p' - }; - break; - } - } - - return models.Rooms.find(query, options).fetch(); - }), - channelByName: authenticated(AccountsServer, (root, { name, isDirect }, { models }) => { - const query = { - name - }; - - if (isDirect === true) { - query.c = 'd'; - } - - return models.Rooms.findOne(query, { - fields: roomPublicFields - }); - }), - channelsByUser: authenticated(AccountsServer, (root, { userId }, { models }) => { - const user = models.Users.findOneById(userId); - - if (!user) { - // TODO: - throw new Error('No user'); - } - - return models.Rooms.find({ - 'usernames': { - $in: user.username - } - }, { - sort: { - name: 1 - }, - fields: roomPublicFields - }).fetch(); - }), - messages: authenticated(AccountsServer, (root, args, { models }) => { - if (!args.channelId) { - console.error('messages query must be called with channelId'); - return null; - } - - const query = {}; - - if (args.channelId) { - query.rid = args.channelId; - } - - const messagesArray = models.Messages.find(query).fetch(); - const channel = models.Rooms.findOne(args.channelId); - - return { - cursor: 'CURSOR', - channel, - messagesArray - }; - }) - }, +const rootResolvers = { Mutation: { - sendMessage: authenticated(AccountsServer, (root, { channelId, content }, { user }) => { - const messageReturn = processWebhookMessage({ - roomId: channelId, - text: content - }, user)[0]; - - if (!messageReturn) { - throw new Error('Unknown error'); - } - - return messageReturn.message; - }), - editMessage: authenticated(AccountsServer, (root, { id, content }, { user, models }) => { - const msg = models.Messages.findOneById(id.messageId); - - //Ensure the message exists - if (!msg) { - throw new Error(`No message found with the id of "${ id.messageId }".`); - } - - if (id.channelId !== msg.rid) { - throw new Error('The channel id provided does not match where the message is from.'); - } - - //Permission checks are already done in the updateMessage method, so no need to duplicate them - Meteor.runAsUser(user._id, () => { - Meteor.call('updateMessage', { _id: msg._id, msg: content, rid: msg.rid }); - }); - - return models.Messages.findOneById(msg._id); - }), - deleteMessage: authenticated(AccountsServer, (root, { id }, { models, user }) => { - const msg = models.Messages.findOneById(id.messageId, { fields: { u: 1, rid: 1 }}); - - if (!msg) { - throw new Error(`No message found with the id of "${ id.messageId }".`); - } - - if (id.channelId !== msg.rid) { - throw new Error('The room id provided does not match where the message is from.'); - } - - Meteor.runAsUser(user._id, () => { - Meteor.call('deleteMessage', { _id: msg._id }); - }); - - return msg; - }), setStatus: authenticated(AccountsServer, (root, { status }, { models, user }) => { models.Users.update(user._id, { $set: { @@ -283,144 +45,26 @@ const resolvers = { }); return models.Users.findOne(user._id); - }), - createChannel: authenticated(AccountsServer, (root, args, { models, user }) => { - if (!RocketChat.authz.hasPermission(user._id, 'create-c')) { - return RocketChat.API.v1.unauthorized(); - } - - if (!args.name) { - throw new Error('Param "name" is required'); - } - - if (args.membersId && !_.isArray(args.membersId)) { - throw new Error('Param "membersId" must be an array if provided'); - } - - let readOnly = false; - if (typeof args.readOnly !== 'undefined') { - readOnly = args.readOnly; - } - - let id; - Meteor.runAsUser(user._id, () => { - id = Meteor.call('createChannel', args.name, args.membersId ? args.membersId : [], readOnly); - }); - - return models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude }); }) }, - Channel: { - id: property('_id'), - members: (root, args, { models }) => { - return root.usernames.map( - username => models.Users.findOneByUsername(username) - ); - }, - owners: (root, args, { models }) => { - // there might be no owner - if (!root.u) { - return; - } - - return [models.Users.findOneByUsername(root.u.username)]; - }, - numberOfMembers: (root) => (root.usernames || []).length, - numberOfMessages: property('msgs'), - readOnly: (root) => root.ro === true, - direct: (root) => root.t === 'd', - privateChannel: (root) => root.t === 'p', - favourite: (root, args, { user }) => { - const room = findChannelByIdAndUser({ - params: { - roomId: root._id, - userId: user._id - }, - options: { fields: { f: 1 }} - }); - - return room && room.f === true; - }, - unseenMessages: (root, args, { user }) => { - const room = findChannelByIdAndUser({ - params: { - roomId: root._id, - userId: user._id - }, - options: { fields: { unread: 1 }} - }); - - return (room || {}).unread; - } - }, Member: { id: property('_id'), status: ({status}) => status.toUpperCase() - }, - Message: { - id: property('_id'), - content: property('msg'), - creationTime: property('ts'), - author: (root, args, { models }) => { - return models.Users.findOne(root.u._id); - }, - channel: (root, args, { models }) => { - return models.Rooms.findOne(root.rid); - }, - fromServer: (root) => typeof root.t !== 'undefined', // on a message sent by user `true` otherwise `false` - channelRef: (root, args, { models }) => { - if (!root.channels) { - return; - } - - return models.Rooms.find({ - _id: { - $in: root.channels.map(c => c._id) - } - }, { - sort: { - name: 1 - } - }).fetch(); - }, - userRef: (root, args, { models }) => { - if (!root.mentions) { - return; - } - - return models.Users.find({ - _id: { - $in: root.mentions.map(c => c._id) - } - }, { - sort: { - username: 1 - } - }).fetch(); - }, - reactions: (root) => { - if (!root.reactions || Object.keys(root.reactions).length === 0) { - return; - } - - const reactions = []; - - Object.keys(root.reactions).forEach(icon => { - root.reactions[icon].usernames.forEach(username => { - reactions.push({ - icon, - username - }); - }); - }); - - return reactions; - }, - // TODO - tags: () => {} } }; +const schema = mergeTypes([ + rootSchema, + channels.schema, + messages.schema +]); + +const resolvers = mergeResolvers([ + rootResolvers, + channels.resolvers, + messages.resolvers +]); + export const executableSchema = makeExecutableSchema({ typeDefs: [schema], resolvers, diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js new file mode 100644 index 000000000000..0d6dbac4512f --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js @@ -0,0 +1,67 @@ +import { property } from '../../helpers/property'; +import { findChannelByIdAndUser } from '../../helpers/findChannelByIdAndUser'; + +export const schema = ` + type Channel { + id: String! + name: String + description: String + announcement: String + topic: String + members: [Member] + owners: [Member] + numberOfMembers: Int + numberOfMessages: Int + readOnly: Boolean + direct: Boolean + privateChannel: Boolean + favourite: Boolean + unseenMessages: Int + } +`; + +export const resolver = { + Channel: { + id: property('_id'), + members: (root, args, { models }) => { + return root.usernames.map( + username => models.Users.findOneByUsername(username) + ); + }, + owners: (root, args, { models }) => { + // there might be no owner + if (!root.u) { + return; + } + + return [models.Users.findOneByUsername(root.u.username)]; + }, + numberOfMembers: (root) => (root.usernames || []).length, + numberOfMessages: property('msgs'), + readOnly: (root) => root.ro === true, + direct: (root) => root.t === 'd', + privateChannel: (root) => root.t === 'p', + favourite: (root, args, { user }) => { + const room = findChannelByIdAndUser({ + params: { + roomId: root._id, + userId: user._id + }, + options: { fields: { f: 1 }} + }); + + return room && room.f === true; + }, + unseenMessages: (root, args, { user }) => { + const room = findChannelByIdAndUser({ + params: { + roomId: root._id, + userId: user._id + }, + options: { fields: { unread: 1 }} + }); + + return (room || {}).unread; + } + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.js b/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.js new file mode 100644 index 000000000000..b80d4c680a95 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.js @@ -0,0 +1,8 @@ +export const schema = ` + input ChannelFilter { + nameFilter: String + privacy: Privacy + joinedChannels: Boolean + sortBy: ChannelSort + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.js b/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.js new file mode 100644 index 000000000000..beecdedd89ef --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.js @@ -0,0 +1,6 @@ +export const schema = ` + enum ChannelSort { + NAME + NUMBER_OF_MESSAGES + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.js b/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.js new file mode 100644 index 000000000000..d0cd977a9470 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.js @@ -0,0 +1,7 @@ +export const schema = ` + enum Privacy { + PRIVATE + PUBLIC + ALL + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js new file mode 100644 index 000000000000..9e0f0ca3c39c --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js @@ -0,0 +1,27 @@ +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; +import { roomPublicFields } from './settings'; + +export const schema = ` + type Query { + channelByName(name: String!, isDirect: Boolean!): Channel + } +`; + +export const resolver = { + Query: { + channelByName: authenticated(AccountsServer, (root, { name, isDirect }, { models }) => { + const query = { + name + }; + + if (isDirect === true) { + query.c = 'd'; + } + + return models.Rooms.findOne(query, { + fields: roomPublicFields + }); + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.js b/packages/rocketchat-graphql/server/schemas/channels/channels.js new file mode 100644 index 000000000000..f53979adf037 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/channels.js @@ -0,0 +1,51 @@ +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; +import { roomPublicFields } from './settings'; + +export const schema = ` + type Query { + channels(filter: ChannelFilter = { + privacy: ALL, + joinedChannels: false, + sortBy: NAME + }): [Channel] + } +`; + +export const resolver = { + Query: { + channels: authenticated(AccountsServer, (root, args, { models }) => { + const query = {}; + const options = { + sort: { + name: 1 + }, + fields: roomPublicFields + }; + + // Filter + if (typeof args.filter !== 'undefined') { + // sortBy + if (args.filter.sortBy === 'NUMBER_OF_MESSAGES') { + options.sort = { + msgs: -1 + }; + } + + // privacy + switch (args.filter.privacy) { + case 'PRIVATE': + query.t = 'p'; + break; + case 'PUBLIC': + query.t = { + $ne: 'p' + }; + break; + } + } + + return models.Rooms.find(query, options).fetch(); + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js new file mode 100644 index 000000000000..98a888fe8970 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js @@ -0,0 +1,33 @@ +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; +import { roomPublicFields } from './settings'; + +export const schema = ` + type Query { + channelsByUser(userId: String!): [Channel] + } +`; + +export const resolver = { + Query: { + channelsByUser: authenticated(AccountsServer, (root, { userId }, { models }) => { + const user = models.Users.findOneById(userId); + + if (!user) { + // TODO: + throw new Error('No user'); + } + + return models.Rooms.find({ + 'usernames': { + $in: user.username + } + }, { + sort: { + name: 1 + }, + fields: roomPublicFields + }).fetch(); + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js new file mode 100644 index 000000000000..736afdaf00c0 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js @@ -0,0 +1,41 @@ +import { Meteor } from 'meteor/meteor'; + +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + createChannel(name: String!, private: Boolean = false, readOnly: Boolean = false, membersId: [String!]): Channel + } +`; + +export const resolver = { + Mutation: { + createChannel: authenticated(AccountsServer, (root, args, { models, user }) => { + if (!RocketChat.authz.hasPermission(user._id, 'create-c')) { + return RocketChat.API.v1.unauthorized(); + } + + if (!args.name) { + throw new Error('Param "name" is required'); + } + + if (args.membersId && !_.isArray(args.membersId)) { + throw new Error('Param "membersId" must be an array if provided'); + } + + let readOnly = false; + if (typeof args.readOnly !== 'undefined') { + readOnly = args.readOnly; + } + + let id; + Meteor.runAsUser(user._id, () => { + id = Meteor.call('createChannel', args.name, args.membersId ? args.membersId : [], readOnly); + }); + + return models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude }); + }) + } +}; + diff --git a/packages/rocketchat-graphql/server/schemas/channels/index.js b/packages/rocketchat-graphql/server/schemas/channels/index.js new file mode 100644 index 000000000000..25a1efcb4ebb --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/index.js @@ -0,0 +1,38 @@ +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; + +// queries +import * as channels from './channels'; +import * as channelByName from './channelByName'; +import * as channelsByUser from './channelsByUser'; +// mutations +import * as createChannel from './createChannel'; +// types +import * as channelType from './Channel-type'; +import * as channelSort from './ChannelSort-enum'; +import * as channelFilter from './ChannelFilter-input'; +import * as Privacy from './Privacy-enum'; + +export const schema = mergeTypes([ + // queries + channels.schema, + channelByName.schema, + channelsByUser.schema, + // mutations + createChannel.schema, + // types + channelType.schema, + channelSort.schema, + channelFilter.schema, + Privacy.schema +]); + +export const resolvers = mergeResolvers([ + // queries + channels.resolver, + channelByName.resolver, + channelsByUser.resolver, + // mutations + createChannel.resolver, + // types + channelType.resolver +]); diff --git a/packages/rocketchat-graphql/server/schemas/channels/settings.js b/packages/rocketchat-graphql/server/schemas/channels/settings.js new file mode 100644 index 000000000000..7cace07a7cbc --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/settings.js @@ -0,0 +1,12 @@ +export const roomPublicFields = { + t: 1, + name: 1, + description: 1, + announcement: 1, + topic: 1, + usernames: 1, + msgs: 1, + ro: 1, + u: 1, + archived: 1 +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js new file mode 100644 index 000000000000..9513feb12e10 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js @@ -0,0 +1,82 @@ +import { property } from '../../helpers/property'; + +export const schema = ` + type Message { + id: String + author: Member + content: String + channel: Channel + creationTime: String + fromServer: Boolean + userRef: [Member] + channelRef: [Channel] + reactions: [Reaction] + # TODO + tags: [String] + } +`; + +export const resolver = { + Message: { + id: property('_id'), + content: property('msg'), + creationTime: property('ts'), + author: (root, args, { models }) => { + return models.Users.findOne(root.u._id); + }, + channel: (root, args, { models }) => { + return models.Rooms.findOne(root.rid); + }, + fromServer: (root) => typeof root.t !== 'undefined', // on a message sent by user `true` otherwise `false` + channelRef: (root, args, { models }) => { + if (!root.channels) { + return; + } + + return models.Rooms.find({ + _id: { + $in: root.channels.map(c => c._id) + } + }, { + sort: { + name: 1 + } + }).fetch(); + }, + userRef: (root, args, { models }) => { + if (!root.mentions) { + return; + } + + return models.Users.find({ + _id: { + $in: root.mentions.map(c => c._id) + } + }, { + sort: { + username: 1 + } + }).fetch(); + }, + reactions: (root) => { + if (!root.reactions || Object.keys(root.reactions).length === 0) { + return; + } + + const reactions = []; + + Object.keys(root.reactions).forEach(icon => { + root.reactions[icon].usernames.forEach(username => { + reactions.push({ + icon, + username + }); + }); + }); + + return reactions; + }, + // TODO + tags: () => {} + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.js b/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.js new file mode 100644 index 000000000000..bb8571477bfe --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.js @@ -0,0 +1,6 @@ +export const schema = ` + input MessageIdentifier { + channelId: String! + messageId: String! + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.js b/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.js new file mode 100644 index 000000000000..b70b287321b8 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.js @@ -0,0 +1,7 @@ +export const schema = ` + type MessagesWithCursor { + cursor: String + channel: Channel + messagesArray: [Message] + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.js b/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.js new file mode 100644 index 000000000000..c337f52ce6bf --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.js @@ -0,0 +1,6 @@ +export const schema = ` + type Reaction { + username: String + icon: String + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js new file mode 100644 index 000000000000..0b941817a8dd --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js @@ -0,0 +1,32 @@ +import { Meteor } from 'meteor/meteor'; + +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + deleteMessage(id: MessageIdentifier!): Message + } +`; + +export const resolver = { + Mutation: { + deleteMessage: authenticated(AccountsServer, (root, { id }, { models, user }) => { + const msg = models.Messages.findOneById(id.messageId, { fields: { u: 1, rid: 1 }}); + + if (!msg) { + throw new Error(`No message found with the id of "${ id.messageId }".`); + } + + if (id.channelId !== msg.rid) { + throw new Error('The room id provided does not match where the message is from.'); + } + + Meteor.runAsUser(user._id, () => { + Meteor.call('deleteMessage', { _id: msg._id }); + }); + + return msg; + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js b/packages/rocketchat-graphql/server/schemas/messages/editMessage.js new file mode 100644 index 000000000000..6eacb619f51d --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/editMessage.js @@ -0,0 +1,34 @@ +import { Meteor } from 'meteor/meteor'; + +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + editMessage(id: MessageIdentifier!, content: String!): Message + } +`; + +export const resolver = { + Mutation: { + editMessage: authenticated(AccountsServer, (root, { id, content }, { user, models }) => { + const msg = models.Messages.findOneById(id.messageId); + + //Ensure the message exists + if (!msg) { + throw new Error(`No message found with the id of "${ id.messageId }".`); + } + + if (id.channelId !== msg.rid) { + throw new Error('The channel id provided does not match where the message is from.'); + } + + //Permission checks are already done in the updateMessage method, so no need to duplicate them + Meteor.runAsUser(user._id, () => { + Meteor.call('updateMessage', { _id: msg._id, msg: content, rid: msg.rid }); + }); + + return models.Messages.findOneById(msg._id); + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/index.js b/packages/rocketchat-graphql/server/schemas/messages/index.js new file mode 100644 index 000000000000..438930fe8698 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/index.js @@ -0,0 +1,38 @@ +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; + +// queries +import * as messages from './messages'; +// mutations +import * as sendMessage from './sendMessage'; +import * as editMessage from './editMessage'; +import * as deleteMessage from './deleteMessage'; +// types +import * as MessageType from './Message-type'; +import * as MessagesWithCursorType from './MessagesWithCursor-type'; +import * as MessageIdentifier from './MessageIdentifier-input'; +import * as ReactionType from './Reaction-type'; + +export const schema = mergeTypes([ + // queries + messages.schema, + // mutations + sendMessage.schema, + editMessage.schema, + deleteMessage.schema, + // types + MessageType.schema, + MessagesWithCursorType.schema, + MessageIdentifier.schema, + ReactionType.schema +]); + +export const resolvers = mergeResolvers([ + // queries + messages.resolver, + // mutations + sendMessage.resolver, + editMessage.resolver, + deleteMessage.resolver, + // types + MessageType.resolver +]); diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.js b/packages/rocketchat-graphql/server/schemas/messages/messages.js new file mode 100644 index 000000000000..84d0509f0fdc --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.js @@ -0,0 +1,34 @@ +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Query { + messages(channelId: String): MessagesWithCursor + } +`; + +export const resolver = { + Query: { + messages: authenticated(AccountsServer, (root, args, { models }) => { + if (!args.channelId) { + console.error('messages query must be called with channelId'); + return null; + } + + const query = {}; + + if (args.channelId) { + query.rid = args.channelId; + } + + const messagesArray = models.Messages.find(query).fetch(); + const channel = models.Rooms.findOne(args.channelId); + + return { + cursor: 'CURSOR', + channel, + messagesArray + }; + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js new file mode 100644 index 000000000000..ed675ce002d8 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js @@ -0,0 +1,27 @@ +/* global processWebhookMessage */ + +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + sendMessage(channelId: String!, content: String!): Message + } +`; + +export const resolver = { + Mutation: { + sendMessage: authenticated(AccountsServer, (root, { channelId, content }, { user }) => { + const messageReturn = processWebhookMessage({ + roomId: channelId, + text: content + }, user)[0]; + + if (!messageReturn) { + throw new Error('Unknown error'); + } + + return messageReturn.message; + }) + } +}; From 373e8e56afcc51d41a1c94ee4c752e01c55f1d13 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Sat, 1 Jul 2017 15:20:05 +0100 Subject: [PATCH 074/801] Support nameFilter in channels query --- .../rocketchat-graphql/server/schemas/channels/channels.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.js b/packages/rocketchat-graphql/server/schemas/channels/channels.js index f53979adf037..4fa4dbfe224a 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channels.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channels.js @@ -25,6 +25,13 @@ export const resolver = { // Filter if (typeof args.filter !== 'undefined') { + // nameFilter + if (typeof args.filter.nameFilter !== undefined) { + query.name = { + $regex: new RegExp(args.filter.nameFilter, 'i') + }; + } + // sortBy if (args.filter.sortBy === 'NUMBER_OF_MESSAGES') { options.sort = { From 858a9c09ea33189d07b0efcc144ae22f187f8ee5 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Wed, 19 Jul 2017 17:03:30 +0100 Subject: [PATCH 075/801] WIP --- .meteor/packages | 1 + .meteor/versions | 1 + .../.npm/package/.gitignore | 1 + .../rocketchat-accounts/.npm/package/README | 7 + .../.npm/package/npm-shrinkwrap.json | 236 ++++++++++++++++++ packages/rocketchat-accounts/package.js | 23 ++ packages/rocketchat-accounts/server/config.js | 21 ++ packages/rocketchat-accounts/server/index.js | 7 + .../.npm/package/npm-shrinkwrap.json | 175 ++++++++++++- packages/rocketchat-graphql/package.js | 18 +- packages/rocketchat-graphql/server/api.js | 21 +- .../server/mocks/accounts/server.js | 2 +- packages/rocketchat-graphql/server/schema.js | 58 +---- .../schemas/accounts/LoginResult-type.js | 6 + .../server/schemas/accounts/index.js | 8 + .../accounts/loginWithServiceAccessToken.js | 32 +++ .../server/schemas/channels/Channel-type.js | 4 +- .../channels/ChannelNameAndDirect-input.js | 6 + .../server/schemas/channels/channels.js | 3 + .../server/schemas/channels/createChannel.js | 7 +- .../server/schemas/channels/hideChannel.js | 41 +++ .../server/schemas/channels/index.js | 24 +- .../server/schemas/channels/leaveChannel.js | 31 +++ .../server/schemas/messages/Message-type.js | 4 +- .../schemas/messages/addReactionToMessage.js | 24 ++ .../schemas/messages/chatMessageAdded.js | 29 +++ .../server/schemas/messages/index.js | 9 + .../server/schemas/messages/messages.js | 68 ++++- .../server/schemas/users/User-type.js | 36 +++ .../server/schemas/users/UserStatus-enum.js | 9 + .../server/schemas/users/index.js | 22 ++ .../server/schemas/users/setStatus.js | 22 ++ .../server/subscriptions.js | 3 + packages/rocketchat-lib/package.js | 1 + 34 files changed, 866 insertions(+), 94 deletions(-) create mode 100644 packages/rocketchat-accounts/.npm/package/.gitignore create mode 100644 packages/rocketchat-accounts/.npm/package/README create mode 100644 packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json create mode 100644 packages/rocketchat-accounts/package.js create mode 100644 packages/rocketchat-accounts/server/config.js create mode 100644 packages/rocketchat-accounts/server/index.js create mode 100644 packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/accounts/index.js create mode 100644 packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/hideChannel.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.js create mode 100644 packages/rocketchat-graphql/server/schemas/users/User-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.js create mode 100644 packages/rocketchat-graphql/server/schemas/users/index.js create mode 100644 packages/rocketchat-graphql/server/schemas/users/setStatus.js create mode 100644 packages/rocketchat-graphql/server/subscriptions.js diff --git a/.meteor/packages b/.meteor/packages index 53fb9389b819..c2f5c2bc98e6 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -38,6 +38,7 @@ tracker@1.1.3 rocketchat:2fa rocketchat:action-links +rocketchat:accounts rocketchat:analytics rocketchat:api rocketchat:assets diff --git a/.meteor/versions b/.meteor/versions index 5ceb7cee121a..253d100b0338 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -123,6 +123,7 @@ reactive-var@1.0.11 reload@1.1.11 retry@1.0.9 rocketchat:2fa@0.0.1 +rocketchat:accounts@0.0.1 rocketchat:action-links@0.0.1 rocketchat:analytics@0.0.2 rocketchat:api@0.0.1 diff --git a/packages/rocketchat-accounts/.npm/package/.gitignore b/packages/rocketchat-accounts/.npm/package/.gitignore new file mode 100644 index 000000000000..3c3629e647f5 --- /dev/null +++ b/packages/rocketchat-accounts/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/rocketchat-accounts/.npm/package/README b/packages/rocketchat-accounts/.npm/package/README new file mode 100644 index 000000000000..3d492553a438 --- /dev/null +++ b/packages/rocketchat-accounts/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json new file mode 100644 index 000000000000..0ff3f7f21819 --- /dev/null +++ b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,236 @@ +{ + "dependencies": { + "addressparser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.3.2.tgz", + "from": "addressparser@>=0.3.2 <0.4.0" + }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "from": "babel-polyfill@>=6.23.0 <7.0.0" + }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "from": "babel-runtime@>=6.22.0 <7.0.0" + }, + "base64url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", + "from": "base64url@>=2.0.0 <3.0.0" + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "from": "bcryptjs@>=2.4.0 <3.0.0" + }, + "bson": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.4.tgz", + "from": "bson@>=1.0.4 <1.1.0" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "from": "buffer-equal-constant-time@1.0.1" + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "from": "buffer-shims@>=1.0.0 <1.1.0" + }, + "bufferjs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bufferjs/-/bufferjs-1.1.0.tgz", + "from": "bufferjs@1.1.0" + }, + "core-js": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "from": "core-js@>=2.4.0 <3.0.0" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "from": "core-util-is@>=1.0.0 <1.1.0" + }, + "crypto": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-0.0.3.tgz", + "from": "crypto@>=0.0.3 <0.0.4" + }, + "ecdsa-sig-formatter": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", + "from": "ecdsa-sig-formatter@1.0.9" + }, + "emailjs": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/emailjs/-/emailjs-1.0.11.tgz", + "from": "emailjs@>=1.0.8 <2.0.0" + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "from": "encoding@>=0.1.0 <0.2.0" + }, + "es6-promise": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", + "from": "es6-promise@3.2.1" + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "from": "hoek@>=2.0.0 <3.0.0" + }, + "iconv-lite": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", + "from": "iconv-lite@>=0.4.13 <0.5.0" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "from": "inherits@>=2.0.1 <2.1.0" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "from": "isarray@>=1.0.0 <1.1.0" + }, + "isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "from": "isemail@>=1.0.0 <2.0.0" + }, + "joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "from": "joi@>=6.10.1 <7.0.0" + }, + "jsonwebtoken": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz", + "from": "jsonwebtoken@>=7.2.1 <8.0.0" + }, + "jwa": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", + "from": "jwa@>=1.1.4 <2.0.0" + }, + "jws": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", + "from": "jws@>=3.1.4 <4.0.0" + }, + "jwt-decode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", + "from": "jwt-decode@>=2.1.0 <3.0.0" + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "from": "lodash@>=4.16.4 <5.0.0" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "from": "lodash.once@>=4.0.0 <5.0.0" + }, + "mimelib": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/mimelib/-/mimelib-0.2.14.tgz", + "from": "mimelib@0.2.14", + "dependencies": { + "addressparser": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.2.1.tgz", + "from": "addressparser@>=0.2.0 <0.3.0" + } + } + }, + "moment": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.11.2.tgz", + "from": "moment@2.11.2" + }, + "mongodb": { + "version": "2.2.30", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.30.tgz", + "from": "mongodb@>=2.2.22 <3.0.0" + }, + "mongodb-core": { + "version": "2.1.14", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.14.tgz", + "from": "mongodb-core@2.1.14" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "from": "ms@>=2.0.0 <3.0.0" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "from": "process-nextick-args@>=1.0.6 <1.1.0" + }, + "readable-stream": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", + "from": "readable-stream@2.2.7" + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "from": "regenerator-runtime@>=0.10.0 <0.11.0" + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "from": "require_optional@>=1.0.0 <1.1.0" + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "from": "resolve-from@>=2.0.0 <3.0.0" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "from": "safe-buffer@>=5.0.1 <6.0.0" + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "from": "semver@>=5.1.0 <6.0.0" + }, + "starttls": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/starttls/-/starttls-1.0.1.tgz", + "from": "starttls@1.0.1" + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "from": "string_decoder@>=1.0.0 <1.1.0" + }, + "topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "from": "topo@>=1.0.0 <2.0.0" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "from": "util-deprecate@>=1.0.1 <1.1.0" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "from": "xtend@>=4.0.1 <5.0.0" + } + } +} diff --git a/packages/rocketchat-accounts/package.js b/packages/rocketchat-accounts/package.js new file mode 100644 index 000000000000..ad3d2abb5687 --- /dev/null +++ b/packages/rocketchat-accounts/package.js @@ -0,0 +1,23 @@ +Package.describe({ + name: 'rocketchat:accounts', + version: '0.0.1', + summary: 'JS-Accounts integration', + git: '' +}); + +Package.onUse(function(api) { + api.use([ + 'underscore', + 'ecmascript' + ]); + + api.use('mongo', ['client', 'server']); + + api.mainModule('server/index.js', 'server'); +}); + +Npm.depends({ + '@accounts/server': '0.0.17', + '@accounts/mongo': '0.0.12-0', + '@accounts/meteor-adapter': '0.1.1' +}); diff --git a/packages/rocketchat-accounts/server/config.js b/packages/rocketchat-accounts/server/config.js new file mode 100644 index 000000000000..a9c215fdbd77 --- /dev/null +++ b/packages/rocketchat-accounts/server/config.js @@ -0,0 +1,21 @@ +import AccountsServer from '@accounts/server'; +import MongoAdapter from '@accounts/mongo'; +import { MongoInternals } from 'meteor/mongo'; +import { Meteor } from 'meteor/meteor'; + +Meteor.startup(() => { + const mongodb = MongoInternals.defaultRemoteCollectionDriver().mongo.db; + + const mongoAdapter = new MongoAdapter(mongodb); + + AccountsServer.config({ + tokenConfigs: { + accessToken: { + expiresIn: '3d' + }, + refreshToken: { + expiresIn: '30d' + } + } + }, mongoAdapter); +}); diff --git a/packages/rocketchat-accounts/server/index.js b/packages/rocketchat-accounts/server/index.js new file mode 100644 index 000000000000..7e25e6061c78 --- /dev/null +++ b/packages/rocketchat-accounts/server/index.js @@ -0,0 +1,7 @@ +import './config'; + +import AccountsServer from '@accounts/server'; + +export { + AccountsServer +}; diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json index 1c663c3f6914..9d5e2541f031 100644 --- a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -15,11 +15,36 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "from": "array-flatten@1.1.1" }, + "babel-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "from": "babel-runtime@>=6.23.0 <7.0.0" + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "from": "backo2@>=1.0.2 <2.0.0" + }, + "base64url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", + "from": "base64url@>=2.0.0 <3.0.0" + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "from": "bcryptjs@>=2.4.0 <3.0.0" + }, "body-parser": { "version": "1.17.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", "from": "body-parser@1.17.2" }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "from": "buffer-equal-constant-time@1.0.1" + }, "bytes": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", @@ -45,19 +70,29 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "from": "cookie-signature@1.0.6" }, + "core-js": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "from": "core-js@>=2.4.0 <3.0.0" + }, "cors": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.3.tgz", "from": "cors@2.8.3" }, + "crypto": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-0.0.3.tgz", + "from": "crypto@>=0.0.3 <0.0.4" + }, "debug": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", "from": "debug@2.6.7" }, "deepmerge": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.4.4.tgz", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.0.tgz", "from": "deepmerge@>=1.3.2 <2.0.0" }, "depd": { @@ -75,6 +110,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "from": "destroy@>=1.0.4 <1.1.0" }, + "ecdsa-sig-formatter": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", + "from": "ecdsa-sig-formatter@1.0.9" + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -85,6 +125,11 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", "from": "encodeurl@>=1.0.1 <1.1.0" }, + "es6-promise": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", + "from": "es6-promise@>=4.0.5 <5.0.0" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -95,6 +140,11 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", "from": "etag@>=1.8.0 <1.9.0" }, + "eventemitter3": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", + "from": "eventemitter3@>=2.0.3 <3.0.0" + }, "express": { "version": "4.15.3", "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", @@ -140,6 +190,11 @@ "resolved": "https://registry.npmjs.org/graphql-server-module-graphiql/-/graphql-server-module-graphiql-0.9.0.tgz", "from": "graphql-server-module-graphiql@>=0.9.0 <0.10.0" }, + "graphql-subscriptions": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-0.4.4.tgz", + "from": "graphql-subscriptions@0.4.4" + }, "graphql-tag": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.4.2.tgz", @@ -150,6 +205,11 @@ "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.1.0.tgz", "from": "graphql-tools@1.1.0" }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "from": "hoek@>=2.0.0 <3.0.0" + }, "http-errors": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", @@ -170,26 +230,76 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", "from": "ipaddr.js@1.3.0" }, + "isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "from": "isemail@>=1.0.0 <2.0.0" + }, "iterall": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.1.tgz", "from": "iterall@>=1.1.0 <2.0.0" }, + "joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "from": "joi@>=6.10.1 <7.0.0" + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", "from": "js-tokens@>=3.0.0 <4.0.0" }, + "jsonwebtoken": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz", + "from": "jsonwebtoken@>=7.2.1 <8.0.0" + }, + "jwa": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", + "from": "jwa@>=1.1.4 <2.0.0" + }, + "jws": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", + "from": "jws@>=3.1.4 <4.0.0" + }, + "jwt-decode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", + "from": "jwt-decode@>=2.1.0 <3.0.0" + }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "from": "lodash@>=4.2.1 <5.0.0" + "from": "lodash@>=4.16.4 <5.0.0" }, "lodash-es": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", "from": "lodash-es@>=4.2.1 <5.0.0" }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "from": "lodash.assign@>=4.2.0 <5.0.0" + }, + "lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "from": "lodash.isobject@>=3.0.2 <4.0.0" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "from": "lodash.isstring@>=4.0.1 <5.0.0" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "from": "lodash.once@>=4.0.0 <5.0.0" + }, "loose-envify": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", @@ -228,12 +338,17 @@ "mime-types": { "version": "2.1.15", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", - "from": "mime-types@>=2.1.11 <2.2.0" + "from": "mime-types@>=2.1.15 <2.2.0" + }, + "moment": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", + "from": "moment@>=2.0.0 <3.0.0" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "from": "ms@2.0.0" + "from": "ms@>=2.0.0 <3.0.0" }, "negotiator": { "version": "0.6.1", @@ -281,10 +396,20 @@ "from": "raw-body@>=2.2.0 <2.3.0" }, "redux": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.1.tgz", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", "from": "redux@>=3.4.0 <4.0.0" }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "from": "regenerator-runtime@>=0.10.0 <0.11.0" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "from": "safe-buffer@>=5.0.1 <6.0.0" + }, "send": { "version": "0.15.3", "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", @@ -303,22 +428,37 @@ "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "from": "statuses@>=1.3.1 <1.4.0" + "from": "statuses@>=1.3.1 <2.0.0" + }, + "subscriptions-transport-ws": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.8.1.tgz", + "from": "subscriptions-transport-ws@0.8.1" }, "symbol-observable": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", "from": "symbol-observable@>=1.0.2 <2.0.0" }, + "topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "from": "topo@>=1.0.0 <2.0.0" + }, "type-is": { "version": "1.6.15", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", "from": "type-is@>=1.6.15 <1.7.0" }, + "ultron": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz", + "from": "ultron@>=1.1.0 <1.2.0" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "from": "unpipe@>=1.0.0 <1.1.0" + "from": "unpipe@1.0.0" }, "utils-merge": { "version": "1.0.0", @@ -339,6 +479,23 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", "from": "whatwg-fetch@>=2.0.0 <3.0.0" + }, + "ws": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.0.0.tgz", + "from": "ws@>=3.0.0 <4.0.0", + "dependencies": { + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "from": "safe-buffer@>=5.0.1 <5.1.0" + } + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "from": "xtend@>=4.0.1 <5.0.0" } } } diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js index 3c29cdb70911..24f1b58779af 100644 --- a/packages/rocketchat-graphql/package.js +++ b/packages/rocketchat-graphql/package.js @@ -10,19 +10,23 @@ Package.onUse(function(api) { 'underscore', 'ecmascript', 'rocketchat:lib', - 'rocketchat:api' + 'rocketchat:api', + 'rocketchat:accounts' ]); - api.addFiles('server/api.js', 'server'); + api.mainModule('server/api.js', 'server'); }); Npm.depends({ + '@accounts/graphql-api': '0.1.1', 'apollo-client': '1.6.0', - cors: '2.8.3', - express: '4.15.3', - graphql: '0.10.3', + 'cors': '2.8.3', + 'body-parser': '1.17.2', + 'express': '4.15.3', + 'graphql': '0.10.3', 'graphql-server-express': '0.9.0', + 'graphql-subscriptions': '0.4.4', 'graphql-tools': '1.1.0', - 'body-parser': '1.17.2', - 'merge-graphql-schemas': '1.1.0' + 'merge-graphql-schemas': '1.1.0', + 'subscriptions-transport-ws': '0.8.1' }); diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index 040845247a44..069ada537a9b 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -1,4 +1,7 @@ import { graphqlExpress, graphiqlExpress } from 'graphql-server-express'; +import { JSAccountsContext as jsAccountsContext } from '@accounts/graphql-api'; +import { SubscriptionServer } from 'subscriptions-transport-ws'; +import { execute, subscribe } from 'graphql'; import bodyParser from 'body-parser'; import express from 'express'; import cors from 'cors'; @@ -16,11 +19,11 @@ graphQLServer.use(bodyParser.urlencoded({ extended: true })); graphQLServer.use( '/graphql', bodyParser.json(), - graphqlExpress(() => ({ + graphqlExpress(request => ({ schema: executableSchema, - context: { + context: Object.assign({ models: RocketChat.models - }, + }, jsAccountsContext(request)), formatError: e => ({ message: e.message, locations: e.locations, @@ -30,9 +33,19 @@ graphQLServer.use( }))); graphQLServer.use('/graphiql', graphiqlExpress({ - endpointURL: '/graphql' + endpointURL: '/graphql', + subscriptionsEndpoint: 'ws://localhost:3000/subscriptions' })); +new SubscriptionServer({ + schema: executableSchema, + execute, + subscribe +}, +{ + path: '/subscriptions', + server: WebApp.httpServer +}); // this binds the specified paths to the Express server running Apollo + GraphiQL WebApp.connectHandlers.use(graphQLServer); diff --git a/packages/rocketchat-graphql/server/mocks/accounts/server.js b/packages/rocketchat-graphql/server/mocks/accounts/server.js index 2d472b58e125..d44d2d09efae 100644 --- a/packages/rocketchat-graphql/server/mocks/accounts/server.js +++ b/packages/rocketchat-graphql/server/mocks/accounts/server.js @@ -7,7 +7,7 @@ const AccountsServer = { } // User credentials // mys:admin - return RocketChat.models.Users.findOneById('fnw4B4suFsTXf8rZq'); + return RocketChat.models.Users.findOne({username: 'mys'}); } }; diff --git a/packages/rocketchat-graphql/server/schema.js b/packages/rocketchat-graphql/server/schema.js index dd1fbb53097f..3ee5b41532fa 100644 --- a/packages/rocketchat-graphql/server/schema.js +++ b/packages/rocketchat-graphql/server/schema.js @@ -4,65 +4,23 @@ import { import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; -import { authenticated } from './mocks/accounts/graphql-api'; - -import AccountsServer from './mocks/accounts/server'; - -import { - property -} from './helpers/property'; - import * as channels from './schemas/channels'; import * as messages from './schemas/messages'; - -const rootSchema = ` - type Mutation { - setStatus(status: UserStatus!): Member - } - - enum UserStatus { - ONLINE - AWAY - BUSY - INVISIBLE - } - - type Member { - id: String! - name: String - # TODO: change to UserStatus - status: String - } -`; - -const rootResolvers = { - Mutation: { - setStatus: authenticated(AccountsServer, (root, { status }, { models, user }) => { - models.Users.update(user._id, { - $set: { - status: status.toLowerCase() - } - }); - - return models.Users.findOne(user._id); - }) - }, - Member: { - id: property('_id'), - status: ({status}) => status.toUpperCase() - } -}; +import * as accounts from './schemas/accounts'; +import * as users from './schemas/users'; const schema = mergeTypes([ - rootSchema, channels.schema, - messages.schema + messages.schema, + accounts.schema, + users.schema ]); const resolvers = mergeResolvers([ - rootResolvers, channels.resolvers, - messages.resolvers + messages.resolvers, + accounts.resolvers, + users.resolvers ]); export const executableSchema = makeExecutableSchema({ diff --git a/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.js b/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.js new file mode 100644 index 000000000000..4a0a7c8397b4 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.js @@ -0,0 +1,6 @@ +export const schema = ` + type LoginResult { + accessToken: String! + refreshToken: String! + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/accounts/index.js b/packages/rocketchat-graphql/server/schemas/accounts/index.js new file mode 100644 index 000000000000..cf41ed398f04 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/accounts/index.js @@ -0,0 +1,8 @@ +import { createJSAccountsGraphQL } from '@accounts/graphql-api'; +import { AccountsServer } from 'meteor/rocketchat:accounts'; + +const accountsGraphQL = createJSAccountsGraphQL(AccountsServer); + +export const schema = accountsGraphQL.schema; + +export const resolvers = accountsGraphQL.extendWithResolvers({}); diff --git a/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js b/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js new file mode 100644 index 000000000000..26d95f49c0cf --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js @@ -0,0 +1,32 @@ +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + loginWithServiceAccessToken(service: String!, accessToken: String!): LoginResult + } +`; + +export const resolver = { + Mutation: { + loginWithServiceAccessToken: async(root, { service, accessToken }) => { + try { + const userData = await oauthResolver.getUserDataFromService(accessToken, service); + const accountsServer = AccountsServer; + const user = await oauthResolver.getUserFromServiceUserData(service, userData); + + if (!user) { + return null; + } + + const loginResult = await accountsServer.loginWithUser(user); + + return { + refreshToken: loginResult.tokens.refreshToken, + accessToken: loginResult.tokens.accessToken + }; + } catch (e) { + console.error('Failed to login with service', e); + } + } + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js index 0d6dbac4512f..9d394c536aae 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js +++ b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js @@ -8,8 +8,8 @@ export const schema = ` description: String announcement: String topic: String - members: [Member] - owners: [Member] + members: [User] + owners: [User] numberOfMembers: Int numberOfMessages: Int readOnly: Boolean diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.js b/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.js new file mode 100644 index 000000000000..f3bbda3125d1 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.js @@ -0,0 +1,6 @@ +export const schema = ` + input ChannelNameAndDirect { + name: String! + direct: Boolean! + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.js b/packages/rocketchat-graphql/server/schemas/channels/channels.js index 4fa4dbfe224a..61a8535da41d 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channels.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channels.js @@ -50,6 +50,9 @@ export const resolver = { }; break; } + + // joinedChannels + // TODO: } return models.Rooms.find(query, options).fetch(); diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js index 736afdaf00c0..e7fe0ce09a16 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js @@ -5,7 +5,12 @@ import AccountsServer from '../../mocks/accounts/server'; export const schema = ` type Mutation { - createChannel(name: String!, private: Boolean = false, readOnly: Boolean = false, membersId: [String!]): Channel + createChannel( + name: String!, + private: Boolean = false, + readOnly: Boolean = false, + membersId: [String!] + ): Channel } `; diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js new file mode 100644 index 000000000000..95a8e0f0486f --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js @@ -0,0 +1,41 @@ +import { Meteor } from 'meteor/meteor'; + +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + hideChannel(channelId: String!): Boolean + } +`; + +export const resolver = { + Mutation: { + hideChannel: authenticated(AccountsServer, (root, args, { models, user }) => { + const channel = models.Rooms.findOne({ + _id: args.channelId, + t: 'c' + }); + + if (!channel) { + throw new Error('error-room-not-found', 'The required "channelId" param provided does not match any channel'); + } + + const sub = models.Subscriptions.findOneByRoomIdAndUserId(channel._id, user._id); + + if (!sub) { + throw new Error(`The user/callee is not in the channel "${ channel.name }.`); + } + + if (!sub.open) { + throw new Error(`The channel, ${ channel.name }, is already closed to the sender`); + } + + Meteor.runAsUser(this.userId, () => { + Meteor.call('hideRoom', channel._id); + }); + + return true; + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/index.js b/packages/rocketchat-graphql/server/schemas/channels/index.js index 25a1efcb4ebb..aa340a0030c5 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/index.js +++ b/packages/rocketchat-graphql/server/schemas/channels/index.js @@ -6,11 +6,14 @@ import * as channelByName from './channelByName'; import * as channelsByUser from './channelsByUser'; // mutations import * as createChannel from './createChannel'; +import * as leaveChannel from './leaveChannel'; +import * as hideChannel from './hideChannel'; // types -import * as channelType from './Channel-type'; -import * as channelSort from './ChannelSort-enum'; -import * as channelFilter from './ChannelFilter-input'; +import * as ChannelType from './Channel-type'; +import * as ChannelSort from './ChannelSort-enum'; +import * as ChannelFilter from './ChannelFilter-input'; import * as Privacy from './Privacy-enum'; +import * as ChannelNameAndDirect from './ChannelNameAndDirect-input'; export const schema = mergeTypes([ // queries @@ -19,11 +22,14 @@ export const schema = mergeTypes([ channelsByUser.schema, // mutations createChannel.schema, + leaveChannel.schema, + hideChannel.schema, // types - channelType.schema, - channelSort.schema, - channelFilter.schema, - Privacy.schema + ChannelType.schema, + ChannelSort.schema, + ChannelFilter.schema, + Privacy.schema, + ChannelNameAndDirect.schema ]); export const resolvers = mergeResolvers([ @@ -33,6 +39,8 @@ export const resolvers = mergeResolvers([ channelsByUser.resolver, // mutations createChannel.resolver, + leaveChannel.resolver, + hideChannel.resolver, // types - channelType.resolver + ChannelType.resolver ]); diff --git a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js new file mode 100644 index 000000000000..d20c6042b0e9 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js @@ -0,0 +1,31 @@ +import { Meteor } from 'meteor/meteor'; + +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + leaveChannel(channelId: String!): Boolean + } +`; + +export const resolver = { + Mutation: { + leaveChannel: authenticated(AccountsServer, (root, args, { models, user }) => { + const channel = models.Rooms.findOne({ + _id: args.channelId, + t: 'c' + }); + + if (!channel) { + throw new Error('error-room-not-found', 'The required "channelId" param provided does not match any channel'); + } + + Meteor.runAsUser(user._id, () => { + Meteor.call('leaveRoom', channel._id); + }); + + return true; + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js index 9513feb12e10..3c6a1f0b34be 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js @@ -3,12 +3,12 @@ import { property } from '../../helpers/property'; export const schema = ` type Message { id: String - author: Member + author: User content: String channel: Channel creationTime: String fromServer: Boolean - userRef: [Member] + userRef: [User] channelRef: [Channel] reactions: [Reaction] # TODO diff --git a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js new file mode 100644 index 000000000000..89d020ea82b1 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js @@ -0,0 +1,24 @@ +import { Meteor } from 'meteor/meteor'; + +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + addReactionToMassage(id: MessageIdentifier!, icon: String!): Message + } +`; + +export const resolver = { + Mutation: { + addReactionToMassage: authenticated(AccountsServer, (root, { id, icon }, { models, user }) => { + return new Promise((resolve) => { + Meteor.runAsUser(user._id, () => { + Meteor.call('setReaction', id.messageId, icon, () => { + resolve(models.findOne(id.messageId)); + }); + }); + }); + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.js b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.js new file mode 100644 index 000000000000..0f127c3c934f --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.js @@ -0,0 +1,29 @@ +import { withFilter } from 'graphql-subscriptions'; + +import { pubsub } from '../../subscriptions'; + +export const CHAT_MESSAGE_SUBSCRIPTION_TOPIC = 'CHAT_MESSAGE_ADDED'; + +export function publishMessage(message) { + pubsub.publish(CHAT_MESSAGE_SUBSCRIPTION_TOPIC, { chatMessageAdded: message }); +} + +export const schema = ` + type Subscription { + chatMessageAdded(channelId: String!): Message + } +`; + +export const resolver = { + Subscription: { + chatMessageAdded: { + subscribe: withFilter(() => pubsub.asyncIterator(CHAT_MESSAGE_SUBSCRIPTION_TOPIC), (payload, args) => { + return payload.chatMessageAdded.rid === args.channelId; + }) + } + } +}; + +RocketChat.callbacks.add('afterSaveMessage', (message) => { + publishMessage(message); +}, null, 'chatMessageAddedSubscription'); diff --git a/packages/rocketchat-graphql/server/schemas/messages/index.js b/packages/rocketchat-graphql/server/schemas/messages/index.js index 438930fe8698..fb9728b19815 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/index.js +++ b/packages/rocketchat-graphql/server/schemas/messages/index.js @@ -6,6 +6,9 @@ import * as messages from './messages'; import * as sendMessage from './sendMessage'; import * as editMessage from './editMessage'; import * as deleteMessage from './deleteMessage'; +import * as addReactionToMessage from './addReactionToMessage'; +// subscriptions +import * as chatMessageAdded from './chatMessageAdded'; // types import * as MessageType from './Message-type'; import * as MessagesWithCursorType from './MessagesWithCursor-type'; @@ -19,6 +22,9 @@ export const schema = mergeTypes([ sendMessage.schema, editMessage.schema, deleteMessage.schema, + addReactionToMessage.schema, + // subscriptions + chatMessageAdded.schema, // types MessageType.schema, MessagesWithCursorType.schema, @@ -33,6 +39,9 @@ export const resolvers = mergeResolvers([ sendMessage.resolver, editMessage.resolver, deleteMessage.resolver, + addReactionToMessage.resolver, + // subscriptions + chatMessageAdded.resolver, // types MessageType.resolver ]); diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.js b/packages/rocketchat-graphql/server/schemas/messages/messages.js index 84d0509f0fdc..a55aa09981b0 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/messages.js +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.js @@ -3,29 +3,77 @@ import AccountsServer from '../../mocks/accounts/server'; export const schema = ` type Query { - messages(channelId: String): MessagesWithCursor + messages( + channelId: String, + channelDetails: ChannelNameAndDirect, + channelName: String, + cursor: String, + count: Int, + searchRegex: String + ): MessagesWithCursor } `; export const resolver = { Query: { messages: authenticated(AccountsServer, (root, args, { models }) => { - if (!args.channelId) { - console.error('messages query must be called with channelId'); + const messagesQuery = {}; + const messagesOptions = { + sort: { ts: 1 } + }; + const channelQuery = {}; + const isPagination = !!args.cursor || args.count > 0; + let cursor; + + if (args.channelId) { + // channelId + channelQuery._id = args.channelId; + } else if (args.channelDetails) { + // channelDetails + channelQuery.name = args.channelDetails.name; + channelQuery.t = args.channelDetails.direct === true ? 'd' : { $ne: 'd' }; + } else { + console.error('messages query must be called with channelId or channelDetails'); return null; } - const query = {}; + const channel = models.Rooms.findOne(channelQuery); + let messagesArray = []; - if (args.channelId) { - query.rid = args.channelId; - } + if (channel) { + + // cursor + if (isPagination && args.cursor) { + const cursorMsg = models.Messages.findOne(args.cursor, { fields: { ts: 1 } }); + messagesQuery.ts = { $gt: cursorMsg.ts }; + } - const messagesArray = models.Messages.find(query).fetch(); - const channel = models.Rooms.findOne(args.channelId); + // searchRegex + if (typeof args.searchRegex !== undefined) { + messagesQuery.msg = { + $regex: new RegExp(args.searchRegex, 'i') + }; + } + + // count + if (isPagination && args.count) { + messagesOptions.limit = args.count; + } + + const messages = models.Messages.find( + Object.assign({}, messagesQuery, { rid: channel._id }), + messagesOptions + ); + + messagesArray = messages.fetch(); + + if (isPagination) { + cursor = (messagesArray[messagesArray.length - 1] || {})._id; + } + } return { - cursor: 'CURSOR', + cursor, channel, messagesArray }; diff --git a/packages/rocketchat-graphql/server/schemas/users/User-type.js b/packages/rocketchat-graphql/server/schemas/users/User-type.js new file mode 100644 index 000000000000..76f75c194153 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/users/User-type.js @@ -0,0 +1,36 @@ +import { + property +} from '../../helpers/property'; + +export const schema = ` + extend type User { + status: UserStatus + avatar: String + name: String + lastLogin: String + channels: [Channel] + directMessages: [Channel] + } +`; + +export const resolver = { + User: { + id: property('_id'), + status: ({status}) => status.toUpperCase(), + avatar: ({ _id}, args, { models }) => { + const avatar = models.Avatars.findOne({ + userId: _id + }, { fields: { url: 1 }}); + + if (avatar) { + return avatar.url; + } + }, + channels: ({ _id }, args, { models }) => { + return models.Rooms.findBySubscriptionUserId(_id).fetch(); + }, + directMessages: ({ username }, args, { models }) => { + return models.Rooms.findByTypeContainingUsername('d', username).fetch(); + } + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.js b/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.js new file mode 100644 index 000000000000..5e821bb5ee2a --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.js @@ -0,0 +1,9 @@ +export const schema = ` + enum UserStatus { + ONLINE + AWAY + BUSY + INVISIBLE + OFFLINE + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/users/index.js b/packages/rocketchat-graphql/server/schemas/users/index.js new file mode 100644 index 000000000000..7647d5a5fdd6 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/users/index.js @@ -0,0 +1,22 @@ +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; + +// mutations +import * as setStatus from './setStatus'; +// types +import * as UserType from './User-type'; +import * as UserStatus from './UserStatus-enum'; + +export const schema = mergeTypes([ + // mutations + setStatus.schema, + // types + UserType.schema, + UserStatus.schema +]); + +export const resolvers = mergeResolvers([ + // mutations + setStatus.resolver, + // types + UserType.resolver +]); diff --git a/packages/rocketchat-graphql/server/schemas/users/setStatus.js b/packages/rocketchat-graphql/server/schemas/users/setStatus.js new file mode 100644 index 000000000000..007ae3cf050e --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/users/setStatus.js @@ -0,0 +1,22 @@ +import { authenticated } from '../../mocks/accounts/graphql-api'; +import AccountsServer from '../../mocks/accounts/server'; + +export const schema = ` + type Mutation { + setStatus(status: UserStatus!): User + } +`; + +export const resolver = { + Mutation: { + setStatus: authenticated(AccountsServer, (root, { status }, { models, user }) => { + models.Users.update(user._id, { + $set: { + status: status.toLowerCase() + } + }); + + return models.Users.findOne(user._id); + }) + } +}; diff --git a/packages/rocketchat-graphql/server/subscriptions.js b/packages/rocketchat-graphql/server/subscriptions.js new file mode 100644 index 000000000000..d86d23f85d05 --- /dev/null +++ b/packages/rocketchat-graphql/server/subscriptions.js @@ -0,0 +1,3 @@ +import { PubSub } from 'graphql-subscriptions'; + +export const pubsub = new PubSub(); diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index 7be42499e08a..5eed6181d88b 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -34,6 +34,7 @@ Package.onUse(function(api) { api.use('matb33:collection-hooks'); api.use('service-configuration'); api.use('check'); + api.use('rocketchat:accounts'); api.use('rocketchat:i18n'); api.use('rocketchat:streamer'); api.use('rocketchat:version'); From 7bb4bfca525c6c1eefde09dcd6db9451af1e2922 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Thu, 20 Jul 2017 10:29:22 +0100 Subject: [PATCH 076/801] WIP --- packages/rocketchat-accounts/server/config.js | 8 ++++++-- packages/rocketchat-accounts/server/fix.js | 3 +++ packages/rocketchat-accounts/server/index.js | 1 + .../schemas/accounts/loginWithServiceAccessToken.js | 2 +- .../server/schemas/channels/channelByName.js | 5 +++-- .../server/schemas/channels/channels.js | 5 +++-- .../server/schemas/channels/channelsByUser.js | 5 +++-- .../server/schemas/channels/createChannel.js | 5 ++--- .../server/schemas/channels/hideChannel.js | 5 ++--- .../server/schemas/channels/leaveChannel.js | 5 ++--- .../server/schemas/messages/addReactionToMessage.js | 5 ++--- .../server/schemas/messages/deleteMessage.js | 5 ++--- .../server/schemas/messages/editMessage.js | 5 ++--- .../server/schemas/messages/messages.js | 4 ++-- .../server/schemas/messages/sendMessage.js | 4 ++-- .../rocketchat-graphql/server/schemas/users/setStatus.js | 4 ++-- 16 files changed, 38 insertions(+), 33 deletions(-) create mode 100644 packages/rocketchat-accounts/server/fix.js diff --git a/packages/rocketchat-accounts/server/config.js b/packages/rocketchat-accounts/server/config.js index a9c215fdbd77..621db418d784 100644 --- a/packages/rocketchat-accounts/server/config.js +++ b/packages/rocketchat-accounts/server/config.js @@ -6,7 +6,10 @@ import { Meteor } from 'meteor/meteor'; Meteor.startup(() => { const mongodb = MongoInternals.defaultRemoteCollectionDriver().mongo.db; - const mongoAdapter = new MongoAdapter(mongodb); + const mongoAdapter = new MongoAdapter(mongodb, { + // XXX: UserId in RocketChat is a string(17) value + convertUserIdToMongoObjectId: false + }); AccountsServer.config({ tokenConfigs: { @@ -16,6 +19,7 @@ Meteor.startup(() => { refreshToken: { expiresIn: '30d' } - } + }, + passwordHashAlgorithm: 'sha256' }, mongoAdapter); }); diff --git a/packages/rocketchat-accounts/server/fix.js b/packages/rocketchat-accounts/server/fix.js new file mode 100644 index 000000000000..f1900a19c465 --- /dev/null +++ b/packages/rocketchat-accounts/server/fix.js @@ -0,0 +1,3 @@ +import regeneratorRuntime from 'babel-runtime/regenerator'; + +global.regeneratorRuntime = regeneratorRuntime; diff --git a/packages/rocketchat-accounts/server/index.js b/packages/rocketchat-accounts/server/index.js index 7e25e6061c78..a1fd2ccb053e 100644 --- a/packages/rocketchat-accounts/server/index.js +++ b/packages/rocketchat-accounts/server/index.js @@ -1,3 +1,4 @@ +import './fix'; import './config'; import AccountsServer from '@accounts/server'; diff --git a/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js b/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js index 26d95f49c0cf..0aeb4a1647f7 100644 --- a/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js +++ b/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js @@ -1,4 +1,4 @@ -import AccountsServer from '../../mocks/accounts/server'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js index 9e0f0ca3c39c..de526a3659ed 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js @@ -1,5 +1,6 @@ -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; + import { roomPublicFields } from './settings'; export const schema = ` diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.js b/packages/rocketchat-graphql/server/schemas/channels/channels.js index 61a8535da41d..8f50a32442dc 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channels.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channels.js @@ -1,5 +1,6 @@ -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; + import { roomPublicFields } from './settings'; export const schema = ` diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js index 98a888fe8970..188f715e2e8e 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js @@ -1,5 +1,6 @@ -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; + import { roomPublicFields } from './settings'; export const schema = ` diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js index e7fe0ce09a16..a98db3e8529e 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js @@ -1,7 +1,6 @@ import { Meteor } from 'meteor/meteor'; - -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js index 95a8e0f0486f..41b3a9ec48b5 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js @@ -1,7 +1,6 @@ import { Meteor } from 'meteor/meteor'; - -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { diff --git a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js index d20c6042b0e9..a4d7cf9cc97a 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js @@ -1,7 +1,6 @@ import { Meteor } from 'meteor/meteor'; - -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { diff --git a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js index 89d020ea82b1..b986dbc9b447 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js @@ -1,7 +1,6 @@ import { Meteor } from 'meteor/meteor'; - -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { diff --git a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js index 0b941817a8dd..332909ea9493 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js @@ -1,7 +1,6 @@ import { Meteor } from 'meteor/meteor'; - -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { diff --git a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js b/packages/rocketchat-graphql/server/schemas/messages/editMessage.js index 6eacb619f51d..7e412a02076c 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/editMessage.js @@ -1,7 +1,6 @@ import { Meteor } from 'meteor/meteor'; - -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.js b/packages/rocketchat-graphql/server/schemas/messages/messages.js index a55aa09981b0..d2ad849a2da1 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/messages.js +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.js @@ -1,5 +1,5 @@ -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Query { diff --git a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js index ed675ce002d8..a7d40e13213b 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js @@ -1,7 +1,7 @@ /* global processWebhookMessage */ -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { diff --git a/packages/rocketchat-graphql/server/schemas/users/setStatus.js b/packages/rocketchat-graphql/server/schemas/users/setStatus.js index 007ae3cf050e..65311303b7a5 100644 --- a/packages/rocketchat-graphql/server/schemas/users/setStatus.js +++ b/packages/rocketchat-graphql/server/schemas/users/setStatus.js @@ -1,5 +1,5 @@ -import { authenticated } from '../../mocks/accounts/graphql-api'; -import AccountsServer from '../../mocks/accounts/server'; +import { authenticated } from '@accounts/graphql-api'; +import AccountsServer from '@accounts/server'; export const schema = ` type Mutation { From a75b31212a1638a4b7b505af3e25da224729d195 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Fri, 21 Jul 2017 13:32:35 +0100 Subject: [PATCH 077/801] WIP --- packages/rocketchat-accounts/package.js | 2 +- packages/rocketchat-accounts/server/index.js | 1 + packages/rocketchat-graphql/server/api.js | 31 ++++++++++-------- .../server/helpers/authenticated.js | 7 ++++ .../accounts/loginWithServiceAccessToken.js | 32 ------------------- .../server/schemas/channels/channelByName.js | 6 ++-- .../server/schemas/channels/channels.js | 6 ++-- .../server/schemas/channels/channelsByUser.js | 17 +++++----- .../server/schemas/channels/createChannel.js | 6 ++-- .../server/schemas/channels/hideChannel.js | 6 ++-- .../server/schemas/channels/leaveChannel.js | 6 ++-- .../schemas/messages/addReactionToMessage.js | 8 ++--- .../server/schemas/messages/deleteMessage.js | 6 ++-- .../server/schemas/messages/editMessage.js | 6 ++-- .../server/schemas/messages/messages.js | 5 ++- .../server/schemas/messages/sendMessage.js | 5 ++- .../server/schemas/users/User-type.js | 7 ++-- .../server/schemas/users/setStatus.js | 5 ++- 18 files changed, 69 insertions(+), 93 deletions(-) create mode 100644 packages/rocketchat-graphql/server/helpers/authenticated.js delete mode 100644 packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js diff --git a/packages/rocketchat-accounts/package.js b/packages/rocketchat-accounts/package.js index ad3d2abb5687..fd29a0c2ebae 100644 --- a/packages/rocketchat-accounts/package.js +++ b/packages/rocketchat-accounts/package.js @@ -17,7 +17,7 @@ Package.onUse(function(api) { }); Npm.depends({ - '@accounts/server': '0.0.17', + '@accounts/server': '0.0.18', '@accounts/mongo': '0.0.12-0', '@accounts/meteor-adapter': '0.1.1' }); diff --git a/packages/rocketchat-accounts/server/index.js b/packages/rocketchat-accounts/server/index.js index a1fd2ccb053e..87ec121feca8 100644 --- a/packages/rocketchat-accounts/server/index.js +++ b/packages/rocketchat-accounts/server/index.js @@ -3,6 +3,7 @@ import './config'; import AccountsServer from '@accounts/server'; + export { AccountsServer }; diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index 069ada537a9b..73aa590b4f07 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -2,11 +2,11 @@ import { graphqlExpress, graphiqlExpress } from 'graphql-server-express'; import { JSAccountsContext as jsAccountsContext } from '@accounts/graphql-api'; import { SubscriptionServer } from 'subscriptions-transport-ws'; import { execute, subscribe } from 'graphql'; +import { Meteor } from 'meteor/meteor'; +import { WebApp } from 'meteor/webapp'; import bodyParser from 'body-parser'; import express from 'express'; import cors from 'cors'; -import { Meteor } from 'meteor/meteor'; -import { WebApp } from 'meteor/webapp'; import { executableSchema } from './schema'; @@ -19,18 +19,21 @@ graphQLServer.use(bodyParser.urlencoded({ extended: true })); graphQLServer.use( '/graphql', bodyParser.json(), - graphqlExpress(request => ({ - schema: executableSchema, - context: Object.assign({ - models: RocketChat.models - }, jsAccountsContext(request)), - formatError: e => ({ - message: e.message, - locations: e.locations, - path: e.path - }), - debug: Meteor.isDevelopment - }))); + graphqlExpress(request => { + return { + schema: executableSchema, + context: Object.assign({ + models: RocketChat.models + }, jsAccountsContext(request)), + formatError: e => ({ + message: e.message, + locations: e.locations, + path: e.path + }), + debug: Meteor.isDevelopment + }; + }) +); graphQLServer.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql', diff --git a/packages/rocketchat-graphql/server/helpers/authenticated.js b/packages/rocketchat-graphql/server/helpers/authenticated.js new file mode 100644 index 000000000000..789101545ca1 --- /dev/null +++ b/packages/rocketchat-graphql/server/helpers/authenticated.js @@ -0,0 +1,7 @@ +import { Meteor } from 'meteor/meteor'; +import { AccountsServer } from 'meteor/rocketchat:accounts'; +import { authenticated as _authenticated } from '@accounts/graphql-api'; + +export const authenticated = (resolver) => { + return _authenticated(AccountsServer, Meteor.bindEnvironment(resolver), (error) => { throw error; }); +}; diff --git a/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js b/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js deleted file mode 100644 index 0aeb4a1647f7..000000000000 --- a/packages/rocketchat-graphql/server/schemas/accounts/loginWithServiceAccessToken.js +++ /dev/null @@ -1,32 +0,0 @@ -import AccountsServer from '@accounts/server'; - -export const schema = ` - type Mutation { - loginWithServiceAccessToken(service: String!, accessToken: String!): LoginResult - } -`; - -export const resolver = { - Mutation: { - loginWithServiceAccessToken: async(root, { service, accessToken }) => { - try { - const userData = await oauthResolver.getUserDataFromService(accessToken, service); - const accountsServer = AccountsServer; - const user = await oauthResolver.getUserFromServiceUserData(service, userData); - - if (!user) { - return null; - } - - const loginResult = await accountsServer.loginWithUser(user); - - return { - refreshToken: loginResult.tokens.refreshToken, - accessToken: loginResult.tokens.accessToken - }; - } catch (e) { - console.error('Failed to login with service', e); - } - } - } -}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js index de526a3659ed..213af845243c 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js @@ -1,6 +1,4 @@ -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; - +import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; export const schema = ` @@ -11,7 +9,7 @@ export const schema = ` export const resolver = { Query: { - channelByName: authenticated(AccountsServer, (root, { name, isDirect }, { models }) => { + channelByName: authenticated((root, { name, isDirect }, { models }) => { const query = { name }; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.js b/packages/rocketchat-graphql/server/schemas/channels/channels.js index 8f50a32442dc..f926ab80a1af 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channels.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channels.js @@ -1,6 +1,4 @@ -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; - +import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; export const schema = ` @@ -15,7 +13,7 @@ export const schema = ` export const resolver = { Query: { - channels: authenticated(AccountsServer, (root, args, { models }) => { + channels: authenticated((root, args, { models }) => { const query = {}; const options = { sort: { diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js index 188f715e2e8e..5651ef1a27b8 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js @@ -1,5 +1,4 @@ -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; +import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; @@ -11,7 +10,7 @@ export const schema = ` export const resolver = { Query: { - channelsByUser: authenticated(AccountsServer, (root, { userId }, { models }) => { + channelsByUser: authenticated((root, { userId }, { models }) => { const user = models.Users.findOneById(userId); if (!user) { @@ -19,16 +18,18 @@ export const resolver = { throw new Error('No user'); } - return models.Rooms.find({ - 'usernames': { - $in: user.username - } - }, { + // TODO: empty + const rooms = models.Rooms.findByContainingUsername(user.username, { sort: { name: 1 }, fields: roomPublicFields }).fetch(); + + console.log('user.username', user.username); + console.log('rooms', rooms); + + return rooms; }) } }; diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js index a98db3e8529e..8d0274c8a311 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; + +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Mutation { @@ -15,7 +15,7 @@ export const schema = ` export const resolver = { Mutation: { - createChannel: authenticated(AccountsServer, (root, args, { models, user }) => { + createChannel: authenticated((root, args, { models, user }) => { if (!RocketChat.authz.hasPermission(user._id, 'create-c')) { return RocketChat.API.v1.unauthorized(); } diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js index 41b3a9ec48b5..3bb3627fe661 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; + +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Mutation { @@ -10,7 +10,7 @@ export const schema = ` export const resolver = { Mutation: { - hideChannel: authenticated(AccountsServer, (root, args, { models, user }) => { + hideChannel: authenticated((root, args, { models, user }) => { const channel = models.Rooms.findOne({ _id: args.channelId, t: 'c' diff --git a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js index a4d7cf9cc97a..4eee709e2df4 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; + +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Mutation { @@ -10,7 +10,7 @@ export const schema = ` export const resolver = { Mutation: { - leaveChannel: authenticated(AccountsServer, (root, args, { models, user }) => { + leaveChannel: authenticated((root, args, { models, user }) => { const channel = models.Rooms.findOne({ _id: args.channelId, t: 'c' diff --git a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js index b986dbc9b447..0e1104c541e8 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; + +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Mutation { @@ -10,11 +10,11 @@ export const schema = ` export const resolver = { Mutation: { - addReactionToMassage: authenticated(AccountsServer, (root, { id, icon }, { models, user }) => { + addReactionToMassage: authenticated((root, { id, icon }, { models, user }) => { return new Promise((resolve) => { Meteor.runAsUser(user._id, () => { Meteor.call('setReaction', id.messageId, icon, () => { - resolve(models.findOne(id.messageId)); + resolve(models.Messages.findOne(id.messageId)); }); }); }); diff --git a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js index 332909ea9493..2f0aed85073b 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; + +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Mutation { @@ -10,7 +10,7 @@ export const schema = ` export const resolver = { Mutation: { - deleteMessage: authenticated(AccountsServer, (root, { id }, { models, user }) => { + deleteMessage: authenticated((root, { id }, { models, user }) => { const msg = models.Messages.findOneById(id.messageId, { fields: { u: 1, rid: 1 }}); if (!msg) { diff --git a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js b/packages/rocketchat-graphql/server/schemas/messages/editMessage.js index 7e412a02076c..1da2201d331e 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/editMessage.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; + +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Mutation { @@ -10,7 +10,7 @@ export const schema = ` export const resolver = { Mutation: { - editMessage: authenticated(AccountsServer, (root, { id, content }, { user, models }) => { + editMessage: authenticated((root, { id, content }, { user, models }) => { const msg = models.Messages.findOneById(id.messageId); //Ensure the message exists diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.js b/packages/rocketchat-graphql/server/schemas/messages/messages.js index d2ad849a2da1..7417470fdf0c 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/messages.js +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.js @@ -1,5 +1,4 @@ -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Query { @@ -16,7 +15,7 @@ export const schema = ` export const resolver = { Query: { - messages: authenticated(AccountsServer, (root, args, { models }) => { + messages: authenticated((root, args, { models }) => { const messagesQuery = {}; const messagesOptions = { sort: { ts: 1 } diff --git a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js index a7d40e13213b..430460b72de8 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js @@ -1,7 +1,6 @@ /* global processWebhookMessage */ -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Mutation { @@ -11,7 +10,7 @@ export const schema = ` export const resolver = { Mutation: { - sendMessage: authenticated(AccountsServer, (root, { channelId, content }, { user }) => { + sendMessage: authenticated((root, { channelId, content }, { user }) => { const messageReturn = processWebhookMessage({ roomId: channelId, text: content diff --git a/packages/rocketchat-graphql/server/schemas/users/User-type.js b/packages/rocketchat-graphql/server/schemas/users/User-type.js index 76f75c194153..f6c0ff0d60e5 100644 --- a/packages/rocketchat-graphql/server/schemas/users/User-type.js +++ b/packages/rocketchat-graphql/server/schemas/users/User-type.js @@ -1,3 +1,5 @@ +import { Meteor } from 'meteor/meteor'; + import { property } from '../../helpers/property'; @@ -17,7 +19,7 @@ export const resolver = { User: { id: property('_id'), status: ({status}) => status.toUpperCase(), - avatar: ({ _id}, args, { models }) => { + avatar: Meteor.bindEnvironment(({ _id }, args, { models }) => { const avatar = models.Avatars.findOne({ userId: _id }, { fields: { url: 1 }}); @@ -25,7 +27,8 @@ export const resolver = { if (avatar) { return avatar.url; } - }, + return; + }), channels: ({ _id }, args, { models }) => { return models.Rooms.findBySubscriptionUserId(_id).fetch(); }, diff --git a/packages/rocketchat-graphql/server/schemas/users/setStatus.js b/packages/rocketchat-graphql/server/schemas/users/setStatus.js index 65311303b7a5..ca5362c0d945 100644 --- a/packages/rocketchat-graphql/server/schemas/users/setStatus.js +++ b/packages/rocketchat-graphql/server/schemas/users/setStatus.js @@ -1,5 +1,4 @@ -import { authenticated } from '@accounts/graphql-api'; -import AccountsServer from '@accounts/server'; +import { authenticated } from '../../helpers/authenticated'; export const schema = ` type Mutation { @@ -9,7 +8,7 @@ export const schema = ` export const resolver = { Mutation: { - setStatus: authenticated(AccountsServer, (root, { status }, { models, user }) => { + setStatus: authenticated((root, { status }, { models, user }) => { models.Users.update(user._id, { $set: { status: status.toLowerCase() From 9ea0ccef988b1cf1eb739b8b078fd2326fb4670b Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Fri, 21 Jul 2017 22:53:20 +0100 Subject: [PATCH 078/801] WIP --- packages/rocketchat-graphql/server/api.js | 4 +--- .../server/helpers/authenticated.js | 7 +++--- .../server/mocks/accounts/graphql-api.js | 23 ++++++++++++++++++- .../server/mocks/accounts/server.js | 5 ++-- .../server/schemas/channels/Channel-type.js | 8 +++---- .../server/schemas/channels/channelByName.js | 4 ++-- .../server/schemas/channels/channels.js | 4 ++-- .../server/schemas/channels/channelsByUser.js | 9 +++----- .../server/schemas/channels/createChannel.js | 4 ++-- .../server/schemas/channels/hideChannel.js | 6 ++--- .../server/schemas/channels/leaveChannel.js | 4 ++-- .../server/schemas/messages/Message-type.js | 16 ++++++------- .../schemas/messages/addReactionToMessage.js | 4 ++-- .../server/schemas/messages/deleteMessage.js | 4 ++-- .../server/schemas/messages/editMessage.js | 6 ++--- .../server/schemas/messages/messages.js | 10 ++++---- .../server/schemas/users/User-type.js | 16 ++++++------- .../server/schemas/users/setStatus.js | 6 ++--- 18 files changed, 77 insertions(+), 63 deletions(-) diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index 73aa590b4f07..7a82b6acec00 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -22,9 +22,7 @@ graphQLServer.use( graphqlExpress(request => { return { schema: executableSchema, - context: Object.assign({ - models: RocketChat.models - }, jsAccountsContext(request)), + context: jsAccountsContext(request), formatError: e => ({ message: e.message, locations: e.locations, diff --git a/packages/rocketchat-graphql/server/helpers/authenticated.js b/packages/rocketchat-graphql/server/helpers/authenticated.js index 789101545ca1..a0a39e676560 100644 --- a/packages/rocketchat-graphql/server/helpers/authenticated.js +++ b/packages/rocketchat-graphql/server/helpers/authenticated.js @@ -1,7 +1,8 @@ -import { Meteor } from 'meteor/meteor'; import { AccountsServer } from 'meteor/rocketchat:accounts'; -import { authenticated as _authenticated } from '@accounts/graphql-api'; +//import { authenticated as _authenticated } from '@accounts/graphql-api'; + +import { authenticated as _authenticated } from '../mocks/accounts/graphql-api'; export const authenticated = (resolver) => { - return _authenticated(AccountsServer, Meteor.bindEnvironment(resolver), (error) => { throw error; }); + return _authenticated(AccountsServer, resolver); }; diff --git a/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js index ac01fd1b681a..adbaaaa71d7e 100644 --- a/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js +++ b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js @@ -1,9 +1,30 @@ -export const authenticated = (Accounts, func) => (async(root, args, context, info) => { +/*export const authenticated = (Accounts, func) => (async(root, args, context, info) => { const userObject = await Accounts.resumeSession(); if (userObject === null) { throw new Error('Invalid or expired token!'); } + return await func(root, args, Object.assign(context, { user: userObject }), info); +});*/ + +// Same as here: https://github.com/js-accounts/graphql/blob/master/packages/graphql-api/src/utils/authenticated-resolver.js +// except code below works +// It might be like that because of async/await, +// maybe Promise is not wrapped with Fiber +// See: https://github.com/meteor/meteor/blob/a362e20a37547362b581fed52f7171d022e83b62/packages/promise/server.js +export const authenticated = (Accounts, func) => (async(root, args, context, info) => { + const authToken = context.authToken; + + if (!authToken || authToken === '' || authToken === null) { + throw new Error('Unable to find authorization token in request'); + } + + const userObject = await Accounts.resumeSession(authToken); + + if (userObject === null) { + throw new Error('Invalid or expired token!'); + } + return await func(root, args, Object.assign(context, { user: userObject }), info); }); diff --git a/packages/rocketchat-graphql/server/mocks/accounts/server.js b/packages/rocketchat-graphql/server/mocks/accounts/server.js index d44d2d09efae..8bf64b3bccbf 100644 --- a/packages/rocketchat-graphql/server/mocks/accounts/server.js +++ b/packages/rocketchat-graphql/server/mocks/accounts/server.js @@ -1,14 +1,13 @@ const loggedOut = false; const AccountsServer = { - async resumeSession() { + resumeSession: (async() => { if (loggedOut) { throw new Error('User not found'); } // User credentials - // mys:admin return RocketChat.models.Users.findOne({username: 'mys'}); - } + }) }; export default AccountsServer; diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js index 9d394c536aae..8ae65ddb16aa 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js +++ b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js @@ -23,18 +23,18 @@ export const schema = ` export const resolver = { Channel: { id: property('_id'), - members: (root, args, { models }) => { + members: (root) => { return root.usernames.map( - username => models.Users.findOneByUsername(username) + username => RocketChat.models.Users.findOneByUsername(username) ); }, - owners: (root, args, { models }) => { + owners: (root) => { // there might be no owner if (!root.u) { return; } - return [models.Users.findOneByUsername(root.u.username)]; + return [RocketChat.models.Users.findOneByUsername(root.u.username)]; }, numberOfMembers: (root) => (root.usernames || []).length, numberOfMessages: property('msgs'), diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js index 213af845243c..32e6d1e44000 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js @@ -9,7 +9,7 @@ export const schema = ` export const resolver = { Query: { - channelByName: authenticated((root, { name, isDirect }, { models }) => { + channelByName: authenticated((root, { name, isDirect }) => { const query = { name }; @@ -18,7 +18,7 @@ export const resolver = { query.c = 'd'; } - return models.Rooms.findOne(query, { + return RocketChat.models.Rooms.findOne(query, { fields: roomPublicFields }); }) diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.js b/packages/rocketchat-graphql/server/schemas/channels/channels.js index f926ab80a1af..c188819c96b3 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channels.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channels.js @@ -13,7 +13,7 @@ export const schema = ` export const resolver = { Query: { - channels: authenticated((root, args, { models }) => { + channels: authenticated((root, args) => { const query = {}; const options = { sort: { @@ -54,7 +54,7 @@ export const resolver = { // TODO: } - return models.Rooms.find(query, options).fetch(); + return RocketChat.models.Rooms.find(query, options).fetch(); }) } }; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js index 5651ef1a27b8..b16e9f0c12fd 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js @@ -10,8 +10,8 @@ export const schema = ` export const resolver = { Query: { - channelsByUser: authenticated((root, { userId }, { models }) => { - const user = models.Users.findOneById(userId); + channelsByUser: authenticated((root, { userId }) => { + const user = RocketChat.models.Users.findOneById(userId); if (!user) { // TODO: @@ -19,16 +19,13 @@ export const resolver = { } // TODO: empty - const rooms = models.Rooms.findByContainingUsername(user.username, { + const rooms = RocketChat.models.Rooms.findByContainingUsername(user.username, { sort: { name: 1 }, fields: roomPublicFields }).fetch(); - console.log('user.username', user.username); - console.log('rooms', rooms); - return rooms; }) } diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js index 8d0274c8a311..c87e88991767 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js @@ -15,7 +15,7 @@ export const schema = ` export const resolver = { Mutation: { - createChannel: authenticated((root, args, { models, user }) => { + createChannel: authenticated((root, args, { user }) => { if (!RocketChat.authz.hasPermission(user._id, 'create-c')) { return RocketChat.API.v1.unauthorized(); } @@ -38,7 +38,7 @@ export const resolver = { id = Meteor.call('createChannel', args.name, args.membersId ? args.membersId : [], readOnly); }); - return models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude }); + return RocketChat.models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude }); }) } }; diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js index 3bb3627fe661..cab57e119468 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js @@ -10,8 +10,8 @@ export const schema = ` export const resolver = { Mutation: { - hideChannel: authenticated((root, args, { models, user }) => { - const channel = models.Rooms.findOne({ + hideChannel: authenticated((root, args, { user }) => { + const channel = RocketChat.models.Rooms.findOne({ _id: args.channelId, t: 'c' }); @@ -20,7 +20,7 @@ export const resolver = { throw new Error('error-room-not-found', 'The required "channelId" param provided does not match any channel'); } - const sub = models.Subscriptions.findOneByRoomIdAndUserId(channel._id, user._id); + const sub = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(channel._id, user._id); if (!sub) { throw new Error(`The user/callee is not in the channel "${ channel.name }.`); diff --git a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js index 4eee709e2df4..141f1eba171f 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js @@ -10,8 +10,8 @@ export const schema = ` export const resolver = { Mutation: { - leaveChannel: authenticated((root, args, { models, user }) => { - const channel = models.Rooms.findOne({ + leaveChannel: authenticated((root, args, { user }) => { + const channel = RocketChat.models.Rooms.findOne({ _id: args.channelId, t: 'c' }); diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js index 3c6a1f0b34be..3e52885e0ff2 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js @@ -21,19 +21,19 @@ export const resolver = { id: property('_id'), content: property('msg'), creationTime: property('ts'), - author: (root, args, { models }) => { - return models.Users.findOne(root.u._id); + author: (root) => { + return RocketChat.models.Users.findOne(root.u._id); }, - channel: (root, args, { models }) => { - return models.Rooms.findOne(root.rid); + channel: (root) => { + return RocketChat.models.Rooms.findOne(root.rid); }, fromServer: (root) => typeof root.t !== 'undefined', // on a message sent by user `true` otherwise `false` - channelRef: (root, args, { models }) => { + channelRef: (root) => { if (!root.channels) { return; } - return models.Rooms.find({ + return RocketChat.models.Rooms.find({ _id: { $in: root.channels.map(c => c._id) } @@ -43,12 +43,12 @@ export const resolver = { } }).fetch(); }, - userRef: (root, args, { models }) => { + userRef: (root) => { if (!root.mentions) { return; } - return models.Users.find({ + return RocketChat.models.Users.find({ _id: { $in: root.mentions.map(c => c._id) } diff --git a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js index 0e1104c541e8..2dc894969880 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js @@ -10,11 +10,11 @@ export const schema = ` export const resolver = { Mutation: { - addReactionToMassage: authenticated((root, { id, icon }, { models, user }) => { + addReactionToMassage: authenticated((root, { id, icon }, { user }) => { return new Promise((resolve) => { Meteor.runAsUser(user._id, () => { Meteor.call('setReaction', id.messageId, icon, () => { - resolve(models.Messages.findOne(id.messageId)); + resolve(RocketChat.models.Messages.findOne(id.messageId)); }); }); }); diff --git a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js index 2f0aed85073b..91b3d0fa7e92 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js @@ -10,8 +10,8 @@ export const schema = ` export const resolver = { Mutation: { - deleteMessage: authenticated((root, { id }, { models, user }) => { - const msg = models.Messages.findOneById(id.messageId, { fields: { u: 1, rid: 1 }}); + deleteMessage: authenticated((root, { id }, { user }) => { + const msg = RocketChat.models.Messages.findOneById(id.messageId, { fields: { u: 1, rid: 1 }}); if (!msg) { throw new Error(`No message found with the id of "${ id.messageId }".`); diff --git a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js b/packages/rocketchat-graphql/server/schemas/messages/editMessage.js index 1da2201d331e..da1e1c8e850e 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js +++ b/packages/rocketchat-graphql/server/schemas/messages/editMessage.js @@ -10,8 +10,8 @@ export const schema = ` export const resolver = { Mutation: { - editMessage: authenticated((root, { id, content }, { user, models }) => { - const msg = models.Messages.findOneById(id.messageId); + editMessage: authenticated((root, { id, content }, { user }) => { + const msg = RocketChat.models.Messages.findOneById(id.messageId); //Ensure the message exists if (!msg) { @@ -27,7 +27,7 @@ export const resolver = { Meteor.call('updateMessage', { _id: msg._id, msg: content, rid: msg.rid }); }); - return models.Messages.findOneById(msg._id); + return RocketChat.models.Messages.findOneById(msg._id); }) } }; diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.js b/packages/rocketchat-graphql/server/schemas/messages/messages.js index 7417470fdf0c..ad8bb24cdfed 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/messages.js +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.js @@ -15,7 +15,7 @@ export const schema = ` export const resolver = { Query: { - messages: authenticated((root, args, { models }) => { + messages: authenticated((root, args) => { const messagesQuery = {}; const messagesOptions = { sort: { ts: 1 } @@ -36,19 +36,19 @@ export const resolver = { return null; } - const channel = models.Rooms.findOne(channelQuery); + const channel = RocketChat.models.Rooms.findOne(channelQuery); let messagesArray = []; if (channel) { // cursor if (isPagination && args.cursor) { - const cursorMsg = models.Messages.findOne(args.cursor, { fields: { ts: 1 } }); + const cursorMsg = RocketChat.models.Messages.findOne(args.cursor, { fields: { ts: 1 } }); messagesQuery.ts = { $gt: cursorMsg.ts }; } // searchRegex - if (typeof args.searchRegex !== undefined) { + if (typeof args.searchRegex === 'string') { messagesQuery.msg = { $regex: new RegExp(args.searchRegex, 'i') }; @@ -59,7 +59,7 @@ export const resolver = { messagesOptions.limit = args.count; } - const messages = models.Messages.find( + const messages = RocketChat.models.Messages.find( Object.assign({}, messagesQuery, { rid: channel._id }), messagesOptions ); diff --git a/packages/rocketchat-graphql/server/schemas/users/User-type.js b/packages/rocketchat-graphql/server/schemas/users/User-type.js index f6c0ff0d60e5..34978665bcdb 100644 --- a/packages/rocketchat-graphql/server/schemas/users/User-type.js +++ b/packages/rocketchat-graphql/server/schemas/users/User-type.js @@ -1,5 +1,3 @@ -import { Meteor } from 'meteor/meteor'; - import { property } from '../../helpers/property'; @@ -19,8 +17,8 @@ export const resolver = { User: { id: property('_id'), status: ({status}) => status.toUpperCase(), - avatar: Meteor.bindEnvironment(({ _id }, args, { models }) => { - const avatar = models.Avatars.findOne({ + avatar: async({ _id }) => { + const avatar = RocketChat.models.Avatars.findOne({ userId: _id }, { fields: { url: 1 }}); @@ -28,12 +26,12 @@ export const resolver = { return avatar.url; } return; - }), - channels: ({ _id }, args, { models }) => { - return models.Rooms.findBySubscriptionUserId(_id).fetch(); }, - directMessages: ({ username }, args, { models }) => { - return models.Rooms.findByTypeContainingUsername('d', username).fetch(); + channels: ({ _id }) => { + return RocketChat.models.Rooms.findBySubscriptionUserId(_id).fetch(); + }, + directMessages: ({ username }) => { + return RocketChat.models.Rooms.findByTypeContainingUsername('d', username).fetch(); } } }; diff --git a/packages/rocketchat-graphql/server/schemas/users/setStatus.js b/packages/rocketchat-graphql/server/schemas/users/setStatus.js index ca5362c0d945..6c61f4675b77 100644 --- a/packages/rocketchat-graphql/server/schemas/users/setStatus.js +++ b/packages/rocketchat-graphql/server/schemas/users/setStatus.js @@ -8,14 +8,14 @@ export const schema = ` export const resolver = { Mutation: { - setStatus: authenticated((root, { status }, { models, user }) => { - models.Users.update(user._id, { + setStatus: authenticated((root, { status }, { user }) => { + RocketChat.models.Users.update(user._id, { $set: { status: status.toLowerCase() } }); - return models.Users.findOne(user._id); + return RocketChat.models.Users.findOne(user._id); }) } }; From 5f1bbc127b919953caed6b63a320c56380f14024 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Sat, 22 Jul 2017 12:49:43 +0100 Subject: [PATCH 079/801] Date to Float --- packages/rocketchat-graphql/server/helpers/dateToFloat.js | 5 +++++ .../server/schemas/messages/Message-type.js | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 packages/rocketchat-graphql/server/helpers/dateToFloat.js diff --git a/packages/rocketchat-graphql/server/helpers/dateToFloat.js b/packages/rocketchat-graphql/server/helpers/dateToFloat.js new file mode 100644 index 000000000000..faf206706f1b --- /dev/null +++ b/packages/rocketchat-graphql/server/helpers/dateToFloat.js @@ -0,0 +1,5 @@ +export function dateToFloat(date) { + if (date) { + return new Date(date).getTime(); + } +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js index 3e52885e0ff2..09204793acf7 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js @@ -1,4 +1,5 @@ import { property } from '../../helpers/property'; +import { dateToFloat } from '../../helpers/dateToFloat'; export const schema = ` type Message { @@ -6,7 +7,7 @@ export const schema = ` author: User content: String channel: Channel - creationTime: String + creationTime: Float fromServer: Boolean userRef: [User] channelRef: [Channel] @@ -20,7 +21,7 @@ export const resolver = { Message: { id: property('_id'), content: property('msg'), - creationTime: property('ts'), + creationTime: (root) => dateToFloat(root.ts), author: (root) => { return RocketChat.models.Users.findOne(root.u._id); }, From a036416feda5e4ae79aa956da2bc24912211d844 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Mon, 31 Jul 2017 19:13:56 +0200 Subject: [PATCH 080/801] Add directChannel query --- .../.npm/package/npm-shrinkwrap.json | 50 +++++++++---------- .../server/schemas/channels/channelByName.js | 11 ++-- .../server/schemas/channels/channelsByUser.js | 1 - .../server/schemas/channels/directChannel.js | 34 +++++++++++++ .../server/schemas/channels/hideChannel.js | 2 +- .../server/schemas/channels/index.js | 3 ++ 6 files changed, 67 insertions(+), 34 deletions(-) create mode 100644 packages/rocketchat-graphql/server/schemas/channels/directChannel.js diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json index 9d5e2541f031..5e620381c5c9 100644 --- a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -16,8 +16,8 @@ "from": "array-flatten@1.1.1" }, "babel-runtime": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", "from": "babel-runtime@>=6.23.0 <7.0.0" }, "backo2": { @@ -96,8 +96,8 @@ "from": "deepmerge@>=1.3.2 <2.0.0" }, "depd": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", "from": "depd@>=1.1.0 <1.2.0" }, "deprecated-decorator": { @@ -213,7 +213,14 @@ "http-errors": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", - "from": "http-errors@>=1.6.1 <1.7.0" + "from": "http-errors@>=1.6.1 <1.7.0", + "dependencies": { + "depd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "from": "depd@1.1.0" + } + } }, "iconv-lite": { "version": "0.4.15", @@ -226,9 +233,9 @@ "from": "inherits@2.0.3" }, "ipaddr.js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", - "from": "ipaddr.js@1.3.0" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "from": "ipaddr.js@1.4.0" }, "isemail": { "version": "1.2.0", @@ -331,13 +338,13 @@ "from": "mime@1.3.4" }, "mime-db": { - "version": "1.27.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "from": "mime-db@>=1.27.0 <1.28.0" + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", + "from": "mime-db@>=1.29.0 <1.30.0" }, "mime-types": { - "version": "2.1.15", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", "from": "mime-types@>=2.1.15 <2.2.0" }, "moment": { @@ -376,8 +383,8 @@ "from": "path-to-regexp@0.1.7" }, "proxy-addr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", "from": "proxy-addr@>=1.1.4 <1.2.0" }, "qs": { @@ -481,16 +488,9 @@ "from": "whatwg-fetch@>=2.0.0 <3.0.0" }, "ws": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.0.0.tgz", - "from": "ws@>=3.0.0 <4.0.0", - "dependencies": { - "safe-buffer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "from": "safe-buffer@>=5.0.1 <5.1.0" - } - } + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.1.0.tgz", + "from": "ws@>=3.0.0 <4.0.0" }, "xtend": { "version": "4.0.1", diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js index 32e6d1e44000..63b70ddf360e 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channelByName.js @@ -3,21 +3,18 @@ import { roomPublicFields } from './settings'; export const schema = ` type Query { - channelByName(name: String!, isDirect: Boolean!): Channel + channelByName(name: String!): Channel } `; export const resolver = { Query: { - channelByName: authenticated((root, { name, isDirect }) => { + channelByName: authenticated((root, { name }) => { const query = { - name + name, + t: 'c' }; - if (isDirect === true) { - query.c = 'd'; - } - return RocketChat.models.Rooms.findOne(query, { fields: roomPublicFields }); diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js index b16e9f0c12fd..0784da1854a0 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js +++ b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js @@ -18,7 +18,6 @@ export const resolver = { throw new Error('No user'); } - // TODO: empty const rooms = RocketChat.models.Rooms.findByContainingUsername(user.username, { sort: { name: 1 diff --git a/packages/rocketchat-graphql/server/schemas/channels/directChannel.js b/packages/rocketchat-graphql/server/schemas/channels/directChannel.js new file mode 100644 index 000000000000..e2431551e811 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/directChannel.js @@ -0,0 +1,34 @@ +import { authenticated } from '../../helpers/authenticated'; +import { roomPublicFields } from './settings'; + +export const schema = ` + type Query { + directChannel(username: String, channelId: String): Channel + } +`; + +export const resolver = { + Query: { + directChannel: authenticated((root, { username, channelId }, { user }) => { + const query = { + t: 'd', + usernames: user.username + }; + + if (typeof username !== 'undefined') { + if (username === user.username) { + throw new Error('You cannot specify your username'); + } + query.usernames = { $all: [ user.username, username ] }; + } else if (typeof channelId !== 'undefined') { + query.id = channelId; + } else { + throw new Error('Use one of those fields: username, channelId'); + } + + return RocketChat.models.Rooms.findOne(query, { + fields: roomPublicFields + }); + }) + } +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js index cab57e119468..2904ca9dcd2f 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js +++ b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js @@ -30,7 +30,7 @@ export const resolver = { throw new Error(`The channel, ${ channel.name }, is already closed to the sender`); } - Meteor.runAsUser(this.userId, () => { + Meteor.runAsUser(user._id, () => { Meteor.call('hideRoom', channel._id); }); diff --git a/packages/rocketchat-graphql/server/schemas/channels/index.js b/packages/rocketchat-graphql/server/schemas/channels/index.js index aa340a0030c5..063e9da41804 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/index.js +++ b/packages/rocketchat-graphql/server/schemas/channels/index.js @@ -3,6 +3,7 @@ import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; // queries import * as channels from './channels'; import * as channelByName from './channelByName'; +import * as directChannel from './directChannel'; import * as channelsByUser from './channelsByUser'; // mutations import * as createChannel from './createChannel'; @@ -19,6 +20,7 @@ export const schema = mergeTypes([ // queries channels.schema, channelByName.schema, + directChannel.schema, channelsByUser.schema, // mutations createChannel.schema, @@ -36,6 +38,7 @@ export const resolvers = mergeResolvers([ // queries channels.resolver, channelByName.resolver, + directChannel.resolver, channelsByUser.resolver, // mutations createChannel.resolver, From 0ac6e21c5729674e52acd5dbd0f77b7c558888b6 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Tue, 1 Aug 2017 16:07:48 +0200 Subject: [PATCH 081/801] Expose username as name of direct channel --- .../server/schemas/channels/Channel-type.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js index 8ae65ddb16aa..b980acad0f7b 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js +++ b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js @@ -23,6 +23,13 @@ export const schema = ` export const resolver = { Channel: { id: property('_id'), + name: (root, args, { user }) => { + if (root.t === 'd') { + return root.usernames.find(u => u !== user.username); + } + + return root.name; + }, members: (root) => { return root.usernames.map( username => RocketChat.models.Users.findOneByUsername(username) From 0499617c603681eeb30ec54084cdbd8207d3c96b Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Fri, 4 Aug 2017 22:13:44 +0200 Subject: [PATCH 082/801] WIP: rocketchat:grant --- .meteor/packages | 1 + .meteor/versions | 3 +- .../.npm/package/npm-shrinkwrap.json | 8 +- .../rocketchat-grant/.npm/package/.gitignore | 1 + packages/rocketchat-grant/.npm/package/README | 7 + .../.npm/package/npm-shrinkwrap.json | 538 ++++++++++++++++++ packages/rocketchat-grant/README.md | 10 + packages/rocketchat-grant/package.js | 23 + packages/rocketchat-grant/server/grant.js | 62 ++ packages/rocketchat-grant/server/index.js | 53 ++ packages/rocketchat-grant/server/redirect.js | 71 +++ .../.npm/package/npm-shrinkwrap.json | 17 +- 12 files changed, 784 insertions(+), 10 deletions(-) create mode 100644 packages/rocketchat-grant/.npm/package/.gitignore create mode 100644 packages/rocketchat-grant/.npm/package/README create mode 100644 packages/rocketchat-grant/.npm/package/npm-shrinkwrap.json create mode 100644 packages/rocketchat-grant/README.md create mode 100644 packages/rocketchat-grant/package.js create mode 100644 packages/rocketchat-grant/server/grant.js create mode 100644 packages/rocketchat-grant/server/index.js create mode 100644 packages/rocketchat-grant/server/redirect.js diff --git a/.meteor/packages b/.meteor/packages index c2f5c2bc98e6..4231ae96279e 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -64,6 +64,7 @@ rocketchat:file-upload rocketchat:github-enterprise rocketchat:gitlab rocketchat:google-vision +rocketchat:grant rocketchat:graphql rocketchat:highlight-words rocketchat:iframe-login diff --git a/.meteor/versions b/.meteor/versions index 253d100b0338..3d64471778f4 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -42,7 +42,7 @@ ecmascript-runtime-server@0.4.1 edgee:slingshot@0.7.1 ejson@1.0.14 email@1.2.3 -emojione:emojione@2.2.6 +emojione:emojione@3.0.3 facebook-oauth@1.3.2 fastclick@1.0.13 francocatena:status@1.5.3 @@ -152,6 +152,7 @@ rocketchat:file-upload@0.0.1 rocketchat:github-enterprise@0.0.1 rocketchat:gitlab@0.0.1 rocketchat:google-vision@0.0.1 +rocketchat:grant@0.0.1 rocketchat:graphql@0.0.1 rocketchat:highlight-words@0.0.1 rocketchat:i18n@0.0.1 diff --git a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json index 0ff3f7f21819..f279fb73a316 100644 --- a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json @@ -11,8 +11,8 @@ "from": "babel-polyfill@>=6.23.0 <7.0.0" }, "babel-runtime": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", "from": "babel-runtime@>=6.22.0 <7.0.0" }, "base64url": { @@ -203,8 +203,8 @@ "from": "safe-buffer@>=5.0.1 <6.0.0" }, "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", "from": "semver@>=5.1.0 <6.0.0" }, "starttls": { diff --git a/packages/rocketchat-grant/.npm/package/.gitignore b/packages/rocketchat-grant/.npm/package/.gitignore new file mode 100644 index 000000000000..3c3629e647f5 --- /dev/null +++ b/packages/rocketchat-grant/.npm/package/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/packages/rocketchat-grant/.npm/package/README b/packages/rocketchat-grant/.npm/package/README new file mode 100644 index 000000000000..3d492553a438 --- /dev/null +++ b/packages/rocketchat-grant/.npm/package/README @@ -0,0 +1,7 @@ +This directory and the files immediately inside it are automatically generated +when you change this package's NPM dependencies. Commit the files in this +directory (npm-shrinkwrap.json, .gitignore, and this README) to source control +so that others run the same versions of sub-dependencies. + +You should NOT check in the node_modules directory that Meteor automatically +creates; if you are using git, the .gitignore file tells git to ignore it. diff --git a/packages/rocketchat-grant/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-grant/.npm/package/npm-shrinkwrap.json new file mode 100644 index 000000000000..d824bf98528a --- /dev/null +++ b/packages/rocketchat-grant/.npm/package/npm-shrinkwrap.json @@ -0,0 +1,538 @@ +{ + "dependencies": { + "accepts": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", + "from": "accepts@>=1.3.3 <1.4.0" + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "from": "ajv@>=4.9.1 <5.0.0" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "from": "array-flatten@1.1.1" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "from": "asn1@>=0.2.3 <0.3.0" + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "from": "assert-plus@>=0.2.0 <0.3.0" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "from": "asynckit@>=0.4.0 <0.5.0" + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "from": "aws-sign2@>=0.6.0 <0.7.0" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "from": "aws4@>=1.2.1 <2.0.0" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "from": "bcrypt-pbkdf@>=1.0.0 <2.0.0" + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "from": "boom@>=2.0.0 <3.0.0" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "from": "caseless@>=0.12.0 <0.13.0" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "from": "co@>=4.6.0 <5.0.0" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "from": "combined-stream@>=1.0.5 <1.1.0" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "from": "content-disposition@0.5.2" + }, + "content-type": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", + "from": "content-type@>=1.0.2 <1.1.0" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "from": "cookie@0.3.1" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "from": "cookie-signature@1.0.6" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "from": "core-util-is@1.0.2" + }, + "crc": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", + "from": "crc@3.4.4" + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "from": "cryptiles@>=2.0.0 <3.0.0" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "from": "dashdash@>=1.12.0 <2.0.0", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@>=1.0.0 <2.0.0" + } + } + }, + "debug": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", + "from": "debug@2.6.7" + }, + "deep-copy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/deep-copy/-/deep-copy-1.2.0.tgz", + "from": "deep-copy@>=1.2.0 <2.0.0" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "from": "delayed-stream@>=1.0.0 <1.1.0" + }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "from": "depd@>=1.1.0 <1.2.0" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "from": "destroy@>=1.0.4 <1.1.0" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "from": "ecc-jsbn@>=0.1.1 <0.2.0" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "from": "ee-first@1.1.1" + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "from": "encodeurl@>=1.0.1 <1.1.0" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "from": "escape-html@>=1.0.3 <1.1.0" + }, + "etag": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", + "from": "etag@>=1.8.0 <1.9.0" + }, + "express": { + "version": "4.15.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", + "from": "express@4.15.3" + }, + "express-session": { + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.4.tgz", + "from": "express-session@1.15.4", + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "from": "debug@2.6.8" + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "from": "extend@>=3.0.0 <3.1.0" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "from": "extsprintf@1.3.0" + }, + "finalhandler": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", + "from": "finalhandler@>=1.0.3 <1.1.0" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "from": "forever-agent@>=0.6.1 <0.7.0" + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "from": "form-data@>=2.1.1 <2.2.0" + }, + "forwarded": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", + "from": "forwarded@>=0.1.0 <0.2.0" + }, + "fresh": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", + "from": "fresh@0.5.0" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "from": "getpass@>=0.1.1 <0.2.0", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@>=1.0.0 <2.0.0" + } + } + }, + "grant": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/grant/-/grant-3.8.0.tgz", + "from": "grant@3.8.0" + }, + "grant-express": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/grant-express/-/grant-express-3.8.0.tgz", + "from": "grant-express@3.8.0" + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "from": "har-schema@>=1.0.5 <2.0.0" + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "from": "har-validator@>=4.2.1 <4.3.0" + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "from": "hawk@>=3.1.3 <3.2.0" + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "from": "hoek@>=2.0.0 <3.0.0" + }, + "http-errors": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", + "from": "http-errors@>=1.6.1 <1.7.0", + "dependencies": { + "depd": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", + "from": "depd@1.1.0" + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "from": "http-signature@>=1.1.0 <1.2.0" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "from": "inherits@2.0.3" + }, + "ipaddr.js": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", + "from": "ipaddr.js@1.4.0" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "from": "is-typedarray@>=1.0.0 <1.1.0" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "from": "isstream@>=0.1.2 <0.2.0" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "from": "jsbn@>=0.1.0 <0.2.0" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "from": "json-schema@0.2.3" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "from": "json-stable-stringify@>=1.0.1 <2.0.0" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "from": "json-stringify-safe@>=5.0.1 <5.1.0" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "from": "jsonify@>=0.0.0 <0.1.0" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "from": "jsprim@>=1.2.2 <2.0.0", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@1.0.0" + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "from": "media-typer@0.3.0" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "from": "merge-descriptors@1.0.1" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "from": "methods@>=1.1.2 <1.2.0" + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "from": "mime@1.3.4" + }, + "mime-db": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", + "from": "mime-db@>=1.29.0 <1.30.0" + }, + "mime-types": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "from": "mime-types@>=2.1.11 <2.2.0" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "from": "ms@2.0.0" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "from": "negotiator@0.6.1" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "from": "oauth-sign@>=0.8.1 <0.9.0" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "from": "on-finished@>=2.3.0 <2.4.0" + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "from": "on-headers@>=1.0.1 <1.1.0" + }, + "parseurl": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", + "from": "parseurl@>=1.3.1 <1.4.0" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "from": "path-to-regexp@0.1.7" + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "from": "performance-now@>=0.2.0 <0.3.0" + }, + "proxy-addr": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", + "from": "proxy-addr@>=1.1.4 <1.2.0" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "from": "punycode@>=1.4.1 <2.0.0" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "from": "qs@6.4.0" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "from": "random-bytes@>=1.0.0 <1.1.0" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "from": "range-parser@>=1.2.0 <1.3.0" + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "from": "request@2.81.0" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "from": "safe-buffer@>=5.0.1 <6.0.0" + }, + "send": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", + "from": "send@0.15.3" + }, + "serve-static": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz", + "from": "serve-static@1.12.3" + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "from": "setprototypeof@1.0.3" + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "from": "sntp@>=1.0.0 <2.0.0" + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "from": "sshpk@>=1.7.0 <2.0.0", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@>=1.0.0 <2.0.0" + } + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "from": "statuses@>=1.3.1 <1.4.0" + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "from": "stringstream@>=0.0.4 <0.1.0" + }, + "tough-cookie": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", + "from": "tough-cookie@>=2.3.0 <2.4.0" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "from": "tunnel-agent@>=0.6.0 <0.7.0" + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "from": "tweetnacl@>=0.14.0 <0.15.0" + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "from": "type-is@>=1.6.15 <1.7.0" + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "from": "uid-safe@>=2.1.4 <2.2.0" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "from": "unpipe@>=1.0.0 <1.1.0" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "from": "utils-merge@1.0.0" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "from": "uuid@>=3.0.0 <4.0.0" + }, + "vary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", + "from": "vary@>=1.1.1 <1.2.0" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "from": "verror@1.10.0", + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "from": "assert-plus@>=1.0.0 <2.0.0" + } + } + } + } +} diff --git a/packages/rocketchat-grant/README.md b/packages/rocketchat-grant/README.md new file mode 100644 index 000000000000..b6b58a1c818f --- /dev/null +++ b/packages/rocketchat-grant/README.md @@ -0,0 +1,10 @@ +1. Settings should be the same as in OAuth section +1. Should be extendable (rocketchat:grant, rocketchat:grant-github etc) +1. Each package with provider should transform it's scope to user data so we can register a new user +1. rocketchat:grant-sub - to define sub configurations to allow for using external apps +1. rocketchat:grant should contain a middleware and startup fn with setup, that is already in rocketchat:oauth-external +1. in callback it would create and / or log in a user +1. without any specified sub configuration, it would redirect to localhost:3000 by default +1. with a specified sub configuration it would redirect to a path and add access_token to the URL + + diff --git a/packages/rocketchat-grant/package.js b/packages/rocketchat-grant/package.js new file mode 100644 index 000000000000..f6d63e698106 --- /dev/null +++ b/packages/rocketchat-grant/package.js @@ -0,0 +1,23 @@ +Package.describe({ + name: 'rocketchat:grant', + version: '0.0.1', + summary: 'OAuth2', + git: '' +}); + +Package.onUse(function(api) { + api.use([ + 'webapp', + 'mongo', + 'ecmascript', + 'rocketchat:lib' + ]); + + api.mainModule('server/index.js', 'server'); +}); + +Npm.depends({ + 'express': '4.15.3', + 'express-session': '1.15.4', + 'grant-express': '3.8.0' +}); diff --git a/packages/rocketchat-grant/server/grant.js b/packages/rocketchat-grant/server/grant.js new file mode 100644 index 000000000000..947d3d597c86 --- /dev/null +++ b/packages/rocketchat-grant/server/grant.js @@ -0,0 +1,62 @@ +export const path = '/_oauth_apps'; + +function generateCallback(serviceName) { + return `${ path }/${ serviceName }/callback`; +} + +function generateAppCallback(serviceName, appName) { + return generateCallback(`${ serviceName }/${ appName }`); +} + +function addProviders(config) { + const services = RocketChat.settings.get(/^(Accounts_OAuth_)[a-z0-9_]+$/i); + + services.forEach((service) => { + let serviceName = service.key.replace('Accounts_OAuth_', '').toLowerCase(); + + if (serviceName === 'meteor') { + serviceName = 'meteor-developer'; + } + + if (service.value === true) { + // TODO: scope + const data = { + key: RocketChat.settings.get(`${ service.key }_id`), + secret: RocketChat.settings.get(`${ service.key }_secret`), + callback: generateCallback(serviceName) + }; + + // TODO: create a space to set up OAuth services + if (serviceName === 'github') { + data.key = '96db2753350cfe8c8ae1'; + data.secret = '546317a561df5e3d350fca9b5500f270b54f3301'; + + console.log('PWA for GitHub'); + + // TODO: create a space to define Apps + data['pwa'] = { + callback: generateAppCallback(serviceName, 'pwa') + }; + } + + config[serviceName] = data; + } + }); + + return config; +} + +export function generateConfig() { + const config = { + server: { + protocol: 'http', + host: RocketChat.hostname, + path, + state: true + } + }; + + addProviders(config); + + return config; +} diff --git a/packages/rocketchat-grant/server/index.js b/packages/rocketchat-grant/server/index.js new file mode 100644 index 000000000000..c0cdba8bd7e1 --- /dev/null +++ b/packages/rocketchat-grant/server/index.js @@ -0,0 +1,53 @@ +/* +- localhost:3000/_oauth/facebook +- get the URI that this request comes from +- set it as redirectUrl +- do things +- add ?access_token= and ?service= to the URL +- redirect to it +*/ + +/*app.get(`${GRANT_PATH}/google/callback`, function (req, res) { + const accessToken = req.query.access_token; + res.redirect(`${STATIC_SERVER}/login?service=google&access_token=${accessToken}`); +});*/ + +import { WebApp } from 'meteor/webapp'; +import session from 'express-session'; +import Grant from 'grant-express'; +import fiber from 'fibers'; + +import { generateConfig, path } from './grant'; +import { middleware } from './redirect'; + +let grant; + +WebApp.connectHandlers.use(session({ + secret: 'grant', + resave: true, + saveUninitialized: true +})); + +// grant +WebApp.connectHandlers.use(path, (req, res, next) => { + if (grant) { + grant(req, res, next); + } else { + next(); + } +}); + +// callbacks +WebApp.connectHandlers.use((req, res, next) => { + fiber(() => { + middleware(req, res, next); + }).run(); +}); + +Meteor.startup(() => { + const config = generateConfig(); + + grant = new Grant(config); +}); + + diff --git a/packages/rocketchat-grant/server/redirect.js b/packages/rocketchat-grant/server/redirect.js new file mode 100644 index 000000000000..7b52a9b5fb28 --- /dev/null +++ b/packages/rocketchat-grant/server/redirect.js @@ -0,0 +1,71 @@ +function getEntry(req) { + let provider; + let app; + + const i = req.url.indexOf('?'); + let barePath; + + if (i === -1) { + barePath = req.url; + } else { + barePath = req.url.substring(0, i); + } + + const splitPath = barePath.split('/'); + + // Any non-oauth request will continue down the default + // middlewares. + if (splitPath[1] === '_oauth_apps') { + provider = splitPath[2]; + app = splitPath && splitPath[3] !== 'callback' ? splitPath[3] : null; + } + + return { + provider, + app + }; +} + +function getAccessToken(req) { + const i = req.url.indexOf('?'); + + if (i === -1) { + return; + } + + const barePath = req.url.substring(i + 1); + const splitPath = barePath.split('&'); + const token = splitPath.find(p => p.match(/access_token=[a-zA-Z0-9]+/)); + + if (token) { + return token.replace('access_token=', ''); + } +} + +export function middleware(req, res, next) { + const { + provider, + app + } = getEntry(req); + + if (!provider || !app) { + next(); + return; + } + + console.log('provider', provider); + console.log('app', app); + + // handle providers and apps + if (provider === 'github' && app === 'pwa') { + const token = getAccessToken(req); + console.log('token', token); + + // TODO: get redirect URL from settings + const redirectUrl = 'http://localhost:4200/login'; + + res.redirect(`${ redirectUrl }?service=${ provider }&access_token=${ token }`); + } + + next(); +} diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json index 5e620381c5c9..13032f7d6a0d 100644 --- a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -151,9 +151,16 @@ "from": "express@4.15.3" }, "finalhandler": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", - "from": "finalhandler@>=1.0.3 <1.1.0" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz", + "from": "finalhandler@>=1.0.3 <1.1.0", + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "from": "debug@2.6.8" + } + } }, "forwarded": { "version": "0.1.0", @@ -258,8 +265,8 @@ "from": "js-tokens@>=3.0.0 <4.0.0" }, "jsonwebtoken": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.2.tgz", "from": "jsonwebtoken@>=7.2.1 <8.0.0" }, "jwa": { From ebe18ed35f93d2cf389bcd8bbdf26e889b444353 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Wed, 9 Aug 2017 15:25:42 +0200 Subject: [PATCH 083/801] rocketchat-grant --- .meteor/packages | 3 + .meteor/versions | 3 + .../.npm/package/npm-shrinkwrap.json | 8 +- packages/rocketchat-grant-facebook/package.js | 16 +++ .../rocketchat-grant-facebook/server/index.js | 65 ++++++++++++ packages/rocketchat-grant-github/package.js | 16 +++ .../rocketchat-grant-github/server/index.js | 51 ++++++++++ packages/rocketchat-grant-google/package.js | 16 +++ .../rocketchat-grant-google/server/index.js | 43 ++++++++ packages/rocketchat-grant/README.md | 2 - packages/rocketchat-grant/package.js | 4 +- .../rocketchat-grant/server/authenticate.js | 84 ++++++++++++++++ packages/rocketchat-grant/server/grant.js | 73 ++++++-------- packages/rocketchat-grant/server/index.js | 38 +++---- packages/rocketchat-grant/server/providers.js | 42 ++++++++ packages/rocketchat-grant/server/redirect.js | 99 ++++++++----------- packages/rocketchat-grant/server/routes.js | 48 +++++++++ packages/rocketchat-grant/server/settings.js | 42 ++++++++ packages/rocketchat-grant/server/storage.js | 33 +++++++ .../.npm/package/npm-shrinkwrap.json | 17 +--- packages/rocketchat-graphql/package.js | 1 + .../schemas/accounts/OauthProvider-type.js | 5 + .../server/schemas/accounts/index.js | 17 +++- .../server/schemas/accounts/oauthProviders.js | 41 ++++++++ server/configuration/grant.js | 27 +++++ 25 files changed, 653 insertions(+), 141 deletions(-) create mode 100644 packages/rocketchat-grant-facebook/package.js create mode 100644 packages/rocketchat-grant-facebook/server/index.js create mode 100644 packages/rocketchat-grant-github/package.js create mode 100644 packages/rocketchat-grant-github/server/index.js create mode 100644 packages/rocketchat-grant-google/package.js create mode 100644 packages/rocketchat-grant-google/server/index.js create mode 100644 packages/rocketchat-grant/server/authenticate.js create mode 100644 packages/rocketchat-grant/server/providers.js create mode 100644 packages/rocketchat-grant/server/routes.js create mode 100644 packages/rocketchat-grant/server/settings.js create mode 100644 packages/rocketchat-grant/server/storage.js create mode 100644 packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js create mode 100644 server/configuration/grant.js diff --git a/.meteor/packages b/.meteor/packages index 4231ae96279e..610aee81c3d2 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -65,6 +65,9 @@ rocketchat:github-enterprise rocketchat:gitlab rocketchat:google-vision rocketchat:grant +rocketchat:grant-facebook +rocketchat:grant-github +rocketchat:grant-google rocketchat:graphql rocketchat:highlight-words rocketchat:iframe-login diff --git a/.meteor/versions b/.meteor/versions index 3d64471778f4..e178545da53a 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -153,6 +153,9 @@ rocketchat:github-enterprise@0.0.1 rocketchat:gitlab@0.0.1 rocketchat:google-vision@0.0.1 rocketchat:grant@0.0.1 +rocketchat:grant-facebook@0.0.1 +rocketchat:grant-github@0.0.1 +rocketchat:grant-google@0.0.1 rocketchat:graphql@0.0.1 rocketchat:highlight-words@0.0.1 rocketchat:i18n@0.0.1 diff --git a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json index f279fb73a316..548e1696bac6 100644 --- a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json @@ -46,8 +46,8 @@ "from": "bufferjs@1.1.0" }, "core-js": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", "from": "core-js@>=2.4.0 <3.0.0" }, "core-util-is": { @@ -111,8 +111,8 @@ "from": "joi@>=6.10.1 <7.0.0" }, "jsonwebtoken": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.2.tgz", "from": "jsonwebtoken@>=7.2.1 <8.0.0" }, "jwa": { diff --git a/packages/rocketchat-grant-facebook/package.js b/packages/rocketchat-grant-facebook/package.js new file mode 100644 index 000000000000..ad67058dde82 --- /dev/null +++ b/packages/rocketchat-grant-facebook/package.js @@ -0,0 +1,16 @@ +Package.describe({ + name: 'rocketchat:grant-facebook', + version: '0.0.1', + summary: 'Provides Facebook to rocketchat:grant', + git: '' +}); + +Package.onUse(function(api) { + api.use([ + 'ecmascript', + 'http', + 'rocketchat:grant' + ]); + + api.mainModule('server/index.js', 'server'); +}); diff --git a/packages/rocketchat-grant-facebook/server/index.js b/packages/rocketchat-grant-facebook/server/index.js new file mode 100644 index 000000000000..882ef18ac129 --- /dev/null +++ b/packages/rocketchat-grant-facebook/server/index.js @@ -0,0 +1,65 @@ +import { Providers } from 'meteor/rocketchat:grant'; +import { HTTP } from 'meteor/http'; + +const userAgent = 'Meteor'; +const version = 'v2.10'; + +function getIdentity(accessToken, fields) { + try { + return HTTP.get( + `https://graph.facebook.com/${ version }/me`, { + headers: { 'User-Agent': userAgent }, + params: { + access_token: accessToken, + fields: fields.join(',') + } + }).data; + } catch (err) { + console.log('err', err); + throw Object.assign( + new Error(`Failed to fetch identity from Facebook. ${ err.message }`), + { response: err.response } + ); + } +} + +function getPicture(accessToken) { + try { + return HTTP.get( + `https://graph.facebook.com/${ version }/me/picture`, { + headers: { 'User-Agent': userAgent }, + params: { + redirect: false, + height: 200, + width: 200, + type: 'normal', + access_token: accessToken + } + }).data; + } catch (err) { + throw Object.assign( + new Error(`Failed to fetch profile picture from Facebook. ${ err.message }`), + { response: err.response } + ); + } +} + +export function getUser(accessToken) { + const whitelisted = ['id', 'email', 'name', 'first_name', 'last_name']; + const identity = getIdentity(accessToken, whitelisted); + const avatar = getPicture(accessToken); + const username = identity.name.toLowerCase().replace(' ', '.'); + + return { + id: identity.id, + email: identity.email, + username, + profile: { + name: `${ identity.first_name } ${ identity.last_name }`, + avatar: avatar.data.url + } + }; +} + +// Register Facebook OAuth +Providers.register('facebook', { scope: ['public_profile', 'email'] }, getUser); diff --git a/packages/rocketchat-grant-github/package.js b/packages/rocketchat-grant-github/package.js new file mode 100644 index 000000000000..0e3ce2d86198 --- /dev/null +++ b/packages/rocketchat-grant-github/package.js @@ -0,0 +1,16 @@ +Package.describe({ + name: 'rocketchat:grant-github', + version: '0.0.1', + summary: 'Provides GitHub to rocketchat:grant', + git: '' +}); + +Package.onUse(function(api) { + api.use([ + 'ecmascript', + 'http', + 'rocketchat:grant' + ]); + + api.mainModule('server/index.js', 'server'); +}); diff --git a/packages/rocketchat-grant-github/server/index.js b/packages/rocketchat-grant-github/server/index.js new file mode 100644 index 000000000000..4359fe07754b --- /dev/null +++ b/packages/rocketchat-grant-github/server/index.js @@ -0,0 +1,51 @@ +import { Providers } from 'meteor/rocketchat:grant'; +import { HTTP } from 'meteor/http'; + +const userAgent = 'Meteor'; + +function getIdentity(accessToken) { + try { + return HTTP.get( + 'https://api.github.com/user', { + headers: { 'User-Agent': userAgent }, // http://developer.github.com/v3/#user-agent-required + params: { access_token: accessToken } + }).data; + } catch (err) { + throw Object.assign( + new Error(`Failed to fetch identity from Github. ${ err.message }`), + { response: err.response } + ); + } +} + +function getEmails(accessToken) { + try { + return HTTP.get( + 'https://api.github.com/user/emails', { + headers: { 'User-Agent': userAgent }, // http://developer.github.com/v3/#user-agent-required + params: { access_token: accessToken } + }).data; + } catch (err) { + return []; + } +} + +export function getUser(accessToken) { + const identity = getIdentity(accessToken); + const emails = getEmails(accessToken); + const primaryEmail = (emails || []).find(email => email.primary === true); + + return { + id: identity.id, + email: identity.email || (primaryEmail && primaryEmail.email) || '', + username: identity.login, + emails, + profile: { + name: identity.name, + avatar: identity.avatar_url + } + }; +} + +// Register GitHub OAuth +Providers.register('github', { scope: ['user', 'user:email'] }, getUser); diff --git a/packages/rocketchat-grant-google/package.js b/packages/rocketchat-grant-google/package.js new file mode 100644 index 000000000000..b0a538c44e57 --- /dev/null +++ b/packages/rocketchat-grant-google/package.js @@ -0,0 +1,16 @@ +Package.describe({ + name: 'rocketchat:grant-google', + version: '0.0.1', + summary: 'Provides Google to rocketchat:grant', + git: '' +}); + +Package.onUse(function(api) { + api.use([ + 'ecmascript', + 'http', + 'rocketchat:grant' + ]); + + api.mainModule('server/index.js', 'server'); +}); diff --git a/packages/rocketchat-grant-google/server/index.js b/packages/rocketchat-grant-google/server/index.js new file mode 100644 index 000000000000..5cc545c18cda --- /dev/null +++ b/packages/rocketchat-grant-google/server/index.js @@ -0,0 +1,43 @@ +import { Providers } from 'meteor/rocketchat:grant'; +import { HTTP } from 'meteor/http'; + +const userAgent = 'Meteor'; + +function getIdentity(accessToken) { + try { + return HTTP.get( + 'https://www.googleapis.com/oauth2/v1/userinfo', { + headers: { 'User-Agent': userAgent }, + params: { + access_token: accessToken + } + }).data; + } catch (err) { + throw Object.assign( + new Error(`Failed to fetch identity from Google. ${ err.message }`), + { response: err.response } + ); + } +} + +export function getUser(accessToken) { + const whitelisted = [ + 'id', 'email', 'verified_email', 'name', + 'given_name', 'family_name', 'picture' + ]; + const identity = getIdentity(accessToken, whitelisted); + const username = `${ identity.given_name.toLowerCase() }.${ identity.family_name.toLowerCase() }`; + + return { + id: identity.id, + email: identity.email, + username, + profile: { + name: identity.name, + avatar: identity.picture + } + }; +} + +// Register Google OAuth +Providers.register('google', { scope: ['openid', 'email'] }, getUser); diff --git a/packages/rocketchat-grant/README.md b/packages/rocketchat-grant/README.md index b6b58a1c818f..c526711cf6c9 100644 --- a/packages/rocketchat-grant/README.md +++ b/packages/rocketchat-grant/README.md @@ -6,5 +6,3 @@ 1. in callback it would create and / or log in a user 1. without any specified sub configuration, it would redirect to localhost:3000 by default 1. with a specified sub configuration it would redirect to a path and add access_token to the URL - - diff --git a/packages/rocketchat-grant/package.js b/packages/rocketchat-grant/package.js index f6d63e698106..bec938b3cb22 100644 --- a/packages/rocketchat-grant/package.js +++ b/packages/rocketchat-grant/package.js @@ -9,8 +9,10 @@ Package.onUse(function(api) { api.use([ 'webapp', 'mongo', + 'check', 'ecmascript', - 'rocketchat:lib' + 'rocketchat:lib', + 'rocketchat:accounts' ]); api.mainModule('server/index.js', 'server'); diff --git a/packages/rocketchat-grant/server/authenticate.js b/packages/rocketchat-grant/server/authenticate.js new file mode 100644 index 000000000000..bf2512d1f1aa --- /dev/null +++ b/packages/rocketchat-grant/server/authenticate.js @@ -0,0 +1,84 @@ +import { AccountsServer } from 'meteor/rocketchat:accounts'; +import { Accounts } from 'meteor/accounts-base'; + +import Providers from './providers'; + +const findUserByOAuthId = (providerName, id) => { + return RocketChat.models.Users.findOne({ [`settings.profile.oauth.${ providerName }`]: id }); +}; + +const addOAuthIdToUserProfile = (user, providerName, providerId) => { + const profile = Object.assign({}, user.settings.profile, { + oauth: { + ...user.settings.profile.oauth, + [providerName]: providerId + } + }); + + RocketChat.models.Users.setProfile(user.id, profile); +}; + +function getAccessToken(req) { + const i = req.url.indexOf('?'); + + if (i === -1) { + return; + } + + const barePath = req.url.substring(i + 1); + const splitPath = barePath.split('&'); + const token = splitPath.find(p => p.match(/access_token=[a-zA-Z0-9]+/)); + + if (token) { + return token.replace('access_token=', ''); + } +} + +export async function authenticate(providerName, req) { + let tokens; + const accessToken = getAccessToken(req); + const provider = Providers.get(providerName); + + if (!provider) { + throw new Error(`Provider '${ providerName }' not found`); + } + + const userData = provider.getUser(accessToken); + + let user = findUserByOAuthId(providerName, userData.id); + + if (user) { + user.id = user._id; + } else { + user = RocketChat.models.Users.findOneByEmailAddress(userData.email); + if (user) { + user.id = user._id; + } + } + + if (user) { + addOAuthIdToUserProfile(user, providerName, userData.id); + + const loginResult = await AccountsServer.loginWithUser({ id: user.id }); + + tokens = loginResult.tokens; + } else { + const id = Accounts.createUser({ + email: userData.email + }); + + RocketChat.models.Users.setProfile(id, { + name: userData.profile.name, + avatar: userData.profile.avatar, + oauth: { + [providerName]: userData.id + } + }); + + const loginResult = await AccountsServer.loginWithUser({ id }); + + tokens = loginResult.tokens; + } + + return tokens; +} diff --git a/packages/rocketchat-grant/server/grant.js b/packages/rocketchat-grant/server/grant.js index 947d3d597c86..0f8890652909 100644 --- a/packages/rocketchat-grant/server/grant.js +++ b/packages/rocketchat-grant/server/grant.js @@ -1,62 +1,51 @@ -export const path = '/_oauth_apps'; - -function generateCallback(serviceName) { - return `${ path }/${ serviceName }/callback`; -} - -function generateAppCallback(serviceName, appName) { - return generateCallback(`${ serviceName }/${ appName }`); -} +import Providers from './providers'; +import Settings from './settings'; +import { path, generateCallback, generateAppCallback } from './routes'; function addProviders(config) { - const services = RocketChat.settings.get(/^(Accounts_OAuth_)[a-z0-9_]+$/i); - - services.forEach((service) => { - let serviceName = service.key.replace('Accounts_OAuth_', '').toLowerCase(); + Settings.forEach((settings, providerName) => { + if (settings.enabled === true) { + const registeredProvider = Providers.get(providerName); - if (serviceName === 'meteor') { - serviceName = 'meteor-developer'; - } + if (!registeredProvider) { + console.error(`No configuration for '${ providerName }' provider`); + } - if (service.value === true) { - // TODO: scope + // basic settings const data = { - key: RocketChat.settings.get(`${ service.key }_id`), - secret: RocketChat.settings.get(`${ service.key }_secret`), - callback: generateCallback(serviceName) + key: settings.key, + secret: settings.secret, + scope: registeredProvider.scope, + callback: generateCallback(providerName) }; - // TODO: create a space to set up OAuth services - if (serviceName === 'github') { - data.key = '96db2753350cfe8c8ae1'; - data.secret = '546317a561df5e3d350fca9b5500f270b54f3301'; - - console.log('PWA for GitHub'); - - // TODO: create a space to define Apps - data['pwa'] = { - callback: generateAppCallback(serviceName, 'pwa') + // set each app + Settings.apps.forEach((_, appName) => { + data[appName] = { + callback: generateAppCallback(providerName, appName) }; - } + }); - config[serviceName] = data; + config[providerName] = data; } }); - - return config; } +const config = {}; + export function generateConfig() { - const config = { - server: { - protocol: 'http', - host: RocketChat.hostname, - path, - state: true - } + config['server'] = { + protocol: 'http', + host: RocketChat.hostname, + path, + state: true }; addProviders(config); return config; } + +export function getConfig() { + return config; +} diff --git a/packages/rocketchat-grant/server/index.js b/packages/rocketchat-grant/server/index.js index c0cdba8bd7e1..fc06ae57ba3a 100644 --- a/packages/rocketchat-grant/server/index.js +++ b/packages/rocketchat-grant/server/index.js @@ -1,24 +1,13 @@ -/* -- localhost:3000/_oauth/facebook -- get the URI that this request comes from -- set it as redirectUrl -- do things -- add ?access_token= and ?service= to the URL -- redirect to it -*/ - -/*app.get(`${GRANT_PATH}/google/callback`, function (req, res) { - const accessToken = req.query.access_token; - res.redirect(`${STATIC_SERVER}/login?service=google&access_token=${accessToken}`); -});*/ - import { WebApp } from 'meteor/webapp'; import session from 'express-session'; import Grant from 'grant-express'; import fiber from 'fibers'; -import { generateConfig, path } from './grant'; -import { middleware } from './redirect'; +import { generateConfig } from './grant'; +import { path, generateCallback, generateAppCallback } from './routes'; +import { middleware as redirect } from './redirect'; +import Providers, { middleware as providers } from './providers'; +import Settings from './settings'; let grant; @@ -40,7 +29,14 @@ WebApp.connectHandlers.use(path, (req, res, next) => { // callbacks WebApp.connectHandlers.use((req, res, next) => { fiber(() => { - middleware(req, res, next); + redirect(req, res, next); + }).run(); +}); + +// providers +WebApp.connectHandlers.use((req, res, next) => { + fiber(() => { + providers(req, res, next); }).run(); }); @@ -50,4 +46,10 @@ Meteor.startup(() => { grant = new Grant(config); }); - +export { + path, + generateCallback, + generateAppCallback, + Providers, + Settings +}; diff --git a/packages/rocketchat-grant/server/providers.js b/packages/rocketchat-grant/server/providers.js new file mode 100644 index 000000000000..4b2aad10cee5 --- /dev/null +++ b/packages/rocketchat-grant/server/providers.js @@ -0,0 +1,42 @@ +import { check } from 'meteor/check'; + +import { Storage } from './storage'; +import { routes } from './routes'; + +class Providers extends Storage { + register(name, options, getUser) { + check(name, String); + check(options, { + // eslint-disable-next-line + scope: Match.OneOf(String, [String]) + }); + check(getUser, Function); + + this._add(name.toLowerCase(), { + scope: options.scope, + getUser + }); + } +} + +const providers = new Providers; + +export default providers; + +export function middleware(req, res, next) { + const route = routes.providers(req); + + if (route) { + const list = []; + + providers.forEach((_, name) => list.push(name)); + + // TODO: send a list of providers + res.end(JSON.stringify({ + data: list + })); + return; + } + + next(); +} diff --git a/packages/rocketchat-grant/server/redirect.js b/packages/rocketchat-grant/server/redirect.js index 7b52a9b5fb28..25faad1e1ca9 100644 --- a/packages/rocketchat-grant/server/redirect.js +++ b/packages/rocketchat-grant/server/redirect.js @@ -1,70 +1,49 @@ -function getEntry(req) { - let provider; - let app; +import { authenticate } from './authenticate'; +import Settings from './settings'; +import { routes } from './routes'; - const i = req.url.indexOf('?'); - let barePath; - - if (i === -1) { - barePath = req.url; - } else { - barePath = req.url.substring(0, i); - } - - const splitPath = barePath.split('/'); - - // Any non-oauth request will continue down the default - // middlewares. - if (splitPath[1] === '_oauth_apps') { - provider = splitPath[2]; - app = splitPath && splitPath[3] !== 'callback' ? splitPath[3] : null; - } - - return { - provider, - app - }; +function parseUrl(url, config) { + return url.replace(/\{[\ ]*(provider|accessToken|refreshToken|error)[\ ]*\}/g, (_, key) => config[key]); } -function getAccessToken(req) { - const i = req.url.indexOf('?'); +function getAppConfig(providerName, appName) { + const providerConfig = Settings.get(providerName); - if (i === -1) { - return; - } - - const barePath = req.url.substring(i + 1); - const splitPath = barePath.split('&'); - const token = splitPath.find(p => p.match(/access_token=[a-zA-Z0-9]+/)); - - if (token) { - return token.replace('access_token=', ''); + if (providerConfig) { + return Settings.apps.get(appName); } } -export function middleware(req, res, next) { - const { - provider, - app - } = getEntry(req); - - if (!provider || !app) { - next(); - return; - } - - console.log('provider', provider); - console.log('app', app); - - // handle providers and apps - if (provider === 'github' && app === 'pwa') { - const token = getAccessToken(req); - console.log('token', token); - - // TODO: get redirect URL from settings - const redirectUrl = 'http://localhost:4200/login'; - - res.redirect(`${ redirectUrl }?service=${ provider }&access_token=${ token }`); +export async function middleware(req, res, next) { + const route = routes.appCallback(req); + + // handle app callback + if (route) { + const config = { + provider: route.provider + }; + const appConfig = getAppConfig(route.provider, route.app); + + if (appConfig) { + const { + redirectUrl, + errorUrl + } = appConfig; + + try { + const tokens = await authenticate(route.provider, req); + + config.accessToken = tokens.accessToken; + config.refreshToken = tokens.refreshToken; + + res.redirect(parseUrl(redirectUrl, config)); + return; + } catch (error) { + config.error = error.message; + res.redirect(parseUrl(errorUrl, config)); + return; + } + } } next(); diff --git a/packages/rocketchat-grant/server/routes.js b/packages/rocketchat-grant/server/routes.js new file mode 100644 index 000000000000..041156f2abca --- /dev/null +++ b/packages/rocketchat-grant/server/routes.js @@ -0,0 +1,48 @@ +export const path = '/_oauth_apps'; + +export function generateCallback(providerName) { + return `${ path }/${ providerName }/callback`; +} + +export function generateAppCallback(providerName, appName) { + return generateCallback(`${ providerName }/${ appName }`); +} + +export function getPaths(req) { + const i = req.url.indexOf('?'); + let barePath; + + if (i === -1) { + barePath = req.url; + } else { + barePath = req.url.substring(0, i); + } + + const splitPath = barePath.split('/'); + + // Any non-oauth request will continue down the default + // middlewares. + if (splitPath[1] === '_oauth_apps') { + return splitPath.slice(2); + } +} + +export const routes = { + // :path/:provider/:app/callback + appCallback: (req) => { + const paths = getPaths(req); + + if (paths && paths[2] === 'callback') { + return { + provider: paths[0], + app: paths[1] + }; + } + }, + // :path/providers + providers: (req) => { + const paths = getPaths(req); + + return paths && paths[0] === 'providers'; + } +}; diff --git a/packages/rocketchat-grant/server/settings.js b/packages/rocketchat-grant/server/settings.js new file mode 100644 index 000000000000..e53b466fa87f --- /dev/null +++ b/packages/rocketchat-grant/server/settings.js @@ -0,0 +1,42 @@ +import { check } from 'meteor/check'; + +import { Storage } from './storage'; + +class Apps extends Storage { + add(name, body) { + check(name, String); + check(body, { + redirectUrl: String, + errorUrl: String + }); + + this._add(name, body); + } +} + +class Settings extends Storage { + constructor() { + super(); + + this.apps = new Apps; + } + add(settings) { + check(settings, { + enabled: Match.Optional(Boolean), + provider: String, + key: String, + secret: String + }); + + this._add(settings.provider, { + enabled: settings.enabled === true, + provider: settings.provider, + key: settings.key, + secret: settings.secret + }); + } +} + +const settings = new Settings; + +export default settings; diff --git a/packages/rocketchat-grant/server/storage.js b/packages/rocketchat-grant/server/storage.js new file mode 100644 index 000000000000..90d506681a83 --- /dev/null +++ b/packages/rocketchat-grant/server/storage.js @@ -0,0 +1,33 @@ +export class Storage { + constructor() { + this._data = {}; + } + + all() { + return this._data; + } + + forEach(fn) { + Object.keys(this.all()) + .forEach((name) => { + fn(this.get(name), name); + }); + } + + get(name) { + return this.all()[name.toLowerCase()]; + } + + has(name) { + return !!this._data[name]; + } + + _add(name, body) { + if (this.has(name)) { + console.error(`'${ name }' have been already defined`); + return; + } + + this._data[name] = body; + } +} diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json index 13032f7d6a0d..482cfcaf4242 100644 --- a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -71,8 +71,8 @@ "from": "cookie-signature@1.0.6" }, "core-js": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", "from": "core-js@>=2.4.0 <3.0.0" }, "cors": { @@ -218,16 +218,9 @@ "from": "hoek@>=2.0.0 <3.0.0" }, "http-errors": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", - "from": "http-errors@>=1.6.1 <1.7.0", - "dependencies": { - "depd": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", - "from": "depd@1.1.0" - } - } + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "from": "http-errors@>=1.6.1 <1.7.0" }, "iconv-lite": { "version": "0.4.15", diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js index 24f1b58779af..1fbde6720c12 100644 --- a/packages/rocketchat-graphql/package.js +++ b/packages/rocketchat-graphql/package.js @@ -9,6 +9,7 @@ Package.onUse(function(api) { api.use([ 'underscore', 'ecmascript', + 'http', 'rocketchat:lib', 'rocketchat:api', 'rocketchat:accounts' diff --git a/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.js b/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.js new file mode 100644 index 000000000000..dd4a4253fd37 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.js @@ -0,0 +1,5 @@ +export const schema = ` + type OauthProvider { + name: String! + } +`; diff --git a/packages/rocketchat-graphql/server/schemas/accounts/index.js b/packages/rocketchat-graphql/server/schemas/accounts/index.js index cf41ed398f04..e82a7077059b 100644 --- a/packages/rocketchat-graphql/server/schemas/accounts/index.js +++ b/packages/rocketchat-graphql/server/schemas/accounts/index.js @@ -1,8 +1,21 @@ import { createJSAccountsGraphQL } from '@accounts/graphql-api'; import { AccountsServer } from 'meteor/rocketchat:accounts'; +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; + +// queries +import * as oauthProviders from './oauthProviders'; +// types +import * as OauthProviderType from './OauthProvider-type'; const accountsGraphQL = createJSAccountsGraphQL(AccountsServer); -export const schema = accountsGraphQL.schema; +export const schema = mergeTypes([ + accountsGraphQL.schema, + oauthProviders.schema, + OauthProviderType.schema +]); -export const resolvers = accountsGraphQL.extendWithResolvers({}); +export const resolvers = mergeResolvers([ + accountsGraphQL.extendWithResolvers({}), + oauthProviders.resolver +]); diff --git a/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js new file mode 100644 index 000000000000..270f17a355b7 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js @@ -0,0 +1,41 @@ +import { HTTP } from 'meteor/http'; +import { Meteor } from 'meteor/meteor'; + +function isJSON(obj) { + try { + JSON.parse(obj); + return true; + } catch (e) { + return false; + } +} + +export const schema = ` + type Query { + oauthProviders: [OauthProvider] + } +`; + +export const resolver = { + Query: { + oauthProviders: async() => { + // depends on rocketchat:grant package + try { + const url = Meteor.absoluteUrl('_oauth_apps/providers'); + console.log('url', url); + const result = HTTP.get(Meteor.absoluteUrl('_oauth_apps/providers')).content; + + if (isJSON(result)) { + const providers = JSON.parse(result).data; + + return providers.map((name) => ({ name })); + } else { + throw new Error('Could not parse the result'); + } + } catch (e) { + console.error('oauthProviders resolver', e); + throw new Error('rocketchat:grant not installed'); + } + } + } +}; diff --git a/server/configuration/grant.js b/server/configuration/grant.js new file mode 100644 index 000000000000..f12a59c300be --- /dev/null +++ b/server/configuration/grant.js @@ -0,0 +1,27 @@ +import { Settings } from 'meteor/rocketchat:grant'; + +Settings.add({ + enabled: true, + provider: 'github', + key: '96db2753350cfe8c8ae1', + secret: '546317a561df5e3d350fca9b5500f270b54f3301' +}); + +Settings.add({ + enabled: true, + provider: 'facebook', + key: '494859557516801', + secret: '5274d3495cebaf01f7e1b90fe1331fba' +}); + +Settings.add({ + enabled: true, + provider: 'google', + key: '979285364697-pob8soqche90ng1af0pj9if6ed69jalh.apps.googleusercontent.com', + secret: 'lFWtrtJngtlNBdrAoevwPjZh' +}); + +Settings.apps.add('pwa', { + redirectUrl: 'http://localhost:4200/login?service={provider}&access_token={accessToken}&refresh_token={refreshToken}', + errorUrl: 'http://localhost:4200/login?service={provider}&error={error}' +}); From e6e9b1be357ea044b80934f9170bc15e3fff2f4d Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Wed, 9 Aug 2017 18:51:43 +0200 Subject: [PATCH 084/801] Moar --- .../rocketchat-grant-facebook/server/index.js | 19 +++++-------------- .../rocketchat-grant-github/server/index.js | 15 ++++++--------- .../rocketchat-grant-google/server/index.js | 13 ++++--------- .../rocketchat-grant/server/authenticate.js | 13 +++++++++---- packages/rocketchat-grant/server/error.js | 5 +++++ packages/rocketchat-grant/server/index.js | 4 +++- packages/rocketchat-grant/server/redirect.js | 6 +++++- .../server/schemas/messages/Message-type.js | 2 ++ .../server/schemas/messages/messages.js | 7 ++++++- 9 files changed, 45 insertions(+), 39 deletions(-) create mode 100644 packages/rocketchat-grant/server/error.js diff --git a/packages/rocketchat-grant-facebook/server/index.js b/packages/rocketchat-grant-facebook/server/index.js index 882ef18ac129..7dc87f6494f9 100644 --- a/packages/rocketchat-grant-facebook/server/index.js +++ b/packages/rocketchat-grant-facebook/server/index.js @@ -1,4 +1,4 @@ -import { Providers } from 'meteor/rocketchat:grant'; +import { Providers, GrantError } from 'meteor/rocketchat:grant'; import { HTTP } from 'meteor/http'; const userAgent = 'Meteor'; @@ -15,11 +15,7 @@ function getIdentity(accessToken, fields) { } }).data; } catch (err) { - console.log('err', err); - throw Object.assign( - new Error(`Failed to fetch identity from Facebook. ${ err.message }`), - { response: err.response } - ); + throw new GrantError(`Failed to fetch identity from Facebook. ${ err.message }`); } } @@ -37,10 +33,7 @@ function getPicture(accessToken) { } }).data; } catch (err) { - throw Object.assign( - new Error(`Failed to fetch profile picture from Facebook. ${ err.message }`), - { response: err.response } - ); + throw new GrantError(`Failed to fetch profile picture from Facebook. ${ err.message }`); } } @@ -54,10 +47,8 @@ export function getUser(accessToken) { id: identity.id, email: identity.email, username, - profile: { - name: `${ identity.first_name } ${ identity.last_name }`, - avatar: avatar.data.url - } + name: `${ identity.first_name } ${ identity.last_name }`, + avatar: avatar.data.url }; } diff --git a/packages/rocketchat-grant-github/server/index.js b/packages/rocketchat-grant-github/server/index.js index 4359fe07754b..2d82479b7e09 100644 --- a/packages/rocketchat-grant-github/server/index.js +++ b/packages/rocketchat-grant-github/server/index.js @@ -1,4 +1,4 @@ -import { Providers } from 'meteor/rocketchat:grant'; +import { Providers, GrantError } from 'meteor/rocketchat:grant'; import { HTTP } from 'meteor/http'; const userAgent = 'Meteor'; @@ -11,10 +11,7 @@ function getIdentity(accessToken) { params: { access_token: accessToken } }).data; } catch (err) { - throw Object.assign( - new Error(`Failed to fetch identity from Github. ${ err.message }`), - { response: err.response } - ); + throw new GrantError(`Failed to fetch identity from Github. ${ err.message }`); } } @@ -35,15 +32,15 @@ export function getUser(accessToken) { const emails = getEmails(accessToken); const primaryEmail = (emails || []).find(email => email.primary === true); + console.log('identity', identity); + return { id: identity.id, email: identity.email || (primaryEmail && primaryEmail.email) || '', username: identity.login, emails, - profile: { - name: identity.name, - avatar: identity.avatar_url - } + name: identity.name, + avatar: identity.avatar_url }; } diff --git a/packages/rocketchat-grant-google/server/index.js b/packages/rocketchat-grant-google/server/index.js index 5cc545c18cda..f1cf2ae853a6 100644 --- a/packages/rocketchat-grant-google/server/index.js +++ b/packages/rocketchat-grant-google/server/index.js @@ -1,4 +1,4 @@ -import { Providers } from 'meteor/rocketchat:grant'; +import { Providers, GrantError } from 'meteor/rocketchat:grant'; import { HTTP } from 'meteor/http'; const userAgent = 'Meteor'; @@ -13,10 +13,7 @@ function getIdentity(accessToken) { } }).data; } catch (err) { - throw Object.assign( - new Error(`Failed to fetch identity from Google. ${ err.message }`), - { response: err.response } - ); + throw new GrantError(`Failed to fetch identity from Google. ${ err.message }`); } } @@ -32,10 +29,8 @@ export function getUser(accessToken) { id: identity.id, email: identity.email, username, - profile: { - name: identity.name, - avatar: identity.picture - } + name: identity.name, + avatar: identity.picture }; } diff --git a/packages/rocketchat-grant/server/authenticate.js b/packages/rocketchat-grant/server/authenticate.js index bf2512d1f1aa..33544467875b 100644 --- a/packages/rocketchat-grant/server/authenticate.js +++ b/packages/rocketchat-grant/server/authenticate.js @@ -1,6 +1,7 @@ import { AccountsServer } from 'meteor/rocketchat:accounts'; import { Accounts } from 'meteor/accounts-base'; +import { GrantError } from './error'; import Providers from './providers'; const findUserByOAuthId = (providerName, id) => { @@ -40,11 +41,13 @@ export async function authenticate(providerName, req) { const provider = Providers.get(providerName); if (!provider) { - throw new Error(`Provider '${ providerName }' not found`); + throw new GrantError(`Provider '${ providerName }' not found`); } const userData = provider.getUser(accessToken); + console.log('userData', userData); + let user = findUserByOAuthId(providerName, userData.id); if (user) { @@ -64,17 +67,19 @@ export async function authenticate(providerName, req) { tokens = loginResult.tokens; } else { const id = Accounts.createUser({ - email: userData.email + email: userData.email, + username: userData.username }); RocketChat.models.Users.setProfile(id, { - name: userData.profile.name, - avatar: userData.profile.avatar, + avatar: userData.avatar, oauth: { [providerName]: userData.id } }); + RocketChat.models.Users.setName(id, userData.name); + const loginResult = await AccountsServer.loginWithUser({ id }); tokens = loginResult.tokens; diff --git a/packages/rocketchat-grant/server/error.js b/packages/rocketchat-grant/server/error.js new file mode 100644 index 000000000000..16ab38913db8 --- /dev/null +++ b/packages/rocketchat-grant/server/error.js @@ -0,0 +1,5 @@ +export class GrantError extends Error { + constructor(...args) { + super(...args); + } +} diff --git a/packages/rocketchat-grant/server/index.js b/packages/rocketchat-grant/server/index.js index fc06ae57ba3a..5aec92218200 100644 --- a/packages/rocketchat-grant/server/index.js +++ b/packages/rocketchat-grant/server/index.js @@ -3,6 +3,7 @@ import session from 'express-session'; import Grant from 'grant-express'; import fiber from 'fibers'; +import { GrantError } from './error'; import { generateConfig } from './grant'; import { path, generateCallback, generateAppCallback } from './routes'; import { middleware as redirect } from './redirect'; @@ -51,5 +52,6 @@ export { generateCallback, generateAppCallback, Providers, - Settings + Settings, + GrantError }; diff --git a/packages/rocketchat-grant/server/redirect.js b/packages/rocketchat-grant/server/redirect.js index 25faad1e1ca9..2423758f48ca 100644 --- a/packages/rocketchat-grant/server/redirect.js +++ b/packages/rocketchat-grant/server/redirect.js @@ -1,6 +1,7 @@ import { authenticate } from './authenticate'; import Settings from './settings'; import { routes } from './routes'; +import { GrantError } from './error'; function parseUrl(url, config) { return url.replace(/\{[\ ]*(provider|accessToken|refreshToken|error)[\ ]*\}/g, (_, key) => config[key]); @@ -39,7 +40,10 @@ export async function middleware(req, res, next) { res.redirect(parseUrl(redirectUrl, config)); return; } catch (error) { - config.error = error.message; + config.error = error instanceof GrantError ? error.message : 'Something went wrong'; + + console.error(error); + res.redirect(parseUrl(errorUrl, config)); return; } diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js index 09204793acf7..b1234eb9a574 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js @@ -9,6 +9,7 @@ export const schema = ` channel: Channel creationTime: Float fromServer: Boolean + type: String userRef: [User] channelRef: [Channel] reactions: [Reaction] @@ -29,6 +30,7 @@ export const resolver = { return RocketChat.models.Rooms.findOne(root.rid); }, fromServer: (root) => typeof root.t !== 'undefined', // on a message sent by user `true` otherwise `false` + type: property('t'), channelRef: (root) => { if (!root.channels) { return; diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.js b/packages/rocketchat-graphql/server/schemas/messages/messages.js index ad8bb24cdfed..b47062932e96 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/messages.js +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.js @@ -8,7 +8,8 @@ export const schema = ` channelName: String, cursor: String, count: Int, - searchRegex: String + searchRegex: String, + excludeServer: Boolean ): MessagesWithCursor } `; @@ -59,6 +60,10 @@ export const resolver = { messagesOptions.limit = args.count; } + if (args.excludeServer === true) { + messagesQuery.t = { $exists: false }; + } + const messages = RocketChat.models.Messages.find( Object.assign({}, messagesQuery, { rid: channel._id }), messagesOptions From 09157fe1d5a33ea3be7cd66310560847d379c746 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Wed, 9 Aug 2017 19:04:17 +0200 Subject: [PATCH 085/801] Remove console.logs and set email as verified --- packages/rocketchat-grant-github/server/index.js | 2 -- packages/rocketchat-grant/server/authenticate.js | 4 +--- .../server/schemas/accounts/oauthProviders.js | 2 -- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/rocketchat-grant-github/server/index.js b/packages/rocketchat-grant-github/server/index.js index 2d82479b7e09..1358986420c3 100644 --- a/packages/rocketchat-grant-github/server/index.js +++ b/packages/rocketchat-grant-github/server/index.js @@ -32,8 +32,6 @@ export function getUser(accessToken) { const emails = getEmails(accessToken); const primaryEmail = (emails || []).find(email => email.primary === true); - console.log('identity', identity); - return { id: identity.id, email: identity.email || (primaryEmail && primaryEmail.email) || '', diff --git a/packages/rocketchat-grant/server/authenticate.js b/packages/rocketchat-grant/server/authenticate.js index 33544467875b..305ff3ad37c6 100644 --- a/packages/rocketchat-grant/server/authenticate.js +++ b/packages/rocketchat-grant/server/authenticate.js @@ -46,8 +46,6 @@ export async function authenticate(providerName, req) { const userData = provider.getUser(accessToken); - console.log('userData', userData); - let user = findUserByOAuthId(providerName, userData.id); if (user) { @@ -77,8 +75,8 @@ export async function authenticate(providerName, req) { [providerName]: userData.id } }); - RocketChat.models.Users.setName(id, userData.name); + RocketChat.models.Users.setEmailVerified(id, userData.email); const loginResult = await AccountsServer.loginWithUser({ id }); diff --git a/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js index 270f17a355b7..9cefedb7a15e 100644 --- a/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js +++ b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js @@ -21,8 +21,6 @@ export const resolver = { oauthProviders: async() => { // depends on rocketchat:grant package try { - const url = Meteor.absoluteUrl('_oauth_apps/providers'); - console.log('url', url); const result = HTTP.get(Meteor.absoluteUrl('_oauth_apps/providers')).content; if (isJSON(result)) { From 4d5e0b616dc2341bdd3806039c153c08e9fb6754 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Thu, 17 Aug 2017 16:09:56 +0200 Subject: [PATCH 086/801] Implemented saving avatars properly and fixed messages sorting (DESC `ts`) --- .../rocketchat-grant/server/authenticate.js | 23 +++++++++++++++++++ .../server/schemas/messages/Message-type.js | 4 +++- .../server/schemas/messages/messages.js | 2 +- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-grant/server/authenticate.js b/packages/rocketchat-grant/server/authenticate.js index 305ff3ad37c6..ad68fb009681 100644 --- a/packages/rocketchat-grant/server/authenticate.js +++ b/packages/rocketchat-grant/server/authenticate.js @@ -1,9 +1,30 @@ import { AccountsServer } from 'meteor/rocketchat:accounts'; import { Accounts } from 'meteor/accounts-base'; +import { Meteor } from 'meteor/meteor'; import { GrantError } from './error'; import Providers from './providers'; +const setAvatarFromUrl = (userId, url) => { + return new Promise((resolve, reject) => { + Meteor.runAsUser(userId, () => { + Meteor.call('setAvatarFromService', url, '', 'url', (err) => { + if (err) { + if (err.details.timeToReset && err.details.timeToReset) { + reject((t('error-too-many-requests', { + seconds: parseInt(err.details.timeToReset / 1000) + }))); + } else { + reject(t('Avatar_url_invalid_or_error')); + } + } else { + resolve(); + } + }); + }); + }); +}; + const findUserByOAuthId = (providerName, id) => { return RocketChat.models.Users.findOne({ [`settings.profile.oauth.${ providerName }`]: id }); }; @@ -78,6 +99,8 @@ export async function authenticate(providerName, req) { RocketChat.models.Users.setName(id, userData.name); RocketChat.models.Users.setEmailVerified(id, userData.email); + await setAvatarFromUrl(id, userData.avatar); + const loginResult = await AccountsServer.loginWithUser({ id }); tokens = loginResult.tokens; diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js index b1234eb9a574..177a84bd213c 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js @@ -24,7 +24,9 @@ export const resolver = { content: property('msg'), creationTime: (root) => dateToFloat(root.ts), author: (root) => { - return RocketChat.models.Users.findOne(root.u._id); + const user = RocketChat.models.Users.findOne(root.u._id); + + return user || root.u; }, channel: (root) => { return RocketChat.models.Rooms.findOne(root.rid); diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.js b/packages/rocketchat-graphql/server/schemas/messages/messages.js index b47062932e96..8083d2fa6fdf 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/messages.js +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.js @@ -19,7 +19,7 @@ export const resolver = { messages: authenticated((root, args) => { const messagesQuery = {}; const messagesOptions = { - sort: { ts: 1 } + sort: { ts: -1 } }; const channelQuery = {}; const isPagination = !!args.cursor || args.count > 0; From f90e302a15efa0fe6b5dbc6c1ceb91fb6f3e9193 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Tue, 29 Aug 2017 11:40:38 +0200 Subject: [PATCH 087/801] Use findOneByRoomIdAndUserId instead of custom one --- .../server/helpers/findChannelByIdAndUser.js | 8 -------- .../server/schemas/channels/Channel-type.js | 17 ++--------------- 2 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 packages/rocketchat-graphql/server/helpers/findChannelByIdAndUser.js diff --git a/packages/rocketchat-graphql/server/helpers/findChannelByIdAndUser.js b/packages/rocketchat-graphql/server/helpers/findChannelByIdAndUser.js deleted file mode 100644 index b36f972203e6..000000000000 --- a/packages/rocketchat-graphql/server/helpers/findChannelByIdAndUser.js +++ /dev/null @@ -1,8 +0,0 @@ -export function findChannelByIdAndUser({ params, options = {} }) { - const sub = RocketChat.models.Subscriptions.findOne({ - rid: params.roomId, - 'u._id': params.userId - }, options); - - return sub; -} diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js index b980acad0f7b..cfcbebe2a327 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js +++ b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js @@ -1,5 +1,4 @@ import { property } from '../../helpers/property'; -import { findChannelByIdAndUser } from '../../helpers/findChannelByIdAndUser'; export const schema = ` type Channel { @@ -49,24 +48,12 @@ export const resolver = { direct: (root) => root.t === 'd', privateChannel: (root) => root.t === 'p', favourite: (root, args, { user }) => { - const room = findChannelByIdAndUser({ - params: { - roomId: root._id, - userId: user._id - }, - options: { fields: { f: 1 }} - }); + const room = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(root._id, user._id); return room && room.f === true; }, unseenMessages: (root, args, { user }) => { - const room = findChannelByIdAndUser({ - params: { - roomId: root._id, - userId: user._id - }, - options: { fields: { unread: 1 }} - }); + const room = RocketChat.models.Subscriptions.findOneByRoomIdAndUserId(root._id, user._id); return (room || {}).unread; } From c522dd9a5262fe17fee22f3656df97becf4eb0fa Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Tue, 29 Aug 2017 13:00:43 +0200 Subject: [PATCH 088/801] Update deps in rocketchat:graphql --- packages/rocketchat-graphql/package.js | 13 ++++++------- packages/rocketchat-graphql/server/api.js | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js index 1fbde6720c12..b4ceb319ed9b 100644 --- a/packages/rocketchat-graphql/package.js +++ b/packages/rocketchat-graphql/package.js @@ -20,14 +20,13 @@ Package.onUse(function(api) { Npm.depends({ '@accounts/graphql-api': '0.1.1', - 'apollo-client': '1.6.0', - 'cors': '2.8.3', + 'apollo-server-express': '1.1.2', + 'cors': '2.8.4', 'body-parser': '1.17.2', - 'express': '4.15.3', + 'express': '4.15.4', 'graphql': '0.10.3', - 'graphql-server-express': '0.9.0', 'graphql-subscriptions': '0.4.4', - 'graphql-tools': '1.1.0', - 'merge-graphql-schemas': '1.1.0', - 'subscriptions-transport-ws': '0.8.1' + 'graphql-tools': '1.2.2', + 'merge-graphql-schemas': '1.1.2', + 'subscriptions-transport-ws': '0.8.2' }); diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index 7a82b6acec00..a8262a0d33f4 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -1,4 +1,4 @@ -import { graphqlExpress, graphiqlExpress } from 'graphql-server-express'; +import { graphqlExpress, graphiqlExpress } from 'apollo-server-express'; import { JSAccountsContext as jsAccountsContext } from '@accounts/graphql-api'; import { SubscriptionServer } from 'subscriptions-transport-ws'; import { execute, subscribe } from 'graphql'; From 7a6bce9317cd0d9b22fce4c192fe8d0d4b5a80be Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Tue, 29 Aug 2017 13:03:54 +0200 Subject: [PATCH 089/801] Add comments on the schema about meaning of the types --- .../rocketchat-graphql/server/schemas/messages/Message-type.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js index 177a84bd213c..b6567e26f40c 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js @@ -8,9 +8,12 @@ export const schema = ` content: String channel: Channel creationTime: Float + # Message sent by server e.g. User joined channel fromServer: Boolean type: String + # List of mentioned users userRef: [User] + # list of mentioned channels channelRef: [Channel] reactions: [Reaction] # TODO From eac0aac4793e37b2e49459038eaf7127bf573ecb Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Tue, 29 Aug 2017 13:06:44 +0200 Subject: [PATCH 090/801] Remove unnecessary return statement --- packages/rocketchat-graphql/server/schemas/users/User-type.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/rocketchat-graphql/server/schemas/users/User-type.js b/packages/rocketchat-graphql/server/schemas/users/User-type.js index 34978665bcdb..3891f47e1d65 100644 --- a/packages/rocketchat-graphql/server/schemas/users/User-type.js +++ b/packages/rocketchat-graphql/server/schemas/users/User-type.js @@ -25,7 +25,6 @@ export const resolver = { if (avatar) { return avatar.url; } - return; }, channels: ({ _id }) => { return RocketChat.models.Rooms.findBySubscriptionUserId(_id).fetch(); From 10e4b273fe0982a06ffdf00d2c1db90590663d92 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Tue, 29 Aug 2017 13:07:36 +0200 Subject: [PATCH 091/801] Remove unused todos from Message type --- .../server/schemas/messages/Message-type.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js index b6567e26f40c..264ef427390b 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.js @@ -16,8 +16,6 @@ export const schema = ` # list of mentioned channels channelRef: [Channel] reactions: [Reaction] - # TODO - tags: [String] } `; @@ -83,8 +81,6 @@ export const resolver = { }); return reactions; - }, - // TODO - tags: () => {} + } } }; From 0fff6a00712d0574e4ef332e794dde5b4f0892f3 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Thu, 31 Aug 2017 16:59:33 +0200 Subject: [PATCH 092/801] READMEs, separate schema from resolvers, fix sorting and cursor messages resolver, graphql.config.json --- .meteor/versions | 1 + graphql.config.json | 9 + .../.npm/package/npm-shrinkwrap.json | 45 ++- packages/rocketchat-accounts/package.js | 3 +- packages/rocketchat-accounts/server/fix.js | 3 - packages/rocketchat-accounts/server/index.js | 2 +- packages/rocketchat-api/server/v1/channels.js | 93 +++-- packages/rocketchat-grant-facebook/README.md | 3 + packages/rocketchat-grant-github/README.md | 3 + packages/rocketchat-grant-google/README.md | 3 + packages/rocketchat-grant/README.md | 109 +++++- packages/rocketchat-grant/server/providers.js | 1 - .../.npm/package/npm-shrinkwrap.json | 337 +++++++++--------- packages/rocketchat-graphql/README.md | 3 + packages/rocketchat-graphql/package.js | 7 +- packages/rocketchat-graphql/server/api.js | 2 +- .../server/helpers/authenticated.js | 2 +- .../server/mocks/accounts/graphql-api.js | 10 - .../server/mocks/accounts/server.js | 13 - .../resolvers/accounts/OauthProvider-type.js | 5 + .../{schemas => resolvers}/accounts/index.js | 4 +- .../accounts/oauthProviders.js | 16 +- .../channels/Channel-type.js | 27 +- .../resolvers/channels/ChannelFilter-input.js | 5 + .../channels/ChannelNameAndDirect-input.js | 5 + .../resolvers/channels/ChannelSort-enum.js | 5 + .../server/resolvers/channels/Privacy-enum.js | 5 + .../channels/channelByName.js | 14 +- .../channels/channels.js | 22 +- .../channels/channelsByUser.js | 16 +- .../resolvers/channels/createChannel.js | 38 ++ .../channels/directChannel.js | 15 +- .../channels/hideChannel.js | 14 +- .../{schemas => resolvers}/channels/index.js | 2 +- .../channels/leaveChannel.js | 14 +- .../channels/settings.js | 0 .../messages/Message-type.js | 26 +- .../messages/MessageIdentifier-input.js | 5 + .../messages/MessagesWithCursor-type.js | 5 + .../resolvers/messages/Reaction-type.js | 5 + .../messages/addReactionToMessage.js | 14 +- .../messages/chatMessageAdded.js | 14 +- .../messages/deleteMessage.js | 14 +- .../messages/editMessage.js | 14 +- .../{schemas => resolvers}/messages/index.js | 2 +- .../messages/messages.js | 43 ++- .../messages/sendMessage.js | 14 +- .../{schemas => resolvers}/users/User-type.js | 23 +- .../server/resolvers/users/UserStatus-enum.js | 5 + .../{schemas => resolvers}/users/index.js | 2 +- .../{schemas => resolvers}/users/setStatus.js | 14 +- packages/rocketchat-graphql/server/schema.js | 15 +- .../schemas/accounts/LoginResult-type.graphql | 4 + .../schemas/accounts/LoginResult-type.js | 6 - .../accounts/OauthProvider-type.graphql | 3 + .../schemas/accounts/OauthProvider-type.js | 5 - .../schemas/accounts/oauthProviders.graphql | 3 + .../schemas/channels/Channel-type.graphql | 16 + .../channels/ChannelFilter-input.graphql | 6 + .../schemas/channels/ChannelFilter-input.js | 8 - .../ChannelNameAndDirect-input.graphql | 4 + .../channels/ChannelNameAndDirect-input.js | 6 - .../schemas/channels/ChannelSort-enum.graphql | 4 + .../schemas/channels/ChannelSort-enum.js | 6 - .../schemas/channels/Privacy-enum.graphql | 5 + .../server/schemas/channels/Privacy-enum.js | 7 - .../schemas/channels/channelByName.graphql | 3 + .../server/schemas/channels/channels.graphql | 7 + .../schemas/channels/channelsByUser.graphql | 3 + .../schemas/channels/createChannel.graphql | 8 + .../server/schemas/channels/createChannel.js | 45 --- .../schemas/channels/directChannel.graphql | 3 + .../schemas/channels/hideChannel.graphql | 3 + .../schemas/channels/leaveChannel.graphql | 3 + .../schemas/messages/Message-type.graphql | 15 + .../messages/MessageIdentifier-input.graphql | 4 + .../messages/MessageIdentifier-input.js | 6 - .../messages/MessagesWithCursor-type.graphql | 5 + .../messages/MessagesWithCursor-type.js | 7 - .../schemas/messages/Reaction-type.graphql | 4 + .../server/schemas/messages/Reaction-type.js | 6 - .../messages/addReactionToMessage.graphql | 3 + .../schemas/messages/chatMessageAdded.graphql | 3 + .../schemas/messages/deleteMessage.graphql | 3 + .../schemas/messages/editMessage.graphql | 3 + .../server/schemas/messages/messages.graphql | 11 + .../schemas/messages/sendMessage.graphql | 3 + .../server/schemas/users/User-type.graphql | 8 + .../schemas/users/UserStatus-enum.graphql | 7 + .../server/schemas/users/UserStatus-enum.js | 9 - .../server/schemas/users/setStatus.graphql | 3 + 91 files changed, 778 insertions(+), 551 deletions(-) create mode 100644 graphql.config.json delete mode 100644 packages/rocketchat-accounts/server/fix.js create mode 100644 packages/rocketchat-grant-facebook/README.md create mode 100644 packages/rocketchat-grant-github/README.md create mode 100644 packages/rocketchat-grant-google/README.md create mode 100644 packages/rocketchat-graphql/README.md delete mode 100644 packages/rocketchat-graphql/server/mocks/accounts/server.js create mode 100644 packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js rename packages/rocketchat-graphql/server/{schemas => resolvers}/accounts/index.js (76%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/accounts/oauthProviders.js (80%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/Channel-type.js (75%) create mode 100644 packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js create mode 100644 packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js create mode 100644 packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js create mode 100644 packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/channelByName.js (73%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/channels.js (80%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/channelsByUser.js (78%) create mode 100644 packages/rocketchat-graphql/server/resolvers/channels/createChannel.js rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/directChannel.js (84%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/hideChannel.js (87%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/index.js (93%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/leaveChannel.js (81%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/channels/settings.js (100%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/messages/Message-type.js (78%) create mode 100644 packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js create mode 100644 packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js create mode 100644 packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js rename packages/rocketchat-graphql/server/{schemas => resolvers}/messages/addReactionToMessage.js (74%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/messages/chatMessageAdded.js (83%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/messages/deleteMessage.js (83%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/messages/editMessage.js (85%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/messages/index.js (93%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/messages/messages.js (66%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/messages/sendMessage.js (75%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/users/User-type.js (65%) create mode 100644 packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js rename packages/rocketchat-graphql/server/{schemas => resolvers}/users/index.js (82%) rename packages/rocketchat-graphql/server/{schemas => resolvers}/users/setStatus.js (73%) create mode 100644 packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/channelByName.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/channels/channels.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/channels/createChannel.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/channels/createChannel.js create mode 100644 packages/rocketchat-graphql/server/schemas/channels/directChannel.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/Message-type.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/messages/Reaction-type.js create mode 100644 packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/editMessage.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/messages.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/users/User-type.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphql delete mode 100644 packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.js create mode 100644 packages/rocketchat-graphql/server/schemas/users/setStatus.graphql diff --git a/.meteor/versions b/.meteor/versions index e178545da53a..c608ae9d789f 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -246,6 +246,7 @@ spacebars-compiler@1.1.3 srp@1.0.10 standard-minifier-js@2.1.1 steffo:meteor-accounts-saml@0.0.1 +swydo:graphql@0.0.3 tap:i18n@1.8.2 templating@1.3.2 templating-compiler@1.3.2 diff --git a/graphql.config.json b/graphql.config.json new file mode 100644 index 000000000000..2c316a3dbb9f --- /dev/null +++ b/graphql.config.json @@ -0,0 +1,9 @@ +{ + "schema": { + "request": { + "url" : "http://localhost:3000/graphql", + "method" : "POST", + "postIntrospectionQuery" : true + } + } +} diff --git a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json index 548e1696bac6..720452518c3b 100644 --- a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json @@ -6,14 +6,21 @@ "from": "addressparser@>=0.3.2 <0.4.0" }, "babel-polyfill": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", "from": "babel-polyfill@>=6.23.0 <7.0.0" }, "babel-runtime": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", - "from": "babel-runtime@>=6.22.0 <7.0.0" + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "from": "babel-runtime@>=6.26.0 <7.0.0", + "dependencies": { + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "from": "regenerator-runtime@>=0.11.0 <0.12.0" + } + } }, "base64url": { "version": "2.0.0", @@ -48,7 +55,7 @@ "core-js": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", - "from": "core-js@>=2.4.0 <3.0.0" + "from": "core-js@>=2.5.0 <3.0.0" }, "core-util-is": { "version": "1.0.2", @@ -66,8 +73,8 @@ "from": "ecdsa-sig-formatter@1.0.9" }, "emailjs": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/emailjs/-/emailjs-1.0.11.tgz", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/emailjs/-/emailjs-1.0.12.tgz", "from": "emailjs@>=1.0.8 <2.0.0" }, "encoding": { @@ -111,8 +118,8 @@ "from": "joi@>=6.10.1 <7.0.0" }, "jsonwebtoken": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.2.tgz", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz", "from": "jsonwebtoken@>=7.2.1 <8.0.0" }, "jwa": { @@ -153,19 +160,19 @@ } }, "moment": { - "version": "2.11.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.11.2.tgz", - "from": "moment@2.11.2" + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.15.2.tgz", + "from": "moment@2.15.2" }, "mongodb": { - "version": "2.2.30", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.30.tgz", + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.31.tgz", "from": "mongodb@>=2.2.22 <3.0.0" }, "mongodb-core": { - "version": "2.1.14", - "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.14.tgz", - "from": "mongodb-core@2.1.14" + "version": "2.1.15", + "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.15.tgz", + "from": "mongodb-core@2.1.15" }, "ms": { "version": "2.0.0", @@ -185,7 +192,7 @@ "regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "from": "regenerator-runtime@>=0.10.0 <0.11.0" + "from": "regenerator-runtime@>=0.10.5 <0.11.0" }, "require_optional": { "version": "1.0.1", diff --git a/packages/rocketchat-accounts/package.js b/packages/rocketchat-accounts/package.js index fd29a0c2ebae..777c614620ba 100644 --- a/packages/rocketchat-accounts/package.js +++ b/packages/rocketchat-accounts/package.js @@ -18,6 +18,5 @@ Package.onUse(function(api) { Npm.depends({ '@accounts/server': '0.0.18', - '@accounts/mongo': '0.0.12-0', - '@accounts/meteor-adapter': '0.1.1' + '@accounts/mongo': '0.0.12' }); diff --git a/packages/rocketchat-accounts/server/fix.js b/packages/rocketchat-accounts/server/fix.js deleted file mode 100644 index f1900a19c465..000000000000 --- a/packages/rocketchat-accounts/server/fix.js +++ /dev/null @@ -1,3 +0,0 @@ -import regeneratorRuntime from 'babel-runtime/regenerator'; - -global.regeneratorRuntime = regeneratorRuntime; diff --git a/packages/rocketchat-accounts/server/index.js b/packages/rocketchat-accounts/server/index.js index 87ec121feca8..88ebb9b52977 100644 --- a/packages/rocketchat-accounts/server/index.js +++ b/packages/rocketchat-accounts/server/index.js @@ -1,4 +1,4 @@ -import './fix'; +// import './fix'; import './config'; import AccountsServer from '@accounts/server'; diff --git a/packages/rocketchat-api/server/v1/channels.js b/packages/rocketchat-api/server/v1/channels.js index 15a6c3d0eaf4..86abc6ab38e6 100644 --- a/packages/rocketchat-api/server/v1/channels.js +++ b/packages/rocketchat-api/server/v1/channels.js @@ -126,37 +126,82 @@ RocketChat.API.v1.addRoute('channels.close', { authRequired: true }, { } }); -RocketChat.API.v1.addRoute('channels.create', { authRequired: true }, { - post() { - if (!RocketChat.authz.hasPermission(this.userId, 'create-c')) { - return RocketChat.API.v1.unauthorized(); - } +// Channel -> create - if (!this.bodyParams.name) { - return RocketChat.API.v1.failure('Body param "name" is required'); - } +function createChannelValidator(params) { + if (!RocketChat.authz.hasPermission(params.user.value, 'create-c')) { + throw new Error('unauthorized'); + } - if (this.bodyParams.members && !_.isArray(this.bodyParams.members)) { - return RocketChat.API.v1.failure('Body param "members" must be an array if provided'); - } + if (!params.name.value) { + throw new Error(`Param "${ params.name.key }" is required`); + } - if (this.bodyParams.customFields && !(typeof this.bodyParams.customFields === 'object')) { - return RocketChat.API.v1.failure('Body param "customFields" must be an object if provided'); - } + if (params.members.value && !_.isArray(params.members.value)) { + throw new Error(`Param "${ params.members.key }" must be an array if provided`); + } + + if (params.customFields.value && !(typeof params.customFields.value === 'object')) { + throw new Error(`Param "${ params.customFields.key }" must be an object if provided`); + } +} + +function createChannel(userId, params) { + let readOnly = false; + if (typeof params.readOnly !== 'undefined') { + readOnly = params.readOnly; + } + + let id; + Meteor.runAsUser(userId, () => { + id = Meteor.call('createChannel', params.name, params.members ? params.members : [], readOnly, params.customFields); + }); + + return { + channel: RocketChat.models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude }) + }; +} - let readOnly = false; - if (typeof this.bodyParams.readOnly !== 'undefined') { - readOnly = this.bodyParams.readOnly; +RocketChat.API.channels = {}; +RocketChat.API.channels.create = { + validate: createChannelValidator, + execute: createChannel +}; + +RocketChat.API.v1.addRoute('channels.create', { authRequired: true }, { + post() { + const userId = this.userId; + const bodyParams = this.bodyParams; + + let error; + + try { + RocketChat.API.create.validate({ + user: { + value: userId + }, + name: { + value: bodyParams.name, + key: 'name' + }, + members: { + value: bodyParams.members, + key: 'members' + } + }); + } catch (e) { + if (e.message === 'unauthorized') { + error = RocketChat.API.v1.unauthorized(); + } else { + error = RocketChat.API.v1.failure(e.message); + } } - let id; - Meteor.runAsUser(this.userId, () => { - id = Meteor.call('createChannel', this.bodyParams.name, this.bodyParams.members ? this.bodyParams.members : [], readOnly, this.bodyParams.customFields); - }); + if (error) { + return error; + } - return RocketChat.API.v1.success({ - channel: RocketChat.models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude }) - }); + return RocketChat.API.v1.success(RocketChat.API.channels.create.execute(userId, bodyParams)); } }); diff --git a/packages/rocketchat-grant-facebook/README.md b/packages/rocketchat-grant-facebook/README.md new file mode 100644 index 000000000000..9d2da06860b2 --- /dev/null +++ b/packages/rocketchat-grant-facebook/README.md @@ -0,0 +1,3 @@ +# rocketchat:grant-facebook + +An implementation of the Facebook OAuth flow. diff --git a/packages/rocketchat-grant-github/README.md b/packages/rocketchat-grant-github/README.md new file mode 100644 index 000000000000..e5fea3c781c7 --- /dev/null +++ b/packages/rocketchat-grant-github/README.md @@ -0,0 +1,3 @@ +# rocketchat:grant-github + +An implementation of the GitHub OAuth flow. diff --git a/packages/rocketchat-grant-google/README.md b/packages/rocketchat-grant-google/README.md new file mode 100644 index 000000000000..cdd59d97b562 --- /dev/null +++ b/packages/rocketchat-grant-google/README.md @@ -0,0 +1,3 @@ +# rocketchat:grant-google + +An implementation of the Google OAuth flow. diff --git a/packages/rocketchat-grant/README.md b/packages/rocketchat-grant/README.md index c526711cf6c9..716b57bfcf80 100644 --- a/packages/rocketchat-grant/README.md +++ b/packages/rocketchat-grant/README.md @@ -1,8 +1,101 @@ -1. Settings should be the same as in OAuth section -1. Should be extendable (rocketchat:grant, rocketchat:grant-github etc) -1. Each package with provider should transform it's scope to user data so we can register a new user -1. rocketchat:grant-sub - to define sub configurations to allow for using external apps -1. rocketchat:grant should contain a middleware and startup fn with setup, that is already in rocketchat:oauth-external -1. in callback it would create and / or log in a user -1. without any specified sub configuration, it would redirect to localhost:3000 by default -1. with a specified sub configuration it would redirect to a path and add access_token to the URL +# rocketchat:grant + +The main idea behind creating this package was to allow external apps (i.e. PWA) to use OAuth smoothely with currently available accounts system. + +## Usage + +1. Define providers using `Settings.add()` +1. Add apps with `Settings.apps.add()` +1. Put the path that stars OAuth flow in your app +1. You app should be able to authenticate user with received tokens + +## Paths + +There are few paths you need to be familiar with. + +### Start OAuth flow + +> \/_oauth_apps/connect/\/\ + +### Authorization callback URL + +> \/_oauth_apps/connect/\/callback + +### List of available providers + +> \/_oauth_apps/providers + +## API + +### Providers + +#### Providers.register(name, options, getUser) + +Allows to register an OAuth Provider. + +- name - string that represents the name of an OAuth provider +- options - contains fields like _scope_ +- getUser - a function that returns fields: _id, email, username, name and avatar_ + +### Settings + +#### Settings.add(options) + +Defines a provider that is able for being used in OAuth. + +**options**: + +- enabled - __boolean__ - tells to `rocketchat:grant` if provider could be used +- provider - __string__ - id of a provider +- key - __string__ - client ID provided for your OAuth access +- secret - __string__ - secret key + +Example: + +```js + Settings.add({ + enabled: true, + provider: 'google', + key: 'CLIENT_ID', + secret: 'SECRET' + }); +``` + +#### Settings.apps.add(name, options) + +Defines an app that is able for using OAuth. + +**options**: + +- redirectUrl - __string__ - where to redirect if auth was succesful +- errorUrl - __string__ - place to redirect on failure + +Example: + +```js + + const redirectUrl = 'http://localhost:4200/login?service={provider}&access_token={accessToken}&refresh_token={refreshToken}'; + + const errorUrl = 'http://localhost:4200/login?service={provider}&error={error}' + + + Settings.apps.add('PWA', { + redirectUrl, + errorUrl + }); +``` + +About URLs: + +We use a parser to produce a URL. +There are few available variables for each type of redirect. + +- redirectUrl - provider, accessToken, refreshToken +- errorUrl - provider, error + +Example: + +``` +http://localhost:4200/login?provider={provider} +// outputs: http://localhost:4200/login?provider=google +``` diff --git a/packages/rocketchat-grant/server/providers.js b/packages/rocketchat-grant/server/providers.js index 4b2aad10cee5..debad8d091e8 100644 --- a/packages/rocketchat-grant/server/providers.js +++ b/packages/rocketchat-grant/server/providers.js @@ -31,7 +31,6 @@ export function middleware(req, res, next) { providers.forEach((_, name) => list.push(name)); - // TODO: send a list of providers res.end(JSON.stringify({ data: list })); diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json index 482cfcaf4242..6a2374ea66c7 100644 --- a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -1,501 +1,512 @@ { "dependencies": { "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "from": "accepts@>=1.3.3 <1.4.0" + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "from": "accepts@https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz" + }, + "apollo-server-core": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-1.1.0.tgz", + "from": "apollo-server-core@https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-1.1.0.tgz" }, - "apollo-client": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-1.6.0.tgz", - "from": "apollo-client@1.6.0" + "apollo-server-express": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-1.1.2.tgz", + "from": "apollo-server-express@https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-1.1.2.tgz" + }, + "apollo-server-module-graphiql": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.2.tgz", + "from": "apollo-server-module-graphiql@https://registry.npmjs.org/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.2.tgz" + }, + "apollo-tracing": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.0.7.tgz", + "from": "apollo-tracing@https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.0.7.tgz" }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "from": "array-flatten@1.1.1" + "from": "array-flatten@https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "from": "babel-polyfill@https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "from": "regenerator-runtime@https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz" + } + } }, "babel-runtime": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.25.0.tgz", - "from": "babel-runtime@>=6.23.0 <7.0.0" + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "from": "babel-runtime@https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "from": "backo2@>=1.0.2 <2.0.0" + "from": "backo2@https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz" }, "base64url": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", - "from": "base64url@>=2.0.0 <3.0.0" + "from": "base64url@https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz" }, "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "from": "bcryptjs@>=2.4.0 <3.0.0" + "from": "bcryptjs@https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz" }, "body-parser": { "version": "1.17.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", - "from": "body-parser@1.17.2" + "from": "body-parser@https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz" }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "from": "buffer-equal-constant-time@1.0.1" + "from": "buffer-equal-constant-time@https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" }, "bytes": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "from": "bytes@2.4.0" + "from": "bytes@https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "from": "content-disposition@0.5.2" + "from": "content-disposition@https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz" }, "content-type": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", - "from": "content-type@>=1.0.2 <1.1.0" + "from": "content-type@https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "from": "cookie@0.3.1" + "from": "cookie@https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "from": "cookie-signature@1.0.6" + "from": "cookie-signature@https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" }, "core-js": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", - "from": "core-js@>=2.4.0 <3.0.0" + "from": "core-js@https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz" }, "cors": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.3.tgz", - "from": "cors@2.8.3" + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "from": "cors@https://registry.npmjs.org/cors/-/cors-2.8.4.tgz" }, "crypto": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/crypto/-/crypto-0.0.3.tgz", - "from": "crypto@>=0.0.3 <0.0.4" + "from": "crypto@https://registry.npmjs.org/crypto/-/crypto-0.0.3.tgz" }, "debug": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", - "from": "debug@2.6.7" + "from": "debug@https://registry.npmjs.org/debug/-/debug-2.6.7.tgz" }, "deepmerge": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.0.tgz", - "from": "deepmerge@>=1.3.2 <2.0.0" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.1.tgz", + "from": "deepmerge@https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.1.tgz" }, "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "from": "depd@>=1.1.0 <1.2.0" + "from": "depd@https://registry.npmjs.org/depd/-/depd-1.1.1.tgz" }, "deprecated-decorator": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", - "from": "deprecated-decorator@>=0.1.6 <0.2.0" + "from": "deprecated-decorator@https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz" }, "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "from": "destroy@>=1.0.4 <1.1.0" + "from": "destroy@https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" }, "ecdsa-sig-formatter": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", - "from": "ecdsa-sig-formatter@1.0.9" + "from": "ecdsa-sig-formatter@https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz" }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "from": "ee-first@1.1.1" + "from": "ee-first@https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" }, "encodeurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "from": "encodeurl@>=1.0.1 <1.1.0" + "from": "encodeurl@https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" }, "es6-promise": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", - "from": "es6-promise@>=4.0.5 <5.0.0" + "from": "es6-promise@https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz" }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "from": "escape-html@>=1.0.3 <1.1.0" + "from": "escape-html@https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" }, "etag": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", - "from": "etag@>=1.8.0 <1.9.0" + "from": "etag@https://registry.npmjs.org/etag/-/etag-1.8.0.tgz" }, "eventemitter3": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", - "from": "eventemitter3@>=2.0.3 <3.0.0" + "from": "eventemitter3@https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz" }, "express": { - "version": "4.15.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", - "from": "express@4.15.3" + "version": "4.15.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz", + "from": "express@https://registry.npmjs.org/express/-/express-4.15.4.tgz", + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "from": "debug@https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + }, + "qs": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", + "from": "qs@https://registry.npmjs.org/qs/-/qs-6.5.0.tgz" + } + } }, "finalhandler": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz", - "from": "finalhandler@>=1.0.3 <1.1.0", + "from": "finalhandler@https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz", "dependencies": { "debug": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "from": "debug@2.6.8" + "from": "debug@https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" } } }, "forwarded": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", - "from": "forwarded@>=0.1.0 <0.2.0" + "from": "forwarded@https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" }, "fresh": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", - "from": "fresh@0.5.0" + "from": "fresh@https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz" }, "graphql": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.10.3.tgz", - "from": "graphql@0.10.3" - }, - "graphql-anywhere": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/graphql-anywhere/-/graphql-anywhere-3.1.0.tgz", - "from": "graphql-anywhere@>=3.0.1 <4.0.0" - }, - "graphql-server-core": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/graphql-server-core/-/graphql-server-core-0.9.0.tgz", - "from": "graphql-server-core@>=0.9.0 <0.10.0" - }, - "graphql-server-express": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/graphql-server-express/-/graphql-server-express-0.9.0.tgz", - "from": "graphql-server-express@0.9.0" - }, - "graphql-server-module-graphiql": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/graphql-server-module-graphiql/-/graphql-server-module-graphiql-0.9.0.tgz", - "from": "graphql-server-module-graphiql@>=0.9.0 <0.10.0" + "from": "graphql@https://registry.npmjs.org/graphql/-/graphql-0.10.3.tgz" }, "graphql-subscriptions": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-0.4.4.tgz", - "from": "graphql-subscriptions@0.4.4" + "from": "graphql-subscriptions@https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-0.4.4.tgz" }, "graphql-tag": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.4.2.tgz", - "from": "graphql-tag@>=2.0.0 <3.0.0" + "from": "graphql-tag@https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.4.2.tgz" }, "graphql-tools": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.1.0.tgz", - "from": "graphql-tools@1.1.0" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.2.2.tgz", + "from": "graphql-tools@https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.2.2.tgz" }, "hoek": { "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "from": "hoek@>=2.0.0 <3.0.0" + "from": "hoek@https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "from": "http-errors@>=1.6.1 <1.7.0" + "from": "http-errors@https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz" }, "iconv-lite": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "from": "iconv-lite@0.4.15" + "from": "iconv-lite@https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "from": "inherits@2.0.3" + "from": "inherits@https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" }, "ipaddr.js": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", - "from": "ipaddr.js@1.4.0" + "from": "ipaddr.js@https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz" }, "isemail": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "from": "isemail@>=1.0.0 <2.0.0" + "from": "isemail@https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz" }, "iterall": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.1.tgz", - "from": "iterall@>=1.1.0 <2.0.0" + "from": "iterall@https://registry.npmjs.org/iterall/-/iterall-1.1.1.tgz" }, "joi": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "from": "joi@>=6.10.1 <7.0.0" - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "from": "js-tokens@>=3.0.0 <4.0.0" + "from": "joi@https://registry.npmjs.org/joi/-/joi-6.10.1.tgz" }, "jsonwebtoken": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.2.tgz", - "from": "jsonwebtoken@>=7.2.1 <8.0.0" + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz", + "from": "jsonwebtoken@https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz" }, "jwa": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", - "from": "jwa@>=1.1.4 <2.0.0" + "from": "jwa@https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz" }, "jws": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", - "from": "jws@>=3.1.4 <4.0.0" + "from": "jws@https://registry.npmjs.org/jws/-/jws-3.1.4.tgz" }, "jwt-decode": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", - "from": "jwt-decode@>=2.1.0 <3.0.0" + "from": "jwt-decode@https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz" + }, + "kamilkisiela-graphql-api": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/kamilkisiela-graphql-api/-/kamilkisiela-graphql-api-0.1.1.tgz", + "from": "kamilkisiela-graphql-api@https://registry.npmjs.org/kamilkisiela-graphql-api/-/kamilkisiela-graphql-api-0.1.1.tgz" + }, + "kamilkisiela-merge-graphql-schemas": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/kamilkisiela-merge-graphql-schemas/-/kamilkisiela-merge-graphql-schemas-1.1.2.tgz", + "from": "kamilkisiela-merge-graphql-schemas@https://registry.npmjs.org/kamilkisiela-merge-graphql-schemas/-/kamilkisiela-merge-graphql-schemas-1.1.2.tgz" }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "from": "lodash@>=4.16.4 <5.0.0" - }, - "lodash-es": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", - "from": "lodash-es@>=4.2.1 <5.0.0" + "from": "lodash@https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" }, "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "from": "lodash.assign@>=4.2.0 <5.0.0" + "from": "lodash.assign@https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz" }, "lodash.isobject": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "from": "lodash.isobject@>=3.0.2 <4.0.0" + "from": "lodash.isobject@https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz" }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "from": "lodash.isstring@>=4.0.1 <5.0.0" + "from": "lodash.isstring@https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "from": "lodash.once@>=4.0.0 <5.0.0" - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "from": "loose-envify@>=1.1.0 <2.0.0" + "from": "lodash.once@https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "from": "media-typer@0.3.0" + "from": "media-typer@https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "from": "merge-descriptors@1.0.1" + "from": "merge-descriptors@https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" }, - "merge-graphql-schemas": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-graphql-schemas/-/merge-graphql-schemas-1.1.0.tgz", - "from": "merge-graphql-schemas@1.1.0" + "meteor-promise": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.6.tgz", + "from": "meteor-promise@https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.6.tgz" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "from": "methods@>=1.1.2 <1.2.0" + "from": "methods@https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" }, "mime": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "from": "mime@1.3.4" + "from": "mime@https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" }, "mime-db": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", - "from": "mime-db@>=1.29.0 <1.30.0" + "from": "mime-db@https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz" }, "mime-types": { "version": "2.1.16", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", - "from": "mime-types@>=2.1.15 <2.2.0" + "from": "mime-types@https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz" }, "moment": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", - "from": "moment@>=2.0.0 <3.0.0" + "from": "moment@https://registry.npmjs.org/moment/-/moment-2.18.1.tgz" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "from": "ms@>=2.0.0 <3.0.0" + "from": "ms@https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "from": "negotiator@0.6.1" + "from": "negotiator@https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "from": "object-assign@>=4.0.0 <5.0.0" + "from": "object-assign@https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "from": "on-finished@>=2.3.0 <2.4.0" + "from": "on-finished@https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" }, "parseurl": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "from": "parseurl@>=1.3.1 <1.4.0" + "from": "parseurl@https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "from": "path-to-regexp@0.1.7" + "from": "path-to-regexp@https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" }, "proxy-addr": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", - "from": "proxy-addr@>=1.1.4 <1.2.0" + "from": "proxy-addr@https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz" }, "qs": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "from": "qs@6.4.0" + "from": "qs@https://registry.npmjs.org/qs/-/qs-6.4.0.tgz" }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "from": "range-parser@>=1.2.0 <1.3.0" + "from": "range-parser@https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" }, "raw-body": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", - "from": "raw-body@>=2.2.0 <2.3.0" - }, - "redux": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", - "from": "redux@>=3.4.0 <4.0.0" + "from": "raw-body@https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" }, "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "from": "regenerator-runtime@>=0.10.0 <0.11.0" + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "from": "regenerator-runtime@https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz" }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "from": "safe-buffer@>=5.0.1 <6.0.0" + "from": "safe-buffer@https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" }, "send": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", - "from": "send@0.15.3" + "version": "0.15.4", + "resolved": "https://registry.npmjs.org/send/-/send-0.15.4.tgz", + "from": "send@https://registry.npmjs.org/send/-/send-0.15.4.tgz", + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "from": "debug@https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + } + } }, "serve-static": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz", - "from": "serve-static@1.12.3" + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz", + "from": "serve-static@https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz" }, "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "from": "setprototypeof@1.0.3" + "from": "setprototypeof@https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz" }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "from": "statuses@>=1.3.1 <2.0.0" + "from": "statuses@https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" }, "subscriptions-transport-ws": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.8.1.tgz", - "from": "subscriptions-transport-ws@0.8.1" + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.8.2.tgz", + "from": "subscriptions-transport-ws@https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.8.2.tgz" }, "symbol-observable": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", - "from": "symbol-observable@>=1.0.2 <2.0.0" + "from": "symbol-observable@https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz" }, "topo": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "from": "topo@>=1.0.0 <2.0.0" + "from": "topo@https://registry.npmjs.org/topo/-/topo-1.1.0.tgz" }, "type-is": { "version": "1.6.15", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "from": "type-is@>=1.6.15 <1.7.0" + "from": "type-is@https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz" }, "ultron": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz", - "from": "ultron@>=1.1.0 <1.2.0" + "from": "ultron@https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "from": "unpipe@1.0.0" + "from": "unpipe@https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" }, "utils-merge": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "from": "utils-merge@1.0.0" + "from": "utils-merge@https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" }, "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "from": "uuid@>=3.0.1 <4.0.0" + "from": "uuid@https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" }, "vary": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", - "from": "vary@>=1.0.0 <2.0.0" - }, - "whatwg-fetch": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", - "from": "whatwg-fetch@>=2.0.0 <3.0.0" + "from": "vary@https://registry.npmjs.org/vary/-/vary-1.1.1.tgz" }, "ws": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ws/-/ws-3.1.0.tgz", - "from": "ws@>=3.0.0 <4.0.0" + "from": "ws@https://registry.npmjs.org/ws/-/ws-3.1.0.tgz" }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "from": "xtend@>=4.0.1 <5.0.0" + "from": "xtend@https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" } } } diff --git a/packages/rocketchat-graphql/README.md b/packages/rocketchat-graphql/README.md new file mode 100644 index 000000000000..712c36fd39ae --- /dev/null +++ b/packages/rocketchat-graphql/README.md @@ -0,0 +1,3 @@ +# rocketchat:graphql + +GraphQL API diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js index b4ceb319ed9b..def84c4c84c9 100644 --- a/packages/rocketchat-graphql/package.js +++ b/packages/rocketchat-graphql/package.js @@ -12,14 +12,15 @@ Package.onUse(function(api) { 'http', 'rocketchat:lib', 'rocketchat:api', - 'rocketchat:accounts' + 'rocketchat:accounts', + 'swydo:graphql' ]); api.mainModule('server/api.js', 'server'); }); Npm.depends({ - '@accounts/graphql-api': '0.1.1', + 'kamilkisiela-graphql-api': '0.1.1', 'apollo-server-express': '1.1.2', 'cors': '2.8.4', 'body-parser': '1.17.2', @@ -27,6 +28,6 @@ Npm.depends({ 'graphql': '0.10.3', 'graphql-subscriptions': '0.4.4', 'graphql-tools': '1.2.2', - 'merge-graphql-schemas': '1.1.2', + 'kamilkisiela-merge-graphql-schemas': '1.1.2', 'subscriptions-transport-ws': '0.8.2' }); diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index a8262a0d33f4..9c1f36c00a90 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -1,5 +1,5 @@ import { graphqlExpress, graphiqlExpress } from 'apollo-server-express'; -import { JSAccountsContext as jsAccountsContext } from '@accounts/graphql-api'; +import { JSAccountsContext as jsAccountsContext } from 'kamilkisiela-graphql-api'; import { SubscriptionServer } from 'subscriptions-transport-ws'; import { execute, subscribe } from 'graphql'; import { Meteor } from 'meteor/meteor'; diff --git a/packages/rocketchat-graphql/server/helpers/authenticated.js b/packages/rocketchat-graphql/server/helpers/authenticated.js index a0a39e676560..c36223b94b5a 100644 --- a/packages/rocketchat-graphql/server/helpers/authenticated.js +++ b/packages/rocketchat-graphql/server/helpers/authenticated.js @@ -1,6 +1,6 @@ import { AccountsServer } from 'meteor/rocketchat:accounts'; //import { authenticated as _authenticated } from '@accounts/graphql-api'; - +// import { authenticated as _authenticated } from 'kamilkisiela-graphql-api'; import { authenticated as _authenticated } from '../mocks/accounts/graphql-api'; export const authenticated = (resolver) => { diff --git a/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js index adbaaaa71d7e..8bd3dde10230 100644 --- a/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js +++ b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js @@ -1,13 +1,3 @@ -/*export const authenticated = (Accounts, func) => (async(root, args, context, info) => { - const userObject = await Accounts.resumeSession(); - - if (userObject === null) { - throw new Error('Invalid or expired token!'); - } - - return await func(root, args, Object.assign(context, { user: userObject }), info); -});*/ - // Same as here: https://github.com/js-accounts/graphql/blob/master/packages/graphql-api/src/utils/authenticated-resolver.js // except code below works // It might be like that because of async/await, diff --git a/packages/rocketchat-graphql/server/mocks/accounts/server.js b/packages/rocketchat-graphql/server/mocks/accounts/server.js deleted file mode 100644 index 8bf64b3bccbf..000000000000 --- a/packages/rocketchat-graphql/server/mocks/accounts/server.js +++ /dev/null @@ -1,13 +0,0 @@ -const loggedOut = false; - -const AccountsServer = { - resumeSession: (async() => { - if (loggedOut) { - throw new Error('User not found'); - } - // User credentials - return RocketChat.models.Users.findOne({username: 'mys'}); - }) -}; - -export default AccountsServer; diff --git a/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js b/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js new file mode 100644 index 000000000000..fd13e7f61106 --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/accounts/OauthProvider-type.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/schemas/accounts/index.js b/packages/rocketchat-graphql/server/resolvers/accounts/index.js similarity index 76% rename from packages/rocketchat-graphql/server/schemas/accounts/index.js rename to packages/rocketchat-graphql/server/resolvers/accounts/index.js index e82a7077059b..57d98cce5962 100644 --- a/packages/rocketchat-graphql/server/schemas/accounts/index.js +++ b/packages/rocketchat-graphql/server/resolvers/accounts/index.js @@ -1,6 +1,6 @@ -import { createJSAccountsGraphQL } from '@accounts/graphql-api'; +import { createJSAccountsGraphQL } from 'kamilkisiela-graphql-api'; import { AccountsServer } from 'meteor/rocketchat:accounts'; -import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; // queries import * as oauthProviders from './oauthProviders'; diff --git a/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js b/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js similarity index 80% rename from packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js rename to packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js index 9cefedb7a15e..0cccbc9381d9 100644 --- a/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.js +++ b/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js @@ -1,6 +1,8 @@ import { HTTP } from 'meteor/http'; import { Meteor } from 'meteor/meteor'; +import schema from '../../schemas/accounts/oauthProviders.graphql'; + function isJSON(obj) { try { JSON.parse(obj); @@ -10,13 +12,7 @@ function isJSON(obj) { } } -export const schema = ` - type Query { - oauthProviders: [OauthProvider] - } -`; - -export const resolver = { +const resolver = { Query: { oauthProviders: async() => { // depends on rocketchat:grant package @@ -31,9 +27,13 @@ export const resolver = { throw new Error('Could not parse the result'); } } catch (e) { - console.error('oauthProviders resolver', e); throw new Error('rocketchat:grant not installed'); } } } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js b/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js similarity index 75% rename from packages/rocketchat-graphql/server/schemas/channels/Channel-type.js rename to packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js index cfcbebe2a327..e4dfb9ba4371 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js @@ -1,25 +1,7 @@ import { property } from '../../helpers/property'; +import schema from '../../schemas/channels/Channel-type.graphql'; -export const schema = ` - type Channel { - id: String! - name: String - description: String - announcement: String - topic: String - members: [User] - owners: [User] - numberOfMembers: Int - numberOfMessages: Int - readOnly: Boolean - direct: Boolean - privateChannel: Boolean - favourite: Boolean - unseenMessages: Int - } -`; - -export const resolver = { +const resolver = { Channel: { id: property('_id'), name: (root, args, { user }) => { @@ -59,3 +41,8 @@ export const resolver = { } } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js new file mode 100644 index 000000000000..54c5be23b0ff --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/channels/ChannelFilter-input.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js new file mode 100644 index 000000000000..ad769ae36913 --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/channels/ChannelNameAndDirect-input.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js new file mode 100644 index 000000000000..3cd8b5f7b8d3 --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/channels/ChannelSort-enum.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js b/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js new file mode 100644 index 000000000000..bc0172b74adb --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/channels/Privacy-enum.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js b/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js similarity index 73% rename from packages/rocketchat-graphql/server/schemas/channels/channelByName.js rename to packages/rocketchat-graphql/server/resolvers/channels/channelByName.js index 63b70ddf360e..060e2a2526a6 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelByName.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js @@ -1,13 +1,8 @@ import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; +import schema from '../../schemas/channels/channelByName.graphql'; -export const schema = ` - type Query { - channelByName(name: String!): Channel - } -`; - -export const resolver = { +const resolver = { Query: { channelByName: authenticated((root, { name }) => { const query = { @@ -21,3 +16,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.js b/packages/rocketchat-graphql/server/resolvers/channels/channels.js similarity index 80% rename from packages/rocketchat-graphql/server/schemas/channels/channels.js rename to packages/rocketchat-graphql/server/resolvers/channels/channels.js index c188819c96b3..6087771b86fd 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channels.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/channels.js @@ -1,17 +1,8 @@ import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; +import schema from '../../schemas/channels/channels.graphql'; -export const schema = ` - type Query { - channels(filter: ChannelFilter = { - privacy: ALL, - joinedChannels: false, - sortBy: NAME - }): [Channel] - } -`; - -export const resolver = { +const resolver = { Query: { channels: authenticated((root, args) => { const query = {}; @@ -49,12 +40,15 @@ export const resolver = { }; break; } - - // joinedChannels - // TODO: } return RocketChat.models.Rooms.find(query, options).fetch(); }) } }; + + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js b/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js similarity index 78% rename from packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js rename to packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js index 0784da1854a0..29a240e5c000 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js @@ -1,20 +1,13 @@ import { authenticated } from '../../helpers/authenticated'; - import { roomPublicFields } from './settings'; +import schema from '../../schemas/channels/channelsByUser.graphql'; -export const schema = ` - type Query { - channelsByUser(userId: String!): [Channel] - } -`; - -export const resolver = { +const resolver = { Query: { channelsByUser: authenticated((root, { userId }) => { const user = RocketChat.models.Users.findOneById(userId); if (!user) { - // TODO: throw new Error('No user'); } @@ -29,3 +22,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js new file mode 100644 index 000000000000..e0f8a84d6a3d --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js @@ -0,0 +1,38 @@ +import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/channels/createChannel.graphql'; + +const resolver = { + Mutation: { + createChannel: authenticated((root, args, { user }) => { + try { + RocketChat.API.channels.create.validate({ + user: { + value: user._id + }, + name: { + value: args.name, + key: 'name' + }, + members: { + value: args.membersId, + key: 'membersId' + } + }); + } catch (e) { + throw e; + } + + const { channel } = RocketChat.API.channels.create.execute(user._id, { + name: args.name, + members: args.membersId + }); + + return channel; + }) + } +}; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/directChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js similarity index 84% rename from packages/rocketchat-graphql/server/schemas/channels/directChannel.js rename to packages/rocketchat-graphql/server/resolvers/channels/directChannel.js index e2431551e811..2218cdf7837b 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/directChannel.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js @@ -1,13 +1,8 @@ import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; +import schema from '../../schemas/channels/directChannel.graphql'; -export const schema = ` - type Query { - directChannel(username: String, channelId: String): Channel - } -`; - -export const resolver = { +const resolver = { Query: { directChannel: authenticated((root, { username, channelId }, { user }) => { const query = { @@ -19,6 +14,7 @@ export const resolver = { if (username === user.username) { throw new Error('You cannot specify your username'); } + query.usernames = { $all: [ user.username, username ] }; } else if (typeof channelId !== 'undefined') { query.id = channelId; @@ -32,3 +28,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js similarity index 87% rename from packages/rocketchat-graphql/server/schemas/channels/hideChannel.js rename to packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js index 2904ca9dcd2f..23cd1017f985 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js @@ -1,14 +1,9 @@ import { Meteor } from 'meteor/meteor'; import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/channels/hideChannel.graphql'; -export const schema = ` - type Mutation { - hideChannel(channelId: String!): Boolean - } -`; - -export const resolver = { +const resolver = { Mutation: { hideChannel: authenticated((root, args, { user }) => { const channel = RocketChat.models.Rooms.findOne({ @@ -38,3 +33,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/index.js b/packages/rocketchat-graphql/server/resolvers/channels/index.js similarity index 93% rename from packages/rocketchat-graphql/server/schemas/channels/index.js rename to packages/rocketchat-graphql/server/resolvers/channels/index.js index 063e9da41804..82a9dbff107d 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/index.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/index.js @@ -1,4 +1,4 @@ -import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; // queries import * as channels from './channels'; diff --git a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js similarity index 81% rename from packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js rename to packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js index 141f1eba171f..306beff5d7a6 100644 --- a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js @@ -1,14 +1,9 @@ import { Meteor } from 'meteor/meteor'; import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/channels/leaveChannel.graphql'; -export const schema = ` - type Mutation { - leaveChannel(channelId: String!): Boolean - } -`; - -export const resolver = { +const resolver = { Mutation: { leaveChannel: authenticated((root, args, { user }) => { const channel = RocketChat.models.Rooms.findOne({ @@ -28,3 +23,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/channels/settings.js b/packages/rocketchat-graphql/server/resolvers/channels/settings.js similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/settings.js rename to packages/rocketchat-graphql/server/resolvers/channels/settings.js diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js b/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js similarity index 78% rename from packages/rocketchat-graphql/server/schemas/messages/Message-type.js rename to packages/rocketchat-graphql/server/resolvers/messages/Message-type.js index 264ef427390b..0fc8c6c36bb4 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js @@ -1,25 +1,8 @@ import { property } from '../../helpers/property'; import { dateToFloat } from '../../helpers/dateToFloat'; +import schema from '../../schemas/messages/Message-type.graphql'; -export const schema = ` - type Message { - id: String - author: User - content: String - channel: Channel - creationTime: Float - # Message sent by server e.g. User joined channel - fromServer: Boolean - type: String - # List of mentioned users - userRef: [User] - # list of mentioned channels - channelRef: [Channel] - reactions: [Reaction] - } -`; - -export const resolver = { +const resolver = { Message: { id: property('_id'), content: property('msg'), @@ -84,3 +67,8 @@ export const resolver = { } } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js b/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js new file mode 100644 index 000000000000..63f5a8bbb300 --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/messages/MessageIdentifier-input.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js b/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js new file mode 100644 index 000000000000..e25dfb592f7a --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/messages/MessagesWithCursor-type.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js b/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js new file mode 100644 index 000000000000..81ec44c5b9b8 --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/messages/Reaction-type.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js similarity index 74% rename from packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js rename to packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js index 2dc894969880..1c915d3a4c9a 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js @@ -1,14 +1,9 @@ import { Meteor } from 'meteor/meteor'; import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/messages/addReactionToMessage.graphql'; -export const schema = ` - type Mutation { - addReactionToMassage(id: MessageIdentifier!, icon: String!): Message - } -`; - -export const resolver = { +const resolver = { Mutation: { addReactionToMassage: authenticated((root, { id, icon }, { user }) => { return new Promise((resolve) => { @@ -21,3 +16,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.js b/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js similarity index 83% rename from packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.js rename to packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js index 0f127c3c934f..dfbb818e12b2 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js @@ -1,6 +1,7 @@ import { withFilter } from 'graphql-subscriptions'; import { pubsub } from '../../subscriptions'; +import schema from '../../schemas/messages/chatMessageAdded.graphql'; export const CHAT_MESSAGE_SUBSCRIPTION_TOPIC = 'CHAT_MESSAGE_ADDED'; @@ -8,13 +9,7 @@ export function publishMessage(message) { pubsub.publish(CHAT_MESSAGE_SUBSCRIPTION_TOPIC, { chatMessageAdded: message }); } -export const schema = ` - type Subscription { - chatMessageAdded(channelId: String!): Message - } -`; - -export const resolver = { +const resolver = { Subscription: { chatMessageAdded: { subscribe: withFilter(() => pubsub.asyncIterator(CHAT_MESSAGE_SUBSCRIPTION_TOPIC), (payload, args) => { @@ -27,3 +22,8 @@ export const resolver = { RocketChat.callbacks.add('afterSaveMessage', (message) => { publishMessage(message); }, null, 'chatMessageAddedSubscription'); + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js similarity index 83% rename from packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js rename to packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js index 91b3d0fa7e92..851767060869 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js @@ -1,14 +1,9 @@ import { Meteor } from 'meteor/meteor'; import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/messages/deleteMessage.graphql'; -export const schema = ` - type Mutation { - deleteMessage(id: MessageIdentifier!): Message - } -`; - -export const resolver = { +const resolver = { Mutation: { deleteMessage: authenticated((root, { id }, { user }) => { const msg = RocketChat.models.Messages.findOneById(id.messageId, { fields: { u: 1, rid: 1 }}); @@ -29,3 +24,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js similarity index 85% rename from packages/rocketchat-graphql/server/schemas/messages/editMessage.js rename to packages/rocketchat-graphql/server/resolvers/messages/editMessage.js index da1e1c8e850e..42973929e23a 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/editMessage.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js @@ -1,14 +1,9 @@ import { Meteor } from 'meteor/meteor'; import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/messages/editMessage.graphql'; -export const schema = ` - type Mutation { - editMessage(id: MessageIdentifier!, content: String!): Message - } -`; - -export const resolver = { +const resolver = { Mutation: { editMessage: authenticated((root, { id, content }, { user }) => { const msg = RocketChat.models.Messages.findOneById(id.messageId); @@ -31,3 +26,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/index.js b/packages/rocketchat-graphql/server/resolvers/messages/index.js similarity index 93% rename from packages/rocketchat-graphql/server/schemas/messages/index.js rename to packages/rocketchat-graphql/server/resolvers/messages/index.js index fb9728b19815..ad5fc67076e6 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/index.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/index.js @@ -1,4 +1,4 @@ -import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; // queries import * as messages from './messages'; diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.js b/packages/rocketchat-graphql/server/resolvers/messages/messages.js similarity index 66% rename from packages/rocketchat-graphql/server/schemas/messages/messages.js rename to packages/rocketchat-graphql/server/resolvers/messages/messages.js index 8083d2fa6fdf..6ef4b7502591 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/messages.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/messages.js @@ -1,20 +1,7 @@ import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/messages/messages.graphql'; -export const schema = ` - type Query { - messages( - channelId: String, - channelDetails: ChannelNameAndDirect, - channelName: String, - cursor: String, - count: Int, - searchRegex: String, - excludeServer: Boolean - ): MessagesWithCursor - } -`; - -export const resolver = { +const resolver = { Query: { messages: authenticated((root, args) => { const messagesQuery = {}; @@ -45,10 +32,10 @@ export const resolver = { // cursor if (isPagination && args.cursor) { const cursorMsg = RocketChat.models.Messages.findOne(args.cursor, { fields: { ts: 1 } }); - messagesQuery.ts = { $gt: cursorMsg.ts }; + messagesQuery.ts = { $lt: cursorMsg.ts }; } - // searchRegex + // search if (typeof args.searchRegex === 'string') { messagesQuery.msg = { $regex: new RegExp(args.searchRegex, 'i') @@ -60,19 +47,26 @@ export const resolver = { messagesOptions.limit = args.count; } + // exclude messages generated by server if (args.excludeServer === true) { messagesQuery.t = { $exists: false }; } - const messages = RocketChat.models.Messages.find( - Object.assign({}, messagesQuery, { rid: channel._id }), - messagesOptions - ); + // look for messages that belongs to specific channel + messagesQuery.rid = channel._id; + + const messages = RocketChat.models.Messages.find(messagesQuery, messagesOptions); messagesArray = messages.fetch(); if (isPagination) { - cursor = (messagesArray[messagesArray.length - 1] || {})._id; + // oldest first (because of findOne) + messagesOptions.sort.ts = 1; + + const firstMessage = RocketChat.models.Messages.findOne(messagesQuery, messagesOptions); + const lastId = (messagesArray[messagesArray.length - 1] || {})._id; + + cursor = !lastId || lastId === firstMessage._id ? null : lastId; } } @@ -84,3 +78,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js similarity index 75% rename from packages/rocketchat-graphql/server/schemas/messages/sendMessage.js rename to packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js index 430460b72de8..c0930382578b 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js @@ -1,14 +1,9 @@ /* global processWebhookMessage */ import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/messages/sendMessage.graphql'; -export const schema = ` - type Mutation { - sendMessage(channelId: String!, content: String!): Message - } -`; - -export const resolver = { +const resolver = { Mutation: { sendMessage: authenticated((root, { channelId, content }, { user }) => { const messageReturn = processWebhookMessage({ @@ -24,3 +19,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schemas/users/User-type.js b/packages/rocketchat-graphql/server/resolvers/users/User-type.js similarity index 65% rename from packages/rocketchat-graphql/server/schemas/users/User-type.js rename to packages/rocketchat-graphql/server/resolvers/users/User-type.js index 3891f47e1d65..6eede62b43ef 100644 --- a/packages/rocketchat-graphql/server/schemas/users/User-type.js +++ b/packages/rocketchat-graphql/server/resolvers/users/User-type.js @@ -1,19 +1,7 @@ -import { - property -} from '../../helpers/property'; +import { property } from '../../helpers/property'; +import schema from '../../schemas/users/User-type.graphql'; -export const schema = ` - extend type User { - status: UserStatus - avatar: String - name: String - lastLogin: String - channels: [Channel] - directMessages: [Channel] - } -`; - -export const resolver = { +const resolver = { User: { id: property('_id'), status: ({status}) => status.toUpperCase(), @@ -34,3 +22,8 @@ export const resolver = { } } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js b/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js new file mode 100644 index 000000000000..61c84d39a6e5 --- /dev/null +++ b/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js @@ -0,0 +1,5 @@ +import schema from '../../schemas/users/UserStatus-enum.graphql'; + +export { + schema +}; diff --git a/packages/rocketchat-graphql/server/schemas/users/index.js b/packages/rocketchat-graphql/server/resolvers/users/index.js similarity index 82% rename from packages/rocketchat-graphql/server/schemas/users/index.js rename to packages/rocketchat-graphql/server/resolvers/users/index.js index 7647d5a5fdd6..6de11371bf97 100644 --- a/packages/rocketchat-graphql/server/schemas/users/index.js +++ b/packages/rocketchat-graphql/server/resolvers/users/index.js @@ -1,4 +1,4 @@ -import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; // mutations import * as setStatus from './setStatus'; diff --git a/packages/rocketchat-graphql/server/schemas/users/setStatus.js b/packages/rocketchat-graphql/server/resolvers/users/setStatus.js similarity index 73% rename from packages/rocketchat-graphql/server/schemas/users/setStatus.js rename to packages/rocketchat-graphql/server/resolvers/users/setStatus.js index 6c61f4675b77..6d6f4aca4902 100644 --- a/packages/rocketchat-graphql/server/schemas/users/setStatus.js +++ b/packages/rocketchat-graphql/server/resolvers/users/setStatus.js @@ -1,12 +1,7 @@ import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/users/setStatus.graphql'; -export const schema = ` - type Mutation { - setStatus(status: UserStatus!): User - } -`; - -export const resolver = { +const resolver = { Mutation: { setStatus: authenticated((root, { status }, { user }) => { RocketChat.models.Users.update(user._id, { @@ -19,3 +14,8 @@ export const resolver = { }) } }; + +export { + schema, + resolver +}; diff --git a/packages/rocketchat-graphql/server/schema.js b/packages/rocketchat-graphql/server/schema.js index 3ee5b41532fa..1cbf6c38eeac 100644 --- a/packages/rocketchat-graphql/server/schema.js +++ b/packages/rocketchat-graphql/server/schema.js @@ -1,13 +1,10 @@ -import { - makeExecutableSchema -} from 'graphql-tools'; +import { makeExecutableSchema } from 'graphql-tools'; +import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; -import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; - -import * as channels from './schemas/channels'; -import * as messages from './schemas/messages'; -import * as accounts from './schemas/accounts'; -import * as users from './schemas/users'; +import * as channels from './resolvers/channels'; +import * as messages from './resolvers/messages'; +import * as accounts from './resolvers/accounts'; +import * as users from './resolvers/users'; const schema = mergeTypes([ channels.schema, diff --git a/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphql b/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphql new file mode 100644 index 000000000000..0bdf1ed7e00b --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphql @@ -0,0 +1,4 @@ +type LoginResult { + accessToken: String! + refreshToken: String! +} diff --git a/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.js b/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.js deleted file mode 100644 index 4a0a7c8397b4..000000000000 --- a/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.js +++ /dev/null @@ -1,6 +0,0 @@ -export const schema = ` - type LoginResult { - accessToken: String! - refreshToken: String! - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphql b/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphql new file mode 100644 index 000000000000..c91fe5e6379a --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphql @@ -0,0 +1,3 @@ +type OauthProvider { + name: String! +} diff --git a/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.js b/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.js deleted file mode 100644 index dd4a4253fd37..000000000000 --- a/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.js +++ /dev/null @@ -1,5 +0,0 @@ -export const schema = ` - type OauthProvider { - name: String! - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphql b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphql new file mode 100644 index 000000000000..9ba76de8adb8 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphql @@ -0,0 +1,3 @@ +type Query { + oauthProviders: [OauthProvider] +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphql b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphql new file mode 100644 index 000000000000..03c4557918df --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphql @@ -0,0 +1,16 @@ +type Channel { + id: String! + name: String + description: String + announcement: String + topic: String + members: [User] + owners: [User] + numberOfMembers: Int + numberOfMessages: Int + readOnly: Boolean + direct: Boolean + privateChannel: Boolean + favourite: Boolean + unseenMessages: Int +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphql b/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphql new file mode 100644 index 000000000000..a00850e371cc --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphql @@ -0,0 +1,6 @@ +input ChannelFilter { + nameFilter: String + privacy: Privacy + joinedChannels: Boolean + sortBy: ChannelSort +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.js b/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.js deleted file mode 100644 index b80d4c680a95..000000000000 --- a/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.js +++ /dev/null @@ -1,8 +0,0 @@ -export const schema = ` - input ChannelFilter { - nameFilter: String - privacy: Privacy - joinedChannels: Boolean - sortBy: ChannelSort - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphql b/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphql new file mode 100644 index 000000000000..139567e862e9 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphql @@ -0,0 +1,4 @@ +input ChannelNameAndDirect { + name: String! + direct: Boolean! +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.js b/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.js deleted file mode 100644 index f3bbda3125d1..000000000000 --- a/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.js +++ /dev/null @@ -1,6 +0,0 @@ -export const schema = ` - input ChannelNameAndDirect { - name: String! - direct: Boolean! - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphql b/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphql new file mode 100644 index 000000000000..8a2c2902e6db --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphql @@ -0,0 +1,4 @@ +enum ChannelSort { + NAME + NUMBER_OF_MESSAGES +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.js b/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.js deleted file mode 100644 index beecdedd89ef..000000000000 --- a/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.js +++ /dev/null @@ -1,6 +0,0 @@ -export const schema = ` - enum ChannelSort { - NAME - NUMBER_OF_MESSAGES - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphql b/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphql new file mode 100644 index 000000000000..f28a57d51c28 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphql @@ -0,0 +1,5 @@ +enum Privacy { + PRIVATE + PUBLIC + ALL +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.js b/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.js deleted file mode 100644 index d0cd977a9470..000000000000 --- a/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.js +++ /dev/null @@ -1,7 +0,0 @@ -export const schema = ` - enum Privacy { - PRIVATE - PUBLIC - ALL - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.graphql b/packages/rocketchat-graphql/server/schemas/channels/channelByName.graphql new file mode 100644 index 000000000000..e301ce38f7f6 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/channelByName.graphql @@ -0,0 +1,3 @@ +type Query { + channelByName(name: String!): Channel +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.graphql b/packages/rocketchat-graphql/server/schemas/channels/channels.graphql new file mode 100644 index 000000000000..6e4ac5608249 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/channels.graphql @@ -0,0 +1,7 @@ +type Query { + channels(filter: ChannelFilter = { + privacy: ALL, + joinedChannels: false, + sortBy: NAME + }): [Channel] +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphql b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphql new file mode 100644 index 000000000000..8dfe20a071c5 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphql @@ -0,0 +1,3 @@ +type Query { + channelsByUser(userId: String!): [Channel] +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.graphql b/packages/rocketchat-graphql/server/schemas/channels/createChannel.graphql new file mode 100644 index 000000000000..85317c86603a --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/createChannel.graphql @@ -0,0 +1,8 @@ +type Mutation { + createChannel( + name: String!, + private: Boolean = false, + readOnly: Boolean = false, + membersId: [String!] + ): Channel +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js b/packages/rocketchat-graphql/server/schemas/channels/createChannel.js deleted file mode 100644 index c87e88991767..000000000000 --- a/packages/rocketchat-graphql/server/schemas/channels/createChannel.js +++ /dev/null @@ -1,45 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import { authenticated } from '../../helpers/authenticated'; - -export const schema = ` - type Mutation { - createChannel( - name: String!, - private: Boolean = false, - readOnly: Boolean = false, - membersId: [String!] - ): Channel - } -`; - -export const resolver = { - Mutation: { - createChannel: authenticated((root, args, { user }) => { - if (!RocketChat.authz.hasPermission(user._id, 'create-c')) { - return RocketChat.API.v1.unauthorized(); - } - - if (!args.name) { - throw new Error('Param "name" is required'); - } - - if (args.membersId && !_.isArray(args.membersId)) { - throw new Error('Param "membersId" must be an array if provided'); - } - - let readOnly = false; - if (typeof args.readOnly !== 'undefined') { - readOnly = args.readOnly; - } - - let id; - Meteor.runAsUser(user._id, () => { - id = Meteor.call('createChannel', args.name, args.membersId ? args.membersId : [], readOnly); - }); - - return RocketChat.models.Rooms.findOneById(id.rid, { fields: RocketChat.API.v1.defaultFieldsToExclude }); - }) - } -}; - diff --git a/packages/rocketchat-graphql/server/schemas/channels/directChannel.graphql b/packages/rocketchat-graphql/server/schemas/channels/directChannel.graphql new file mode 100644 index 000000000000..4e41994bce80 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/directChannel.graphql @@ -0,0 +1,3 @@ +type Query { + directChannel(username: String, channelId: String): Channel +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphql b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphql new file mode 100644 index 000000000000..5ea9517f5741 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphql @@ -0,0 +1,3 @@ +type Mutation { + hideChannel(channelId: String!): Boolean +} diff --git a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphql b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphql new file mode 100644 index 000000000000..e6ceb4075c4e --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphql @@ -0,0 +1,3 @@ +type Mutation { + leaveChannel(channelId: String!): Boolean +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.graphql b/packages/rocketchat-graphql/server/schemas/messages/Message-type.graphql new file mode 100644 index 000000000000..8ccfdebfbf1d --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/Message-type.graphql @@ -0,0 +1,15 @@ +type Message { + id: String + author: User + content: String + channel: Channel + creationTime: Float + # Message sent by server e.g. User joined channel + fromServer: Boolean + type: String + # List of mentioned users + userRef: [User] + # list of mentioned channels + channelRef: [Channel] + reactions: [Reaction] +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphql b/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphql new file mode 100644 index 000000000000..88fbe90711cf --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphql @@ -0,0 +1,4 @@ +input MessageIdentifier { + channelId: String! + messageId: String! +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.js b/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.js deleted file mode 100644 index bb8571477bfe..000000000000 --- a/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.js +++ /dev/null @@ -1,6 +0,0 @@ -export const schema = ` - input MessageIdentifier { - channelId: String! - messageId: String! - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphql b/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphql new file mode 100644 index 000000000000..e890725f6efb --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphql @@ -0,0 +1,5 @@ +type MessagesWithCursor { + cursor: String + channel: Channel + messagesArray: [Message] +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.js b/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.js deleted file mode 100644 index b70b287321b8..000000000000 --- a/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.js +++ /dev/null @@ -1,7 +0,0 @@ -export const schema = ` - type MessagesWithCursor { - cursor: String - channel: Channel - messagesArray: [Message] - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphql b/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphql new file mode 100644 index 000000000000..e6eedf75d1e1 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphql @@ -0,0 +1,4 @@ +type Reaction { + username: String + icon: String +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.js b/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.js deleted file mode 100644 index c337f52ce6bf..000000000000 --- a/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.js +++ /dev/null @@ -1,6 +0,0 @@ -export const schema = ` - type Reaction { - username: String - icon: String - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphql b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphql new file mode 100644 index 000000000000..61c74c26c499 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphql @@ -0,0 +1,3 @@ +type Mutation { + addReactionToMassage(id: MessageIdentifier!, icon: String!): Message +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphql b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphql new file mode 100644 index 000000000000..f88b2979ca5a --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphql @@ -0,0 +1,3 @@ +type Subscription { + chatMessageAdded(channelId: String!): Message +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphql b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphql new file mode 100644 index 000000000000..f298a14ebf98 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphql @@ -0,0 +1,3 @@ +type Mutation { + deleteMessage(id: MessageIdentifier!): Message +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/editMessage.graphql b/packages/rocketchat-graphql/server/schemas/messages/editMessage.graphql new file mode 100644 index 000000000000..19900c58b272 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/editMessage.graphql @@ -0,0 +1,3 @@ +type Mutation { + editMessage(id: MessageIdentifier!, content: String!): Message +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.graphql b/packages/rocketchat-graphql/server/schemas/messages/messages.graphql new file mode 100644 index 000000000000..2b9774942e76 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.graphql @@ -0,0 +1,11 @@ +type Query { + messages( + channelId: String, + channelDetails: ChannelNameAndDirect, + channelName: String, + cursor: String, + count: Int, + searchRegex: String, + excludeServer: Boolean + ): MessagesWithCursor +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphql b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphql new file mode 100644 index 000000000000..6f160fef1c94 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphql @@ -0,0 +1,3 @@ +type Mutation { + sendMessage(channelId: String!, content: String!): Message +} diff --git a/packages/rocketchat-graphql/server/schemas/users/User-type.graphql b/packages/rocketchat-graphql/server/schemas/users/User-type.graphql new file mode 100644 index 000000000000..2a345415227e --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/users/User-type.graphql @@ -0,0 +1,8 @@ +extend type User { + status: UserStatus + avatar: String + name: String + lastLogin: String + channels: [Channel] + directMessages: [Channel] +} diff --git a/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphql b/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphql new file mode 100644 index 000000000000..a360cc2a72b9 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphql @@ -0,0 +1,7 @@ +enum UserStatus { + ONLINE + AWAY + BUSY + INVISIBLE + OFFLINE +} diff --git a/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.js b/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.js deleted file mode 100644 index 5e821bb5ee2a..000000000000 --- a/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.js +++ /dev/null @@ -1,9 +0,0 @@ -export const schema = ` - enum UserStatus { - ONLINE - AWAY - BUSY - INVISIBLE - OFFLINE - } -`; diff --git a/packages/rocketchat-graphql/server/schemas/users/setStatus.graphql b/packages/rocketchat-graphql/server/schemas/users/setStatus.graphql new file mode 100644 index 000000000000..7beb3512a91b --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/users/setStatus.graphql @@ -0,0 +1,3 @@ +type Mutation { + setStatus(status: UserStatus!): User +} From dfe8d1448a51193795949dde0a3bbca16dee1535 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Sat, 2 Sep 2017 12:26:44 +0200 Subject: [PATCH 093/801] WIP - LAST ONE --- .../.npm/package/npm-shrinkwrap.json | 4 +- packages/rocketchat-accounts/README.md | 3 + packages/rocketchat-accounts/server/config.js | 1 - packages/rocketchat-accounts/server/index.js | 1 - .../rocketchat-grant/server/authenticate.js | 1 + packages/rocketchat-grant/server/grant.js | 2 + .../.npm/package/npm-shrinkwrap.json | 215 +++++++++--------- packages/rocketchat-graphql/package.js | 3 +- packages/rocketchat-graphql/server/api.js | 10 +- .../server/helpers/authenticated.js | 1 - .../server/helpers/property.js | 3 - .../resolvers/accounts/OauthProvider-type.js | 2 +- .../server/resolvers/accounts/index.js | 2 +- .../resolvers/accounts/oauthProviders.js | 2 +- .../server/resolvers/channels/Channel-type.js | 6 +- .../resolvers/channels/ChannelFilter-input.js | 2 +- .../channels/ChannelNameAndDirect-input.js | 2 +- .../resolvers/channels/ChannelSort-enum.js | 2 +- .../server/resolvers/channels/Privacy-enum.js | 2 +- .../resolvers/channels/channelByName.js | 4 +- .../server/resolvers/channels/channels.js | 4 +- .../resolvers/channels/channelsByUser.js | 4 +- .../resolvers/channels/createChannel.js | 4 +- .../resolvers/channels/directChannel.js | 4 +- .../server/resolvers/channels/hideChannel.js | 3 +- .../server/resolvers/channels/leaveChannel.js | 3 +- .../server/resolvers/messages/Message-type.js | 6 +- .../messages/MessageIdentifier-input.js | 2 +- .../messages/MessagesWithCursor-type.js | 2 +- .../resolvers/messages/Reaction-type.js | 2 +- .../messages/addReactionToMessage.js | 3 +- .../resolvers/messages/chatMessageAdded.js | 32 ++- .../resolvers/messages/deleteMessage.js | 3 +- .../server/resolvers/messages/editMessage.js | 3 +- .../server/resolvers/messages/messages.js | 22 +- .../server/resolvers/messages/sendMessage.js | 14 +- .../server/resolvers/users/User-type.js | 6 +- .../server/resolvers/users/UserStatus-enum.js | 2 +- .../server/resolvers/users/setStatus.js | 4 +- ...type.graphql => LoginResult-type.graphqls} | 0 ...pe.graphql => OauthProvider-type.graphqls} | 0 ...viders.graphql => oauthProviders.graphqls} | 0 ...nel-type.graphql => Channel-type.graphqls} | 0 ...t.graphql => ChannelFilter-input.graphqls} | 0 ...ql => ChannelNameAndDirect-input.graphqls} | 0 ...enum.graphql => ChannelSort-enum.graphqls} | 0 ...acy-enum.graphql => Privacy-enum.graphqls} | 0 ...lByName.graphql => channelByName.graphqls} | 0 .../{channels.graphql => channels.graphqls} | 0 ...ByUser.graphql => channelsByUser.graphqls} | 0 ...Channel.graphql => createChannel.graphqls} | 0 ...Channel.graphql => directChannel.graphqls} | 0 ...deChannel.graphql => hideChannel.graphqls} | 0 ...eChannel.graphql => leaveChannel.graphqls} | 0 ...age-type.graphql => Message-type.graphqls} | 0 ...aphql => MessageIdentifier-input.graphqls} | 0 ...aphql => MessagesWithCursor-type.graphqls} | 0 ...on-type.graphql => Reaction-type.graphqls} | 0 ....graphql => addReactionToMessage.graphqls} | 0 .../schemas/messages/chatMessageAdded.graphql | 3 - .../messages/chatMessageAdded.graphqls | 3 + ...Message.graphql => deleteMessage.graphqls} | 0 ...itMessage.graphql => editMessage.graphqls} | 0 .../{messages.graphql => messages.graphqls} | 2 +- .../schemas/messages/sendMessage.graphql | 3 - .../schemas/messages/sendMessage.graphqls | 3 + .../{User-type.graphql => User-type.graphqls} | 0 ...-enum.graphql => UserStatus-enum.graphqls} | 0 .../{setStatus.graphql => setStatus.graphqls} | 0 69 files changed, 232 insertions(+), 173 deletions(-) create mode 100644 packages/rocketchat-accounts/README.md delete mode 100644 packages/rocketchat-graphql/server/helpers/property.js rename packages/rocketchat-graphql/server/schemas/accounts/{LoginResult-type.graphql => LoginResult-type.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/accounts/{OauthProvider-type.graphql => OauthProvider-type.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/accounts/{oauthProviders.graphql => oauthProviders.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{Channel-type.graphql => Channel-type.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{ChannelFilter-input.graphql => ChannelFilter-input.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{ChannelNameAndDirect-input.graphql => ChannelNameAndDirect-input.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{ChannelSort-enum.graphql => ChannelSort-enum.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{Privacy-enum.graphql => Privacy-enum.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{channelByName.graphql => channelByName.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{channels.graphql => channels.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{channelsByUser.graphql => channelsByUser.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{createChannel.graphql => createChannel.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{directChannel.graphql => directChannel.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{hideChannel.graphql => hideChannel.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/channels/{leaveChannel.graphql => leaveChannel.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/messages/{Message-type.graphql => Message-type.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/messages/{MessageIdentifier-input.graphql => MessageIdentifier-input.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/messages/{MessagesWithCursor-type.graphql => MessagesWithCursor-type.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/messages/{Reaction-type.graphql => Reaction-type.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/messages/{addReactionToMessage.graphql => addReactionToMessage.graphqls} (100%) delete mode 100644 packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphqls rename packages/rocketchat-graphql/server/schemas/messages/{deleteMessage.graphql => deleteMessage.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/messages/{editMessage.graphql => editMessage.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/messages/{messages.graphql => messages.graphqls} (81%) delete mode 100644 packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphql create mode 100644 packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphqls rename packages/rocketchat-graphql/server/schemas/users/{User-type.graphql => User-type.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/users/{UserStatus-enum.graphql => UserStatus-enum.graphqls} (100%) rename packages/rocketchat-graphql/server/schemas/users/{setStatus.graphql => setStatus.graphqls} (100%) diff --git a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json index 720452518c3b..9bee17427949 100644 --- a/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-accounts/.npm/package/npm-shrinkwrap.json @@ -53,8 +53,8 @@ "from": "bufferjs@1.1.0" }, "core-js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", "from": "core-js@>=2.5.0 <3.0.0" }, "core-util-is": { diff --git a/packages/rocketchat-accounts/README.md b/packages/rocketchat-accounts/README.md new file mode 100644 index 000000000000..91ee3cc93aa5 --- /dev/null +++ b/packages/rocketchat-accounts/README.md @@ -0,0 +1,3 @@ +# rocketchat:accounts + +Integration with `js-accounts` system. diff --git a/packages/rocketchat-accounts/server/config.js b/packages/rocketchat-accounts/server/config.js index 621db418d784..21a6629b0b08 100644 --- a/packages/rocketchat-accounts/server/config.js +++ b/packages/rocketchat-accounts/server/config.js @@ -7,7 +7,6 @@ Meteor.startup(() => { const mongodb = MongoInternals.defaultRemoteCollectionDriver().mongo.db; const mongoAdapter = new MongoAdapter(mongodb, { - // XXX: UserId in RocketChat is a string(17) value convertUserIdToMongoObjectId: false }); diff --git a/packages/rocketchat-accounts/server/index.js b/packages/rocketchat-accounts/server/index.js index 88ebb9b52977..7651774b4e8c 100644 --- a/packages/rocketchat-accounts/server/index.js +++ b/packages/rocketchat-accounts/server/index.js @@ -1,4 +1,3 @@ -// import './fix'; import './config'; import AccountsServer from '@accounts/server'; diff --git a/packages/rocketchat-grant/server/authenticate.js b/packages/rocketchat-grant/server/authenticate.js index ad68fb009681..7e5aae261e1f 100644 --- a/packages/rocketchat-grant/server/authenticate.js +++ b/packages/rocketchat-grant/server/authenticate.js @@ -1,4 +1,5 @@ import { AccountsServer } from 'meteor/rocketchat:accounts'; +import { RocketChat } from 'meteor/rocketchat:lib'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; diff --git a/packages/rocketchat-grant/server/grant.js b/packages/rocketchat-grant/server/grant.js index 0f8890652909..b4adfd3081dd 100644 --- a/packages/rocketchat-grant/server/grant.js +++ b/packages/rocketchat-grant/server/grant.js @@ -1,3 +1,5 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + import Providers from './providers'; import Settings from './settings'; import { path, generateCallback, generateAppCallback } from './routes'; diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json index 6a2374ea66c7..10d14533cd41 100644 --- a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -3,510 +3,505 @@ "accepts": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "from": "accepts@https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz" + "from": "accepts@>=1.3.3 <1.4.0" }, "apollo-server-core": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-1.1.0.tgz", - "from": "apollo-server-core@https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-1.1.0.tgz" + "from": "apollo-server-core@>=1.1.0 <2.0.0" }, "apollo-server-express": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-1.1.2.tgz", - "from": "apollo-server-express@https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-1.1.2.tgz" + "from": "apollo-server-express@1.1.2" }, "apollo-server-module-graphiql": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.2.tgz", - "from": "apollo-server-module-graphiql@https://registry.npmjs.org/apollo-server-module-graphiql/-/apollo-server-module-graphiql-1.1.2.tgz" + "from": "apollo-server-module-graphiql@>=1.1.2 <2.0.0" }, "apollo-tracing": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.0.7.tgz", - "from": "apollo-tracing@https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.0.7.tgz" + "from": "apollo-tracing@>=0.0.7 <0.0.8" }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "from": "array-flatten@https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + "from": "array-flatten@1.1.1" }, "babel-polyfill": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "from": "babel-polyfill@https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "from": "babel-polyfill@>=6.23.0 <7.0.0", "dependencies": { "regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "from": "regenerator-runtime@https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz" + "from": "regenerator-runtime@>=0.10.5 <0.11.0" } } }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "from": "babel-runtime@https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" + "from": "babel-runtime@>=6.23.0 <7.0.0" }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "from": "backo2@https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz" + "from": "backo2@>=1.0.2 <2.0.0" }, "base64url": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", - "from": "base64url@https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz" + "from": "base64url@>=2.0.0 <3.0.0" }, "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "from": "bcryptjs@https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz" + "from": "bcryptjs@>=2.4.0 <3.0.0" }, "body-parser": { "version": "1.17.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz", - "from": "body-parser@https://registry.npmjs.org/body-parser/-/body-parser-1.17.2.tgz" + "from": "body-parser@1.17.2" }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "from": "buffer-equal-constant-time@https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" + "from": "buffer-equal-constant-time@1.0.1" }, "bytes": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "from": "bytes@https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz" + "from": "bytes@2.4.0" }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "from": "content-disposition@https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz" + "from": "content-disposition@0.5.2" }, "content-type": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", - "from": "content-type@https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz" + "from": "content-type@>=1.0.2 <1.1.0" }, "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "from": "cookie@https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz" + "from": "cookie@0.3.1" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "from": "cookie-signature@https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + "from": "cookie-signature@1.0.6" }, "core-js": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz", - "from": "core-js@https://registry.npmjs.org/core-js/-/core-js-2.5.0.tgz" + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "from": "core-js@>=2.4.0 <3.0.0" }, "cors": { "version": "2.8.4", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", - "from": "cors@https://registry.npmjs.org/cors/-/cors-2.8.4.tgz" + "from": "cors@2.8.4" }, "crypto": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/crypto/-/crypto-0.0.3.tgz", - "from": "crypto@https://registry.npmjs.org/crypto/-/crypto-0.0.3.tgz" + "from": "crypto@>=0.0.3 <0.0.4" }, "debug": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", - "from": "debug@https://registry.npmjs.org/debug/-/debug-2.6.7.tgz" + "from": "debug@2.6.7" }, "deepmerge": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.1.tgz", - "from": "deepmerge@https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.1.tgz" + "from": "deepmerge@>=1.3.2 <2.0.0" }, "depd": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "from": "depd@https://registry.npmjs.org/depd/-/depd-1.1.1.tgz" + "from": "depd@>=1.1.0 <1.2.0" }, "deprecated-decorator": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz", - "from": "deprecated-decorator@https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz" + "from": "deprecated-decorator@>=0.1.6 <0.2.0" }, "destroy": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "from": "destroy@https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" + "from": "destroy@>=1.0.4 <1.1.0" }, "ecdsa-sig-formatter": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", - "from": "ecdsa-sig-formatter@https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz" + "from": "ecdsa-sig-formatter@1.0.9" }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "from": "ee-first@https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + "from": "ee-first@1.1.1" }, "encodeurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "from": "encodeurl@https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz" + "from": "encodeurl@>=1.0.1 <1.1.0" }, "es6-promise": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", - "from": "es6-promise@https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz" + "from": "es6-promise@>=4.0.5 <5.0.0" }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "from": "escape-html@https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + "from": "escape-html@>=1.0.3 <1.1.0" }, "etag": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", - "from": "etag@https://registry.npmjs.org/etag/-/etag-1.8.0.tgz" + "from": "etag@>=1.8.0 <1.9.0" }, "eventemitter3": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", - "from": "eventemitter3@https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz" + "from": "eventemitter3@>=2.0.3 <3.0.0" }, "express": { "version": "4.15.4", "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz", - "from": "express@https://registry.npmjs.org/express/-/express-4.15.4.tgz", + "from": "express@4.15.4", "dependencies": { "debug": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "from": "debug@https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "from": "debug@2.6.8" }, "qs": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz", - "from": "qs@https://registry.npmjs.org/qs/-/qs-6.5.0.tgz" + "from": "qs@6.5.0" } } }, "finalhandler": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz", - "from": "finalhandler@https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz", + "from": "finalhandler@>=1.0.4 <1.1.0", "dependencies": { "debug": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "from": "debug@https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "from": "debug@2.6.8" } } }, "forwarded": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", - "from": "forwarded@https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz" + "from": "forwarded@>=0.1.0 <0.2.0" }, "fresh": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", - "from": "fresh@https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz" + "from": "fresh@0.5.0" }, "graphql": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.10.3.tgz", - "from": "graphql@https://registry.npmjs.org/graphql/-/graphql-0.10.3.tgz" + "from": "graphql@0.10.3" }, "graphql-subscriptions": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-0.4.4.tgz", - "from": "graphql-subscriptions@https://registry.npmjs.org/graphql-subscriptions/-/graphql-subscriptions-0.4.4.tgz" + "from": "graphql-subscriptions@0.4.4" }, "graphql-tag": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.4.2.tgz", - "from": "graphql-tag@https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.4.2.tgz" + "from": "graphql-tag@>=2.4.2 <3.0.0" }, "graphql-tools": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.2.2.tgz", - "from": "graphql-tools@https://registry.npmjs.org/graphql-tools/-/graphql-tools-1.2.2.tgz" + "from": "graphql-tools@1.2.2" }, "hoek": { "version": "2.16.3", "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "from": "hoek@https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz" + "from": "hoek@>=2.0.0 <3.0.0" }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "from": "http-errors@https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz" + "from": "http-errors@>=1.6.1 <1.7.0" }, "iconv-lite": { "version": "0.4.15", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz", - "from": "iconv-lite@https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz" + "from": "iconv-lite@0.4.15" }, "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "from": "inherits@https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" + "from": "inherits@2.0.3" }, "ipaddr.js": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", - "from": "ipaddr.js@https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz" + "from": "ipaddr.js@1.4.0" }, "isemail": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "from": "isemail@https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz" + "from": "isemail@>=1.0.0 <2.0.0" }, "iterall": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.1.tgz", - "from": "iterall@https://registry.npmjs.org/iterall/-/iterall-1.1.1.tgz" + "from": "iterall@>=1.1.0 <2.0.0" }, "joi": { "version": "6.10.1", "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "from": "joi@https://registry.npmjs.org/joi/-/joi-6.10.1.tgz" + "from": "joi@>=6.10.1 <7.0.0" }, "jsonwebtoken": { "version": "7.4.3", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz", - "from": "jsonwebtoken@https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz" + "from": "jsonwebtoken@>=7.2.1 <8.0.0" }, "jwa": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", - "from": "jwa@https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz" + "from": "jwa@>=1.1.4 <2.0.0" }, "jws": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", - "from": "jws@https://registry.npmjs.org/jws/-/jws-3.1.4.tgz" + "from": "jws@>=3.1.4 <4.0.0" }, "jwt-decode": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", - "from": "jwt-decode@https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz" - }, - "kamilkisiela-graphql-api": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/kamilkisiela-graphql-api/-/kamilkisiela-graphql-api-0.1.1.tgz", - "from": "kamilkisiela-graphql-api@https://registry.npmjs.org/kamilkisiela-graphql-api/-/kamilkisiela-graphql-api-0.1.1.tgz" + "from": "jwt-decode@>=2.1.0 <3.0.0" }, "kamilkisiela-merge-graphql-schemas": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/kamilkisiela-merge-graphql-schemas/-/kamilkisiela-merge-graphql-schemas-1.1.2.tgz", - "from": "kamilkisiela-merge-graphql-schemas@https://registry.npmjs.org/kamilkisiela-merge-graphql-schemas/-/kamilkisiela-merge-graphql-schemas-1.1.2.tgz" + "from": "kamilkisiela-merge-graphql-schemas@1.1.2" }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "from": "lodash@https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz" + "from": "lodash@>=4.16.4 <5.0.0" }, "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "from": "lodash.assign@https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz" + "from": "lodash.assign@>=4.2.0 <5.0.0" }, "lodash.isobject": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "from": "lodash.isobject@https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz" + "from": "lodash.isobject@>=3.0.2 <4.0.0" }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "from": "lodash.isstring@https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" + "from": "lodash.isstring@>=4.0.1 <5.0.0" }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "from": "lodash.once@https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" + "from": "lodash.once@>=4.0.0 <5.0.0" + }, + "lodash.property": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.property/-/lodash.property-4.4.2.tgz", + "from": "lodash.property@4.4.2" }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "from": "media-typer@https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + "from": "media-typer@0.3.0" }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "from": "merge-descriptors@https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" - }, - "meteor-promise": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.6.tgz", - "from": "meteor-promise@https://registry.npmjs.org/meteor-promise/-/meteor-promise-0.8.6.tgz" + "from": "merge-descriptors@1.0.1" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "from": "methods@https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + "from": "methods@>=1.1.2 <1.2.0" }, "mime": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "from": "mime@https://registry.npmjs.org/mime/-/mime-1.3.4.tgz" + "from": "mime@1.3.4" }, "mime-db": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", - "from": "mime-db@https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz" + "from": "mime-db@>=1.29.0 <1.30.0" }, "mime-types": { "version": "2.1.16", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", - "from": "mime-types@https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz" + "from": "mime-types@>=2.1.15 <2.2.0" }, "moment": { "version": "2.18.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", - "from": "moment@https://registry.npmjs.org/moment/-/moment-2.18.1.tgz" + "from": "moment@>=2.0.0 <3.0.0" }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "from": "ms@https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + "from": "ms@>=2.0.0 <3.0.0" }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "from": "negotiator@https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz" + "from": "negotiator@0.6.1" }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "from": "object-assign@https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + "from": "object-assign@>=4.0.0 <5.0.0" }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "from": "on-finished@https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" + "from": "on-finished@>=2.3.0 <2.4.0" }, "parseurl": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "from": "parseurl@https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz" + "from": "parseurl@>=1.3.1 <1.4.0" }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "from": "path-to-regexp@https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + "from": "path-to-regexp@0.1.7" }, "proxy-addr": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", - "from": "proxy-addr@https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz" + "from": "proxy-addr@>=1.1.5 <1.2.0" }, "qs": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "from": "qs@https://registry.npmjs.org/qs/-/qs-6.4.0.tgz" + "from": "qs@6.4.0" }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "from": "range-parser@https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" + "from": "range-parser@>=1.2.0 <1.3.0" }, "raw-body": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz", - "from": "raw-body@https://registry.npmjs.org/raw-body/-/raw-body-2.2.0.tgz" + "from": "raw-body@>=2.2.0 <2.3.0" }, "regenerator-runtime": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", - "from": "regenerator-runtime@https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz" + "from": "regenerator-runtime@>=0.11.0 <0.12.0" }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "from": "safe-buffer@https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz" + "from": "safe-buffer@>=5.0.1 <6.0.0" }, "send": { "version": "0.15.4", "resolved": "https://registry.npmjs.org/send/-/send-0.15.4.tgz", - "from": "send@https://registry.npmjs.org/send/-/send-0.15.4.tgz", + "from": "send@0.15.4", "dependencies": { "debug": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "from": "debug@https://registry.npmjs.org/debug/-/debug-2.6.8.tgz" + "from": "debug@2.6.8" } } }, "serve-static": { "version": "1.12.4", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz", - "from": "serve-static@https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz" + "from": "serve-static@1.12.4" }, "setprototypeof": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "from": "setprototypeof@https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz" + "from": "setprototypeof@1.0.3" }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "from": "statuses@https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz" + "from": "statuses@>=1.3.1 <2.0.0" }, "subscriptions-transport-ws": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.8.2.tgz", - "from": "subscriptions-transport-ws@https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.8.2.tgz" + "from": "subscriptions-transport-ws@0.8.2" }, "symbol-observable": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", - "from": "symbol-observable@https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz" + "from": "symbol-observable@>=1.0.4 <2.0.0" }, "topo": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "from": "topo@https://registry.npmjs.org/topo/-/topo-1.1.0.tgz" + "from": "topo@>=1.0.0 <2.0.0" }, "type-is": { "version": "1.6.15", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "from": "type-is@https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz" + "from": "type-is@>=1.6.15 <1.7.0" }, "ultron": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz", - "from": "ultron@https://registry.npmjs.org/ultron/-/ultron-1.1.0.tgz" + "from": "ultron@>=1.1.0 <1.2.0" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "from": "unpipe@https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + "from": "unpipe@1.0.0" }, "utils-merge": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "from": "utils-merge@https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz" + "from": "utils-merge@1.0.0" }, "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "from": "uuid@https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz" + "from": "uuid@>=3.0.1 <4.0.0" }, "vary": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", - "from": "vary@https://registry.npmjs.org/vary/-/vary-1.1.1.tgz" + "from": "vary@>=1.0.0 <2.0.0" }, "ws": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ws/-/ws-3.1.0.tgz", - "from": "ws@https://registry.npmjs.org/ws/-/ws-3.1.0.tgz" + "from": "ws@>=3.0.0 <4.0.0" }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "from": "xtend@https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz" + "from": "xtend@>=4.0.1 <5.0.0" } } } diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js index def84c4c84c9..8d6ff940e0c1 100644 --- a/packages/rocketchat-graphql/package.js +++ b/packages/rocketchat-graphql/package.js @@ -20,7 +20,7 @@ Package.onUse(function(api) { }); Npm.depends({ - 'kamilkisiela-graphql-api': '0.1.1', + '@accounts/graphql-api': '0.1.1', 'apollo-server-express': '1.1.2', 'cors': '2.8.4', 'body-parser': '1.17.2', @@ -28,6 +28,7 @@ Npm.depends({ 'graphql': '0.10.3', 'graphql-subscriptions': '0.4.4', 'graphql-tools': '1.2.2', + 'lodash.property': '4.4.2', 'kamilkisiela-merge-graphql-schemas': '1.1.2', 'subscriptions-transport-ws': '0.8.2' }); diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index 9c1f36c00a90..494429f52e97 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -1,5 +1,5 @@ import { graphqlExpress, graphiqlExpress } from 'apollo-server-express'; -import { JSAccountsContext as jsAccountsContext } from 'kamilkisiela-graphql-api'; +import { JSAccountsContext as jsAccountsContext } from '@accounts/graphql-api'; import { SubscriptionServer } from 'subscriptions-transport-ws'; import { execute, subscribe } from 'graphql'; import { Meteor } from 'meteor/meteor'; @@ -41,7 +41,13 @@ graphQLServer.use('/graphiql', graphiqlExpress({ new SubscriptionServer({ schema: executableSchema, execute, - subscribe + subscribe, + onOperation: ({context}) => { + console.log('context', context); + return { + authToken: context.Authorization + }; + } }, { path: '/subscriptions', diff --git a/packages/rocketchat-graphql/server/helpers/authenticated.js b/packages/rocketchat-graphql/server/helpers/authenticated.js index c36223b94b5a..44c54e053996 100644 --- a/packages/rocketchat-graphql/server/helpers/authenticated.js +++ b/packages/rocketchat-graphql/server/helpers/authenticated.js @@ -1,6 +1,5 @@ import { AccountsServer } from 'meteor/rocketchat:accounts'; //import { authenticated as _authenticated } from '@accounts/graphql-api'; -// import { authenticated as _authenticated } from 'kamilkisiela-graphql-api'; import { authenticated as _authenticated } from '../mocks/accounts/graphql-api'; export const authenticated = (resolver) => { diff --git a/packages/rocketchat-graphql/server/helpers/property.js b/packages/rocketchat-graphql/server/helpers/property.js deleted file mode 100644 index 65485cae9868..000000000000 --- a/packages/rocketchat-graphql/server/helpers/property.js +++ /dev/null @@ -1,3 +0,0 @@ -export function property(key) { - return (object) => object == null ? undefined : object[key]; -} diff --git a/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js b/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js index fd13e7f61106..7cf39ff56139 100644 --- a/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js +++ b/packages/rocketchat-graphql/server/resolvers/accounts/OauthProvider-type.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/accounts/OauthProvider-type.graphql'; +import schema from '../../schemas/accounts/OauthProvider-type.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/accounts/index.js b/packages/rocketchat-graphql/server/resolvers/accounts/index.js index 57d98cce5962..02aceb574911 100644 --- a/packages/rocketchat-graphql/server/resolvers/accounts/index.js +++ b/packages/rocketchat-graphql/server/resolvers/accounts/index.js @@ -1,4 +1,4 @@ -import { createJSAccountsGraphQL } from 'kamilkisiela-graphql-api'; +import { createJSAccountsGraphQL } from '@accounts/graphql-api'; import { AccountsServer } from 'meteor/rocketchat:accounts'; import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; diff --git a/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js b/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js index 0cccbc9381d9..de487b8f9265 100644 --- a/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js +++ b/packages/rocketchat-graphql/server/resolvers/accounts/oauthProviders.js @@ -1,7 +1,7 @@ import { HTTP } from 'meteor/http'; import { Meteor } from 'meteor/meteor'; -import schema from '../../schemas/accounts/oauthProviders.graphql'; +import schema from '../../schemas/accounts/oauthProviders.graphqls'; function isJSON(obj) { try { diff --git a/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js b/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js index e4dfb9ba4371..e16dffa8ab83 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/Channel-type.js @@ -1,5 +1,7 @@ -import { property } from '../../helpers/property'; -import schema from '../../schemas/channels/Channel-type.graphql'; +import { RocketChat } from 'meteor/rocketchat:lib'; +import property from 'lodash.property'; + +import schema from '../../schemas/channels/Channel-type.graphqls'; const resolver = { Channel: { diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js index 54c5be23b0ff..cb1c26b0efa5 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelFilter-input.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/channels/ChannelFilter-input.graphql'; +import schema from '../../schemas/channels/ChannelFilter-input.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js index ad769ae36913..70cb2f18e6b6 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelNameAndDirect-input.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/channels/ChannelNameAndDirect-input.graphql'; +import schema from '../../schemas/channels/ChannelNameAndDirect-input.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js b/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js index 3cd8b5f7b8d3..39e2cfc9aef5 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/ChannelSort-enum.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/channels/ChannelSort-enum.graphql'; +import schema from '../../schemas/channels/ChannelSort-enum.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js b/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js index bc0172b74adb..978a69b5ac0f 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/Privacy-enum.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/channels/Privacy-enum.graphql'; +import schema from '../../schemas/channels/Privacy-enum.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js b/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js index 060e2a2526a6..580280b549a2 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/channelByName.js @@ -1,6 +1,8 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; -import schema from '../../schemas/channels/channelByName.graphql'; +import schema from '../../schemas/channels/channelByName.graphqls'; const resolver = { Query: { diff --git a/packages/rocketchat-graphql/server/resolvers/channels/channels.js b/packages/rocketchat-graphql/server/resolvers/channels/channels.js index 6087771b86fd..04723ff5f5d4 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/channels.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/channels.js @@ -1,6 +1,8 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; -import schema from '../../schemas/channels/channels.graphql'; +import schema from '../../schemas/channels/channels.graphqls'; const resolver = { Query: { diff --git a/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js b/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js index 29a240e5c000..4fdc6e15a309 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/channelsByUser.js @@ -1,6 +1,8 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; -import schema from '../../schemas/channels/channelsByUser.graphql'; +import schema from '../../schemas/channels/channelsByUser.graphqls'; const resolver = { Query: { diff --git a/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js index e0f8a84d6a3d..59435add38bb 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/createChannel.js @@ -1,5 +1,7 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/channels/createChannel.graphql'; +import schema from '../../schemas/channels/createChannel.graphqls'; const resolver = { Mutation: { diff --git a/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js index 2218cdf7837b..e18e39af19dc 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/directChannel.js @@ -1,6 +1,8 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + import { authenticated } from '../../helpers/authenticated'; import { roomPublicFields } from './settings'; -import schema from '../../schemas/channels/directChannel.graphql'; +import schema from '../../schemas/channels/directChannel.graphqls'; const resolver = { Query: { diff --git a/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js index 23cd1017f985..08c55efa7796 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/hideChannel.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; +import { RocketChat } from 'meteor/rocketchat:lib'; import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/channels/hideChannel.graphql'; +import schema from '../../schemas/channels/hideChannel.graphqls'; const resolver = { Mutation: { diff --git a/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js b/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js index 306beff5d7a6..46afd2a08940 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/leaveChannel.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; +import { RocketChat } from 'meteor/rocketchat:lib'; import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/channels/leaveChannel.graphql'; +import schema from '../../schemas/channels/leaveChannel.graphqls'; const resolver = { Mutation: { diff --git a/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js b/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js index 0fc8c6c36bb4..362ce8b50b60 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/Message-type.js @@ -1,6 +1,8 @@ -import { property } from '../../helpers/property'; +import { RocketChat } from 'meteor/rocketchat:lib'; +import property from 'lodash.property'; + import { dateToFloat } from '../../helpers/dateToFloat'; -import schema from '../../schemas/messages/Message-type.graphql'; +import schema from '../../schemas/messages/Message-type.graphqls'; const resolver = { Message: { diff --git a/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js b/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js index 63f5a8bbb300..bda12ad6ac68 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/MessageIdentifier-input.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/messages/MessageIdentifier-input.graphql'; +import schema from '../../schemas/messages/MessageIdentifier-input.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js b/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js index e25dfb592f7a..02e630ff4589 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/MessagesWithCursor-type.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/messages/MessagesWithCursor-type.graphql'; +import schema from '../../schemas/messages/MessagesWithCursor-type.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js b/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js index 81ec44c5b9b8..37a9c7a71ef6 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/Reaction-type.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/messages/Reaction-type.graphql'; +import schema from '../../schemas/messages/Reaction-type.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js index 1c915d3a4c9a..29a55ded3d95 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/addReactionToMessage.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; +import { RocketChat } from 'meteor/rocketchat:lib'; import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/messages/addReactionToMessage.graphql'; +import schema from '../../schemas/messages/addReactionToMessage.graphqls'; const resolver = { Mutation: { diff --git a/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js b/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js index dfbb818e12b2..08cb14bdb274 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js @@ -1,7 +1,9 @@ import { withFilter } from 'graphql-subscriptions'; +import { RocketChat } from 'meteor/rocketchat:lib'; import { pubsub } from '../../subscriptions'; -import schema from '../../schemas/messages/chatMessageAdded.graphql'; +import { authenticated } from '../../helpers/authenticated'; +import schema from '../../schemas/messages/chatMessageAdded.graphqls'; export const CHAT_MESSAGE_SUBSCRIPTION_TOPIC = 'CHAT_MESSAGE_ADDED'; @@ -9,11 +11,35 @@ export function publishMessage(message) { pubsub.publish(CHAT_MESSAGE_SUBSCRIPTION_TOPIC, { chatMessageAdded: message }); } +function shouldPublish(message, { id, directTo }, username) { + if (id) { + return message.rid === id; + } else if (directTo) { + const room = RocketChat.models.Rooms.findOne({ + usernames: { $all: [directTo, username] }, + t: 'd' + }); + + return room && room._id === message.rid; + } + + return false; +} + const resolver = { Subscription: { chatMessageAdded: { - subscribe: withFilter(() => pubsub.asyncIterator(CHAT_MESSAGE_SUBSCRIPTION_TOPIC), (payload, args) => { - return payload.chatMessageAdded.rid === args.channelId; + subscribe: withFilter(() => pubsub.asyncIterator(CHAT_MESSAGE_SUBSCRIPTION_TOPIC), (payload, args, ctx) => { + // FIX: there's no authToken in context + // TODO: check if middleware applies to subscriptions, probably not. + const channel = { + id: args.channelId, + directTo: args.directTo + }; + + console.log('context in sub', ctx); + + return shouldPublish(payload.chatMessageAdded, channel, ctx.user.username); }) } } diff --git a/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js index 851767060869..33225c02f282 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/deleteMessage.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; +import { RocketChat } from 'meteor/rocketchat:lib'; import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/messages/deleteMessage.graphql'; +import schema from '../../schemas/messages/deleteMessage.graphqls'; const resolver = { Mutation: { diff --git a/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js index 42973929e23a..0fabc8b34db9 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/editMessage.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; +import { RocketChat } from 'meteor/rocketchat:lib'; import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/messages/editMessage.graphql'; +import schema from '../../schemas/messages/editMessage.graphqls'; const resolver = { Mutation: { diff --git a/packages/rocketchat-graphql/server/resolvers/messages/messages.js b/packages/rocketchat-graphql/server/resolvers/messages/messages.js index 6ef4b7502591..a163ebefa406 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/messages.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/messages.js @@ -1,9 +1,11 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/messages/messages.graphql'; +import schema from '../../schemas/messages/messages.graphqls'; const resolver = { Query: { - messages: authenticated((root, args) => { + messages: authenticated((root, args, { user }) => { const messagesQuery = {}; const messagesOptions = { sort: { ts: -1 } @@ -15,20 +17,24 @@ const resolver = { if (args.channelId) { // channelId channelQuery._id = args.channelId; - } else if (args.channelDetails) { - // channelDetails - channelQuery.name = args.channelDetails.name; - channelQuery.t = args.channelDetails.direct === true ? 'd' : { $ne: 'd' }; + } else if (args.directTo) { + // direct message where directTo is a user id + channelQuery.t = 'd'; + channelQuery.usernames = { $all: [args.directTo, user.username] }; + } else if (args.channelName) { + // non-direct channel + channelQuery.t = { $ne: 'd' }; + channelQuery.name = args.channelName; } else { - console.error('messages query must be called with channelId or channelDetails'); + console.error('messages query must be called with channelId or directTo'); return null; } const channel = RocketChat.models.Rooms.findOne(channelQuery); + let messagesArray = []; if (channel) { - // cursor if (isPagination && args.cursor) { const cursorMsg = RocketChat.models.Messages.findOne(args.cursor, { fields: { ts: 1 } }); diff --git a/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js b/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js index c0930382578b..7bbd20b71ec0 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/sendMessage.js @@ -1,15 +1,17 @@ /* global processWebhookMessage */ import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/messages/sendMessage.graphql'; +import schema from '../../schemas/messages/sendMessage.graphqls'; const resolver = { Mutation: { - sendMessage: authenticated((root, { channelId, content }, { user }) => { - const messageReturn = processWebhookMessage({ - roomId: channelId, - text: content - }, user)[0]; + sendMessage: authenticated((root, { channelId, directTo, content }, { user }) => { + const options = { + text: content, + channel: channelId || directTo + }; + + const messageReturn = processWebhookMessage(options, user)[0]; if (!messageReturn) { throw new Error('Unknown error'); diff --git a/packages/rocketchat-graphql/server/resolvers/users/User-type.js b/packages/rocketchat-graphql/server/resolvers/users/User-type.js index 6eede62b43ef..f2c13fc58bf3 100644 --- a/packages/rocketchat-graphql/server/resolvers/users/User-type.js +++ b/packages/rocketchat-graphql/server/resolvers/users/User-type.js @@ -1,5 +1,7 @@ -import { property } from '../../helpers/property'; -import schema from '../../schemas/users/User-type.graphql'; +import { RocketChat } from 'meteor/rocketchat:lib'; +import property from 'lodash.property'; + +import schema from '../../schemas/users/User-type.graphqls'; const resolver = { User: { diff --git a/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js b/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js index 61c84d39a6e5..d1d526338c1a 100644 --- a/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js +++ b/packages/rocketchat-graphql/server/resolvers/users/UserStatus-enum.js @@ -1,4 +1,4 @@ -import schema from '../../schemas/users/UserStatus-enum.graphql'; +import schema from '../../schemas/users/UserStatus-enum.graphqls'; export { schema diff --git a/packages/rocketchat-graphql/server/resolvers/users/setStatus.js b/packages/rocketchat-graphql/server/resolvers/users/setStatus.js index 6d6f4aca4902..ad6b4ebef6b6 100644 --- a/packages/rocketchat-graphql/server/resolvers/users/setStatus.js +++ b/packages/rocketchat-graphql/server/resolvers/users/setStatus.js @@ -1,5 +1,7 @@ +import { RocketChat } from 'meteor/rocketchat:lib'; + import { authenticated } from '../../helpers/authenticated'; -import schema from '../../schemas/users/setStatus.graphql'; +import schema from '../../schemas/users/setStatus.graphqls'; const resolver = { Mutation: { diff --git a/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphql b/packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphql rename to packages/rocketchat-graphql/server/schemas/accounts/LoginResult-type.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphql b/packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphql rename to packages/rocketchat-graphql/server/schemas/accounts/OauthProvider-type.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphql b/packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphql rename to packages/rocketchat-graphql/server/schemas/accounts/oauthProviders.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphql b/packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphql rename to packages/rocketchat-graphql/server/schemas/channels/Channel-type.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphql b/packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphql rename to packages/rocketchat-graphql/server/schemas/channels/ChannelFilter-input.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphql b/packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphql rename to packages/rocketchat-graphql/server/schemas/channels/ChannelNameAndDirect-input.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphql b/packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphql rename to packages/rocketchat-graphql/server/schemas/channels/ChannelSort-enum.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphql b/packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphql rename to packages/rocketchat-graphql/server/schemas/channels/Privacy-enum.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelByName.graphql b/packages/rocketchat-graphql/server/schemas/channels/channelByName.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/channelByName.graphql rename to packages/rocketchat-graphql/server/schemas/channels/channelByName.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/channels.graphql b/packages/rocketchat-graphql/server/schemas/channels/channels.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/channels.graphql rename to packages/rocketchat-graphql/server/schemas/channels/channels.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphql b/packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphql rename to packages/rocketchat-graphql/server/schemas/channels/channelsByUser.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/createChannel.graphql b/packages/rocketchat-graphql/server/schemas/channels/createChannel.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/createChannel.graphql rename to packages/rocketchat-graphql/server/schemas/channels/createChannel.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/directChannel.graphql b/packages/rocketchat-graphql/server/schemas/channels/directChannel.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/directChannel.graphql rename to packages/rocketchat-graphql/server/schemas/channels/directChannel.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphql b/packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphql rename to packages/rocketchat-graphql/server/schemas/channels/hideChannel.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphql b/packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphql rename to packages/rocketchat-graphql/server/schemas/channels/leaveChannel.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/messages/Message-type.graphql b/packages/rocketchat-graphql/server/schemas/messages/Message-type.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/messages/Message-type.graphql rename to packages/rocketchat-graphql/server/schemas/messages/Message-type.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphql b/packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphql rename to packages/rocketchat-graphql/server/schemas/messages/MessageIdentifier-input.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphql b/packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphql rename to packages/rocketchat-graphql/server/schemas/messages/MessagesWithCursor-type.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphql b/packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphql rename to packages/rocketchat-graphql/server/schemas/messages/Reaction-type.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphql b/packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphql rename to packages/rocketchat-graphql/server/schemas/messages/addReactionToMessage.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphql b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphql deleted file mode 100644 index f88b2979ca5a..000000000000 --- a/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphql +++ /dev/null @@ -1,3 +0,0 @@ -type Subscription { - chatMessageAdded(channelId: String!): Message -} diff --git a/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphqls b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphqls new file mode 100644 index 000000000000..d05c00afc3bc --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/chatMessageAdded.graphqls @@ -0,0 +1,3 @@ +type Subscription { + chatMessageAdded(channelId: String, directTo: String): Message +} diff --git a/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphql b/packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphql rename to packages/rocketchat-graphql/server/schemas/messages/deleteMessage.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/messages/editMessage.graphql b/packages/rocketchat-graphql/server/schemas/messages/editMessage.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/messages/editMessage.graphql rename to packages/rocketchat-graphql/server/schemas/messages/editMessage.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/messages/messages.graphql b/packages/rocketchat-graphql/server/schemas/messages/messages.graphqls similarity index 81% rename from packages/rocketchat-graphql/server/schemas/messages/messages.graphql rename to packages/rocketchat-graphql/server/schemas/messages/messages.graphqls index 2b9774942e76..a81fe2186ca7 100644 --- a/packages/rocketchat-graphql/server/schemas/messages/messages.graphql +++ b/packages/rocketchat-graphql/server/schemas/messages/messages.graphqls @@ -1,8 +1,8 @@ type Query { messages( channelId: String, - channelDetails: ChannelNameAndDirect, channelName: String, + directTo: String, cursor: String, count: Int, searchRegex: String, diff --git a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphql b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphql deleted file mode 100644 index 6f160fef1c94..000000000000 --- a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphql +++ /dev/null @@ -1,3 +0,0 @@ -type Mutation { - sendMessage(channelId: String!, content: String!): Message -} diff --git a/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphqls b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphqls new file mode 100644 index 000000000000..78933ec6a763 --- /dev/null +++ b/packages/rocketchat-graphql/server/schemas/messages/sendMessage.graphqls @@ -0,0 +1,3 @@ +type Mutation { + sendMessage(channelId: String, directTo: String, content: String!): Message +} diff --git a/packages/rocketchat-graphql/server/schemas/users/User-type.graphql b/packages/rocketchat-graphql/server/schemas/users/User-type.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/users/User-type.graphql rename to packages/rocketchat-graphql/server/schemas/users/User-type.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphql b/packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphql rename to packages/rocketchat-graphql/server/schemas/users/UserStatus-enum.graphqls diff --git a/packages/rocketchat-graphql/server/schemas/users/setStatus.graphql b/packages/rocketchat-graphql/server/schemas/users/setStatus.graphqls similarity index 100% rename from packages/rocketchat-graphql/server/schemas/users/setStatus.graphql rename to packages/rocketchat-graphql/server/schemas/users/setStatus.graphqls From 388ba96aec4e4a86ee1436c709d9862c0afba736 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Wed, 6 Sep 2017 12:13:59 +0200 Subject: [PATCH 094/801] Add a ref to the issue with @accounts/graphql-api --- packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js index 8bd3dde10230..b94a295187f9 100644 --- a/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js +++ b/packages/rocketchat-graphql/server/mocks/accounts/graphql-api.js @@ -3,6 +3,7 @@ // It might be like that because of async/await, // maybe Promise is not wrapped with Fiber // See: https://github.com/meteor/meteor/blob/a362e20a37547362b581fed52f7171d022e83b62/packages/promise/server.js +// Opened issue: https://github.com/js-accounts/graphql/issues/16 export const authenticated = (Accounts, func) => (async(root, args, context, info) => { const authToken = context.authToken; From 8dffc899a447a31e876bd5b5b2e2d112f4c43ee5 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Wed, 6 Sep 2017 12:15:23 +0200 Subject: [PATCH 095/801] Back to merge-graphql-schemas@1.1.3 Since they fixed https://github.com/okgrow/merge-graphql-schemas/pull/83 --- packages/rocketchat-graphql/package.js | 2 +- packages/rocketchat-graphql/server/resolvers/accounts/index.js | 2 +- packages/rocketchat-graphql/server/resolvers/channels/index.js | 2 +- packages/rocketchat-graphql/server/resolvers/messages/index.js | 2 +- packages/rocketchat-graphql/server/resolvers/users/index.js | 2 +- packages/rocketchat-graphql/server/schema.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/rocketchat-graphql/package.js b/packages/rocketchat-graphql/package.js index 8d6ff940e0c1..436d212f3e89 100644 --- a/packages/rocketchat-graphql/package.js +++ b/packages/rocketchat-graphql/package.js @@ -29,6 +29,6 @@ Npm.depends({ 'graphql-subscriptions': '0.4.4', 'graphql-tools': '1.2.2', 'lodash.property': '4.4.2', - 'kamilkisiela-merge-graphql-schemas': '1.1.2', + 'merge-graphql-schemas': '1.1.3', 'subscriptions-transport-ws': '0.8.2' }); diff --git a/packages/rocketchat-graphql/server/resolvers/accounts/index.js b/packages/rocketchat-graphql/server/resolvers/accounts/index.js index 02aceb574911..e82a7077059b 100644 --- a/packages/rocketchat-graphql/server/resolvers/accounts/index.js +++ b/packages/rocketchat-graphql/server/resolvers/accounts/index.js @@ -1,6 +1,6 @@ import { createJSAccountsGraphQL } from '@accounts/graphql-api'; import { AccountsServer } from 'meteor/rocketchat:accounts'; -import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; // queries import * as oauthProviders from './oauthProviders'; diff --git a/packages/rocketchat-graphql/server/resolvers/channels/index.js b/packages/rocketchat-graphql/server/resolvers/channels/index.js index 82a9dbff107d..063e9da41804 100644 --- a/packages/rocketchat-graphql/server/resolvers/channels/index.js +++ b/packages/rocketchat-graphql/server/resolvers/channels/index.js @@ -1,4 +1,4 @@ -import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; // queries import * as channels from './channels'; diff --git a/packages/rocketchat-graphql/server/resolvers/messages/index.js b/packages/rocketchat-graphql/server/resolvers/messages/index.js index ad5fc67076e6..fb9728b19815 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/index.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/index.js @@ -1,4 +1,4 @@ -import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; // queries import * as messages from './messages'; diff --git a/packages/rocketchat-graphql/server/resolvers/users/index.js b/packages/rocketchat-graphql/server/resolvers/users/index.js index 6de11371bf97..7647d5a5fdd6 100644 --- a/packages/rocketchat-graphql/server/resolvers/users/index.js +++ b/packages/rocketchat-graphql/server/resolvers/users/index.js @@ -1,4 +1,4 @@ -import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; // mutations import * as setStatus from './setStatus'; diff --git a/packages/rocketchat-graphql/server/schema.js b/packages/rocketchat-graphql/server/schema.js index 1cbf6c38eeac..e8d3cbdd489e 100644 --- a/packages/rocketchat-graphql/server/schema.js +++ b/packages/rocketchat-graphql/server/schema.js @@ -1,5 +1,5 @@ import { makeExecutableSchema } from 'graphql-tools'; -import { mergeTypes, mergeResolvers } from 'kamilkisiela-merge-graphql-schemas'; +import { mergeTypes, mergeResolvers } from 'merge-graphql-schemas'; import * as channels from './resolvers/channels'; import * as messages from './resolvers/messages'; From 5619e785652193e0ce42f9db5dd3e0a7608cc178 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Fri, 8 Sep 2017 19:29:13 +0200 Subject: [PATCH 096/801] Add Authorization token to WebSocket connection --- .../.npm/package/npm-shrinkwrap.json | 20 +++++++++---------- packages/rocketchat-graphql/server/api.js | 7 +------ .../resolvers/messages/chatMessageAdded.js | 10 +++------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json index 10d14533cd41..d496fa3ccc45 100644 --- a/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-graphql/.npm/package/npm-shrinkwrap.json @@ -291,11 +291,6 @@ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", "from": "jwt-decode@>=2.1.0 <3.0.0" }, - "kamilkisiela-merge-graphql-schemas": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/kamilkisiela-merge-graphql-schemas/-/kamilkisiela-merge-graphql-schemas-1.1.2.tgz", - "from": "kamilkisiela-merge-graphql-schemas@1.1.2" - }, "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", @@ -336,6 +331,11 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "from": "merge-descriptors@1.0.1" }, + "merge-graphql-schemas": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/merge-graphql-schemas/-/merge-graphql-schemas-1.1.3.tgz", + "from": "merge-graphql-schemas@1.1.3" + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -347,13 +347,13 @@ "from": "mime@1.3.4" }, "mime-db": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", - "from": "mime-db@>=1.29.0 <1.30.0" + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "from": "mime-db@>=1.30.0 <1.31.0" }, "mime-types": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", "from": "mime-types@>=2.1.15 <2.2.0" }, "moment": { diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index 494429f52e97..ede3862d58c0 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -42,12 +42,7 @@ new SubscriptionServer({ schema: executableSchema, execute, subscribe, - onOperation: ({context}) => { - console.log('context', context); - return { - authToken: context.Authorization - }; - } + onConnect: (connectionParams) => ({ authToken: connectionParams.Authorization }) }, { path: '/subscriptions', diff --git a/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js b/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js index 08cb14bdb274..8a81c66a69b3 100644 --- a/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js +++ b/packages/rocketchat-graphql/server/resolvers/messages/chatMessageAdded.js @@ -29,18 +29,14 @@ function shouldPublish(message, { id, directTo }, username) { const resolver = { Subscription: { chatMessageAdded: { - subscribe: withFilter(() => pubsub.asyncIterator(CHAT_MESSAGE_SUBSCRIPTION_TOPIC), (payload, args, ctx) => { - // FIX: there's no authToken in context - // TODO: check if middleware applies to subscriptions, probably not. + subscribe: withFilter(() => pubsub.asyncIterator(CHAT_MESSAGE_SUBSCRIPTION_TOPIC), authenticated((payload, args, { user }) => { const channel = { id: args.channelId, directTo: args.directTo }; - console.log('context in sub', ctx); - - return shouldPublish(payload.chatMessageAdded, channel, ctx.user.username); - }) + return shouldPublish(payload.chatMessageAdded, channel, user.username); + })) } } }; From 04e2494d29e65d4f55c9ab38d03bfac015aa2392 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Tue, 12 Sep 2017 09:54:05 +0200 Subject: [PATCH 097/801] Fix an issue with Fiber (User.avatar) --- .../rocketchat-graphql/server/resolvers/users/User-type.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/rocketchat-graphql/server/resolvers/users/User-type.js b/packages/rocketchat-graphql/server/resolvers/users/User-type.js index f2c13fc58bf3..67d0e451925f 100644 --- a/packages/rocketchat-graphql/server/resolvers/users/User-type.js +++ b/packages/rocketchat-graphql/server/resolvers/users/User-type.js @@ -8,7 +8,8 @@ const resolver = { id: property('_id'), status: ({status}) => status.toUpperCase(), avatar: async({ _id }) => { - const avatar = RocketChat.models.Avatars.findOne({ + // XXX js-accounts/graphql#16 + const avatar = await RocketChat.models.Avatars.model.rawCollection().findOne({ userId: _id }, { fields: { url: 1 }}); From 9dd51b363d68e239185f9e0b90143dc135fe0427 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Tue, 12 Sep 2017 16:11:20 +0200 Subject: [PATCH 098/801] Meteor 1.5.2 --- .meteor/versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.meteor/versions b/.meteor/versions index c608ae9d789f..8d8ebbff6657 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -42,7 +42,7 @@ ecmascript-runtime-server@0.4.1 edgee:slingshot@0.7.1 ejson@1.0.14 email@1.2.3 -emojione:emojione@3.0.3 +emojione:emojione@2.2.6 facebook-oauth@1.3.2 fastclick@1.0.13 francocatena:status@1.5.3 From 161f9a1b0ab368d21aadd4b3034f9a25d722a5b5 Mon Sep 17 00:00:00 2001 From: Kamil Kisiela Date: Sat, 16 Sep 2017 22:24:01 +0200 Subject: [PATCH 099/801] Use a separate server for graphql subscriptions and fix channels.create (#2) * Use a separate server for graphql subscriptions * Fix an issue with channel creation in REST API --- packages/rocketchat-api/server/v1/channels.js | 8 ++-- packages/rocketchat-graphql/server/api.js | 42 ++++++++++++------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/packages/rocketchat-api/server/v1/channels.js b/packages/rocketchat-api/server/v1/channels.js index 86abc6ab38e6..1075a0f2be34 100644 --- a/packages/rocketchat-api/server/v1/channels.js +++ b/packages/rocketchat-api/server/v1/channels.js @@ -133,15 +133,15 @@ function createChannelValidator(params) { throw new Error('unauthorized'); } - if (!params.name.value) { + if (!params.name || !params.name.value) { throw new Error(`Param "${ params.name.key }" is required`); } - if (params.members.value && !_.isArray(params.members.value)) { + if (params.members && params.members.value && !_.isArray(params.members.value)) { throw new Error(`Param "${ params.members.key }" must be an array if provided`); } - if (params.customFields.value && !(typeof params.customFields.value === 'object')) { + if (params.customFields && params.customFields.value && !(typeof params.customFields.value === 'object')) { throw new Error(`Param "${ params.customFields.key }" must be an object if provided`); } } @@ -176,7 +176,7 @@ RocketChat.API.v1.addRoute('channels.create', { authRequired: true }, { let error; try { - RocketChat.API.create.validate({ + RocketChat.API.channels.create.validate({ user: { value: userId }, diff --git a/packages/rocketchat-graphql/server/api.js b/packages/rocketchat-graphql/server/api.js index ede3862d58c0..1b2177a653d9 100644 --- a/packages/rocketchat-graphql/server/api.js +++ b/packages/rocketchat-graphql/server/api.js @@ -10,11 +10,12 @@ import cors from 'cors'; import { executableSchema } from './schema'; +const subscriptionPort = 3100; + // the Meteor GraphQL server is an Express server const graphQLServer = express(); graphQLServer.use(cors()); -graphQLServer.use(bodyParser.urlencoded({ extended: true })); graphQLServer.use( '/graphql', @@ -33,20 +34,31 @@ graphQLServer.use( }) ); -graphQLServer.use('/graphiql', graphiqlExpress({ - endpointURL: '/graphql', - subscriptionsEndpoint: 'ws://localhost:3000/subscriptions' -})); - -new SubscriptionServer({ - schema: executableSchema, - execute, - subscribe, - onConnect: (connectionParams) => ({ authToken: connectionParams.Authorization }) -}, -{ - path: '/subscriptions', - server: WebApp.httpServer +graphQLServer.use( + '/graphiql', + graphiqlExpress({ + endpointURL: '/graphql', + subscriptionsEndpoint: `ws://localhost:${ subscriptionPort }` + }) +); + +function startSubscriptionServer() { + SubscriptionServer.create({ + schema: executableSchema, + execute, + subscribe, + onConnect: (connectionParams) => ({ authToken: connectionParams.Authorization }) + }, + { + port: subscriptionPort, + host: process.env.BIND_IP || '0.0.0.0' + }); + + console.log('GraphQL Subscription server runs on port:', subscriptionPort); +} + +WebApp.onListening(() => { + startSubscriptionServer(); }); // this binds the specified paths to the Express server running Apollo + GraphiQL From df42f903793fc43d57488e6e2dd281c83baf14d3 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Mon, 18 Sep 2017 12:21:46 -0500 Subject: [PATCH 100/801] Add the enable method for commands --- packages/rocketchat-rocketlets/package.js | 4 +-- .../server/bridges/commands.js | 29 +++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index 46de00cdc6bd..3e8b874429a9 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -81,6 +81,6 @@ Package.onUse(function(api) { Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.27', - 'temporary-rocketlets-ts-definition': '0.6.27' + 'temporary-rocketlets-server': '0.1.29', + 'temporary-rocketlets-ts-definition': '0.6.29' }); diff --git a/packages/rocketchat-rocketlets/server/bridges/commands.js b/packages/rocketchat-rocketlets/server/bridges/commands.js index d1a6728e4af4..c5d6ba2a5ea7 100644 --- a/packages/rocketchat-rocketlets/server/bridges/commands.js +++ b/packages/rocketchat-rocketlets/server/bridges/commands.js @@ -9,11 +9,30 @@ export class RocketletCommandsBridge { doesCommandExist(command, rocketletId) { console.log(`The Rocketlet ${ rocketletId } is checking if "${ command }" command exists.`); - if (typeof command !== 'string') { + if (typeof command !== 'string' || command.length === 0) { return false; } - return typeof RocketChat.slashCommands.commands[command.toLowerCase()] === 'object'; + const cmd = command.toLowerCase(); + return typeof RocketChat.slashCommands.commands[cmd] === 'object' || this.disabledCommands.has(cmd); + } + + enableCommand(command, rocketletId) { + console.log(`The Rocketlet ${ rocketletId } is attempting to enable the command: "${ command }"`); + + if (typeof command !== 'string' || command.trim().length === 0) { + throw new Error('Invalid command parameter provided, must be a string.'); + } + + const cmd = command.toLowerCase(); + if (!this.disabledCommands.has(cmd)) { + throw new Error(`The command is not currently disabled: "${ cmd }"`); + } + + RocketChat.slashCommands.commands[cmd] = this.disabledCommands.get(cmd); + this.disabledCommands.delete(cmd); + + this.orch.getNotifier().commandUpdated(cmd); } disableCommand(command, rocketletId) { @@ -25,7 +44,7 @@ export class RocketletCommandsBridge { const cmd = command.toLowerCase(); if (typeof RocketChat.slashCommands.commands[cmd] === 'undefined') { - throw new Error(`Command does not exist in the system currently (or it is disabled): ${ cmd }`); + throw new Error(`Command does not exist in the system currently (or it is disabled): "${ cmd }"`); } this.disabledCommands.set(cmd, RocketChat.slashCommands.commands[cmd]); @@ -42,7 +61,7 @@ export class RocketletCommandsBridge { const cmd = command.toLowerCase(); if (typeof RocketChat.slashCommands.commands[cmd] === 'undefined') { - throw new Error(`Command does not exist in the system currently (or it is disabled): ${ cmd }`); + throw new Error(`Command does not exist in the system currently (or it is disabled): "${ cmd }"`); } const item = RocketChat.slashCommands.commands[cmd]; @@ -79,7 +98,7 @@ export class RocketletCommandsBridge { const cmd = command.toLowerCase(); if (typeof RocketChat.slashCommands.commands[cmd] === 'undefined' || !this.disabledCommands.has(cmd)) { - throw new Error(`Command does not exist in the system currently: ${ cmd }`); + throw new Error(`Command does not exist in the system currently: "${ cmd }"`); } this.disabledCommands.delete(cmd); From da44bb19e9ed3cf3b50fa1925173fa2bb9e3ae8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lindo=C3=A9lio=20L=C3=A1zaro?= Date: Mon, 18 Sep 2017 17:13:14 -0300 Subject: [PATCH 101/801] Add avatar conversion of SVG to PNG. --- server/startup/avatar.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/server/startup/avatar.js b/server/startup/avatar.js index 261f18fa276e..912cd887a08c 100644 --- a/server/startup/avatar.js +++ b/server/startup/avatar.js @@ -1,4 +1,4 @@ -/* globals FileUpload */ +/* globals FileUpload, RocketChatFile */ Meteor.startup(function() { WebApp.connectHandlers.use('/avatar/', Meteor.bindEnvironment(function(req, res/*, next*/) { @@ -86,11 +86,16 @@ Meteor.startup(function() { initials = initials.toUpperCase(); } - const svg = `\n\n\n\n${ initials }\n\n`; - - res.write(svg); - res.end(); + const svg = `\n\n\n\n${ initials }\n\n`; + if (RocketChat.Info.GraphicsMagick.enabled || RocketChat.Info.ImageMagick.enabled) { + const svgBuffer = new Buffer(svg); + res.setHeader('Content-Type', 'image/png'); + RocketChatFile.gm(svgBuffer).stream('png').pipe(res); + } else { + res.write(svg); + res.end(); + } return; } } From 358cbf2f8956f115d1ce0d859055cc64b6b4e0ae Mon Sep 17 00:00:00 2001 From: mutdmour Date: Thu, 26 Oct 2017 23:27:07 +0300 Subject: [PATCH 102/801] fixed issue #8336 --- .../client/models/EmojiCustom.js | 12 ++++++++++++ .../client/methods/setReaction.js | 2 ++ packages/rocketchat-reactions/setReaction.js | 4 ++++ 3 files changed, 18 insertions(+) diff --git a/packages/rocketchat-emoji-custom/client/models/EmojiCustom.js b/packages/rocketchat-emoji-custom/client/models/EmojiCustom.js index 369ab9754dcf..d37b8f4f4051 100644 --- a/packages/rocketchat-emoji-custom/client/models/EmojiCustom.js +++ b/packages/rocketchat-emoji-custom/client/models/EmojiCustom.js @@ -3,6 +3,18 @@ class EmojiCustom extends RocketChat.models._Base { super(); this._initModel('custom_emoji'); } + + //find + findByNameOrAlias(name, options) { + const query = { + $or: [ + {name}, + {aliases: name} + ] + }; + + return this.find(query, options); + } } RocketChat.models.EmojiCustom = new EmojiCustom(); diff --git a/packages/rocketchat-reactions/client/methods/setReaction.js b/packages/rocketchat-reactions/client/methods/setReaction.js index 38fcd46a3d28..5eac14b9ee9c 100644 --- a/packages/rocketchat-reactions/client/methods/setReaction.js +++ b/packages/rocketchat-reactions/client/methods/setReaction.js @@ -15,6 +15,8 @@ Meteor.methods({ return false; } else if (message.private) { return false; + } else if (!RocketChat.emoji.list[reaction] && RocketChat.models.EmojiCustom.findByNameOrAlias(reaction).count() === 0){ + return false; } if (message.reactions && message.reactions[reaction] && message.reactions[reaction].usernames.indexOf(user.username) !== -1) { diff --git a/packages/rocketchat-reactions/setReaction.js b/packages/rocketchat-reactions/setReaction.js index 1d655e50576b..54223516b6f3 100644 --- a/packages/rocketchat-reactions/setReaction.js +++ b/packages/rocketchat-reactions/setReaction.js @@ -17,6 +17,10 @@ Meteor.methods({ throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setReaction' }); } + if (!RocketChat.emoji.list[reaction] && RocketChat.models.EmojiCustom.findByNameOrAlias(reaction).count() === 0){ + throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setReaction' }); + } + const user = Meteor.user(); if (Array.isArray(room.muted) && room.muted.indexOf(user.username) !== -1 && !room.reactWhenReadOnly) { From 6a660c12d405614bb8ffe2289ee1977b933e5a5e Mon Sep 17 00:00:00 2001 From: mutdmour Date: Thu, 26 Oct 2017 23:35:49 +0300 Subject: [PATCH 103/801] eslint --- .../client/models/EmojiCustom.js | 20 +++++++++---------- .../client/methods/setReaction.js | 2 +- packages/rocketchat-reactions/setReaction.js | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/rocketchat-emoji-custom/client/models/EmojiCustom.js b/packages/rocketchat-emoji-custom/client/models/EmojiCustom.js index d37b8f4f4051..78cae29a32b7 100644 --- a/packages/rocketchat-emoji-custom/client/models/EmojiCustom.js +++ b/packages/rocketchat-emoji-custom/client/models/EmojiCustom.js @@ -4,17 +4,17 @@ class EmojiCustom extends RocketChat.models._Base { this._initModel('custom_emoji'); } - //find - findByNameOrAlias(name, options) { - const query = { - $or: [ - {name}, - {aliases: name} - ] - }; + //find + findByNameOrAlias(name, options) { + const query = { + $or: [ + {name}, + {aliases: name} + ] + }; - return this.find(query, options); - } + return this.find(query, options); + } } RocketChat.models.EmojiCustom = new EmojiCustom(); diff --git a/packages/rocketchat-reactions/client/methods/setReaction.js b/packages/rocketchat-reactions/client/methods/setReaction.js index 5eac14b9ee9c..48c2ffd1ff2a 100644 --- a/packages/rocketchat-reactions/client/methods/setReaction.js +++ b/packages/rocketchat-reactions/client/methods/setReaction.js @@ -15,7 +15,7 @@ Meteor.methods({ return false; } else if (message.private) { return false; - } else if (!RocketChat.emoji.list[reaction] && RocketChat.models.EmojiCustom.findByNameOrAlias(reaction).count() === 0){ + } else if (!RocketChat.emoji.list[reaction] && RocketChat.models.EmojiCustom.findByNameOrAlias(reaction).count() === 0) { return false; } diff --git a/packages/rocketchat-reactions/setReaction.js b/packages/rocketchat-reactions/setReaction.js index 54223516b6f3..e4c3994238c2 100644 --- a/packages/rocketchat-reactions/setReaction.js +++ b/packages/rocketchat-reactions/setReaction.js @@ -17,7 +17,7 @@ Meteor.methods({ throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setReaction' }); } - if (!RocketChat.emoji.list[reaction] && RocketChat.models.EmojiCustom.findByNameOrAlias(reaction).count() === 0){ + if (!RocketChat.emoji.list[reaction] && RocketChat.models.EmojiCustom.findByNameOrAlias(reaction).count() === 0) { throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setReaction' }); } From b8553d7ac07ca4e9f2a6e34f2dc73da45e557487 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Mon, 30 Oct 2017 14:38:14 -0500 Subject: [PATCH 104/801] Remove the local docker file --- .docker/Dockerfile.local | 51 ---------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 .docker/Dockerfile.local diff --git a/.docker/Dockerfile.local b/.docker/Dockerfile.local deleted file mode 100644 index cbf1f2a93d0e..000000000000 --- a/.docker/Dockerfile.local +++ /dev/null @@ -1,51 +0,0 @@ -FROM ubuntu:16.04 as builder - -RUN apt update && apt install curl git bzip2 -y - -RUN set -x \ -&& curl https://install.meteor.com | sed s/--progress-bar/-sL/g | /bin/sh \ -&& export PATH="$HOME/.meteor:$PATH" - -COPY . /app - -WORKDIR /app - -RUN set -x \ -&& meteor npm i --unsafe-perm - -RUN set -x \ -&& meteor build --allow-superuser --headless --directory /tmp/build - -FROM rocketchat/base:4 - -ENV RC_VERSION 0.59.0-develop - -MAINTAINER buildmaster@rocket.chat - -COPY --from=builder /tmp/build/bundle /app/bundle - -RUN set -x \ - && ls -l /app \ - && cd /app/bundle/programs/server \ - && npm install \ - && npm cache clear \ - && chown -R rocketchat:rocketchat /app - -USER rocketchat - -VOLUME /app/uploads - -WORKDIR /app/bundle - -# needs a mongoinstance - defaults to container linking with alias 'mongo' -ENV DEPLOY_METHOD=docker \ - NODE_ENV=production \ - MONGO_URL=mongodb://mongo:27017/rocketchat \ - HOME=/tmp \ - PORT=3000 \ - ROOT_URL=http://localhost:3000 \ - Accounts_AvatarStorePath=/app/uploads - -EXPOSE 3000 - -CMD ["node", "main.js"] From d74cc942fa79a2a413fb89511b46b64cedf7a5e6 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Thu, 2 Nov 2017 02:26:17 -0500 Subject: [PATCH 105/801] Implmement the discovery layout for the Rocketlets --- .../.npm/package/npm-shrinkwrap.json | 52 ++++++----- .../client/admin/rocketlets.html | 48 ++++++++-- .../client/imports/components/discovery.css | 93 +++++++++++++++++++ .../client/imports/components/tab.css | 62 +++++++++++++ .../client/imports/general/variables.css | 7 +- packages/rocketchat-theme/client/main.css | 4 + 6 files changed, 232 insertions(+), 34 deletions(-) create mode 100644 packages/rocketchat-theme/client/imports/components/discovery.css create mode 100644 packages/rocketchat-theme/client/imports/components/tab.css diff --git a/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json b/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json index 2617915b67c1..b2d682c623e3 100644 --- a/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json +++ b/packages/rocketchat-google-vision/.npm/package/npm-shrinkwrap.json @@ -1,8 +1,8 @@ { "dependencies": { "ajv": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz", "from": "ajv@>=5.1.0 <6.0.0" }, "ansi-regex": { @@ -247,6 +247,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", "from": "fast-deep-equal@>=1.0.0 <2.0.0" }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "from": "fast-json-stable-stringify@>=2.0.0 <3.0.0" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -285,7 +290,14 @@ "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "from": "globby@>=6.1.0 <7.0.0" + "from": "globby@>=6.1.0 <7.0.0", + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "from": "pify@>=2.0.0 <3.0.0" + } + } }, "google-auth-library": { "version": "0.10.0", @@ -919,8 +931,8 @@ } }, "gtoken": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-1.2.2.tgz", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-1.2.3.tgz", "from": "gtoken@>=1.2.1 <2.0.0" }, "har-schema": { @@ -1023,21 +1035,11 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", "from": "json-schema-traverse@>=0.3.0 <0.4.0" }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "from": "json-stable-stringify@>=1.0.1 <2.0.0" - }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "from": "json-stringify-safe@>=5.0.1 <5.1.0" }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "from": "jsonify@>=0.0.0 <0.1.0" - }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1079,8 +1081,8 @@ "from": "long@>=3.0.0 <4.0.0" }, "make-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", "from": "make-dir@>=1.0.0 <2.0.0" }, "methmeth": { @@ -1091,7 +1093,7 @@ "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "from": "mime@>=1.2.11 <2.0.0" + "from": "mime@>=1.4.1 <2.0.0" }, "mime-db": { "version": "1.30.0", @@ -1164,9 +1166,9 @@ "from": "performance-now@>=2.1.0 <3.0.0" }, "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "from": "pify@>=2.3.0 <3.0.0" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "from": "pify@>=3.0.0 <4.0.0" }, "pinkie": { "version": "2.0.4", @@ -1229,8 +1231,8 @@ "from": "request@>=2.79.0 <3.0.0" }, "retry-request": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.0.1.tgz", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.1.0.tgz", "from": "retry-request@>=3.0.0 <4.0.0" }, "rgb-hex": { @@ -1249,8 +1251,8 @@ "from": "signal-exit@>=3.0.2 <4.0.0" }, "sntp": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.0.2.tgz", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", "from": "sntp@>=2.0.0 <3.0.0" }, "split-array-stream": { diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html index 29be20cdabed..3b7d14a659cd 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.html +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -9,16 +9,48 @@

{{#requiresPermission 'manage-rocketlets'}} - {{#each rocketlets}} - - {{/each}} +
+
+
+
+
+
+ +
+
+ {{#each rocketlets}} +
+
+
+
+
+ +
+
+ {{/each}} +
{{/requiresPermission}}
- {{#with flexData}} - {{> flexTabBar}} - {{/with}} diff --git a/packages/rocketchat-theme/client/imports/components/discovery.css b/packages/rocketchat-theme/client/imports/components/discovery.css new file mode 100644 index 000000000000..282b9ce89791 --- /dev/null +++ b/packages/rocketchat-theme/client/imports/components/discovery.css @@ -0,0 +1,93 @@ +.rc-discovery { + justify-content: center; + + &__empty { + padding: 40px; + + text-align: center; + + color: var(--color-gray); + } + + &-wrap { + display: flex; + + margin: 0 -12px; + flex-wrap: wrap; + justify-content: flex-start; + } + + &__container { + flex: 1 1 100%; + } + + &__item { + min-width: 304px; + margin: 12px; + padding: 10px; + + border-radius: 2px; + background: #f7f8fa; + + &:hover &__image { + transform: scale(1.1); + } + + &__image-wrap { + overflow: hidden; + + height: 128px; + } + + &__image { + height: 128px; + + transition: all 0.3s; + + border-radius: 2px; + background: #cccccc; + + background: url(http://www.clickgratis.com.br/fotos-imagens/gatinho/aHR0cDovL3d3dy5jb21vZmF6ZXIub3JnL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDEyLzA3L2dhdGluaG8tcGVyc2EuanBn.jpg); + background-repeat: no-repeat; + background-position: 50%; + background-size: cover; + } + + &__footer { + display: flex; + + padding: 10px 10px 0; + + font-weight: 500; + line-height: 20px; + align-items: center; + + &__title { + margin-bottom: 4px; + + font-size: 18px; + } + + &__description { + color: #9ea2a8; + + font-size: 14px; + } + } + + & .rc-button { + flex: 0; + + width: 20px; + height: 20px; + + color: #1d74f5; + border-color: #1d74f5; + border-radius: 4px; + + & .rc-icon { + font-size: 1rem; + } + } + } +} diff --git a/packages/rocketchat-theme/client/imports/components/tab.css b/packages/rocketchat-theme/client/imports/components/tab.css new file mode 100644 index 000000000000..2d82549d594d --- /dev/null +++ b/packages/rocketchat-theme/client/imports/components/tab.css @@ -0,0 +1,62 @@ +.rc-tabs { + position: relative; + + display: flex; + + margin: 0 calc(var(--tabs-padding) / -2); + padding: calc(var(--tabs-padding) / 2); + + list-style: none; + + color: var(--color-gray); + + font-size: 14px; + + &::before { + position: absolute; + bottom: 0; + + width: 100%; + height: 2px; + + content: ''; + + background: var(--color-gray-light); + } + + &__tab { + position: relative; + + margin: calc(var(--tabs-padding) / 2); + padding: 0 5px; + + cursor: pointer; + transition: all 0.3s; + + &-link { + color: inherit !important; + } + + &:hover { + opacity: 0.5; + } + + &.active, + &:active { + color: #1d74f5; + + &::before { + position: absolute; + bottom: calc(var(--tabs-padding) * -1); + left: 0; + + width: 100%; + height: 2px; + + content: ''; + + background: #1d74f5; + } + } + } +} diff --git a/packages/rocketchat-theme/client/imports/general/variables.css b/packages/rocketchat-theme/client/imports/general/variables.css index 4735fc17660f..0af2b71c45aa 100644 --- a/packages/rocketchat-theme/client/imports/general/variables.css +++ b/packages/rocketchat-theme/client/imports/general/variables.css @@ -4,7 +4,7 @@ */ --color-darkest: #1f2329; - --color-dark: #2f343d; + --color-dark: #2f343d; --color-dark-medium: #414852; --color-dark-light: #6c727a; --color-gray: #9ea2a8; @@ -273,4 +273,9 @@ --message-box-editing-color: #fff5df; --message-box-popover-title-text-color: var(--color-gray); --message-box-popover-title-text-size: 0.75rem; + + /* + * Tabs + */ + --tabs-padding: 1rem; } diff --git a/packages/rocketchat-theme/client/main.css b/packages/rocketchat-theme/client/main.css index dc41e7515e1d..9e8732f7b90a 100644 --- a/packages/rocketchat-theme/client/main.css +++ b/packages/rocketchat-theme/client/main.css @@ -38,5 +38,9 @@ @import 'imports/components/modal/full-modal.css'; @import 'imports/components/modal/create-channel.css'; +/* Tabs */ +@import 'imports/components/tab.css'; +@import 'imports/components/discovery.css'; + /* RTL */ @import 'imports/general/rtl.css'; From 990aa6000406f2f62fa2dccfddad286b7377ccc6 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Thu, 2 Nov 2017 17:41:18 -0500 Subject: [PATCH 106/801] Fix the discovery add button, thanks to @ggazzo --- .../rocketchat-theme/client/imports/components/discovery.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-theme/client/imports/components/discovery.css b/packages/rocketchat-theme/client/imports/components/discovery.css index 282b9ce89791..27bc32f9b0e6 100644 --- a/packages/rocketchat-theme/client/imports/components/discovery.css +++ b/packages/rocketchat-theme/client/imports/components/discovery.css @@ -76,7 +76,7 @@ } & .rc-button { - flex: 0; + flex: 0 0 auto; width: 20px; height: 20px; From eb3e20c0c9a28af7708db78326abdbf0cfa9c03f Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Fri, 3 Nov 2017 11:24:31 -0500 Subject: [PATCH 107/801] Change the icons over to the template format --- .../client/admin/rocketlets.html | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html index 3b7d14a659cd..2917283995a8 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.html +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -10,7 +10,7 @@

{{#requiresPermission 'manage-rocketlets'}}
-
+
@@ -21,9 +21,7 @@

@@ -37,12 +35,10 @@

From b1b70c712e53750bc24b5ead055c14fefa3e227b Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Thu, 9 Nov 2017 16:10:04 -0600 Subject: [PATCH 108/801] Update the rocketlet packages and improve the storage query --- packages/rocketchat-rocketlets/client/admin/rocketlets.html | 2 +- packages/rocketchat-rocketlets/package.js | 4 ++-- packages/rocketchat-rocketlets/server/communication/rest.js | 6 ++++++ packages/rocketchat-rocketlets/server/storage/storage.js | 4 ++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html index 2917283995a8..54bc7bbd26eb 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.html +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -37,7 +37,7 @@

-
diff --git a/packages/rocketchat-rocketlets/package.js b/packages/rocketchat-rocketlets/package.js index 3e8b874429a9..22cd4e8a1120 100644 --- a/packages/rocketchat-rocketlets/package.js +++ b/packages/rocketchat-rocketlets/package.js @@ -81,6 +81,6 @@ Package.onUse(function(api) { Npm.depends({ 'busboy': '0.2.13', - 'temporary-rocketlets-server': '0.1.29', - 'temporary-rocketlets-ts-definition': '0.6.29' + 'temporary-rocketlets-server': '0.1.32', + 'temporary-rocketlets-ts-definition': '0.6.30' }); diff --git a/packages/rocketchat-rocketlets/server/communication/rest.js b/packages/rocketchat-rocketlets/server/communication/rest.js index 6ce815a68102..732bef420a22 100644 --- a/packages/rocketchat-rocketlets/server/communication/rest.js +++ b/packages/rocketchat-rocketlets/server/communication/rest.js @@ -95,6 +95,12 @@ export class RocketletsRestApi { } }); + this.api.addRoute(':id/icon', { authRequired: true }, { + get() { + return { success: false }; + } + }); + this.api.addRoute(':id/languages', { authRequired: true }, { get() { console.log(`Getting ${ this.urlParams.id }'s languages..`); diff --git a/packages/rocketchat-rocketlets/server/storage/storage.js b/packages/rocketchat-rocketlets/server/storage/storage.js index 0ac51c5e0a48..78ba07fd8793 100644 --- a/packages/rocketchat-rocketlets/server/storage/storage.js +++ b/packages/rocketchat-rocketlets/server/storage/storage.js @@ -39,7 +39,7 @@ export class RocketletRealStorage extends RocketletStorage { let doc; try { - doc = this.db.findOneById(id); + doc = this.db.findOne({ $or: [ {_id: id }, { id } ]}); } catch (e) { return reject(e); } @@ -47,7 +47,7 @@ export class RocketletRealStorage extends RocketletStorage { if (doc) { resolve(doc); } else { - reject(new Error(`Nothing found by the id: ${ id }`)); + reject(new Error(`No Rocketlet found by the id: ${ id }`)); } }); } From 37fab88475dd407d9179f0a5153baa28092a3b70 Mon Sep 17 00:00:00 2001 From: Bradley Hilton Date: Mon, 13 Nov 2017 17:13:08 -0600 Subject: [PATCH 109/801] Display the Rocketlet's icon file in the list of rocketlets --- .../client/admin/rocketletInstall.html | 3 +++ .../client/admin/rocketletInstall.js | 4 ++++ .../client/admin/rocketlets.html | 4 ++-- .../rocketchat-rocketlets/client/admin/rocketlets.js | 4 ++++ packages/rocketchat-rocketlets/client/orchestrator.js | 7 +++++++ packages/rocketchat-rocketlets/package.js | 8 +++++--- .../server/communication/rest.js | 11 ++++++++++- 7 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 packages/rocketchat-rocketlets/client/admin/rocketletInstall.html create mode 100644 packages/rocketchat-rocketlets/client/admin/rocketletInstall.js diff --git a/packages/rocketchat-rocketlets/client/admin/rocketletInstall.html b/packages/rocketchat-rocketlets/client/admin/rocketletInstall.html new file mode 100644 index 000000000000..597805a242dc --- /dev/null +++ b/packages/rocketchat-rocketlets/client/admin/rocketletInstall.html @@ -0,0 +1,3 @@ + diff --git a/packages/rocketchat-rocketlets/client/admin/rocketletInstall.js b/packages/rocketchat-rocketlets/client/admin/rocketletInstall.js new file mode 100644 index 000000000000..0e6e1f3d796a --- /dev/null +++ b/packages/rocketchat-rocketlets/client/admin/rocketletInstall.js @@ -0,0 +1,4 @@ +Template.rocketletInstall.onCreated(function() { + const instance = this; + instance.status = new ReactiveVar(false); +}); diff --git a/packages/rocketchat-rocketlets/client/admin/rocketlets.html b/packages/rocketchat-rocketlets/client/admin/rocketlets.html index 54bc7bbd26eb..334c339d326c 100644 --- a/packages/rocketchat-rocketlets/client/admin/rocketlets.html +++ b/packages/rocketchat-rocketlets/client/admin/rocketlets.html @@ -20,7 +20,7 @@

- @@ -30,7 +30,7 @@

-
+