Merge branch 'develop' into new-sidebar

pull/9608/head
Karl Prieb 7 years ago
commit 77698dad9e
  1. 32
      .meteor/packages
  2. 2
      .meteor/release
  3. 77
      .meteor/versions
  4. 13
      client/notifications/notification.js
  5. 13570
      package-lock.json
  6. 109
      package.json
  7. 44
      packages/autoupdate/autoupdate_client.js
  8. 8
      packages/autoupdate/package.js
  9. 19
      packages/rocketchat-api/package.js
  10. 21
      packages/rocketchat-api/server/api.js
  11. 12
      packages/rocketchat-api/server/default/helpers/getLoggedInUser.js
  12. 4
      packages/rocketchat-api/server/helpers/README.md
  13. 2
      packages/rocketchat-api/server/helpers/getLoggedInUser.js
  14. 2
      packages/rocketchat-api/server/helpers/getPaginationItems.js
  15. 2
      packages/rocketchat-api/server/helpers/getUserFromParams.js
  16. 2
      packages/rocketchat-api/server/helpers/isUserFromParams.js
  17. 2
      packages/rocketchat-api/server/helpers/parseJsonQuery.js
  18. 2
      packages/rocketchat-api/server/helpers/requestParams.js
  19. 20
      packages/rocketchat-api/server/v1/chat.js
  20. 14
      packages/rocketchat-api/server/v1/permissions.js
  21. 27
      packages/rocketchat-api/server/v1/spotlight.js
  22. 21
      packages/rocketchat-api/server/v1/users.js
  23. 15
      packages/rocketchat-file-upload/server/config/AmazonS3.js
  24. 14
      packages/rocketchat-file-upload/server/config/FileSystem.js
  25. 16
      packages/rocketchat-file-upload/server/config/GoogleStorage.js
  26. 70
      packages/rocketchat-file-upload/server/config/GridFS.js
  27. 132
      packages/rocketchat-file-upload/server/lib/FileUpload.js
  28. 3
      packages/rocketchat-file-upload/server/methods/sendFileMessage.js
  29. 14
      packages/rocketchat-file-upload/server/startup/settings.js
  30. 65
      packages/rocketchat-file/file.server.js
  31. 4
      packages/rocketchat-gitlab/common.js
  32. 40
      packages/rocketchat-i18n/i18n/de.i18n.json
  33. 5
      packages/rocketchat-i18n/i18n/en.i18n.json
  34. 2
      packages/rocketchat-integrations/server/processWebhookMessage.js
  35. 3
      packages/rocketchat-katex/package-lock.json
  36. 5
      packages/rocketchat-lib/server/startup/settings.js
  37. 22
      packages/rocketchat-livechat/.app/.meteor/packages
  38. 2
      packages/rocketchat-livechat/.app/.meteor/release
  39. 75
      packages/rocketchat-livechat/.app/.meteor/versions
  40. 6
      packages/rocketchat-livechat/.app/package.json
  41. 4
      packages/rocketchat-livechat/app/i18n/af.i18n.json
  42. 3
      packages/rocketchat-livechat/app/i18n/mn.i18n.json
  43. 4
      packages/rocketchat-livechat/app/i18n/sl-SI.i18n.json
  44. 46
      packages/rocketchat-livechat/app/i18n/th-TH.i18n.json
  45. 46
      packages/rocketchat-livechat/app/i18n/vi-VN.i18n.json
  46. 879
      packages/rocketchat-livechat/app/package-lock.json
  47. 11
      packages/rocketchat-livechat/imports/server/rest/facebook.js
  48. 6
      packages/rocketchat-livechat/server/lib/Livechat.js
  49. 6
      packages/rocketchat-livechat/server/models/LivechatInquiry.js
  50. 2
      packages/rocketchat-livechat/server/sendMessageBySMS.js
  51. 2
      packages/rocketchat-oembed/server/jumpToMessage.js
  52. 2
      packages/rocketchat-theme/client/imports/components/emojiPicker.css
  53. 7
      packages/rocketchat-ui-account/client/accountPreferences.html
  54. 6
      packages/rocketchat-ui-account/client/accountPreferences.js
  55. 6
      packages/rocketchat-ui/client/lib/avatar.js
  56. 3
      server/methods/saveUserPreferences.js
  57. 30
      server/startup/avatar.js
  58. 17
      tests/end-to-end/api/01-users.js
  59. 15
      tests/end-to-end/api/05-chat.js
  60. 33
      tests/end-to-end/api/11-permissions.js
  61. 40
      tests/end-to-end/api/11-spotlight.js
  62. 4
      tests/pageobjects/administration.page.js

@ -5,37 +5,37 @@
rocketchat:cors
accounts-facebook@1.3.0
accounts-github@1.4.0
accounts-google@1.3.0
accounts-meteor-developer@1.4.0
accounts-facebook@1.3.1
accounts-github@1.4.1
accounts-google@1.3.1
accounts-meteor-developer@1.4.1
accounts-password@1.5.0
accounts-twitter@1.4.0
accounts-twitter@1.4.1
blaze-html-templates
check@1.2.5
check@1.3.0
ddp-rate-limiter@1.0.7
ddp-common@1.3.0
dynamic-import@0.2.0
ecmascript@0.9.0
ddp-common@1.4.0
dynamic-import@0.3.0
ecmascript@0.10.0
ejson@1.1.0
email@1.2.3
fastclick@1.0.13
http@1.3.0
http@1.4.0
jquery@1.11.10
logging@1.1.19
meteor-base@1.2.0
meteor-base@1.3.0
mobile-experience@1.0.5
mongo@1.3.1
random@1.0.10
mongo@1.4.2
random@1.1.0
rate-limit@1.0.8
reactive-dict@1.2.0
reactive-var@1.0.11
reload@1.1.11
reload@1.2.0
service-configuration@1.0.11
session@1.1.7
shell-server@0.3.0
shell-server@0.3.1
spacebars
standard-minifier-js@2.2.0
standard-minifier-js@2.3.1
tracker@1.1.3
rocketchat:2fa

@ -1 +1 @@
METEOR@1.6.0.1
METEOR@1.6.1

@ -8,41 +8,41 @@ accounts-password@1.5.0
accounts-twitter@1.4.1
aldeed:simple-schema@1.5.3
allow-deny@1.1.0
autoupdate@1.3.12
babel-compiler@6.24.7
babel-runtime@1.1.1
base64@1.0.10
autoupdate@1.4.0
babel-compiler@7.0.4
babel-runtime@1.2.2
base64@1.0.11
binary-heap@1.0.10
blaze@2.3.2
blaze-html-templates@1.1.2
blaze-tools@1.0.10
boilerplate-generator@1.3.1
caching-compiler@1.1.9
boilerplate-generator@1.4.0
caching-compiler@1.1.11
caching-html-compiler@1.1.2
callback-hook@1.0.10
callback-hook@1.1.0
cfs:http-methods@0.0.32
check@1.2.5
coffeescript@1.12.7_3
coffeescript-compiler@1.12.7_3
check@1.3.0
coffeescript@1.0.17
dandv:caret-position@2.1.1
ddp@1.4.0
ddp-client@2.2.0
ddp-common@1.3.0
ddp-client@2.3.1
ddp-common@1.4.0
ddp-rate-limiter@1.0.7
ddp-server@2.1.1
ddp-server@2.1.2
deepwell:bootstrap-datepicker2@1.3.0
deps@1.0.12
diff-sequence@1.0.7
diff-sequence@1.1.0
dispatch:run-as-user@1.1.1
dynamic-import@0.2.1
ecmascript@0.9.0
dynamic-import@0.3.0
ecmascript@0.10.4
ecmascript-runtime@0.5.0
ecmascript-runtime-client@0.5.0
ecmascript-runtime-client@0.6.2
ecmascript-runtime-server@0.5.0
edgee:slingshot@0.7.1
ejson@1.1.0
email@1.2.3
emojione:emojione@2.2.6
es5-shim@4.7.3
facebook-oauth@1.4.0
fastclick@1.0.13
francocatena:status@1.5.3
@ -52,15 +52,15 @@ google-oauth@1.2.5
hot-code-push@1.0.4
html-tools@1.0.11
htmljs@1.0.11
http@1.3.0
id-map@1.0.9
http@1.4.0
id-map@1.1.0
jalik:ufs@0.7.4_1
jalik:ufs-gridfs@0.2.1
jalik:ufs-local@0.2.9
jparker:crypto-core@0.1.0
jparker:crypto-md5@0.1.1
jparker:gravatar@0.5.1
jquery@1.11.10
jquery@1.11.11
kadira:blaze-layout@2.3.0
kadira:flow-router@2.12.1
keepnox:perfect-scrollbar@0.6.8
@ -72,28 +72,28 @@ konecty:multiple-instances-status@1.1.0
konecty:nrr@2.0.2
konecty:user-presence@2.0.1
launch-screen@1.1.1
less@2.7.11
less@2.7.12
livedata@1.0.18
localstorage@1.2.0
logging@1.1.19
matb33:collection-hooks@0.8.4
mdg:validation-error@0.5.1
meteor@1.8.2
meteor-base@1.2.0
meteor-base@1.3.0
meteor-developer-oauth@1.2.0
meteorhacks:inject-initial@1.0.4
meteorhacks:meteorx@1.4.1
meteorspark:util@0.2.0
minifier-css@1.2.16
minifier-js@2.2.2
minifier-css@1.3.1
minifier-js@2.3.2
minimongo@1.4.3
mizzao:autocomplete@0.5.1
mizzao:timesync@0.3.4
mobile-experience@1.0.5
mobile-status-bar@1.0.14
modules@0.11.2
modules-runtime@0.9.1
mongo@1.3.1
modules@0.11.4
modules-runtime@0.9.2
mongo@1.4.3
mongo-dev-server@1.1.0
mongo-id@1.0.6
mongo-livedata@1.0.12
@ -102,28 +102,28 @@ mystor:device-detection@0.2.0
nimble:restivus@0.8.12
nooitaf:colors@1.1.2_1
npm-bcrypt@0.9.3
npm-mongo@2.2.33
npm-mongo@2.2.34
oauth@1.2.1
oauth1@1.2.0
oauth2@1.2.0
observe-sequence@1.0.16
ordered-dict@1.0.9
ordered-dict@1.1.0
ostrio:cookies@2.2.4
pauli:accounts-linkedin@2.1.5
pauli:linkedin-oauth@1.2.0
percolate:synced-cron@1.3.2
promise@0.10.1
promise@0.10.2
raix:eventemitter@0.1.3
raix:eventstate@0.0.4
raix:handlebar-helpers@0.2.5
raix:push@3.3.0
raix:ui-dropped-event@0.0.7
random@1.0.10
rate-limit@1.0.8
random@1.1.0
rate-limit@1.0.9
reactive-dict@1.2.0
reactive-var@1.0.11
reload@1.1.11
retry@1.0.9
reload@1.2.0
retry@1.1.0
rocketchat:2fa@0.0.1
rocketchat:accounts@0.0.1
rocketchat:action-links@0.0.1
@ -239,15 +239,18 @@ rocketchat:videobridge@0.2.0
rocketchat:webrtc@0.0.1
rocketchat:wordpress@0.0.1
routepolicy@1.0.12
server-render@0.3.0
service-configuration@1.0.11
session@1.1.7
sha@1.0.9
shell-server@0.3.1
shim-common@0.1.0
simple:json-routes@2.1.0
socket-stream-client@0.1.0
spacebars@1.0.15
spacebars-compiler@1.1.3
srp@1.0.10
standard-minifier-js@2.2.3
standard-minifier-js@2.3.2
steffo:meteor-accounts-saml@0.0.1
swydo:graphql@0.0.3
tap:i18n@1.8.2
@ -260,8 +263,8 @@ tracker@1.1.3
twitter-oauth@1.2.0
ui@1.0.13
underscore@1.0.10
url@1.1.0
webapp@1.4.0
url@1.2.0
webapp@1.5.0
webapp-hashing@1.0.9
yasaricli:slugify@0.0.7
yasinuslu:blaze-meta@0.3.3

