瀏覽代碼

Upgrade to Meteor 2.3.4

Thanks to xet7 !
Lauri Ojansivu 3 年之前
父節點
當前提交
40265144af
共有 100 個文件被更改,包括 147 次插入10304 次删除
  1. 14 31
      .meteor/packages
  2. 1 1
      .meteor/release
  3. 38 82
      .meteor/versions
  4. 2 1
      client/components/cards/cardDetails.js
  5. 3 0
      client/components/users/userAvatar.js
  6. 0 7
      client/config/presence.js
  7. 3 0
      config/accounts.js
  8. 10 10
      config/router.js
  9. 6 1
      models/attachments.js
  10. 3 0
      models/avatars.js
  11. 0 12
      models/presences.js
  12. 61 5
      package-lock.json
  13. 3 0
      package.json
  14. 3 3
      packages/markdown/package.js
  15. 0 2
      packages/meteor-accounts-cas/.gitignore
  16. 0 21
      packages/meteor-accounts-cas/LICENSE
  17. 0 88
      packages/meteor-accounts-cas/README.md
  18. 0 117
      packages/meteor-accounts-cas/cas_client.js
  19. 0 71
      packages/meteor-accounts-cas/cas_client_cordova.js
  20. 0 304
      packages/meteor-accounts-cas/cas_server.js
  21. 0 29
      packages/meteor-accounts-cas/package.js
  22. 0 18
      packages/meteor-useraccounts-core/.editorconfig
  23. 0 2
      packages/meteor-useraccounts-core/.gitignore
  24. 0 2
      packages/meteor-useraccounts-core/.jshintignore
  25. 0 132
      packages/meteor-useraccounts-core/.jshintrc
  26. 0 8
      packages/meteor-useraccounts-core/.travis.yml
  27. 0 1433
      packages/meteor-useraccounts-core/Guide.md
  28. 0 353
      packages/meteor-useraccounts-core/History.md
  29. 0 20
      packages/meteor-useraccounts-core/LICENSE.md
  30. 0 104
      packages/meteor-useraccounts-core/README.md
  31. 0 464
      packages/meteor-useraccounts-core/lib/client.js
  32. 0 593
      packages/meteor-useraccounts-core/lib/core.js
  33. 0 292
      packages/meteor-useraccounts-core/lib/field.js
  34. 0 25
      packages/meteor-useraccounts-core/lib/methods.js
  35. 0 184
      packages/meteor-useraccounts-core/lib/server.js
  36. 0 142
      packages/meteor-useraccounts-core/lib/server_methods.js
  37. 0 26
      packages/meteor-useraccounts-core/lib/templates_helpers/at_error.js
  38. 0 83
      packages/meteor-useraccounts-core/lib/templates_helpers/at_form.js
  39. 0 124
      packages/meteor-useraccounts-core/lib/templates_helpers/at_input.js
  40. 0 7
      packages/meteor-useraccounts-core/lib/templates_helpers/at_message.js
  41. 0 16
      packages/meteor-useraccounts-core/lib/templates_helpers/at_nav_button.js
  42. 0 5
      packages/meteor-useraccounts-core/lib/templates_helpers/at_oauth.js
  43. 0 331
      packages/meteor-useraccounts-core/lib/templates_helpers/at_pwd_form.js
  44. 0 18
      packages/meteor-useraccounts-core/lib/templates_helpers/at_pwd_form_btn.js
  45. 0 24
      packages/meteor-useraccounts-core/lib/templates_helpers/at_pwd_link.js
  46. 0 19
      packages/meteor-useraccounts-core/lib/templates_helpers/at_reCaptcha.js
  47. 0 24
      packages/meteor-useraccounts-core/lib/templates_helpers/at_resend_verification_email_link.js
  48. 0 7
      packages/meteor-useraccounts-core/lib/templates_helpers/at_result.js
  49. 0 5
      packages/meteor-useraccounts-core/lib/templates_helpers/at_sep.js
  50. 0 24
      packages/meteor-useraccounts-core/lib/templates_helpers/at_signin_link.js
  51. 0 24
      packages/meteor-useraccounts-core/lib/templates_helpers/at_signup_link.js
  52. 0 105
      packages/meteor-useraccounts-core/lib/templates_helpers/at_social.js
  53. 0 33
      packages/meteor-useraccounts-core/lib/templates_helpers/at_terms_link.js
  54. 0 7
      packages/meteor-useraccounts-core/lib/templates_helpers/at_title.js
  55. 0 12
      packages/meteor-useraccounts-core/lib/templates_helpers/ensure_signed_in.html
  56. 0 15
      packages/meteor-useraccounts-core/lib/templates_helpers/ensure_signed_in.js
  57. 0 19
      packages/meteor-useraccounts-core/lib/utils.js
  58. 0 94
      packages/meteor-useraccounts-core/package.js
  59. 0 215
      packages/meteor-useraccounts-core/tests/tests.js
  60. 0 13
      packages/meteorx/package.js
  61. 0 88
      packages/wekan-accounts-cas/README.md
  62. 0 112
      packages/wekan-accounts-cas/cas_client.js
  63. 0 71
      packages/wekan-accounts-cas/cas_client_cordova.js
  64. 0 281
      packages/wekan-accounts-cas/cas_server.js
  65. 0 29
      packages/wekan-accounts-cas/package.js
  66. 0 1
      packages/wekan-accounts-oidc/.gitignore
  67. 0 14
      packages/wekan-accounts-oidc/LICENSE.txt
  68. 0 75
      packages/wekan-accounts-oidc/README.md
  69. 0 22
      packages/wekan-accounts-oidc/oidc.js
  70. 0 3
      packages/wekan-accounts-oidc/oidc_login_button.css
  71. 0 19
      packages/wekan-accounts-oidc/package.js
  72. 0 5
      packages/wekan-cfs-access-point/.travis.yml
  73. 0 288
      packages/wekan-cfs-access-point/CHANGELOG.md
  74. 0 20
      packages/wekan-cfs-access-point/LICENSE.md
  75. 0 32
      packages/wekan-cfs-access-point/README.md
  76. 0 58
      packages/wekan-cfs-access-point/access-point-client.js
  77. 0 199
      packages/wekan-cfs-access-point/access-point-common.js
  78. 0 307
      packages/wekan-cfs-access-point/access-point-handlers.js
  79. 0 362
      packages/wekan-cfs-access-point/access-point-server.js
  80. 0 271
      packages/wekan-cfs-access-point/api.md
  81. 0 332
      packages/wekan-cfs-access-point/internal.api.md
  82. 0 65
      packages/wekan-cfs-access-point/package.js
  83. 0 125
      packages/wekan-cfs-access-point/tests/client-tests.js
  84. 0 68
      packages/wekan-cfs-access-point/tests/server-tests.js
  85. 0 5
      packages/wekan-cfs-base-package/.travis.yml
  86. 0 20
      packages/wekan-cfs-base-package/LICENSE.md
  87. 0 11
      packages/wekan-cfs-base-package/README.md
  88. 0 213
      packages/wekan-cfs-base-package/api.md
  89. 0 51
      packages/wekan-cfs-base-package/base-client.js
  90. 0 317
      packages/wekan-cfs-base-package/base-common.js
  91. 0 95
      packages/wekan-cfs-base-package/base-server.js
  92. 0 293
      packages/wekan-cfs-base-package/internal.api.md
  93. 0 37
      packages/wekan-cfs-base-package/package.js
  94. 0 179
      packages/wekan-cfs-base-package/polyfill.base64.js
  95. 0 161
      packages/wekan-cfs-base-package/tests/common-tests.js
  96. 0 5
      packages/wekan-cfs-collection-filters/.travis.yml
  97. 0 20
      packages/wekan-cfs-collection-filters/LICENSE.md
  98. 0 8
      packages/wekan-cfs-collection-filters/README.md
  99. 0 44
      packages/wekan-cfs-collection-filters/api.md
  100. 0 191
      packages/wekan-cfs-collection-filters/filters.js

+ 14 - 31
.meteor/packages

@@ -3,12 +3,12 @@
 # 'meteor add' and 'meteor remove' will edit this file for you,
 # but you can also edit it by hand.
 
-meteor-base@1.4.0
+meteor-base@1.5.1
 
 # Build system
-ecmascript@0.15.1
-standard-minifier-css@1.7.2
-standard-minifier-js@2.6.0
+ecmascript@0.15.2
+standard-minifier-css@1.7.3
+standard-minifier-js@2.6.1
 mquandalle:jade
 coffeescript@2.4.1!
 
@@ -17,23 +17,14 @@ es5-shim@4.8.0
 
 # Collections
 aldeed:collection2
-wekan-cfs-standard-packages
 cottz:publish-relations
 dburles:collection-helpers
 idmontie:migrations
-matb33:collection-hooks
 matteodem:easy-search
-mongo@1.11.0
+mongo@1.12.0
 mquandalle:collection-mutations
 
 # Account system
-kenton:accounts-sandstorm
-service-configuration@1.0.11
-useraccounts:unstyled
-useraccounts:flow-routing
-wekan-ldap
-wekan-accounts-cas
-wekan-accounts-oidc
 
 # Utilities
 check@1.3.1
@@ -43,7 +34,6 @@ reactive-dict@1.3.0
 session@1.2.0
 tracker@1.2.0
 underscore@1.0.10
-3stack:presence
 arillo:flow-router-helpers
 audit-argument-checks@1.0.7
 kadira:blaze-layout
@@ -51,8 +41,7 @@ kadira:dochead
 mquandalle:autofocus
 ongoworks:speakingurl
 raix:handlebar-helpers
-tap:i18n
-http@1.4.2
+http@2.0.0
 
 # UI components
 blaze
@@ -64,17 +53,11 @@ mquandalle:mousetrap-bindglobal
 peerlibrary:blaze-components@=0.15.1
 templates:tabs
 meteor-autosize
-simple:json-routes
 rajit:bootstrap3-datepicker
 shell-server@0.5.0
-simple:rest-accounts-password
-useraccounts:core
-email@2.0.0
+email@2.1.1
 horka:swipebox
-dynamic-import@0.6.0
-
-accounts-password@1.7.0
-wekan-cfs-gridfs
+dynamic-import@0.7.1
 rzymek:fullcalendar
 momentjs:moment@2.22.2
 browser-policy-framing@1.1.0
@@ -84,13 +67,10 @@ msavin:usercache
 coagmano:stylus@1.1.0!
 meteorhacks:subs-manager
 meteorhacks:picker
-lamhieu:unblock
 meteorhacks:aggregate@1.3.0
 wekan-markdown
 konecty:mongo-counter
 percolate:synced-cron
-wekan-cfs-filesystem
-steffo:meteor-accounts-saml
 rajit:bootstrap3-datepicker-fi
 rajit:bootstrap3-datepicker-ar
 rajit:bootstrap3-datepicker-bg
@@ -139,10 +119,13 @@ rajit:bootstrap3-datepicker-uk
 rajit:bootstrap3-datepicker-vi
 rajit:bootstrap3-datepicker-zh-cn
 rajit:bootstrap3-datepicker-zh-tw
-staringatlights:fast-render
-spacebars
 easylogic:summernote
 pascoual:pdfkit
-wekan-accounts-lockout
 lmieulet:meteor-coverage
 meteortesting:mocha
+aldeed:simple-schema
+accounts-password@2.0.0
+matb33:collection-hooks
+simple:json-routes
+kadira:flow-router
+spacebars

+ 1 - 1
.meteor/release

@@ -1 +1 @@
-METEOR@2.2
+METEOR@2.3.4

+ 38 - 82
.meteor/versions

@@ -1,7 +1,5 @@
-3stack:presence@1.1.2
-accounts-base@1.9.0
-accounts-oauth@1.2.0
-accounts-password@1.7.1
+accounts-base@2.0.1
+accounts-password@2.0.0
 aldeed:collection2@2.10.0
 aldeed:collection2-core@1.2.0
 aldeed:schema-deny@1.1.0
@@ -11,7 +9,7 @@ allow-deny@1.1.0
 arillo:flow-router-helpers@0.5.2
 audit-argument-checks@1.0.7
 autoupdate@1.7.0
-babel-compiler@7.6.1
+babel-compiler@7.6.2
 babel-runtime@1.5.0
 base64@1.0.12
 binary-heap@1.0.11
@@ -21,31 +19,30 @@ boilerplate-generator@1.7.1
 browser-policy-common@1.0.11
 browser-policy-framing@1.1.0
 caching-compiler@1.2.2
-caching-html-compiler@1.2.0
-callback-hook@1.3.0
+caching-html-compiler@1.2.1
+callback-hook@1.3.1
 cfs:http-methods@0.0.32
 check@1.3.1
-chuangbo:cookie@1.1.0
 coagmano:stylus@1.1.0
 coffeescript@2.4.1
 coffeescript-compiler@2.4.1
 cottz:publish-relations@2.0.8
 dburles:collection-helpers@1.1.0
 ddp@1.4.0
-ddp-client@2.4.1
+ddp-client@2.5.0
 ddp-common@1.4.0
-ddp-rate-limiter@1.0.9
-ddp-server@2.3.3
+ddp-rate-limiter@1.1.0
+ddp-server@2.4.0
 deps@1.0.12
 diff-sequence@1.1.1
-dynamic-import@0.6.0
+dynamic-import@0.7.1
 easylogic:summernote@0.8.8
-ecmascript@0.15.1
+ecmascript@0.15.2
 ecmascript-runtime@0.7.0
 ecmascript-runtime-client@0.11.1
 ecmascript-runtime-server@0.10.1
 ejson@1.1.1
-email@2.0.0
+email@2.1.1
 es5-shim@4.8.0
 fastclick@1.0.13
 fetch@0.1.1
@@ -55,7 +52,7 @@ horka:swipebox@1.0.2
 hot-code-push@1.0.4
 html-tools@1.1.2
 htmljs@1.1.1
-http@1.4.4
+http@2.0.0
 id-map@1.1.1
 idmontie:migrations@1.0.3
 inter-process-messaging@0.1.1
@@ -63,40 +60,36 @@ jquery@1.11.11
 kadira:blaze-layout@2.3.0
 kadira:dochead@1.5.0
 kadira:flow-router@2.12.1
-kenton:accounts-sandstorm@0.7.0
 konecty:mongo-counter@0.0.5_3
-lamhieu:meteorx@2.1.1
-lamhieu:unblock@1.0.0
-launch-screen@1.2.1
+launch-screen@1.3.0
 livedata@1.0.18
-lmieulet:meteor-coverage@3.2.0
+lmieulet:meteor-coverage@1.1.4
 localstorage@1.2.0
 logging@1.2.0
-matb33:collection-hooks@0.9.1
+matb33:collection-hooks@1.1.0
 matteodem:easy-search@1.6.4
 mdg:validation-error@0.5.1
 meteor@1.9.3
 meteor-autosize@5.0.1
-meteor-base@1.4.0
+meteor-base@1.5.1
 meteor-platform@1.2.6
 meteorhacks:aggregate@1.3.0
 meteorhacks:collection-utils@1.2.0
 meteorhacks:picker@1.0.3
 meteorhacks:subs-manager@1.6.4
 meteorspark:util@0.2.0
-meteortesting:browser-tests@1.3.4
-meteortesting:mocha@2.0.1
-meteortesting:mocha-core@8.0.1
+meteortesting:browser-tests@0.2.0
+meteortesting:mocha@0.6.0
 minifier-css@1.5.4
-minifier-js@2.6.0
+minifier-js@2.6.1
 minifiers@1.1.8-faster-rebuild.0
-minimongo@1.6.2
+minimongo@1.7.0
 mobile-status-bar@1.1.0
 modern-browsers@0.1.5
 modules@0.16.0
 modules-runtime@0.12.0
 momentjs:moment@2.29.1
-mongo@1.11.1
+mongo@1.12.0
 mongo-decimal@0.1.2
 mongo-dev-server@1.1.0
 mongo-id@1.0.8
@@ -107,24 +100,24 @@ mquandalle:collection-mutations@0.1.0
 mquandalle:jade@0.4.9
 mquandalle:jade-compiler@0.4.5
 mquandalle:jquery-textcomplete@0.8.0_1
+mquandalle:jquery-ui-drag-drop-sort@0.2.0
 mquandalle:moment@1.0.1
 mquandalle:mousetrap-bindglobal@0.0.1
+mrt:just-i18n@0.3.0
 msavin:usercache@1.8.0
-npm-bcrypt@0.9.4
-npm-mongo@3.9.0
-oauth@1.3.2
-oauth2@1.3.0
-observe-sequence@1.0.16
+npm-mongo@3.9.1
+observe-sequence@1.0.19
 ongoworks:speakingurl@1.1.0
 ordered-dict@1.1.0
 pascoual:pdfkit@1.0.7
 peerlibrary:assert@0.3.0
-peerlibrary:base-component@0.16.0
+peerlibrary:base-component@0.17.1
 peerlibrary:blaze-components@0.15.1
 peerlibrary:computed-field@0.10.0
 peerlibrary:reactive-field@0.6.0
 percolate:synced-cron@1.3.2
-promise@0.11.2
+practicalmeteor:mocha-core@1.0.1
+promise@0.12.0
 raix:eventemitter@0.1.3
 raix:handlebar-helpers@0.2.5
 rajit:bootstrap3-datepicker@1.7.1_1
@@ -183,67 +176,30 @@ reactive-dict@1.3.0
 reactive-var@1.0.11
 reload@1.3.1
 retry@1.1.0
-routepolicy@1.1.0
+routepolicy@1.1.1
 rzymek:fullcalendar@3.8.0
-server-render@0.3.1
-service-configuration@1.0.11
+service-configuration@1.1.0
 session@1.2.0
 sha@1.0.9
 shell-server@0.5.0
-simple:authenticate-user-by-token@1.0.1
 simple:json-routes@2.1.0
-simple:rest-accounts-password@1.1.2
-simple:rest-bearer-token-parser@1.0.1
-simple:rest-json-error-handler@1.0.1
-socket-stream-client@0.3.3
-softwarerero:accounts-t9n@1.3.11
+socket-stream-client@0.4.0
 spacebars@1.2.0
-spacebars-compiler@1.2.1
-srp@1.1.0
-standard-minifier-css@1.7.2
-standard-minifier-js@2.6.0
-staringatlights:fast-render@3.3.0
-staringatlights:inject-data@2.3.0
-steffo:meteor-accounts-saml@0.0.18
+spacebars-compiler@1.3.0
+standard-minifier-css@1.7.3
+standard-minifier-js@2.6.1
 tap:i18n@1.8.2
 templates:tabs@2.3.0
-templating@1.4.0
+templating@1.4.1
 templating-compiler@1.4.1
-templating-runtime@1.4.0
-templating-tools@1.2.0
+templating-runtime@1.5.0
+templating-tools@1.2.1
 tracker@1.2.0
 twbs:bootstrap@3.3.6
 ui@1.0.13
 underscore@1.0.10
 url@1.3.2
-useraccounts:core@1.14.2
-useraccounts:flow-routing@1.14.2
-useraccounts:unstyled@1.14.2
-webapp@1.10.1
+webapp@1.11.1
 webapp-hashing@1.1.0
-wekan-accounts-cas@0.1.0
-wekan-accounts-lockout@1.0.0
-wekan-accounts-oidc@1.0.10
-wekan-cfs-access-point@0.1.50
-wekan-cfs-base-package@0.0.30
-wekan-cfs-collection@0.5.5
-wekan-cfs-collection-filters@0.2.4
-wekan-cfs-data-man@0.0.6
-wekan-cfs-file@0.1.17
-wekan-cfs-filesystem@0.1.2
-wekan-cfs-gridfs@0.0.34
-wekan-cfs-http-methods@0.0.32
-wekan-cfs-http-publish@0.0.13
-wekan-cfs-power-queue@0.9.11
-wekan-cfs-reactive-list@0.0.9
-wekan-cfs-reactive-property@0.0.4
-wekan-cfs-standard-packages@0.5.10
-wekan-cfs-storage-adapter@0.2.4
-wekan-cfs-tempstore@0.1.6
-wekan-cfs-upload-http@0.0.21
-wekan-cfs-worker@0.1.5
-wekan-ldap@0.0.2
 wekan-markdown@1.0.9
-wekan-oidc@1.0.12
-yasaricli:slugify@0.0.7
 zimme:active-route@2.3.2

+ 2 - 1
client/components/cards/cardDetails.js

@@ -1795,6 +1795,7 @@ Template.cardAssigneePopup.helpers({
     return user && user.isBoardAdmin() ? 'admin' : 'normal';
   },
 
+/*
   presenceStatusClassName() {
     const user = Users.findOne(this.userId);
     const userPresence = presences.findOne({ userId: this.userId });
@@ -1804,7 +1805,7 @@ Template.cardAssigneePopup.helpers({
       return 'active';
     else return 'idle';
   },
-
+*/
   isCardAssignee() {
     const card = Template.parentData();
     const cardAssignees = card.getAssignees();

+ 3 - 0
client/components/users/userAvatar.js

@@ -25,6 +25,7 @@ Template.userAvatar.helpers({
     return user && user.isBoardAdmin() ? 'admin' : 'normal';
   },
 
+/*
   presenceStatusClassName() {
     const user = Users.findOne(this.userId);
     const userPresence = presences.findOne({ userId: this.userId });
@@ -34,6 +35,8 @@ Template.userAvatar.helpers({
       return 'active';
     else return 'idle';
   },
+*/
+
 });
 
 Template.userAvatarInitials.helpers({

+ 0 - 7
client/config/presence.js

@@ -1,7 +0,0 @@
-Presence.configure({
-  state() {
-    return {
-      currentBoardId: Session.get('currentBoard'),
-    };
-  },
-});

+ 3 - 0
config/accounts.js

@@ -1,3 +1,4 @@
+/*
 const passwordField = AccountsTemplates.removeField('password');
 const emailField = AccountsTemplates.removeField('email');
 
@@ -88,3 +89,5 @@ if (Meteor.isServer) {
     };
   });
 }
+
+*/

+ 10 - 10
config/router.js

@@ -7,7 +7,7 @@ FlowRouter.triggers.exit([
 
 FlowRouter.route('/', {
   name: 'home',
-  triggersEnter: [AccountsTemplates.ensureSignedIn],
+  //triggersEnter: [qAccountsTemplates.ensureSignedIn],
   action() {
     Session.set('currentBoard', null);
     Session.set('currentList', null);
@@ -31,7 +31,7 @@ FlowRouter.route('/', {
 
 FlowRouter.route('/public', {
   name: 'public',
-  triggersEnter: [AccountsTemplates.ensureSignedIn],
+  //triggersEnter: [AccountsTemplates.ensureSignedIn],
   action() {
     Session.set('currentBoard', null);
     Session.set('currentList', null);
@@ -150,7 +150,7 @@ FlowRouter.route('/b/templates', {
 
 FlowRouter.route('/my-cards', {
   name: 'my-cards',
-  triggersEnter: [AccountsTemplates.ensureSignedIn],
+  //triggersEnter: [AccountsTemplates.ensureSignedIn],
   action() {
     Filter.reset();
     Session.set('sortBy', '');
@@ -170,7 +170,7 @@ FlowRouter.route('/my-cards', {
 
 FlowRouter.route('/due-cards', {
   name: 'due-cards',
-  triggersEnter: [AccountsTemplates.ensureSignedIn],
+  //triggersEnter: [AccountsTemplates.ensureSignedIn],
   action() {
     Filter.reset();
     Session.set('sortBy', '');
@@ -190,7 +190,7 @@ FlowRouter.route('/due-cards', {
 
 FlowRouter.route('/global-search', {
   name: 'global-search',
-  triggersEnter: [AccountsTemplates.ensureSignedIn],
+  //triggersEnter: [AccountsTemplates.ensureSignedIn],
   action() {
     Filter.reset();
     Session.set('sortBy', '');
@@ -236,7 +236,7 @@ FlowRouter.route('/broken-cards', {
 
 FlowRouter.route('/import/:source', {
   name: 'import',
-  triggersEnter: [AccountsTemplates.ensureSignedIn],
+  //triggersEnter: [AccountsTemplates.ensureSignedIn],
   action(params) {
     if (Session.get('currentBoard')) {
       Session.set('fromBoard', Session.get('currentBoard'));
@@ -261,7 +261,7 @@ FlowRouter.route('/import/:source', {
 FlowRouter.route('/setting', {
   name: 'setting',
   triggersEnter: [
-    AccountsTemplates.ensureSignedIn,
+    //AccountsTemplates.ensureSignedIn,
     () => {
       Session.set('currentBoard', null);
       Session.set('currentList', null);
@@ -286,7 +286,7 @@ FlowRouter.route('/setting', {
 FlowRouter.route('/information', {
   name: 'information',
   triggersEnter: [
-    AccountsTemplates.ensureSignedIn,
+    //AccountsTemplates.ensureSignedIn,
     () => {
       Session.set('currentBoard', null);
       Session.set('currentList', null);
@@ -310,7 +310,7 @@ FlowRouter.route('/information', {
 FlowRouter.route('/people', {
   name: 'people',
   triggersEnter: [
-    AccountsTemplates.ensureSignedIn,
+    //AccountsTemplates.ensureSignedIn,
     () => {
       Session.set('currentBoard', null);
       Session.set('currentList', null);
@@ -334,7 +334,7 @@ FlowRouter.route('/people', {
 FlowRouter.route('/admin-reports', {
   name: 'admin-reports',
   triggersEnter: [
-    AccountsTemplates.ensureSignedIn,
+    //AccountsTemplates.ensureSignedIn,
     () => {
       Session.set('currentBoard', null);
       Session.set('currentList', null);

+ 6 - 1
models/attachments.js

@@ -1,3 +1,5 @@
+/*
+
 export const AttachmentStorage = new Mongo.Collection(
   'cfs_gridfs.attachments.files',
 );
@@ -24,7 +26,7 @@ if (localFSStore) {
   const Grid = Npm.require('gridfs-stream');
   // calulate the absolute path here, because FS.Store.FileSystem didn't expose the aboslutepath or FS.Store didn't expose api calls :(
   let pathname = localFSStore;
-  /*eslint camelcase: ["error", {allow: ["__meteor_bootstrap__"]}] */
+  // eslint camelcase: ["error", {allow: ["__meteor_bootstrap__"]}]
 
   if (!pathname && __meteor_bootstrap__ && __meteor_bootstrap__.serverDir) {
     pathname = path.join(
@@ -180,6 +182,8 @@ Attachments = new FS.Collection('attachments', {
   stores: [store],
 });
 
+
+
 if (Meteor.isServer) {
   Meteor.startup(() => {
     Attachments.files._ensureIndex({ cardId: 1 });
@@ -266,3 +270,4 @@ if (Meteor.isServer) {
 }
 
 export default Attachments;
+*/

+ 3 - 0
models/avatars.js

@@ -1,3 +1,5 @@
+/*
+
 Avatars = new FS.Collection('avatars', {
   stores: [new FS.Store.GridFS('avatars')],
   filter: {
@@ -27,3 +29,4 @@ Avatars.files.before.insert((userId, doc) => {
 });
 
 export default Avatars;
+*/

+ 0 - 12
models/presences.js

@@ -1,12 +0,0 @@
-if (Meteor.isServer) {
-  Meteor.startup(() => {
-    // Date of 7 days ago
-    let lastWeek = new Date();
-    lastWeek.setDate(lastWeek.getDate() - 7);
-
-    presences.remove({ ttl: { $lte: lastWeek } });
-
-    // Create index for serverId that is queried often
-    presences._collection._ensureIndex({ serverId: -1 });
-  });
-}

+ 61 - 5
package-lock.json

@@ -709,6 +709,13 @@
         "ansi-styles": "^3.2.1",
         "escape-string-regexp": "^1.0.5",
         "supports-color": "^5.3.0"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "1.0.5",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+          "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+        }
       }
     },
     "check-error": {
@@ -717,6 +724,11 @@
       "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
       "dev": true
     },
+    "clone": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+      "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
+    },
     "color-convert": {
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -1538,9 +1550,9 @@
       "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
     },
     "escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="
     },
     "esprima": {
       "version": "4.0.1",
@@ -2048,6 +2060,11 @@
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
       "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
     },
+    "lodash._reinterpolate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
+      "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
+    },
     "lodash.defaults": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
@@ -2109,6 +2126,23 @@
       "resolved": "https://registry.npmjs.org/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz",
       "integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g="
     },
+    "lodash.template": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
+      "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==",
+      "requires": {
+        "lodash._reinterpolate": "^3.0.0",
+        "lodash.templatesettings": "^4.0.0"
+      }
+    },
+    "lodash.templatesettings": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz",
+      "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==",
+      "requires": {
+        "lodash._reinterpolate": "^3.0.0"
+      }
+    },
     "lodash.union": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
@@ -2170,6 +2204,14 @@
         "stylis": "^4.0.10"
       }
     },
+    "message-box": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmjs.org/message-box/-/message-box-0.2.7.tgz",
+      "integrity": "sha512-C4ccA5nHb58kTS+pLrgF/JWtr7fAIkHxRDceH7tdy5fMA783nUfbYwZ7H2XLvSeYfcnWIYCig5dWW+icK9X/Ag==",
+      "requires": {
+        "lodash.template": "^4.5.0"
+      }
+    },
     "meteor-node-stubs": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-1.1.0.tgz",
@@ -2977,14 +3019,18 @@
     "moment": {
       "version": "2.29.1",
       "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
-      "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
-      "optional": true
+      "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
     },
     "moment-mini": {
       "version": "2.24.0",
       "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz",
       "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ=="
     },
+    "mongo-object": {
+      "version": "0.1.4",
+      "resolved": "https://registry.npmjs.org/mongo-object/-/mongo-object-0.1.4.tgz",
+      "integrity": "sha512-QtYk0gupWEn2+iB+DDRt1L+WbcNYvJRaHdih/dcqthOa1DbnREUGSs2WGcW478GNYpElflo/yybZXu0sTiRXHg=="
+    },
     "mongodb": {
       "version": "3.7.3",
       "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
@@ -3362,6 +3408,16 @@
         "object-inspect": "^1.9.0"
       }
     },
+    "simpl-schema": {
+      "version": "1.12.0",
+      "resolved": "https://registry.npmjs.org/simpl-schema/-/simpl-schema-1.12.0.tgz",
+      "integrity": "sha512-lzXC3L8jJbPhNXGR3cjlyIauqqrC5WUJS4O34Ym/wLIvb8K3ZieK+1OfTzs4mBpDc3Y8u53gQFAr1X37DmTcEg==",
+      "requires": {
+        "clone": "^2.1.2",
+        "message-box": "^0.2.7",
+        "mongo-object": "^0.1.4"
+      }
+    },
     "sinon": {
       "version": "11.1.2",
       "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz",

+ 3 - 0
package.json

@@ -31,6 +31,7 @@
     "core-js": "^2.6.12",
     "dompurify": "^2.3.0",
     "es6-promise": "^4.2.4",
+    "escape-string-regexp": "^5.0.0",
     "exceljs": "^4.2.1",
     "fibers": "^5.0.0",
     "gridfs-stream": "https://github.com/wekan/gridfs-stream/tarball/master",
@@ -42,11 +43,13 @@
     "markdown-it": "^12.3.2",
     "markdown-it-emoji": "^2.0.0",
     "meteor-node-stubs": "^1.1.0",
+    "moment": "^2.29.1",
     "mongodb": "^3.7.3",
     "os": "^0.1.2",
     "page": "^1.11.5",
     "papaparse": "^5.3.1",
     "qs": "^6.10.1",
+    "simpl-schema": "^1.12.0",
     "source-map-support": "^0.5.19"
   },
   "meteor": {

+ 3 - 3
packages/markdown/package.js

@@ -12,11 +12,11 @@ Package.onUse(function (api) {
 	if(api.versionsFrom) api.versionsFrom('1.8.2');
 
 	api.use('templating');
-  api.use("ecmascript", ['server', 'client']);
+	api.use("ecmascript", ['server', 'client']);
 
 	api.export('Markdown', ['server', 'client']);
 
-  api.use('ui', 'client', {weak: true});
+	api.use('ui', 'client', {weak: true});
 
-	api.add_files('src/template-integration.js', 'client');
+	api.addFiles('src/template-integration.js', 'client');
 });

+ 0 - 2
packages/meteor-accounts-cas/.gitignore

@@ -1,2 +0,0 @@
-.build*
-node_modules/

+ 0 - 21
packages/meteor-accounts-cas/LICENSE

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014-2019 The Wekan Team
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 0 - 88
packages/meteor-accounts-cas/README.md

@@ -1,88 +0,0 @@
-This is a merged repository of useful forks of: atoy40:accounts-cas
-===================
-([(https://atmospherejs.com/atoy40/accounts-cas](https://atmospherejs.com/atoy40/accounts-cas))
-
-## Essential improvements by ppoulard to atoy40 and xaionaro versions
-
-* Added support of CAS attributes
-
-With this plugin, you can pick CAS attributes : https://github.com/joshchan/node-cas/wiki/CAS-Attributes
-
-Moved to Wekan GitHub org from from https://github.com/ppoulard/meteor-accounts-cas
-
-## Install
-
-```
-cd ~site
-mkdir packages
-cd packages
-git clone https://github.com/wekan/meteor-accounts-cas
-cd ~site
-meteor add wekan:accounts-cas
-```
-
-## Usage
-
-Put CAS settings in Meteor.settings (for example using METEOR_SETTINGS env or --settings) like so:
-
-If casVersion is not defined, it will assume you use CAS 1.0. (note by xaionaro: option `casVersion` seems to be just ignored in the code, ATM).
-
-Server side settings:
-
-```
-Meteor.settings = {
-    "cas": {
-        "baseUrl": "https://cas.example.com/cas",
-        "autoClose": true,
-        "validateUrl":"https://cas.example.com/cas/p3/serviceValidate",
-        "casVersion": 3.0,
-        "attributes": {
-            "debug" : true
-        }
-    },
-}
-```
-
-CAS `attributes` settings :
-
-* `attributes`: by default `{}` : all default values below will apply
-* *  `debug` : by default `false` ; `true` will print to the server console the CAS attribute names to map, the CAS attributes values retrieved, if necessary the new user account created, and finally the user to use
-* *  `id` : by default, the CAS user is used for the user account, but you can specified another CAS attribute
-* *  `firstname` : by default `cas:givenName` ; but you can use your own CAS attribute
-* *  `lastname` : by default `cas:sn` (respectively) ; but you can use your own CAS attribute
-* *  `fullname` : by default unused, but if you specify your own CAS attribute, it will be used instead of the `firstname` + `lastname`
-* *  `mail` : by default `cas:mail`
-
-Client side settings:
-
-```
-Meteor.settings = {
-	"public": {
-		"cas": {
-			"loginUrl": "https://cas.example.com/login",
-			"serviceParam": "service",
-			"popupWidth": 810,
-			"popupHeight": 610,
-			"popup": true,
-		}
-	}
-}
-```
-
-`proxyUrl` is not required. Setup [ROOT_URL](http://docs.meteor.com/api/core.html#Meteor-absoluteUrl) environment variable instead.
-
-Then, to start authentication, you have to call the following method from the client (for example in a click handler) :
-
-```
-Meteor.loginWithCas([callback]);
-```
-
-It must open a popup containing you CAS login form or redirect to the CAS login form (depending on "popup" setting).
-
-If popup is disabled (== false), then it's required to execute `Meteor.initCas([callback])` in `Meteor.startup` of the client side. ATM, `Meteor.initCas()` completes authentication.
-
-## Examples
-
-* [https://devel.mephi.ru/dyokunev/start-mephi-ru](https://devel.mephi.ru/dyokunev/start-mephi-ru)
-
-

+ 0 - 117
packages/meteor-accounts-cas/cas_client.js

@@ -1,117 +0,0 @@
-
-function addParameterToURL(url, param){
-  var urlSplit = url.split('?');
-  return url+(urlSplit.length>0 ? '?':'&') + param;
-}
-
-Meteor.initCas = function(callback) {
-    const casTokenMatch = window.location.href.match(/[?&]casToken=([^&]+)/);
-    if (casTokenMatch == null) {
-        return;
-    }
-
-    window.history.pushState('', document.title, window.location.href.replace(/([&?])casToken=[^&]+[&]?/, '$1').replace(/[?&]+$/g, ''));
-
-    Accounts.callLoginMethod({
-        methodArguments: [{ cas: { credentialToken: casTokenMatch[1] } }],
-        userCallback: function(err){
-            if (err == null) {
-                // should we do anything on success?
-            }
-            if (callback != null) {
-                callback(err);
-            }
-        }
-    });
-}
-
-Meteor.loginWithCas = function(options, callback) {
-
-    var credentialToken = Random.id();
-
-    if (!Meteor.settings.public &&
-        !Meteor.settings.public.cas &&
-        !Meteor.settings.public.cas.loginUrl) {
-        return;
-    }
-
-    var settings = Meteor.settings.public.cas;
-
-    var backURL = window.location.href.replace('#', '');
-    if (options != null && options.redirectUrl != null)
-        backURL = options.redirectUrl;
-
-    var serviceURL = addParameterToURL(backURL, 'casToken='+credentialToken);
-
-    var loginUrl = settings.loginUrl +
-        "?" + (settings.serviceParam || "service") + "=" +
-        encodeURIComponent(serviceURL)
-
-    if (settings.popup == false) {
-      window.location = loginUrl;
-      return;
-    }
-
-    var popup = openCenteredPopup(
-        loginUrl,
-        settings.width || 800,
-        settings.height || 600
-    );
-
-    var checkPopupOpen = setInterval(function() {
-        try {
-	    if(popup && popup.document && popup.document.getElementById('popupCanBeClosed')) {
-                popup.close();
-      	    }
-            // Fix for #328 - added a second test criteria (popup.closed === undefined)
-            // to humour this Android quirk:
-            // http://code.google.com/p/android/issues/detail?id=21061
-            var popupClosed = popup.closed || popup.closed === undefined;
-        } catch (e) {
-            // For some unknown reason, IE9 (and others?) sometimes (when
-            // the popup closes too quickly?) throws "SCRIPT16386: No such
-            // interface supported" when trying to read 'popup.closed'. Try
-            // again in 100ms.
-            return;
-        }
-
-        if (popupClosed) {
-            clearInterval(checkPopupOpen);
-
-            // check auth on server.
-            Accounts.callLoginMethod({
-                methodArguments: [{ cas: { credentialToken: credentialToken } }],
-                userCallback: err => {
-                    // Fix redirect bug after login successfully
-                    if (!err) {
-                        window.location.href = '/';
-                    }
-                }
-            });
-        }
-    }, 100);
-};
-
-var openCenteredPopup = function(url, width, height) {
-  var screenX = typeof window.screenX !== 'undefined'
-  ? window.screenX : window.screenLeft;
-  var screenY = typeof window.screenY !== 'undefined'
-  ? window.screenY : window.screenTop;
-  var outerWidth = typeof window.outerWidth !== 'undefined'
-  ? window.outerWidth : document.body.clientWidth;
-  var outerHeight = typeof window.outerHeight !== 'undefined'
-  ? window.outerHeight : (document.body.clientHeight - 22);
-  // XXX what is the 22?
-
-  // Use `outerWidth - width` and `outerHeight - height` for help in
-  // positioning the popup centered relative to the current window
-  var left = screenX + (outerWidth - width) / 2;
-  var top = screenY + (outerHeight - height) / 2;
-  var features = ('width=' + width + ',height=' + height +
-      ',left=' + left + ',top=' + top + ',scrollbars=yes');
-
-  var newwindow = window.open(url, '_blank', features);
-  if (newwindow.focus)
-    newwindow.focus();
-  return newwindow;
-};

+ 0 - 71
packages/meteor-accounts-cas/cas_client_cordova.js

@@ -1,71 +0,0 @@
-
-Meteor.loginWithCas = function(callback) {
-
-  var credentialToken = Random.id();
-
-  if (!Meteor.settings.public &&
-      !Meteor.settings.public.cas &&
-      !Meteor.settings.public.cas.loginUrl) {
-    return;
-  }
-
-  var settings = Meteor.settings.public.cas;
-
-  var loginUrl = settings.loginUrl +
-      "?" + (settings.service || "service") + "=" +
-      Meteor.absoluteUrl('_cas/') +
-      credentialToken;
-
-
-  var fail = function (err) {
-    Meteor._debug("Error from OAuth popup: " + JSON.stringify(err));
-  };
-
-  // When running on an android device, we sometimes see the
-  // `pageLoaded` callback fire twice for the final page in the OAuth
-  // popup, even though the page only loads once. This is maybe an
-  // Android bug or maybe something intentional about how onPageFinished
-  // works that we don't understand and isn't well-documented.
-  var oauthFinished = false;
-
-  var pageLoaded = function (event) {
-    if (oauthFinished) {
-      return;
-    }
-
-    if (event.url.indexOf(Meteor.absoluteUrl('_cas')) === 0) {
-
-      oauthFinished = true;
-
-      // On iOS, this seems to prevent "Warning: Attempt to dismiss from
-      // view controller <MainViewController: ...> while a presentation
-      // or dismiss is in progress". My guess is that the last
-      // navigation of the OAuth popup is still in progress while we try
-      // to close the popup. See
-      // https://issues.apache.org/jira/browse/CB-2285.
-      //
-      // XXX Can we make this timeout smaller?
-      setTimeout(function () {
-        popup.close();
-        // check auth on server.
-        Accounts.callLoginMethod({
-          methodArguments: [{ cas: { credentialToken: credentialToken } }],
-          userCallback: callback
-        });
-      }, 100);
-    }
-  };
-
-  var onExit = function () {
-    popup.removeEventListener('loadstop', pageLoaded);
-    popup.removeEventListener('loaderror', fail);
-    popup.removeEventListener('exit', onExit);
-  };
-
-  var popup = window.open(loginUrl, '_blank', 'location=no,hidden=no');
-  popup.addEventListener('loadstop', pageLoaded);
-  popup.addEventListener('loaderror', fail);
-  popup.addEventListener('exit', onExit);
-  popup.show();
-
-};

+ 0 - 304
packages/meteor-accounts-cas/cas_server.js

@@ -1,304 +0,0 @@
-"use strict";
-
-const Fiber = Npm.require('fibers');
-const https = Npm.require('https');
-const url = Npm.require('url');
-const xmlParser = Npm.require('xml2js');
-
-// Library
-class CAS {
-  constructor(options) {
-    options = options || {};
-
-    if (!options.validate_url) {
-      throw new Error('Required CAS option `validateUrl` missing.');
-    }
-
-    if (!options.service) {
-      throw new Error('Required CAS option `service` missing.');
-    }
-
-    const cas_url = url.parse(options.validate_url);
-    if (cas_url.protocol != 'https:' ) {
-      throw new Error('Only https CAS servers are supported.');
-    } else if (!cas_url.hostname) {
-      throw new Error('Option `validateUrl` must be a valid url like: https://example.com/cas/serviceValidate');
-    } else {
-      this.hostname = cas_url.host;
-      this.port = 443;// Should be 443 for https
-      this.validate_path = cas_url.pathname;
-    }
-
-    this.service = options.service;
-  }
-
-  validate(ticket, callback) {
-    const httparams = {
-      host: this.hostname,
-      port: this.port,
-      path: url.format({
-        pathname: this.validate_path,
-        query: {ticket: ticket, service: this.service},
-      }),
-    };
-
-    https.get(httparams, (res) => {
-      res.on('error', (e) => {
-        console.log('error' + e);
-        callback(e);
-      });
-
-      // Read result
-      res.setEncoding('utf8');
-      let response = '';
-      res.on('data', (chunk) => {
-        response += chunk;
-      });
-
-      res.on('end', (error) => {
-        if (error) {
-          console.log('error callback');
-          console.log(error);
-          callback(undefined, false);
-        } else {
-          xmlParser.parseString(response, (err, result) => {
-            if (err) {
-              console.log('Bad response format.');
-              callback({message: 'Bad response format. XML could not parse it'});
-            } else {
-              if (result['cas:serviceResponse'] == null) {
-                console.log('Empty response.');
-                callback({message: 'Empty response.'});
-              }
-              if (result['cas:serviceResponse']['cas:authenticationSuccess']) {
-                const userData = {
-                  id: result['cas:serviceResponse']['cas:authenticationSuccess'][0]['cas:user'][0].toLowerCase(),
-                };
-                const attributes = result['cas:serviceResponse']['cas:authenticationSuccess'][0]['cas:attributes'][0];
-
-                // Check allowed ldap groups if exist (array only)
-                // example cas settings : "allowedLdapGroups" : ["wekan", "admin"],
-                let findedGroup = false;
-                const allowedLdapGroups = Meteor.settings.cas.allowedLdapGroups || false;
-                for (const fieldName in attributes) {
-                  if (allowedLdapGroups && fieldName === 'cas:memberOf') {
-                    for (const groups in attributes[fieldName]) {
-                      const str = attributes[fieldName][groups];
-                      if (!Array.isArray(allowedLdapGroups)) {
-                        callback({message: 'Settings "allowedLdapGroups" must be an array'});
-                      }
-                      for (const allowedLdapGroup in allowedLdapGroups) {
-                        if (str.search(`cn=${allowedLdapGroups[allowedLdapGroup]}`) >= 0) {
-                          findedGroup = true;
-                        }
-                      }
-                    }
-                  }
-                  userData[fieldName] = attributes[fieldName][0];
-                }
-
-                if (allowedLdapGroups && !findedGroup) {
-                  callback({message: 'Group not finded.'}, false);
-                } else {
-                  callback(undefined, true, userData);
-                }
-              } else {
-                callback(undefined, false);
-              }
-            }
-          });
-        }
-      });
-    });
-  }
-}
-////// END OF CAS MODULE
-
-let _casCredentialTokens = {};
-let _userData = {};
-
-//RoutePolicy.declare('/_cas/', 'network');
-
-// Listen to incoming OAuth http requests
-WebApp.connectHandlers.use((req, res, next) => {
-  // Need to create a Fiber since we're using synchronous http calls and nothing
-  // else is wrapping this in a fiber automatically
-
-  Fiber(() => {
-    middleware(req, res, next);
-  }).run();
-});
-
-const middleware = (req, res, next) => {
-  // Make sure to catch any exceptions because otherwise we'd crash
-  // the runner
-  try {
-    urlParsed = url.parse(req.url, true);
-
-    // Getting the ticket (if it's defined in GET-params)
-    // If no ticket, then request will continue down the default
-    // middlewares.
-    const query = urlParsed.query;
-    if (query == null) {
-      next();
-      return;
-    }
-    const ticket = query.ticket;
-    if (ticket == null) {
-      next();
-      return;
-    }
-
-    const serviceUrl = Meteor.absoluteUrl(urlParsed.href.replace(/^\//g, '')).replace(/([&?])ticket=[^&]+[&]?/g, '$1').replace(/[?&]+$/g, '');
-    const redirectUrl = serviceUrl;//.replace(/([&?])casToken=[^&]+[&]?/g, '$1').replace(/[?&]+$/g, '');
-
-    // get auth token
-    const credentialToken = query.casToken;
-    if (!credentialToken) {
-      end(res, redirectUrl);
-      return;
-    }
-
-    // validate ticket
-    casValidate(req, ticket, credentialToken, serviceUrl, () => {
-      end(res, redirectUrl);
-    });
-
-  } catch (err) {
-    console.log("account-cas: unexpected error : " + err.message);
-    end(res, redirectUrl);
-  }
-};
-
-const casValidate = (req, ticket, token, service, callback) => {
-  // get configuration
-  if (!Meteor.settings.cas/* || !Meteor.settings.cas.validate*/) {
-    throw new Error('accounts-cas: unable to get configuration.');
-  }
-
-  const cas = new CAS({
-    validate_url: Meteor.settings.cas.validateUrl,
-    service: service,
-    version: Meteor.settings.cas.casVersion
-  });
-
-  cas.validate(ticket, (err, status, userData) => {
-    if (err) {
-      console.log("accounts-cas: error when trying to validate " + err);
-      console.log(err);
-    } else {
-      if (status) {
-        console.log(`accounts-cas: user validated ${userData.id}
-          (${JSON.stringify(userData)})`);
-        _casCredentialTokens[token] = { id: userData.id };
-        _userData = userData;
-      } else {
-        console.log("accounts-cas: unable to validate " + ticket);
-      }
-    }
-    callback();
-  });
-
-  return;
-};
-
-/*
- * Register a server-side login handle.
- * It is call after Accounts.callLoginMethod() is call from client.
- */
- Accounts.registerLoginHandler((options) => {
-  if (!options.cas)
-    return undefined;
-
-  if (!_hasCredential(options.cas.credentialToken)) {
-    throw new Meteor.Error(Accounts.LoginCancelledError.numericError,
-      'no matching login attempt found');
-  }
-
-  const result = _retrieveCredential(options.cas.credentialToken);
-
-  const attrs = Meteor.settings.cas.attributes || {};
-  // CAS keys
-  const fn = attrs.firstname || 'cas:givenName';
-  const ln = attrs.lastname || 'cas:sn';
-  const full = attrs.fullname;
-  const mail = attrs.mail || 'cas:mail'; // or 'email'
-  const uid = attrs.id || 'id';
-  if (attrs.debug) {
-    if (full) {
-      console.log(`CAS fields : id:"${uid}", fullname:"${full}", mail:"${mail}"`);
-    } else {
-      console.log(`CAS fields : id:"${uid}", firstname:"${fn}", lastname:"${ln}", mail:"${mail}"`);
-    }
-  }
-  const name = full ? _userData[full] : _userData[fn] + ' ' +  _userData[ln];
-  // https://docs.meteor.com/api/accounts.html#Meteor-users
-  options = {
-    // _id: Meteor.userId()
-    username: _userData[uid], // Unique name
-    emails: [
-      { address: _userData[mail], verified: true }
-    ],
-    createdAt: new Date(),
-    profile: {
-      // The profile is writable by the user by default.
-      name: name,
-      fullname : name,
-      email : _userData[mail]
-    },
-    active: true,
-    globalRoles: ['user']
-  };
-  if (attrs.debug) {
-    console.log(`CAS response : ${JSON.stringify(result)}`);
-  }
-  let user = Meteor.users.findOne({ 'username': options.username });
-  if (! user) {
-    if (attrs.debug) {
-      console.log(`Creating user account ${JSON.stringify(options)}`);
-    }
-    const userId = Accounts.insertUserDoc({}, options);
-    user = Meteor.users.findOne(userId);
-  }
-  if (attrs.debug) {
-    console.log(`Using user account ${JSON.stringify(user)}`);
-  }
-  return { userId: user._id };
-});
-
-const _hasCredential = (credentialToken) => {
-  return _.has(_casCredentialTokens, credentialToken);
-}
-
-/*
- * Retrieve token and delete it to avoid replaying it.
- */
-const _retrieveCredential = (credentialToken) => {
-  const result = _casCredentialTokens[credentialToken];
-  delete _casCredentialTokens[credentialToken];
-  return result;
-}
-
-const closePopup = (res) => {
-  if (Meteor.settings.cas && Meteor.settings.cas.popup == false) {
-    return;
-  }
-  res.writeHead(200, {'Content-Type': 'text/html'});
-  const content = '<html><body><div id="popupCanBeClosed"></div></body></html>';
-  res.end(content, 'utf-8');
-}
-
-const redirect = (res, whereTo) => {
-  res.writeHead(302, {'Location': whereTo});
-  const content = '<html><head><meta http-equiv="refresh" content="0; url='+whereTo+'" /></head><body>Redirection to <a href='+whereTo+'>'+whereTo+'</a></body></html>';
-  res.end(content, 'utf-8');
-  return
-}
-
-const end = (res, whereTo) => {
-  if (Meteor.settings.cas && Meteor.settings.cas.popup == false) {
-    redirect(res, whereTo);
-  } else {
-    closePopup(res);
-  }
-}

+ 0 - 29
packages/meteor-accounts-cas/package.js

@@ -1,29 +0,0 @@
-Package.describe({
-  summary: "CAS support for accounts",
-  version: "0.1.0",
-  name: "wekan:accounts-cas",
-  git: "https://github.com/wekan/meteor-accounts-cas"
-});
-
-Package.onUse(function(api) {
-  api.versionsFrom('METEOR@1.3.5.1');
-  api.use('routepolicy', 'server');
-  api.use('webapp', 'server');
-  api.use('accounts-base', ['client', 'server']);
-  // Export Accounts (etc) to packages using this one.
-  api.imply('accounts-base', ['client', 'server']);
-  api.use('underscore');
-  api.add_files('cas_client.js', 'web.browser');
-  api.add_files('cas_client_cordova.js', 'web.cordova');
-  api.add_files('cas_server.js', 'server');
-
-});
-
-Npm.depends({
-  xml2js: "0.4.17",
-  cas: "https://github.com/anrizal/node-cas/tarball/2baed530842e7a437f8f71b9346bcac8e84773cc"
-});
-
-Cordova.depends({
-  'cordova-plugin-inappbrowser': '1.2.0'
-});

+ 0 - 18
packages/meteor-useraccounts-core/.editorconfig

@@ -1,18 +0,0 @@
-#.editorconfig
-# Meteor adapted EditorConfig, http://EditorConfig.org
-# By RaiX 2013
-
-root = true
-
-[*.js]
-end_of_line = lf
-insert_final_newline = true
-indent_style = space
-indent_size = 2
-trim_trailing_whitespace = true
-charset = utf-8
-max_line_length = 80
-indent_brace_style = 1TBS
-spaces_around_operators = true
-quote_type = auto
-# curly_bracket_next_line = true

+ 0 - 2
packages/meteor-useraccounts-core/.gitignore

@@ -1,2 +0,0 @@
-.build*
-versions.json

+ 0 - 2
packages/meteor-useraccounts-core/.jshintignore

@@ -1,2 +0,0 @@
-client/compatibility
-packages

+ 0 - 132
packages/meteor-useraccounts-core/.jshintrc

@@ -1,132 +0,0 @@
-//.jshintrc
-{
-  // JSHint Meteor Configuration File
-  // Match the Meteor Style Guide
-  //
-  // By @raix with contributions from @aldeed and @awatson1978
-  // Source https://github.com/raix/Meteor-jshintrc
-  //
-  // See http://jshint.com/docs/ for more details
-
-  "maxerr"        : 50,       // {int} Maximum error before stopping
-
-  // Enforcing
-  "bitwise"       : true,     // true: Prohibit bitwise operators (&, |, ^, etc.)
-  "camelcase"     : true,     // true: Identifiers must be in camelCase
-  "curly"         : true,     // true: Require {} for every new block or scope
-  "eqeqeq"        : true,     // true: Require triple equals (===) for comparison
-  "forin"         : true,     // true: Require filtering for..in loops with obj.hasOwnProperty()
-  "immed"         : false,    // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
-  "indent"        : 2,        // {int} Number of spaces to use for indentation
-  "latedef"       : false,    // true: Require variables/functions to be defined before being used
-  "newcap"        : false,    // true: Require capitalization of all constructor functions e.g. `new F()`
-  "noarg"         : true,     // true: Prohibit use of `arguments.caller` and `arguments.callee`
-  "noempty"       : true,     // true: Prohibit use of empty blocks
-  "nonew"         : false,    // true: Prohibit use of constructors for side-effects (without assignment)
-  "plusplus"      : false,    // true: Prohibit use of `++` & `--`
-  "quotmark"      : false,    // Quotation mark consistency:
-  //   false    : do nothing (default)
-  //   true     : ensure whatever is used is consistent
-  //   "single" : require single quotes
-  //   "double" : require double quotes
-  "undef"         : true,     // true: Require all non-global variables to be declared (prevents global leaks)
-  "unused"        : true,     // true: Require all defined variables be used
-  "strict"        : true,     // true: Requires all functions run in ES5 Strict Mode
-  "trailing"      : true,     // true: Prohibit trailing whitespaces
-  "maxparams"     : false,    // {int} Max number of formal params allowed per function
-  "maxdepth"      : false,    // {int} Max depth of nested blocks (within functions)
-  "maxstatements" : false,    // {int} Max number statements per function
-  "maxcomplexity" : false,    // {int} Max cyclomatic complexity per function
-  "maxlen"        : 80,       // {int} Max number of characters per line
-
-  // Relaxing
-  "asi"           : false,     // true: Tolerate Automatic Semicolon Insertion (no semicolons)
-  "boss"          : false,     // true: Tolerate assignments where comparisons would be expected
-  "debug"         : false,     // true: Allow debugger statements e.g. browser breakpoints.
-  "eqnull"        : false,     // true: Tolerate use of `== null`
-  "es5"           : false,     // true: Allow ES5 syntax (ex: getters and setters)
-  "esnext"        : false,     // true: Allow ES.next (ES6) syntax (ex: `const`)
-  "moz"           : false,     // true: Allow Mozilla specific syntax (extends and overrides esnext features)
-  // (ex: `for each`, multiple try/catch, function expression…)
-  "evil"          : false,     // true: Tolerate use of `eval` and `new Function()`
-  "expr"          : false,     // true: Tolerate `ExpressionStatement` as Programs
-  "funcscope"     : false,     // true: Tolerate defining variables inside control statements"
-  "globalstrict"  : true,      // true: Allow global "use strict" (also enables 'strict')
-  "iterator"      : false,     // true: Tolerate using the `__iterator__` property
-  "lastsemic"     : false,     // true: Tolerate omitting a semicolon for the last statement of a 1-line block
-  "laxbreak"      : false,     // true: Tolerate possibly unsafe line breakings
-  "laxcomma"      : false,     // true: Tolerate comma-first style coding
-  "loopfunc"      : false,     // true: Tolerate functions being defined in loops
-  "multistr"      : false,     // true: Tolerate multi-line strings
-  "proto"         : false,     // true: Tolerate using the `__proto__` property
-  "scripturl"     : false,     // true: Tolerate script-targeted URLs
-  "smarttabs"     : false,     // true: Tolerate mixed tabs/spaces when used for alignment
-  "shadow"        : false,     // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
-  "sub"           : false,     // true: Tolerate using `[]` notation when it can still be expressed in dot notation
-  "supernew"      : false,     // true: Tolerate `new function () { ... };` and `new Object;`
-  "validthis"     : false,     // true: Tolerate using this in a non-constructor function
-
-  // Environments
-  "browser"       : true,     // Web Browser (window, document, etc)
-  "couch"         : false,    // CouchDB
-  "devel"         : true,     // Development/debugging (alert, confirm, etc)
-  "dojo"          : false,    // Dojo Toolkit
-  "jquery"        : false,    // jQuery
-  "mootools"      : false,    // MooTools
-  "node"          : false,    // Node.js
-  "nonstandard"   : false,    // Widely adopted globals (escape, unescape, etc)
-  "prototypejs"   : false,    // Prototype and Scriptaculous
-  "rhino"         : false,    // Rhino
-  "worker"        : false,    // Web Workers
-  "wsh"           : false,    // Windows Scripting Host
-  "yui"           : false,    // Yahoo User Interface
-  //"meteor"        : false,    // Meteor.js
-
-  // Legacy
-  "nomen"         : false,    // true: Prohibit dangling `_` in variables
-  "onevar"        : false,    // true: Allow only one `var` statement per function
-  "passfail"      : false,    // true: Stop on first error
-  "white"         : false,    // true: Check against strict whitespace and indentation rules
-
-  // Custom globals, from http://docs.meteor.com, in the order they appear there
-  "globals"       : {
-    "Meteor": false,
-    "DDP": false,
-    "Mongo": false, //Meteor.Collection renamed to Mongo.Collection
-    "Session": false,
-    "Accounts": false,
-    "Template": false,
-    "Blaze": false,  //UI is being renamed Blaze
-    "UI": false,
-    "Match": false,
-    "check": false,
-    "Tracker": false, //Deps renamed to Tracker
-    "Deps": false,
-    "ReactiveVar": false,
-    "EJSON": false,
-    "HTTP": false,
-    "Email": false,
-    "Assets": false,
-    "Handlebars": false,      // https://github.com/meteor/meteor/wiki/Handlebars
-    "Package": false,
-
-    // Meteor internals
-    "DDPServer": false,
-    "global": false,
-    "Log": false,
-    "MongoInternals": false,
-    "process": false,
-    "WebApp": false,
-    "WebAppInternals": false,
-
-    // globals useful when creating Meteor packages
-    "Npm": false,
-    "Tinytest": false,
-
-    // common Meteor packages
-    "Random": false,
-    "_": false,               // Underscore.js
-    "$": false,               // jQuery
-    "Router": false           // iron-router
-  }
-}

+ 0 - 8
packages/meteor-useraccounts-core/.travis.yml

@@ -1,8 +0,0 @@
-sudo: required
-language: node_js
-node_js:
-  - "0.10"
-before_install:
-  - "curl -L http://git.io/ejPSng | /bin/sh"
-env:
-  - TEST_COMMAND=meteor

+ 0 - 1433
packages/meteor-useraccounts-core/Guide.md

@@ -1,1433 +0,0 @@
-User Accounts
-=============
-
-User Accounts is a suite of packages for the [Meteor.js](https://www.meteor.com/) platform. It provides highly customizable user accounts UI templates for many different front-end frameworks. At the moment it includes forms for sign in, sign up, forgot password, reset password, change password, enroll account, and link or remove of many 3rd party services.
-
-<a name="documentation"/>
-# Documentation
-
-* [Features](#features)
-* [Quick Start](#quickstart)
-  * [Available Versions](#available-versions)
-  * [Boilerplates](#boilerplates)
-  * [Setup](#setup)
-  * [Routing](#routing)
-  * [Templates](#templates)
-* [Basic Customization](#basic-customization)
-  * [I18n Support](#i18n)
-  * [Configuration API](#configuration-api)
-    * [Options](#options)
-    * [logout](#logout)
-  * [Internal States](#internal-states)
-  * [Content Protection](#content-protection)
-  * [reCaptcha Setup](#reCaptcha-setup)
-  * [Detect reactively when a form is being processed](#detect-reactively-when-a-form-is-being-processed)
-* [Advanced Customization](#advanced-customization)
-  * [Configuring Texts](#configuring-texts)
-    * [Form Title](#form-title)
-    * [Button Text](#button-text)
-    * [Social Button Icons](#social-button-icons)
-    * [Info Text](#info-text)
-    * [Errors Text](#errors-text)
-  * [Disabling Client-side Accounts Creation](#disabling-client-side-accounts-creation)
-  * [Form Fields Configuration](#form-fields-configuration)
-  * [Extending Templates](#extending-templates)
-    * [Grouping Fields](#grouping-fields)
-  * [CSS Rules](#css-rules)
-* [Wrapping Up for Famo.us](#wrapping-up-for-famo.us)
-* [Side Notes](#side-notes)
-  * [3rd Party Login Services Configuration](#3rd-party-login-services-configuration)
-
-
-<a name="features"/>
-## Features
-
-* fully customizable
-* security aware
-* internationalization support thanks to [accounts-t9n](https://github.com/softwarerero/meteor-accounts-t9n)
-* custom sign-up fields
-* robust server side sign-up field validation
-* easy content protection
-* return to previous route after sign-in (even for random sign in choice and not only after required sign-in)
-* fully reactive, Blaze fast!
-* no use of `Session` object
-* very easily stylizable for different font-end frameworks
-* ...[wrap it up for famo.us](#wrapping-up-for-famo.us) with a simple meteor line!
-
-
-
-<a name="quickstart"/>
-## Quick Start
-
-
-<a name="available-versions"/>
-### Available Versions
-
-* [useraccounts:bootstrap](https://atmospherejs.com/useraccounts/bootstrap) styled for [Twitter Bootstrap](http://getbootstrap.com/)
-* [useraccounts:foundation](https://atmospherejs.com/useraccounts/foundation) styled for [Zurb Foundation](http://foundation.zurb.com/)
-* [useraccounts:ionic](https://atmospherejs.com/useraccounts/ionic) styled for [Ionic](http://ionicframework.com/)
-* [useraccounts:materialize](https://atmospherejs.com/useraccounts/materialize) styled for [Materialize](http://materializecss.com/)
-* [useraccounts:polymer](https://atmospherejs.com/useraccounts/polymer) styled for [Polymer](https://www.polymer-project.org/) (WIP)
-* [useraccounts:ratchet](https://atmospherejs.com/useraccounts/ratchet) styled for [Ratchet](http://goratchet.com/)
-* [useraccounts:semantic-ui](https://atmospherejs.com/useraccounts/semantic-ui) styled for [Semantic UI](http://semantic-ui.com)
-* [useraccounts:unstyled](https://atmospherejs.com/useraccounts/unstyled) with plain html and no CSS rules
-* plus others coming soon...
-
-
-<a name="boilerplates"/>
-### Boilerplates
-
-For a very very quick start you can find some boilerplate examples inside [this repository](https://github.com/meteor-useraccounts/boilerplates).
-
-We'll try to make them richer and richer, while still keeping them as general as possible.
-
-<a name="setup"/>
-### Setup
-
-Just choose one of the packages among the [available styled versions](#available-versions) and install it:
-
-```Shell
-meteor add useraccounts:bootstrap
-meteor add <your preferred bootstrap package>
-```
-
-**Note 1:** no additional packages nor CSS/LESS/SASS files providing styles are included by useraccounts packages. This is to let you choose your preferred way to include them!
-
-**Note 2:** You don't have to add `useraccounts:core` to your app! It is automatically added when you add `useraccounts:<something>`...
-
-Then add at least one login service:
-
-```Shell
-meteor add accounts-password
-meteor add accounts-facebook
-meteor add accounts-google
-...
-```
-
-**Note**: 3rd party services need to be configured... more about this [here](http://docs.meteor.com/#meteor_loginwithexternalservice)
-
-And that's it!
-
-...but don't expect to see much without doing something more ;-)
-This is to let you configure your app exactly the way you wish, without imposing anything beforehand!
-
-
-<a name="routing"/>
-### Routing
-
-If you'd like to easily configure specific routes to deal with accounts management, you might be interested to check out
-[useraccounts:iron-routing](https://github.com/meteor-useraccounts/iron-routing) and [useraccounts:flow-routing](https://github.com/meteor-useraccounts/flow-routing) packages.
-They provide very easy routes set-up via the `AccountsTemplates.configureRoute` method.
-
-
-<a name="templates"/>
-### Templates
-
-There is **only one template** which is used to reactively draw appropriate sign in, sign up, forgot password, reset password, change password, and enroll account forms!
-
-It is `atForm` and can be used anywhere you wish like this:
-
-```html
-{{> atForm}}
-```
-
-Its design is as *transparent* as possible, making it play nicely with themes and your CSS customizations! Also, it is not wrapped inside any *container* so that you can put it anywhere, including complex multi-column layouts.
-
-In case you wish to *lock* the template to a particular state, you can specify that via the `state` parameter:
-
-```html
-{{> atForm state='signUp'}}
-```
-
-This will prevent the template from changing its content. See [internal states](#internal-states) for more details...
-
-
-Well, actually there is many, used inside `atForm`...
-
-...plus one another: `atNavButton` which can be used inside navbars to get a basic sign-in sign-out button which changes text and behaviour based on the user status (to get it working you should set up at least a `signIn` route).
-
-
-<a name="basic-customization"/>
-## Basic Customization
-
-
-<a name="i18n"/>
-### I18n Support
-
-i18n is achieved using [accounts-t9n](https://atmospherejs.com/softwarerero/accounts-t9n). The only thing you have to do is ensure
-
-```javascript
-T9n.setLanguage('<lang>');
-```
-
-is called somewhere, whenever you want to switch language.
-
-
-<a name="configuration-api"/>
-### Configuration API
-
-There are basically two different ways to interact with AccountsTemplates for basic configuration:
-
-* AccountsTemplates.configureRoute(route_code, options);
-* AccountsTemplates.configure(options);
-
-**These functions should be called in top-level code, not inside `Meteor.startup()`.**
-
-There is no specific order for the above calls to be effective, and you can call them more than once, possibly in different files.
-
-**The only other requirement is to make exactly the same calls on both the server and the client.** The best thing is to put everything inside a file shared between both. I suggest you use something like `lib/config/at_config.js`
-
-
-<a name="options"/>
-#### Options
-
-By calling `AccountsTemplates.configure(options)` you can specify a bunch of choices regarding both visual appearance and behavior.
-
-The following is an almost complete example of options configuration (with fields in alphabetical order):
-
-```javascript
-AccountsTemplates.configure({
-    // Behavior
-    confirmPassword: true,
-    enablePasswordChange: true,
-    forbidClientAccountCreation: false,
-    overrideLoginErrors: true,
-    sendVerificationEmail: false,
-    lowercaseUsername: false,
-    focusFirstInput: true,
-
-    // Appearance
-    showAddRemoveServices: false,
-    showForgotPasswordLink: false,
-    showLabels: true,
-    showPlaceholders: true,
-    showResendVerificationEmailLink: false,
-
-    // Client-side Validation
-    continuousValidation: false,
-    negativeFeedback: false,
-    negativeValidation: true,
-    positiveValidation: true,
-    positiveFeedback: true,
-    showValidating: true,
-
-    // Privacy Policy and Terms of Use
-    privacyUrl: 'privacy',
-    termsUrl: 'terms-of-use',
-
-    // Redirects
-    homeRoutePath: '/home',
-    redirectTimeout: 4000,
-
-    // Hooks
-    onLogoutHook: myLogoutFunc,
-    onSubmitHook: mySubmitFunc,
-    preSignUpHook: myPreSubmitFunc,
-    postSignUpHook: myPostSubmitFunc,
-
-    // Texts
-    texts: {
-      button: {
-          signUp: "Register Now!"
-      },
-      socialSignUp: "Register",
-      socialIcons: {
-          "meteor-developer": "fa fa-rocket"
-      },
-      title: {
-          forgotPwd: "Recover Your Password"
-      },
-    },
-});
-```
-
-Details for each of them follow.
-
-| Option                      | Type     | Default   | Description |
-| --------------------------- | -------- | --------- | ----------- |
-| **Behavior**               |          |           |             |
-| confirmPassword             | Boolean  | true      | Specifies whether to ask the password twice for confirmation. This has no effect on the sign in form. |
-| defaultState                | String   | "signIn"  | Specifies the state to be used initially when atForm is rendered. This is not considered when rendering atForm on configured routes. |
-| enablePasswordChange        | Boolean  | false     | Specifies whether to allow to show the form for password change. Note: In case the `changePwd` route is not configured, this is to be done *manually* inside some custom template. |
-| enforceEmailVerification    | Boolean  | false     | When set to true together with sendVerificationEmail, forbids user login unless the email address is verified. **Warning: experimental! Use it only if you have accounts-password as the only service!!!** |
-| focusFirstInput             | Boolean  | !Meteor.isCordova      | When set to true, asks to autofocus the first input of atForm when the template is rendered. Note: have a look at [this issue](https://github.com/meteor-useraccounts/core/issues/594) in case you're getting problems with cordova apps. |
-| forbidClientAccountCreation | Boolean  | false     | Specifies whether to forbid user registration from the client side. In case it is set to true, neither the link for user registration nor the sign up form will be shown. |
-| overrideLoginErrors         | Boolean  | true      | Asks to show a general `Login Forbidden` on a login failure, without specifying whether it was for a wrong email or for a wrong password. |
-| sendVerificationEmail       | Boolean  | false     | Specifies whether to send the verification email after successful registration. |
-| redirectTimeout             | Number   | 2000      | Specifies a timeout time for the redirect after successful form submit on `enrollAccount`, `forgotPwd`, `resetPwd`, and `verifyEmail` routes. |
-| socialLoginStyle            | String   | "popup"   | Specifies the login style for 3rd party services login. Valid values are `popup` or `redirect`. See `loginStyle` option of [Meteor.loginWith<ExternalService>](http://docs.meteor.com/#/full/meteor_loginwithexternalservice) for more information.  |
-| lowercaseUsername           | Boolean  | false     | Possibly asks to transform `username` field for user objects at registration time to be always in lowercase with no spaces. The original `username` value will be added to the `user.profile` field for later use.  |
-| **Appearance**              |          |           |             |
-| hideSignInLink              | Boolean  | false     | When set to true, asks to never show the link to the sign in page  |
-| hideSignUpLink              | Boolean  | false     | When set to true, asks to never show the link to the sign up page  |
-| showAddRemoveServices       | Boolean  | false     | Tells whether to show social account buttons also when the user is signed in. In case it is set to true, the text of buttons will change from 'Sign in With XXX' to 'Add XXX' or 'Remove XXX' when the user signs in. 'Add' will be used if that particular service is still not associated with the current account, while 'Remove' is used only in case a particular service is already used by the user **and** there are at least two services available for sign in operations. Clicks on 'Add XXX' trigger the call to `Meteor.loginWithXXX`, as usual, while click on 'Remove XXX' will call the method `ATRemoveService` provided by AccountsTemplates. This means you need to have some additional logic to deal with the call `Meteor.loginWithXXX` in order to actually add the service to the user account. One solution to this is to use the package [accounts-meld](https://atmospherejs.com/package/accounts-meld) which was build exactly for this purpose. |
-| showForgotPasswordLink      | Boolean  | false     | Specifies whether to display a link to the forgot password page/form |
-| showLabels                  | Boolean  | true      | Specifies whether to display text labels above input elements. |
-| showPlaceholders            | Boolean  | true      | Specifies whether to display place-holder text inside input elements. |
-| showResendVerificationEmailLink      | Boolean  | false     | Specifies whether to display a link to the resend verification email page/form |
-| **Texts**                   |          |           |             |
-| texts                       | Object   |           | Permits to specify texts to be shown on the atForm for each of its states (see [below](#configuring-texts)). |
-| **Client-side Validation**  |          |           |             |
-| continuousValidation        | Boolean  | false     | Specifies whether to continuously validate fields' value while the user is typing. *It is performed client-side only to save round trips with the server*. |
-| negativeValidation          | Boolean  | false     | Specifies whether to highlight input elements in case of negative validation. |
-| positiveValidation          | Boolean  | false     | Specifies whether to highlight input elements in case of positive validation. |
-| negativeFeedback            | Boolean  | false     | Specifies whether to display negative validation feed-back inside input elements. |
-| positiveFeedback            | Boolean  | false     | Specifies whether to display positive validation feed-back inside input elements. |
-| showValidating              | Boolean  | false     | Specifies whether to display a loading icon inside input elements while the validation process is in progress. |
-| **Links**                   |          |           |             |
-| homeRoutePath               | String   | '/'       | Path for the home route, to be possibly used for redirects after successful form submission. |
-| privacyUrl                  | String   | undefined | Path for the route displaying the privacy document. In case it is specified, a link to the page will be displayed at the bottom of the form (when appropriate). |
-| termsUrl                    | String   | undefined | Path for the route displaying the document about terms of use. In case it is specified, a link to the page will be displayed at the bottom of the form (when appropriate). |
-| **Hooks**                   |          |           |             |
-| onLogoutHook                | Function |           | Called on `AccountsTemplates.logout` invocation: allows for custom redirects or whatever custom action to be taken on user logout. |
-| onSubmitHook                | Function |           | `func(error, state)` Called when the `pwdForm` is being submitted: allows for custom actions to be taken on form submission. `error` contains possible errors occurred during the submission process, `state` specifies the `atForm` internal state from which the submission was triggered. A nice use case might be closing the modal or side-menu showing `atForm` |
-| preSignUpHook               | Function |           | `func(password, info)` Called just before submitting the `pwdForm` for sign-up: allows for custom actions on the data being submitted. A nice use could be extending the user profile object accessing `info.profile`.  to be taken on form submission. The plain text `password` is also provided for any reasonable use. |
-| postSignUpHook               | Function |           | `func(userId, info)` Called, **server side only**, just after a successfull user account creation, post submitting the `pwdForm` for sign-up: allows for custom actions on the data being submitted ___after___ we are sure a new user was ___successfully___ created.  A common use might be applying roles to the user, as this is only possible after fully completing user creation in alanning:roles.  The `userId` is available as the first parameter, so that user user object may be retrieved.  The `password` is not available as it's already encrypted, though the encrypted password may be found in `info` if of use. |
-
-##### onSubmitHook
-
-A straightforward configuration about how to detect when a user logs in or registers might look like the following:
-
-```javascript
-var mySubmitFunc = function(error, state){
-  if (!error) {
-    if (state === "signIn") {
-      // Successfully logged in
-      // ...
-    }
-    if (state === "signUp") {
-      // Successfully registered
-      // ...
-    }
-  }
-};
-
-AccountsTemplates.configure({
-    onSubmitHook: mySubmitFunc
-});
-```
-
-<a name="logout"/>
-##### AccountsTemplates.logout()
-
-Should be used in place of `Meteor.logout()`.  This function invokes the `onLogoutHook` specified in the optional configuration.
-Also note that `AccountsTemplates.logout()` is invoked when logging out using the `atNavButton`.
-
-
-```javascript
-//Use in  place of Meteor.logout() in your client code.  Also called automatically by atNavButton when clicking Sign Off
-AccountsTemplates.logout();
-
-```
-
-
-```javascript
-var myPostLogout = function(){
-    //example redirect after logout
-    Router.go('/home');
-};
-
-AccountsTemplates.configure({
-    onLogoutHook: myPostLogout
-});
-```
-
-<a name="internal-states"/>
-### Internal States
-
-The `atForm` template changes reactively based on the current internal state of AccountsTemplates.
-The current internal state can be queried with `AccountsTemplates.getState()` and set with `AccountsTemplates.setState(new_state)`
-
-
-Currently available states are:
-
-| Internal State          | What's shown                                                                          |
-| ----------------------- | ------------------------------------------------------------------------------------- |
-| changePwd               | Change password form asking to set a new password                                     |
-| enrollAccount           | Account Enrollment form asking to set a password                                      |
-| forgotPwd               | Forgot Password form asking for the email address where to send a reset password link |
-| hide                    | None at all...                                                                        |
-| resendVerificationEmail | Login form with an additional button to get another verification email                |
-| resetPwd                | Reset Password form asking to set a password                                          |
-| signIn                  | Login form                                                                            |
-| signUp                  | Registration form                                                                     |
-| verifyEmail             | Only the result about email verification                                              |
-
-
-
-<a name="content-protection"/>
-### Content Protection
-
-
-If you want to secure a specific template, you could add that template like this:
-
-```handlebars
-{{> ensureSignedIn template="myTemplate"}}
-```
-and that will render the default `fullPageAtForm` template from your chosen User Accounts templates package (bootstrap, materialize, etc).  Once signed in, it'll render `myTemplate` instead of the accounts form.
-
-If you want to declare a custom sign in template instead of `fullPageAtForm`, you would do this:
-
-```handlebars
-{{> ensureSignedIn template="myTemplate" auth="myLoginForm"}}
-```
-That custom auth template just needs to include `{{> atForm}}` somewhere in it.  The only reason you'd use this optional feature is if you wanted to modify the layout around the `atForm` template (like
-`fullPageAtForm` does).
-
-
-In case you're using one of the routing packages [useraccounts:iron-routing](https://github.com/meteor-useraccounts/iron-routing)
-or [useraccounts:flow-routing](https://github.com/meteor-useraccounts/flow-routing) refer to their documentation for more possibilities.
-
-
-<a name="reCaptcha-setup"/>
-### reCaptcha Setup
-To set up [reCaptcha](https://www.google.com/recaptcha/intro/index.html), you need to first obtain API keys.
-
-Then, a recommended setup is as follows.
-
-A [Meteor settings file](http://docs.meteor.com/#/full/meteor_settings) with the keys:
-
-```javascript
-{
-    "public": {
-        "reCaptcha": {
-            "siteKey": YOUR SITE KEY
-        }
-    },
-    "reCaptcha": {
-        "secretKey": YOUR SECRET KEY
-    }
-}
-```
-
-and configuration to show the reCaptcha widget:
-
-```javascript
-AccountsTemplates.configure({
-    showReCaptcha: true
-});
-```
-
-The reCaptcha plugin can likewise be set up with the following complete example:
-
-
-```javascript
-AccountsTemplates.configure({
-    reCaptcha: {
-        siteKey: YOUR SITE KEY,
-        theme: "light",
-        data_type: "image"
-    },
-    showReCaptcha: true
-});
-```
-
-And, in a separate file in the `/server` folder:
-
-```javascript
-AccountsTemplates.configure({
-    reCaptcha: {
-        secretKey: YOUR SECRET KEY.
-    },
-});
-```
-
-Each option is described below:
-
-| Option                      | Type     | Default   | Description |
-| --------------------------- | -------- | --------- | ----------- |
-| siteKey                     | String   | none      | The site key needed to create the reCaptcha widget. This can be specified in just the Meteor settings file. |
-| secretKey                   | String   | none      | The secret key needed to verify the reCaptcha response. ***Warning: Only set this in a file in `/server` or in a Meteor settings file. Otherwise, your private key can be read by anyone!*** |
-| theme                       | String   | "light"   | Sets the reCaptcha theme color. The options are "light" and "dark". |
-| data_type                   | String   | "image"   | Sets the verification method. Options are "image" or "audio". |
-| showReCaptcha               | Boolean  | false     | Whether to show the reCaptcha widget on sign in or not. No reCaptcha validation will occur if set to false. |
-
-<a name="detect-reactively-when-a-form-is-being-processed"/>
-### Detect reactively when a form is being processed
-
-`AccountsTemplates.disabled()` returns `true` when a submitted form is being processed and `false` once the submission process has been completed (successfully or not). `AccountsTemplate.disabled()` is reactive and can be used to trigger UI events, such as spinners, "Please wait" messages or to disable input elements, while the form is being processed. The function works irrespectively of form status (signIn, signUp, pwdReset etc.). A typical use-case would be in a template helper:
-
-```html
-<template name="myLogin">
- {{#if atDisabled}}
-  Please wait...
- {{/if}}
- <div class="{{atClass}}">
-  {{> atForm}}
- </div>
-</template>
-```
-
-```js
-Template.myLogin.helpers({
- atDisabled: function() {
-  return AccountsTemplates.disabled();
- },
- atClass: function() {
-  return AccountsTemplates.disabled() ? 'disabled' : 'active';
- }
-});
-```
-
-<a name="advanced-customization"/>
-## Advanced Customization
-
-
-<a name="configuring-texts"/>
-### Configuring Texts
-
-In case you wish to change texts on atForm, you can call:
-
-```javascript
-AccountsTemplates.configure({
-    texts: {
-        navSignIn: "signIn",
-        navSignOut: "signOut",
-        optionalField: "optional",
-        pwdLink_pre: "",
-        pwdLink_link: "forgotPassword",
-        pwdLink_suff: "",
-        resendVerificationEmailLink_pre: "Verification email lost?",
-        resendVerificationEmailLink_link: "Send again",
-        resendVerificationEmailLink_suff: "",
-        sep: "OR",
-        signInLink_pre: "ifYouAlreadyHaveAnAccount",
-        signInLink_link: "signin",
-        signInLink_suff: "",
-        signUpLink_pre: "dontHaveAnAccount",
-        signUpLink_link: "signUp",
-        signUpLink_suff: "",
-        socialAdd: "add",
-        socialConfigure: "configure",
-        socialIcons: {
-            "meteor-developer": "fa fa-rocket",
-        },
-        socialRemove: "remove",
-        socialSignIn: "signIn",
-        socialSignUp: "signUp",
-        socialWith: "with",
-        termsPreamble: "clickAgree",
-        termsPrivacy: "privacyPolicy",
-        termsAnd: "and",
-        termsTerms: "terms",
-    }
-});
-```
-
-the above example asks to change some of the available text configurations. You can specify only a subsets of them leaving default values unchanged.
-To learn how to change title, button, social buttons' icon, info, and errors text read below.
-
-
-<a name="form-title"/>
-#### Form Title
-
-In case you wish to change form titles, you can call:
-
-```javascript
-AccountsTemplates.configure({
-    texts: {
-      title: {
-        changePwd: "Password Title",
-        enrollAccount: "Enroll Title",
-        forgotPwd: "Forgot Pwd Title",
-        resetPwd: "Reset Pwd Title",
-        signIn: "Sign In Title",
-        signUp: "Sign Up Title",
-        verifyEmail: "Verify Email Title",
-      }
-    }
-});
-```
-
-the above example asks to change the title for all possible form states, but you can specify only a subset of them leaving default values unchanged.
-
-You can also *hide* a title by setting it to an empty string. For example with:
-
-```
-AccountsTemplates.configure({
-    texts: {
-      title: {
-        signIn: "",
-      }
-    }
-});
-```
-
-no title will be shown on the sign in form.
-
-
-<a name="button-text"/>
-#### Button Text
-
-In case you wish to change the text appearing inside the submission button, you can call:
-
-```javascript
-AccountsTemplates.configure({
-    texts: {
-        button: {
-          changePwd: "Password Text",
-          enrollAccount: "Enroll Text",
-          forgotPwd: "Forgot Pwd Text",
-          resetPwd: "Reset Pwd Text",
-          signIn: "Sign In Text",
-          signUp: "Sign Up Text",
-        }
-    }
-});
-```
-
-the above example asks to change the button text for all possible form states, but you can specify only a subset of them leaving default values unchanged.
-
-<a name="social-button-icons"/>
-#### Social Button Icons
-
-In case you wish to change the icon appearing on the left of social login buttons, you can call:
-
-```javascript
-AccountsTemplates.configure({
-    texts: {
-        socialIcons: {
-          google: "myGoogleIcon",
-          "meteor-developer": "myMeteorIcon",
-        }
-    }
-});
-```
-
-to specify a different icon classes to be used for services. By default the icon class is set to `fa fa-*service*`,
-but for the "meteor-developer" service for which `fa fa-rocket` is used. An exception is made for `useaccounts:semantic-ui`
-which sets them simply to `*service*`, which is the correct way to go.
-
-<a name="info-text"/>
-#### Info Text
-
-In case you wish to change the info text appearing inside the results box, you can call:
-
-```javascript
-AccountsTemplates.configure({
-    texts: {
-        info: {
-            emailSent: "info.emailSent",
-            emailVerified: "info.emailVerified",
-            pwdChanged: "info.passwordChanged",
-            pwdReset: "info.passwordReset",
-            pwdSet: "info.passwordReset",
-            signUpVerifyEmail: "Successful Registration! Please check your email and follow the instructions.",
-            verificationEmailSent: "A new email has been sent to you. If the email doesn't show up in your inbox, be sure to check your spam folder.",
-        }
-    }
-});
-```
-
-The above calls simply set all values as the current default ones.
-
-<a name="input-icons"/>
-#### Input Field Icons
-
-In case you wish to change the icon appearing on the right side of input fields to show their validation status, you can call:
-
-```javascript
-AccountsTemplates.configure({
-    texts: {
-      inputIcons: {
-          isValidating: "fa fa-spinner fa-spin",
-          hasSuccess: "fa fa-check",
-          hasError: "fa fa-times",
-      }
-    }
-});
-```
-
-<a name="errors-text"/>
-#### Errors Text
-
-In case you wish to change the text for errors appearing inside the error box, you can call:
-
-```javascript
-AccountsTemplates.configure({
-    texts: {
-        errors: {
-            accountsCreationDisabled: "Client side accounts creation is disabled!!!",
-            cannotRemoveService: "Cannot remove the only active service!",
-            captchaVerification: "Captcha verification failed!",
-            loginForbidden: "error.accounts.Login forbidden",
-            mustBeLoggedIn: "error.accounts.Must be logged in",
-            pwdMismatch: "error.pwdsDontMatch",
-            validationErrors: "Validation Errors",
-            verifyEmailFirst: "Please verify your email first. Check the email and follow the link!",
-        }
-    }
-});
-```
-
-The above calls simply set all values as the current default ones.
-*Note:* The above list of errors refers to those set directly by AccountsTemplates only!
-Errors which comes from the Accounts packages cannot be overwritten (at least not easily...)
-Please have a look at [Form Fields Configuration](#form-fields-configuration) to learn how to set validation errors on a field basis.
-
-
-<a name="disabling-client-side-accounts-creation"/>
-### Disabling Client-side Accounts Creation
-
-AccountsTemplates disables by default accounts creation on the client. This is done to use a dedicated method called `ATCreateUserServer` **(sending the password on the wire already hashed as usual...)** to create the new users server-side.
-This way a bulletproof profile fields full validation can be performed.
-But there is one more parameter to set in case you'd like to forbid client-side accounts creation, which is the following:
-
-* `forbidClientAccountCreation` - (Boolean, default false) Specifies whether to forbid accounts creation from the client.
-
-it is exactly the same provided by the Accounts object, so this means you need to do:
-
-```javascript
-AccountsTemplates.configure({
-    forbidClientAccountCreation: true
-});
-```
-
-instead of the usual:
-
-```javascript
-Accounts.config({
-  forbidClientAccountCreation : true
-});
-```
-
-
-<a name="form-fields-configuration"/>
-### Form Fields Configuration
-
-Every input field appearing inside AccountsTemplates forms can be easily customized both for appearance and validation behaviour. Additional (custom) fields can be added to the sign up and registration forms, and the properties of built-in fields, like `email` and `password` can be overridden (see [Remove fields](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#remove-fields))
-
-Each field object is represented by the following properties:
-
-| Property             | Type             | Required | Description                                                                                                                                                                                                                            |
-| -------------------- | -----------------|:--------:| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| _id                  | String           |    X     | A unique field's id/name (internal use only) to be also used as attribute name into `Meteor.user().profile` in case it identifies an additional sign up field. Usually all lowercase letters.                                       |
-| type                 | String           |    X     | Specifies the input element type. At the moment supported inputs are: `password`, `email`, `text`, `tel`, `url`, `checkbox`, `select`, `radio`, `hidden`.                                                                                        |
-| required             | Boolean          |          | When set to true the corresponding field cannot be left blank                                                                                                                                                                          |
-| displayName          | String or Object |          | The field name to be shown as text label above the input element. In case nothing is specified, the capitalized `_id` is used. The text label is shown only if `showLabels` options is set to true.                             |
-| placeholder          | String or Object |          | The placeholder text to be shown inside the input element. In case nothing is specified, the capitalized `_id` will be used. The place-holder is shown only if `showPlaceholders` option is set to true.                    |
-| select               | [Object]         |          | Lets you specify an array of choices to be displayed for select and radio inputs. See example below.                                                                                                                                   |
-| minLength            | Integer          |          | If specified, requires the content of the field to be at least `minLength` characters.                                                                                                                                                  |
-| maxLength            | Integer          |          | If specified, require the content of the field to be at most `maxLength` characters.                                                                                                                                                    |
-| re                   | RegExp           |          | Possibly specifies the regular expression to be used for the field's content validation. Validation is performed both client-side (at every input change if `continuousValidation` option is set to true) and server-side on form submit. |
-| func                 | Function         |          | Custom function to be used for validation.                                                                                                                                                                                             |
-| errStr               | String           |          | Error message to be displayed in case re or func validation fail.                                                                                                                                                                      |
-| trim                 | Boolean          |          | Trim the input value.                                                                                                                                                                                      |
-| lowercase            | Boolean          |          | Convert the input value to lowercase.                                                                                                                                                                      |
-| uppercase            | Boolean          |          | Convert the input value to uppercase.                                                                                                                                                                      |
-| transform            | Function         |          | Custom function to transform the input value.                                                                                                                                                                      |
-| continuousValidation | Boolean          |          | Continuously validate fields' value while the user is typing. *It is performed client-side only to save round trips with the server*. |
-| negativeValidation   | Boolean          |          | Highlight input elements in case of negative validation. |
-| positiveValidation   | Boolean          |          | Highlight input elements in case of positive validation. |
-| negativeFeedback     | Boolean          |          | Display negative validation feedback inside input elements. |
-| positiveFeedback     | Boolean          |          | Display positive validation feedback inside input elements. |
-| showValidating       | Boolean          |          | Display a loading icon inside input elements while the validation process is in progress. |
-| options              | Object           |          | Allows to pass in additional custom options to be possibly used to extend input templates (see [Extending Templates](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#extending-templates))  |
-| template             | String           |          | The name of a custom template to be used in place of the default one. |
-
-
-`displayName`, `placeholder`, and `errStr` can also be an [accounts-t9n](https://atmospherejs.com/softwarerero/accounts-t9n) registered key, in which case it will be translated based on the currently selected language.
-In case you'd like to specify a key which is not already provided by accounts-t9n you can always map your own keys. To learn how to register new labels, please refer to the official [documentation](https://github.com/softwarerero/meteor-accounts-t9n#define-translations).
-
-`continuousValidation`, `negativeFeedback`, `negativeValidation`, `positiveValidation`, `positiveFeedback`, `showValidating` can be used to override global settings (see [Form Fields Configuration](#form-fields-configuration)) on a per field basis.
-
-Furthermore, you can pass an object for `displayName`, `placeholder` to specify different texts for different form states. The matched pattern is:
-
-```javascript
-{
-    default: Match.Optional(String),
-    changePwd: Match.Optional(String),
-    enrollAccount: Match.Optional(String),
-    forgotPwd: Match.Optional(String),
-    resetPwd: Match.Optional(String),
-    signIn: Match.Optional(String),
-    signUp: Match.Optional(String),
-}
-```
-
-which permits to specify a different text for each different state, or a default value to be used for states which are not explicitly provided. For example:
-
-```javascript
-AccountsTemplates.addField({
-    _id: 'password',
-    type: 'password',
-    placeholder: {
-        signUp: "At least six characters"
-    },
-    required: true,
-    minLength: 6,
-    re: /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/,
-    errStr: 'At least 1 digit, 1 lowercase and 1 uppercase',
-});
-```
-
-asks AccountsTemplates to display "At least six characters" as the placeholder for the password field when the sign up form is display, and to display "Password" (the capitalized *_id*_) in any other case.
-
-##### Custom validation
-Custom validation can be achieved by providing a regular expression or a function. In case you go for the function solution, this:
-
-```javascript
-AccountsTemplates.addField({
-    _id: 'name',
-    type: 'text',
-    displayName: "Name",
-    func: function(value){return value !== 'Full Name';},
-    errStr: 'Only "Full Name" allowed!',
-});
-```
-
-will require the name input to be exactly "Full Name" (though this might not be that interesting...).
-If instead you do something along the following line:
-
-```javascript
-AccountsTemplates.addField({
-    _id: 'phone',
-    type: 'tel',
-    displayName: "Phone",
-    required: true,
-    func: function (number) {
-        if (Meteor.isServer){
-          if (isValidPhone(number))
-              return false; // meaning no error!
-          return true; // Validation error!
-        }
-    },
-    errStr: 'Invalid Phone number!',
-});
-```
-
-supposing `isValidPhone` is available only server-side, you will be validating the field only server-side, on form submission.
-
-If, differently, you do something like this:
-
-```javascript
-if (Meteor.isServer){
-    Meteor.methods({
-        "userExists": function(username){
-            return !!Meteor.users.findOne({username: username});
-        },
-    });
-}
-
-AccountsTemplates.addField({
-    _id: 'username',
-    type: 'text',
-    required: true,
-    func: function(value){
-        if (Meteor.isClient) {
-            console.log("Validating username...");
-            var self = this;
-            Meteor.call("userExists", value, function(err, userExists){
-                if (!userExists)
-                    self.setSuccess();
-                else
-                    self.setError(userExists);
-                self.setValidating(false);
-            });
-            return;
-        }
-        // Server
-        return Meteor.call("userExists", value);
-    },
-});
-```
-
-you can achieve also client-side and server-side validation calling a server method
-During the waiting time a loading icon will be displayed (if you configure `showValidating` to be true).
-To configure the loading icon see [Input Field Icons](#input-icons).
-
-*Note:* `field.setError(err)`, `field.setSuccess()`, and `field.setValidating()` are methods used to deal with inputs' validation states. A `null` value means non-validated, `false` means correctly validated, no error, and any other value evaluated as true (usually strings specifying the reason for the validation error), are finally interpreted as error and displayed where more appropriate.
-
-#### Checkboxes, Selects, Radios, and Hidden
-
-This is an example about how to add Checkboxes, Selects, and Radios to the sign up fields:
-
-```javascript
-AccountsTemplates.addField({
-    _id: "gender",
-    type: "select",
-    displayName: "Gender",
-    select: [
-        {
-            text: "Male",
-            value: "male",
-        },
-        {
-            text: "Female",
-            value: "female",
-        },
-    ],
-});
-
-AccountsTemplates.addField({
-    _id: "fruit",
-    type: "radio",
-    displayName: "Preferred Fruit",
-    select: [
-        {
-        text: "Apple",
-        value: "aa",
-      }, {
-        text: "Banana",
-        value: "bb",
-      }, {
-        text: "Carrot",
-        value: "cc",
-      },
-    ],
-});
-
-AccountsTemplates.addField({
-    _id: "mailing_list",
-    type: "checkbox",
-    displayName: "Subscribe me to mailing List",
-});
-
-AccountsTemplates.addField({
-    _id: 'reg_code',
-    type: 'hidden'
-});
-```
-
-please note the `select` list which lets you specify the values for the choice.
-The `value` value of corresponding selected `text` will be picked up and added into the `profile` field of the user object.
-
-Hidden inputs might be of help in case you want to consider to link to your registration page from around the web (emails, ads, discount campaigns, etc...) with links like this:
-
-```
-http://my.splendido.site/sign-up?email=giorgio@example.com&reg_code=123
-```
-
-exploiting the ability of AccountsTemplates to pick-up query parameters having the same key as field ids, this would permit to get `reg_code: "123"` under the `profile` field of the user object.
-**Please use this with caution!** ..never ever do something like:
-```
-http://my.splendido.site/sign-up?role=admin
-```
-and then set the role of the new user based on the hidden `role` field. I guess you can appreciate the security hole there ;-)
-
-#### Special Field's Ids
-
-There are a number of special ids used for basic input fields. These are:
-
-* current_password
-* email
-* password
-* password_again
-* username
-* username_and_email
-
-Any other id will be interpreted as an additional sign up field.
-In case a special field is not explicitly added, it will be automatically inserted at initialization time (with appropriate default properties). To customize special fields see [Remove fields](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#remove-fields)
-
-#### Add a field
-
-You can use `AccountsTemplates.addField(options)` to configure an input field. This apply for both special fields and custom ones.
-For example you can do:
-
-```javascript
-AccountsTemplates.addField({
-    _id: 'phone',
-    type: 'tel',
-    displayName: "Landline Number",
-});
-```
-
-The above snippet asks `AccountsTemplates` to draw an additional input element within the sign-up form.
-
-#### Add many fields at once
-
-Another possibility is to add many additional fields at once using `addFields`:
-
-```javascript
-AccountsTemplates.addFields([
-    {
-        _id: 'phone',
-        type: 'tel',
-        displayName: "Landline Number",
-    },
-    {
-        _id: 'fax',
-        type: 'tel',
-        displayName: "Fax Number",
-    }
-]);
-```
-
-#### Remove fields
-
-There is also a `removeField` method which can be used to remove predefined required fields and adding them again specify different options.
-
-```javascript
-AccountsTemplates.removeField('password');
-AccountsTemplates.addField({
-    _id: 'password',
-    type: 'password',
-    required: true,
-    minLength: 6,
-    re: /(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/,
-    errStr: 'At least 1 digit, 1 lower-case and 1 upper-case',
-});
-```
-
-#### Login with Username or Email
-
-In order to let the user register with both a `username` and an `email` address and let him the possibility to log in using one of them, both the `username` and `email` fields must be added.
-This is an example about how to configure such a behaviour:
-
-```javascript
-var pwd = AccountsTemplates.removeField('password');
-AccountsTemplates.removeField('email');
-AccountsTemplates.addFields([
-  {
-      _id: "username",
-      type: "text",
-      displayName: "username",
-      required: true,
-      minLength: 5,
-  },
-  {
-      _id: 'email',
-      type: 'email',
-      required: true,
-      displayName: "email",
-      re: /.+@(.+){2,}\.(.+){2,}/,
-      errStr: 'Invalid email',
-  },
-  pwd
-]);
-```
-
-This will trigger the automatic insertion of the special field `username_and_email` to be used for the sign in form.
-If you wish to further customize the `username_and_email` field you can add it together with the other two:
-
-```javascript
-var pwd = AccountsTemplates.removeField('password');
-AccountsTemplates.removeField('email');
-AccountsTemplates.addFields([
-  {
-      _id: "username",
-      type: "text",
-      displayName: "username",
-      required: true,
-      minLength: 5,
-  },
-  {
-      _id: 'email',
-      type: 'email',
-      required: true,
-      displayName: "email",
-      re: /.+@(.+){2,}\.(.+){2,}/,
-      errStr: 'Invalid email',
-  },
-  {
-      _id: 'username_and_email',
-      type: 'text',
-      required: true,
-      displayName: "Login",
-  },
-  pwd
-]);
-```
-
-
-<a name="extending-templates"/>
-### Extending Templates
-
-With the [aldeed:template-extension](https://github.com/aldeed/meteor-template-extension) package, the built-in templates or sub-templates of any `user-accounts` UI package may be replaced by custom templates. The purpose is to create more sophisticated or specialized layouts or styling.
-
-In case of input fields the option `template` (see [Form Fields Configuration](#form-fields-configuration)) can be directly used without the need to rely on `aldeed:template-extension` package.
-
-Here is a simple example of a template you can use for a field of type 'select':
-
-```html
-<template name="customSelectTemplate">
-  <select id="at-field-{{_id}}" name="at-field-{{_id}}" data-something="{{options.someOption}}">
-    {{#each select}}
-    <option value="{{value}}">{{text}}</option>
-    {{/each}}
-  </select>
-</template>
-```
-
-Custom properties that hold information about the look of the form may be attached to the `options` object of a field. It may then be used to change the output while looping the fields. Adding a divider might look like this:
-
-```javascript
-AccountsTemplates.addField({
-  _id: "address",
-  type: "text",
-
-  // Options object with custom properties for my layout. At the moment, there are
-  // no special properties; it is up the developer to invent them
-  options: {
-    // Put a divider before this field
-    dividerBefore: true
-  }
-});
-```
-
-```html
-<template name="appAtInput">
-  {{#if options.dividerBefore}}<hr>{{/if}}
-
-  {{> Template.dynamic template=templateName}}
-</template>
-```
-
-```javascript
-Template.appAtInput.replaces("atInput");
-```
-
-
-<a name="grouping-fields"/>
-#### Grouping fields
-
-Grouping fields together is a special problem in regard to layout. The issue is creating some container markup *while* iterating over the fields (the templating engine of Meteor doesn't allow outputting an opening tag inside a loop without closing it in the same iteration).
-
-A solution to the problem is demonstrated in [this gist](https://gist.github.com/dalgard/a844f6569d8f471db9a7) (Semantic UI version).
-
-
-<a name="css-rules"/>
-### CSS Rules
-
-The main atForm is build up of several pieces, appearing and disappearing based on configuration options as well as the current internal status.
-Each of these blocks is wrapped inside a `div` with class `at-<something>`: this should made your life easier if you're trying to write your own CSS rules to change templates' appearance.
-
-Social login buttons (`button.at-social-btn`) have an `id` in the form `at-<servicename>` and name `<servicename>`.
-
-Input fields for the password service form are wrapped inside a div with class `at-input`. The same div gets classes `has-error`, `has-success`, and `has-feedback` in case of negative validation result, positive validation and validation with feedback respectively.
-The input element itself has id and name in the form `at-field-<field_id>`.
-**Note:** `has-error`, `has-success`, and `has-feedback` names might change from framework to framework. These are valid for the *unstyled* and *bootstrap* versions...
-
-
-Below is a html snapshot of an over-complete `atForm` taken from the unstyled version in which you can find all elements possibly shown under different configurations and circumstances.
-
-```html
-<div class="at-form">
-  <!-- Title -->
-  <div class="at-title">
-    <h3>Create an Account</h3>
-  </div>
-  <!-- Social Buttons for Oauth Sign In / Sign Up-->
-  <div class="at-oauth">
-    <button class="at-social-btn" id="at-facebook" name="facebook">
-      <i class="fa fa-facebook"></i> Sign in with Facebook
-    </button>
-    <button class="at-social-btn" id="at-twitter" name="twitter">
-      <i class="fa fa-twitter"></i> Sign in with Twitter
-    </button>
-  </div>
-  <!-- Services Separator -->
-  <div class="at-sep">
-    <strong>OR</strong>
-  </div>
-  <!-- Global Error -->
-  <div class="at-error">
-      <p>Login forbidden</p>
-  </div>
-  <!-- Global Resutl -->
-  <div class="at-result">
-      <p>Email Sent!</p>
-  </div>
-  <!-- Password Service -->
-  <div class="at-pwd-form">
-    <form role="form" id="at-pwd-form" novalidate="">
-      <!-- Input -->
-      <div class="at-input">
-        <label for="at-field-username">
-          Username
-        </label>
-        <input type="text" id="at-field-username" name="at-field-username" placeholder="Username" autocapitalize="none" autocorrect="off">
-      </div>
-      <!-- Input with Validation Error -->
-      <div class="at-input has-error">
-        <label for="at-field-email">
-          Email
-        </label>
-        <input type="email" id="at-field-email" name="at-field-email" placeholder="Email" autocapitalize="none" autocorrect="off">
-        <span>Invalid email</span>
-      </div>
-      <!-- Input with Successful Validation -->
-      <div class="at-input has-success">
-        <label for="at-field-password">
-          Password
-        </label>
-        <input type="password" id="at-field-password" name="at-field-password" placeholder="Password" autocapitalize="none" autocorrect="off">
-      </div>
-      <!-- Forgot Password Link -->
-      <div class="at-pwd-link">
-        <p>
-          <a href="/forgot-password" id="at-forgotPwd" class="at-link at-pwd">Forgot your password?</a>
-        </p>
-      </div>
-      <!-- Form Submit Button -->
-      <button type="submit" class="at-btn submit disabled" id="at-btn">
-        Register
-      </button>
-    </form>
-  </div>
-  <!-- Link to Sign In -->
-  <div class="at-signin-link">
-    <p>
-      If you already have an account
-      <a href="/sign-in" id="at-signIn" class="at-link at-signin">sign in</a>
-    </p>
-  </div>
-  <!-- Link to Sign Up -->
-  <div class="at-signup-link">
-    <p>
-      Don't have an account?
-      <a href="/sign-up" id="at-signUp" class="at-link at-signup">Register</a>
-    </p>
-  </div>
-  <!-- Link to Privacy Policy and Terms of use -->
-  <div class="at-terms-link">
-    <p>
-      By clicking Register, you agree to our
-        <a href="/privacyPolicy">Privacy Policy</a>
-        and
-        <a href="/termsOfUse">Terms of Use</a>
-    </p>
-  </div>
-</div>
-```
-
-
-
-<a name="wrapping-up-for-famo.us"/>
-## Wrapping Up for Famo.us
-
-By simply typing
-
-```shell
-meteor add useraccounts:famous-wrapper
-```
-
-you'll be able to turn your preferred flavour of accounts templates into a package ready to be used within a [famous-views](https://atmospherejs.com/gadicohen/famous-views) + [Famo.us](http://famo.us) application.
-
-This means you can get an animated version of the `atForm` template without any effort! :-)
-
-To learn how to make animations you might want to check the following links:
-
-* http://famous-views.meteor.com
-* http://famous-views.meteor.com/examples/animate
-* http://famo.us/university/lessons/#/famous-101/animating/1
-* http://famo.us/guides/layout
-* http://famo.us/guides/animations
-* http://famo.us/docs/modifiers/StateModifier
-* http://famo.us/docs/transitions/Transitionable
-
-### configureAnimations
-
-...well, actually it might be that you don't like the default animations so you might consider to use `AccountsTemplates.configureAnimations` (provided by the wrapper...) to specify your custom animation functions.
-This is an example showing how to do it:
-
-```javascript
-var Transform;
-var Easing;
-if (Meteor.isClient){
-    FView.ready(function(require) {
-        Transform = famous.core.Transform;
-        Easing = famous.transitions.Easing;
-    });
-}
-
-var slideLeftDestroy = function(fview){
-    fview.modifier.setTransform(
-        Transform.translate(-$(window).width(),0),
-        { duration : 250, curve: Easing.easeOutSine },
-        function() { fview.destroy();}
-    );
-};
-
-
-AccountsTemplates.configureAnimations({
-    destroy: {
-        atSignupLink: slideLeftDestroy,
-    }
-});
-```
-
-this asks AT to use `slideLeftDestroy` to animate the template `atSignupLink` when it is to be destroyed.
-
-As you've just seen `configureAnimations` take an `options` object as parameter:
-
-```javascript
-AccountsTemplates.configureAnimations(options);
-```
-
-this options object can have three different keys at the first level:
-
-```javascript
-var options = {
-    render: {
-      // more stuff here...
-    },
-    destroy: {
-      // more stuff here...
-    },
-    state_change: {
-      // more stuff here...
-    },
-    animQueueDelay: 100,
-    animQueueStartDelay: 200,
-    setStateDelay: 300,
-
-};
-AccountsTemplates.configureAnimations(options);
-```
-
-they are `render`, `destroy`, `state_change`, `animQueueDelay`, `animQueueStartDelay`, and `setStateDelay`.
-The first three, what a surprise, they let you specify what to do when one of the templates building up the `atForm` is rendered, destroyed or when the form's state changes (respectively).
-
-...at the second level you can specify which animation has to be applied to which template:
-
-```javascript
-var options = {
-    render: {
-        default: animA,
-        atTitle: animB,
-        atSocial: animC,
-        atSep: animC,
-        atError: animB,
-        atResult: animB,
-        atPwdForm: null,
-        atSigninLink: null,
-        atSignupLink: animB,
-        atTermsLink: animD,
-    },
-    // ...
-};
-```
-
-the above one is the full list of available animated templates...
-The value you specify can be `null` (to remove a default animation...) or a function.
-If you specify a function it should be like the following:
-
-```javascript
-var animFunc = function(fview){
-    fview.modifier.setTransform(
-        Transform.<some_transform>( ... ),
-        { duration : <millisecs>, curve: Easing.<some_curve> }
-    );
-};
-```
-
-the `fview` parameter actually let you access the famous view associated with the template (so feel free to do whatever you wish with it...).
-
-**Warning:** when you specify an animation to be used on `destroy` you must take care of the actual destroy!
-...usually it is enough to call `fview.destroy()` when the animation completes:
-
-```javascript
-var animFunc = function(fview){
-    fview.modifier.setTransform(
-        Transform.<some_transform>( ... ),
-        { duration : <millisecs>, curve: Easing.<some_curve> },
-        function(){ fview.destroy();}
-    );
-};
-```
-
-**Warning2:** At the moment the animation for the state change is supposed to last for double the `setStateDelay` duration, and the state change is actually postponed by `setStateDelay` milliseconds. This let you divide your animation in two different part (so, e.g., you can hide things and show them again with the new content...).
-The following is the default animations used on state change:
-
-```javascript
-vFlip = function(fview){
-    fview.modifier.setTransform(
-        Transform.rotate(Math.PI-0.05,0,0),
-        {
-            duration : AccountsTemplates.animations.setStateDelay,
-            curve: "easeIn",
-        },
-        function() {
-            fview.modifier.setTransform(
-                Transform.rotate(-0.1,0,0),
-                {
-                    duration : AccountsTemplates.animations.setStateDelay,
-                    curve: "easeOut",
-                }
-            );
-        }
-    );
-};
-```
-
-and as you can see schedules two different animations, one after the another, lasting `setStateDelay` ms each.
-
-
-### pushToAnimationQueue
-
-In case you're interested in sequence animation, AT also provides an experimental animation cue you can use to schedule your animation with a bit of delay between them.
-To use it simply wrap the `modifier.setTransform` within an `AccountsTemplates.pushToAnimationQueue` call, like this:
-
-```jacascript
-var fallFromTop = function(fview){
-    fview.modifier.setTransform(Transform.translate(0, -$(window).height()));
-    AccountsTemplates.pushToAnimationQueue(function() {
-        fview.modifier.setTransform(
-            Transform.translate(0,0),
-            { duration : 450, curve: Easing.easeOutSine }
-        );
-    });
-};
-```
-
-the full signature for it is:
-
-```javascript
-AccountsTemplates.pushToAnimationQueue(func, at_begin);
-```
-
-and if pass `true` for `at_begin`, the function will be pushed to the begin of the cue rather than at the end.
-
-The first animation is started after `animQueueStartDelay` milliseconds from the first insertion and a delay of `animQueueStartDelay` milliseconds is applied between start of animations (you can configure these two values with `configureAnimations` function as listed above...).
-
-And that's it!
-Enjoy ;-)
-
-
-<a name="side-notes"/>
-## Side Notes
-
-
-<a name="3rd-party-login-services-configuration"/>
-### 3rd Party Login Services Configuration
-
-Normally, if you have not configured a social account with, e.g.,
-
-```javascript
-// Set up login services
-Meteor.startup(function() {
-    // Add Facebook configuration entry
-    ServiceConfiguration.configurations.update(
-      { "service": "facebook" },
-      {
-        $set: {
-          "appId": "XXXXXXXXXXXXXXX",
-          "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
-        }
-      },
-      { upsert: true }
-    );
-
-    // Add GitHub configuration entry
-    ServiceConfiguration.configurations.update(
-      { "service": "github" },
-      {
-        $set: {
-          "clientId": "XXXXXXXXXXXXXXXXXXXX",
-          "secret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
-        }
-      },
-      { upsert: true }
-    );
-});
-```
-
-3rd party login buttons are not shown. To allow display buttons with, e.g., 'Configure Foobook', simply add the packages `service-configuration` and `accounts-ui` with:
-
-```Shell
-meteor add service-configuration
-meteor add accounts-ui
-```
-
-**Warning**: At the moment the UI for service configuration is not supported and the one provided by `accounts-ui` will be shown!

+ 0 - 353
packages/meteor-useraccounts-core/History.md

@@ -1,353 +0,0 @@
-## Master
-
-## v1.14.2
-
-* [flow-routing] fixed dependency on kadira:flow-router: now using the last non-Meteor@1.3 one
-
-## v1.14.1
-
-* fixed automatic update of weak dependencies on routing packages when publishing new versions
-
-## v1.14.0
-
-* [bulma] *new* `useraccounts:bulma` package to get UI templates styled for [Bulma](http://bulma.io/) (thanks to @dominikmayer)
-* [flow-routing] better error management (merged https://github.com/meteor-useraccounts/flow-routing/pull/23 thanks @stubailo)
-* [flow-routing] added support for FlowRouter 3 (merged https://github.com/meteor-useraccounts/flow-routing/pull/26 thanks @timothyarmes)
-* [foundation-sites] *new* `useraccounts:foundation-sites` package to get UI templates styled for [Foundation for Sites 6](http://foundation.zurb.com/sites.html) (thanks to @venetianthief)
-* [materialize] Added row around recaptcha (thanks @qwIvan)
-* some minor fixed to the Guide
-
-## v1.13.1
-
-* added language support to recaptcha (fixed https://github.com/meteor-useraccounts/core/issues/561 tnx @canesin)
-* fixed validation trigger for select inputs (see discussion within https://github.com/meteor-useraccounts/core/issues/569 tnx @cunneen)
-* change default value for `focusFirstInput` to get it disabled when running on Cordova (see https://github.com/meteor-useraccounts/core/issues/594 tnx @derwaldgeist)
-* fixed regression about reCaptcha reset due to https://github.com/meteor-useraccounts/core/pull/565 (merged https://github.com/meteor-useraccounts/core/pull/597 tnx @jebh)
-
-## v1.13.0
-
-* [mdl] *new* `useraccounts:mdl` package to get UI templates styled for [Material Design Lite](http://www.getmdl.io/) (kudos to @kctang and @liquidautumn, thank you guys!).
-* [flow-routing] added support for React-based layouts (merged https://github.com/meteor-useraccounts/flow-routing/pull/20 tnx @timothyarmes).
-* [materialize] fixed offset problem for fullPageAtForm on medium screens.
-* [materialize] fixed some margins (see https://github.com/meteor-useraccounts/materialize/issues/19).
-* [iron-routing] fixed a problem with route paths (merged https://github.com/meteor-useraccounts/iron-routing/pull/8 tnx @trave7er).
-* [core] updated dependency to softwarerero:accounts-t9n@1.1.7
-* [core] fixed a bug with reCaptcha (merged https://github.com/meteor-useraccounts/core/pull/565 tnx @scsirdx).
-* [core] added missing dependency on JQuery (merged https://github.com/meteor-useraccounts/core/pull/574 tnx @stubailo).
-* [core] added postSignUpHook hook to let people modify newly created user objects (merged https://github.com/meteor-useraccounts/core/pull/586 tnx @shwaydogg)
-* added [Meteor Icon](http://www.getmdl.io/) badges to all packages' README file.
-
-## v1.12.4
-
-* fixed input element classes for `useraccounts:materialize` (see https://github.com/meteor-useraccounts/materialize/pull/18)
-* fixed query parameters look-up for `useraccounts:iron-routing`
-* updated `useraccounts:polymer` to use Polimer 1.0 (see updated [boilerplate](https://github.com/meteor-useraccounts/boilerplates/tree/master/polymer) with some instructions for Meteor 1.2)
-* updates and fixes for `useraccounts:flow-rounting` (see https://github.com/meteor-useraccounts/flow-routing/issues/12)
-* improoved css for `useraccounts:semantic-ui`
-* disallowed use of `signUp` state in case `forbidClientAccountCreation` is set (see #547)
-* updated dependency on softwarerero:accounts-t9n to version 1.1.4
-* a bit of linting here and there...
-* a few typos correction and improvements to the [Guide](https://github.com/meteor-useraccounts/core/blob/master/Guide.md)
-
-## v1.12.3
-
-* fixed radio buttons for useraccounts:materialize (see https://github.com/meteor-useraccounts/core/issues/421)
-* fixed query parameters pick up for useraccounts:iron-routing (see meteor-useraccounts/core#367)
-* corrected few typos within the docs and removed unnecessary debug log
-
-## v1.12.2
-
-* various fixes and a bit of clean up for `useraccounts:flow-routing`
-
-
-## v1.12.1
-
-* fixed inifinite redirect loop for `ensuredSignedIn` within `useraccounts:flow-routing` (see https://github.com/meteor-useraccounts/flow-routing/issues/2)
-
-
-## v1.12.0
-
-* removed routing support from core: refer to [useraccounts:iron-routing](https://github.com/meteor-useraccounts/iron-routing) and [useraccounts:flow-routing](https://github.com/meteor-useraccounts/flow-routing) packages to get some ;-)
-* added template level content protection (see new [Content Protection](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#content-protection) section)
-* updated `useraccounts:semantic-ui` to SUI v2.0 (thanks @lumatijev)
-* `displayName` configuration option for form fields now accepts also functions
-* added the `focusFirstInput` configuration option
-* fixed many typos and added/removed some sections in the Guide
-
-
-## v1.11.1
-
-* fixes for #410, #411, and #413
-* Added a section about available internal states to the Guide (see [Internal States](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#internal-states)
-
-
-## v1.11.0
-
-* change `profile.username` to `profile.name` when using `lowercaseUsername` options (WARNING! this is a bit of a breaking change, see #388)
-* removed possibly annoying warning (see #398)
-* added a `preSignUpHook` to be possibly used to enrich the user profile just before new user registration (see #400)
-* route configuration now accepts additional parameters to be passed to IR (see #409)
-* some improvements to the docs
-
-## v1.10.0
-
-* more customizable texts (see 7d166b74f111e05b22ef2c7d93908441e242350d)
-* added autofocus for the first input field of `atPwdForm`.
-* fixed some texts configuration capability (see #380)
-* various corrections/improvements to the docs
-* allowed for `field.setError` to take in Boolean values (see #361)
-* fixed bug with `Must be logged in` error message shown after sign out (see #321)
-
-## v1.9.1
-
-* aligned `useraccounts:unstyled` with the latest PRs
-
-## v1.9.0
-
-* resend verification email (see #349, thanks @dalgard)
-* allow for a neutral message text to be displayed (see #314 and #317, thanks @dalgard)
-* more configurable error texts (see [Errors Text](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#errors-text), plus #301 #342)
-* fixed little redirect bug (see #315)
-* added title configuration for `verifyEmail` state plus letting titles to be hidden by
-  setting the corresponding text to an empy string (see [Form Title](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#form-title))
-
-## v1.8.1
-
-* made (a fake) `ensureSignedIn` plugin available also on server side code (fixed #291)
-
-## v1.8.0
-
-* added `lowercaseUsername` configuration option (see [Configuration API Options](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#options))
-* added `ensureSignedIn` plugin for Iron Router (see [Content Protection](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#content-protection))
-* fixed `ensureSignedIn` regression (see #286)
-
-## v1.7.1
-
-* fixed routing regression (see #284)
-* removed useless logs
-
-## v1.7.0
-
-* `useraccounts:materialize` to the suite! (Many thanks to @Kestanous!!!)
-* fixed glitch within `ensureSignedIn` (see #278)
-* added experimental support for [reChaptcha](https://www.google.com/recaptcha/intro/index.html) (see #268 and [reCaptcha Setup](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#recaptcha-setup), great work @theplatapi!)
-* new `template` option for deeper input fields customization (see #273 and [Form Fields Configuration](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#form-fields-configuration))
-* prevent access to `atChangePwd` for users not being logged in (see #207)
-* use `Meteor.userID()` in place of `Meteor.user()` where possible to reduce reactive re-computations
-* fixed bug with timed out redirects  (see #263)
-* fixed reactivity bug within `ensureSignedIn` (see #262)
-* removed warning about MAIL_URL not being configured (see #267, #210)
-* better `atNavButton` behaviour (see #265 tnx @adrianmc)
-
-## v1.6.1
-
-* updated deps for iron:router and softwarerero:accounts-t9n to latest versions
-
-## v1.6.0
-
-* moved the documentation to a separate file: [Guide](https://github.com/meteor-useraccounts/core/blob/master/Guide.md)
-* fixed bug about calling `sibmitHook` (see #249 #252 tnx @dalgard)
-* new `options` for field configuration (see #250 and [Extending Templates](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#extending-templates) tnx @dalgard)
-* a bit of cleanup for docs (see #251 tnx @dalgard)
-* capitalazed default value for display name and placeholder (see #247)
-* switch to official `Accounts._hasPassword` (see [this](https://github.com/meteor/meteor/pull/2271) and [this](https://github.com/meteor/meteor/pull/3410), tnx @glasser)
-* more sites using useraccounts: congrats to @nate-strauser and @msamoylov on their launches! (see [the list](https://github.com/meteor-useraccounts/core#whos-using-this))
-* new landing page for the whole project and new live examples (still to be further improoved...) :) (see [useraccounts.meteor.com](https://useraccounts.meteor.com))
-* added `transform` among the options for [field configuration](https://github.com/meteor-useraccounts/core/blob/master/Guide.md#form-fields-configuration)
-* better behaviour for input value tranform/fix
-* terms and agreements now showed also on enrollment form (see #253)
-* link to singIn now shown also on forgot password form in case `forbidClientAccountCreation` is set to true (partial solution to #229)
-* moved terms and agreements link right after the submit button (see #239)
-
-## v1.5.0
-
-* added `useraccounts:polymer` to the suite! (WIP, Thanks @kevohagan!!!)
-* fixed a bug with atVerifyEmail route (see #241 and #173)
-* little docs improovements
-
-## v1.4.1
-
-* updated dependency to softwarerero:accounts-t9n@1.0.5 to include Turkish language
-* fixed `{{> atForm state='<state>'}}` which was no more working with Meteor@1.0.2 (see #217)
-* fixed some text configuration (see #209, thanks @bumbleblym)
-* fixed some typos into the docs (see #208, thanks @bumbleblym)
-
-## v1.4.0
-
-* added `useraccounts:ionic` to the suite! (Thanks @nickw!!!)
-* updated `useraccounts:semantic-ui` to SemanticUI@1.0.0 (Thanks @lumatijev!!!)
-* added `onLogoutHook` to be able to run code (custom redirects?) on `AccountsTemplates.logout` (see #191)
-* added `onSubmitHook` among configuration parameters to be able to run code on form submission (might be useful for modals! see #201 and #180)
-* submission button get now disabled also during fields (asynchronous) validation
-* `enforceEmailVerification` now works also with username login (fixed #196)
-* better IE compatibility (see #199)
-* better input field validation flows to recover from previous errors (see #177)
-* updated dependency to softwarerero:accounts-t9n@1.0.4
-* new [Contributing section](https://github.com/meteor-useraccounts/core#contributing) among docs
-* a few improvements and typo fixes for README.md
-
-## v1.3.2 / 2014/11/25
-
-* more robust logout pattern when dealing with routes protected with ensureSigndIn
-
-## v1.3.1 / 2014/11/25
-
-* updated dependency to iron:router@1.0.3
-* fixed bug in linkClick (see #170)
-* fixed bug in configureRoute
-
-## v1.3.0 / 2014/11/23
-
-* added support for [Ratchet](http://goratchet.com/): see [useraccounts:ratchet](https://atmospherejs.com/useraccounts/ratchet). Note: form validation is currently not supported by Ratchet!
-* fixed bug in custom validation flow
-* better default validation for `email` field (see #156)
-* few corrections inside docs
-* added `ensuredSignedIn` among configurable routes so that different `template` and `layoutTemplate` can be specified (fix for #160 and #98)
-* added `socialLoginStyle` among the configuration options to select the login flow (`popup` or `redirect`) for 3rd party login services (see #163)
-* fixed bug about fields ordering
-
-## v1.2.3 / 2014/11/13
-
-* put back in a `init` method dispalying a warning to preserve backward compatibility...
-
-## v1.2.2 / 2014/11/12
-
-* fixed bad redirect for cheange password route (see #154)
-
-## v1.2.1 / 2014/11/12
-
-* fixed regression due reactivity problems after fix for #139
-
-## v1.2.0 / 2014/11/12
-
-* **breaking change:** removed the need to call `Accounts.init()`
-* added support for fields' validating state to display a 'loading' icon
-* added support for fields' icon configuration
-* added support for social buttons' icon configuration (see [this](https://github.com/meteor-useraccounts/core#social-button-icons) new section)
-* added support for `meteor-developer` oauth service (see #147)
-* fixed (special) fields ordering, see #144
-* fixed ensureSignedIn (see #152)
-* removed `new_password` and `new_password_again` special fields, simply use `password` and `password_again` from now on!
-* better redirect behaviour when a logged in user lands on a sign-in/sign-up page: usual redirect is now performed. (see #139)
-* better field validation patterns...
-* updated dependency to irou:router@1.0.1
-* updated dependency to softwarerero:accounts-t9n@1.0.2
-* corrected many errors and typos inside the Documentation
-
-## v1.1.1
-## v1.1.0
-
-* fixed  `atNavButton` for useraccounts:unstyled
-* fixed variour names and links in README files
-
-## v1.1.0
-
-* new template `atNavButton`
-* added methos `AccountsTemplates.logout()` which redirects back to `homeRoutePath` when configured
-* support for hidden fields
-* url query parameters loaded into input fields -> useful mostly for hidden fields ;-)
-* granted full control over field ordering (except for special fields...). see #135
-* fixes for #130, #132
-
-## v1.0.1
-
-* fixed link to git repositories inside package.js files
-
-## v1.0.0
-
-* new names: no more splendido:accounts-templates:<somethig> but useraccounts:<somethig> !
-* updated iron:router to v1.0.0
-
-## v0.11.0
-
-* added support for checkbox, select, and radio inputs
-* added defaultState as referred in #125
-* fixes for #127
-
-## v0.10.0
-
-* better texts configuration API (as for #117)
-* prevPath fix
-
-
-## v0.9.16
-
-* updated iron:router to v0.9.4
-
-## v0.9.15
-
-* fixed #110
-
-## v0.9.14
-
-* fixed some redirection problems connected with `ensureSignedIn`
-
-## v0.9.13
-
-* experimental implementation for forbidding access with unverified email (see #108) through configuration flag `enforceEmailVerification`
-* added options to hide links: hideSignInLink, hideSignUpLink
-* fixed #107
-
-## v0.9.12
-
-* fixed #109
-
-## v0.9.11
-
-* better submit button disabling when no negative feedback is used
-* fixed #105
-
-## v0.9.10
-
-* added `defaultLayout` to configuration options
-* new callback parameter to `setState`
-* better rendering behaviour on `ensureSignedIn`
-
-## v0.9.9
-
-* Fixed links for `reset-password`, `enroll-account`, and `verify-email`
-
-## v0.9.8
-
-* fixed checks for login services (see #93)
-* minor updates to docs
-
-## v0.9.7
-
-* fixed #92, to permit the use of, e.g., `{{> atForm state="changePwd"}}` ( see [docs](https://github.com/splendido/accounts-templates-core#templates))
-
-## v0.9.6
-
-* fixed #91, pwdForm submission on signin page has no effect unless both password and usename/email are not empty
-
-## v0.9.5
-
-* show title on sign in also with other services
-* moved sign in link below pwd form
-* removed sign in link from forgot-pwd page (sign up link is still there!)
-* added class at-btn to submit button
-* added class at-signin to sign in link
-* added class at-signup to sign up link
-* added class at-pwd to forgot password link
-* accounts-t9n dependency updated to @1.0.0
-
-## v0.9.4
-
-
-## Older versions (to be written)
-
-* Fixes for #19, #24, #25, #26
-* layoutTemplate option
-* Better signup flow, with proper server side validation!
-* Fixes for #15, and #16
-* Do not show validation errors during sign in
-* Do not show sign up link when account creation is disabled
-* Better use of UnderscoreJS
-* Corrected documentation for showAddRemoveServices
-
-## v0.0.9
-
-* added configuration parameter [`showAddRemoveServices`](https://github.com/splendido/accounts-templates-core#appearance)
-* Fix ensureSignedIn for drawing correct template
-
-## v0.0.8

+ 0 - 20
packages/meteor-useraccounts-core/LICENSE.md

@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 [@splendido](https://github.com/splendido)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0 - 104
packages/meteor-useraccounts-core/README.md

@@ -1,104 +0,0 @@
-[![Meteor Icon](http://icon.meteor.com/package/useraccounts:core)](https://atmospherejs.com/useraccounts/core)
-[![Build Status](https://travis-ci.org/meteor-useraccounts/core.svg?branch=master)](https://travis-ci.org/meteor-useraccounts/core)
-
-# User Accounts
-
-User Accounts is a suite of packages for the [Meteor.js](https://www.meteor.com/) platform. It provides highly customizable user accounts UI templates for many different front-end frameworks. At the moment it includes forms for sign in, sign up, forgot password, reset password, change password, enroll account, and link or remove of many 3rd party services.
-
-## Some Details
-
-The package `useraccounts:core` contains all the core logic and templates' helpers and events used by dependant packages providing styled versions of the accounts UI.
-This means that developing a version of the UI with a different styling is just a matter of writing a few dozen of html lines, nothing more!
-
-Thanks to [accounts-t9n](https://github.com/softwarerero/meteor-accounts-t9n) you can switch to your preferred language on the fly! Available languages are now: Arabic, Czech, French, German, Italian, Polish, Portuguese, Russian, Slovenian, Spanish, Swedish, Turkish and Vietnamese.
-
-For basic routing and content protection, `useraccounts:core` integrates with either [flow-router](https://github.com/meteor-useraccounts/flow-routing) or [iron-router](https://atmospherejs.com/package/iron-router).
-
-Any comments, suggestions, testing efforts, and PRs are very very welcome! Please use the [repository](https://github.com/meteor-useraccounts/ui) issues tracker for reporting bugs, problems, ideas, discussions, etc..
-
-## The UserAccounts Guide
-Detailed explanations of features and configuration options can be found in the <a href="https://github.com/meteor-useraccounts/core/blob/master/Guide.md" target="_blank">Guide</a>.
-
-## Who's using this?
-
-* [Abesea](https://abesea.com/)
-* [backspace.academy](http://backspace.academy/)
-* [bootstrappers.io](http://www.bootstrappers.io/)
-* [crater.io](http://crater.io/)
-* [Dechiper Chinese](http://app.decipherchinese.com/)
-* [Henfood](http://labs.henesis.eu/henfood)
-* [meteorgigs.io](https://www.meteorgigs.io/)
-* [Orion](http://orionjs.org/)
-* [Telescope](http://www.telesc.pe/)
-* [We Work Meteor](http://www.weworkmeteor.com/)
-
-
-Aren't you on the list?!
-If you have a production app using accounts templates, let me know! I'd like to add your link to the above ones.
-
-## Contributing
-Contributors are very welcome. There are many things you can help with,
-including finding and fixing bugs and creating examples for the brand new [wiki](https://github.com/meteor-useraccounts/wiki).
-We're also working on `useraccounts@2.0` (see the [Milestone](https://github.com/meteor-useraccounts/core/milestones)) so you can also help
-with an improved design or adding features.
-
-Some guidelines below:
-
-* **Questions**: Please create a new issue and label it as a `question`.
-
-* **New Features**: If you'd like to work on a feature,
-  start by creating a 'Feature Design: Title' issue. This will let people bat it
-  around a bit before you send a full blown pull request. Also, you can create
-  an issue to discuss a design even if you won't be working on it.
-
-* **Bugs**: If you think you found a bug, please create a "reproduction." This is a small project that demonstrates the problem as concisely as possible. If you think the bug can be reproduced with only a few steps a description by words might be enough though. The project should be cloneable from Github. Any bug reports without a reproduction that don't have an obvious solution will be marked as "awaiting-reproduction" and closed after a bit of time.
-
-###  Working Locally
-This is useful if you're contributing code to useraccounts or just trying to modify something to suit your own specific needs.
-
-##### Scenario A
-
-1. Set up a local packages folder
-2. Add the PACKAGE_DIRS environment variable to your .bashrc file
-  - Example: `export PACKAGE_DIRS="/full/path/topackages/folder"`
-  - Screencast: https://www.eventedmind.com/posts/meteor-versioning-and-packages
-3. Clone the repository into your local packages directory
-4. Add the package just like any other meteor core package like this: `meteor
-   add useraccounts:unstyled`
-
-```bash
-> cd /full/path/topackages/folder
-> git clone https://github.com/meteor-useraccounts/semantic-ui.git
-> cd your/project/path
-> meteor add useraccounts:semantic-ui
-> meteor
-```
-
-##### Scenario B
-
-Like Scenario A, but skipping point 2.
-Add the official package as usual with `meteor add useraccounts:semantic-ui` but then run your project like this:
-
-```bash
-> PACKAGE_DIRS="/full/path/topackages/folder" meteor
-```
-
-##### Scenario C
-
-```bash
-> cd your/project/path
-> mkdir packages && cd packages
-> git clone https://github.com/meteor-useraccounts/semantic-ui.git
-> cd ..
-> meteor add useraccounts:semantic-ui
-> meteor
-```
-
-
-## Thanks
-
-Anyone is welcome to contribute. Fork, make your changes, and then submit a pull request.
-
-Thanks to [all those who have contributed code changes](https://github.com/meteor-useraccounts/ui/graphs/contributors) and all who have helped by submitting bug reports and feature ideas.
-
-[![Support via Gittip](https://rawgithub.com/twolfson/gittip-badge/0.2.0/dist/gittip.png)](https://www.gittip.com/splendido/)

+ 0 - 464
packages/meteor-useraccounts-core/lib/client.js

@@ -1,464 +0,0 @@
-/* global
-  AT: false
-*/
-"use strict";
-
-// Allowed Internal (client-side) States
-AT.prototype.STATES = [
-  "changePwd", // Change Password
-  "enrollAccount", // Account Enrollment
-  "forgotPwd", // Forgot Password
-  "hide", // Nothing displayed
-  "resetPwd", // Reset Password
-  "signIn", // Sign In
-  "signUp", // Sign Up
-  "verifyEmail", // Email verification
-  "resendVerificationEmail", // Resend verification email
-];
-
-AT.prototype._loginType = "";
-
-// Flag telling whether the whole form should appear disabled
-AT.prototype._disabled = false;
-
-// State validation
-AT.prototype._isValidState = function(value) {
-  return _.contains(this.STATES, value);
-};
-
-// Flags used to avoid clearing errors and redirecting to previous route when
-// signing in/up as a results of a call to ensureSignedIn
-AT.prototype.avoidRedirect = false;
-AT.prototype.avoidClearError = false;
-
-// Token to be provided for routes like reset-password and enroll-account
-AT.prototype.paramToken = null;
-
-AT.prototype.loginType = function () {
-  return this._loginType;
-};
-
-AT.prototype.getparamToken = function() {
-  return this.paramToken;
-};
-
-// Getter for current state
-AT.prototype.getState = function() {
-  return this.state.form.get("state");
-};
-
-// Getter for disabled state
-AT.prototype.disabled = function() {
-  return this.state.form.equals("disabled", true) ? "disabled" : undefined;
-};
-
-// Setter for disabled state
-AT.prototype.setDisabled = function(value) {
-  check(value, Boolean);
-  return this.state.form.set("disabled", value);
-};
-
-// Setter for current state
-AT.prototype.setState = function(state, callback) {
-  check(state, String);
-
-  if (!this._isValidState(state) || (this.options.forbidClientAccountCreation && state === 'signUp')) {
-    throw new Meteor.Error(500, "Internal server error", "accounts-templates-core package got an invalid state value!");
-  }
-
-  this.state.form.set("state", state);
-  if (!this.avoidClearError) {
-    this.clearState();
-  }
-  this.avoidClearError = false;
-
-  if (_.isFunction(callback)) {
-    callback();
-  }
-};
-
-AT.prototype.clearState = function() {
-  _.each(this._fields, function(field) {
-    field.clearStatus();
-  });
-
-  var form = this.state.form;
-
-  form.set("error", null);
-  form.set("result", null);
-  form.set("message", null);
-
-  AccountsTemplates.setDisabled(false);
-};
-
-AT.prototype.clearError = function() {
-  this.state.form.set("error", null);
-};
-
-AT.prototype.clearResult = function() {
-  this.state.form.set("result", null);
-};
-
-AT.prototype.clearMessage = function() {
-  this.state.form.set("message", null);
-};
-
-// Initialization
-AT.prototype.init = function() {
-  console.warn("[AccountsTemplates] There is no more need to call AccountsTemplates.init()! Simply remove the call ;-)");
-};
-
-AT.prototype._init = function() {
-  if (this._initialized) {
-    return;
-  }
-
-  var usernamePresent = this.hasField("username");
-  var emailPresent = this.hasField("email");
-
-  if (usernamePresent && emailPresent) {
-    this._loginType = "username_and_email";
-  } else {
-    this._loginType = usernamePresent ? "username" : "email";
-  }
-
-  if (this._loginType === "username_and_email") {
-    // Possibly adds the field username_and_email in case
-    // it was not configured
-    if (!this.hasField("username_and_email")) {
-      this.addField({
-        _id: "username_and_email",
-        type: "text",
-        displayName: "usernameOrEmail",
-        placeholder: "usernameOrEmail",
-        required: true,
-      });
-    }
-  }
-
-  // Only in case password confirmation is required
-  if (this.options.confirmPassword) {
-    // Possibly adds the field password_again in case
-    // it was not configured
-    if (!this.hasField("password_again")) {
-      var pwdAgain = _.clone(this.getField("password"));
-
-      pwdAgain._id = "password_again";
-      pwdAgain.displayName = {
-        "default": "passwordAgain",
-        changePwd: "newPasswordAgain",
-        resetPwd: "newPasswordAgain",
-      };
-      pwdAgain.placeholder = {
-        "default": "passwordAgain",
-        changePwd: "newPasswordAgain",
-        resetPwd: "newPasswordAgain",
-      };
-      this.addField(pwdAgain);
-    }
-  } else {
-    if (this.hasField("password_again")) {
-      throw new Error("AccountsTemplates: a field password_again was added but confirmPassword is set to false!");
-    }
-  }
-
-  // Possibly adds the field current_password in case
-  // it was not configured
-  if (this.options.enablePasswordChange) {
-    if (!this.hasField("current_password")) {
-      this.addField({
-        _id: "current_password",
-        type: "password",
-        displayName: "currentPassword",
-        placeholder: "currentPassword",
-        required: true,
-      });
-    }
-  }
-
-  // Ensuser the right order of special fields
-  var moveFieldAfter = function(fieldName, referenceFieldName) {
-    var fieldIds = AccountsTemplates.getFieldIds();
-    var refFieldId = _.indexOf(fieldIds, referenceFieldName);
-    // In case the reference field is not present, just return...
-    if (refFieldId === -1) {
-      return;
-    }
-
-    var fieldId = _.indexOf(fieldIds, fieldName);
-    // In case the sought field is not present, just return...
-    if (fieldId === -1) {
-      return;
-    }
-
-    if (fieldId !== -1 && fieldId !== (refFieldId + 1)) {
-      // removes the field
-      var field = AccountsTemplates._fields.splice(fieldId, 1)[0];
-      // push the field right after the reference field position
-      var newFieldIds = AccountsTemplates.getFieldIds();
-      var newReferenceFieldId = _.indexOf(newFieldIds, referenceFieldName);
-      AccountsTemplates._fields.splice(newReferenceFieldId + 1, 0, field);
-    }
-  };
-
-  // Ensuser the right order of special fields
-  var moveFieldBefore = function(fieldName, referenceFieldName) {
-    var fieldIds = AccountsTemplates.getFieldIds();
-    var refFieldId = _.indexOf(fieldIds, referenceFieldName);
-    // In case the reference field is not present, just return...
-    if (refFieldId === -1) {
-      return;
-    }
-
-    var fieldId = _.indexOf(fieldIds, fieldName);
-    // In case the sought field is not present, just return...
-    if (fieldId === -1) {
-      return;
-    }
-
-    if (fieldId !== -1 && fieldId !== (refFieldId - 1)) {
-      // removes the field
-      var field = AccountsTemplates._fields.splice(fieldId, 1)[0];
-      // push the field right after the reference field position
-      var newFieldIds = AccountsTemplates.getFieldIds();
-      var newReferenceFieldId = _.indexOf(newFieldIds, referenceFieldName);
-      AccountsTemplates._fields.splice(newReferenceFieldId, 0, field);
-    }
-  };
-
-  // The final order should be something like:
-  // - username
-  // - email
-  // - username_and_email
-  // - password
-  // - password_again
-  //
-  // ...so lets do it in reverse order...
-  moveFieldAfter("username_and_email", "username");
-  moveFieldAfter("username_and_email", "email");
-  moveFieldBefore("current_password", "password");
-  moveFieldAfter("password", "current_password");
-  moveFieldAfter("password_again", "password");
-
-
-  // Sets visibility condition and validation flags for each field
-  var gPositiveValidation = !!AccountsTemplates.options.positiveValidation;
-  var gNegativeValidation = !!AccountsTemplates.options.negativeValidation;
-  var gShowValidating = !!AccountsTemplates.options.showValidating;
-  var gContinuousValidation = !!AccountsTemplates.options.continuousValidation;
-  var gNegativeFeedback = !!AccountsTemplates.options.negativeFeedback;
-  var gPositiveFeedback = !!AccountsTemplates.options.positiveFeedback;
-
-  _.each(this._fields, function(field) {
-    // Visibility
-    switch(field._id) {
-      case "current_password":
-        field.visible = ["changePwd"];
-        break;
-      case "email":
-        field.visible = ["forgotPwd", "signUp", "resendVerificationEmail"];
-        if (AccountsTemplates.loginType() === "email") {
-          field.visible.push("signIn");
-        }
-        break;
-      case "password":
-        field.visible = ["changePwd", "enrollAccount", "resetPwd", "signIn", "signUp"];
-        break;
-      case "password_again":
-        field.visible = ["changePwd", "enrollAccount", "resetPwd", "signUp"];
-        break;
-      case "username":
-        field.visible = ["signUp"];
-        if (AccountsTemplates.loginType() === "username") {
-          field.visible.push("signIn");
-        }
-        break;
-      case "username_and_email":
-        field.visible = [];
-        if (AccountsTemplates.loginType() === "username_and_email") {
-          field.visible.push("signIn");
-        }
-        break;
-      default:
-        field.visible = ["signUp"];
-    }
-
-      // Validation
-      var positiveValidation = field.positiveValidation;
-      if (_.isUndefined(positiveValidation)) {
-        field.positiveValidation = gPositiveValidation;
-      }
-
-      var negativeValidation = field.negativeValidation;
-      if (_.isUndefined(negativeValidation)) {
-        field.negativeValidation = gNegativeValidation;
-      }
-
-      field.validation = field.positiveValidation || field.negativeValidation;
-      if (_.isUndefined(field.continuousValidation)) {
-        field.continuousValidation = gContinuousValidation;
-      }
-
-      field.continuousValidation = field.validation && field.continuousValidation;
-      if (_.isUndefined(field.negativeFeedback)) {
-        field.negativeFeedback = gNegativeFeedback;
-      }
-
-      if (_.isUndefined(field.positiveFeedback)) {
-        field.positiveFeedback = gPositiveFeedback;
-      }
-
-      field.feedback = field.negativeFeedback || field.positiveFeedback;
-      // Validating icon
-      var showValidating = field.showValidating;
-      if (_.isUndefined(showValidating)) {
-        field.showValidating = gShowValidating;
-      }
-
-      // Custom Template
-      if (field.template) {
-        if (field.template in Template) {
-          Template[field.template].helpers(AccountsTemplates.atInputHelpers);
-        } else {
-          console.warn(
-            "[UserAccounts] Warning no template " + field.template + " found!"
-          );
-        }
-      }
-  });
-
-  // Initializes reactive states
-  var form = new ReactiveDict();
-
-  form.set("disabled", false);
-  form.set("state", "signIn");
-  form.set("result", null);
-  form.set("error", null);
-  form.set("message", null);
-  this.state = {
-    form: form,
-  };
-
-  // Possibly subscribes to extended user data (to get the list of registered services...)
-  if (this.options.showAddRemoveServices) {
-      Meteor.subscribe("userRegisteredServices");
-  }
-
-  //Check that reCaptcha site keys are available and no secret keys visible
-  if (this.options.showReCaptcha) {
-    var atSiteKey = null;
-    var atSecretKey = null;
-    var settingsSiteKey = null;
-    var settingsSecretKey = null;
-
-    if (AccountsTemplates.options.reCaptcha) {
-      atSiteKey = AccountsTemplates.options.reCaptcha.siteKey;
-      atSecretKey = AccountsTemplates.options.reCaptcha.secretKey;
-    }
-
-    if (Meteor.settings && Meteor.settings.public && Meteor.settings.public.reCaptcha) {
-      settingsSiteKey = Meteor.settings.public.reCaptcha.siteKey;
-      settingsSecretKey = Meteor.settings.public.reCaptcha.secretKey;
-    }
-
-    if (atSecretKey || settingsSecretKey) {
-      //erase the secret key
-      if (atSecretKey) {
-          AccountsTemplates.options.reCaptcha.secretKey = null;
-      }
-
-      if (settingsSecretKey) {
-          Meteor.settings.public.reCaptcha.secretKey = null;
-      }
-
-      var loc = atSecretKey ? "User Accounts configuration!" : "Meteor settings!";
-      throw new Meteor.Error(401, "User Accounts: DANGER - reCaptcha private key leaked to client from " + loc
-      + " Provide the key in server settings ONLY.");
-    }
-
-    if (!atSiteKey && !settingsSiteKey) {
-      throw new Meteor.Error(401, "User Accounts: reCaptcha site key not found! Please provide it or set showReCaptcha to false.");
-    }
-  }
-
-  // Marks AccountsTemplates as initialized
-  this._initialized = true;
-};
-
-AT.prototype.linkClick = function(route) {
-  if (AccountsTemplates.disabled()) {
-    return;
-  }
-
-  AccountsTemplates.setState(route);
-
-  if (AccountsTemplates.options.focusFirstInput) {
-    var firstVisibleInput = _.find(this.getFields(), function(f) {
-      return _.contains(f.visible, route);
-    });
-
-    if (firstVisibleInput) {
-      $("input#at-field-" + firstVisibleInput._id).focus();
-    }
-  }
-};
-
-AT.prototype.logout = function() {
-  var onLogoutHook = AccountsTemplates.options.onLogoutHook;
-
-  Meteor.logout(function() {
-    if (onLogoutHook) {
-      onLogoutHook();
-    }
-  });
-};
-
-AT.prototype.submitCallback = function(error, state, onSuccess) {
-  var onSubmitHook = AccountsTemplates.options.onSubmitHook;
-
-  if (onSubmitHook) {
-    onSubmitHook(error, state);
-  }
-
-  if (error) {
-    if (_.isObject(error.details)) {
-      // If error.details is an object, we may try to set fields errors from it
-      _.each(error.details, function(error, fieldId) {
-          AccountsTemplates.getField(fieldId).setError(error);
-      });
-    } else {
-      var err = "error.accounts.Unknown error";
-
-      if (error.reason) {
-        err = error.reason;
-      }
-
-      if (err.substring(0, 15) !== "error.accounts.") {
-        err = "error.accounts." + err;
-      }
-
-      AccountsTemplates.state.form.set("error", [err]);
-    }
-
-    AccountsTemplates.setDisabled(false);
-    // Possibly resets reCaptcha form
-    if (state === "signUp" && AccountsTemplates.options.showReCaptcha) {
-      grecaptcha.reset();
-    }
-  } else {
-    if (onSuccess) {
-      onSuccess();
-    }
-
-    if (state) {
-      AccountsTemplates.setDisabled(false);
-    }
-  }
-};
-
-AccountsTemplates = new AT();
-
-// Initialization
-Meteor.startup(function() {
-  AccountsTemplates._init();
-});

+ 0 - 593
packages/meteor-useraccounts-core/lib/core.js

@@ -1,593 +0,0 @@
-// ---------------------------------------------------------------------------------
-// Patterns for methods" parameters
-// ---------------------------------------------------------------------------------
-
-STATE_PAT = {
-  changePwd: Match.Optional(String),
-  enrollAccount: Match.Optional(String),
-  forgotPwd: Match.Optional(String),
-  resetPwd: Match.Optional(String),
-  signIn: Match.Optional(String),
-  signUp: Match.Optional(String),
-  verifyEmail: Match.Optional(String),
-  resendVerificationEmail: Match.Optional(String),
-};
-
-ERRORS_PAT = {
-  accountsCreationDisabled: Match.Optional(String),
-  cannotRemoveService: Match.Optional(String),
-  captchaVerification: Match.Optional(String),
-  loginForbidden: Match.Optional(String),
-  mustBeLoggedIn: Match.Optional(String),
-  pwdMismatch: Match.Optional(String),
-  validationErrors: Match.Optional(String),
-  verifyEmailFirst: Match.Optional(String),
-};
-
-INFO_PAT = {
-  emailSent: Match.Optional(String),
-  emailVerified: Match.Optional(String),
-  pwdChanged: Match.Optional(String),
-  pwdReset: Match.Optional(String),
-  pwdSet: Match.Optional(String),
-  signUpVerifyEmail: Match.Optional(String),
-  verificationEmailSent: Match.Optional(String),
-};
-
-INPUT_ICONS_PAT = {
-  hasError: Match.Optional(String),
-  hasSuccess: Match.Optional(String),
-  isValidating: Match.Optional(String),
-};
-
-ObjWithStringValues = Match.Where(function (x) {
-  check(x, Object);
-  _.each(_.values(x), function(value) {
-      check(value, String);
-  });
-  return true;
-});
-
-TEXTS_PAT = {
-  button: Match.Optional(STATE_PAT),
-  errors: Match.Optional(ERRORS_PAT),
-  info: Match.Optional(INFO_PAT),
-  inputIcons: Match.Optional(INPUT_ICONS_PAT),
-  maxAllowedLength: Match.Optional(String),
-  minRequiredLength: Match.Optional(String),
-  navSignIn: Match.Optional(String),
-  navSignOut: Match.Optional(String),
-  optionalField: Match.Optional(String),
-  pwdLink_link: Match.Optional(String),
-  pwdLink_pre: Match.Optional(String),
-  pwdLink_suff: Match.Optional(String),
-  requiredField: Match.Optional(String),
-  resendVerificationEmailLink_pre: Match.Optional(String),
-  resendVerificationEmailLink_link: Match.Optional(String),
-  resendVerificationEmailLink_suff: Match.Optional(String),
-  sep: Match.Optional(String),
-  signInLink_link: Match.Optional(String),
-  signInLink_pre: Match.Optional(String),
-  signInLink_suff: Match.Optional(String),
-  signUpLink_link: Match.Optional(String),
-  signUpLink_pre: Match.Optional(String),
-  signUpLink_suff: Match.Optional(String),
-  socialAdd: Match.Optional(String),
-  socialConfigure: Match.Optional(String),
-  socialIcons: Match.Optional(ObjWithStringValues),
-  socialRemove: Match.Optional(String),
-  socialSignIn: Match.Optional(String),
-  socialSignUp: Match.Optional(String),
-  socialWith: Match.Optional(String),
-  termsAnd: Match.Optional(String),
-  termsPreamble: Match.Optional(String),
-  termsPrivacy: Match.Optional(String),
-  termsTerms: Match.Optional(String),
-  title: Match.Optional(STATE_PAT),
-};
-
-// Configuration pattern to be checked with check
-CONFIG_PAT = {
-  // Behaviour
-  confirmPassword: Match.Optional(Boolean),
-  defaultState: Match.Optional(String),
-  enablePasswordChange: Match.Optional(Boolean),
-  enforceEmailVerification: Match.Optional(Boolean),
-  focusFirstInput: Match.Optional(Boolean),
-  forbidClientAccountCreation: Match.Optional(Boolean),
-  lowercaseUsername: Match.Optional(Boolean),
-  overrideLoginErrors: Match.Optional(Boolean),
-  sendVerificationEmail: Match.Optional(Boolean),
-  socialLoginStyle: Match.Optional(Match.OneOf("popup", "redirect")),
-
-  // Appearance
-  defaultLayout: Match.Optional(String),
-  hideSignInLink: Match.Optional(Boolean),
-  hideSignUpLink: Match.Optional(Boolean),
-  showAddRemoveServices: Match.Optional(Boolean),
-  showForgotPasswordLink: Match.Optional(Boolean),
-  showResendVerificationEmailLink: Match.Optional(Boolean),
-  showLabels: Match.Optional(Boolean),
-  showPlaceholders: Match.Optional(Boolean),
-
-  // Client-side Validation
-  continuousValidation: Match.Optional(Boolean),
-  negativeFeedback: Match.Optional(Boolean),
-  negativeValidation: Match.Optional(Boolean),
-  positiveFeedback: Match.Optional(Boolean),
-  positiveValidation: Match.Optional(Boolean),
-  showValidating: Match.Optional(Boolean),
-
-  // Privacy Policy and Terms of Use
-  privacyUrl: Match.Optional(String),
-  termsUrl: Match.Optional(String),
-
-  // Redirects
-  homeRoutePath: Match.Optional(String),
-  redirectTimeout: Match.Optional(Number),
-
-  // Hooks
-  onLogoutHook: Match.Optional(Function),
-  onSubmitHook: Match.Optional(Function),
-  preSignUpHook: Match.Optional(Function),
-  postSignUpHook: Match.Optional(Function),
-
-  texts: Match.Optional(TEXTS_PAT),
-
-  //reCaptcha config
-  reCaptcha: Match.Optional({
-    data_type: Match.Optional(Match.OneOf("audio", "image")),
-    secretKey: Match.Optional(String),
-    siteKey: Match.Optional(String),
-    theme: Match.Optional(Match.OneOf("dark", "light")),
-  }),
-
-  showReCaptcha: Match.Optional(Boolean),
-};
-
-
-FIELD_SUB_PAT = {
-  "default": Match.Optional(String),
-  changePwd: Match.Optional(String),
-  enrollAccount: Match.Optional(String),
-  forgotPwd: Match.Optional(String),
-  resetPwd: Match.Optional(String),
-  signIn: Match.Optional(String),
-  signUp: Match.Optional(String),
-};
-
-
-// Field pattern
-FIELD_PAT = {
-  _id: String,
-  type: String,
-  required: Match.Optional(Boolean),
-  displayName: Match.Optional(Match.OneOf(String, Match.Where(_.isFunction), FIELD_SUB_PAT)),
-  placeholder: Match.Optional(Match.OneOf(String, FIELD_SUB_PAT)),
-  select: Match.Optional([{text: String, value: Match.Any}]),
-  minLength: Match.Optional(Match.Integer),
-  maxLength: Match.Optional(Match.Integer),
-  re: Match.Optional(RegExp),
-  func: Match.Optional(Match.Where(_.isFunction)),
-  errStr: Match.Optional(String),
-
-  // Client-side Validation
-  continuousValidation: Match.Optional(Boolean),
-  negativeFeedback: Match.Optional(Boolean),
-  negativeValidation: Match.Optional(Boolean),
-  positiveValidation: Match.Optional(Boolean),
-  positiveFeedback: Match.Optional(Boolean),
-
-  // Transforms
-  trim: Match.Optional(Boolean),
-  lowercase: Match.Optional(Boolean),
-  uppercase: Match.Optional(Boolean),
-  transform: Match.Optional(Match.Where(_.isFunction)),
-
-  // Custom options
-  options: Match.Optional(Object),
-  template: Match.Optional(String),
-};
-
-// -----------------------------------------------------------------------------
-// AccountsTemplates object
-// -----------------------------------------------------------------------------
-
-// -------------------
-// Client/Server stuff
-// -------------------
-
-// Constructor
-AT = function() {
-
-};
-
-AT.prototype.CONFIG_PAT = CONFIG_PAT;
-
-/*
-  Each field object is represented by the following properties:
-    _id:         String   (required)  // A unique field"s id / name
-    type:        String   (required)  // Displayed input type
-    required:    Boolean  (optional)  // Specifies Whether to fail or not when field is left empty
-    displayName: String   (optional)  // The field"s name to be displayed as a label above the input element
-    placeholder: String   (optional)  // The placeholder text to be displayed inside the input element
-    minLength:   Integer  (optional)  // Possibly specifies the minimum allowed length
-    maxLength:   Integer  (optional)  // Possibly specifies the maximum allowed length
-    re:          RegExp   (optional)  // Regular expression for validation
-    func:        Function (optional)  // Custom function for validation
-    errStr:      String   (optional)  // Error message to be displayed in case re validation fails
-*/
-
-
-// Allowed input types
-AT.prototype.INPUT_TYPES = [
-  "checkbox",
-  "email",
-  "hidden",
-  "password",
-  "radio",
-  "select",
-  "tel",
-  "text",
-  "url",
-];
-
-// Current configuration values
-AT.prototype.options = {
-  // Appearance
-  //defaultLayout: undefined,
-  showAddRemoveServices: false,
-  showForgotPasswordLink: false,
-  showResendVerificationEmailLink: false,
-  showLabels: true,
-  showPlaceholders: true,
-
-  // Behaviour
-  confirmPassword: true,
-  defaultState: "signIn",
-  enablePasswordChange: false,
-  focusFirstInput: !Meteor.isCordova,
-  forbidClientAccountCreation: false,
-  lowercaseUsername: false,
-  overrideLoginErrors: true,
-  sendVerificationEmail: false,
-  socialLoginStyle: "popup",
-
-  // Client-side Validation
-  //continuousValidation: false,
-  //negativeFeedback: false,
-  //negativeValidation: false,
-  //positiveValidation: false,
-  //positiveFeedback: false,
-  //showValidating: false,
-
-  // Privacy Policy and Terms of Use
-  privacyUrl: undefined,
-  termsUrl: undefined,
-
-  // Hooks
-  onSubmitHook: undefined,
-};
-
-AT.prototype.texts = {
-  button: {
-    changePwd: "updateYourPassword",
-    //enrollAccount: "createAccount",
-    enrollAccount: "signUp",
-    forgotPwd: "emailResetLink",
-    resetPwd: "setPassword",
-    signIn: "signIn",
-    signUp: "signUp",
-    resendVerificationEmail: "Send email again",
-  },
-  errors: {
-    accountsCreationDisabled: "Client side accounts creation is disabled!!!",
-    cannotRemoveService: "Cannot remove the only active service!",
-    captchaVerification: "Captcha verification failed!",
-    loginForbidden: "error.accounts.Login forbidden",
-    mustBeLoggedIn: "error.accounts.Must be logged in",
-    pwdMismatch: "error.pwdsDontMatch",
-    validationErrors: "Validation Errors",
-    verifyEmailFirst: "Please verify your email first. Check the email and follow the link!",
-  },
-  navSignIn: 'signIn',
-  navSignOut: 'signOut',
-  info: {
-    emailSent: "info.emailSent",
-    emailVerified: "info.emailVerified",
-    pwdChanged: "info.passwordChanged",
-    pwdReset: "info.passwordReset",
-    pwdSet: "Password Set",
-    signUpVerifyEmail: "Successful Registration! Please check your email and follow the instructions.",
-    verificationEmailSent: "A new email has been sent to you. If the email doesn't show up in your inbox, be sure to check your spam folder.",
-  },
-  inputIcons: {
-    isValidating: "fa fa-spinner fa-spin",
-    hasSuccess: "fa fa-check",
-    hasError: "fa fa-times",
-  },
-  maxAllowedLength: "Maximum allowed length",
-  minRequiredLength: "Minimum required length",
-  optionalField: "optional",
-  pwdLink_pre: "",
-  pwdLink_link: "forgotPassword",
-  pwdLink_suff: "",
-  requiredField: "Required Field",
-  resendVerificationEmailLink_pre: "Verification email lost?",
-  resendVerificationEmailLink_link: "Send again",
-  resendVerificationEmailLink_suff: "",
-  sep: "OR",
-  signInLink_pre: "ifYouAlreadyHaveAnAccount",
-  signInLink_link: "signin",
-  signInLink_suff: "",
-  signUpLink_pre: "dontHaveAnAccount",
-  signUpLink_link: "signUp",
-  signUpLink_suff: "",
-  socialAdd: "add",
-  socialConfigure: "configure",
-  socialIcons: {
-      "meteor-developer": "fa fa-rocket"
-  },
-  socialRemove: "remove",
-  socialSignIn: "signIn",
-  socialSignUp: "signUp",
-  socialWith: "with",
-  termsPreamble: "clickAgree",
-  termsPrivacy: "privacyPolicy",
-  termsAnd: "and",
-  termsTerms: "terms",
-  title: {
-    changePwd: "changePassword",
-    enrollAccount: "createAccount",
-    forgotPwd: "resetYourPassword",
-    resetPwd: "resetYourPassword",
-    signIn: "signIn",
-    signUp: "createAccount",
-    verifyEmail: "",
-    resendVerificationEmail: "Send the verification email again",
-  },
-};
-
-AT.prototype.SPECIAL_FIELDS = [
-  "password_again",
-  "username_and_email",
-];
-
-// SignIn / SignUp fields
-AT.prototype._fields = [
-  new Field({
-    _id: "email",
-    type: "email",
-    required: true,
-    lowercase: true,
-    trim: true,
-    func: function(email) {
-        return !_.contains(email, '@');
-    },
-    errStr: 'Invalid email',
-  }),
-  new Field({
-    _id: "password",
-    type: "password",
-    required: true,
-    minLength: 6,
-    displayName: {
-        "default": "password",
-        changePwd: "newPassword",
-        resetPwd: "newPassword",
-    },
-    placeholder: {
-        "default": "password",
-        changePwd: "newPassword",
-        resetPwd: "newPassword",
-    },
-  }),
-];
-
-
-AT.prototype._initialized = false;
-
-// Input type validation
-AT.prototype._isValidInputType = function(value) {
-    return _.indexOf(this.INPUT_TYPES, value) !== -1;
-};
-
-AT.prototype.addField = function(field) {
-    // Fields can be added only before initialization
-    if (this._initialized) {
-      throw new Error("AccountsTemplates.addField should strictly be called before AccountsTemplates.init!");
-    }
-
-    field = _.pick(field, _.keys(FIELD_PAT));
-    check(field, FIELD_PAT);
-    // Checks there"s currently no field called field._id
-    if (_.indexOf(_.pluck(this._fields, "_id"), field._id) !== -1) {
-      throw new Error("A field called " + field._id + " already exists!");
-    }
-    // Validates field.type
-    if (!this._isValidInputType(field.type)) {
-      throw new Error("field.type is not valid!");
-    }
-    // Checks field.minLength is strictly positive
-    if (typeof field.minLength !== "undefined" && field.minLength <= 0) {
-      throw new Error("field.minLength should be greater than zero!");
-    }
-    // Checks field.maxLength is strictly positive
-    if (typeof field.maxLength !== "undefined" && field.maxLength <= 0) {
-      throw new Error("field.maxLength should be greater than zero!");
-    }
-    // Checks field.maxLength is greater than field.minLength
-    if (typeof field.minLength !== "undefined" && typeof field.minLength !== "undefined" && field.maxLength < field.minLength) {
-      throw new Error("field.maxLength should be greater than field.maxLength!");
-    }
-
-    if (!(Meteor.isServer && _.contains(this.SPECIAL_FIELDS, field._id))) {
-      this._fields.push(new Field(field));
-    }
-
-    return this._fields;
-};
-
-AT.prototype.addFields = function(fields) {
-  var ok;
-
-  try { // don"t bother with `typeof` - just access `length` and `catch`
-    ok = fields.length > 0 && "0" in Object(fields);
-  } catch (e) {
-    throw new Error("field argument should be an array of valid field objects!");
-  }
-  if (ok) {
-    _.map(fields, function(field) {
-      this.addField(field);
-    }, this);
-  } else {
-    throw new Error("field argument should be an array of valid field objects!");
-  }
-
-  return this._fields;
-};
-
-AT.prototype.configure = function(config) {
-  // Configuration options can be set only before initialization
-  if (this._initialized) {
-    throw new Error("Configuration options must be set before AccountsTemplates.init!");
-  }
-
-  // Updates the current configuration
-  check(config, CONFIG_PAT);
-  var options = _.omit(config, "texts", "reCaptcha");
-  this.options = _.defaults(options, this.options);
-
-  // Possibly sets up reCaptcha options
-  var reCaptcha = config.reCaptcha;
-  if (reCaptcha) {
-    // Updates the current button object
-    this.options.reCaptcha = _.defaults(reCaptcha, this.options.reCaptcha || {});
-  }
-
-  // Possibly sets up texts...
-  if (config.texts) {
-    var texts = config.texts;
-    var simpleTexts = _.omit(texts, "button", "errors", "info", "inputIcons", "socialIcons", "title");
-
-    this.texts = _.defaults(simpleTexts, this.texts);
-
-    if (texts.button) {
-      // Updates the current button object
-      this.texts.button = _.defaults(texts.button, this.texts.button);
-    }
-
-    if (texts.errors) {
-      // Updates the current errors object
-      this.texts.errors = _.defaults(texts.errors, this.texts.errors);
-    }
-
-    if (texts.info) {
-      // Updates the current info object
-      this.texts.info = _.defaults(texts.info, this.texts.info);
-    }
-
-    if (texts.inputIcons) {
-      // Updates the current inputIcons object
-      this.texts.inputIcons = _.defaults(texts.inputIcons, this.texts.inputIcons);
-    }
-
-    if (texts.socialIcons) {
-      // Updates the current socialIcons object
-      this.texts.socialIcons = _.defaults(texts.socialIcons, this.texts.socialIcons);
-    }
-
-    if (texts.title) {
-      // Updates the current title object
-      this.texts.title = _.defaults(texts.title, this.texts.title);
-    }
-  }
-};
-
-
-AT.prototype.configureRoute = function(route, options) {
-  console.warn('You now need a routing package like useraccounts:iron-routing or useraccounts:flow-routing to be able to configure routes!');
-};
-
-
-AT.prototype.hasField = function(fieldId) {
-  return !!this.getField(fieldId);
-};
-
-AT.prototype.getField = function(fieldId) {
-  var field = _.filter(this._fields, function(field) {
-    return field._id === fieldId;
-  });
-
-  return (field.length === 1) ? field[0] : undefined;
-};
-
-AT.prototype.getFields = function() {
-    return this._fields;
-};
-
-AT.prototype.getFieldIds = function() {
-    return _.pluck(this._fields, "_id");
-};
-
-AT.prototype.getRoutePath = function(route) {
-    return "#";
-};
-
-AT.prototype.oauthServices = function() {
-  // Extracts names of available services
-  var names;
-
-  if (Meteor.isServer) {
-    names = (Accounts.oauth && Accounts.oauth.serviceNames()) || [];
-  } else {
-    names = (Accounts.oauth && Accounts.loginServicesConfigured() && Accounts.oauth.serviceNames()) || [];
-  }
-  // Extracts names of configured services
-  var configuredServices = [];
-
-  if (Accounts.loginServiceConfiguration) {
-    configuredServices = _.pluck(Accounts.loginServiceConfiguration.find().fetch(), "service");
-  }
-
-  // Builds a list of objects containing service name as _id and its configuration status
-  var services = _.map(names, function(name) {
-    return {
-      _id : name,
-      configured: _.contains(configuredServices, name),
-    };
-  });
-
-  // Checks whether there is a UI to configure services...
-  // XXX: this only works with the accounts-ui package
-  var showUnconfigured = typeof Accounts._loginButtonsSession !== "undefined";
-
-  // Filters out unconfigured services in case they"re not to be displayed
-  if (!showUnconfigured) {
-    services = _.filter(services, function(service) {
-      return service.configured;
-    });
-  }
-
-  // Sorts services by name
-  services = _.sortBy(services, function(service) {
-    return service._id;
-  });
-
-  return services;
-};
-
-AT.prototype.removeField = function(fieldId) {
-  // Fields can be removed only before initialization
-  if (this._initialized) {
-    throw new Error("AccountsTemplates.removeField should strictly be called before AccountsTemplates.init!");
-  }
-  // Tries to look up the field with given _id
-  var index = _.indexOf(_.pluck(this._fields, "_id"), fieldId);
-
-  if (index !== -1) {
-    return this._fields.splice(index, 1)[0];
-  } else if (!(Meteor.isServer && _.contains(this.SPECIAL_FIELDS, fieldId))) {
-    throw new Error("A field called " + fieldId + " does not exist!");
-  }
-};

+ 0 - 292
packages/meteor-useraccounts-core/lib/field.js

@@ -1,292 +0,0 @@
-// ---------------------------------------------------------------------------------
-// Field object
-// ---------------------------------------------------------------------------------
-
-Field = function(field) {
-  check(field, FIELD_PAT);
-  _.defaults(this, field);
-
-  this.validating = new ReactiveVar(false);
-  this.status = new ReactiveVar(null);
-};
-
-if (Meteor.isClient) {
-  Field.prototype.clearStatus = function() {
-    return this.status.set(null);
-  };
-}
-
-if (Meteor.isServer) {
-  Field.prototype.clearStatus = function() {
-    // Nothing to do server-side
-    return;
-  };
-}
-
-Field.prototype.fixValue = function(value) {
-  if (this.type === "checkbox") {
-    return !!value;
-  }
-
-  if (this.type === "select") {
-    // TODO: something working...
-    return value;
-  }
-
-  if (this.type === "radio") {
-    // TODO: something working...
-    return value;
-  }
-
-  // Possibly applies required transformations to the input value
-  if (this.trim) {
-    value = value.trim();
-  }
-
-  if (this.lowercase) {
-    value = value.toLowerCase();
-  }
-
-  if (this.uppercase) {
-    value = value.toUpperCase();
-  }
-
-  if (!!this.transform) {
-    value = this.transform(value);
-  }
-
-  return value;
-};
-
-if (Meteor.isClient) {
-  Field.prototype.getDisplayName = function(state) {
-    var displayName = this.displayName;
-
-    if (_.isFunction(displayName)) {
-      displayName = displayName();
-    } else if (_.isObject(displayName)) {
-      displayName = displayName[state] || displayName["default"];
-    }
-
-    if (!displayName) {
-      displayName = capitalize(this._id);
-    }
-
-    return displayName;
-  };
-}
-
-if (Meteor.isClient) {
-  Field.prototype.getPlaceholder = function(state) {
-    var placeholder = this.placeholder;
-
-    if (_.isObject(placeholder)) {
-      placeholder = placeholder[state] || placeholder["default"];
-    }
-
-    if (!placeholder) {
-      placeholder = capitalize(this._id);
-    }
-
-    return placeholder;
-  };
-}
-
-Field.prototype.getStatus = function() {
-  return this.status.get();
-};
-
-if (Meteor.isClient) {
-  Field.prototype.getValue = function(templateInstance) {
-    if (this.type === "checkbox") {
-      return !!(templateInstance.$("#at-field-" + this._id + ":checked").val());
-    }
-
-    if (this.type === "radio") {
-      return templateInstance.$("[name=at-field-"+ this._id + "]:checked").val();
-    }
-
-    return templateInstance.$("#at-field-" + this._id).val();
-  };
-}
-
-if (Meteor.isClient) {
-  Field.prototype.hasError = function() {
-    return this.negativeValidation && this.status.get();
-  };
-}
-
-if (Meteor.isClient) {
-  Field.prototype.hasIcon = function() {
-    if (this.showValidating && this.isValidating()) {
-      return true;
-    }
-
-    if (this.negativeFeedback && this.hasError()) {
-      return true;
-    }
-
-    if (this.positiveFeedback && this.hasSuccess()) {
-      return true;
-    }
-  };
-}
-
-if (Meteor.isClient) {
-  Field.prototype.hasSuccess = function() {
-    return this.positiveValidation && this.status.get() === false;
-  };
-}
-
-if (Meteor.isClient)
-  Field.prototype.iconClass = function() {
-    if (this.isValidating()) {
-      return AccountsTemplates.texts.inputIcons["isValidating"];
-    }
-
-    if (this.hasError()) {
-      return AccountsTemplates.texts.inputIcons["hasError"];
-    }
-
-    if (this.hasSuccess()) {
-      return AccountsTemplates.texts.inputIcons["hasSuccess"];
-    }
-  };
-
-if (Meteor.isClient) {
-  Field.prototype.isValidating = function() {
-    return this.validating.get();
-  };
-}
-
-if (Meteor.isClient) {
-  Field.prototype.setError = function(err) {
-    check(err, Match.OneOf(String, undefined, Boolean));
-
-    if (err === false) {
-      return this.status.set(false);
-    }
-
-    return this.status.set(err || true);
-  };
-}
-
-if (Meteor.isServer) {
-  Field.prototype.setError = function(err) {
-    // Nothing to do server-side
-    return;
-  };
-}
-
-if (Meteor.isClient) {
-  Field.prototype.setSuccess = function() {
-    return this.status.set(false);
-  };
-}
-
-if (Meteor.isServer) {
-  Field.prototype.setSuccess = function() {
-    // Nothing to do server-side
-    return;
-  };
-}
-
-if (Meteor.isClient) {
-  Field.prototype.setValidating = function(state) {
-    check(state, Boolean);
-    return this.validating.set(state);
-  };
-}
-
-if (Meteor.isServer) {
-  Field.prototype.setValidating = function(state) {
-    // Nothing to do server-side
-    return;
-  };
-}
-
-if (Meteor.isClient) {
-  Field.prototype.setValue = function(templateInstance, value) {
-    if (this.type === "checkbox") {
-      templateInstance.$("#at-field-" + this._id).prop('checked', true);
-      return;
-    }
-
-    if (this.type === "radio") {
-      templateInstance.$("[name=at-field-"+ this._id + "]").prop('checked', true);
-      return;
-    }
-
-    templateInstance.$("#at-field-" + this._id).val(value);
-  };
-}
-
-Field.prototype.validate = function(value, strict) {
-  check(value, Match.OneOf(undefined, String, Boolean));
-  this.setValidating(true);
-  this.clearStatus();
-
-  if (_.isUndefined(value) || value === '') {
-    if (!!strict) {
-      if (this.required) {
-        this.setError(AccountsTemplates.texts.requiredField);
-        this.setValidating(false);
-
-        return AccountsTemplates.texts.requiredField;
-      } else {
-        this.setSuccess();
-        this.setValidating(false);
-
-        return false;
-      }
-    } else {
-      this.clearStatus();
-      this.setValidating(false);
-
-      return null;
-    }
-  }
-
-  var valueLength = value.length;
-  var minLength = this.minLength;
-  if (minLength && valueLength < minLength) {
-    this.setError(AccountsTemplates.texts.minRequiredLength + ": " + minLength);
-    this.setValidating(false);
-
-    return AccountsTemplates.texts.minRequiredLength + ": " + minLength;
-  }
-
-  var maxLength = this.maxLength;
-  if (maxLength && valueLength > maxLength) {
-    this.setError(AccountsTemplates.texts.maxAllowedLength + ": " + maxLength);
-    this.setValidating(false);
-
-    return AccountsTemplates.texts.maxAllowedLength + ": " + maxLength;
-  }
-
-  if (this.re && valueLength && !value.match(this.re)) {
-    this.setError(this.errStr);
-    this.setValidating(false);
-
-    return this.errStr;
-  }
-
-  if (this.func) {
-    var result = this.func(value);
-    var err = result === true ? this.errStr || true : result;
-
-    if (_.isUndefined(result)) {
-      return err;
-    }
-
-    this.status.set(err);
-    this.setValidating(false);
-
-    return err;
-  }
-
-  this.setSuccess();
-  this.setValidating(false);
-
-  return false;
-};

+ 0 - 25
packages/meteor-useraccounts-core/lib/methods.js

@@ -1,25 +0,0 @@
-/* global
-  AccountsTemplates: false
-*/
-"use strict";
-
-Meteor.methods({
-  ATRemoveService: function(serviceName) {
-    check(serviceName, String);
-
-    var userId = this.userId;
-
-    if (userId) {
-      var user = Meteor.users.findOne(userId);
-      var numServices = _.keys(user.services).length; // including "resume"
-      var unset = {};
-
-      if (numServices === 2) {
-        throw new Meteor.Error(403, AccountsTemplates.texts.errors.cannotRemoveService, {});
-      }
-
-      unset["services." + serviceName] = "";
-      Meteor.users.update(userId, {$unset: unset});
-    }
-  },
-});

+ 0 - 184
packages/meteor-useraccounts-core/lib/server.js

@@ -1,184 +0,0 @@
-/* global
-  AT: false,
-  AccountsTemplates: false
-*/
-"use strict";
-
-// Initialization
-AT.prototype.init = function() {
-  console.warn("[AccountsTemplates] There is no more need to call AccountsTemplates.init()! Simply remove the call ;-)");
-};
-
-AT.prototype._init = function() {
-  if (this._initialized) {
-    return;
-  }
-
-  // Checks there is at least one account service installed
-  if (!Package["accounts-password"] && (!Accounts.oauth || Accounts.oauth.serviceNames().length === 0)) {
-    throw Error("AccountsTemplates: You must add at least one account service!");
-  }
-
-  // A password field is strictly required
-  var password = this.getField("password");
-  if (!password) {
-    throw Error("A password field is strictly required!");
-  }
-
-  if (password.type !== "password") {
-    throw Error("The type of password field should be password!");
-  }
-
-  // Then we can have "username" or "email" or even both of them
-  // but at least one of the two is strictly required
-  var username = this.getField("username");
-  var email = this.getField("email");
-
-  if (!username && !email) {
-    throw Error("At least one field out of username and email is strictly required!");
-  }
-
-  if (username && !username.required) {
-    throw Error("The username field should be required!");
-  }
-
-  if (email) {
-    if (email.type !== "email") {
-      throw Error("The type of email field should be email!");
-    }
-
-    if (username) {
-      // username and email
-      if (username.type !== "text") {
-        throw Error("The type of username field should be text when email field is present!");
-      }
-    } else {
-      // email only
-      if (!email.required) {
-        throw Error("The email field should be required when username is not present!");
-      }
-    }
-  } else {
-    // username only
-    if (username.type !== "text" && username.type !== "tel") {
-      throw Error("The type of username field should be text or tel!");
-    }
-  }
-
-  // Possibly publish more user data in order to be able to show add/remove
-  // buttons for 3rd-party services
-  if (this.options.showAddRemoveServices) {
-    // Publish additional current user info to get the list of registered services
-    // XXX TODO: use
-    // Accounts.addAutopublishFields({
-    //   forLoggedInUser: ['services.facebook'],
-    //   forOtherUsers: [],
-    // })
-    // ...adds only user.services.*.id
-    Meteor.publish("userRegisteredServices", function() {
-      var userId = this.userId;
-      return Meteor.users.find(userId, {fields: {services: 1}});
-      /*
-      if (userId) {
-        var user = Meteor.users.findOne(userId);
-        var services_id = _.chain(user.services)
-          .keys()
-          .reject(function(service) {return service === "resume";})
-          .map(function(service) {return "services." + service + ".id";})
-          .value();
-        var projection = {};
-        _.each(services_id, function(key) {projection[key] = 1;});
-        return Meteor.users.find(userId, {fields: projection});
-      }
-      */
-    });
-  }
-
-  // Security stuff
-  if (this.options.overrideLoginErrors) {
-    Accounts.validateLoginAttempt(function(attempt) {
-      if (attempt.error) {
-        var reason = attempt.error.reason;
-        if (reason === "User not found" || reason === "Incorrect password") {
-          throw new Meteor.Error(403, AccountsTemplates.texts.errors.loginForbidden);
-        }
-      }
-      return attempt.allowed;
-    });
-  }
-
-  if (this.options.sendVerificationEmail && this.options.enforceEmailVerification) {
-    Accounts.validateLoginAttempt(function(attempt) {
-      if (!attempt.allowed) {
-        return false;
-      }
-
-      if (attempt.type !== "password" || attempt.methodName !== "login") {
-        return attempt.allowed;
-      }
-
-      var user = attempt.user;
-      if (!user) {
-        return attempt.allowed;
-      }
-
-      var ok = true;
-      var loginEmail = attempt.methodArguments[0].user.email.toLowerCase();
-      if (loginEmail) {
-        var email = _.filter(user.emails, function(obj) {
-          return obj.address.toLowerCase() === loginEmail;
-        });
-        if (!email.length || !email[0].verified) {
-          ok = false;
-        }
-      } else {
-        // we got the username, lets check there's at lease one verified email
-        var emailVerified = _.chain(user.emails)
-        .pluck('verified')
-        .any()
-        .value();
-
-        if (!emailVerified) {
-          ok = false;
-        }
-      }
-      if (!ok) {
-        throw new Meteor.Error(401, AccountsTemplates.texts.errors.verifyEmailFirst);
-      }
-
-      return attempt.allowed;
-    });
-  }
-
-  //Check that reCaptcha secret keys are available
-  if (this.options.showReCaptcha) {
-    var atSecretKey = AccountsTemplates.options.reCaptcha && AccountsTemplates.options.reCaptcha.secretKey;
-    var settingsSecretKey = Meteor.settings.reCaptcha && Meteor.settings.reCaptcha.secretKey;
-
-    if (!atSecretKey && !settingsSecretKey) {
-      throw new Meteor.Error(401, "User Accounts: reCaptcha secret key not found! Please provide it or set showReCaptcha to false." );
-    }
-  }
-
-  // Marks AccountsTemplates as initialized
-  this._initialized = true;
-};
-
-AccountsTemplates = new AT();
-
-// Client side account creation is disabled by default:
-// the methos ATCreateUserServer is used instead!
-// to actually disable client side account creation use:
-//
-//    AccountsTemplates.config({
-//        forbidClientAccountCreation: true
-//    });
-
-Accounts.config({
-  forbidClientAccountCreation: true
-});
-
-// Initialization
-Meteor.startup(function() {
-  AccountsTemplates._init();
-});

+ 0 - 142
packages/meteor-useraccounts-core/lib/server_methods.js

@@ -1,142 +0,0 @@
-/* global
-  AccountsTemplates
-*/
-"use strict";
-
-Meteor.methods({
-  ATCreateUserServer: function(options) {
-    if (AccountsTemplates.options.forbidClientAccountCreation) {
-      throw new Meteor.Error(403, AccountsTemplates.texts.errors.accountsCreationDisabled);
-    }
-
-    // createUser() does more checking.
-    check(options, Object);
-    var allFieldIds = AccountsTemplates.getFieldIds();
-
-    // Picks-up whitelisted fields for profile
-    var profile = options.profile;
-    profile = _.pick(profile, allFieldIds);
-    profile = _.omit(profile, "username", "email", "password");
-
-    // Validates fields" value
-    var signupInfo = _.clone(profile);
-    if (options.username) {
-      signupInfo.username = options.username;
-
-      if (AccountsTemplates.options.lowercaseUsername) {
-        signupInfo.username = signupInfo.username.trim().replace(/\s+/gm, ' ');
-        options.profile.name = signupInfo.username;
-        signupInfo.username = signupInfo.username.toLowerCase().replace(/\s+/gm, '');
-        options.username = signupInfo.username;
-      }
-    }
-
-    if (options.email) {
-      signupInfo.email = options.email;
-
-      if (AccountsTemplates.options.lowercaseUsername) {
-        signupInfo.email = signupInfo.email.toLowerCase().replace(/\s+/gm, '');
-        options.email = signupInfo.email;
-      }
-    }
-
-    if (options.password) {
-      signupInfo.password = options.password;
-    }
-
-    var validationErrors = {};
-    var someError = false;
-
-    // Validates fields values
-    _.each(AccountsTemplates.getFields(), function(field) {
-      var fieldId = field._id;
-      var value = signupInfo[fieldId];
-
-      if (fieldId === "password") {
-        // Can"t Pick-up password here
-        // NOTE: at this stage the password is already encripted,
-        //       so there is no way to validate it!!!
-        check(value, Object);
-        return;
-      }
-
-      var validationErr = field.validate(value, "strict");
-      if (validationErr) {
-        validationErrors[fieldId] = validationErr;
-        someError = true;
-      }
-    });
-
-    if (AccountsTemplates.options.showReCaptcha) {
-      var secretKey = null;
-
-      if (AccountsTemplates.options.reCaptcha && AccountsTemplates.options.reCaptcha.secretKey) {
-        secretKey = AccountsTemplates.options.reCaptcha.secretKey;
-      } else {
-        secretKey = Meteor.settings.reCaptcha.secretKey;
-      }
-
-      var apiResponse = HTTP.post("https://www.google.com/recaptcha/api/siteverify", {
-        params: {
-          secret: secretKey,
-          response: options.profile.reCaptchaResponse,
-          remoteip: this.connection.clientAddress,
-        }
-      }).data;
-
-      if (!apiResponse.success) {
-        throw new Meteor.Error(403, AccountsTemplates.texts.errors.captchaVerification,
-          apiResponse['error-codes'] ? apiResponse['error-codes'].join(", ") : "Unknown Error.");
-      }
-    }
-
-    if (someError) {
-      throw new Meteor.Error(403, AccountsTemplates.texts.errors.validationErrors, validationErrors);
-    }
-
-    // Possibly removes the profile field
-    if (_.isEmpty(options.profile)) {
-      delete options.profile;
-    }
-
-    // Create user. result contains id and token.
-    var userId = Accounts.createUser(options);
-    // safety belt. createUser is supposed to throw on error. send 500 error
-    // instead of sending a verification email with empty userid.
-    if (! userId) {
-      throw new Error("createUser failed to insert new user");
-    }
-
-    // Call postSignUpHook, if any...
-    var postSignUpHook = AccountsTemplates.options.postSignUpHook;
-    if (postSignUpHook) {
-      postSignUpHook(userId, options);
-    }
-
-    // Send a email address verification email in case the context permits it
-    // and the specific configuration flag was set to true
-    if (options.email && AccountsTemplates.options.sendVerificationEmail) {
-      Accounts.sendVerificationEmail(userId, options.email);
-    }
-  },
-
-  // Resend a user's verification e-mail
-  ATResendVerificationEmail: function (email) {
-    check(email, String);
-
-    var user = Meteor.users.findOne({ "emails.address": email });
-
-    // Send the standard error back to the client if no user exist with this e-mail
-    if (!user) {
-      throw new Meteor.Error(403, "User not found");
-    }
-
-    try {
-      Accounts.sendVerificationEmail(user._id);
-    } catch (error) {
-      // Handle error when email already verified
-      // https://github.com/dwinston/send-verification-email-bug
-      throw new Meteor.Error(403, "Already verified");
-    }
-  },
-});

+ 0 - 26
packages/meteor-useraccounts-core/lib/templates_helpers/at_error.js

@@ -1,26 +0,0 @@
-AT.prototype.atErrorHelpers = {
-    singleError: function() {
-        var errors = AccountsTemplates.state.form.get("error");
-        return errors && errors.length === 1;
-    },
-    error: function() {
-        return AccountsTemplates.state.form.get("error");
-    },
-    errorText: function(){
-        var field, err;
-        if (this.field){
-            field = T9n.get(this.field, markIfMissing=false);
-            err = T9n.get(this.err, markIfMissing=false);
-        }
-        else
-            err = T9n.get(this.valueOf(), markIfMissing=false);
-
-        // Possibly removes initial prefix in case the key in not found inside t9n
-        if (err.substring(0, 15) === "error.accounts.")
-            err = err.substring(15);
-
-        if (field)
-            return field + ": " + err;
-        return err;
-    },
-};

+ 0 - 83
packages/meteor-useraccounts-core/lib/templates_helpers/at_form.js

@@ -1,83 +0,0 @@
-AT.prototype.atFormHelpers = {
-    hide: function(){
-        var state = this.state || AccountsTemplates.getState();
-        return state === "hide";
-    },
-    showTitle: function(next_state){
-        var state = next_state || this.state || AccountsTemplates.getState();
-        if (Meteor.userId() && state === "signIn")
-          return false;
-        return !!AccountsTemplates.texts.title[state];
-    },
-    showOauthServices: function(next_state){
-        var state = next_state || this.state || AccountsTemplates.getState();
-        if (!(state === "signIn" || state === "signUp"))
-            return false;
-        var services = AccountsTemplates.oauthServices();
-        if (!services.length)
-            return false;
-        if (Meteor.userId())
-            return AccountsTemplates.options.showAddRemoveServices;
-        return true;
-    },
-    showServicesSeparator: function(next_state){
-        var pwdService = Package["accounts-password"] !== undefined;
-        var state = next_state || this.state || AccountsTemplates.getState();
-        var rightState = (state === "signIn" || state === "signUp");
-        return rightState && !Meteor.userId() && pwdService && AccountsTemplates.oauthServices().length;
-    },
-    showError: function(next_state) {
-        return !!AccountsTemplates.state.form.get("error");
-    },
-    showResult: function(next_state) {
-        return !!AccountsTemplates.state.form.get("result");
-    },
-    showMessage: function(next_state) {
-        return !!AccountsTemplates.state.form.get("message");
-    },
-    showPwdForm: function(next_state) {
-        if (Package["accounts-password"] === undefined)
-            return false;
-        var state = next_state || this.state || AccountsTemplates.getState();
-        if ((state === "verifyEmail") || (state === "signIn" && Meteor.userId()))
-            return false;
-        return true;
-    },
-    showSignInLink: function(next_state){
-        if (AccountsTemplates.options.hideSignInLink)
-            return false;
-        var state = next_state || this.state || AccountsTemplates.getState();
-        if (AccountsTemplates.options.forbidClientAccountCreation && state === "forgotPwd")
-            return true;
-        return state === "signUp";
-    },
-    showSignUpLink: function(next_state){
-        if  (AccountsTemplates.options.hideSignUpLink)
-            return false;
-        var state = next_state || this.state || AccountsTemplates.getState();
-        return ((state === "signIn" && !Meteor.userId()) || state === "forgotPwd") && !AccountsTemplates.options.forbidClientAccountCreation;
-    },
-    showTermsLink: function(next_state){
-        //TODO: Add privacyRoute and termsRoute as alternatives (the point of named routes is
-        // being able to change the url in one place only)
-        if (!!AccountsTemplates.options.privacyUrl || !!AccountsTemplates.options.termsUrl) {
-            var state = next_state || this.state || AccountsTemplates.getState();
-            if (state === "signUp" || state === "enrollAccount" ) {
-              return true;
-            }
-        }
-        /*
-        if (state === "signIn"){
-            var pwdService = Package["accounts-password"] !== undefined;
-            if (!pwdService)
-                return true;
-        }
-        */
-        return false;
-    },
-    showResendVerificationEmailLink: function(){
-        var parentData = Template.currentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        return (state === "signIn" || state === "forgotPwd") && AccountsTemplates.options.showResendVerificationEmailLink;
-    },
-};

+ 0 - 124
packages/meteor-useraccounts-core/lib/templates_helpers/at_input.js

@@ -1,124 +0,0 @@
-AT.prototype.atInputRendered = [function(){
-    var fieldId = this.data._id;
-
-    var parentData = Template.currentData();
-    var state = (parentData && parentData.state) || AccountsTemplates.getState();
-
-    if (AccountsTemplates.options.focusFirstInput) {
-      var firstVisibleInput = _.find(AccountsTemplates.getFields(), function(f){
-        return _.contains(f.visible, state);
-      });
-
-      if (firstVisibleInput && firstVisibleInput._id === fieldId) {
-        this.$("input#at-field-" + fieldId).focus();
-      }
-  }
-}];
-
-AT.prototype.atInputHelpers = {
-    disabled: function() {
-        return AccountsTemplates.disabled();
-    },
-    showLabels: function() {
-        return AccountsTemplates.options.showLabels;
-    },
-    displayName: function() {
-        var parentData = Template.parentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        var displayName = this.getDisplayName(state);
-        return T9n.get(displayName, markIfMissing=false);
-    },
-    optionalText: function(){
-        return "(" + T9n.get(AccountsTemplates.texts.optionalField, markIfMissing=false) + ")";
-    },
-    templateName: function() {
-        if (this.template)
-            return this.template;
-        if (this.type === "checkbox")
-            return "atCheckboxInput";
-        if (this.type === "select")
-            return "atSelectInput";
-        if (this.type === "radio")
-            return "atRadioInput";
-        if (this.type === "hidden")
-            return "atHiddenInput";
-        return "atTextInput";
-    },
-    values: function(){
-        var id = this._id;
-        return _.map(this.select, function(select){
-            var s = _.clone(select);
-            s._id = id + "-" + select.value;
-            s.id = id;
-            return s;
-        });
-    },
-    errorText: function() {
-        var err = this.getStatus();
-        return T9n.get(err, markIfMissing=false);
-    },
-    placeholder: function() {
-        if (AccountsTemplates.options.showPlaceholders) {
-            var parentData = Template.parentData();
-            var state = (parentData && parentData.state) || AccountsTemplates.getState();
-            var placeholder = this.getPlaceholder(state);
-            return T9n.get(placeholder, markIfMissing=false);
-        }
-    },
-};
-
-AT.prototype.atInputEvents = {
-    "focusin input": function(event, t){
-        var field = Template.currentData();
-        field.clearStatus();
-    },
-    "focusout input, change select": function(event, t){
-        var field = Template.currentData();
-        var fieldId = field._id;
-        var rawValue = field.getValue(t);
-        var value = field.fixValue(rawValue);
-        // Possibly updates the input value
-        if (value !== rawValue) {
-            field.setValue(t, value);
-        }
-
-        // Client-side only validation
-        if (!field.validation)
-            return;
-        var parentData = Template.parentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        // No validation during signIn
-        if (state === "signIn")
-            return;
-        // Special case for password confirmation
-        if (value && fieldId === "password_again"){
-            if (value !== $("#at-field-password").val())
-                return field.setError(AccountsTemplates.texts.errors.pwdMismatch);
-        }
-        field.validate(value);
-    },
-    "keyup input": function(event, t){
-        var field = Template.currentData();
-        // Client-side only continuous validation
-        if (!field.continuousValidation)
-            return;
-        var parentData = Template.parentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        // No validation during signIn
-        if (state === "signIn")
-            return;
-        var fieldId = field._id;
-        var rawValue = field.getValue(t);
-        var value = field.fixValue(rawValue);
-        // Possibly updates the input value
-        if (value !== rawValue) {
-            field.setValue(t, value);
-        }
-        // Special case for password confirmation
-        if (value && fieldId === "password_again"){
-            if (value !== $("#at-field-password").val())
-                return field.setError(AccountsTemplates.texts.errors.pwdMismatch);
-        }
-        field.validate(value);
-    },
-};

+ 0 - 7
packages/meteor-useraccounts-core/lib/templates_helpers/at_message.js

@@ -1,7 +0,0 @@
-AT.prototype.atMessageHelpers = {
-    message: function() {
-        var messageText = AccountsTemplates.state.form.get("message");
-        if (messageText)
-            return T9n.get(messageText, markIfMissing=false);
-    },
-};

+ 0 - 16
packages/meteor-useraccounts-core/lib/templates_helpers/at_nav_button.js

@@ -1,16 +0,0 @@
-AT.prototype.atNavButtonHelpers = {
-    text: function(){
-        var key = Meteor.userId() ? AccountsTemplates.texts.navSignOut : AccountsTemplates.texts.navSignIn;
-        return T9n.get(key, markIfMissing=false);
-    }
-};
-
-AT.prototype.atNavButtonEvents = {
-    'click #at-nav-button': function(event){
-        event.preventDefault();
-        if (Meteor.userId())
-            AccountsTemplates.logout();
-        else
-            AccountsTemplates.linkClick("signIn");
-    },
-};

+ 0 - 5
packages/meteor-useraccounts-core/lib/templates_helpers/at_oauth.js

@@ -1,5 +0,0 @@
-AT.prototype.atOauthHelpers = {
-    oauthService: function() {
-        return AccountsTemplates.oauthServices();
-    },
-};

+ 0 - 331
packages/meteor-useraccounts-core/lib/templates_helpers/at_pwd_form.js

@@ -1,331 +0,0 @@
-AT.prototype.atPwdFormHelpers = {
-    disabled: function() {
-        return AccountsTemplates.disabled();
-    },
-    fields: function() {
-        var parentData = Template.currentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        return _.filter(AccountsTemplates.getFields(), function(s) {
-            return _.contains(s.visible, state);
-        });
-    },
-    showForgotPasswordLink: function() {
-        var parentData = Template.currentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        return state === "signIn" && AccountsTemplates.options.showForgotPasswordLink;
-    },
-    showReCaptcha: function() {
-      var parentData = Template.currentData();
-      var state = (parentData && parentData.state) || AccountsTemplates.getState();
-      return state === "signUp" && AccountsTemplates.options.showReCaptcha;
-    },
-};
-
-
-var toLowercaseUsername = function(value){
-  return value.toLowerCase().replace(/\s+/gm, '');
-};
-
-AT.prototype.atPwdFormEvents = {
-    // Form submit
-    "submit #at-pwd-form": function(event, t) {
-        event.preventDefault();
-        t.$("#at-btn").blur();
-
-        AccountsTemplates.setDisabled(true);
-
-        var parentData = Template.currentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        var preValidation = (state !== "signIn");
-
-        // Client-side pre-validation
-        // Validates fields values
-        // NOTE: This is the only place where password validation can be enforced!
-        var formData = {};
-        var someError = false;
-        var errList = [];
-        _.each(AccountsTemplates.getFields(), function(field){
-            // Considers only visible fields...
-            if (!_.contains(field.visible, state))
-                return;
-
-            var fieldId = field._id;
-
-            var rawValue = field.getValue(t);
-            var value = field.fixValue(rawValue);
-            // Possibly updates the input value
-            if (value !== rawValue) {
-                field.setValue(t, value);
-            }
-            if (value !== undefined && value !== "") {
-                formData[fieldId] = value;
-            }
-
-            // Validates the field value only if current state is not "signIn"
-            if (preValidation && field.getStatus() !== false){
-                var validationErr = field.validate(value, "strict");
-                if (validationErr) {
-                    if (field.negativeValidation)
-                        field.setError(validationErr);
-                    else{
-                        var fId = T9n.get(field.getDisplayName(), markIfMissing=false);
-                        //errList.push(fId + ": " + err);
-                        errList.push({
-                            field: field.getDisplayName(),
-                            err: validationErr
-                        });
-                    }
-                    someError = true;
-                }
-                else
-                    field.setSuccess();
-            }
-        });
-
-        // Clears error and result
-        AccountsTemplates.clearError();
-        AccountsTemplates.clearResult();
-        AccountsTemplates.clearMessage();
-        // Possibly sets errors
-        if (someError){
-            if (errList.length)
-                AccountsTemplates.state.form.set("error", errList);
-            AccountsTemplates.setDisabled(false);
-            //reset reCaptcha form
-            if (state === "signUp" && AccountsTemplates.options.showReCaptcha) {
-                grecaptcha.reset();
-            }
-            return;
-        }
-
-        // Extracts username, email, and pwds
-        var current_password = formData.current_password;
-        var email = formData.email;
-        var password = formData.password;
-        var password_again = formData.password_again;
-        var username = formData.username;
-        var username_and_email = formData.username_and_email;
-        // Clears profile data removing username, email, and pwd
-        delete formData.current_password;
-        delete formData.email;
-        delete formData.password;
-        delete formData.password_again;
-        delete formData.username;
-        delete formData.username_and_email;
-
-        if (AccountsTemplates.options.confirmPassword){
-            // Checks passwords for correct match
-            if (password_again && password !== password_again){
-                var pwd_again = AccountsTemplates.getField("password_again");
-                if (pwd_again.negativeValidation)
-                    pwd_again.setError(AccountsTemplates.texts.errors.pwdMismatch);
-                else
-                    AccountsTemplates.state.form.set("error", [{
-                        field: pwd_again.getDisplayName(),
-                        err: AccountsTemplates.texts.errors.pwdMismatch
-                    }]);
-                AccountsTemplates.setDisabled(false);
-                //reset reCaptcha form
-                if (state === "signUp" && AccountsTemplates.options.showReCaptcha) {
-                  grecaptcha.reset();
-                }
-                return;
-            }
-        }
-
-        // -------
-        // Sign In
-        // -------
-        if (state === "signIn") {
-            var pwdOk = !!password;
-            var userOk = true;
-            var loginSelector;
-            if (email) {
-                if (AccountsTemplates.options.lowercaseUsername) {
-                  email = toLowercaseUsername(email);
-                }
-
-                loginSelector = {email: email};
-            }
-            else if (username) {
-                if (AccountsTemplates.options.lowercaseUsername) {
-                  username = toLowercaseUsername(username);
-                }
-                loginSelector = {username: username};
-            }
-            else if (username_and_email) {
-                if (AccountsTemplates.options.lowercaseUsername) {
-                  username_and_email = toLowercaseUsername(username_and_email);
-                }
-                loginSelector = username_and_email;
-            }
-            else
-                userOk = false;
-
-            // Possibly exits if not both 'password' and 'username' are non-empty...
-            if (!pwdOk || !userOk){
-                AccountsTemplates.state.form.set("error", [AccountsTemplates.texts.errors.loginForbidden]);
-                AccountsTemplates.setDisabled(false);
-                return;
-            }
-
-
-            return Meteor.loginWithPassword(loginSelector, password, function(error) {
-                AccountsTemplates.submitCallback(error, state);
-            });
-        }
-
-        // -------
-        // Sign Up
-        // -------
-        if (state === "signUp") {
-            // Possibly gets reCaptcha response
-            if (AccountsTemplates.options.showReCaptcha) {
-              var response = grecaptcha.getResponse();
-              if (response === "") {
-                // recaptcha verification has not completed yet (or has expired)...
-                // ...simply ignore submit event!
-                AccountsTemplates.setDisabled(false);
-                return;
-              } else {
-                formData.reCaptchaResponse = response;
-              }
-            }
-
-            var hash = Accounts._hashPassword(password);
-            var options = {
-                username: username,
-                email: email,
-                password: hash,
-                profile: formData,
-            };
-
-            // Call preSignUpHook, if any...
-            var preSignUpHook = AccountsTemplates.options.preSignUpHook;
-            if (preSignUpHook) {
-              preSignUpHook(password, options);
-            }
-
-            return Meteor.call("ATCreateUserServer", options, function(error){
-                if (error && error.reason === 'Email already exists.') {
-                    if (AccountsTemplates.options.showReCaptcha) {
-                      grecaptcha.reset();
-                    }
-                }
-                AccountsTemplates.submitCallback(error, undefined, function(){
-                    if (AccountsTemplates.options.sendVerificationEmail && AccountsTemplates.options.enforceEmailVerification){
-                        AccountsTemplates.submitCallback(error, state, function () {
-                            AccountsTemplates.state.form.set("result", AccountsTemplates.texts.info.signUpVerifyEmail);
-                            // Cleans up input fields' content
-                            _.each(AccountsTemplates.getFields(), function(field){
-                                // Considers only visible fields...
-                                if (!_.contains(field.visible, state))
-                                    return;
-
-                                var elem = t.$("#at-field-" + field._id);
-
-                                // Naïve reset
-                                if (field.type === "checkbox") elem.prop('checked', false);
-                                else elem.val("");
-
-                            });
-                            AccountsTemplates.setDisabled(false);
-                            AccountsTemplates.avoidRedirect = true;
-                        });
-                    }
-                    else {
-                        var loginSelector;
-
-                        if (email) {
-                            if (AccountsTemplates.options.lowercaseUsername) {
-                              email = toLowercaseUsername(email);
-                            }
-
-                            loginSelector = {email: email};
-                        }
-                        else if (username) {
-                            if (AccountsTemplates.options.lowercaseUsername) {
-                              username = toLowercaseUsername(username);
-                            }
-                            loginSelector = {username: username};
-                        }
-                        else {
-                            if (AccountsTemplates.options.lowercaseUsername) {
-                              username_and_email = toLowercaseUsername(username_and_email);
-                            }
-                            loginSelector = username_and_email;
-                        }
-
-                        Meteor.loginWithPassword(loginSelector, password, function(error) {
-                            AccountsTemplates.submitCallback(error, state, function(){
-                                AccountsTemplates.setState("signIn");
-                            });
-                        });
-                    }
-                });
-            });
-        }
-
-        //----------------
-        // Forgot Password
-        //----------------
-        if (state === "forgotPwd"){
-            return Accounts.forgotPassword({
-                email: email
-            }, function(error) {
-                AccountsTemplates.submitCallback(error, state, function(){
-                    AccountsTemplates.state.form.set("result", AccountsTemplates.texts.info.emailSent);
-                    t.$("#at-field-email").val("");
-                });
-            });
-        }
-
-        //--------------------------------
-        // Reset Password / Enroll Account
-        //--------------------------------
-        if (state === "resetPwd" || state === "enrollAccount") {
-            var paramToken = AccountsTemplates.getparamToken();
-            return Accounts.resetPassword(paramToken, password, function(error) {
-                AccountsTemplates.submitCallback(error, state, function(){
-                    var pwd_field_id;
-                    if (state === "resetPwd")
-                        AccountsTemplates.state.form.set("result", AccountsTemplates.texts.info.pwdReset);
-                    else // Enroll Account
-                        AccountsTemplates.state.form.set("result", AccountsTemplates.texts.info.pwdSet);
-                    t.$("#at-field-password").val("");
-                    if (AccountsTemplates.options.confirmPassword)
-                        t.$("#at-field-password_again").val("");
-                });
-            });
-        }
-
-        //----------------
-        // Change Password
-        //----------------
-        if (state === "changePwd"){
-            return Accounts.changePassword(current_password, password, function(error) {
-                AccountsTemplates.submitCallback(error, state, function(){
-                    AccountsTemplates.state.form.set("result", AccountsTemplates.texts.info.pwdChanged);
-                    t.$("#at-field-current_password").val("");
-                    t.$("#at-field-password").val("");
-                    if (AccountsTemplates.options.confirmPassword)
-                        t.$("#at-field-password_again").val("");
-                });
-            });
-        }
-
-        //----------------
-        // Resend Verification E-mail
-        //----------------
-        if (state === "resendVerificationEmail"){
-            return Meteor.call("ATResendVerificationEmail", email, function (error) {
-                AccountsTemplates.submitCallback(error, state, function(){
-                    AccountsTemplates.state.form.set("result", AccountsTemplates.texts.info.verificationEmailSent);
-                    t.$("#at-field-email").val("");
-
-                    AccountsTemplates.avoidRedirect = true;
-                });
-            });
-        }
-    },
-};

+ 0 - 18
packages/meteor-useraccounts-core/lib/templates_helpers/at_pwd_form_btn.js

@@ -1,18 +0,0 @@
-AT.prototype.atPwdFormBtnHelpers = {
-    submitDisabled: function(){
-        var disable = _.chain(AccountsTemplates.getFields())
-            .map(function(field){
-                return field.hasError() || field.isValidating();
-            })
-            .some()
-            .value()
-        ;
-        if (disable)
-            return "disabled";
-    },
-    buttonText: function() {
-        var parentData = Template.currentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        return T9n.get(AccountsTemplates.texts.button[state], markIfMissing=false);
-    },
-};

+ 0 - 24
packages/meteor-useraccounts-core/lib/templates_helpers/at_pwd_link.js

@@ -1,24 +0,0 @@
-AT.prototype.atPwdLinkHelpers = {
-    disabled: function() {
-        return AccountsTemplates.disabled();
-    },
-    forgotPwdLink: function(){
-        return AccountsTemplates.getRoutePath("forgotPwd");
-    },
-    preText: function(){
-        return T9n.get(AccountsTemplates.texts.pwdLink_pre, markIfMissing=false);
-    },
-    linkText: function(){
-        return T9n.get(AccountsTemplates.texts.pwdLink_link, markIfMissing=false);
-    },
-    suffText: function(){
-        return T9n.get(AccountsTemplates.texts.pwdLink_suff, markIfMissing=false);
-    },
-};
-
-AT.prototype.atPwdLinkEvents = {
-    "click #at-forgotPwd": function(event, t) {
-        event.preventDefault();
-        AccountsTemplates.linkClick("forgotPwd");
-    },
-};

+ 0 - 19
packages/meteor-useraccounts-core/lib/templates_helpers/at_reCaptcha.js

@@ -1,19 +0,0 @@
-AT.prototype.atReCaptchaRendered = function() {
-    $.getScript('//www.google.com/recaptcha/api.js?hl=' + T9n.getLanguage());
-};
-
-AT.prototype.atReCaptchaHelpers = {
-    key: function() {
-        if (AccountsTemplates.options.reCaptcha && AccountsTemplates.options.reCaptcha.siteKey)
-            return AccountsTemplates.options.reCaptcha.siteKey;
-        return Meteor.settings.public.reCaptcha.siteKey;
-    },
-
-    theme: function() {
-        return AccountsTemplates.options.reCaptcha && AccountsTemplates.options.reCaptcha.theme;
-    },
-
-    data_type: function() {
-        return AccountsTemplates.options.reCaptcha && AccountsTemplates.options.reCaptcha.data_type;
-    },
-};

+ 0 - 24
packages/meteor-useraccounts-core/lib/templates_helpers/at_resend_verification_email_link.js

@@ -1,24 +0,0 @@
-AT.prototype.atResendVerificationEmailLinkHelpers = {
-    disabled: function () {
-        return AccountsTemplates.disabled();
-    },
-    resendVerificationEmailLink: function () {
-        return AccountsTemplates.getRoutePath("resendVerificationEmail");
-    },
-    preText: function(){
-        return T9n.get(AccountsTemplates.texts.resendVerificationEmailLink_pre, markIfMissing=false);
-    },
-    linkText: function(){
-        return T9n.get(AccountsTemplates.texts.resendVerificationEmailLink_link, markIfMissing=false);
-    },
-    suffText: function(){
-        return T9n.get(AccountsTemplates.texts.resendVerificationEmailLink_suff, markIfMissing=false);
-    },
-};
-
-AT.prototype.atResendVerificationEmailLinkEvents = {
-    "click #at-resend-verification-email": function(event, t) {
-        event.preventDefault();
-        AccountsTemplates.linkClick('resendVerificationEmail');
-    },
-};

+ 0 - 7
packages/meteor-useraccounts-core/lib/templates_helpers/at_result.js

@@ -1,7 +0,0 @@
-AT.prototype.atResultHelpers = {
-    result: function() {
-        var resultText = AccountsTemplates.state.form.get("result");
-        if (resultText)
-            return T9n.get(resultText, markIfMissing=false);
-    },
-};

+ 0 - 5
packages/meteor-useraccounts-core/lib/templates_helpers/at_sep.js

@@ -1,5 +0,0 @@
-AT.prototype.atSepHelpers = {
-    sepText: function(){
-        return T9n.get(AccountsTemplates.texts.sep, markIfMissing=false);
-    },
-};

+ 0 - 24
packages/meteor-useraccounts-core/lib/templates_helpers/at_signin_link.js

@@ -1,24 +0,0 @@
-AT.prototype.atSigninLinkHelpers = {
-    disabled: function() {
-        return AccountsTemplates.disabled();
-    },
-    signInLink: function(){
-        return AccountsTemplates.getRoutePath("signIn");
-    },
-    preText: function(){
-        return T9n.get(AccountsTemplates.texts.signInLink_pre, markIfMissing=false);
-    },
-    linkText: function(){
-        return T9n.get(AccountsTemplates.texts.signInLink_link, markIfMissing=false);
-    },
-    suffText: function(){
-        return T9n.get(AccountsTemplates.texts.signInLink_suff, markIfMissing=false);
-    },
-};
-
-AT.prototype.atSigninLinkEvents = {
-    "click #at-signIn": function(event, t) {
-        event.preventDefault();
-        AccountsTemplates.linkClick("signIn");
-    },
-};

+ 0 - 24
packages/meteor-useraccounts-core/lib/templates_helpers/at_signup_link.js

@@ -1,24 +0,0 @@
-AT.prototype.atSignupLinkHelpers = {
-    disabled: function() {
-        return AccountsTemplates.disabled();
-    },
-    signUpLink: function(){
-        return AccountsTemplates.getRoutePath("signUp");
-    },
-    preText: function(){
-        return T9n.get(AccountsTemplates.texts.signUpLink_pre, markIfMissing=false);
-    },
-    linkText: function(){
-        return T9n.get(AccountsTemplates.texts.signUpLink_link, markIfMissing=false);
-    },
-    suffText: function(){
-        return T9n.get(AccountsTemplates.texts.signUpLink_suff, markIfMissing=false);
-    },
-};
-
-AT.prototype.atSignupLinkEvents = {
-    "click #at-signUp": function(event, t) {
-        event.preventDefault();
-        AccountsTemplates.linkClick('signUp');
-    },
-};

+ 0 - 105
packages/meteor-useraccounts-core/lib/templates_helpers/at_social.js

@@ -1,105 +0,0 @@
-AT.prototype.atSocialHelpers = {
-    disabled: function() {
-        if (AccountsTemplates.disabled())
-            return "disabled";
-        var user = Meteor.user();
-        if (user){
-            var numServices = 0;
-            if (user.services)
-                numServices = _.keys(user.services).length; // including "resume"
-            if (numServices === 2 && user.services[this._id])
-                return "disabled";
-        }
-    },
-    name: function(){
-        return this._id;
-    },
-    iconClass: function() {
-        var ic = AccountsTemplates.texts.socialIcons[this._id];
-        if (!ic)
-            ic = "fa fa-" + this._id;
-        return ic;
-    },
-    buttonText: function() {
-        var service = this;
-        var serviceName = this._id;
-        if (serviceName === "meteor-developer")
-            serviceName = "meteor";
-        serviceName = capitalize(serviceName);
-        if (!service.configured)
-            return T9n.get(AccountsTemplates.texts.socialConfigure, markIfMissing=false) + " " + serviceName;
-        var showAddRemove = AccountsTemplates.options.showAddRemoveServices;
-        var user = Meteor.user();
-        if (user && showAddRemove){
-            if (user.services && user.services[this._id]){
-                var numServices = _.keys(user.services).length; // including "resume"
-                if (numServices === 2)
-                    return serviceName;
-                else
-                    return T9n.get(AccountsTemplates.texts.socialRemove, markIfMissing=false) + " " + serviceName;
-            } else
-                    return T9n.get(AccountsTemplates.texts.socialAdd, markIfMissing=false) + " " + serviceName;
-        }
-        var parentData = Template.parentData();
-        var state = (parentData && parentData.state) || AccountsTemplates.getState();
-        var prefix = state === "signIn" ?
-            T9n.get(AccountsTemplates.texts.socialSignIn, markIfMissing=false) :
-            T9n.get(AccountsTemplates.texts.socialSignUp, markIfMissing=false);
-        return prefix + " " + T9n.get(AccountsTemplates.texts.socialWith, markIfMissing=false) + " " + serviceName;
-    },
-};
-
-AT.prototype.atSocialEvents = {
-    "click button": function(event, t) {
-        event.preventDefault();
-        event.currentTarget.blur();
-        if (AccountsTemplates.disabled())
-            return;
-        var user = Meteor.user();
-        if (user && user.services && user.services[this._id]){
-            var numServices = _.keys(user.services).length; // including "resume"
-            if (numServices === 2)
-                return;
-            else{
-                AccountsTemplates.setDisabled(true);
-                Meteor.call("ATRemoveService", this._id, function(error){
-                    AccountsTemplates.setDisabled(false);
-                });
-            }
-        } else {
-            AccountsTemplates.setDisabled(true);
-            var parentData = Template.parentData();
-            var state = (parentData && parentData.state) || AccountsTemplates.getState();
-            var serviceName = this._id;
-            var methodName;
-            if (serviceName === 'meteor-developer')
-                methodName = "loginWithMeteorDeveloperAccount";
-            else
-                methodName = "loginWith" + capitalize(serviceName);
-            var loginWithService = Meteor[methodName];
-            options = {
-                loginStyle: AccountsTemplates.options.socialLoginStyle,
-            };
-            if (Accounts.ui) {
-                if (Accounts.ui._options.requestPermissions[serviceName]) {
-                    options.requestPermissions = Accounts.ui._options.requestPermissions[serviceName];
-                }
-                if (Accounts.ui._options.requestOfflineToken[serviceName]) {
-                    options.requestOfflineToken = Accounts.ui._options.requestOfflineToken[serviceName];
-                }
-            }
-            loginWithService(options, function(err) {
-                AccountsTemplates.setDisabled(false);
-                if (err && err instanceof Accounts.LoginCancelledError) {
-                    // do nothing
-                }
-                else if (err && err instanceof ServiceConfiguration.ConfigError) {
-                    if (Accounts._loginButtonsSession)
-                        return Accounts._loginButtonsSession.configureService(serviceName);
-                }
-                else
-                    AccountsTemplates.submitCallback(err, state);
-            });
-        }
-    },
-};

+ 0 - 33
packages/meteor-useraccounts-core/lib/templates_helpers/at_terms_link.js

@@ -1,33 +0,0 @@
-AT.prototype.atTermsLinkHelpers = {
-    disabled: function() {
-        return AccountsTemplates.disabled();
-    },
-    text: function(){
-        return T9n.get(AccountsTemplates.texts.termsPreamble, markIfMissing=false);
-    },
-    privacyUrl: function(){
-        return AccountsTemplates.options.privacyUrl;
-    },
-    privacyLinkText: function(){
-        return T9n.get(AccountsTemplates.texts.termsPrivacy, markIfMissing=false);
-    },
-    showTermsAnd: function(){
-        return !!AccountsTemplates.options.privacyUrl && !!AccountsTemplates.options.termsUrl;
-    },
-    and: function(){
-        return T9n.get(AccountsTemplates.texts.termsAnd, markIfMissing=false);
-    },
-    termsUrl: function(){
-        return AccountsTemplates.options.termsUrl;
-    },
-    termsLinkText: function(){
-        return T9n.get(AccountsTemplates.texts.termsTerms, markIfMissing=false);
-    },
-};
-
-AT.prototype.atTermsLinkEvents = {
-    "click a": function(event) {
-        if (AccountsTemplates.disabled())
-            event.preventDefault();
-    },
-};

+ 0 - 7
packages/meteor-useraccounts-core/lib/templates_helpers/at_title.js

@@ -1,7 +0,0 @@
-AT.prototype.atTitleHelpers = {
-  title: function() {
-    var parentData = Template.currentData();
-    var state = (parentData && parentData.state) || AccountsTemplates.getState();
-    return T9n.get(AccountsTemplates.texts.title[state], markIfMissing = false);
-  },
-};

+ 0 - 12
packages/meteor-useraccounts-core/lib/templates_helpers/ensure_signed_in.html

@@ -1,12 +0,0 @@
-<!-- Template level auth -->
-<template name="ensureSignedIn">
-  {{#if signedIn}}
-    {{> Template.dynamic template=template}}
-  {{else}}
-    {{#if auth}}
-      {{> Template.dynamic template=auth}}
-    {{else}}
-      {{> fullPageAtForm}}
-    {{/if}}
-  {{/if}}
-</template>

+ 0 - 15
packages/meteor-useraccounts-core/lib/templates_helpers/ensure_signed_in.js

@@ -1,15 +0,0 @@
-
-Template.ensureSignedIn.helpers({
-  signedIn: function () {
-    if (!Meteor.user()) {
-      AccountsTemplates.setState(AccountsTemplates.options.defaultState, function(){
-        var err = AccountsTemplates.texts.errors.mustBeLoggedIn;
-        AccountsTemplates.state.form.set('error', [err]);
-      });
-      return false;
-    } else {
-      AccountsTemplates.clearError();
-      return true;
-    }
-  }
-});

+ 0 - 19
packages/meteor-useraccounts-core/lib/utils.js

@@ -1,19 +0,0 @@
-capitalize = function(str) {
-  return str.charAt(0).toUpperCase() + str.slice(1);
-};
-
-signedInAs =  function() {
-  var user = Meteor.user();
-
-  if (user) {
-    if (user.username) {
-      return user.username;
-    } else if (user.profile && user.profile.name) {
-      return user.profile.name;
-    } else if (user.emails && user.emails[0]) {
-      return user.emails[0].address;
-    } else {
-      return "Signed In";
-    }
-  }
-};

+ 0 - 94
packages/meteor-useraccounts-core/package.js

@@ -1,94 +0,0 @@
-'use strict';
-
-Package.describe({
-  summary: 'Meteor sign up and sign in templates core package.',
-  version: '1.14.2',
-  name: 'useraccounts:core',
-  git: 'https://github.com/meteor-useraccounts/core.git',
-});
-
-Package.onUse(function(api) {
-  //api.versionsFrom('METEOR@1.0.3');
-
-  api.use([
-    'accounts-base',
-    'check',
-    'underscore',
-    'reactive-var',
-  ], ['client', 'server']);
-
-  api.use([
-    'blaze',
-    'reactive-dict',
-    'templating',
-    'jquery'
-  ], 'client');
-
-  api.use([
-    'http'
-  ], 'server');
-
-  api.imply([
-    'accounts-base',
-    'softwarerero:accounts-t9n@1.3.3',
-  ], ['client', 'server']);
-
-  api.imply([
-    'templating',
-  ], ['client']);
-
-  api.addFiles([
-    'lib/field.js',
-    'lib/core.js',
-    'lib/server.js',
-    'lib/methods.js',
-    'lib/server_methods.js',
-  ], ['server']);
-
-  api.addFiles([
-    'lib/utils.js',
-    'lib/field.js',
-    'lib/core.js',
-    'lib/client.js',
-    'lib/templates_helpers/at_error.js',
-    'lib/templates_helpers/at_form.js',
-    'lib/templates_helpers/at_input.js',
-    'lib/templates_helpers/at_nav_button.js',
-    'lib/templates_helpers/at_oauth.js',
-    'lib/templates_helpers/at_pwd_form.js',
-    'lib/templates_helpers/at_pwd_form_btn.js',
-    'lib/templates_helpers/at_pwd_link.js',
-    'lib/templates_helpers/at_reCaptcha.js',
-    'lib/templates_helpers/at_resend_verification_email_link.js',
-    'lib/templates_helpers/at_result.js',
-    'lib/templates_helpers/at_sep.js',
-    'lib/templates_helpers/at_signin_link.js',
-    'lib/templates_helpers/at_signup_link.js',
-    'lib/templates_helpers/at_social.js',
-    'lib/templates_helpers/at_terms_link.js',
-    'lib/templates_helpers/at_title.js',
-    'lib/templates_helpers/at_message.js',
-    'lib/templates_helpers/ensure_signed_in.html',
-    'lib/templates_helpers/ensure_signed_in.js',
-    'lib/methods.js',
-  ], ['client']);
-
-  api.export([
-    'AccountsTemplates',
-  ], ['client', 'server']);
-});
-
-Package.onTest(function(api) {
-  api.use('useraccounts:core@1.14.2');
-
-  api.use([
-    'accounts-password',
-    'tinytest',
-    'test-helpers',
-    'underscore',
-  ], ['client', 'server']);
-
-  api.addFiles([
-    'tests/tests.js',
-  ], ['client', 'server']);
-});

+ 0 - 215
packages/meteor-useraccounts-core/tests/tests.js

@@ -1,215 +0,0 @@
-Tinytest.add("AccountsTemplates - addField/removeField", function(test) {
-    // Calls after AccountsTemplates.init()
-    AccountsTemplates._initialized = true;
-    test.throws(function() {
-        AccountsTemplates.addField("");
-    }, function(err) {
-        if (err instanceof Error && err.message === "AccountsTemplates.addField should strictly be called before AccountsTemplates.init!")
-            return true;
-    });
-    test.throws(function() {
-        AccountsTemplates.removeField("");
-    }, function(err) {
-        if (err instanceof Error && err.message === "AccountsTemplates.removeField should strictly be called before AccountsTemplates.init!")
-            return true;
-    });
-    AccountsTemplates._initialized = false;
-
-    // Trying to remove a non-existing field
-    test.throws(function() {
-        AccountsTemplates.removeField("foo");
-    }, function(err) {
-        if (err instanceof Error && err.message == "A field called foo does not exist!")
-            return true;
-    });
-
-    // Trying to remove an existing field
-    var email = AccountsTemplates.removeField("email");
-    test.isUndefined(AccountsTemplates.getField("email"));
-    // ...and puts it back in for tests re-run
-    AccountsTemplates.addField(email);
-
-    // Trying to add an already existing field
-    test.throws(function() {
-        var pwd = AccountsTemplates.getField("password");
-        AccountsTemplates.addField(pwd);
-    }, function(err) {
-        if (err instanceof Error && err.message == "A field called password already exists!")
-            return true;
-    });
-
-    var login = {
-        _id: "login",
-        displayName: "Email",
-        type: "email"
-    };
-
-    // Successful add
-    AccountsTemplates.addField(login);
-    // ...and removes it for tests re-run
-    AccountsTemplates.removeField("login");
-
-    // Invalid field.type
-    test.throws(function() {
-        AccountsTemplates.addField({
-            _id: "foo",
-            displayName: "Foo",
-            type: "bar"
-        });
-    }, function(err) {
-        if (err instanceof Error && err.message == "field.type is not valid!")
-            return true;
-    });
-
-    // Invalid minLength
-    test.throws(function() {
-        AccountsTemplates.addField({
-            _id: "first-name",
-            displayName: "First Name",
-            type: "text",
-            minLength: 0
-        });
-    }, function(err) {
-        if (err instanceof Error && err.message == "field.minLength should be greater than zero!")
-            return true;
-    });
-    // Invalid maxLength
-    test.throws(function() {
-        AccountsTemplates.addField({
-            _id: "first-name",
-            displayName: "First Name",
-            type: "text",
-            maxLength: 0
-        });
-    }, function(err) {
-        if (err instanceof Error && err.message == "field.maxLength should be greater than zero!")
-            return true;
-    });
-    // maxLength < minLength
-    test.throws(function() {
-        AccountsTemplates.addField({
-            _id: "first-name",
-            displayName: "First Name",
-            type: "text",
-            minLength: 2,
-            maxLength: 1
-        });
-    }, function(err) {
-        if (err instanceof Error && err.message == "field.maxLength should be greater than field.maxLength!")
-            return true;
-    });
-
-    // Successful add
-    var first_name = {
-        _id: "first_name",
-        displayName: "First Name",
-        type: "text",
-        minLength: 2,
-        maxLength: 50,
-        required: true
-    };
-    AccountsTemplates.addField(first_name);
-    // Now removes it to be consistent with tests re-run
-    AccountsTemplates.removeField("first_name");
-});
-
-
-Tinytest.add("AccountsTemplates - addFields", function(test) {
-    // Fake uninitialized state...
-    AccountsTemplates._initialized = false;
-
-    if (Meteor.isClient) {
-        // addFields does not exist client-side
-        test.throws(function() {
-            AccountsTemplates.addFields();
-        });
-    } else {
-        // Not an array of objects
-        test.throws(function() {
-            AccountsTemplates.addFields("");
-        }, function(err) {
-            if (err instanceof Error && err.message === "field argument should be an array of valid field objects!")
-                return true;
-        });
-        test.throws(function() {
-            AccountsTemplates.addFields(100);
-        }, function(err) {
-            if (err instanceof Error && err.message === "field argument should be an array of valid field objects!")
-                return true;
-        });
-        // Empty array
-        test.throws(function() {
-            AccountsTemplates.addFields([]);
-        }, function(err) {
-            if (err instanceof Error && err.message === "field argument should be an array of valid field objects!")
-                return true;
-        });
-
-        // Successful add
-        var first_name = {
-            _id: "first_name",
-            displayName: "First Name",
-            type: "text",
-            minLength: 2,
-            maxLength: 50,
-            required: true
-        };
-        var last_name = {
-            _id: "last_name",
-            displayName: "Last Name",
-            type: "text",
-            minLength: 2,
-            maxLength: 100,
-            required: false
-        };
-        AccountsTemplates.addFields([first_name, last_name]);
-        // Now removes ot to be consistend with tests re-run
-        AccountsTemplates.removeField("first_name");
-        AccountsTemplates.removeField("last_name");
-    }
-    // Restores initialized state...
-    AccountsTemplates._initialized = true;
-});
-
-
-Tinytest.add("AccountsTemplates - setState/getState", function(test) {
-    if (Meteor.isServer) {
-        // getState does not exist server-side
-        test.throws(function() {
-            AccountsTemplates.getState();
-        });
-        // setState does not exist server-side
-        test.throws(function() {
-            AccountsTemplates.setState();
-        });
-    } else {
-        _.each(AccountsTemplates.STATES, function(state){
-            AccountsTemplates.setState(state);
-            test.equal(AccountsTemplates.getState(), state);
-        });
-        // Setting an invalid state should throw a Meteor.Error
-        test.throws(function() {
-            AccountsTemplates.setState("foo");
-        }, function(err) {
-            if (err instanceof Meteor.Error && err.details == "accounts-templates-core package got an invalid state value!")
-                return true;
-        });
-    }
-});
-
-
-// -------------------------------------
-// TODO: complite the following tests...
-// -------------------------------------
-
-
-Tinytest.add("AccountsTemplates - configure", function(test) {
-    if (Meteor.isClient) {
-        // configure does not exist client-side
-        test.throws(function() {
-            AccountsTemplates.configure({});
-        });
-    } else {
-        // TODO: write actual tests...
-    }
-});

+ 0 - 13
packages/meteorx/package.js

@@ -1,13 +0,0 @@
-Package.describe({
-  name: 'meteorhacks:meteorx',
-  summary: 'Proxy for getting another meteorx fork',
-  version: '1.4.1'
-});
-
-Package.onUse((api) => {
-  api.export('MeteorX');
-  api.use([
-    'lamhieu:meteorx',
-  ]);
-});
-

+ 0 - 88
packages/wekan-accounts-cas/README.md

@@ -1,88 +0,0 @@
-This is a merged repository of useful forks of: atoy40:accounts-cas
-===================
-([(https://atmospherejs.com/atoy40/accounts-cas](https://atmospherejs.com/atoy40/accounts-cas))
-
-## Essential improvements by ppoulard to atoy40 and xaionaro versions
-
-* Added support of CAS attributes
-
-With this plugin, you can pick CAS attributes : https://github.com/joshchan/node-cas/wiki/CAS-Attributes
-
-Moved to Wekan GitHub org from from https://github.com/ppoulard/meteor-accounts-cas
-
-## Install
-
-```
-cd ~site
-mkdir packages
-cd packages
-git clone https://github.com/wekan/meteor-accounts-cas
-cd ~site
-meteor add wekan:accounts-cas
-```
-
-## Usage
-
-Put CAS settings in Meteor.settings (for example using METEOR_SETTINGS env or --settings) like so:
-
-If casVersion is not defined, it will assume you use CAS 1.0. (note by xaionaro: option `casVersion` seems to be just ignored in the code, ATM).
-
-Server side settings:
-
-```
-Meteor.settings = {
-    "cas": {
-        "baseUrl": "https://cas.example.com/cas",
-        "autoClose": true,
-        "validateUrl":"https://cas.example.com/cas/p3/serviceValidate",
-        "casVersion": 3.0,
-        "attributes": {
-            "debug" : true
-        }
-    },
-}
-```
-
-CAS `attributes` settings :
-
-* `attributes`: by default `{}` : all default values below will apply
-* *  `debug` : by default `false` ; `true` will print to the server console the CAS attribute names to map, the CAS attributes values retrieved, if necessary the new user account created, and finally the user to use
-* *  `id` : by default, the CAS user is used for the user account, but you can specified another CAS attribute
-* *  `firstname` : by default `cas:givenName` ; but you can use your own CAS attribute
-* *  `lastname` : by default `cas:sn` (respectively) ; but you can use your own CAS attribute
-* *  `fullname` : by default unused, but if you specify your own CAS attribute, it will be used instead of the `firstname` + `lastname`
-* *  `mail` : by default `cas:mail`
-
-Client side settings:
-
-```
-Meteor.settings = {
-	"public": {
-		"cas": {
-			"loginUrl": "https://cas.example.com/login",
-			"serviceParam": "service",
-			"popupWidth": 810,
-			"popupHeight": 610,
-			"popup": true,
-		}
-	}
-}
-```
-
-`proxyUrl` is not required. Setup [ROOT_URL](http://docs.meteor.com/api/core.html#Meteor-absoluteUrl) environment variable instead.
-
-Then, to start authentication, you have to call the following method from the client (for example in a click handler) :
-
-```
-Meteor.loginWithCas([callback]);
-```
-
-It must open a popup containing you CAS login form or redirect to the CAS login form (depending on "popup" setting).
-
-If popup is disabled (== false), then it's required to execute `Meteor.initCas([callback])` in `Meteor.startup` of the client side. ATM, `Meteor.initCas()` completes authentication.
-
-## Examples
-
-* [https://devel.mephi.ru/dyokunev/start-mephi-ru](https://devel.mephi.ru/dyokunev/start-mephi-ru)
-
-

+ 0 - 112
packages/wekan-accounts-cas/cas_client.js

@@ -1,112 +0,0 @@
-
-function addParameterToURL(url, param){
-  var urlSplit = url.split('?');
-  return url+(urlSplit.length>0 ? '?':'&') + param;
-}
-
-Meteor.initCas = function(callback) {
-    const casTokenMatch = window.location.href.match(/[?&]casToken=([^&]+)/);
-    if (casTokenMatch == null) {
-        return;
-    }
-
-    window.history.pushState('', document.title, window.location.href.replace(/([&?])casToken=[^&]+[&]?/, '$1').replace(/[?&]+$/g, ''));
-
-    Accounts.callLoginMethod({
-        methodArguments: [{ cas: { credentialToken: casTokenMatch[1] } }],
-        userCallback: function(err){
-            if (err == null) {
-                // should we do anything on success?
-            }
-            if (callback != null) {
-                callback(err);
-            }
-        }
-    });
-}
-
-Meteor.loginWithCas = function(options, callback) {
-
-    var credentialToken = Random.id();
-
-    if (!Meteor.settings.public &&
-        !Meteor.settings.public.cas &&
-        !Meteor.settings.public.cas.loginUrl) {
-        return;
-    }
-
-    var settings = Meteor.settings.public.cas;
-
-    var backURL = window.location.href.replace('#', '');
-    if (options != null && options.redirectUrl != null)
-        backURL = options.redirectUrl;
-
-    var serviceURL = addParameterToURL(backURL, 'casToken='+credentialToken);
-
-    var loginUrl = settings.loginUrl +
-        "?" + (settings.serviceParam || "service") + "=" +
-        encodeURIComponent(serviceURL)
-
-    if (settings.popup == false) {
-      window.location = loginUrl;
-      return;
-    }
-
-    var popup = openCenteredPopup(
-        loginUrl,
-        settings.width || 800,
-        settings.height || 600
-    );
-
-    var checkPopupOpen = setInterval(function() {
-        try {
-	    if(popup && popup.document && popup.document.getElementById('popupCanBeClosed')) {
-                popup.close();
-      	    }
-            // Fix for #328 - added a second test criteria (popup.closed === undefined)
-            // to humour this Android quirk:
-            // http://code.google.com/p/android/issues/detail?id=21061
-            var popupClosed = popup.closed || popup.closed === undefined;
-        } catch (e) {
-            // For some unknown reason, IE9 (and others?) sometimes (when
-            // the popup closes too quickly?) throws "SCRIPT16386: No such
-            // interface supported" when trying to read 'popup.closed'. Try
-            // again in 100ms.
-            return;
-        }
-
-        if (popupClosed) {
-            clearInterval(checkPopupOpen);
-
-            // check auth on server.
-            Accounts.callLoginMethod({
-                methodArguments: [{ cas: { credentialToken: credentialToken } }],
-                userCallback: callback
-            });
-        }
-    }, 100);
-};
-
-var openCenteredPopup = function(url, width, height) {
-  var screenX = typeof window.screenX !== 'undefined'
-  ? window.screenX : window.screenLeft;
-  var screenY = typeof window.screenY !== 'undefined'
-  ? window.screenY : window.screenTop;
-  var outerWidth = typeof window.outerWidth !== 'undefined'
-  ? window.outerWidth : document.body.clientWidth;
-  var outerHeight = typeof window.outerHeight !== 'undefined'
-  ? window.outerHeight : (document.body.clientHeight - 22);
-  // XXX what is the 22?
-
-  // Use `outerWidth - width` and `outerHeight - height` for help in
-  // positioning the popup centered relative to the current window
-  var left = screenX + (outerWidth - width) / 2;
-  var top = screenY + (outerHeight - height) / 2;
-  var features = ('width=' + width + ',height=' + height +
-      ',left=' + left + ',top=' + top + ',scrollbars=yes');
-
-  var newwindow = window.open(url, '_blank', features);
-  if (newwindow.focus)
-    newwindow.focus();
-  return newwindow;
-};

+ 0 - 71
packages/wekan-accounts-cas/cas_client_cordova.js

@@ -1,71 +0,0 @@
-
-Meteor.loginWithCas = function(callback) {
-
-  var credentialToken = Random.id();
-
-  if (!Meteor.settings.public &&
-      !Meteor.settings.public.cas &&
-      !Meteor.settings.public.cas.loginUrl) {
-    return;
-  }
-
-  var settings = Meteor.settings.public.cas;
-
-  var loginUrl = settings.loginUrl +
-      "?" + (settings.service || "service") + "=" +
-      Meteor.absoluteUrl('_cas/') +
-      credentialToken;
-
-
-  var fail = function (err) {
-    Meteor._debug("Error from OAuth popup: " + JSON.stringify(err));
-  };
-
-  // When running on an android device, we sometimes see the
-  // `pageLoaded` callback fire twice for the final page in the OAuth
-  // popup, even though the page only loads once. This is maybe an
-  // Android bug or maybe something intentional about how onPageFinished
-  // works that we don't understand and isn't well-documented.
-  var oauthFinished = false;
-
-  var pageLoaded = function (event) {
-    if (oauthFinished) {
-      return;
-    }
-
-    if (event.url.indexOf(Meteor.absoluteUrl('_cas')) === 0) {
-
-      oauthFinished = true;
-
-      // On iOS, this seems to prevent "Warning: Attempt to dismiss from
-      // view controller <MainViewController: ...> while a presentation
-      // or dismiss is in progress". My guess is that the last
-      // navigation of the OAuth popup is still in progress while we try
-      // to close the popup. See
-      // https://issues.apache.org/jira/browse/CB-2285.
-      //
-      // XXX Can we make this timeout smaller?
-      setTimeout(function () {
-        popup.close();
-        // check auth on server.
-        Accounts.callLoginMethod({
-          methodArguments: [{ cas: { credentialToken: credentialToken } }],
-          userCallback: callback
-        });
-      }, 100);
-    }
-  };
-
-  var onExit = function () {
-    popup.removeEventListener('loadstop', pageLoaded);
-    popup.removeEventListener('loaderror', fail);
-    popup.removeEventListener('exit', onExit);
-  };
-
-  var popup = window.open(loginUrl, '_blank', 'location=no,hidden=no');
-  popup.addEventListener('loadstop', pageLoaded);
-  popup.addEventListener('loaderror', fail);
-  popup.addEventListener('exit', onExit);
-  popup.show();
-
-};

+ 0 - 281
packages/wekan-accounts-cas/cas_server.js

@@ -1,281 +0,0 @@
-"use strict";
-
-const Fiber = Npm.require('fibers');
-const https = Npm.require('https');
-const url = Npm.require('url');
-const xmlParser = Npm.require('xml2js');
-
-// Library
-class CAS {
-  constructor(options) {
-    options = options || {};
-
-    if (!options.validate_url) {
-      throw new Error('Required CAS option `validateUrl` missing.');
-    }
-
-    if (!options.service) {
-      throw new Error('Required CAS option `service` missing.');
-    }
-
-    const cas_url = url.parse(options.validate_url);
-    if (cas_url.protocol != 'https:' ) {
-      throw new Error('Only https CAS servers are supported.');
-    } else if (!cas_url.hostname) {
-      throw new Error('Option `validateUrl` must be a valid url like: https://example.com/cas/serviceValidate');
-    } else {
-      this.hostname = cas_url.host;
-      this.port = 443;// Should be 443 for https
-      this.validate_path = cas_url.pathname;
-    }
-
-    this.service = options.service;
-  }
-
-  validate(ticket, callback) {
-    const httparams = {
-      host: this.hostname,
-      port: this.port,
-      path: url.format({
-        pathname: this.validate_path,
-        query: {ticket: ticket, service: this.service},
-      }),
-    };
-
-    https.get(httparams, (res) => {
-      res.on('error', (e) => {
-        console.log('error' + e);
-        callback(e);
-      });
-
-      // Read result
-      res.setEncoding('utf8');
-      let response = '';
-      res.on('data', (chunk) => {
-        response += chunk;
-      });
-
-      res.on('end', (error) => {
-        if (error) {
-          console.log('error callback');
-          console.log(error);
-          callback(undefined, false);
-        } else {
-          xmlParser.parseString(response, (err, result) => {
-            if (err) {
-              console.log('Bad response format.');
-              callback({message: 'Bad response format. XML could not parse it'});
-            } else {
-              if (result['cas:serviceResponse'] == null) {
-                console.log('Empty response.');
-                callback({message: 'Empty response.'});
-              }
-              if (result['cas:serviceResponse']['cas:authenticationSuccess']) {
-                var userData = {
-                  id: result['cas:serviceResponse']['cas:authenticationSuccess'][0]['cas:user'][0].toLowerCase(),
-                }
-                const attributes = result['cas:serviceResponse']['cas:authenticationSuccess'][0]['cas:attributes'][0];
-                for (var fieldName in attributes) {
-                  userData[fieldName] = attributes[fieldName][0];
-                };
-                callback(undefined, true, userData);
-              } else {
-                callback(undefined, false);
-              }
-            }
-          });
-        }
-      });
-    });
-  }
-}
-////// END OF CAS MODULE
-
-let _casCredentialTokens = {};
-let _userData = {};
-
-//RoutePolicy.declare('/_cas/', 'network');
-
-// Listen to incoming OAuth http requests
-WebApp.connectHandlers.use((req, res, next) => {
-  // Need to create a Fiber since we're using synchronous http calls and nothing
-  // else is wrapping this in a fiber automatically
-
-  Fiber(() => {
-    middleware(req, res, next);
-  }).run();
-});
-
-const middleware = (req, res, next) => {
-  // Make sure to catch any exceptions because otherwise we'd crash
-  // the runner
-  try {
-    urlParsed = url.parse(req.url, true);
-
-    // Getting the ticket (if it's defined in GET-params)
-    // If no ticket, then request will continue down the default
-    // middlewares.
-    const query = urlParsed.query;
-    if (query == null) {
-      next();
-      return;
-    }
-    const ticket = query.ticket;
-    if (ticket == null) {
-      next();
-      return;
-    }
-
-    const serviceUrl = Meteor.absoluteUrl(urlParsed.href.replace(/^\//g, '')).replace(/([&?])ticket=[^&]+[&]?/g, '$1').replace(/[?&]+$/g, '');
-    const redirectUrl = serviceUrl;//.replace(/([&?])casToken=[^&]+[&]?/g, '$1').replace(/[?&]+$/g, '');
-
-    // get auth token
-    const credentialToken = query.casToken;
-    if (!credentialToken) {
-      end(res, redirectUrl);
-      return;
-    }
-
-    // validate ticket
-    casValidate(req, ticket, credentialToken, serviceUrl, () => {
-      end(res, redirectUrl);
-    });
-
-  } catch (err) {
-    console.log("account-cas: unexpected error : " + err.message);
-    end(res, redirectUrl);
-  }
-};
-
-const casValidate = (req, ticket, token, service, callback) => {
-  // get configuration
-  if (!Meteor.settings.cas/* || !Meteor.settings.cas.validate*/) {
-    throw new Error('accounts-cas: unable to get configuration.');
-  }
-
-  const cas = new CAS({
-    validate_url: Meteor.settings.cas.validateUrl,
-    service: service,
-    version: Meteor.settings.cas.casVersion
-  });
-
-  cas.validate(ticket, (err, status, userData) => {
-    if (err) {
-      console.log("accounts-cas: error when trying to validate " + err);
-      console.log(err);
-    } else {
-      if (status) {
-        console.log(`accounts-cas: user validated ${userData.id}
-          (${JSON.stringify(userData)})`);
-        _casCredentialTokens[token] = { id: userData.id };
-        _userData = userData;
-      } else {
-        console.log("accounts-cas: unable to validate " + ticket);
-      }
-    }
-    callback();
-  });
-
-  return;
-};
-
-/*
- * Register a server-side login handle.
- * It is call after Accounts.callLoginMethod() is call from client.
- */
- Accounts.registerLoginHandler((options) => {
-  if (!options.cas)
-    return undefined;
-
-  if (!_hasCredential(options.cas.credentialToken)) {
-    throw new Meteor.Error(Accounts.LoginCancelledError.numericError,
-      'no matching login attempt found');
-  }
-
-  const result = _retrieveCredential(options.cas.credentialToken);
-
-  const attrs = Meteor.settings.cas.attributes || {};
-  // CAS keys
-  const fn = attrs.firstname || 'cas:givenName';
-  const ln = attrs.lastname || 'cas:sn';
-  const full = attrs.fullname;
-  const mail = attrs.mail || 'cas:mail'; // or 'email'
-  const uid = attrs.id || 'id';
-  if (attrs.debug) {
-    if (full) {
-      console.log(`CAS fields : id:"${uid}", fullname:"${full}", mail:"${mail}"`);
-    } else {
-      console.log(`CAS fields : id:"${uid}", firstname:"${fn}", lastname:"${ln}", mail:"${mail}"`);
-    }
-  }
-  const name = full ? _userData[full] : _userData[fn] + ' ' +  _userData[ln];
-  // https://docs.meteor.com/api/accounts.html#Meteor-users
-  options = {
-    // _id: Meteor.userId()
-    username: _userData[uid], // Unique name
-    emails: [
-      { address: _userData[mail], verified: true }
-    ],
-    createdAt: new Date(),
-    profile: {
-      // The profile is writable by the user by default.
-      name: name,
-      fullname : name,
-      email : _userData[mail]
-    },
-    active: true,
-    globalRoles: ['user']
-  };
-  if (attrs.debug) {
-    console.log(`CAS response : ${JSON.stringify(result)}`);
-  }
-  let user = Users.findOne({ 'username': options.username });
-  if (! user) {
-    if (attrs.debug) {
-      console.log(`Creating user account ${JSON.stringify(options)}`);
-    }
-    const userId = Accounts.insertUserDoc({}, options);
-    user = Users.findOne(userId);
-  }
-  if (attrs.debug) {
-    console.log(`Using user account ${JSON.stringify(user)}`);
-  }
-  return { userId: user._id };
-});
-
-const _hasCredential = (credentialToken) => {
-  return _.has(_casCredentialTokens, credentialToken);
-}
-
-/*
- * Retrieve token and delete it to avoid replaying it.
- */
-const _retrieveCredential = (credentialToken) => {
-  const result = _casCredentialTokens[credentialToken];
-  delete _casCredentialTokens[credentialToken];
-  return result;
-}
-
-const closePopup = (res) => {
-  if (Meteor.settings.cas && Meteor.settings.cas.popup == false) {
-    return;
-  }
-  res.writeHead(200, {'Content-Type': 'text/html'});
-  const content = '<html><body><div id="popupCanBeClosed"></div></body></html>';
-  res.end(content, 'utf-8');
-}
-
-const redirect = (res, whereTo) => {
-  res.writeHead(302, {'Location': whereTo});
-  const content = '<html><head><meta http-equiv="refresh" content="0; url='+whereTo+'" /></head><body>Redirection to <a href='+whereTo+'>'+whereTo+'</a></body></html>';
-  res.end(content, 'utf-8');
-  return
-}
-
-const end = (res, whereTo) => {
-  if (Meteor.settings.cas && Meteor.settings.cas.popup == false) {
-    redirect(res, whereTo);
-  } else {
-    closePopup(res);
-  }
-}

+ 0 - 29
packages/wekan-accounts-cas/package.js

@@ -1,29 +0,0 @@
-Package.describe({
-  summary: "CAS support for accounts",
-  version: "0.1.0",
-  name: "wekan-accounts-cas",
-  git: "https://github.com/wekan/wekan-accounts-cas"
-});
-
-Package.onUse(function(api) {
-  api.versionsFrom('METEOR@1.3.5.1');
-  api.use('routepolicy', 'server');
-  api.use('webapp', 'server');
-  api.use('accounts-base', ['client', 'server']);
-  // Export Accounts (etc) to packages using this one.
-  api.imply('accounts-base', ['client', 'server']);
-  api.use('underscore');
-  api.add_files('cas_client.js', 'web.browser');
-  api.add_files('cas_client_cordova.js', 'web.cordova');
-  api.add_files('cas_server.js', 'server');
-
-});
-
-Npm.depends({
-  xml2js: "0.4.17",
-  cas: "https://github.com/anrizal/node-cas/tarball/2baed530842e7a437f8f71b9346bcac8e84773cc"
-});
-
-Cordova.depends({
-  'cordova-plugin-inappbrowser': '1.2.0'
-});

+ 0 - 1
packages/wekan-accounts-oidc/.gitignore

@@ -1 +0,0 @@
-.versions

+ 0 - 14
packages/wekan-accounts-oidc/LICENSE.txt

@@ -1,14 +0,0 @@
-Copyright (C) 2016 SWITCH 
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-

+ 0 - 75
packages/wekan-accounts-oidc/README.md

@@ -1,75 +0,0 @@
-# salleman:accounts-oidc package
-
-A Meteor login service for OpenID Connect (OIDC).
-
-## Installation
-
-    meteor add salleman:accounts-oidc
-
-## Usage
-
-`Meteor.loginWithOidc(options, callback)`
-* `options` - object containing options, see below (optional)
-* `callback` - callback function (optional)
-
-#### Example
-
-```js
-Template.myTemplateName.events({
-  'click #login-button': function() {
-    Meteor.loginWithOidc();
-  }
-);
-```
-
-
-## Options
-
-These options override service configuration stored in the database.
-
-* `loginStyle`: `redirect` or `popup`
-* `redirectUrl`: Where to redirect after successful login. Only used if `loginStyle` is set to `redirect`
-
-## Manual Configuration Setup
-
-You can manually configure this package by upserting the service configuration on startup. First, add the `service-configuration` package:
-
-    meteor add service-configuration
-
-### Service Configuration
-
-The following service configuration are available:
-
-* `clientId`: OIDC client identifier
-* `secret`: OIDC client shared secret
-* `serverUrl`: URL of the OIDC server. e.g. `https://openid.example.org:8443`
-* `authorizationEndpoint`: Endpoint of the OIDC authorization service, e.g. `/oidc/authorize`
-* `tokenEndpoint`: Endpoint of the OIDC token service, e.g. `/oidc/token`
-* `userinfoEndpoint`: Endpoint of the OIDC userinfo service, e.g. `/oidc/userinfo`
-* `idTokenWhitelistFields`: A list of fields from IDToken to be added to Meteor.user().services.oidc object
-
-### Project Configuration
-
-Then in your project:
-
-```js
-if (Meteor.isServer) {
-  Meteor.startup(function () {
-    ServiceConfiguration.configurations.upsert(
-      { service: 'oidc' },
-      {
-        $set: {
-          loginStyle: 'redirect',
-          clientId: 'my-client-id-registered-with-the-oidc-server',
-          secret: 'my-client-shared-secret',
-          serverUrl: 'https://openid.example.org',
-          authorizationEndpoint: '/oidc/authorize',
-          tokenEndpoint: '/oidc/token',
-          userinfoEndpoint: '/oidc/userinfo',
-          idTokenWhitelistFields: []
-        }
-      }
-    );
-  });
-}
-```

+ 0 - 22
packages/wekan-accounts-oidc/oidc.js

@@ -1,22 +0,0 @@
-Accounts.oauth.registerService('oidc');
-
-if (Meteor.isClient) {
-  Meteor.loginWithOidc = function(options, callback) {
-    // support a callback without options
-    if (! callback && typeof options === "function") {
-      callback = options;
-      options = null;
-    }
-
-    var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);
-    Oidc.requestCredential(options, credentialRequestCompleteCallback);
-  };
-} else {
-  Accounts.addAutopublishFields({
-    // not sure whether the OIDC api can be used from the browser,
-    // thus not sure if we should be sending access tokens; but we do it
-    // for all other oauth2 providers, and it may come in handy.
-    forLoggedInUser: ['services.oidc'],
-    forOtherUsers: ['services.oidc.id']
-  });
-}

+ 0 - 3
packages/wekan-accounts-oidc/oidc_login_button.css

@@ -1,3 +0,0 @@
-#login-buttons-image-oidc {
-    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACQUlEQVQ4T5WTy2taQRTGv4kSXw0IoYIihCjFmhhfhUqW9a+o0I2LInTRRbtw05V2I9KQuuimi24KXQqChIhQQcQgGGNz0YpvMCG1yL1tGqvBZsKMIIXcjQcOcznnfL+ZOecOEUVx4/Ly8mQ6neqxhKlUKmltbc1Nut2uqJ/bEnJAkiTmEhEEgVqtViiVyjuAP70j/Pj6Htbglzu52WyGdrsNUq1Wqc1mk939+9sHPP7wTVM232g0QMrlMrXb7bIFndgcbAk3ZPP1eh2kVCrRra2tRcFoNEK1WoXf78fg3Rxsfl3H3t4e3G43dnd3wWrMZjNqtRpIsVhcAFKpFPL5PBfF43H8TDj49/2XAvb393F2dgaNRgNKKaLR6ByQz+epw+HAwcEBisUijEYjgsEg1Go1pA9ODtC/+MZFDCKKIo9FIhEIggCSy+Xozs4OYrEY2ChDoRAIIVww/ujhxdrnFTSbTX6Cfr+Pi4sLhMNhnJ6egmSzWepyuZBIJGAwGBAIBLiY2ezTI74qg2UoFIqFr6ys4OrqiveKHB4eckAmk8FgMMD29jZ8Ph8XKj4/5uu/ZyXZKXBAOp2mHo+H/0isD6zDOp0Om5ubsAuvcA+/8ffpkSygUqmApFIp6vV6+b2ZsNfrodVqYTgcwqXtwul04pfhiSzg+PgYJJlMUovFwhvIbHV1lTs70c3NDSaTCa6vr+8A2FvodDr8CmwuepPJtIDIbvdfkInPz89ZRCKFQmFjNBqdjMfjpZ6jVquV1tfX3bcYegI7CyIWlgAAAABJRU5ErkJggg==');
-}

+ 0 - 19
packages/wekan-accounts-oidc/package.js

@@ -1,19 +0,0 @@
-Package.describe({
-  summary: "OpenID Connect (OIDC) for Meteor accounts",
-  version: "1.0.10",
-  name: "wekan-accounts-oidc",
-  git: "https://github.com/wekan/meteor-accounts-oidc.git",
-
-});
-
-Package.onUse(function(api) {
-  api.use('accounts-base@1.2.0', ['client', 'server']);
-  // Export Accounts (etc) to packages using this one.
-  api.imply('accounts-base', ['client', 'server']);
-  api.use('accounts-oauth@1.1.0', ['client', 'server']);
-  api.use('wekan-oidc@1.0.10', ['client', 'server']);
-
-  api.addFiles('oidc_login_button.css', 'client');
-
-  api.addFiles('oidc.js');
-});

+ 0 - 5
packages/wekan-cfs-access-point/.travis.yml

@@ -1,5 +0,0 @@
-language: node_js
-node_js:
-  - "0.10"
-before_install:
-  - "curl -L http://git.io/s0Zu-w | /bin/sh"

+ 0 - 288
packages/wekan-cfs-access-point/CHANGELOG.md

@@ -1,288 +0,0 @@
-# Changelog
-
-## [v0.1.50] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.46)
-#### 21/1/19 by Harry Adel
-
-- Bump to version 0.1.50
-
-- *Merged pull-request:* "filename conversion for FS.HTTP.Handlers.Get" [#9](https://github.com/zcfs/Meteor-CollectionFS/pull/994) ([yatusiter](https://github.com/yatusiter))
-
-
-
-## [v0.1.46] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.46)
-#### 30/3/15 by Eric Dobbertin
-
-- Bump to version 0.1.46
-
-- *Merged pull-request:* [#611](https://github.com/zcfs/Meteor-CollectionFS/issues/611)
-
-- Exposed request handlers on `FS.HTTP.Handlers` object so that app can override
-
-## [v0.1.43] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.43)
-#### 20/12/14 by Morten Henriksen
-- add changelog
-
-- Bump to version 0.1.43
-
-- *Fixed bug:* "Doesn't work in IE 8" [#10](https://github.com/zcfs/Meteor-cfs-access-point/issues/10)
-
-- *Merged pull-request:* "rootUrlPathPrefix fix for cordova" [#9](https://github.com/zcfs/Meteor-cfs-access-point/issues/9) ([dmitriyles](https://github.com/dmitriyles))
-
-- *Merged pull-request:* "Support for expiration token" [#1](https://github.com/zcfs/Meteor-cfs-access-point/issues/1) ([tanis2000](https://github.com/tanis2000))
-
-Patches by GitHub users [@dmitriyles](https://github.com/dmitriyles), [@tanis2000](https://github.com/tanis2000).
-
-## [v0.1.42] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.42)
-#### 17/12/14 by Morten Henriksen
-## [v0.1.41] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.41)
-#### 17/12/14 by Morten Henriksen
-- mbr update, remove versions.json
-
-- Cordova rootUrlPathPrefix fix
-
-- Bump to version 0.1.41
-
-## [v0.1.40] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.40)
-#### 17/12/14 by Morten Henriksen
-- mbr fixed warnings
-
-- fixes to GET handler
-
-- add back tests
-
-- support apps in server subdirectories; closes #8
-
-- 0.9.1 support
-
-## [v0.0.39] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.39)
-#### 28/08/14 by Morten Henriksen
-- Meteor Package System Update
-
-## [v0.0.38] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.38)
-#### 27/08/14 by Eric Dobbertin
-## [v0.0.37] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.37)
-#### 26/08/14 by Eric Dobbertin
-- change package name to lowercase
-
-## [v0.0.36] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.36)
-#### 06/08/14 by Eric Dobbertin
-- pass correct arg
-
-## [v0.0.35] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.35)
-#### 06/08/14 by Eric Dobbertin
-- move to correct place
-
-## [v0.0.34] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.34)
-#### 05/08/14 by Eric Dobbertin
-- *Merged pull-request:* "Added contentLength for ranges and inline content" [#5](https://github.com/zcfs/Meteor-cfs-access-point/issues/5) ([maomorales](https://github.com/maomorales))
-
-- Content-Length and Last-Modified headers
-
-Patches by GitHub user [@maomorales](https://github.com/maomorales).
-
-## [v0.0.33] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.33)
-#### 31/07/14 by Eric Dobbertin
-- *Merged pull-request:* "Force browser to download with filename passed in url" [#3](https://github.com/zcfs/Meteor-cfs-access-point/issues/3) ([elbowz](https://github.com/elbowz))
-
-- Force browser to download with filename passed in url
-
-Patches by GitHub user [@elbowz](https://github.com/elbowz).
-
-## [v0.0.32] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.32)
-#### 28/07/14 by Eric Dobbertin
-- support collection-specific GET headers
-
-- update API docs
-
-## [v0.0.31] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.31)
-#### 06/07/14 by Eric Dobbertin
-- allow override filename
-
-## [v0.0.30] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.30)
-#### 30/04/14 by Eric Dobbertin
-- ignore auth on server so that url method can be called on the server
-
-## [v0.0.29] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.29)
-#### 30/04/14 by Eric Dobbertin
-- rework the new authtoken stuff to make it easier to debug and cleaner
-
-## [v0.0.28] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.28)
-#### 29/04/14 by Eric Dobbertin
-- generate api docs
-
-- adjustments to use new FS.File API functions, plus have `url` function omit query string whenever possible
-
-- *Merged pull-request:* "Support for expiration token" [#1](https://github.com/zcfs/Meteor-cfs-access-point/issues/1) ([tanis2000](https://github.com/tanis2000))
-
-- Switched to HTTP.call() to get the server time
-
-- Better check for options.auth being a number. Check to see if we have Buffer() available on the server side. New check to make sure we have the token. Switched Metheor.method to HTTP.methods for the getServerTime() function.
-
-- Expiration is now optional. If auth is set to a number, that is the number of seconds the token is valid for.
-
-- Added time sync with the server for token generation.
-
-- Added code to pass a token with a set expiration date from the client. Added token check on the server side.
-
-Patches by GitHub user [@tanis2000](https://github.com/tanis2000).
-
-## [v0.0.27] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.27)
-#### 08/04/14 by Eric Dobbertin
-- clean up/fix whole-file upload handler
-
-## [v0.0.26] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.26)
-#### 07/04/14 by Eric Dobbertin
-- add URL options to get temporary images while uploading and storing
-
-## [v0.0.25] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.25)
-#### 03/04/14 by Eric Dobbertin
-- * allow `setBaseUrl` to be called either outside of Meteor.startup or inside * move encodeParams helper to FS.Utility
-
-## [v0.0.24] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.24)
-#### 03/04/14 by Eric Dobbertin
-- properly remount URLs
-
-- when uploading chunks, check the insert allow/deny since it's part of inserting
-
-## [v0.0.23] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.23)
-#### 31/03/14 by Eric Dobbertin
-- use latest releases
-
-## [v0.0.22] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.22)
-#### 29/03/14 by Morten Henriksen
-- remove underscore deps
-
-## [v0.0.21] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.21)
-#### 25/03/14 by Morten Henriksen
-- add comments about shareId
-
-## [v0.0.20] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.20)
-#### 23/03/14 by Morten Henriksen
-- Rollback to specific git dependency
-
-- Try modified test script
-
-- deps are already in collectionFS
-
-## [v0.0.19] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.19)
-#### 22/03/14 by Morten Henriksen
-- try to fix travis test by using general package references
-
-## [v0.0.18] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.18)
-#### 22/03/14 by Morten Henriksen
-- If the read stream fails we send an error to the client
-
-## [v0.0.17] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.17)
-#### 21/03/14 by Morten Henriksen
-- remove smart lock
-
-- commit smart.lock, trying to get tests to pass on travis
-
-- some minor pkg adjustments; trying to get tests to pass on travis
-
-## [v0.0.16] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.16)
-#### 18/03/14 by Morten Henriksen
-- Rollback to using the direct storage adapter - makes more sense when serving files
-
-- shift to new http.methods streaming api
-
-- move server side DDP access points to cfs-download-ddp pkg; update API docs
-
-- fix typo...
-
-- return something useful
-
-- convert to streaming
-
-- Add streaming WIP
-
-- fix/adjust some tests; minor improvements to some handlers
-
-- Add unmount and allow mount to use default selector function
-
-- Refactor access point - wip
-
-## [v0.0.15] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.15)
-#### 05/03/14 by Morten Henriksen
-- Refactor note, encode stuff should be prefixed into FS.Utility
-
-- FS.File.url add user deps when auth is used
-
-- fix url method
-
-- query string fix
-
-- move PUT access points for HTTP upload into this package; mount DELETE on /record/ as well as /files/; some fixes and improvements to handlers
-
-## [v0.0.14] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.14)
-#### 03/03/14 by Eric Dobbertin
-- better error; return Buffer instead of converting to Uint8Array
-
-## [v0.0.13] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.13)
-#### 02/03/14 by Eric Dobbertin
-- more tests, make everything work, add unpublish method
-
-- Merge branch 'master' of https://github.com/zcfs/Meteor-cfs-access-point
-
-## [v0.0.12] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.12)
-#### 01/03/14 by Eric Dobbertin
-- add travis-ci image
-
-- rework URLs a bit, use http-publish package to publish FS.Collection listing, and add a test for this (!)
-
-- add http-publish dependency
-
-- del should be delete
-
-## [v0.0.11] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.11)
-#### 28/02/14 by Eric Dobbertin
-- move some code to other packages; redo the HTTP GET/DEL methods
-
-## [v0.0.10] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.10)
-#### 28/02/14 by Eric Dobbertin
-- move DDP upload methods to new cfs-upload-ddp package
-
-## [v0.0.9] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.9)
-#### 21/02/14 by Eric Dobbertin
-- new URL syntax; use the store's file key instead of ID; also fix allow/deny checks with insecure
-
-## [v0.0.8] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.8)
-#### 20/02/14 by Eric Dobbertin
-- support HTTP PUT of new file and fix PUT of existing file
-
-## [v0.0.7] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.7)
-#### 17/02/14 by Morten Henriksen
-- add http-methods dependency
-
-## [v0.0.6] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.6)
-#### 16/02/14 by Morten Henriksen
-## [v0.0.5] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.5)
-#### 16/02/14 by Morten Henriksen
-- a few fixes and improvements
-
-- need to actually mount it
-
-- attempt at switching to generic HTTP access point; also add support for chunked http downloads (range header)
-
-## [v0.0.4] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.4)
-#### 15/02/14 by Morten Henriksen
-- Merge branch 'master' of https://github.com/zcfs/Meteor-cfs-access-point
-
-- corrected typo
-
-- added debugging
-
-- call HTTP.methods on server only
-
-- run client side, too, for side effects
-
-- rework for additional abstraction; also DDP methods don't need to be per-collection so they no longer are
-
-## [v0.0.3] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.3)
-#### 13/02/14 by Morten Henriksen
-## [v0.0.2] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.2)
-#### 13/02/14 by Morten Henriksen
-## [v0.0.1] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.1)
-#### 13/02/14 by Morten Henriksen
-- init commit
-

+ 0 - 20
packages/wekan-cfs-access-point/LICENSE.md

@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0 - 32
packages/wekan-cfs-access-point/README.md

@@ -1,32 +0,0 @@
-wekan-cfs-access-point [![Build Status](https://travis-ci.org/CollectionFS/Meteor-cfs-access-point.png?branch=master)](https://travis-ci.org/CollectionFS/Meteor-cfs-access-point)
-=========================
-
-This is a Meteor package used by
-[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS).
-
-You don't need to manually add this package to your app. It is added when you
-add the `wekan-cfs-standard-packages` package. You could potentially use your own access point
-package instead.
-
-## Define a URL for Collection Listing
-
-To define a URL that accepts GET requests and returns a list of published
-files in a FS.Collection:
-
-```js
-Images = new FS.Collection("images", {
- stores: [myStore]
-});
-
-FS.HTTP.publish(Images, function () {
-  // `this` provides a context similar to Meteor.publish
-  return Images.find();
-});
-```
-
-The URL will be '/cfs/record/images', where the `cfs` piece is configurable
-using the `FS.HTTP.setBaseUrl` method.
-
-## API Documentation
-
-[Here](api.md)

+ 0 - 58
packages/wekan-cfs-access-point/access-point-client.js

@@ -1,58 +0,0 @@
-FS.HTTP.setHeadersForGet = function setHeadersForGet() {
-  // Client Stub
-};
-
-FS.HTTP.now = function() {
-  return new Date(new Date() + FS.HTTP._serverTimeDiff);
-};
-
-// Returns the localstorage if its found and working
-// TODO: check if this works in IE
-// could use Meteor._localStorage - just needs a rewrite
-FS.HTTP._storage = function() {
-  var storage,
-      fail,
-      uid;
-  try {
-    uid = "test";
-    (storage = window.localStorage).setItem(uid, uid);
-    fail = (storage.getItem(uid) !== uid);
-    storage.removeItem(uid);
-    if (fail) {
-      storage = false;
-    }
-  } catch(e) {
-    console.log("Error initializing storage for FS.HTTP");
-    console.log(e);
-  }
-
-  return storage;
-};
-
-// get our storage if found
-FS.HTTP.storage = FS.HTTP._storage();
-
-FS.HTTP._prefix = 'fsHTTP.';
-
-FS.HTTP._serverTimeDiff = 0; // Time difference in ms
-
-if (FS.HTTP.storage) {
-  // Initialize the FS.HTTP._serverTimeDiff
-  FS.HTTP._serverTimeDiff = (1*FS.HTTP.storage.getItem(FS.HTTP._prefix+'timeDiff')) || 0;
-  // At client startup we figure out the time difference between server and
-  // client time - this includes lag and timezone
-  Meteor.startup(function() {
-    // Call the server method an get server time
-    HTTP.get(rootUrlPathPrefix + '/cfs/servertime', function(error, result) {
-      if (!error) {
-        // Update our server time diff
-        var dateNew = new Date(+result.content);
-        FS.HTTP._serverTimeDiff = dateNew - new Date();// - lag or/and timezone
-        // Update the localstorage
-        FS.HTTP.storage.setItem(FS.HTTP._prefix + 'timeDiff', FS.HTTP._serverTimeDiff);
-      } else {
-      	console.log(error.message);
-      }
-    }); // EO Server call
-  });
-}

+ 0 - 199
packages/wekan-cfs-access-point/access-point-common.js

@@ -1,199 +0,0 @@
-rootUrlPathPrefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || "";
-// Adjust the rootUrlPathPrefix if necessary
-if (rootUrlPathPrefix.length > 0) {
-  if (rootUrlPathPrefix.slice(0, 1) !== '/') {
-    rootUrlPathPrefix = '/' + rootUrlPathPrefix;
-  }
-  if (rootUrlPathPrefix.slice(-1) === '/') {
-    rootUrlPathPrefix = rootUrlPathPrefix.slice(0, -1);
-  }
-}
-
-// prepend ROOT_URL when isCordova
-if (Meteor.isCordova) {
-  rootUrlPathPrefix = Meteor.absoluteUrl(rootUrlPathPrefix.replace(/^\/+/, '')).replace(/\/+$/, '');
-}
-
-baseUrl = '/cfs';
-FS.HTTP = FS.HTTP || {};
-
-// Note the upload URL so that client uploader packages know what it is
-FS.HTTP.uploadUrl = rootUrlPathPrefix + baseUrl + '/files';
-
-/**
- * @method FS.HTTP.setBaseUrl
- * @public
- * @param {String} newBaseUrl - Change the base URL for the HTTP GET and DELETE endpoints.
- * @returns {undefined}
- */
-FS.HTTP.setBaseUrl = function setBaseUrl(newBaseUrl) {
-
-  // Adjust the baseUrl if necessary
-  if (newBaseUrl.slice(0, 1) !== '/') {
-    newBaseUrl = '/' + newBaseUrl;
-  }
-  if (newBaseUrl.slice(-1) === '/') {
-    newBaseUrl = newBaseUrl.slice(0, -1);
-  }
-
-  // Update the base URL
-  baseUrl = newBaseUrl;
-
-  // Change the upload URL so that client uploader packages know what it is
-  FS.HTTP.uploadUrl = rootUrlPathPrefix + baseUrl + '/files';
-
-  // Remount URLs with the new baseUrl, unmounting the old, on the server only.
-  // If existingMountPoints is empty, then we haven't run the server startup
-  // code yet, so this new URL will be used at that point for the initial mount.
-  if (Meteor.isServer && !FS.Utility.isEmpty(_existingMountPoints)) {
-    mountUrls();
-  }
-};
-
-/*
- * FS.File extensions
- */
-
-/**
- * @method FS.File.prototype.urlRelative Construct the file url
- * @public
- * @param {Object} [options]
- * @param {String} [options.store] Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used.
- * @param {Boolean} [options.auth=null] Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds.
- * @param {Boolean} [options.download=false] Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser.
- * @param {Boolean} [options.brokenIsFine=false] Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet.
- * @param {Boolean} [options.returnWhenStored=false] Flag relevant only on server, Return the URL only when file has been saved to the requested store.
- * @param {Boolean} [options.metadata=false] Return the URL for the file metadata access point rather than the file itself.
- * @param {String} [options.uploading=null] A URL to return while the file is being uploaded.
- * @param {String} [options.storing=null] A URL to return while the file is being stored.
- * @param {String} [options.filename=null] Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store.
- *
- * Returns the relative HTTP URL for getting the file or its metadata.
- */
-FS.File.prototype.urlRelative = function(options) {
-  var self = this;
-  options = options || {};
-  options = FS.Utility.extend({
-    store: null,
-    auth: null,
-    download: false,
-    metadata: false,
-    brokenIsFine: false,
-    returnWhenStored: false,
-    uploading: null, // return this URL while uploading
-    storing: null, // return this URL while storing
-    filename: null // override the filename that is shown to the user
-  }, options.hash || options); // check for "hash" prop if called as helper
-
-  // Primarily useful for displaying a temporary image while uploading an image
-  if (options.uploading && !self.isUploaded()) {
-    return options.uploading;
-  }
-
-  if (self.isMounted()) {
-    // See if we've stored in the requested store yet
-    var storeName = options.store || self.collection.primaryStore.name;
-    if (!self.hasStored(storeName)) {
-      if (options.storing) {
-        return options.storing;
-      } else if (!options.brokenIsFine) {
-        // In case we want to get back the url only when he is stored
-        if (Meteor.isServer && options.returnWhenStored) {
-          // Wait till file is stored to storeName
-          self.onStored(storeName);
-        } else {
-          // We want to return null if we know the URL will be a broken
-          // link because then we can avoid rendering broken links, broken
-          // images, etc.
-          return null;
-        }
-      }
-    }
-
-    // Add filename to end of URL if we can determine one
-    var filename = options.filename || self.name({store: storeName});
-    if (typeof filename === "string" && filename.length) {
-      filename = '/' + filename;
-    } else {
-      filename = '';
-    }
-
-    // TODO: Could we somehow figure out if the collection requires login?
-    var authToken = '';
-    if (Meteor.isClient && typeof Accounts !== "undefined" && typeof Accounts._storedLoginToken === "function") {
-      if (options.auth !== false) {
-        // Add reactive deps on the user
-        Meteor.userId();
-
-        var authObject = {
-          authToken: Accounts._storedLoginToken() || ''
-        };
-
-        // If it's a number, we use that as the expiration time (in seconds)
-        if (options.auth === +options.auth) {
-          authObject.expiration = FS.HTTP.now() + options.auth * 1000;
-        }
-
-        // Set the authToken
-        var authString = JSON.stringify(authObject);
-        authToken = FS.Utility.btoa(authString);
-      }
-    } else if (typeof options.auth === "string") {
-      // If the user supplies auth token the user will be responsible for
-      // updating
-      authToken = options.auth;
-    }
-
-    // Construct query string
-    var params = {};
-    if (authToken !== '') {
-      params.token = authToken;
-    }
-    if (options.download) {
-      params.download = true;
-    }
-    if (options.store) {
-      // We use options.store here instead of storeName because we want to omit the queryString
-      // whenever possible, allowing users to have "clean" URLs if they want. The server will
-      // assume the first store defined on the server, which means that we are assuming that
-      // the first on the client is also the first on the server. If that's not the case, the
-      // store option should be supplied.
-      params.store = options.store;
-    }
-    var queryString = FS.Utility.encodeParams(params);
-    if (queryString.length) {
-      queryString = '?' + queryString;
-    }
-
-    // Determine which URL to use
-    var area;
-    if (options.metadata) {
-      area = '/record';
-    } else {
-      area = '/files';
-    }
-
-    // Construct and return the http method url
-    return baseUrl + area + '/' + self.collection.name + '/' + self._id + filename + queryString;
-  }
-};
-
-/**
- * @method FS.File.prototype.url Construct the file url
- * @public
- * @param {Object} [options]
- * @param {String} [options.store] Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used.
- * @param {Boolean} [options.auth=null] Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds.
- * @param {Boolean} [options.download=false] Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser.
- * @param {Boolean} [options.brokenIsFine=false] Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet.
- * @param {Boolean} [options.metadata=false] Return the URL for the file metadata access point rather than the file itself.
- * @param {String} [options.uploading=null] A URL to return while the file is being uploaded.
- * @param {String} [options.storing=null] A URL to return while the file is being stored.
- * @param {String} [options.filename=null] Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store.
- *
- * Returns the HTTP URL for getting the file or its metadata.
- */
-FS.File.prototype.url = function(options) {
-  self = this;
-  return  rootUrlPathPrefix + self.urlRelative(options);
-};

+ 0 - 307
packages/wekan-cfs-access-point/access-point-handlers.js

@@ -1,307 +0,0 @@
-getHeaders = [];
-getHeadersByCollection = {};
-
-var contentDisposition = Npm.require('content-disposition');
-
-FS.HTTP.Handlers = {};
-
-/**
- * @method FS.HTTP.Handlers.Del
- * @public
- * @returns {any} response
- *
- * HTTP DEL request handler
- */
-FS.HTTP.Handlers.Del = function httpDelHandler(ref) {
-  var self = this;
-  var opts = FS.Utility.extend({}, self.query || {}, self.params || {});
-
-  // If DELETE request, validate with 'remove' allow/deny, delete the file, and return
-  FS.Utility.validateAction(ref.collection.files._validators['remove'], ref.file, self.userId);
-
-  /*
-   * From the DELETE spec:
-   * A successful response SHOULD be 200 (OK) if the response includes an
-   * entity describing the status, 202 (Accepted) if the action has not
-   * yet been enacted, or 204 (No Content) if the action has been enacted
-   * but the response does not include an entity.
-   */
-  self.setStatusCode(200);
-
-  return {
-    deleted: !!ref.file.remove()
-  };
-};
-
-/**
- * @method FS.HTTP.Handlers.GetList
- * @public
- * @returns {Object} response
- *
- * HTTP GET file list request handler
- */
-FS.HTTP.Handlers.GetList = function httpGetListHandler() {
-  // Not Yet Implemented
-  // Need to check publications and return file list based on
-  // what user is allowed to see
-};
-
-/*
-  requestRange will parse the range set in request header - if not possible it
-  will throw fitting errors and autofill range for both partial and full ranges
-
-  throws error or returns the object:
-  {
-    start
-    end
-    length
-    unit
-    partial
-  }
-*/
-var requestRange = function(req, fileSize) {
-  if (req) {
-    if (req.headers) {
-      var rangeString = req.headers.range;
-
-      // Make sure range is a string
-      if (rangeString === ''+rangeString) {
-
-        // range will be in the format "bytes=0-32767"
-        var parts = rangeString.split('=');
-        var unit = parts[0];
-
-        // Make sure parts consists of two strings and range is of type "byte"
-        if (parts.length == 2 && unit == 'bytes') {
-          // Parse the range
-          var range = parts[1].split('-');
-          var start = Number(range[0]);
-          var end = Number(range[1]);
-
-          // Fix invalid ranges?
-          if (range[0] != start) start = 0;
-          if (range[1] != end || !end) end = fileSize - 1;
-
-          // Make sure range consists of a start and end point of numbers and start is less than end
-          if (start < end) {
-
-            var partSize = 0 - start + end + 1;
-
-            // Return the parsed range
-            return {
-              start: start,
-              end: end,
-              length: partSize,
-              size: fileSize,
-              unit: unit,
-              partial: (partSize < fileSize)
-            };
-
-          } else {
-            throw new Meteor.Error(416, "Requested Range Not Satisfiable");
-          }
-
-        } else {
-          // The first part should be bytes
-          throw new Meteor.Error(416, "Requested Range Unit Not Satisfiable");
-        }
-
-      } else {
-        // No range found
-      }
-
-    } else {
-      // throw new Error('No request headers set for _parseRange function');
-    }
-  } else {
-    throw new Error('No request object passed to _parseRange function');
-  }
-
-  return {
-    start: 0,
-    end: fileSize - 1,
-    length: fileSize,
-    size: fileSize,
-    unit: 'bytes',
-    partial: false
-  };
-};
-
-/**
- * @method FS.HTTP.Handlers.Get
- * @public
- * @returns {any} response
- *
- * HTTP GET request handler
- */
-FS.HTTP.Handlers.Get = function httpGetHandler(ref) {
-  var self = this;
-  // Once we have the file, we can test allow/deny validators
-  // XXX: pass on the "share" query eg. ?share=342hkjh23ggj for shared url access?
-  FS.Utility.validateAction(ref.collection._validators['download'], ref.file, self.userId /*, self.query.shareId*/);
-
-  var storeName = ref.storeName;
-
-  // If no storeName was specified, use the first defined storeName
-  if (typeof storeName !== "string") {
-    // No store handed, we default to primary store
-    storeName = ref.collection.primaryStore.name;
-  }
-
-  // Get the storage reference
-  var storage = ref.collection.storesLookup[storeName];
-
-  if (!storage) {
-    throw new Meteor.Error(404, "Not Found", 'There is no store "' + storeName + '"');
-  }
-
-  // Get the file
-  var copyInfo = ref.file.copies[storeName];
-
-  if (!copyInfo) {
-    throw new Meteor.Error(404, "Not Found", 'This file was not stored in the ' + storeName + ' store');
-  }
-
-  // Set the content type for file
-  if (typeof copyInfo.type === "string") {
-    self.setContentType(copyInfo.type);
-  } else {
-    self.setContentType('application/octet-stream');
-  }
-
-  // Add 'Content-Disposition' header if requested a download/attachment URL
-  if (typeof ref.download !== "undefined") {
-    var filename = ref.filename || copyInfo.name;
-    self.addHeader('Content-Disposition', contentDisposition(filename));
-  } else {
-    self.addHeader('Content-Disposition', 'inline');
-  }
-
-  // Get the contents range from request
-  var range = requestRange(self.request, copyInfo.size);
-
-  // Some browsers cope better if the content-range header is
-  // still included even for the full file being returned.
-  self.addHeader('Content-Range', range.unit + ' ' + range.start + '-' + range.end + '/' + range.size);
-
-  // If a chunk/range was requested instead of the whole file, serve that'
-  if (range.partial) {
-    self.setStatusCode(206, 'Partial Content');
-  } else {
-    self.setStatusCode(200, 'OK');
-  }
-
-  // Add any other global custom headers and collection-specific custom headers
-  FS.Utility.each(getHeaders.concat(getHeadersByCollection[ref.collection.name] || []), function(header) {
-    self.addHeader(header[0], header[1]);
-  });
-
-  // Inform clients about length (or chunk length in case of ranges)
-  self.addHeader('Content-Length', range.length);
-
-  // Last modified header (updatedAt from file info)
-  self.addHeader('Last-Modified', copyInfo.updatedAt.toUTCString());
-
-  // Inform clients that we accept ranges for resumable chunked downloads
-  self.addHeader('Accept-Ranges', range.unit);
-
-  if (FS.debug) console.log('Read file "' + (ref.filename || copyInfo.name) + '" ' + range.unit + ' ' + range.start + '-' + range.end + '/' + range.size);
-
-  var readStream = storage.adapter.createReadStream(ref.file, {start: range.start, end: range.end});
-
-  readStream.on('error', function(err) {
-    // Send proper error message on get error
-    if (err.message && err.statusCode) {
-      self.Error(new Meteor.Error(err.statusCode, err.message));
-    } else {
-      self.Error(new Meteor.Error(503, 'Service unavailable'));
-    }
-  });
-
-  readStream.pipe(self.createWriteStream());
-};
-
-// File with unicode or other encodings filename can upload to server susscessfully,
-// but when download, the  HTTP header "Content-Disposition" cannot accept 
-// characters other than ASCII, the filename should be converted to binary or URI encoded.
-// https://github.com/wekan/wekan/issues/784
-const originalHandler = FS.HTTP.Handlers.Get;
-FS.HTTP.Handlers.Get = function (ref) {
-  try {
-      var userAgent = (this.requestHeaders['user-agent']||'').toLowerCase();
-      if(userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) {
-          ref.filename =  encodeURIComponent(ref.filename);
-      } else if(userAgent.indexOf('firefox') >= 0) {
-          ref.filename = new Buffer(ref.filename).toString('binary');
-      } else {
-          /* safari*/
-          ref.filename = new Buffer(ref.filename).toString('binary');
-      }   
-   } catch (ex){
-        ref.filename = ref.filename;
-   } 
-   return originalHandler.call(this, ref);
-};
-
-
-/**
- * @method FS.HTTP.Handlers.PutInsert
- * @public
- * @returns {Object} response object with _id property
- *
- * HTTP PUT file insert request handler
- */
-FS.HTTP.Handlers.PutInsert = function httpPutInsertHandler(ref) {
-  var self = this;
-  var opts = FS.Utility.extend({}, self.query || {}, self.params || {});
-
-  FS.debug && console.log("HTTP PUT (insert) handler");
-
-  // Create the nice FS.File
-  var fileObj = new FS.File();
-
-  // Set its name
-  fileObj.name(opts.filename || null);
-
-  // Attach the readstream as the file's data
-  fileObj.attachData(self.createReadStream(), {type: self.requestHeaders['content-type'] || 'application/octet-stream'});
-
-  // Validate with insert allow/deny
-  FS.Utility.validateAction(ref.collection.files._validators['insert'], fileObj, self.userId);
-
-  // Insert file into collection, triggering readStream storage
-  ref.collection.insert(fileObj);
-
-  // Send response
-  self.setStatusCode(200);
-
-  // Return the new file id
-  return {_id: fileObj._id};
-};
-
-/**
- * @method FS.HTTP.Handlers.PutUpdate
- * @public
- * @returns {Object} response object with _id and chunk properties
- *
- * HTTP PUT file update chunk request handler
- */
-FS.HTTP.Handlers.PutUpdate = function httpPutUpdateHandler(ref) {
-  var self = this;
-  var opts = FS.Utility.extend({}, self.query || {}, self.params || {});
-
-  var chunk = parseInt(opts.chunk, 10);
-  if (isNaN(chunk)) chunk = 0;
-
-  FS.debug && console.log("HTTP PUT (update) handler received chunk: ", chunk);
-
-  // Validate with insert allow/deny; also mounts and retrieves the file
-  FS.Utility.validateAction(ref.collection.files._validators['insert'], ref.file, self.userId);
-
-  self.createReadStream().pipe( FS.TempStore.createWriteStream(ref.file, chunk) );
-
-  // Send response
-  self.setStatusCode(200);
-
-  return { _id: ref.file._id, chunk: chunk };
-};

+ 0 - 362
packages/wekan-cfs-access-point/access-point-server.js

@@ -1,362 +0,0 @@
-var path = Npm.require("path");
-
-HTTP.publishFormats({
-  fileRecordFormat: function (input) {
-    // Set the method scope content type to json
-    this.setContentType('application/json');
-    if (FS.Utility.isArray(input)) {
-      return EJSON.stringify(FS.Utility.map(input, function (obj) {
-        return FS.Utility.cloneFileRecord(obj);
-      }));
-    } else {
-      return EJSON.stringify(FS.Utility.cloneFileRecord(input));
-    }
-  }
-});
-
-/**
- * @method FS.HTTP.setHeadersForGet
- * @public
- * @param {Array} headers - List of headers, where each is a two-item array in which item 1 is the header name and item 2 is the header value.
- * @param {Array|String} [collections] - Which collections the headers should be added for. Omit this argument to add the header for all collections.
- * @returns {undefined}
- */
-FS.HTTP.setHeadersForGet = function setHeadersForGet(headers, collections) {
-  if (typeof collections === "string") {
-    collections = [collections];
-  }
-  if (collections) {
-    FS.Utility.each(collections, function(collectionName) {
-      getHeadersByCollection[collectionName] = headers || [];
-    });
-  } else {
-    getHeaders = headers || [];
-  }
-};
-
-/**
- * @method FS.HTTP.publish
- * @public
- * @param {FS.Collection} collection
- * @param {Function} func - Publish function that returns a cursor.
- * @returns {undefined}
- *
- * Publishes all documents returned by the cursor at a GET URL
- * with the format baseUrl/record/collectionName. The publish
- * function `this` is similar to normal `Meteor.publish`.
- */
-FS.HTTP.publish = function fsHttpPublish(collection, func) {
-  var name = baseUrl + '/record/' + collection.name;
-  // Mount collection listing URL using http-publish package
-  HTTP.publish({
-    name: name,
-    defaultFormat: 'fileRecordFormat',
-    collection: collection,
-    collectionGet: true,
-    collectionPost: false,
-    documentGet: true,
-    documentPut: false,
-    documentDelete: false
-  }, func);
-
-  FS.debug && console.log("Registered HTTP method GET URLs:\n\n" + name + '\n' + name + '/:id\n');
-};
-
-/**
- * @method FS.HTTP.unpublish
- * @public
- * @param {FS.Collection} collection
- * @returns {undefined}
- *
- * Unpublishes a restpoint created by a call to `FS.HTTP.publish`
- */
-FS.HTTP.unpublish = function fsHttpUnpublish(collection) {
-  // Mount collection listing URL using http-publish package
-  HTTP.unpublish(baseUrl + '/record/' + collection.name);
-};
-
-_existingMountPoints = {};
-
-/**
- * @method defaultSelectorFunction
- * @private
- * @returns { collection, file }
- *
- * This is the default selector function
- */
-var defaultSelectorFunction = function() {
-  var self = this;
-  // Selector function
-  //
-  // This function will have to return the collection and the
-  // file. If file not found undefined is returned - if null is returned the
-  // search was not possible
-  var opts = FS.Utility.extend({}, self.query || {}, self.params || {});
-
-  // Get the collection name from the url
-  var collectionName = opts.collectionName;
-
-  // Get the id from the url
-  var id = opts.id;
-
-  // Get the collection
-  var collection = FS._collections[collectionName];
-
-  //if Mongo ObjectIds are used, then we need to use that in find statement
-  if(collection.options.idGeneration && collection.options.idGeneration === 'MONGO') {
-    // Get the file if possible else return null
-    var file = (id && collection)? collection.findOne({ _id: new Meteor.Collection.ObjectID(id)}): null;
-  } else {
-    var file = (id && collection)? collection.findOne({ _id: id }): null;
-  }
-
-
-  // Return the collection and the file
-  return {
-    collection: collection,
-    file: file,
-    storeName: opts.store,
-    download: opts.download,
-    filename: opts.filename
-  };
-};
-
-/*
- * @method FS.HTTP.mount
- * @public
- * @param {array of string} mountPoints mount points to map rest functinality on
- * @param {function} selector_f [selector] function returns `{ collection, file }` for mount points to work with
- *
-*/
-FS.HTTP.mount = function(mountPoints, selector_f) {
-  // We take mount points as an array and we get a selector function
-  var selectorFunction = selector_f || defaultSelectorFunction;
-
-  var accessPoint = {
-    'stream': true,
-    'auth': expirationAuth,
-    'post': function(data) {
-      // Use the selector for finding the collection and file reference
-      var ref = selectorFunction.call(this);
-
-      // We dont support post - this would be normal insert eg. of filerecord?
-      throw new Meteor.Error(501, "Not implemented", "Post is not supported");
-    },
-    'put': function(data) {
-      // Use the selector for finding the collection and file reference
-      var ref = selectorFunction.call(this);
-
-      // Make sure we have a collection reference
-      if (!ref.collection)
-        throw new Meteor.Error(404, "Not Found", "No collection found");
-
-      // Make sure we have a file reference
-      if (ref.file === null) {
-        // No id supplied so we will create a new FS.File instance and
-        // insert the supplied data.
-        return FS.HTTP.Handlers.PutInsert.apply(this, [ref]);
-      } else {
-        if (ref.file) {
-          return FS.HTTP.Handlers.PutUpdate.apply(this, [ref]);
-        } else {
-          throw new Meteor.Error(404, "Not Found", 'No file found');
-        }
-      }
-    },
-    'get': function(data) {
-      // Use the selector for finding the collection and file reference
-      var ref = selectorFunction.call(this);
-
-      // Make sure we have a collection reference
-      if (!ref.collection)
-        throw new Meteor.Error(404, "Not Found", "No collection found");
-
-      // Make sure we have a file reference
-      if (ref.file === null) {
-        // No id supplied so we will return the published list of files ala
-        // http.publish in json format
-        return FS.HTTP.Handlers.GetList.apply(this, [ref]);
-      } else {
-        if (ref.file) {
-          return FS.HTTP.Handlers.Get.apply(this, [ref]);
-        } else {
-          throw new Meteor.Error(404, "Not Found", 'No file found');
-        }
-      }
-    },
-    'delete': function(data) {
-      // Use the selector for finding the collection and file reference
-      var ref = selectorFunction.call(this);
-
-      // Make sure we have a collection reference
-      if (!ref.collection)
-        throw new Meteor.Error(404, "Not Found", "No collection found");
-
-      // Make sure we have a file reference
-      if (ref.file) {
-        return FS.HTTP.Handlers.Del.apply(this, [ref]);
-      } else {
-        throw new Meteor.Error(404, "Not Found", 'No file found');
-      }
-    }
-  };
-
-  var accessPoints = {};
-
-  // Add debug message
-  FS.debug && console.log('Registered HTTP method URLs:');
-
-  FS.Utility.each(mountPoints, function(mountPoint) {
-    // Couple mountpoint and accesspoint
-    accessPoints[mountPoint] = accessPoint;
-    // Remember our mountpoints
-    _existingMountPoints[mountPoint] = mountPoint;
-    // Add debug message
-    FS.debug && console.log(mountPoint);
-  });
-
-  // XXX: HTTP:methods should unmount existing mounts in case of overwriting?
-  HTTP.methods(accessPoints);
-
-};
-
-/**
- * @method FS.HTTP.unmount
- * @public
- * @param {string | array of string} [mountPoints] Optional, if not specified all mountpoints are unmounted
- *
- */
-FS.HTTP.unmount = function(mountPoints) {
-  // The mountPoints is optional, can be string or array if undefined then
-  // _existingMountPoints will be used
-  var unmountList;
-  // Container for the mount points to unmount
-  var unmountPoints = {};
-
-  if (typeof mountPoints === 'undefined') {
-    // Use existing mount points - unmount all
-    unmountList = _existingMountPoints;
-  } else if (mountPoints === ''+mountPoints) {
-    // Got a string
-    unmountList = [mountPoints];
-  } else if (mountPoints.length) {
-    // Got an array
-    unmountList = mountPoints;
-  }
-
-  // If we have a list to unmount
-  if (unmountList) {
-    // Iterate over each item
-    FS.Utility.each(unmountList, function(mountPoint) {
-      // Check _existingMountPoints to make sure the mount point exists in our
-      // context / was created by the FS.HTTP.mount
-      if (_existingMountPoints[mountPoint]) {
-        // Mark as unmount
-        unmountPoints[mountPoint] = false;
-        // Release
-        delete _existingMountPoints[mountPoint];
-      }
-    });
-    FS.debug && console.log('FS.HTTP.unmount:');
-    FS.debug && console.log(unmountPoints);
-    // Complete unmount
-    HTTP.methods(unmountPoints);
-  }
-};
-
-// ### FS.Collection maps on HTTP pr. default on the following restpoints:
-// *
-//    baseUrl + '/files/:collectionName/:id/:filename',
-//    baseUrl + '/files/:collectionName/:id',
-//    baseUrl + '/files/:collectionName'
-//
-// Change/ replace the existing mount point by:
-// ```js
-//   // unmount all existing
-//   FS.HTTP.unmount();
-//   // Create new mount point
-//   FS.HTTP.mount([
-//    '/cfs/files/:collectionName/:id/:filename',
-//    '/cfs/files/:collectionName/:id',
-//    '/cfs/files/:collectionName'
-//  ]);
-//  ```
-//
-mountUrls = function mountUrls() {
-  // We unmount first in case we are calling this a second time
-  FS.HTTP.unmount();
-
-  FS.HTTP.mount([
-    baseUrl + '/files/:collectionName/:id/:filename',
-    baseUrl + '/files/:collectionName/:id',
-    baseUrl + '/files/:collectionName'
-  ]);
-};
-
-// Returns the userId from URL token
-var expirationAuth = function expirationAuth() {
-  var self = this;
-
-  // Read the token from '/hello?token=base64'
-  var encodedToken = self.query.token;
-
-  FS.debug && console.log("token: "+encodedToken);
-
-  if (!encodedToken || !Meteor.users) return false;
-
-  // Check the userToken before adding it to the db query
-  // Set the this.userId
-  var tokenString = FS.Utility.atob(encodedToken);
-
-  var tokenObject;
-  try {
-    tokenObject = JSON.parse(tokenString);
-  } catch(err) {
-    throw new Meteor.Error(400, 'Bad Request');
-  }
-
-  // XXX: Do some check here of the object
-  var userToken = tokenObject.authToken;
-  if (userToken !== ''+userToken) {
-    throw new Meteor.Error(400, 'Bad Request');
-  }
-
-  // If we have an expiration token we should check that it's still valid
-  if (tokenObject.expiration != null) {
-    // check if its too old
-    var now = Date.now();
-    if (tokenObject.expiration < now) {
-      FS.debug && console.log('Expired token: ' + tokenObject.expiration + ' is less than ' + now);
-      throw new Meteor.Error(500, 'Expired token');
-    }
-  }
-
-  // We are not on a secure line - so we have to look up the user...
-  var user = Meteor.users.findOne({
-    $or: [
-      {'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken(userToken)},
-      {'services.resume.loginTokens.token': userToken}
-    ]
-  });
-
-  // Set the userId in the scope
-  return user && user._id;
-};
-
-HTTP.methods(
-  {'/cfs/servertime': {
-    get: function(data) {
-      return Date.now().toString();
-    }
-  }
-});
-
-// Unify client / server api
-FS.HTTP.now = function() {
-  return Date.now();
-};
-
-// Start up the basic mount points
-Meteor.startup(function () {
-  mountUrls();
-});

+ 0 - 271
packages/wekan-cfs-access-point/api.md

@@ -1,271 +0,0 @@
-## wekan-cfs-access-point Public API ##
-
-CollectionFS, add ddp and http accesspoint capability
-
-_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._
-
--
-
-### <a name="FS.HTTP.setBaseUrl"></a>*FSHTTP*.setBaseUrl(newBaseUrl)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __setBaseUrl__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __newBaseUrl__ *{String}*  
-
- Change the base URL for the HTTP GET and DELETE endpoints.
-
-
-__Returns__  *{undefined}*
-
-
-> ```FS.HTTP.setBaseUrl = function setBaseUrl(newBaseUrl) { ...``` [access-point-common.js:29](access-point-common.js#L29)
-
-
--
-
-### <a name="FS.File.prototype.url"></a>*fsFile*.url([options])&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __url__ is defined in `prototype` of `FS.File`*
-
-__Arguments__
-
-* __options__ *{Object}*  (Optional)
-    * __store__ *{String}*  (Optional)
-
-    Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used.
-
-    * __auth__ *{Boolean}*  (Optional, Default = null)
-
-    Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds.
-
-    * __download__ *{Boolean}*  (Optional, Default = false)
-
-    Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser.
-
-    * __brokenIsFine__ *{Boolean}*  (Optional, Default = false)
-
-    Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet.
-
-    * __metadata__ *{Boolean}*  (Optional, Default = false)
-
-    Return the URL for the file metadata access point rather than the file itself.
-
-    * __uploading__ *{String}*  (Optional, Default = null)
-
-    A URL to return while the file is being uploaded.
-
-    * __storing__ *{String}*  (Optional, Default = null)
-
-    A URL to return while the file is being stored.
-
-    * __filename__ *{String}*  (Optional, Default = null)
-
-    Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store.
-
-
-
-Returns the HTTP URL for getting the file or its metadata.
-
-> ```FS.File.prototype.url = function(options) { ...``` [access-point-common.js:72](access-point-common.js#L72)
-
-
--
-
-### <a name="FS.HTTP.Handlers.Del"></a>*FSHTTPHandlers*.Del()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __Del__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{any}*
-response
-
-
-HTTP DEL request handler
-
-> ```FS.HTTP.Handlers.Del = function httpDelHandler(ref) { ...``` [access-point-handlers.js:13](access-point-handlers.js#L13)
-
-
--
-
-### <a name="FS.HTTP.Handlers.GetList"></a>*FSHTTPHandlers*.GetList()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __GetList__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{Object}*
-response
-
-
-HTTP GET file list request handler
-
-> ```FS.HTTP.Handlers.GetList = function httpGetListHandler() { ...``` [access-point-handlers.js:41](access-point-handlers.js#L41)
-
-
--
-
-### <a name="FS.HTTP.Handlers.Get"></a>*FSHTTPHandlers*.Get()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __Get__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{any}*
-response
-
-
-HTTP GET request handler
-
-> ```FS.HTTP.Handlers.Get = function httpGetHandler(ref) { ...``` [access-point-handlers.js:135](access-point-handlers.js#L135)
-
-
--
-
-### <a name="FS.HTTP.Handlers.PutInsert"></a>*FSHTTPHandlers*.PutInsert()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __PutInsert__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{Object}*
-response object with _id property
-
-
-HTTP PUT file insert request handler
-
-> ```FS.HTTP.Handlers.PutInsert = function httpPutInsertHandler(ref) { ...``` [access-point-handlers.js:229](access-point-handlers.js#L229)
-
-
--
-
-### <a name="FS.HTTP.Handlers.PutUpdate"></a>*FSHTTPHandlers*.PutUpdate()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __PutUpdate__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{Object}*
-response object with _id and chunk properties
-
-
-HTTP PUT file update chunk request handler
-
-> ```FS.HTTP.Handlers.PutUpdate = function httpPutUpdateHandler(ref) { ...``` [access-point-handlers.js:264](access-point-handlers.js#L264)
-
-
--
-
-### <a name="FS.HTTP.setHeadersForGet"></a>*FSHTTP*.setHeadersForGet(headers, [collections])&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __setHeadersForGet__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __headers__ *{Array}*  
-
- List of headers, where each is a two-item array in which item 1 is the header name and item 2 is the header value.
-
-* __collections__ *{Array|String}*  (Optional)
-
- Which collections the headers should be added for. Omit this argument to add the header for all collections.
-
-
-__Returns__  *{undefined}*
-
-
-> ```FS.HTTP.setHeadersForGet = function setHeadersForGet(headers, collections) { ...``` [access-point-server.js:24](access-point-server.js#L24)
-
-
--
-
-### <a name="FS.HTTP.publish"></a>*FSHTTP*.publish(collection, func)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __publish__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __collection__ *{[FS.Collection](#FS.Collection)}*  
-* __func__ *{Function}*  
-
- Publish function that returns a cursor.
-
-
-__Returns__  *{undefined}*
-
-
-Publishes all documents returned by the cursor at a GET URL
-with the format baseUrl/record/collectionName. The publish
-function `this` is similar to normal `Meteor.publish`.
-
-> ```FS.HTTP.publish = function fsHttpPublish(collection, func) { ...``` [access-point-server.js:48](access-point-server.js#L48)
-
-
--
-
-### <a name="FS.HTTP.unpublish"></a>*FSHTTP*.unpublish(collection)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __unpublish__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __collection__ *{[FS.Collection](#FS.Collection)}*  
-
-__Returns__  *{undefined}*
-
-
-Unpublishes a restpoint created by a call to `FS.HTTP.publish`
-
-> ```FS.HTTP.unpublish = function fsHttpUnpublish(collection) { ...``` [access-point-server.js:73](access-point-server.js#L73)
-
-
--
-
-### <a name="FS.HTTP.mount"></a>*FSHTTP*.mount(mountPoints, selector_f)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __mount__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __mountPoints__ *{[array of string](#array of string)}*  
-
- mount points to map rest functinality on
-
-* __selector_f__ *{function}*  
-
- [selector] function returns `{ collection, file }` for mount points to work with
-
-
-
-> ```FS.HTTP.mount = function(mountPoints, selector_f) { ...``` [access-point-server.js:125](access-point-server.js#L125)
-
-
--
-
-### <a name="FS.HTTP.unmount"></a>*FSHTTP*.unmount([mountPoints])&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __unmount__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __mountPoints__ *{[string ](#string )|[ array of string](# array of string)}*  (Optional)
-
- Optional, if not specified all mountpoints are unmounted
-
-
-
-
-> ```FS.HTTP.unmount = function(mountPoints) { ...``` [access-point-server.js:223](access-point-server.js#L223)
-
-
-
--
-### FS.Collection maps on HTTP pr. default on the following restpoints:
-*
-baseUrl + '/files/:collectionName/:id/:filename',
-baseUrl + '/files/:collectionName/:id',
-baseUrl + '/files/:collectionName'
-
-Change/ replace the existing mount point by:
-```js
-unmount all existing
-FS.HTTP.unmount();
-Create new mount point
-FS.HTTP.mount([
-'/cfs/files/:collectionName/:id/:filename',
-'/cfs/files/:collectionName/:id',
-'/cfs/files/:collectionName'
-]);
-```

+ 0 - 332
packages/wekan-cfs-access-point/internal.api.md

@@ -1,332 +0,0 @@
-## Public and Private API ##
-
-_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._
-
-***
-
-__File: ["access-point-common.js"](access-point-common.js) Where: {server|client}__
-
-***
-
-### <a name="FS.HTTP.setBaseUrl"></a>*FSHTTP*.setBaseUrl(newBaseUrl)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __setBaseUrl__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __newBaseUrl__ *{String}*  
-
- Change the base URL for the HTTP GET and DELETE endpoints.
-
-
-__Returns__  *{undefined}*
-
-
-> ```FS.HTTP.setBaseUrl = function setBaseUrl(newBaseUrl) { ...``` [access-point-common.js:29](access-point-common.js#L29)
-
-
--
-
-### <a name="FS.File.prototype.url"></a>*fsFile*.url([options])&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __url__ is defined in `prototype` of `FS.File`*
-
-__Arguments__
-
-* __options__ *{Object}*  (Optional)
-    * __store__ *{String}*  (Optional)
-
-    Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used.
-
-    * __auth__ *{Boolean}*  (Optional, Default = null)
-
-    Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds.
-
-    * __download__ *{Boolean}*  (Optional, Default = false)
-
-    Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser.
-
-    * __brokenIsFine__ *{Boolean}*  (Optional, Default = false)
-
-    Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet.
-
-    * __metadata__ *{Boolean}*  (Optional, Default = false)
-
-    Return the URL for the file metadata access point rather than the file itself.
-
-    * __uploading__ *{String}*  (Optional, Default = null)
-
-    A URL to return while the file is being uploaded.
-
-    * __storing__ *{String}*  (Optional, Default = null)
-
-    A URL to return while the file is being stored.
-
-    * __filename__ *{String}*  (Optional, Default = null)
-
-    Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store.
-
-
-
-Returns the HTTP URL for getting the file or its metadata.
-
-> ```FS.File.prototype.url = function(options) { ...``` [access-point-common.js:72](access-point-common.js#L72)
-
-
-***
-
-__File: ["access-point-handlers.js"](access-point-handlers.js) Where: {server}__
-
-***
-
-### <a name="FS.HTTP.Handlers.Del"></a>*FSHTTPHandlers*.Del()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __Del__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{any}*
-response
-
-
-HTTP DEL request handler
-
-> ```FS.HTTP.Handlers.Del = function httpDelHandler(ref) { ...``` [access-point-handlers.js:13](access-point-handlers.js#L13)
-
-
--
-
-### <a name="self.setStatusCode"></a>*self*.setStatusCode {any}&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-```
-From the DELETE spec:
-A successful response SHOULD be 200 (OK) if the response includes an
-entity describing the status, 202 (Accepted) if the action has not
-yet been enacted, or 204 (No Content) if the action has been enacted
-but the response does not include an entity.
-```
-*This property __setStatusCode__ is defined in `self`*
-
-> ```self.setStatusCode(200);``` [access-point-handlers.js:27](access-point-handlers.js#L27)
-
-
--
-
-### <a name="FS.HTTP.Handlers.GetList"></a>*FSHTTPHandlers*.GetList()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __GetList__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{Object}*
-response
-
-
-HTTP GET file list request handler
-
-> ```FS.HTTP.Handlers.GetList = function httpGetListHandler() { ...``` [access-point-handlers.js:41](access-point-handlers.js#L41)
-
-
--
-
-### <a name="requestRange"></a>requestRange {any}&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-```
-requestRange will parse the range set in request header - if not possible it
-will throw fitting errors and autofill range for both partial and full ranges
-throws error or returns the object:
-{
-start
-end
-length
-unit
-partial
-}
-```
-*This property is private*
-
-> ```var requestRange = function(req, fileSize) { ...``` [access-point-handlers.js:60](access-point-handlers.js#L60)
-
-
--
-
-### <a name="FS.HTTP.Handlers.Get"></a>*FSHTTPHandlers*.Get()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __Get__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{any}*
-response
-
-
-HTTP GET request handler
-
-> ```FS.HTTP.Handlers.Get = function httpGetHandler(ref) { ...``` [access-point-handlers.js:135](access-point-handlers.js#L135)
-
-
--
-
-### <a name="FS.HTTP.Handlers.PutInsert"></a>*FSHTTPHandlers*.PutInsert()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __PutInsert__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{Object}*
-response object with _id property
-
-
-HTTP PUT file insert request handler
-
-> ```FS.HTTP.Handlers.PutInsert = function httpPutInsertHandler(ref) { ...``` [access-point-handlers.js:229](access-point-handlers.js#L229)
-
-
--
-
-### <a name="FS.HTTP.Handlers.PutUpdate"></a>*FSHTTPHandlers*.PutUpdate()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __PutUpdate__ is defined in `FS.HTTP.Handlers`*
-
-__Returns__  *{Object}*
-response object with _id and chunk properties
-
-
-HTTP PUT file update chunk request handler
-
-> ```FS.HTTP.Handlers.PutUpdate = function httpPutUpdateHandler(ref) { ...``` [access-point-handlers.js:264](access-point-handlers.js#L264)
-
-
-***
-
-__File: ["access-point-server.js"](access-point-server.js) Where: {server}__
-
-***
-
-### <a name="FS.HTTP.setHeadersForGet"></a>*FSHTTP*.setHeadersForGet(headers, [collections])&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __setHeadersForGet__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __headers__ *{Array}*  
-
- List of headers, where each is a two-item array in which item 1 is the header name and item 2 is the header value.
-
-* __collections__ *{Array|String}*  (Optional)
-
- Which collections the headers should be added for. Omit this argument to add the header for all collections.
-
-
-__Returns__  *{undefined}*
-
-
-> ```FS.HTTP.setHeadersForGet = function setHeadersForGet(headers, collections) { ...``` [access-point-server.js:24](access-point-server.js#L24)
-
-
--
-
-### <a name="FS.HTTP.publish"></a>*FSHTTP*.publish(collection, func)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __publish__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __collection__ *{[FS.Collection](#FS.Collection)}*  
-* __func__ *{Function}*  
-
- Publish function that returns a cursor.
-
-
-__Returns__  *{undefined}*
-
-
-Publishes all documents returned by the cursor at a GET URL
-with the format baseUrl/record/collectionName. The publish
-function `this` is similar to normal `Meteor.publish`.
-
-> ```FS.HTTP.publish = function fsHttpPublish(collection, func) { ...``` [access-point-server.js:48](access-point-server.js#L48)
-
-
--
-
-### <a name="FS.HTTP.unpublish"></a>*FSHTTP*.unpublish(collection)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __unpublish__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __collection__ *{[FS.Collection](#FS.Collection)}*  
-
-__Returns__  *{undefined}*
-
-
-Unpublishes a restpoint created by a call to `FS.HTTP.publish`
-
-> ```FS.HTTP.unpublish = function fsHttpUnpublish(collection) { ...``` [access-point-server.js:73](access-point-server.js#L73)
-
-
--
-
-### <a name="defaultSelectorFunction"></a>defaultSelectorFunction()&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method is private*
-
-__Returns__  *{ collection, file }*
-
-
-This is the default selector function
-
-> ```var defaultSelectorFunction = function() { ...``` [access-point-server.js:87](access-point-server.js#L87)
-
-
--
-
-### <a name="FS.HTTP.mount"></a>*FSHTTP*.mount(mountPoints, selector_f)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __mount__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __mountPoints__ *{[array of string](#array of string)}*  
-
- mount points to map rest functinality on
-
-* __selector_f__ *{function}*  
-
- [selector] function returns `{ collection, file }` for mount points to work with
-
-
-
-> ```FS.HTTP.mount = function(mountPoints, selector_f) { ...``` [access-point-server.js:125](access-point-server.js#L125)
-
-
--
-
-### <a name="FS.HTTP.unmount"></a>*FSHTTP*.unmount([mountPoints])&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __unmount__ is defined in `FS.HTTP`*
-
-__Arguments__
-
-* __mountPoints__ *{[string ](#string )|[ array of string](# array of string)}*  (Optional)
-
- Optional, if not specified all mountpoints are unmounted
-
-
-
-
-> ```FS.HTTP.unmount = function(mountPoints) { ...``` [access-point-server.js:223](access-point-server.js#L223)
-
-
-
--
-### FS.Collection maps on HTTP pr. default on the following restpoints:
-*
-baseUrl + '/files/:collectionName/:id/:filename',
-baseUrl + '/files/:collectionName/:id',
-baseUrl + '/files/:collectionName'
-
-Change/ replace the existing mount point by:
-```js
-unmount all existing
-FS.HTTP.unmount();
-Create new mount point
-FS.HTTP.mount([
-'/cfs/files/:collectionName/:id/:filename',
-'/cfs/files/:collectionName/:id',
-'/cfs/files/:collectionName'
-]);
-```

+ 0 - 65
packages/wekan-cfs-access-point/package.js

@@ -1,65 +0,0 @@
-Package.describe({
-  name: 'wekan-cfs-access-point',
-  version: '0.1.50',
-  summary: 'CollectionFS, add ddp and http accesspoint capability',
-  git: 'https://github.com/zcfs/Meteor-cfs-access-point.git'
-});
-
-Npm.depends({
-  "content-disposition": "0.5.0"
-});
-
-Package.onUse(function(api) {
-  api.versionsFrom('1.0');
-
-  // This imply is needed for tests, and is technically probably correct anyway.
-  api.imply([
-    'wekan-cfs-base-package'
-  ]);
-
-  api.use([
-    //CFS packages
-    'wekan-cfs-base-package@0.0.30',
-    'wekan-cfs-file@0.1.16',
-    //Core packages
-    'check',
-    'ejson',
-    //Other packages
-    'wekan-cfs-http-methods@0.0.29',
-    'wekan-cfs-http-publish@0.0.13'
-  ]);
-
-  api.addFiles([
-    'access-point-common.js',
-    'access-point-handlers.js',
-    'access-point-server.js'
-  ], 'server');
-
-  api.addFiles([
-    'access-point-common.js',
-    'access-point-client.js'
-  ], 'client');
-});
-
-Package.onTest(function (api) {
-  api.versionsFrom('1.0');
-
-  api.use([
-    //CFS packages
-    'wekan-cfs-access-point',
-    'wekan-cfs-standard-packages@0.0.2',
-    'wekan-cfs-gridfs@0.0.0',
-    //Core packages
-    'test-helpers',
-    'http',
-    'tinytest',
-    'underscore',
-    'ejson',
-    'ordered-dict',
-    'random',
-    'deps'
-  ]);
-
-  api.addFiles('tests/client-tests.js', 'client');
-  api.addFiles('tests/server-tests.js', 'server');
-});

+ 0 - 125
packages/wekan-cfs-access-point/tests/client-tests.js

@@ -1,125 +0,0 @@
-function equals(a, b) {
-  return !!(EJSON.stringify(a) === EJSON.stringify(b));
-}
-
-Tinytest.add('cfs-access-point - client - test environment', function(test) {
-  test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection');
-  test.isTrue(typeof FS.HTTP !== 'undefined', 'test environment not initialized FS.HTTP');
-});
-
-Images = new FS.Collection('images', {
-  stores: [
-    new FS.Store.GridFS('gridList')
-  ]
-});
-
-Meteor.subscribe("img");
-
-var id;
-
-Tinytest.addAsync('cfs-access-point - client - addTestImage', function(test, onComplete) {
-  Meteor.call('addTestImage', function(err, result) {
-    id = result;
-    test.equal(typeof id, "string", "Test image was not inserted properly");
-    //Don't continue until the data has been stored
-    Deps.autorun(function (c) {
-      var img = Images.findOne(id);
-      if (img && img.hasCopy('gridList')) {
-        onComplete();
-        c.stop();
-      }
-    });
-  });
-});
-
-Tinytest.addAsync('cfs-access-point - client - GET list of files in collection', function(test, onComplete) {
-
-  HTTP.get(Meteor.absoluteUrl('cfs/record/images'), function(err, result) {
-    // Test the length of array result
-    var len = result.data && result.data.length;
-    test.isTrue(!!len, 'Result was empty');
-    // Get the object
-    var obj = result.data && result.data[0] || {};
-    test.equal(obj._id, id, 'Didn\'t get the expected result');
-    onComplete();
-  });
-
-});
-
-Tinytest.addAsync('cfs-access-point - client - GET filerecord', function(test, onComplete) {
-
-  HTTP.get(Meteor.absoluteUrl('cfs/record/images/' + id), function(err, result) {
-    // Get the object
-    var obj = result.data;
-    test.equal(typeof obj, "object", "Expected object data");
-    test.equal(obj._id, id, 'Didn\'t get the expected result');
-    onComplete();
-  });
-
-});
-
-Tinytest.addAsync('cfs-access-point - client - GET file itself', function(test, onComplete) {
-
-  HTTP.get(Meteor.absoluteUrl('cfs/files/images/' + id), function(err, result) {
-    test.isTrue(!!result.content, "Expected content in response");
-    console.log(result);
-    test.equal(result.statusCode, 200, "Expected 200 OK response");
-    onComplete();
-  });
-
-});
-
-Tinytest.addAsync('cfs-access-point - client - PUT new file data (update)', function(test, onComplete) {
-// TODO
-//  HTTP.put(Meteor.absoluteUrl('cfs/files/images/' + id), function(err, result) {
-//    test.equal(result.statusCode, 200, "Expected 200 OK response");
-  onComplete();
-//  });
-
-});
-
-Tinytest.addAsync('cfs-access-point - client - PUT insert a new file', function(test, onComplete) {
-// TODO
-//  HTTP.put(Meteor.absoluteUrl('cfs/files/images'), function(err, result) {
-//    test.equal(result.statusCode, 200, "Expected 200 OK response");
-  onComplete();
-//  });
-
-});
-
-Tinytest.addAsync('cfs-access-point - client - DELETE filerecord and data', function(test, onComplete) {
-
-  HTTP.del(Meteor.absoluteUrl('cfs/files/images/' + id), function(err, result) {
-    test.equal(result.statusCode, 200, "Expected 200 OK response");
-
-    // Make sure it's gone
-    HTTP.get(Meteor.absoluteUrl('cfs/record/images/' + id), function(err, result) {
-      test.isTrue(!!err, 'Expected 404 error');
-      test.equal(result.statusCode, 404, "Expected 404 response");
-      onComplete();
-    });
-  });
-
-});
-
-//TODO test FS.File.prototype.url method with various options
-
-//Test API:
-//test.isFalse(v, msg)
-//test.isTrue(v, msg)
-//test.equalactual, expected, message, not
-//test.length(obj, len)
-//test.include(s, v)
-//test.isNaN(v, msg)
-//test.isUndefined(v, msg)
-//test.isNotNull
-//test.isNull
-//test.throws(func)
-//test.instanceOf(obj, klass)
-//test.notEqual(actual, expected, message)
-//test.runId()
-//test.exception(exception)
-//test.expect_fail()
-//test.ok(doc)
-//test.fail(doc)
-//test.equal(a, b, msg)

+ 0 - 68
packages/wekan-cfs-access-point/tests/server-tests.js

@@ -1,68 +0,0 @@
-function equals(a, b) {
-  return !!(EJSON.stringify(a) === EJSON.stringify(b));
-}
-
-FS.debug = true;
-
-Tinytest.add('cfs-access-point - server - test environment', function(test) {
-  test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection');
-  test.isTrue(typeof FS.HTTP !== 'undefined', 'test environment not initialized FS.HTTP');
-});
-
-Images = new FS.Collection('images', {
-  stores: [
-    new FS.Store.GridFS('gridList')
-  ]
-});
-
-Images.allow({
-  insert: function() {
-    return true;
-  },
-  update: function() {
-    return true;
-  },
-  remove: function() {
-    return true;
-  },
-  download: function() {
-    return true;
-  }
-});
-
-Meteor.publish("img", function () {
-  return Images.find();
-});
-
-FS.HTTP.publish(Images, function () {
-  return Images.find();
-});
-
-Meteor.methods({
-  addTestImage: function() {
-    Images.remove({});
-    var url = "http://cdn.morguefile.com/imageData/public/files/b/bboomerindenial/preview/fldr_2009_04_01/file3301238617907.jpg";
-    var fsFile = Images.insert(url);
-    return fsFile._id;
-  }
-});
-
-//Test API:
-//test.isFalse(v, msg)
-//test.isTrue(v, msg)
-//test.equalactual, expected, message, not
-//test.length(obj, len)
-//test.include(s, v)
-//test.isNaN(v, msg)
-//test.isUndefined(v, msg)
-//test.isNotNull
-//test.isNull
-//test.throws(func)
-//test.instanceOf(obj, klass)
-//test.notEqual(actual, expected, message)
-//test.runId()
-//test.exception(exception)
-//test.expect_fail()
-//test.ok(doc)
-//test.fail(doc)
-//test.equal(a, b, msg)

+ 0 - 5
packages/wekan-cfs-base-package/.travis.yml

@@ -1,5 +0,0 @@
-language: node_js
-node_js:
-  - "0.10"
-before_install:
-  - "curl -L http://git.io/s0Zu-w | /bin/sh"

+ 0 - 20
packages/wekan-cfs-base-package/LICENSE.md

@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013-2015 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0 - 11
packages/wekan-cfs-base-package/README.md

@@ -1,11 +0,0 @@
-wekan-cfs-base-package
-=========================
-
-This is a Meteor package used by
-[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS).
-
-You don't need to manually add this package to your app. It is added when you
-add the `wekan-cfs-standard-packages` package.
-
-This package provides the `FS` namespace and helper methods used by many
-CollectionFS packages.

+ 0 - 213
packages/wekan-cfs-base-package/api.md

@@ -1,213 +0,0 @@
-## cfs-base-package Public API ##
-
-CollectionFS, Base package
-
-_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._
-
-#############################################################################
-
-HELPERS
-
-#############################################################################
--
-
-### <a name="FS.Utility.cloneFileRecord"></a>*fsUtility*.cloneFileRecord(rec, [options])&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __cloneFileRecord__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __rec__ *{[FS.File](#FS.File)|[FS.Collection filerecord](#FS.Collection filerecord)}*  
-* __options__ *{Object}*  (Optional)
-    * __full__ *{Boolean}*  (Optional, Default = false)
-
-    Set `true` to prevent certain properties from being omitted from the clone.
-
-
-__Returns__  *{Object}*
-Cloned filerecord
-
-
-Makes a shallow clone of `rec`, filtering out some properties that might be present if
-it's an FS.File instance, but which we never want to be part of the stored
-filerecord.
-
-This is a blacklist clone rather than a whitelist because we want the user to be able
-to specify whatever additional properties they wish.
-
-In general, we expect the following whitelist properties used by the internal and
-external APIs:
-
-_id, name, size, type, chunkCount, chunkSize, chunkSum, copies, createdAt, updatedAt, uploadedAt
-
-Those properties, and any additional properties added by the user, should be present
-in the returned object, which is suitable for inserting into the backing collection or
-extending an FS.File instance.
-
-
-> ```FS.Utility.cloneFileRecord = function(rec, options) { ...``` [base-common.js:71](base-common.js#L71)
-
-
--
-
-### <a name="FS.Utility.defaultCallback"></a>*fsUtility*.defaultCallback([err])&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __defaultCallback__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __err__ *{[Error](#Error)}*  (Optional)
-
-__Returns__  *{undefined}*
-
-
-Can be used as a default callback for client methods that need a callback.
-Simply throws the provided error if there is one.
-
-> ```FS.Utility.defaultCallback = function defaultCallback(err) { ...``` [base-common.js:96](base-common.js#L96)
-
-
--
-
-### <a name="FS.Utility.defaultCallback"></a>*fsUtility*.defaultCallback([f], [err])&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __defaultCallback__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __f__ *{Function}*  (Optional)
-
- A callback function, if you have one. Can be undefined or null.
-
-* __err__ *{[Meteor.Error ](#Meteor.Error )|[ Error ](# Error )|[ String](# String)}*  (Optional)
-
- Error or error message (string)
-
-
-__Returns__  *{Any}*
-the callback result if any
-
-
-Handle Error, creates an Error instance with the given text. If callback is
-a function, passes the error to that function. Otherwise throws it. Useful
-for dealing with errors in methods that optionally accept a callback.
-
-> ```FS.Utility.handleError = function(f, err, result) { ...``` [base-common.js:120](base-common.js#L120)
-
-
--
-
-### <a name="FS.Utility.noop"></a>*fsUtility*.noop()&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __noop__ is defined in `FS.Utility`*
-
-Use this to hand a no operation / empty function
-
-> ```FS.Utility.noop = function() { ...``` [base-common.js:134](base-common.js#L134)
-
-
--
-
-### <a name="FS.Utility.getFileExtension"></a>*fsUtility*.getFileExtension(name)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __getFileExtension__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __name__ *{String}*  
-
- A filename, filepath, or URL that may or may not have an extension.
-
-
-__Returns__  *{String}*
-The extension or an empty string if no extension found.
-
-
-> ```FS.Utility.getFileExtension = function utilGetFileExtension(name) { ...``` [base-common.js:205](base-common.js#L205)
-
-
--
-
-### <a name="FS.Utility.setFileExtension"></a>*fsUtility*.setFileExtension(name, ext)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __setFileExtension__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __name__ *{String}*  
-
- A filename that may or may not already have an extension.
-
-* __ext__ *{String}*  
-
- An extension without leading period, which you want to be the new extension on `name`.
-
-
-__Returns__  *{String}*
-The filename with changed extension.
-
-
-> ```FS.Utility.setFileExtension = function utilSetFileExtension(name, ext) { ...``` [base-common.js:222](base-common.js#L222)
-
-
--
-
-### <a name="FS.Utility.binaryToBuffer"></a>*fsUtility*.binaryToBuffer(data)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __binaryToBuffer__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __data__ *{Uint8Array}*  
-
-__Returns__  *{Buffer}*
-
-
-Converts a Uint8Array instance to a Node Buffer instance
-
-> ```FS.Utility.binaryToBuffer = function(data) { ...``` [base-server.js:9](base-server.js#L9)
-
-
--
-
-### <a name="FS.Utility.bufferToBinary"></a>*fsUtility*.bufferToBinary(data)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __bufferToBinary__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __data__ *{Buffer}*  
-
-__Returns__  *{Uint8Array}*
-
-
-Converts a Node Buffer instance to a Uint8Array instance
-
-> ```FS.Utility.bufferToBinary = function(data) { ...``` [base-server.js:26](base-server.js#L26)
-
-
--
-
-### <a name="FS.Utility.eachFile"></a>*fsUtility*.eachFile(e, f)&nbsp;&nbsp;<sub><i>Client</i></sub> ###
-
-*This method __eachFile__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __e__ *{[Event](#Event)}*  
-
- Browser event
-
-* __f__ *{Function}*  
-
- Function to run for each file found in the event.
-
-
-__Returns__  *{undefined}*
-
-
-Utility for iteration over files in event
-
-> ```FS.Utility.eachFile = function(e, f) { ...``` [base-client.js:37](base-client.js#L37)
-
-

+ 0 - 51
packages/wekan-cfs-base-package/base-client.js

@@ -1,51 +0,0 @@
-
-//XXX not sure this is still working properly?
-FS.Utility.connectionLogin = function(connection) {
-  // We check if the accounts package is installed, since we depend on
-  // `Meteor.userId()`
-  if (typeof Accounts !== 'undefined') {
-    // Monitor logout from main connection
-    Meteor.startup(function() {
-      Tracker.autorun(function() {
-        var userId = Meteor.userId();
-        if (userId) {
-          connection.onReconnect = function() {
-            var token = Accounts._storedLoginToken();
-            connection.apply('login', [{resume: token}], function(err, result) {
-              if (!err && result) {
-                connection.setUserId(result.id);
-              }
-            });
-          };
-        } else {
-          connection.onReconnect = null;
-          connection.setUserId(null);
-        }
-      });
-    });
-
-  }
-};
-
-/**
- * @method FS.Utility.eachFile
- * @public
- * @param {Event} e - Browser event
- * @param {Function} f - Function to run for each file found in the event.
- * @returns {undefined}
- * 
- * Utility for iteration over files in event
- */
-FS.Utility.eachFile = function(e, f) {
-  var evt = (e.originalEvent || e);
-
-  var files = evt.target.files;
-
-  if (!files || files.length === 0) {
-    files = evt.dataTransfer ? evt.dataTransfer.files : [];
-  }
-
-  for (var i = 0; i < files.length; i++) {
-    f(files[i], i);
-  }
-};

+ 0 - 317
packages/wekan-cfs-base-package/base-common.js

@@ -1,317 +0,0 @@
-// Exported namespace
-FS = {};
-
-// namespace for adapters; XXX should this be added by cfs-storage-adapter pkg instead?
-FS.Store = {
-  GridFS: function () {
-    throw new Error('To use FS.Store.GridFS, you must add the "wekan-cfs-gridfs" package.');
-  },
-  FileSystem: function () {
-    throw new Error('To use FS.Store.FileSystem, you must add the "wekan-cfs-filesystem" package.');
-  },
-  S3: function () {
-    throw new Error('To use FS.Store.S3, you must add the "wekan-cfs-s3" package.');
-  },
-  WABS: function () {
-    throw new Error('To use FS.Store.WABS, you must add the "wekan-cfs-wabs" package.');
-  },
-  Dropbox: function () {
-    throw new Error('To use FS.Store.Dropbox, you must add the "wekan-cfs-dropbox" package.');
-  }
-};
-
-// namespace for access points
-FS.AccessPoint = {};
-
-// namespace for utillities
-FS.Utility = {};
-
-// A general place for any package to store global config settings
-FS.config = {};
-
-// An internal collection reference
-FS._collections = {};
-
-// Test scope
-_Utility = {};
-
-// #############################################################################
-//
-// HELPERS
-//
-// #############################################################################
-
-/** @method _Utility.defaultZero
- * @private
-  * @param {Any} val Returns number or 0 if value is a falsy
-  */
-_Utility.defaultZero = function(val) {
-  return +(val || 0);
-};
-
-/**
- * @method FS.Utility.cloneFileRecord
- * @public
- * @param {FS.File|FS.Collection filerecord} rec
- * @param {Object} [options]
- * @param {Boolean} [options.full=false] Set `true` to prevent certain properties from being omitted from the clone.
- * @returns {Object} Cloned filerecord
- *
- * Makes a shallow clone of `rec`, filtering out some properties that might be present if
- * it's an FS.File instance, but which we never want to be part of the stored
- * filerecord.
- *
- * This is a blacklist clone rather than a whitelist because we want the user to be able
- * to specify whatever additional properties they wish.
- *
- * In general, we expect the following whitelist properties used by the internal and
- * external APIs:
- *
- * _id, name, size, type, chunkCount, chunkSize, chunkSum, copies, createdAt, updatedAt, uploadedAt
- *
- * Those properties, and any additional properties added by the user, should be present
- * in the returned object, which is suitable for inserting into the backing collection or
- * extending an FS.File instance.
- *
- */
-FS.Utility.cloneFileRecord = function(rec, options) {
-  options = options || {};
-  var result = {};
-  // We use this method for two purposes. If using it to clone one FS.File into another, then
-  // we want a full clone. But if using it to get a filerecord object for inserting into the
-  // internal collection, then there are certain properties we want to omit so that they aren't
-  // stored in the collection.
-  var omit = options.full ? [] : ['collectionName', 'collection', 'data', 'createdByTransform'];
-  for (var prop in rec) {
-    if (rec.hasOwnProperty(prop) && !_.contains(omit, prop)) {
-      result[prop] = rec[prop];
-    }
-  }
-  return result;
-};
-
-/**
- * @method FS.Utility.defaultCallback
- * @public
- * @param {Error} [err]
- * @returns {undefined}
- *
- * Can be used as a default callback for client methods that need a callback.
- * Simply throws the provided error if there is one.
- */
-FS.Utility.defaultCallback = function defaultCallback(err) {
-  if (err) {
-    // Show gentle error if Meteor error
-    if (err instanceof Meteor.Error) {
-      console.error(err.message);
-    } else {
-      // Normal error, just throw error
-      throw err;
-    }
-
-  }
-};
-
-/**
- * @method FS.Utility.defaultCallback
- * @public
- * @param {Function} [f] A callback function, if you have one. Can be undefined or null.
- * @param {Meteor.Error | Error | String} [err] Error or error message (string)
- * @returns {Any} the callback result if any
- *
- * Handle Error, creates an Error instance with the given text. If callback is
- * a function, passes the error to that function. Otherwise throws it. Useful
- * for dealing with errors in methods that optionally accept a callback.
- */
-FS.Utility.handleError = function(f, err, result) {
-  // Set callback
-  var callback = (typeof f === 'function')? f : FS.Utility.defaultCallback;
-  // Set the err
-  var error = (err === ''+err)? new Error(err) : err;
-  // callback
-  return callback(error, result);
-}
-
-/**
- * @method FS.Utility.noop
- * @public
- * Use this to hand a no operation / empty function
- */
-FS.Utility.noop = function() {};
-
-/**
- * @method validateAction
- * @private
- * @param {Object} validators - The validators object to use, with `deny` and `allow` properties.
- * @param {FS.File} fileObj - Mounted or mountable file object to be passed to validators.
- * @param {String} userId - The ID of the user who is attempting the action.
- * @returns {undefined}
- *
- * Throws a "400-Bad Request" Meteor error if the file is not mounted or
- * a "400-Access denied" Meteor error if the action is not allowed.
- */
-FS.Utility.validateAction = function validateAction(validators, fileObj, userId) {
-  var denyValidators = validators.deny;
-  var allowValidators = validators.allow;
-
-  // If insecure package is used and there are no validators defined,
-  // allow the action.
-  if (typeof Package === 'object'
-          && Package.insecure
-          && denyValidators.length + allowValidators.length === 0) {
-    return;
-  }
-
-  // If already mounted, validators should receive a fileObj
-  // that is fully populated
-  if (fileObj.isMounted()) {
-    fileObj.getFileRecord();
-  }
-
-  // Any deny returns true means denied.
-  if (_.any(denyValidators, function(validator) {
-    return validator(userId, fileObj);
-  })) {
-    throw new Meteor.Error(403, "Access denied");
-  }
-  // Any allow returns true means proceed. Throw error if they all fail.
-  if (_.all(allowValidators, function(validator) {
-    return !validator(userId, fileObj);
-  })) {
-    throw new Meteor.Error(403, "Access denied");
-  }
-};
-
-/**
- * @method FS.Utility.getFileName
- * @private
- * @param {String} name - A filename, filepath, or URL
- * @returns {String} The filename without the URL, filepath, or query string
- */
-FS.Utility.getFileName = function utilGetFileName(name) {
-  // in case it's a URL, strip off potential query string
-  // should have no effect on filepath
-  name = name.split('?')[0];
-  // strip off beginning path or url
-  var lastSlash = name.lastIndexOf('/');
-  if (lastSlash !== -1) {
-    name = name.slice(lastSlash + 1);
-  }
-  return name;
-};
-
-/**
- * @method FS.Utility.getFileExtension
- * @public
- * @param {String} name - A filename, filepath, or URL that may or may not have an extension.
- * @returns {String} The extension or an empty string if no extension found.
- */
-FS.Utility.getFileExtension = function utilGetFileExtension(name) {
-  name = FS.Utility.getFileName(name);
-  // Seekout the last '.' if found
-  var found = name.lastIndexOf('.');
-  // Return the extension if found else ''
-  // If found is -1, we return '' because there is no extension
-  // If found is 0, we return '' because it's a hidden file
-  return (found > 0 ? name.slice(found + 1).toLowerCase() : '');
-};
-
-/**
- * @method FS.Utility.setFileExtension
- * @public
- * @param {String} name - A filename that may or may not already have an extension.
- * @param {String} ext - An extension without leading period, which you want to be the new extension on `name`.
- * @returns {String} The filename with changed extension.
- */
-FS.Utility.setFileExtension = function utilSetFileExtension(name, ext) {
-  if (!name || !name.length) {
-    return name;
-  }
-  var currentExt = FS.Utility.getFileExtension(name);
-  if (currentExt.length) {
-    name = name.slice(0, currentExt.length * -1) + ext;
-  } else {
-    name = name + '.' + ext;
-  }
-  return name;
-};
-
-/*
- * Borrowed these from http package
- */
-FS.Utility.encodeParams = function encodeParams(params) {
-  var buf = [];
-  _.each(params, function(value, key) {
-    if (buf.length)
-      buf.push('&');
-    buf.push(FS.Utility.encodeString(key), '=', FS.Utility.encodeString(value));
-  });
-  return buf.join('').replace(/%20/g, '+');
-};
-
-FS.Utility.encodeString = function encodeString(str) {
-  return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
-};
-
-/*
- * btoa and atob shims for client and server
- */
-
-FS.Utility._btoa = function _fsUtility_btoa(str) {
-  var buffer;
-
-  if (str instanceof Buffer) {
-    buffer = str;
-  } else {
-    buffer = new Buffer(str.toString(), 'binary');
-  }
-
-  return buffer.toString('base64');
-};
-
-FS.Utility.btoa = function fsUtility_btoa(str) {
-  if (typeof btoa === 'function') {
-    // Client
-    return btoa(str);
-  } else if (typeof Buffer !== 'undefined') {
-    // Server
-    return FS.Utility._btoa(str);
-  } else {
-    throw new Error('FS.Utility.btoa: Cannot base64 encode on your system');
-  }
-};
-
-FS.Utility._atob = function _fsUtility_atob(str) {
-  return new Buffer(str, 'base64').toString('binary');
-};
-
-FS.Utility.atob = function fsUtility_atob(str) {
-  if (typeof atob === 'function') {
-    // Client
-    return atob(str);
-  } else if (typeof Buffer !== 'undefined') {
-    // Server
-    return FS.Utility._atob(str);
-  } else {
-    throw new Error('FS.Utility.atob: Cannot base64 encode on your system');
-  }
-};
-
-// Api wrap for 3party libs like underscore
-FS.Utility.extend = _.extend;
-
-FS.Utility.each = _.each;
-
-FS.Utility.isEmpty = _.isEmpty;
-
-FS.Utility.indexOf = _.indexOf;
-
-FS.Utility.isArray = _.isArray;
-
-FS.Utility.map = _.map;
-
-FS.Utility.once = _.once;
-
-FS.Utility.include = _.include;
-
-FS.Utility.size = _.size;

+ 0 - 95
packages/wekan-cfs-base-package/base-server.js

@@ -1,95 +0,0 @@
-/**
- * @method FS.Utility.binaryToBuffer
- * @public
- * @param {Uint8Array} data
- * @returns {Buffer}
- *
- * Converts a Uint8Array instance to a Node Buffer instance
- */
-FS.Utility.binaryToBuffer = function(data) {
-  var len = data.length;
-  var buffer = new Buffer(len);
-  for (var i = 0; i < len; i++) {
-    buffer[i] = data[i];
-  }
-  return buffer;
-};
-
-/**
- * @method FS.Utility.bufferToBinary
- * @public
- * @param {Buffer} data
- * @returns {Uint8Array}
- *
- * Converts a Node Buffer instance to a Uint8Array instance
- */
-FS.Utility.bufferToBinary = function(data) {
-  var len = data.length;
-  var binary = EJSON.newBinary(len);
-  for (var i = 0; i < len; i++) {
-    binary[i] = data[i];
-  }
-  return binary;
-};
-
-/**
- * @method FS.Utility.safeCallback
- * @public
- * @param {Function} callback
- * @returns {Function}
- *
- * Makes a callback safe for Meteor code
- */
-FS.Utility.safeCallback = function (callback) {
-  return Meteor.bindEnvironment(callback, function(err) { throw err; });
-};
-
-/**
- * @method FS.Utility.safeStream
- * @public
- * @param {Stream} nodestream
- * @returns {Stream}
- *
- * Adds `safeOn` and `safeOnce` methods to a NodeJS Stream
- * object. These are the same as `on` and `once`, except
- * that the callback is wrapped for use in Meteor.
- */
-FS.Utility.safeStream = function(nodestream) {
-  if (!nodestream || typeof nodestream.on !== 'function')
-    throw new Error('FS.Utility.safeStream requires a NodeJS Stream');
-
-  // Create Meteor safe events
-  nodestream.safeOn = function(name, callback) {
-    return nodestream.on(name, FS.Utility.safeCallback(callback));
-  };
-
-  // Create Meteor safe events
-  nodestream.safeOnce = function(name, callback) {
-    return nodestream.once(name, FS.Utility.safeCallback(callback));
-  };
-
-  // Return the modified stream - modified anyway
-  return nodestream;
-};
-
-/**
- * @method FS.Utility.eachFileFromPath
- * @public
- * @param {String} p - Server path
- * @param {Function} f - Function to run for each file found in the path.
- * @returns {undefined}
- *
- * Utility for iteration over files from path on server
- */
-FS.Utility.eachFileFromPath = function(p, f) {
-  var fs = Npm.require('fs');
-  var path = Npm.require('path');
-  var files = fs.readdirSync(p);
-  files.map(function (file) {
-    return path.join(p, file);
-  }).filter(function (filePath) {
-    return fs.statSync(filePath).isFile() && path.basename(filePath)[0] !== '.';
-  }).forEach(function (filePath) {
-    f(filePath);
-  });
-};

+ 0 - 293
packages/wekan-cfs-base-package/internal.api.md

@@ -1,293 +0,0 @@
-## Public and Private API ##
-
-_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._
-
-***
-
-__File: ["base-common.js"](base-common.js) Where: {server|client}__
-
-***
-
-#############################################################################
-
-HELPERS
-
-#############################################################################
--
-
-### <a name="_Utility.defaultZero"></a>*_utility*.defaultZero(val)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method is private*
-*This method __defaultZero__ is defined in `_Utility`*
-
-__Arguments__
-
-* __val__ *{Any}*  
-
- Returns number or 0 if value is a falsy
-
-
-> ```_Utility.defaultZero = function(val) { ...``` [base-common.js:42](base-common.js#L42)
-
-
--
-
-### <a name="FS.Utility.cloneFileRecord"></a>*fsUtility*.cloneFileRecord(rec, [options])&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __cloneFileRecord__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __rec__ *{[FS.File](#FS.File)|[FS.Collection filerecord](#FS.Collection filerecord)}*  
-* __options__ *{Object}*  (Optional)
-    * __full__ *{Boolean}*  (Optional, Default = false)
-
-    Set `true` to prevent certain properties from being omitted from the clone.
-
-
-__Returns__  *{Object}*
-Cloned filerecord
-
-
-Makes a shallow clone of `rec`, filtering out some properties that might be present if
-it's an FS.File instance, but which we never want to be part of the stored
-filerecord.
-
-This is a blacklist clone rather than a whitelist because we want the user to be able
-to specify whatever additional properties they wish.
-
-In general, we expect the following whitelist properties used by the internal and
-external APIs:
-
-_id, name, size, type, chunkCount, chunkSize, chunkSum, copies, createdAt, updatedAt, uploadedAt
-
-Those properties, and any additional properties added by the user, should be present
-in the returned object, which is suitable for inserting into the backing collection or
-extending an FS.File instance.
-
-
-> ```FS.Utility.cloneFileRecord = function(rec, options) { ...``` [base-common.js:71](base-common.js#L71)
-
-
--
-
-### <a name="FS.Utility.defaultCallback"></a>*fsUtility*.defaultCallback([err])&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __defaultCallback__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __err__ *{[Error](#Error)}*  (Optional)
-
-__Returns__  *{undefined}*
-
-
-Can be used as a default callback for client methods that need a callback.
-Simply throws the provided error if there is one.
-
-> ```FS.Utility.defaultCallback = function defaultCallback(err) { ...``` [base-common.js:96](base-common.js#L96)
-
-
--
-
-### <a name="FS.Utility.defaultCallback"></a>*fsUtility*.defaultCallback([f], [err])&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __defaultCallback__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __f__ *{Function}*  (Optional)
-
- A callback function, if you have one. Can be undefined or null.
-
-* __err__ *{[Meteor.Error ](#Meteor.Error )|[ Error ](# Error )|[ String](# String)}*  (Optional)
-
- Error or error message (string)
-
-
-__Returns__  *{Any}*
-the callback result if any
-
-
-Handle Error, creates an Error instance with the given text. If callback is
-a function, passes the error to that function. Otherwise throws it. Useful
-for dealing with errors in methods that optionally accept a callback.
-
-> ```FS.Utility.handleError = function(f, err, result) { ...``` [base-common.js:120](base-common.js#L120)
-
-
--
-
-### <a name="FS.Utility.noop"></a>*fsUtility*.noop()&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __noop__ is defined in `FS.Utility`*
-
-Use this to hand a no operation / empty function
-
-> ```FS.Utility.noop = function() { ...``` [base-common.js:134](base-common.js#L134)
-
-
--
-
-### <a name="validateAction"></a>validateAction(validators, fileObj, userId)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method is private*
-
-__Arguments__
-
-* __validators__ *{Object}*  
-
- The validators object to use, with `deny` and `allow` properties.
-
-* __fileObj__ *{[FS.File](#FS.File)}*  
-
- Mounted or mountable file object to be passed to validators.
-
-* __userId__ *{String}*  
-
- The ID of the user who is attempting the action.
-
-
-__Returns__  *{undefined}*
-
-
-Throws a "400-Bad Request" Meteor error if the file is not mounted or
-a "400-Access denied" Meteor error if the action is not allowed.
-
-> ```FS.Utility.validateAction = function validateAction(validators, fileObj, userId) { ...``` [base-common.js:147](base-common.js#L147)
-
-
--
-
-### <a name="FS.Utility.getFileName"></a>*fsUtility*.getFileName(name)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method is private*
-*This method __getFileName__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __name__ *{String}*  
-
- A filename, filepath, or URL
-
-
-__Returns__  *{String}*
-The filename without the URL, filepath, or query string
-
-
-> ```FS.Utility.getFileName = function utilGetFileName(name) { ...``` [base-common.js:187](base-common.js#L187)
-
-
--
-
-### <a name="FS.Utility.getFileExtension"></a>*fsUtility*.getFileExtension(name)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __getFileExtension__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __name__ *{String}*  
-
- A filename, filepath, or URL that may or may not have an extension.
-
-
-__Returns__  *{String}*
-The extension or an empty string if no extension found.
-
-
-> ```FS.Utility.getFileExtension = function utilGetFileExtension(name) { ...``` [base-common.js:205](base-common.js#L205)
-
-
--
-
-### <a name="FS.Utility.setFileExtension"></a>*fsUtility*.setFileExtension(name, ext)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __setFileExtension__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __name__ *{String}*  
-
- A filename that may or may not already have an extension.
-
-* __ext__ *{String}*  
-
- An extension without leading period, which you want to be the new extension on `name`.
-
-
-__Returns__  *{String}*
-The filename with changed extension.
-
-
-> ```FS.Utility.setFileExtension = function utilSetFileExtension(name, ext) { ...``` [base-common.js:222](base-common.js#L222)
-
-
-***
-
-__File: ["base-server.js"](base-server.js) Where: {server}__
-
-***
-
-### <a name="FS.Utility.binaryToBuffer"></a>*fsUtility*.binaryToBuffer(data)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __binaryToBuffer__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __data__ *{Uint8Array}*  
-
-__Returns__  *{Buffer}*
-
-
-Converts a Uint8Array instance to a Node Buffer instance
-
-> ```FS.Utility.binaryToBuffer = function(data) { ...``` [base-server.js:9](base-server.js#L9)
-
-
--
-
-### <a name="FS.Utility.bufferToBinary"></a>*fsUtility*.bufferToBinary(data)&nbsp;&nbsp;<sub><i>Server</i></sub> ###
-
-*This method __bufferToBinary__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __data__ *{Buffer}*  
-
-__Returns__  *{Uint8Array}*
-
-
-Converts a Node Buffer instance to a Uint8Array instance
-
-> ```FS.Utility.bufferToBinary = function(data) { ...``` [base-server.js:26](base-server.js#L26)
-
-
-***
-
-__File: ["base-client.js"](base-client.js) Where: {client}__
-
-***
-
-### <a name="FS.Utility.eachFile"></a>*fsUtility*.eachFile(e, f)&nbsp;&nbsp;<sub><i>Client</i></sub> ###
-
-*This method __eachFile__ is defined in `FS.Utility`*
-
-__Arguments__
-
-* __e__ *{[Event](#Event)}*  
-
- Browser event
-
-* __f__ *{Function}*  
-
- Function to run for each file found in the event.
-
-
-__Returns__  *{undefined}*
-
-
-Utility for iteration over files in event
-
-> ```FS.Utility.eachFile = function(e, f) { ...``` [base-client.js:37](base-client.js#L37)
-
-

+ 0 - 37
packages/wekan-cfs-base-package/package.js

@@ -1,37 +0,0 @@
-Package.describe({
-  version: '0.0.30',
-  name: 'wekan-cfs-base-package',
-  summary: 'CollectionFS, Base package',
-  git: 'https://github.com/zcfs/Meteor-cfs-base-package.git'
-});
-
-Package.onUse(function(api) {
-  api.versionsFrom('1.0');
-
-  api.use(['deps', 'underscore', 'ejson']);
-
-  if (api.export) {
-    api.export('FS');
-    api.export('_Utility', { testOnly: true });
-  }
-
-  api.addFiles([
-    'base-common.js',
-    'base-server.js'
-  ], 'server');
-
-  api.addFiles([
-    'polyfill.base64.js',
-    'base-common.js',
-    'base-client.js'
-  ], 'client');
-});
-
-// Package.on_test(function (api) {
-//   api.use(['wekan-cfs-base-package', 'cfs-file']);
-//   api.use('test-helpers', 'server');
-//   api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict',
-//            'random', 'deps']);
-
-//   api.add_files('tests/common-tests.js', ['client', 'server']);
-// });

+ 0 - 179
packages/wekan-cfs-base-package/polyfill.base64.js

@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2010 Nick Galbreath
- * http://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/* base64 encode/decode compatible with window.btoa/atob
- *
- * window.atob/btoa is a Firefox extension to convert binary data (the "b")
- * to base64 (ascii, the "a").
- *
- * It is also found in Safari and Chrome.  It is not available in IE.
- *
- * if (!window.btoa) window.btoa = base64.encode
- * if (!window.atob) window.atob = base64.decode
- *
- * The original spec's for atob/btoa are a bit lacking
- * https://developer.mozilla.org/en/DOM/window.atob
- * https://developer.mozilla.org/en/DOM/window.btoa
- *
- * window.btoa and base64.encode takes a string where charCodeAt is [0,255]
- * If any character is not [0,255], then an DOMException(5) is thrown.
- *
- * window.atob and base64.decode take a base64-encoded string
- * If the input length is not a multiple of 4, or contains invalid characters
- *   then an DOMException(5) is thrown.
- */
-var base64 = {};
-base64.PADCHAR = '=';
-base64.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-
-base64.makeDOMException = function() {
-    // sadly in FF,Safari,Chrome you can't make a DOMException
-    var e, tmp;
-
-    try {
-        return new DOMException(DOMException.INVALID_CHARACTER_ERR);
-    } catch (tmp) {
-        // not available, just passback a duck-typed equiv
-        // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error
-        // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error/prototype
-        var ex = new Error("DOM Exception 5");
-
-        // ex.number and ex.description is IE-specific.
-        ex.code = ex.number = 5;
-        ex.name = ex.description = "INVALID_CHARACTER_ERR";
-
-        // Safari/Chrome output format
-        ex.toString = function() { return 'Error: ' + ex.name + ': ' + ex.message; };
-        return ex;
-    }
-}
-
-base64.getbyte64 = function(s,i) {
-    // This is oddly fast, except on Chrome/V8.
-    //  Minimal or no improvement in performance by using a
-    //   object with properties mapping chars to value (eg. 'A': 0)
-    var idx = base64.ALPHA.indexOf(s.charAt(i));
-    if (idx === -1) {
-        throw base64.makeDOMException();
-    }
-    return idx;
-}
-
-base64.decode = function(s) {
-    // convert to string
-    s = '' + s;
-    var getbyte64 = base64.getbyte64;
-    var pads, i, b10;
-    var imax = s.length
-    if (imax === 0) {
-        return s;
-    }
-
-    if (imax % 4 !== 0) {
-        throw base64.makeDOMException();
-    }
-
-    pads = 0
-    if (s.charAt(imax - 1) === base64.PADCHAR) {
-        pads = 1;
-        if (s.charAt(imax - 2) === base64.PADCHAR) {
-            pads = 2;
-        }
-        // either way, we want to ignore this last block
-        imax -= 4;
-    }
-
-    var x = [];
-    for (i = 0; i < imax; i += 4) {
-        b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) |
-            (getbyte64(s,i+2) << 6) | getbyte64(s,i+3);
-        x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff));
-    }
-
-    switch (pads) {
-    case 1:
-        b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6);
-        x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff));
-        break;
-    case 2:
-        b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12);
-        x.push(String.fromCharCode(b10 >> 16));
-        break;
-    }
-    return x.join('');
-}
-
-base64.getbyte = function(s,i) {
-    var x = s.charCodeAt(i);
-    if (x > 255) {
-        throw base64.makeDOMException();
-    }
-    return x;
-}
-
-base64.encode = function(s) {
-    if (arguments.length !== 1) {
-        throw new SyntaxError("Not enough arguments");
-    }
-    var padchar = base64.PADCHAR;
-    var alpha   = base64.ALPHA;
-    var getbyte = base64.getbyte;
-
-    var i, b10;
-    var x = [];
-
-    // convert to string
-    s = '' + s;
-
-    var imax = s.length - s.length % 3;
-
-    if (s.length === 0) {
-        return s;
-    }
-    for (i = 0; i < imax; i += 3) {
-        b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8) | getbyte(s,i+2);
-        x.push(alpha.charAt(b10 >> 18));
-        x.push(alpha.charAt((b10 >> 12) & 0x3F));
-        x.push(alpha.charAt((b10 >> 6) & 0x3f));
-        x.push(alpha.charAt(b10 & 0x3f));
-    }
-    switch (s.length - imax) {
-    case 1:
-        b10 = getbyte(s,i) << 16;
-        x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
-               padchar + padchar);
-        break;
-    case 2:
-        b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8);
-        x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
-               alpha.charAt((b10 >> 6) & 0x3f) + padchar);
-        break;
-    }
-    return x.join('');
-}
-
-if (!window.btoa) window.btoa = base64.encode
-if (!window.atob) window.atob = base64.decode

+ 0 - 161
packages/wekan-cfs-base-package/tests/common-tests.js

@@ -1,161 +0,0 @@
-function equals(a, b) {
-  return EJSON.stringify(a) === EJSON.stringify(b);
-}
-
-Tinytest.add('cfs-base-package - test environment', function(test) {
-  test.isTrue(typeof FS !== 'undefined',
-              'FS scope not declared');
-
-  test.isTrue(typeof FS.Store !== 'undefined',
-              'FS scope "FS.Store" not declared');
-
-  test.isTrue(typeof FS.AccessPoint !== 'undefined',
-              'FS scope "FS.AccessPoint" not declared');
-
-  test.isTrue(typeof FS.Utility !== 'undefined',
-              'FS scope "FS.Utility" not declared');
-
-  test.isTrue(typeof FS._collections !== 'undefined',
-              'FS scope "FS._collections" not declared');
-
-  test.isTrue(typeof _Utility !== 'undefined',
-              '_Utility test scope not declared');
-});
-
-Tinytest.add('cfs-base-package - _Utility.defaultZero', function(test) {
-  test.equal(_Utility.defaultZero(), 0, 'Failes to return 0 when (undefined)');
-  test.equal(_Utility.defaultZero(undefined), 0, 'Failes to return 0 when undefined');
-  test.equal(_Utility.defaultZero(null), 0, 'Failes to return 0 when null');
-  test.equal(_Utility.defaultZero(false), 0, 'Failes to return 0 when false');
-  test.equal(_Utility.defaultZero(0), 0, 'Failes to return 0 when 0');
-  test.equal(_Utility.defaultZero(-1), -1, 'Failes to return -1');
-  test.equal(_Utility.defaultZero(1), 1, 'Failes to return 1');
-  test.equal(_Utility.defaultZero(-0.1), -0.1, 'Failes to return -0.1');
-  test.equal(_Utility.defaultZero(0.1), 0.1, 'Failes to return 0.1');
-  test.equal(_Utility.defaultZero(''), 0, 'Failes to return ""');
-  test.equal(_Utility.defaultZero({}), NaN, 'Failes to return NaN when object');
-  test.equal(_Utility.defaultZero("dfdsfs"), NaN, 'Failes to return NaN when string');
-  test.equal(_Utility.defaultZero("1"), 1, 'Failes to return 1 when string "1"');
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.cloneFileRecord', function(test) {
-  // Given an object with any props, should filter out 'collectionName',
-  // 'collection', 'data', and 'createdByTransform'
-  var result = FS.Utility.cloneFileRecord({a: 1, b: {c: 1}, d: [1, 2], collectionName: 'test', collection: {}, data: {}, createdByTransform: false});
-  test.equal(result, {a: 1, b: {c: 1}, d: [1, 2]});
-
-  // Given an FS.File instance, should filter out 'collectionName',
-  // 'collection', 'data', and 'createdByTransform' and return a plain Object
-  var fileObj = new FS.File({a: 1, b: {c: 1}, d: [1, 2], name: 'name.png', type: 'image/png', size: 100, collectionName: 'test', collection: {}, data: {}, createdByTransform: false});
-  test.isTrue(fileObj instanceof FS.File);
-  var result = FS.Utility.cloneFileRecord(fileObj);
-  test.isFalse(result instanceof FS.File);
-  test.isTrue(equals(result, {a: 1, b: {c: 1}, d: [1, 2], name: 'name.png', type: 'image/png', size: 100}));
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.defaultCallback', function(test) {
-  // should throw an error passed in, but not a Meteor.Error
-  test.throws(function () {
-    var cb = FS.Utility.defaultCallback;
-    cb(new Error('test'));
-  });
-
-  var cb2 = FS.Utility.defaultCallback;
-  test.isUndefined(cb2(new Meteor.Error('test')));
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.handleError', function(test) {
-  test.isTrue(true);
-  // TODO
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.binaryToBuffer', function(test) {
-  test.isTrue(true);
-  // TODO
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.bufferToBinary', function(test) {
-  test.isTrue(true);
-  // TODO
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.connectionLogin', function(test) {
-  test.isTrue(true);
-  // TODO
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.getFileName', function(test) {
-
-  function t(input, expected) {
-    var ext = FS.Utility.getFileName(input);
-    test.equal(ext, expected, 'Got incorrect filename');
-  }
-
-  t('bar.png', 'bar.png');
-  t('foo/bar.png', 'bar.png');
-  t('/foo/foo/bar.png', 'bar.png');
-  t('http://foobar.com/file.png', 'file.png');
-  t('http://foobar.com/file', 'file');
-  t('http://foobar.com/file.png?a=b', 'file.png');
-  t('http://foobar.com/.file?a=b', '.file');
-  t('file', 'file');
-  t('.file', '.file');
-  t('foo/.file', '.file');
-  t('/foo/foo/.file', '.file');
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.getFileExtension', function(test) {
-
-  function t(input, expected) {
-    var ext = FS.Utility.getFileExtension(input);
-    test.equal(ext, expected, 'Got incorrect extension');
-  }
-
-  t('bar.png', 'png');
-  t('foo/bar.png', 'png');
-  t('/foo/foo/bar.png', 'png');
-  t('http://foobar.com/file.png', 'png');
-  t('http://foobar.com/file', '');
-  t('http://foobar.com/file.png?a=b', 'png');
-  t('http://foobar.com/file?a=b', '');
-  t('file', '');
-  t('.file', '');
-  t('foo/.file', '');
-  t('/foo/foo/.file', '');
-});
-
-Tinytest.add('cfs-base-package - FS.Utility.setFileExtension', function(test) {
-
-  function t(name, ext, expected) {
-    var newName = FS.Utility.setFileExtension(name, ext);
-    test.equal(newName, expected, 'Extension was not set correctly');
-  }
-
-  t('bar.png', 'jpeg', 'bar.jpeg');
-  t('bar', 'jpeg', 'bar.jpeg');
-  t('.bar', 'jpeg', '.bar.jpeg');
-  t('', 'jpeg', '');
-  t(null, 'jpeg', null);
-});
-
-//Test API:
-//Tinytest.add('', function(test) {});
-//Tinytest.addAsync('', function(test, onComplete) {});
-//test.isFalse(v, msg)
-//test.isTrue(v, msg)
-//test.equalactual, expected, message, not
-//test.length(obj, len)
-//test.include(s, v)
-//test.isNaN(v, msg)
-//test.isUndefined(v, msg)
-//test.isNotNull
-//test.isNull
-//test.throws(func)
-//test.instanceOf(obj, klass)
-//test.notEqual(actual, expected, message)
-//test.runId()
-//test.exception(exception)
-//test.expect_fail()
-//test.ok(doc)
-//test.fail(doc)
-//test.equal(a, b, msg)

+ 0 - 5
packages/wekan-cfs-collection-filters/.travis.yml

@@ -1,5 +0,0 @@
-language: node_js
-node_js:
-  - "0.10"
-before_install:
-  - "curl -L http://git.io/s0Zu-w | /bin/sh"

+ 0 - 20
packages/wekan-cfs-collection-filters/LICENSE.md

@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013-2014 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 0 - 8
packages/wekan-cfs-collection-filters/README.md

@@ -1,8 +0,0 @@
-wekan-cfs-collection-filters
-=========================
-
-This is a Meteor package used by
-[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS).
-
-You don't need to manually add this package to your app. It is added when you
-add the `wekan-cfs-standard-packages` package.

+ 0 - 44
packages/wekan-cfs-collection-filters/api.md

@@ -1,44 +0,0 @@
-## cfs-collection-filters Public API ##
-
-CollectionFS, adds FS.Collection filters
-
-_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._
-
--
-
-### <a name="FS.Collection.prototype.filters"></a>*fsCollection*.filters(filters)&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __filters__ is defined in `prototype` of `FS.Collection`*
-
-__Arguments__
-
-* __filters__ *{Object}*  
-
- File filters for this collection.
-
-
-__Returns__  *{undefined}*
-
-
-> ```FS.Collection.prototype.filters = function fsColFilters(filters) { ...``` [filters.js:7](filters.js#L7)
-
-
--
-
-### <a name="FS.Collection.prototype.allowsFile"></a>*fsCollection*.allowsFile()&nbsp;&nbsp;<sub><i>Anywhere</i></sub> ###
-
-*This method __allowsFile__ is defined in `prototype` of `FS.Collection`*
-
-__Returns__  *{boolean}*
-True if the collection allows this file.
-
-
-Checks based on any filters defined on the collection. If the
-file is not valid according to the filters, this method returns false
-and also calls the filter `onInvalid` method defined for the
-collection, passing it an English error string that explains why it
-failed.
-
-> ```FS.Collection.prototype.allowsFile = function fsColAllowsFile(fileObj) { ...``` [filters.js:108](filters.js#L108)
-
-

+ 0 - 191
packages/wekan-cfs-collection-filters/filters.js

@@ -1,191 +0,0 @@
-/**
- * @method FS.Collection.prototype.filters
- * @public
- * @param {Object} filters - File filters for this collection.
- * @returns {undefined}
- */
-FS.Collection.prototype.filters = function fsColFilters(filters) {
-  var self = this;
-
-  // Check filter option values and normalize them for quicker checking later
-  if (filters) {
-    // check/adjust allow/deny
-    FS.Utility.each(['allow', 'deny'], function (type) {
-      if (!filters[type]) {
-        filters[type] = {};
-      } else if (typeof filters[type] !== "object") {
-        throw new Error(type + ' filter must be an object');
-      }
-    });
-
-    // check/adjust maxSize
-    if (typeof filters.maxSize === "undefined") {
-      filters.maxSize = null;
-    } else if (filters.maxSize && typeof filters.maxSize !== "number") {
-      throw new Error('maxSize filter must be an number');
-    }
-
-    // check/adjust extensions
-    FS.Utility.each(['allow', 'deny'], function (type) {
-      if (!filters[type].extensions) {
-        filters[type].extensions = [];
-      } else if (!FS.Utility.isArray(filters[type].extensions)) {
-        throw new Error(type + '.extensions filter must be an array of extensions');
-      } else {
-        //convert all to lowercase
-        for (var i = 0, ln = filters[type].extensions.length; i < ln; i++) {
-          filters[type].extensions[i] = filters[type].extensions[i].toLowerCase();
-        }
-      }
-    });
-
-    // check/adjust content types
-    FS.Utility.each(['allow', 'deny'], function (type) {
-      if (!filters[type].contentTypes) {
-        filters[type].contentTypes = [];
-      } else if (!FS.Utility.isArray(filters[type].contentTypes)) {
-        throw new Error(type + '.contentTypes filter must be an array of content types');
-      }
-    });
-
-    self.options.filter = filters;
-  }
-
-  // Define deny functions to enforce file filters on the server
-  // for inserts and updates that initiate from untrusted code.
-  self.files.deny({
-    insert: function(userId, fsFile) {
-      return !self.allowsFile(fsFile);
-    },
-    update: function(userId, fsFile, fields, modifier) {
-      // TODO will need some kind of additional security here:
-      // Don't allow them to change the type, size, name, and
-      // anything else that would be security or data integrity issue.
-      // Such security should probably be added by cfs-collection package, not here.
-      return !self.allowsFile(fsFile);
-    },
-    fetch: []
-  });
-
-  // If insecure package is in use, we need to add allow rules that return
-  // true. Otherwise, it would seemingly turn off insecure mode.
-  if (Package && Package.insecure) {
-    self.allow({
-      insert: function() {
-        return true;
-      },
-      update: function() {
-        return true;
-      },
-      remove: function() {
-        return true;
-      },
-      download: function() {
-        return true;
-      },
-      fetch: [],
-      transform: null
-    });
-  }
-  // If insecure package is NOT in use, then adding the deny function
-  // does not have any effect on the main app's security paradigm. The
-  // user will still be required to add at least one allow function of her
-  // own for each operation for this collection. And the user may still add
-  // additional deny functions, but does not have to.
-};
-
-/**
- * @method FS.Collection.prototype.allowsFile Does the collection allow the specified file?
- * @public
- * @returns {boolean} True if the collection allows this file.
- *
- * Checks based on any filters defined on the collection. If the
- * file is not valid according to the filters, this method returns false
- * and also calls the filter `onInvalid` method defined for the
- * collection, passing it an English error string that explains why it
- * failed.
- */
-FS.Collection.prototype.allowsFile = function fsColAllowsFile(fileObj) {
-  var self = this;
-
-  // Get filters
-  var filter = self.options.filter;
-  if (!filter) {
-    return true;
-  }
-  var saveAllFileExtensions = (filter.allow.extensions.length === 0);
-  var saveAllContentTypes = (filter.allow.contentTypes.length === 0);
-
-  // Get info about the file
-  var filename = fileObj.name();
-  var contentType = fileObj.type();
-  if (!saveAllContentTypes && !contentType) {
-    filter.onInvalid && filter.onInvalid(filename + " has an unknown content type");
-    return false;
-  }
-  var fileSize = fileObj.size();
-  if (!fileSize || isNaN(fileSize)) {
-    filter.onInvalid && filter.onInvalid(filename + " has an unknown file size");
-    return false;
-  }
-
-  // Do extension checks only if we have a filename
-  if (filename) {
-    var ext = fileObj.getExtension();
-    if (!((saveAllFileExtensions ||
-            FS.Utility.indexOf(filter.allow.extensions, ext) !== -1) &&
-            FS.Utility.indexOf(filter.deny.extensions, ext) === -1)) {
-      filter.onInvalid && filter.onInvalid(filename + ' has the extension "' + ext + '", which is not allowed');
-      return false;
-    }
-  }
-
-  // Do content type checks
-  if (!((saveAllContentTypes ||
-          contentTypeInList(filter.allow.contentTypes, contentType)) &&
-          !contentTypeInList(filter.deny.contentTypes, contentType))) {
-    filter.onInvalid && filter.onInvalid(filename + ' is of the type "' + contentType + '", which is not allowed');
-    return false;
-  }
-
-  // Do max size check
-  if (typeof filter.maxSize === "number" && fileSize > filter.maxSize) {
-    filter.onInvalid && filter.onInvalid(filename + " is too big");
-    return false;
-  }
-  return true;
-};
-
-/**
- * @method contentTypeInList Is the content type string in the list?
- * @private
- * @param {String[]} list - Array of content types
- * @param {String} contentType - The content type
- * @returns {Boolean}
- *
- * Returns true if the content type is in the list, or if it matches
- * one of the special types in the list, e.g., "image/*".
- */
-function contentTypeInList(list, contentType) {
-  var listType, found = false;
-  for (var i = 0, ln = list.length; i < ln; i++) {
-    listType = list[i];
-    if (listType === contentType) {
-      found = true;
-      break;
-    }
-    if (listType === "image/*" && contentType.indexOf("image/") === 0) {
-      found = true;
-      break;
-    }
-    if (listType === "audio/*" && contentType.indexOf("audio/") === 0) {
-      found = true;
-      break;
-    }
-    if (listType === "video/*" && contentType.indexOf("video/") === 0) {
-      found = true;
-      break;
-    }
-  }
-  return found;
-}

Some files were not shown because too many files changed in this diff