@ -29,6 +29,7 @@ Meteor.startup(function() {
// This logic is duplicated in /client/startup/unread.coffee.
const hasFocus = readMessage.isEnable();
const messageIsInOpenedRoom = openedRoomId === notification.payload.rid;
const muteFocusedConversations = RocketChat.getUserPreference(Meteor.user(), 'muteFocusedConversations');
fireGlobalEvent('notification', {
notification,
@ -42,10 +43,13 @@ Meteor.startup(function() {
KonchatNotification.newMessage(notification.payload.rid);
KonchatNotification.showDesktop(notification);
}
} else if (!(hasFocus && messageIsInOpenedRoom)) {
} else if (!hasFocus || !messageIsInOpenedRoom) {
// Play a sound and show a notification.
KonchatNotification.newMessage(notification.payload.rid);
KonchatNotification.showDesktop(notification);
} else if (!muteFocusedConversations) {
// Play a notification sound
KonchatNotification.newMessage(notification.payload.rid);
}
});
@ -56,14 +60,15 @@ Meteor.startup(function() {
// This logic is duplicated in /client/startup/unread.coffee.
const hasFocus = readMessage.isEnable();
const messageIsInOpenedRoom = openedRoomId === notification.payload.rid;
const muteFocusedConversations = RocketChat.getUserPreference(Meteor.user(), 'muteFocusedConversations');
if (RocketChat.Layout.isEmbedded()) {
if (!hasFocus && messageIsInOpenedRoom) {
// Play a sound and show a notification.
// Play a notification sound
KonchatNotification.newMessage(notification.payload.rid);
}
} else if (!(hasFocus && messageIsInOpenedRoom)) {
// Play a sound and show a notification.
} else if (!hasFocus || !messageIsInOpenedRoom || !muteFocusedConversations) {
// Play a notification sound
KonchatNotification.newMessage(notification.payload.rid);
}
});

13570
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -86,93 +86,94 @@
"email": "support@rocket.chat"
},
"devDependencies": {
"autoprefixer": "^7.2.5",
"autoprefixer": "^8.0.0",
"babel-mocha-es6-compiler": "^0.1.0",
"babel-plugin-array-includes": "^2.0.3",
"chimp": "^0.51.0",
"conventional-changelog-cli": "^1.3.5",
"eslint": "^4.15.0",
"conventional-changelog-cli": "^1.3.13",
"eslint": "^4.17.0",
"mocha": "^5.0.1",
"mock-require": "^3.0.1",
"postcss-custom-properties": "^6.2.0",
"postcss-import": "^11.0.0",
"postcss-import": "^11.1.0",
"postcss-media-minmax": "^3.0.0",
"postcss-nested": "^3.0.0",
"postcss-selector-not": "^3.0.1",
"proxyquire": "^1.8.0",
"simple-git": "^1.85.0",
"simple-git": "^1.89.0",
"stylelint": "^8.4.0",
"stylelint-order": "^0.8.0",
"supertest": "^3.0.0"
},
"dependencies": {
"@google-cloud/language": "0.8.0",
"@google-cloud/storage": "1.4.0",
"@google-cloud/vision": "0.11.5",
"adm-zip": "0.4.7",
"atlassian-crowd": "0.5.0",
"autolinker": "1.6.0",
"aws-sdk": "^2.180.0",
"babel-runtime": "^6.26.0",
"bad-words": "1.3.1",
"@babel/runtime": "^7.0.0-beta.40",
"@google-cloud/language": "^1.1.0",
"@google-cloud/storage": "^1.6.0",
"@google-cloud/vision": "^0.15.2",
"adm-zip": "^0.4.7",
"atlassian-crowd": "^0.5.0",
"autolinker": "^1.6.2",
"aws-sdk": "^2.195.0",
"bad-words": "^1.6.1",
"bcrypt": "^1.0.3",
"bson": "0.5.5",
"bugsnag": "1.8.0",
"bson": "^1.0.4",
"bugsnag": "^2.1.3",
"bunyan": "^1.8.12",
"busboy": "0.2.14",
"busboy": "^0.2.14",
"cas": "https://github.com/kcbanner/node-cas/tarball/fcd27dad333223b3b75a048bce27973fb3ca0f62",
"clipboard": "1.7.1",
"codemirror": "^5.33.0",
"coffeescript": "1.12.7",
"connect": "2.7.10",
"clipboard": "^1.7.1",
"codemirror": "^5.34.0",
"coffeescript": "^1.12.7",
"connect": "^2.7.10",
"core-js": "^2.5.3",
"csv-parse": "1.2.0",
"csv-parse": "^1.3.3",
"emailreplyparser": "^0.0.5",
"file-type": "^7.4.0",
"filesize": "3.5.11",
"gm": "1.23.1",
"gridfs-stream": "1.1.1",
"he": "1.1.1",
"file-type": "^7.5.0",
"filesize": "^3.6.0",
"gridfs-stream": "^1.1.1",
"he": "^1.1.1",
"highlight.js": "^9.12.0",
"iconv-lite": "0.4.19",
"image-size": "0.6.2",
"iconv-lite": "^0.4.19",
"image-size": "^0.6.2",
"imap": "^0.8.19",
"ip-range-check": "0.0.2",
"jquery": "^3.2.1",
"jschardet": "1.6.0",
"ip-range-check": "^0.0.2",
"jquery": "^3.3.1",
"jschardet": "^1.6.0",
"ldapjs": "^1.0.2",
"less": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6",
"less-plugin-autoprefix": "1.5.1",
"localforage": "1.5.5",
"lokijs": "1.4.1",
"lru-cache": "2.6.5",
"mailparser": "^2.1.0",
"marked": "0.3.12",
"less-plugin-autoprefix": "^1.5.1",
"localforage": "^1.5.6",
"lokijs": "^1.5.2",
"lru-cache": "^2.6.5",
"mailparser": "^2.2.0",
"marked": "^0.3.12",
"mime-db": "^1.32.0",
"mime-type": "^3.0.5",
"mkdirp": "0.5.1",
"mkdirp": "^0.5.1",
"moment": "^2.20.1",
"moment-timezone": "^0.5.14",
"node-dogstatsd": "0.0.7",
"object-path": "0.11.4",
"node-dogstatsd": "^0.0.7",
"object-path": "^0.11.4",
"photoswipe": "^4.1.2",
"poplib": "^0.1.7",
"prom-client": "^10.2.2",
"querystring": "0.2.0",
"redis": "2.2.5",
"semver": "^5.4.1",
"slack-client": "2.0.6",
"speakeasy": "2.0.0",
"tar-stream": "1.5.5",
"querystring": "^0.2.0",
"redis": "^2.8.0",
"semver": "^5.5.0",
"sharp": "^0.19.0",
"slack-client": "^2.0.6",
"speakeasy": "^2.0.0",
"tar-stream": "^1.5.5",
"toastr": "^2.1.4",
"twilio": "2.9.1",
"ua-parser-js": "0.7.17",
"twilio": "^2.9.1",
"ua-parser-js": "^0.7.17",
"underscore": "^1.8.3",
"underscore.string": "^3.3.4",
"wolfy87-eventemitter": "^5.2.4",
"xml-crypto": "0.6.0",
"xml2js": "0.2.0",
"xmlbuilder": "2.6.4",
"xmldom": "0.1.27",
"yaqrcode": "0.2.1"
"xml-crypto": "^0.10.1",
"xml2js": "^0.4.19",
"xmlbuilder": "^2.6.4",
"xmldom": "^0.1.27",
"yaqrcode": "^0.2.1"
}
}

@ -59,6 +59,14 @@ var retry = new Retry({
});
var failures = 0;
function after(times, func) {
return function() {
if (--times < 1) {
return func.apply(this, arguments);
}
};
};
Autoupdate._retrySubscription = function () {
Meteor.subscribe("meteor_autoupdate_clientVersions", {
onError: function (error) {
@ -86,18 +94,30 @@ Autoupdate._retrySubscription = function () {
// https://github.com/guard/guard-livereload/blob/master/js/livereload.js#L710
var newCss = (doc.assets && doc.assets.allCss) || [];
var oldLinks = [];
_.each(document.getElementsByTagName('link'), function (link) {
if (link.className === '__meteor-css__') {
oldLinks.push(link);
Array.prototype.forEach.call(
document.getElementsByTagName('link'),
function (link) {
if (link.className === '__meteor-css__') {
oldLinks.push(link);
}
}
);
function waitUntilCssLoads(link, callback) {
var called;
function executeCallback(...args) {
if (! called) {
called = true;
return callback(...args);
}
}
});
var waitUntilCssLoads = function (link, callback) {
var executeCallback = _.once(callback);
link.onload = function () {
knownToSupportCssOnLoad = true;
executeCallback();
};
if (! knownToSupportCssOnLoad) {
var id = Meteor.setInterval(function () {
if (link.sheet) {
@ -106,11 +126,11 @@ Autoupdate._retrySubscription = function () {
}
}, 50);
}
};
}
var removeOldLinks = _.after(newCss.length, function () {
_.each(oldLinks, function (oldLink) {
oldLink.parentNode.removeChild(oldLink);
var removeOldLinks = after(newCss.length, function () {
oldLinks.forEach(function (link) {
link.parentNode.removeChild(link);
});
});
@ -123,7 +143,7 @@ Autoupdate._retrySubscription = function () {
};
if (newCss.length !== 0) {
_.each(newCss, function (css) {
newCss.forEach(function (css) {
var newLink = document.createElement("link");
newLink.setAttribute("rel", "stylesheet");
newLink.setAttribute("type", "text/css");
@ -153,4 +173,4 @@ Autoupdate._retrySubscription = function () {
}
});
};
Autoupdate._retrySubscription();
Autoupdate._retrySubscription();

@ -1,6 +1,6 @@
Package.describe({
summary: "Update the client when new client code is available",
version: '1.3.12'
version: '1.4.0'
});
Package.onUse(function (api) {
@ -15,9 +15,9 @@ Package.onUse(function (api) {
], 'client');
api.use([
'ecmascript',
'ddp',
'mongo',
'ecmascript'
'mongo'
], ['client', 'server']);
api.use(['http', 'random'], 'web.cordova');
@ -27,4 +27,4 @@ Package.onUse(function (api) {
api.addFiles('autoupdate_cordova.js', 'web.cordova');
api.export('Autoupdate');
});
});

@ -15,16 +15,13 @@ Package.onUse(function(api) {
api.addFiles('server/api.js', 'server');
api.addFiles('server/settings.js', 'server');
//Register v1 helpers
api.addFiles('server/v1/helpers/requestParams.js', 'server');
api.addFiles('server/v1/helpers/getPaginationItems.js', 'server');
api.addFiles('server/v1/helpers/getUserFromParams.js', 'server');
api.addFiles('server/v1/helpers/isUserFromParams.js', 'server');
api.addFiles('server/v1/helpers/parseJsonQuery.js', 'server');
api.addFiles('server/v1/helpers/getLoggedInUser.js', 'server');
//Register default helpers
api.addFiles('server/default/helpers/getLoggedInUser.js', 'server');
//Register helpers
api.addFiles('server/helpers/requestParams.js', 'server');
api.addFiles('server/helpers/getPaginationItems.js', 'server');
api.addFiles('server/helpers/getUserFromParams.js', 'server');
api.addFiles('server/helpers/isUserFromParams.js', 'server');
api.addFiles('server/helpers/parseJsonQuery.js', 'server');
api.addFiles('server/helpers/getLoggedInUser.js', 'server');
//Add default routes
api.addFiles('server/default/info.js', 'server');
@ -40,8 +37,10 @@ Package.onUse(function(api) {
api.addFiles('server/v1/im.js', 'server');
api.addFiles('server/v1/integrations.js', 'server');
api.addFiles('server/v1/misc.js', 'server');
api.addFiles('server/v1/permissions.js', 'server');
api.addFiles('server/v1/push.js', 'server');
api.addFiles('server/v1/settings.js', 'server');
api.addFiles('server/v1/stats.js', 'server');
api.addFiles('server/v1/users.js', 'server');
api.addFiles('server/v1/spotlight.js', 'server');
});

@ -6,7 +6,6 @@ class API extends Restivus {
super(properties);
this.logger = new Logger(`API ${ properties.version ? properties.version : 'default' } Logger`, {});
this.authMethods = [];
this.helperMethods = new Map();
this.fieldSeparator = '.';
this.defaultFieldsToExclude = {
joinCode: 0,
@ -51,6 +50,14 @@ class API extends Restivus {
};
}
hasHelperMethods() {
return RocketChat.API.helperMethods.size !== 0;
}
getHelperMethods() {
return RocketChat.API.helperMethods;
}
addAuthMethod(method) {
this.authMethods.push(method);
}
@ -121,7 +128,7 @@ class API extends Restivus {
routes.forEach((route) => {
//Note: This is required due to Restivus calling `addRoute` in the constructor of itself
if (this.helperMethods) {
if (this.hasHelperMethods()) {
Object.keys(endpoints).forEach((method) => {
if (typeof endpoints[method] === 'function') {
endpoints[method] = {action: endpoints[method]};
@ -129,7 +136,7 @@ class API extends Restivus {
//Add a try/catch for each endpoint
const originalAction = endpoints[method].action;
endpoints[method].action = function() {
endpoints[method].action = function _internalRouteActionHandler() {
this.logger.debug(`${ this.request.method.toUpperCase() }: ${ this.request.url }`);
let result;
try {
@ -155,7 +162,7 @@ class API extends Restivus {
return result;
};
for (const [name, helperMethod] of this.helperMethods) {
for (const [name, helperMethod] of this.getHelperMethods()) {
endpoints[method][name] = helperMethod;
}
@ -344,7 +351,9 @@ class API extends Restivus {
}
RocketChat.API = {};
RocketChat.API = {
helperMethods: new Map()
};
const getUserAuth = function _getUserAuth() {
const invalidResults = [undefined, null, false];
@ -379,7 +388,7 @@ const getUserAuth = function _getUserAuth() {
};
};
const createApi = function(enableCors) {
const createApi = function _createApi(enableCors) {
if (!RocketChat.API.v1 || RocketChat.API.v1._config.enableCors !== enableCors) {
RocketChat.API.v1 = new API({
version: 'v1',

@ -1,12 +0,0 @@
RocketChat.API.default.helperMethods.set('getLoggedInUser', function _getLoggedInUser() {
let user;
if (this.request.headers['x-auth-token'] && this.request.headers['x-user-id']) {
user = RocketChat.models.Users.findOne({
'_id': this.request.headers['x-user-id'],
'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken(this.request.headers['x-auth-token'])
});
}
return user;
});

@ -0,0 +1,4 @@
# REST API Helpers
## What are they?
Helpers are functions which get injected into the context of `this` on each request the REST API recieves. This allows for commonly used code, such as retriving the target user, to be placed in one spot and used throughout the entire REST API code base.

@ -1,4 +1,4 @@
RocketChat.API.v1.helperMethods.set('getLoggedInUser', function _getLoggedInUser() {
RocketChat.API.helperMethods.set('getLoggedInUser', function _getLoggedInUser() {
let user;
if (this.request.headers['x-auth-token'] && this.request.headers['x-user-id']) {

@ -2,7 +2,7 @@
// If the count query param isn't defined, then we set it to the "API_Default_Count" setting
// If the count is zero, then that means unlimited and is only allowed if the setting "API_Allow_Infinite_Count" is true
RocketChat.API.v1.helperMethods.set('getPaginationItems', function _getPaginationItems() {
RocketChat.API.helperMethods.set('getPaginationItems', function _getPaginationItems() {
const hardUpperLimit = RocketChat.settings.get('API_Upper_Count_Limit') <= 0 ? 100 : RocketChat.settings.get('API_Upper_Count_Limit');
const defaultCount = RocketChat.settings.get('API_Default_Count') <= 0 ? 50 : RocketChat.settings.get('API_Default_Count');
const offset = this.queryParams.offset ? parseInt(this.queryParams.offset) : 0;

@ -1,5 +1,5 @@
//Convenience method, almost need to turn it into a middleware of sorts
RocketChat.API.v1.helperMethods.set('getUserFromParams', function _getUserFromParams() {
RocketChat.API.helperMethods.set('getUserFromParams', function _getUserFromParams() {
const doesntExist = { _doesntExist: true };
let user;
const params = this.requestParams();

@ -1,4 +1,4 @@
RocketChat.API.v1.helperMethods.set('isUserFromParams', function _isUserFromParams() {
RocketChat.API.helperMethods.set('isUserFromParams', function _isUserFromParams() {
const params = this.requestParams();
return (!params.userId && !params.username && !params.user) ||

@ -1,4 +1,4 @@
RocketChat.API.v1.helperMethods.set('parseJsonQuery', function _parseJsonQuery() {
RocketChat.API.helperMethods.set('parseJsonQuery', function _parseJsonQuery() {
let sort;
if (this.queryParams.sort) {
try {

@ -1,3 +1,3 @@
RocketChat.API.v1.helperMethods.set('requestParams', function _requestParams() {
RocketChat.API.helperMethods.set('requestParams', function _requestParams() {
return ['POST', 'PUT'].includes(this.request.method) ? this.bodyParams : this.queryParams;
});

@ -255,3 +255,23 @@ RocketChat.API.v1.addRoute('chat.update', { authRequired: true }, {
});
}
});
RocketChat.API.v1.addRoute('chat.react', { authRequired: true }, {
post() {
if (!this.bodyParams.messageId || !this.bodyParams.messageId.trim()) {
throw new Meteor.Error('error-messageid-param-not-provided', 'The required "messageId" param is missing.');
}
const msg = RocketChat.models.Messages.findOneById(this.bodyParams.messageId);
if (!msg) {
throw new Meteor.Error('error-message-not-found', 'The provided "messageId" does not match any existing message.');
}
const emoji = this.bodyParams.emoji;
Meteor.runAsUser(this.userId, () => Meteor.call('setReaction', emoji, msg._id));
return RocketChat.API.v1.success();
}
});

@ -0,0 +1,14 @@
/**
This API returns all permissions that exists
on the server, with respective roles.
Method: GET
Route: api/v1/permissions
*/
RocketChat.API.v1.addRoute('permissions', { authRequired: true }, {
get() {
const result = Meteor.runAsUser(this.userId, () => Meteor.call('permissions/get'));
return RocketChat.API.v1.success(result);
}
});

@ -0,0 +1,27 @@
/**
This API returns the result of a query of rooms
and users, using Meteor's Spotlight method.
Method: GET
Route: api/v1/spotlight
Query params:
- query: The term to be searched.
*/
RocketChat.API.v1.addRoute('spotlight', { authRequired: true }, {
get() {
check(this.queryParams, {
query: String
});
const { query } = this.queryParams;
const result = Meteor.runAsUser(this.userId, () =>
Meteor.call('spotlight', query, null, {
rooms: true,
users: true
})
);
return RocketChat.API.v1.success(result);
}
});

@ -270,3 +270,24 @@ RocketChat.API.v1.addRoute('users.createToken', { authRequired: true }, {
return data ? RocketChat.API.v1.success({data}) : RocketChat.API.v1.unauthorized();
}
});
/**
This API returns the logged user roles.
Method: GET
Route: api/v1/user.roles
*/
RocketChat.API.v1.addRoute('user.roles', { authRequired: true }, {
get() {
let currentUserRoles = {};
const result = Meteor.runAsUser(this.userId, () => Meteor.call('getUserRoles'));
if (Array.isArray(result) && result.length > 0) {
currentUserRoles = result[0];
}
return RocketChat.API.v1.success(currentUserRoles);
}
});

@ -3,15 +3,24 @@
import _ from 'underscore';
import { FileUploadClass } from '../lib/FileUpload';
import '../../ufs/AmazonS3/server.js';
import http from 'http';
import https from 'https';
const get = function(file, req, res) {
const fileUrl = this.store.getRedirectURL(file);
if (fileUrl) {
res.setHeader('Location', fileUrl);
res.writeHead(302);
if (RocketChat.settings.get('FileUpload_S3_Proxy')) {
const request = /^https:/.test(fileUrl) ? https : http;
request.get(fileUrl, fileRes => fileRes.pipe(res));
} else {
res.setHeader('Location', fileUrl);
res.writeHead(302);
res.end();
}
} else {
res.end();
}
res.end();
};
const AmazonS3Uploads = new FileUploadClass({

@ -36,16 +36,6 @@ const FileSystemAvatars = new FileUploadClass({
// store setted bellow
get(file, req, res) {
const reqModifiedHeader = req.headers['if-modified-since'];
if (reqModifiedHeader) {
if (reqModifiedHeader === (file.uploadedAt && file.uploadedAt.toUTCString())) {
res.setHeader('Last-Modified', reqModifiedHeader);
res.writeHead(304);
res.end();
return;
}
}
const filePath = this.store.getFilePath(file._id, file);
try {
@ -53,10 +43,6 @@ const FileSystemAvatars = new FileUploadClass({
if (stat && stat.isFile()) {
file = FileUpload.addExtensionTo(file);
res.setHeader('Content-Disposition', 'inline');
res.setHeader('Last-Modified', file.uploadedAt.toUTCString());
res.setHeader('Content-Type', file.type);
res.setHeader('Content-Length', file.size);
this.store.getReadStream(file._id, file).pipe(res);
}

@ -3,7 +3,8 @@
import _ from 'underscore';
import { FileUploadClass } from '../lib/FileUpload';
import '../../ufs/GoogleStorage/server.js';
import http from 'http';
import https from 'https';
const get = function(file, req, res) {
this.store.getRedirectURL(file, (err, fileUrl) => {
@ -12,10 +13,17 @@ const get = function(file, req, res) {
}
if (fileUrl) {
res.setHeader('Location', fileUrl);
res.writeHead(302);
if (RocketChat.settings.get('FileUpload_GoogleStorage_Proxy')) {
const request = /^https:/.test(fileUrl) ? https : http;
request.get(fileUrl, fileRes => fileRes.pipe(res));
} else {
res.setHeader('Location', fileUrl);
res.writeHead(302);
res.end();
}
} else {
res.end();
}
res.end();
});
};

@ -64,7 +64,7 @@ const getByteRange = function(header) {
// code from: https://github.com/jalik/jalik-ufs/blob/master/ufs-server.js#L310
const readFromGridFS = function(storeName, fileId, file, headers, req, res) {
const readFromGridFS = function(storeName, fileId, file, req, res) {
const store = UploadFS.getStore(storeName);
const rs = store.getReadStream(fileId, file);
const ws = new stream.PassThrough();
@ -82,7 +82,7 @@ const readFromGridFS = function(storeName, fileId, file, headers, req, res) {
const accept = req.headers['accept-encoding'] || '';
// Transform stream
store.transformRead(rs, ws, fileId, file, req, headers);
store.transformRead(rs, ws, fileId, file, req);
const range = getByteRange(req.headers.range);
let out_of_range = false;
if (range) {
@ -91,34 +91,34 @@ const readFromGridFS = function(storeName, fileId, file, headers, req, res) {
// Compress data using gzip
if (accept.match(/\bgzip\b/) && range === null) {
headers['Content-Encoding'] = 'gzip';
delete headers['Content-Length'];
res.writeHead(200, headers);
res.setHeader('Content-Encoding', 'gzip');
res.removeHeader('Content-Length');
res.writeHead(200);
ws.pipe(zlib.createGzip()).pipe(res);
} else if (accept.match(/\bdeflate\b/) && range === null) {
// Compress data using deflate
headers['Content-Encoding'] = 'deflate';
delete headers['Content-Length'];
res.writeHead(200, headers);
res.setHeader('Content-Encoding', 'deflate');
res.removeHeader('Content-Length');
res.writeHead(200);
ws.pipe(zlib.createDeflate()).pipe(res);
} else if (range && out_of_range) {
// out of range request, return 416
delete headers['Content-Length'];
delete headers['Content-Type'];
delete headers['Content-Disposition'];
delete headers['Last-Modified'];
headers['Content-Range'] = `bytes */${ file.size }`;
res.writeHead(416, headers);
res.removeHeader('Content-Length');
res.removeHeader('Content-Type');
res.removeHeader('Content-Disposition');
res.removeHeader('Last-Modified');
res.setHeader('Content-Range', `bytes */${ file.size }`);
res.writeHead(416);
res.end();
} else if (range) {
headers['Content-Range'] = `bytes ${ range.start }-${ range.stop }/${ file.size }`;
delete headers['Content-Length'];
headers['Content-Length'] = range.stop - range.start + 1;
res.writeHead(206, headers);
res.setHeader('Content-Range', `bytes ${ range.start }-${ range.stop }/${ file.size }`);
res.removeHeader('Content-Length');
res.setHeader('Content-Length', range.stop - range.start + 1);
res.writeHead(206);
logger.debug('File upload extracting range');
ws.pipe(new ExtractRange({ start: range.start, stop: range.stop })).pipe(res);
} else {
res.writeHead(200, headers);
res.writeHead(200);
ws.pipe(res);
}
};
@ -140,13 +140,13 @@ new FileUploadClass({
get(file, req, res) {
file = FileUpload.addExtensionTo(file);
const headers = {
'Content-Disposition': `attachment; filename*=UTF-8''${ encodeURIComponent(file.name) }`,
'Last-Modified': file.uploadedAt.toUTCString(),
'Content-Type': file.type,
'Content-Length': file.size
};
return readFromGridFS(file.store, file._id, file, headers, req, res);
res.setHeader('Content-Disposition', `attachment; filename*=UTF-8''${ encodeURIComponent(file.name) }`);
res.setHeader('Last-Modified', file.uploadedAt.toUTCString());
res.setHeader('Content-Type', file.type);
res.setHeader('Content-Length', file.size);
return readFromGridFS(file.store, file._id, file, req, res);
}
});
@ -154,22 +154,8 @@ new FileUploadClass({
name: 'GridFS:Avatars',
get(file, req, res) {
const reqModifiedHeader = req.headers['if-modified-since'];
if (reqModifiedHeader && reqModifiedHeader === (file.uploadedAt && file.uploadedAt.toUTCString())) {
res.setHeader('Last-Modified', reqModifiedHeader);
res.writeHead(304);
res.end();
return;
}
file = FileUpload.addExtensionTo(file);
const headers = {
'Cache-Control': 'public, max-age=0',
'Expires': '-1',
'Content-Disposition': 'inline',
'Last-Modified': file.uploadedAt.toUTCString(),
'Content-Type': file.type,
'Content-Length': file.size
};
return readFromGridFS(file.store, file._id, file, headers, req, res);
return readFromGridFS(file.store, file._id, file, req, res);
}
});

@ -4,6 +4,7 @@ import fs from 'fs';
import stream from 'stream';
import mime from 'mime-type/with-db';
import Future from 'fibers/future';
import sharp from 'sharp';
import { Cookies } from 'meteor/ostrio:cookies';
const cookie = new Cookies();
@ -30,7 +31,6 @@ Object.assign(FileUpload, {
getPath(file) {
return `${ RocketChat.settings.get('uniqueID') }/uploads/${ file.rid }/${ file.userId }/${ file._id }`;
},
// transformWrite: FileUpload.uploadsTransformWrite
onValidate: FileUpload.uploadsOnValidate,
onRead(fileId, file, req, res) {
if (!FileUpload.requestCanAccessFiles(req)) {
@ -50,7 +50,6 @@ Object.assign(FileUpload, {
// filter: new UploadFS.Filter({
// onCheck: FileUpload.validateFileUpload
// }),
// transformWrite: FileUpload.avatarTransformWrite,
getPath(file) {
return `${ RocketChat.settings.get('uniqueID') }/avatars/${ file.userId }`;
},
@ -59,66 +58,63 @@ Object.assign(FileUpload, {
};
},
avatarTransformWrite(readStream, writeStream/*, fileId, file*/) {
if (RocketChatFile.enabled === false || RocketChat.settings.get('Accounts_AvatarResize') !== true) {
return readStream.pipe(writeStream);
}
const height = RocketChat.settings.get('Accounts_AvatarSize');
const width = height;
return (file => RocketChat.Info.GraphicsMagick.enabled ? file: file.alpha('remove'))(RocketChatFile.gm(readStream).background('#FFFFFF')).resize(width, `${ height }^`).gravity('Center').crop(width, height).extent(width, height).stream('jpeg').pipe(writeStream);
},
avatarsOnValidate(file) {
if (RocketChatFile.enabled === false || RocketChat.settings.get('Accounts_AvatarResize') !== true) {
if (RocketChat.settings.get('Accounts_AvatarResize') !== true) {
return;
}
const tempFilePath = UploadFS.getTempFilePath(file._id);
const height = RocketChat.settings.get('Accounts_AvatarSize');
const width = height;
const future = new Future();
(file => RocketChat.Info.GraphicsMagick.enabled ? file: file.alpha('remove'))(RocketChatFile.gm(tempFilePath).background('#FFFFFF')).resize(width, `${ height }^`).gravity('Center').crop(width, height).extent(width, height).setFormat('jpeg').write(tempFilePath, Meteor.bindEnvironment(err => {
if (err != null) {
console.error(err);
}
const size = fs.lstatSync(tempFilePath).size;
this.getCollection().direct.update({_id: file._id}, {$set: {size}});
future.return();
const s = sharp(tempFilePath);
s.rotate();
// Get metadata to resize the image the first time to keep "inside" the dimensions
// then resize again to create the canvas around
s.metadata(Meteor.bindEnvironment((err, metadata) => {
s.toFormat(sharp.format.jpeg)
.resize(Math.min(height, metadata.width), Math.min(height, metadata.height))
.pipe(sharp()
.resize(height, height)
.background('#FFFFFF')
.embed()
)
// Use buffer to get the result in memory then replace the existing file
// There is no option to override a file using this library
.toBuffer()
.then(Meteor.bindEnvironment(outputBuffer => {
fs.writeFile(tempFilePath, outputBuffer, Meteor.bindEnvironment(err => {
if (err != null) {
console.error(err);
}
const size = fs.lstatSync(tempFilePath).size;
this.getCollection().direct.update({_id: file._id}, {$set: {size}});
future.return();
}));
}));
}));
return future.wait();
},
uploadsTransformWrite(readStream, writeStream, fileId, file) {
if (RocketChatFile.enabled === false || !/^image\/.+/.test(file.type)) {
return readStream.pipe(writeStream);
}
let stream = undefined;
const identify = function(err, data) {
if (err) {
return stream.pipe(writeStream);
}
file.identify = {
format: data.format,
size: data.size
};
if (data.Orientation && !['', 'Unknown', 'Undefined'].includes(data.Orientation)) {
RocketChatFile.gm(stream).autoOrient().stream().pipe(writeStream);
} else {
stream.pipe(writeStream);
}
};
stream = RocketChatFile.gm(readStream).identify(identify).stream();
resizeImagePreview(file) {
file = RocketChat.models.Uploads.findOneById(file._id);
file = FileUpload.addExtensionTo(file);
const image = FileUpload.getStore('Uploads')._store.getReadStream(file._id, file);
const transformer = sharp()
.resize(32, 32)
.max()
.jpeg()
.blur();
const result = transformer.toBuffer().then((out) => out.toString('base64'));
image.pipe(transformer);
return result;
},
uploadsOnValidate(file) {
if (RocketChatFile.enabled === false || !/^image\/((x-windows-)?bmp|p?jpeg|png)$/.test(file.type)) {
if (!/^image\/((x-windows-)?bmp|p?jpeg|png)$/.test(file.type)) {
return;
}
@ -126,33 +122,45 @@ Object.assign(FileUpload, {
const fut = new Future();
const identify = Meteor.bindEnvironment((err, data) => {
const s = sharp(tmpFile);
s.metadata(Meteor.bindEnvironment((err, metadata) => {
if (err != null) {
console.error(err);
return fut.return();
}
file.identify = {
format: data.format,
size: data.size
const identify = {
format: metadata.format,
size: {
width: metadata.width,
height: metadata.height
}
};
if ([null, undefined, '', 'Unknown', 'Undefined'].includes(data.Orientation)) {
if (metadata.orientation == null) {
return fut.return();
}
RocketChatFile.gm(tmpFile).autoOrient().write(tmpFile, Meteor.bindEnvironment((err) => {
if (err != null) {
s.rotate()
.toFile(`${ tmpFile }.tmp`)
.then(Meteor.bindEnvironment(() => {
fs.unlink(tmpFile, Meteor.bindEnvironment(() => {
fs.rename(`${ tmpFile }.tmp`, tmpFile, Meteor.bindEnvironment(() => {
const size = fs.lstatSync(tmpFile).size;
this.getCollection().direct.update({_id: file._id}, {
$set: {
size,
identify
}
});
fut.return();
}));
}));
})).catch((err) => {
console.error(err);
}
const size = fs.lstatSync(tmpFile).size;
this.getCollection().direct.update({_id: file._id}, {$set: {size}});
fut.return();
}));
});
RocketChatFile.gm(tmpFile).identify(identify);
fut.return();
});
}));
return fut.wait();
},

@ -1,7 +1,7 @@
import _ from 'underscore';
Meteor.methods({
'sendFileMessage'(roomId, store, file, msgData = {}) {
async 'sendFileMessage'(roomId, store, file, msgData = {}) {
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'sendFileMessage' });
}
@ -39,6 +39,7 @@ Meteor.methods({
if (file.identify && file.identify.size) {
attachment.image_dimensions = file.identify.size;
}
attachment.image_preview = await FileUpload.resizeImagePreview(file);
} else if (/^audio\/.+/.test(file.type)) {
attachment.audio_url = fileUrl;
attachment.audio_type = file.type;

@ -112,6 +112,13 @@ RocketChat.settings.addGroup('FileUpload', function() {
},
i18nDescription: 'FileUpload_S3_URLExpiryTimeSpan_Description'
});
this.add('FileUpload_S3_Proxy', false, {
type: 'boolean',
enableQuery: {
_id: 'FileUpload_Storage_Type',
value: 'AmazonS3'
}
});
});
this.section('Google Cloud Storage', function() {
@ -140,6 +147,13 @@ RocketChat.settings.addGroup('FileUpload', function() {
value: 'GoogleCloudStorage'
}
});
this.add('FileUpload_GoogleStorage_Proxy', false, {
type: 'boolean',
enableQuery: {
_id: 'FileUpload_Storage_Type',
value: 'GoogleCloudStorage'
}
});
});
this.section('File System', function() {

@ -3,76 +3,13 @@ import stream from 'stream';
import fs from 'fs';
import path from 'path';
import mkdirp from 'mkdirp';
import gm from 'gm';
import {exec} from 'child_process';
// Fix problem with usernames being converted to object id
Grid.prototype.tryParseObjectId = function() {
return false;
};
//TODO: REMOVE RocketChatFile from globals
RocketChatFile = {
gm,
enabled: undefined,
enable() {
RocketChatFile.enabled = true;
return RocketChat.settings.updateOptionsById('Accounts_AvatarResize', {
alert: undefined
});
},
disable() {
RocketChatFile.enabled = false;
return RocketChat.settings.updateOptionsById('Accounts_AvatarResize', {
alert: 'The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server'
});
}
};
const detectGM = function() {
return exec('gm version', Meteor.bindEnvironment(function(error, stdout) {
if ((error == null) && stdout.indexOf('GraphicsMagick') > -1) {
RocketChatFile.enable();
RocketChat.Info.GraphicsMagick = {
enabled: true,
version: stdout
};
} else {
RocketChat.Info.GraphicsMagick = {
enabled: false
};
}
return exec('convert -version', Meteor.bindEnvironment(function(error, stdout) {
if ((error == null) && stdout.indexOf('ImageMagick') > -1) {
if (RocketChatFile.enabled !== true) {
// Enable GM to work with ImageMagick if no GraphicsMagick
RocketChatFile.gm = RocketChatFile.gm.subClass({
imageMagick: true
});
RocketChatFile.enable();
}
return RocketChat.Info.ImageMagick = {
enabled: true,
version: stdout
};
} else {
if (RocketChatFile.enabled !== true) {
RocketChatFile.disable();
}
return RocketChat.Info.ImageMagick = {
enabled: false
};
}
}));
}));
};
detectGM();
Meteor.methods({
'detectGM'() {
detectGM();
}
});
RocketChatFile = {};
RocketChatFile.bufferToStream = function(buffer) {
const bufferStream = new stream.PassThrough();

@ -14,7 +14,7 @@ const Gitlab = new CustomOAuth('gitlab', config);
if (Meteor.isServer) {
Meteor.startup(function() {
RocketChat.settings.get('API_Gitlab_URL', function(key, value) {
config.serverURL = value;
config.serverURL = value.trim().replace(/\/*$/, '');
Gitlab.configure(config);
});
});
@ -22,7 +22,7 @@ if (Meteor.isServer) {
Meteor.startup(function() {
Tracker.autorun(function() {
if (RocketChat.settings.get('API_Gitlab_URL')) {
config.serverURL = RocketChat.settings.get('API_Gitlab_URL');
config.serverURL = RocketChat.settings.get('API_Gitlab_URL').trim().replace(/\/*$/, '');
Gitlab.configure(config);
}
});

@ -46,7 +46,7 @@
"Accounts_Default_User_Preferences_mobileNotifications": "Mobile Benachrichtigungen bei",
"Accounts_denyUnverifiedEmail": "Nicht verifizierte E-Mail-Adressen ablehnen",
"Accounts_EmailVerification": "E-Mail-Verifizierung",
"Accounts_EmailVerification_Description": "Um diese Funktion nutzen zu können, stell bitte sicher, dass Deine SMTP-Einstellungen korrekt sind.",
"Accounts_EmailVerification_Description": "Um diese Funktion nutzen zu können, stellen Sie bitte sicher, dass Ihre SMTP-Einstellungen korrekt sind.",
"Accounts_Enrollment_Email": "Registrierungsmail",
"Accounts_Enrollment_Email_Default": "<h2> Willkommen zu <h1>[Site_Name]</h1></h2><p>Besuche <a href=\"[Site_URL]\">[Site_URL]</a> und probiere noch heute die beste Open-Source-Chat-Lösung aus.</p>",
"Accounts_Enrollment_Email_Description": "Sie können die folgenden Platzhalter verwenden: <br/><ul><li> [name], [fname], [lname] für den vollständigen Namen, Vornamen oder Nachnamen des Benutzers. </li><li> [email] für die E-Mail-Adresse des Benutzers. </li><li> [Site_Name] und [Site_URL] für den Anwendungsnamen und die URL. </li></ul>",
@ -774,12 +774,12 @@
"Hidden": "Versteckt",
"Hide_Avatars": "Avatare verstecken",
"Hide_flextab": "Rechte Seitenleiste über Klick verstecken",
"Hide_Group_Warning": "Sind sie sicher, dass Sie die Gruppe \"%s\" verstecken wollen?",
"Hide_Group_Warning": "Sind Sie sicher, dass Sie die Gruppe \"%s\" verstecken wollen?",
"Hide_Livechat_Warning": "Sind Sie sich sicher, dass Sie den Livechat mit \"%s\" ausblenden wollen?",
"Hide_Private_Warning": "Sind sie sicher, dass Sie das Gespräch mit \"%s\" verstecken wollen?",
"Hide_Private_Warning": "Sind Sie sicher, dass Sie das Gespräch mit \"%s\" verstecken wollen?",
"Hide_roles": "Rollen nicht anzeigen",
"Hide_room": "Raum verstecken",
"Hide_Room_Warning": "Sind sie sicher, dass Sie den Raum \"%s\" verstecken wollen?",
"Hide_Room_Warning": "Sind Sie sicher, dass Sie den Raum \"%s\" verstecken wollen?",
"Hide_Unread_Room_Status": "Ungelesen-Status des Raums nicht anzeigen",
"Hide_usernames": "Benutzernamen ausblenden",
"Highlights": "Hervorhebungen",
@ -796,8 +796,8 @@
"How_satisfied_were_you_with_this_chat": "Wie zufrieden warst Du mit diesem Chat?",
"How_to_handle_open_sessions_when_agent_goes_offline": "Behandlung von offenen Konversationen, wenn ein Agent Offline geht",
"If_this_email_is_registered": "Wenn es sich um eine registrierte E-Mail-Adresse handelt, werden wir an diese eine Anleitung zum Zurücksetzen des Passworts senden. Sollten Sie in Kürzen keine E-Mail erhalten, kommen Sie wieder und versuchen Sie es noch einmal.",
"If_you_are_sure_type_in_your_password": "Wenn Sie sich sicher sind, geben Sie ihr Passwort ein:",
"If_you_are_sure_type_in_your_username": "Wenn Du Dir sicher bist, gib Deinen Benutzernamen ein:",
"If_you_are_sure_type_in_your_password": "Wenn Sie sich sicher sind, geben Sie Ihr Passwort ein:",
"If_you_are_sure_type_in_your_username": "Wenn Sie sich sicher sind, geben Sie Ihren Benutzernamen ein:",
"Iframe_Integration": "Iframe-Integration",
"Iframe_Integration_receive_enable": "Empfang zulassen",
"Iframe_Integration_receive_enable_Description": "Erlaube dem übergeordneten Fenster (parent window) Befehle an Rocket.Chat zu senden.",
@ -997,7 +997,7 @@
"LDAP_Default_Domain_Description": "Wenn eine Standard-Domäne angegeben wurde, wird diese zur Erzeugung von E-Mail-Adressen verwendet, sofern keine E-Mail-Adresse aus dem LDAP importiert wurde. Die E-Mail wird konstruiert als `benutzername@standard-domäne` oder `unique_id@standard-domäne`<br/>Beispiel: `rocket.chat`",
"LDAP_Description": "LDAP ist eine hierarchische Datenbank, die viele Unternehmen nutzen, um eine eine Einmalanmeldung (SSO) zu ermöglichen. Über SSO kann \"ein Benutzer nach einer einmaligen Authentifizierung an einem Arbeitsplatz auf alle Rechner und Dienste, für die er lokal berechtigt ist, am selben Arbeitsplatz zugreifen kann, ohne sich jedes Mal neu anmelden zu müssen\". Genauere Informationen zur Konfiguration von LDAP mit Konfigurationsbeispielen erhalten Sie unter folgendem Link: https://rocket.chat/docs/administrator-guides/authentication/ldap/",
"LDAP_BaseDN": "Base DN",
"LDAP_BaseDN_Description": "Der volle Distinguished Name (DN) von einem LDAP-Unterverzeichnis, den Sie nach Benutzern und Gruppen durchsuchen möchten. Sie können so viele hinzufügen wie sie möchten. Jede Gruppe muss aber der selben Domainbasis angehören, in der sich die Benutzer befindet. Beispiel: `ou=Users+ou=Projects,dc=Example,dc=com`. Wenn Sie beschränkte Nutzergruppen angeben, werden nur Benutzer, die diesen Gruppen angehören, berücksichtig. Wir empfehlen, die oberste Ebene des LDAP-Verzeichnisbaums als Domainbasis anzugeben und Suchfilter zu verwenden, um Einschränkungen vorzunehmen.",
"LDAP_BaseDN_Description": "Der volle Distinguished Name (DN) von einem LDAP-Unterverzeichnis, den Sie nach Benutzern und Gruppen durchsuchen möchten. Sie können so viele hinzufügen, wie Sie möchten. Jede Gruppe muss aber der selben Domainbasis angehören, in der sich die Benutzer befinden. Wenn Sie beschränkte Nutzergruppen angeben, werden nur Benutzer, die diesen Gruppen angehören, berücksichtigt. Wir empfehlen, die oberste Ebene des LDAP-Verzeichnisbaums als Domainbasis anzugeben und Suchfilter zu verwenden, um Einschränkungen vorzunehmen.",
"LDAP_User_Search_Field": "Suchfeld",
"LDAP_User_Search_Field_Description": "Das LDAP-Attribut, welches den LDAP-Benutzer identifiziert, der sich zu authentifizieren versucht. Das Feld ist für die meisten Active-Directory-Installationen `sAMAccountName`, für andere LDAP-Lösungen wie OpenLDAP kann dieses jedoch auch `uid` sein. Sie können aber auch `mail` verwenden, um Benutzer mit Ihrer E-Mail-Adresse zu identifizieren - oder jedes Attribut, das Sie möchten. <br/>Sie können mehrere Werte, getrennt mit Kommata, verwenden, um es Benutzern zu erlauben, sich mit mehreren Kennungen anzumelden, wie zum Beispiel einem Benutzernamen und der E-Mail-Adresse.",
"LDAP_User_Search_Filter": "Filter",
@ -1066,11 +1066,11 @@
"LDAP_Username_Field_Description": "Geben Sie an, welches Feld als *Benutzername* für neue Benutzer verwendet werden soll. Lassen Sie das Feld leer, um den Nutzernamen zu verwenden, der auf der Anmeldeseite verwendet wird.<br/>Es können auch Template-Tags wie `#{givenNamen}.#{sn}` verwendet werden.<br/>Der Standardwert ist `sAMAccountName`.",
"Execute_Synchronization_Now": "Jetzt eine Synchronisierung ausführen",
"Least_Amount": "Geringste Anzahl",
"Leave_Group_Warning": "Sind sie sicher, dass Sie die Gruppe \"%s\" verlassen wollen?",
"Leave_Group_Warning": "Sind Sie sicher, dass Sie die Gruppe \"%s\" verlassen wollen?",
"Leave_Livechat_Warning": "Sind Sie sich sicher, dass Sie den Livechat mit \"%s\" verlassen wollen?",
"Leave_Private_Warning": "Sind sie sicher, dass Sie das Gespräch mit \"%s\" verlassen wollen?",
"Leave_Private_Warning": "Sind Sie sicher, dass Sie das Gespräch mit \"%s\" verlassen wollen?",
"Leave_room": "Raum verlassen",
"Leave_Room_Warning": "Sind sie sicher, dass Sie den Raum \"%s\" verlassen wollen?",
"Leave_Room_Warning": "Sind Sie sicher, dass Sie den Raum \"%s\" verlassen wollen?",
"Leave_the_current_channel": "Aktuellen Kanal verlassen",
"line": "Zeile",
"List_of_Channels": "Liste der Kanäle",
@ -1177,7 +1177,7 @@
"Message_AllowStarring": "Erlaube es, Nachrichten als Favoriten zu markieren",
"Message_AllowUnrecognizedSlashCommand": "Unerkannte Slash-Kommandos erlauben",
"Message_AlwaysSearchRegExp": "Beim Suchen immer reguläre Ausdrücke verwenden",
"Message_AlwaysSearchRegExp_Description": "Wir empfehlen diese Option, wenn ihre Sprache in der <a target=\"_blank\" href=\"https://docs.mongodb.org/manual/reference/text-search-languages/#text-search-languages\">MongoDB-Textsuche</a> nicht unterstützt wird.",
"Message_AlwaysSearchRegExp_Description": "Wir empfehlen diese Option, wenn Ihre Sprache in der <a target=\"_blank\" href=\"https://docs.mongodb.org/manual/reference/text-search-languages/#text-search-languages\">MongoDB-Textsuche</a> nicht unterstützt wird.",
"Message_Attachments": "Nachrichten-Anhänge",
"Message_Attachments_GroupAttach": "Schaltflächen für Anhänge gruppieren",
"Message_Attachments_GroupAttachDescription": "Dies sorgt dafür, dass die Schaltflächen in einem erweiterbaren Menü untergebracht werden. So wird weniger Bildschirmplatz benötigt.",
@ -1253,7 +1253,7 @@
"Name_cant_be_empty": "Es muss ein Name angegeben werden",
"Name_of_agent": "Name des Agenten",
"Name_optional": "Name (optional)",
"Name_Placeholder": "Bitte geben sie Ihren Namen ein",
"Name_Placeholder": "Bitte geben Sie Ihren Namen ein",
"Navigation_History": "Navigationsverlauf",
"New_Application": "Neue Anwendung",
"New_Custom_Field": "Neues benutzerdefiniertes Feld",
@ -1405,7 +1405,7 @@
"Please_wait_activation": "Bitte warten, das kann einige Zeit in Anspruch nehmen",
"Please_wait_while_OTR_is_being_established": "Bitte warten Sie, während OTR gestartet wird",
"Please_wait_while_your_account_is_being_deleted": "Bitte warten Sie, während Ihr Konto gelöscht wird",
"Please_wait_while_your_profile_is_being_saved": "Bitte warten Sie, während ihr Profil gespeichert wird",
"Please_wait_while_your_profile_is_being_saved": "Bitte warten Sie, während Ihr Profil gespeichert wird",
"Port": "Port",
"post-readonly": "Schreibgeschützt posten",
"post-readonly_description": "Berechtigung, in einen schreibgeschützten Kanal zu posten",
@ -1945,9 +1945,9 @@
"Validate_email_address": "E-Mail-Adresse bestätigen",
"Verification": "Überprüfung ",
"Verification_Description": "Sie können die folgenden Platzhalter verwenden: <br/><ul><li>[[Verification_Url] für die Verifikations-URL</li><li>[name], [fname], [lname] für den vollständigen Namen, Vornamen oder Nachnamen des Benutzers</li><li>[email] für die E-Mail-Adresse des Benutzers.</li><li>[Site_Name] und [Site_URL] für den Anwendungsnamen und die URL der Anwendung</li></ul>",
"Verification_Email": "Klicken Sie <a href=\"[Verification_Url]\">hier</a>, um ihr Benutzerkonto zu bestätigen",
"Verification_Email": "Klicken Sie <a href=\"[Verification_Url]\">hier</a>, um Ihr Benutzerkonto zu bestätigen",
"Verification_email_sent": "Bestätigungsmail gesendet",
"Verification_Email_Subject": "[Site_Name] - Bestätigen Sie ihr Benutzerkonto",
"Verification_Email_Subject": "[Site_Name] - Bestätigen Sie Ihr Benutzerkonto",
"Verified": "Überprüft",
"Verify": "überprüfen",
"Version": "Version",
@ -2044,8 +2044,8 @@
"You_must_join_to_view_messages_in_this_channel": "Sie müssen dem Kanal beitreten, um Nachrichten darin lesen zu können",
"You_need_confirm_email": "Sie müssen Ihre E-Mail-Adresse bestätigen, um sich anmelden zu können",
"You_need_install_an_extension_to_allow_screen_sharing": "Sie müssen eine Erweiterung installieren, um eine Bildschirmübertragung zu starten",
"You_need_to_change_your_password": "Sie müssen ihr Passwort ändern",
"You_need_to_type_in_your_password_in_order_to_do_this": "Um diese Aktion auszuführen, müssen sie Ihr Passwort eingeben",
"You_need_to_change_your_password": "Sie müssen Ihr Passwort ändern",
"You_need_to_type_in_your_password_in_order_to_do_this": "Um diese Aktion auszuführen, müssen Sie Ihr Passwort eingeben",
"You_need_to_type_in_your_username_in_order_to_do_this": "Sie müssen Ihren Benutzernamen angeben, um diese Aktion auszuführen",
"You_need_to_verifiy_your_email_address_to_get_notications": "Sie müssen Ihre E-Mail-Adresse bestätigen, um Benachrichtigungen erhalten zu können",
"You_need_to_write_something": "Du solltest etwas schreiben!",
@ -2053,13 +2053,13 @@
"You_should_name_it_to_easily_manage_your_integrations": "Zur einfacheren Verwaltung der Integrationen empfehlen wir, der Integration einen Namen zu geben.",
"You_will_not_be_able_to_recover": "Die Nachricht kann anschließend nicht wiederhergestellt werden",
"You_will_not_be_able_to_recover_file": "Das Wiederherstellen dieser Datei wird nicht möglich sein",
"You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Sie werden keine E-Mail-Benachrichtigungen erhalten, da Sie ihre E-Mail-Adresse nicht bestätigt haben",
"You_wont_receive_email_notifications_because_you_have_not_verified_your_email": "Sie werden keine E-Mail-Benachrichtigungen erhalten, da Sie Ihre E-Mail-Adresse nicht bestätigt haben",
"Your_email_has_been_queued_for_sending": "Ihre E-Mail wird in Kürze gesendet werden",
"Your_entry_has_been_deleted": "Ihr Eintrag wurde gelöscht",
"Your_file_has_been_deleted": "Ihre Datei wurde erfolgreich gelöscht",
"Your_mail_was_sent_to_s": "Ihre E-Mail wurde an %s gesendet",
"your_message": "ihre Nachricht",
"your_message_optional": "ihre optionale Nachricht",
"your_message": "Ihre Nachricht",
"your_message_optional": "Ihre optionale Nachricht",
"Your_password_is_wrong": "Falsches Passwort",
"Your_push_was_sent_to_s_devices": "Eine Push-Nachricht wurde an %s Geräte gesendet."
}

@ -722,6 +722,8 @@
"FileUpload_GoogleStorage_AccessId_Description": "The Access Id is generally in an email format, for example: \"example-test@example.iam.gserviceaccount.com\"",
"FileUpload_GoogleStorage_Bucket": "Google Storage Bucket Name",
"FileUpload_GoogleStorage_Bucket_Description": "The name of the bucket which the files should be uploaded to.",
"FileUpload_GoogleStorage_Proxy": "Proxy",
"FileUpload_GoogleStorage_Proxy_Description": "Proxy all file transmissions through your server instead of direct access to the asset's URL",
"FileUpload_GoogleStorage_Secret": "Google Storage Secret",
"FileUpload_GoogleStorage_Secret_Description": "Please follow <a href=\"https://github.com/CulturalMe/meteor-slingshot#google-cloud\">these instructions</a> and paste the result here.",
"FileUpload_MaxFileSize": "Maximum File Upload Size (in bytes)",
@ -737,6 +739,8 @@
"FileUpload_S3_BucketURL": "Bucket URL",
"FileUpload_S3_CDN": "CDN Domain for Downloads",
"FileUpload_S3_ForcePathStyle": "Force Path Style",
"FileUpload_S3_Proxy": "Proxy",
"FileUpload_S3_Proxy_Description": "Proxy all file transmissions through your server instead of direct access to the asset's URL",
"FileUpload_S3_Region": "Region",
"FileUpload_S3_SignatureVersion": "Signature Version",
"FileUpload_S3_URLExpiryTimeSpan": "URLs Expiration Timespan",
@ -1299,6 +1303,7 @@
"Mute_all_notifications": "Mute all notifications",
"mute-user": "Mute User",
"mute-user_description": "Permission to mute other users in the same channel",
"Mute_Focused_Conversations": "Mute Focused Conversations",
"Mute_someone_in_room": "Mute someone in the room",
"Mute_user": "Mute user",
"Muted": "Muted",

@ -50,7 +50,7 @@ this.processWebhookMessage = function(messageObj, user, defaultValues = { channe
const message = {
alias: messageObj.username || messageObj.alias || defaultValues.alias,
msg: s.trim(messageObj.text || messageObj.msg || ''),
attachments: messageObj.attachments,
attachments: messageObj.attachments || [],
parseUrls: messageObj.parseUrls !== undefined ? messageObj.parseUrls : !messageObj.attachments,
bot: messageObj.bot,
groupable: (messageObj.groupable !== undefined) ? messageObj.groupable : false

@ -5,8 +5,7 @@
"requires": true,
"dependencies": {
"katex": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.7.1.tgz",
"version": "https://registry.npmjs.org/katex/-/katex-0.7.1.tgz",
"integrity": "sha1-BrtSmO+tBeHnIoA1uo4VkfMGG48=",
"requires": {
"match-at": "0.1.1"

@ -402,6 +402,11 @@ RocketChat.settings.addGroup('Accounts', function() {
'public': true,
i18nLabel: 'New_Message_Notification'
});
this.add('Accounts_Default_User_Preferences_muteFocusedConversations', true, {
type: 'boolean',
'public': true,
i18nLabel: 'Mute_Focused_Conversations'
});
this.add('Accounts_Default_User_Preferences_notificationsSoundVolume', 100, {
type: 'int',
'public': true,

@ -4,22 +4,22 @@
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
meteor@1.8.0
webapp@1.4.0
meteor@1.8.2
webapp@1.5.0
logging@1.1.19
tracker@1.1.3
deps@1.0.12
session@1.1.7
ddp@1.4.0
livedata@1.0.18
mongo@1.3.1
mongo@1.4.2
blaze
ui
spacebars
templating
check@1.2.5
check@1.3.0
jquery@1.11.10
random@1.0.10
random@1.1.0
ejson@1.1.0
rocketchat:streamer
kadira:flow-router
@ -32,11 +32,11 @@ reactive-var@1.0.11
accounts-password@1.5.0
tap:i18n
smoral:sweetalert
ecmascript@0.9.0
es5-shim@4.6.15
standard-minifier-css@1.3.5
standard-minifier-js@2.2.0
shell-server@0.3.0
dynamic-import@0.2.0
ecmascript@0.10.0
es5-shim@4.7.0
standard-minifier-css@1.4.0
standard-minifier-js@2.3.1
shell-server@0.3.1
dynamic-import@0.3.0
konecty:user-presence

@ -2,86 +2,89 @@ accounts-base@1.4.2
accounts-password@1.5.0
aldeed:simple-schema@1.5.3
allow-deny@1.1.0
babel-compiler@6.24.7
babel-runtime@1.1.1
base64@1.0.10
babel-compiler@7.0.4
babel-runtime@1.2.2
base64@1.0.11
binary-heap@1.0.10
blaze@2.3.2
blaze-tools@1.0.10
boilerplate-generator@1.3.1
caching-compiler@1.1.9
boilerplate-generator@1.4.0
caching-compiler@1.1.11
caching-html-compiler@1.1.2
callback-hook@1.0.10
callback-hook@1.1.0
cfs:http-methods@0.0.32
check@1.2.5
coffeescript@1.12.7_3
coffeescript-compiler@1.12.7_3
check@1.3.0
coffeescript@1.0.17
ddp@1.4.0
ddp-client@2.2.0
ddp-common@1.3.0
ddp-client@2.3.1
ddp-common@1.4.0
ddp-rate-limiter@1.0.7
ddp-server@2.1.1
ddp-server@2.1.2
deps@1.0.12
diff-sequence@1.0.7
dynamic-import@0.2.1
ecmascript@0.9.0
diff-sequence@1.1.0
dynamic-import@0.3.0
ecmascript@0.10.4
ecmascript-runtime@0.5.0
ecmascript-runtime-client@0.5.0
ecmascript-runtime-client@0.6.2
ecmascript-runtime-server@0.5.0
ejson@1.1.0
email@1.2.3
es5-shim@4.6.15
es5-shim@4.7.3
geojson-utils@1.0.10
html-tools@1.0.11
htmljs@1.0.11
http@1.3.0
id-map@1.0.9
jquery@1.11.10
http@1.4.0
id-map@1.1.0
jquery@1.11.11
kadira:blaze-layout@2.3.0
kadira:flow-router@2.12.1
konecty:nrr@2.0.2
konecty:user-presence@2.0.1
less@2.7.11
less@2.7.12
livedata@1.0.18
localstorage@1.2.0
logging@1.1.19
mdg:validation-error@0.5.1
meteor@1.8.2
meteorspark:util@0.2.0
minifier-css@1.2.16
minifier-js@2.2.2
minifier-css@1.3.1
minifier-js@2.3.2
minimongo@1.4.3
mizzao:timesync@0.5.0
modules@0.11.2
modules-runtime@0.9.1
modules@0.11.4
modules-runtime@0.9.2
momentjs:moment@2.20.1
mongo@1.3.1
mongo@1.4.3
mongo-dev-server@1.1.0
mongo-id@1.0.6
nooitaf:colors@1.1.2_1
npm-bcrypt@0.9.3
npm-mongo@2.2.33
npm-mongo@2.2.34
observe-sequence@1.0.16
ordered-dict@1.0.9
promise@0.10.1
ordered-dict@1.1.0
promise@0.10.2
raix:eventemitter@0.1.3
random@1.0.10
rate-limit@1.0.8
random@1.1.0
rate-limit@1.0.9
reactive-dict@1.2.0
reactive-var@1.0.11
retry@1.0.9
reload@1.2.0
retry@1.1.0
rocketchat:streamer@0.6.1
routepolicy@1.0.12
server-render@0.3.0
service-configuration@1.0.11
session@1.1.7
sha@1.0.9
shell-server@0.3.1
shim-common@0.1.0
smoral:sweetalert@1.1.1
socket-stream-client@0.1.0
spacebars@1.0.15
spacebars-compiler@1.1.3
srp@1.0.10
standard-minifier-css@1.3.5
standard-minifier-js@2.2.3
standard-minifier-css@1.4.1
standard-minifier-js@2.3.2
tap:i18n@1.8.2
templating@1.3.2
templating-compiler@1.3.3
@ -90,6 +93,6 @@ templating-tools@1.1.2
tracker@1.1.3
ui@1.0.13
underscore@1.0.10
url@1.1.0
webapp@1.4.0
url@1.2.0
webapp@1.5.0
webapp-hashing@1.0.9

@ -20,11 +20,11 @@
"email": "support@rocket.chat"
},
"dependencies": {
"autolinker": "^1.6.0",
"jquery": "^3.2.1",
"babel-runtime": "^6.26.0",
"@babel/runtime": "^7.0.0-beta.40",
"autolinker": "^1.6.2",
"bcrypt": "^1.0.3",
"core-js": "^2.5.3",
"jquery": "^3.3.1",
"moment": "^2.20.1",
"toastr": "^2.1.4",
"underscore": "^1.8.3",

@ -1,4 +0,0 @@
{
"Additional_Feedback": "Bykomende terugvoer",
"No": "Nee"
}

@ -1,3 +0,0 @@
{
"Additional_Feedback": "Нэмэлт санал хүсэлт"
}

@ -1,4 +0,0 @@
{
"Additional_Feedback": "Dodatne povratne informacije",
"Appearance": "Videz"
}

@ -1,46 +0,0 @@
{
"Additional_Feedback": "ความคดเหนเพมเตม",
"Appearance": "ลกษณะภายนอก",
"Are_you_sure_do_you_want_end_this_chat": "คณตองการทจะจบการสนทนาไชหรอไม",
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "คณตองการทจะจบการสนทนาและเปลยนแผนกไชหรอไม",
"Cancel": "ยกเลก",
"Change": "เปลยน",
"Chat_ended": "การสนทนาจบสนแลว!",
"Choose_a_new_department": "เลอกแผนกใหม",
"Close_menu": "ปดตวเลอก",
"Conversation_finished": "การสนทนาเสรจสนแลว",
"End_chat": "จบการสนทนา",
"How_friendly_was_the_chat_agent": "Chat agent เปนมตรแคไหน?",
"How_knowledgeable_was_the_chat_agent": "Chat agent มความฉลาดแคไหน?",
"How_responsive_was_the_chat_agent": "Chat agent ตอบสนองดแคไหน?",
"How_satisfied_were_you_with_this_chat": "คณพงพอใจใน Chat นแคไหน?",
"Installation": "การตดตง",
"New_messages": "ขอความใหม",
"No": "ไม",
"Options": "ตวเลอก",
"Please_answer_survey": "กรณาสละเวลาตอบแบบสอบถามเกยวกบ Chat น",
"Please_choose_a_department": "กรณาเลอกแผนก",
"Please_fill_name_and_email": "กรณากรอกชอและอเมล",
"Powered_by": "ถกสรางโดย",
"Request_video_chat": "รองขอการสนทนาแบบวโอ",
"Select_a_department": "เลอกแผนก",
"Switch_department": "เปลยนแผนก",
"Department_switched": "แผนกถกเปลยนแลว",
"Send": "สง",
"Skip": "ขาม",
"Start_Chat": "เรมการสนทนา",
"Survey": "แบบสอบถาม",
"Survey_instructions": "ใหคะแนนคำถามตามความพอใจ, 1 แปลวาไมพอใจอยางมากและ 5 แปลวาพอใจอยางทด",
"Thank_you_for_your_feedback": "ขอบคณสำหรบความคดเหน",
"Thanks_We_ll_get_back_to_you_soon": "ขอบคณ! เราจะตดตอกลบโดยเรว",
"transcript_sent": "สำเนาถกสงแลว",
"Type_your_email": "พมอเมลของคณ",
"Type_your_message": "พมขอความของคณ",
"Type_your_name": "พมชอของคณ",
"User_joined": "ผใชงานเขารวมแลว",
"User_left": "ผใชงานออกแลว",
"We_are_offline_Sorry_for_the_inconvenience": "เรากำลงออฟไลน ขออภยในความไมสะดวก",
"Yes": "ไช",
"You": "คณ",
"You_must_complete_all_fields": "คณตองกรอกขอมลทกชอง"
}

@ -1,46 +0,0 @@
{
"Additional_Feedback": "Phản hồi bổ sung",
"Appearance": "Kiểu hiển thị",
"Are_you_sure_do_you_want_end_this_chat": "Bạn có chắc muốn kết thúc cuộc nói chuyện này?",
"Are_you_sure_do_you_want_end_this_chat_and_switch_department": "Bạn muốn kết thúc cuộc nói chuyện này và chuyển sang bộ phận khác?",
"Cancel": "Hủy",
"Change": "Thay đổi",
"Chat_ended": "Cuộc nói chuyện đã kết thúc!",
"Choose_a_new_department": "Chọn bộ phận mới",
"Close_menu": "Đóng",
"Conversation_finished": "Cuộc hội thoại đã kết thúc",
"End_chat": "Kết thúc nói chuyện",
"How_friendly_was_the_chat_agent": "Độ thân thiện của nhân viên hỗ trợ như thế nào?",
"How_knowledgeable_was_the_chat_agent": "Độ hiểu biết của nhân viên hỗ trợ như thế nào?",
"How_responsive_was_the_chat_agent": "Phản hồi của nhân viên tư vấn như thế nào?",
"How_satisfied_were_you_with_this_chat": "Mức độ thỏa mãn của bạn với cuộc nói chuyện vừa xong?",
"Installation": "Cài đặt",
"New_messages": "Tin nhắn mới",
"No": "Không",
"Options": "Tùy chọn",
"Please_answer_survey": "Vui lòng dành ít thời gian để trả lời một khảo sát ngắn về cuộc nói chuyện vừa xong",
"Please_choose_a_department": "Vui lòng chọn bộ phận",
"Please_fill_name_and_email": "Vui lòng nhập tên và email",
"Powered_by": "Được hỗ trợ bởi",
"Request_video_chat": "Yêu cầu đàm thoại video",
"Select_a_department": "Chọn một bộ phận",
"Switch_department": "Chuyển bộ phận",
"Department_switched": "Bộ phận đã chuyển",
"Send": "Gửi",
"Skip": "Bỏ qua",
"Start_Chat": "Bắt đầu trò chuyện",
"Survey": "Khảo sát",
"Survey_instructions": "Đánh giá mức độ hài lòng cho mỗi câu hỏi, 1 tức là hoàn toàn thất vọng và 5 tức là tuyệt đối hài lòng",
"Thank_you_for_your_feedback": "Cảm ơn sự phản hồi của bạn",
"Thanks_We_ll_get_back_to_you_soon": "Xin cảm ơn! Chúng tôi sẽ phản hồi bạn sớm.",
"transcript_sent": "Bản dịch đã được gửi",
"Type_your_email": "Gõ email của bạn",
"Type_your_message": "Gõ tin nhắn của bạn",
"Type_your_name": "Gõ tên của bạn",
"User_joined": "Người dùng đã tham gia",
"User_left": "Người dùng rời đi",
"We_are_offline_Sorry_for_the_inconvenience": "Chúng tôi đang offline. Rất tiếc vì sự bất tiện này.",
"Yes": "Có",
"You": "Bạn",
"You_must_complete_all_fields": "Bạn phải điền hết các ô"
}

@ -1,879 +0,0 @@
{
"name": "rocketchat-livechat",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"ajv": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz",
"integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=",
"requires": {
"co": "4.6.0",
"fast-deep-equal": "1.0.0",
"fast-json-stable-stringify": "2.0.0",
"json-schema-traverse": "0.3.1"
}
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
"integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo="
},
"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",
"integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=",
"requires": {
"delegates": "1.0.0",
"readable-stream": "2.3.3"
}
},
"asn1": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y="
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"autolinker": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.6.0.tgz",
"integrity": "sha1-utN2t62OQV8i8QL8Dzf2QOZPHL8="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz",
"integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4="
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "2.5.1",
"regenerator-runtime": "0.11.0"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"bcrypt": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-1.0.3.tgz",
"integrity": "sha1-sC3cbAtS6ha40883XVoy54DatUg=",
"requires": {
"nan": "2.6.2",
"node-pre-gyp": "0.6.36"
}
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
"integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
}
},
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
"requires": {
"inherits": "2.0.3"
}
},
"boom": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz",
"integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=",
"requires": {
"hoek": "4.2.0"
}
},
"brace-expansion": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
"requires": {
"balanced-match": "1.0.0",
"concat-map": "0.0.1"
}
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
},
"combined-stream": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
"integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=",
"requires": {
"delayed-stream": "1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
},
"core-js": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz",
"integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cryptiles": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz",
"integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=",
"requires": {
"boom": "5.2.0"
},
"dependencies": {
"boom": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz",
"integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=",
"requires": {
"hoek": "4.2.0"
}
}
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "1.0.0"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"deep-extend": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz",
"integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8="
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
},
"ecc-jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"extend": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz",
"integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8="
},
"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",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
"integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=",
"requires": {
"asynckit": "0.4.0",
"combined-stream": "1.0.5",
"mime-types": "2.1.17"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fstream": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
"requires": {
"graceful-fs": "4.1.11",
"inherits": "2.0.3",
"mkdirp": "0.5.1",
"rimraf": "2.6.2"
}
},
"fstream-ignore": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz",
"integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=",
"requires": {
"fstream": "1.0.11",
"inherits": "2.0.3",
"minimatch": "3.0.4"
}
},
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"requires": {
"aproba": "1.2.0",
"console-control-strings": "1.1.0",
"has-unicode": "2.0.1",
"object-assign": "4.1.1",
"signal-exit": "3.0.2",
"string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"strip-ansi": "3.0.1",
"wide-align": "1.1.2"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "1.0.0"
}
},
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"graceful-fs": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
"requires": {
"ajv": "5.3.0",
"har-schema": "2.0.0"
}
},
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
},
"hawk": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz",
"integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=",
"requires": {
"boom": "4.3.1",
"cryptiles": "3.1.2",
"hoek": "4.2.0",
"sntp": "2.1.0"
}
},
"hoek": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz",
"integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0="
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "1.0.0",
"jsprim": "1.4.1",
"sshpk": "1.13.1"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
"integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4="
},
"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",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"requires": {
"number-is-nan": "1.0.1"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jquery": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.2.1.tgz",
"integrity": "sha1-XE2d5lKvbNCncBVKYxu6ErAVx4c="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"mime-db": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
"integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE="
},
"mime-types": {
"version": "2.1.17",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
"integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
"requires": {
"mime-db": "1.30.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"requires": {
"brace-expansion": "1.1.8"
}
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"requires": {
"minimist": "0.0.8"
}
},
"moment": {
"version": "2.20.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
"integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"nan": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz",
"integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U="
},
"node-pre-gyp": {
"version": "0.6.36",
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz",
"integrity": "sha1-22BBEst04NR3VU6bUFsXq936t4Y=",
"requires": {
"mkdirp": "0.5.1",
"nopt": "4.0.1",
"npmlog": "4.1.2",
"rc": "1.2.2",
"request": "2.83.0",
"rimraf": "2.6.2",
"semver": "5.4.1",
"tar": "2.2.1",
"tar-pack": "3.4.1"
}
},
"nopt": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"requires": {
"abbrev": "1.1.1",
"osenv": "0.1.4"
}
},
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=",
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
"gauge": "2.7.4",
"set-blocking": "2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"oauth-sign": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
"integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1.0.2"
}
},
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"osenv": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
"integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
},
"qs": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz",
"integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg="
},
"rc": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz",
"integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=",
"requires": {
"deep-extend": "0.4.2",
"ini": "1.3.4",
"minimist": "1.2.0",
"strip-json-comments": "2.0.1"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
},
"readable-stream": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
"integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"safe-buffer": "5.1.1",
"string_decoder": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"util-deprecate": "1.0.2"
}
},
"regenerator-runtime": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz",
"integrity": "sha1-flT+W1zNXWYk6mJVw0c74JC4AuE="
},
"request": {
"version": "2.83.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz",
"integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==",
"requires": {
"aws-sign2": "0.7.0",
"aws4": "1.6.0",
"caseless": "0.12.0",
"combined-stream": "1.0.5",
"extend": "3.0.1",
"forever-agent": "0.6.1",
"form-data": "2.3.1",
"har-validator": "5.0.3",
"hawk": "6.0.2",
"http-signature": "1.2.0",
"is-typedarray": "1.0.0",
"isstream": "0.1.2",
"json-stringify-safe": "5.0.1",
"mime-types": "2.1.17",
"oauth-sign": "0.8.2",
"performance-now": "2.1.0",
"qs": "6.5.1",
"safe-buffer": "5.1.1",
"stringstream": "0.0.5",
"tough-cookie": "2.3.3",
"tunnel-agent": "0.6.0",
"uuid": "3.1.0"
}
},
"rimraf": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
"integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=",
"requires": {
"glob": "7.1.2"
}
},
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
},
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
"integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4="
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
"sntp": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz",
"integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==",
"requires": {
"hoek": "4.2.0"
}
},
"sprintf-js": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz",
"integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw="
},
"sshpk": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz",
"integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=",
"requires": {
"asn1": "0.2.3",
"assert-plus": "1.0.0",
"bcrypt-pbkdf": "1.0.1",
"dashdash": "1.14.1",
"ecc-jsbn": "0.1.1",
"getpass": "0.1.7",
"jsbn": "0.1.1",
"tweetnacl": "0.14.5"
}
},
"string-width": {
"version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
},
"string_decoder": {
"version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
"requires": {
"safe-buffer": "5.1.1"
}
},
"string_decoder": {
"version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
"requires": {
"safe-buffer": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz"
}
},
"stringstream": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg="
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"requires": {
"ansi-regex": "2.1.1"
}
},
"strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
},
"tar": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
"requires": {
"block-stream": "0.0.9",
"fstream": "1.0.11",
"inherits": "2.0.3"
}
},
"tar-pack": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.1.tgz",
"integrity": "sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==",
"requires": {
"debug": "2.6.9",
"fstream": "1.0.11",
"fstream-ignore": "1.0.5",
"once": "1.4.0",
"readable-stream": "2.3.3",
"rimraf": "2.6.2",
"tar": "2.2.1",
"uid-number": "0.0.6"
}
},
"toastr": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz",
"integrity": "sha1-i0O+ZPudDEFIcURvLbjoyk6V8YE=",
"requires": {
"jquery": "3.2.1"
}
},
"tough-cookie": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz",
"integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=",
"requires": {
"punycode": "1.4.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "5.1.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
"optional": true
},
"uid-number": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
"integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE="
},
"underscore": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
},
"underscore.string": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz",
"integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=",
"requires": {
"sprintf-js": "1.1.1",
"util-deprecate": "1.0.2"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
"integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "1.3.0"
}
},
"wide-align": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
"integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=",
"requires": {
"string-width": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
}
}

@ -1,4 +1,7 @@
import crypto from 'crypto';
import LivechatVisitors from '../../../server/models/LivechatVisitors';
/**
* @api {post} /livechat/facebook Send Facebook message
* @apiName Facebook
@ -52,17 +55,15 @@ RocketChat.API.v1.addRoute('livechat/facebook', {
}
}
};
let visitor = RocketChat.models.Users.getVisitorByToken(this.bodyParams.token);
let visitor = LivechatVisitors.getVisitorByToken(this.bodyParams.token);
if (visitor) {
const rooms = RocketChat.models.Rooms.findOpenByVisitorToken(visitor.profile.token).fetch();
const rooms = RocketChat.models.Rooms.findOpenByVisitorToken(visitor.token).fetch();
if (rooms && rooms.length > 0) {
sendMessage.message.rid = rooms[0]._id;
} else {
sendMessage.message.rid = Random.id();
}
sendMessage.message.token = visitor.profile.token;
sendMessage.message.token = visitor.token;
} else {
sendMessage.message.rid = Random.id();
sendMessage.message.token = this.bodyParams.token;

@ -215,10 +215,6 @@ RocketChat.Livechat = {
const now = new Date();
const closeData = {
user: {
_id: user._id,
username: user.username
},
closedAt: now,
chatDuration: (now.getTime() - room.ts) / 1000
};
@ -251,7 +247,7 @@ RocketChat.Livechat = {
if (room.servedBy) {
RocketChat.models.Subscriptions.hideByRoomIdAndUserId(room._id, room.servedBy._id);
}
RocketChat.models.Messages.createCommandWithRoomIdAndUser('promptTranscript', room._id, closeData.user);
RocketChat.models.Messages.createCommandWithRoomIdAndUser('promptTranscript', room._id, closeData.closedBy);
Meteor.defer(() => {
RocketChat.callbacks.run('livechat.closeRoom', room);

@ -35,10 +35,8 @@ class LivechatInquiry extends RocketChat.models._Base {
}, {
$set: {
status: 'closed',
closedBy: {
_id: closeInfo.user._id,
username: closeInfo.user.username
},
closer: closeInfo.closer,
closedBy: closeInfo.closedBy,
closedAt: closeInfo.closedAt,
chatDuration: closeInfo.chatDuration
}

@ -33,7 +33,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
const visitor = LivechatVisitors.getVisitorByToken(room.v.token);
if (!visitor || !visitor.profile || !visitor.phone || visitor.phone.length === 0) {
if (!visitor || !visitor.phone || visitor.phone.length === 0) {
return message;
}

@ -5,7 +5,7 @@ import QueryString from 'querystring';
const recursiveRemove = (message, deep = 1) => {
if (message) {
if ('attachments' in message && deep < RocketChat.settings.get('Message_QuoteChainLimit')) {
if ('attachments' in message && message.attachments !== null && deep < RocketChat.settings.get('Message_QuoteChainLimit')) {
message.attachments.map((msg) => recursiveRemove(msg, deep + 1));
} else {
delete(message.attachments);

@ -262,6 +262,8 @@
}
.emoji.big {
display: inline-block !important;
width: 44px;
height: 44px;
}

@ -276,6 +276,13 @@
</select>
</div>
</div>
<div class="input-line double-col" id="muteFocusedConversations">
<label>{{_ "Mute_Focused_Conversations"}}</label>
<div>
<label><input type="radio" name="muteFocusedConversations" value="true" checked="{{checked 'muteFocusedConversations' true}}"/> {{_ "True"}}</label>
<label><input type="radio" name="muteFocusedConversations" value="false" checked="{{checked 'muteFocusedConversations' false}}"/> {{_ "False"}}</label>
</div>
</div>
<div class="input-line double-col">
<label>{{_ "Notifications_Sound_Volume"}}</label>
<div>

@ -26,6 +26,9 @@ Template.accountPreferences.helpers({
newRoomNotification() {
return RocketChat.getUserPreference(Meteor.user(), 'newRoomNotification');
},
muteFocusedConversations() {
return RocketChat.getUserPreference(Meteor.user(), 'muteFocusedConversations');
},
languages() {
const languages = TAPi18n.getLanguages();
@ -129,6 +132,7 @@ Template.accountPreferences.onCreated(function() {
data.convertAsciiEmoji = JSON.parse($('input[name=convertAsciiEmoji]:checked').val());
data.saveMobileBandwidth = JSON.parse($('input[name=saveMobileBandwidth]:checked').val());
data.collapseMediaByDefault = JSON.parse($('input[name=collapseMediaByDefault]:checked').val());
data.muteFocusedConversations = JSON.parse($('#muteFocusedConversations').find('input:checked').val());
data.viewMode = parseInt($('#viewMode').find('select').val());
data.hideUsernames = JSON.parse($('#hideUsernames').find('input:checked').val());
data.hideRoles = JSON.parse($('#hideRoles').find('input:checked').val());
@ -228,7 +232,7 @@ Template.accountPreferences.events({
}
if (audio) {
const $audio = $(`audio#${ audio }`);
return $audio && $audio[0] && $audio.play();
return $audio && $audio[0] && $audio[0].play();
}
}
});

@ -10,7 +10,11 @@ this.getAvatarAsPng = function(username, cb) {
canvas.height = image.height;
const context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
return cb(canvas.toDataURL('image/png'));
try {
return cb(canvas.toDataURL('image/png'));
} catch (e) {
return cb('');
}
};
return image.onerror = function() {
return cb('');

@ -30,7 +30,8 @@ Meteor.methods({
sidebarShowUnread: Match.Optional(Boolean),
sidebarSortby: Match.Optional(String),
sidebarViewMode: Match.Optional(String),
sidebarHideAvatar: Match.Optional(Boolean)
sidebarHideAvatar: Match.Optional(Boolean),
muteFocusedConversations: Match.Optional(Boolean)
};
check(settings, Match.ObjectIncluding(keys));
if (settings.mergeChannels) {

@ -1,5 +1,6 @@
/* globals FileUpload */
import _ from 'underscore';
import sharp from 'sharp';
Meteor.startup(function() {
WebApp.connectHandlers.use('/avatar/', Meteor.bindEnvironment(function(req, res/*, next*/) {
@ -38,6 +39,21 @@ Meteor.startup(function() {
if (file) {
res.setHeader('Content-Security-Policy', 'default-src \'none\'');
const reqModifiedHeader = req.headers['if-modified-since'];
if (reqModifiedHeader && reqModifiedHeader === (file.uploadedAt && file.uploadedAt.toUTCString())) {
res.setHeader('Last-Modified', reqModifiedHeader);
res.writeHead(304);
res.end();
return;
}
res.setHeader('Cache-Control', 'public, max-age=0');
res.setHeader('Expires', '-1');
res.setHeader('Content-Disposition', 'inline');
res.setHeader('Last-Modified', file.uploadedAt.toUTCString());
res.setHeader('Content-Type', file.type);
res.setHeader('Content-Length', file.size);
return FileUpload.get(file, req, res);
} else {
res.setHeader('Content-Type', 'image/svg+xml');
@ -79,11 +95,21 @@ Meteor.startup(function() {
initials = username.replace(/[^A-Za-z0-9]/g, '').substr(0, 1).toUpperCase();
}
const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 80 80\">\n<rect width=\"100%\" height=\"100%\" rx=\"6\" ry=\"6\" fill=\"${ color }\"/>\n<text x=\"50%\" y=\"50%\" dy=\"0.36em\" text-anchor=\"middle\" pointer-events=\"none\" fill=\"#ffffff\" font-family=\"Helvetica, Arial, Lucida Grande, sans-serif\" font-size="50">\n${ initials }\n</text>\n</svg>`;
const viewSize = parseInt(req.query.size) || 200;
const fontSize = viewSize / 1.6;
const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${ viewSize } ${ viewSize }\">\n<rect width=\"100%\" height=\"100%\" fill=\"${ color }\"/>\n<text x=\"50%\" y=\"50%\" dy=\"0.36em\" text-anchor=\"middle\" pointer-events=\"none\" fill=\"#ffffff\" font-family=\"Helvetica, Arial, Lucida Grande, sans-serif\" font-size="${ fontSize }">\n${ initials }\n</text>\n</svg>`;
if (['png', 'jpg', 'jpeg'].includes(req.query.format)) {
res.setHeader('Content-Type', `image/${ req.query.format }`);
sharp(new Buffer(svg))
.toFormat(req.query.format)
.pipe(res);
return;
}
res.write(svg);
res.end();
return;
}
}

@ -360,4 +360,21 @@ describe('[Users]', function() {
});
});
});
describe('[/user.roles]', () => {
it('should return id and name of user, and an array of roles', (done) => {
request.get(api('user.roles'))
.set(credentials)
.expect(200)
.expect('Content-Type', 'application/json')
.expect((res) => {
expect(res.body).to.have.property('username');
expect(res.body).to.have.property('roles').and.to.be.a('array');
expect(res.body).to.have.property('_id');
expect(res.body).to.have.property('success', true);
})
.end(done);
});
});
});

@ -168,4 +168,19 @@ describe('[Chat]', function() {
})
.end(done);
});
it('/chat.react', (done) => {
request.post(api('chat.react'))
.set(credentials)
.send({
emoji: 'smile',
messageId: message._id
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
})
.end(done);
});
});

@ -0,0 +1,33 @@
/* eslint-env mocha */
/* globals expect */
import { getCredentials, api, request, credentials } from '../../data/api-data.js';
describe('[Permissions]', function() {
this.retries(0);
before(done => getCredentials(done));
describe('[/permissions]', () => {
it('should return all permissions that exists on the server, with respective roles', (done) => {
request.get(api('permissions'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.be.a('array');
const firstElement = res.body[0];
expect(firstElement).to.have.property('_id');
expect(firstElement).to.have.property('roles').and.to.be.a('array');
expect(firstElement).to.have.property('_updatedAt');
expect(firstElement).to.have.property('meta');
expect(firstElement.meta).to.have.property('revision');
expect(firstElement.meta).to.have.property('created');
expect(firstElement.meta).to.have.property('version');
expect(firstElement).to.have.property('$loki');
})
.end(done);
});
});
});

@ -0,0 +1,40 @@
/* eslint-env mocha */
/* globals expect */
import {getCredentials, api, request, credentials } from '../../data/api-data.js';
describe('[Spotlight]', function() {
this.retries(0);
before(done => getCredentials(done));
describe('[/spotlight]', () => {
it('should fail when does not have query param', (done) => {
request.get(api('spotlight'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(400)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error');
})
.end(done);
});
it('should return objects for a valid query param', (done) => {
request.get(api('spotlight'))
.query({
query: 'foobar'
})
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('users').that.have.lengthOf(0);
expect(res.body).to.have.property('rooms').that.have.lengthOf(0);
})
.end(done);
});
});
});

@ -211,6 +211,10 @@ class Administration extends Page {
get accountsNewMessageNotification() { return browser.element('[name="Accounts_Default_User_Preferences_newMessageNotification"]'); }
get accountsNewMessageNotificationReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_newMessageNotification"]'); }
get accountsMuteFocusedConversationsTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_muteFocusedConversations"]'); }
get accountsMuteFocusedConversationsFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_muteFocusedConversations"]'); }
get accountsMuteFocusedConversationsReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_muteFocusedConversations"]'); }
get accountsNotificationsSoundVolume() { return browser.element('[name="Accounts_Default_User_Preferences_notificationsSoundVolume"]'); }
get accountsNotificationsSoundVolumeReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_notificationsSoundVolume"]'); }

Loading…
Cancel
Save