├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── client ├── entry.coffee ├── entry.less ├── helpers.coffee ├── t9n │ ├── arabic.coffee │ ├── english.coffee │ ├── french.coffee │ ├── german.coffee │ ├── hebrew.coffee │ ├── italian.coffee │ ├── polish.coffee │ ├── portuguese.coffee │ ├── russian.coffee │ ├── slovene.coffee │ ├── spanish.coffee │ └── swedish.coffee └── views │ ├── accountButtons │ ├── _wrapLinks.html │ ├── accountButtons.coffee │ ├── accountButtons.html │ └── signedIn.html │ ├── enrollAccount │ ├── enrollAccount.coffee │ └── enrollAccount.html │ ├── error │ ├── error.coffee │ └── error.html │ ├── forgotPassword │ ├── forgotPassword.coffee │ └── forgotPassword.html │ ├── resetPassword │ ├── resetPassword.coffee │ └── resetPassword.html │ ├── signIn │ ├── signIn.coffee │ └── signIn.html │ ├── signUp │ ├── extraSignUpFields.coffee │ ├── extraSignUpFields.html │ ├── signUp.coffee │ └── signUp.html │ ├── social │ ├── social.coffee │ └── social.html │ └── verificationPending │ ├── verificationPending.coffee │ └── verificationPending.html ├── package.js ├── server └── entry.coffee ├── shared └── router.coffee ├── tests ├── client.coffee ├── client.html ├── route.coffee └── server.coffee └── versions.json /.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | _site/ 3 | .bundle/ 4 | vendor/ 5 | *.iml 6 | .idea 7 | packages 8 | *.lock 9 | *.sublime-workspace 10 | *.sublime-project 11 | Makefile 12 | start_test.js 13 | phantom_runner.js -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | node_js: 3 | - "0.10" 4 | before_install: 5 | # Install phantomjs 6 | - wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.0.0-macosx.zip 7 | - unzip phantomjs-2.0.0-macosx.zip 8 | - export PATH="`pwd`/phantomjs-2.0.0-macosx/bin:${PATH}" 9 | # Run Arunoda's script 10 | - "curl -L http://git.io/ejPSng | /bin/sh" 11 | script: "make test" 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | username: Differential 4 | repo: accounts-entry 5 | desc: Meteor sign up and sign in pages. 6 | version: 0.8.0 7 | 8 | --- 9 | # Changelog 10 | 11 | ### 0.8.0 12 | 13 | * Support email verification sending for accounts-password. Fixes #75. Fixes #190. [8540eb5](http://github.com/Differential/accounts-entry/commit/8540eb5fa5a3fdbdc729f2f74e72c9397e66ce37) 14 | * Hash passwords client-side before they go over the wire. [f53c7c8](http://github.com/Differential/accounts-entry/commit/f53c7c8a5bc3c3589d4b54fac47c50028345e06d) 15 | * added arabic translation [3a2fa7b](http://github.com/Differential/accounts-entry/commit/3a2fa7b4c38cdcf866f403fa45d97743b45412ec) 16 | * added russian translation [4b106e3](http://github.com/Differential/accounts-entry/commit/4b106e3dadcc4638232bcca01d61a2e44ab50346) 17 | * Add a profile helper to accountButtons helper methods [7c41760](http://github.com/Differential/accounts-entry/commit/7c4176085d170f4fb15077f4a73c8d2fdaaecf7b) 18 | * added current route to fromWhere session var [94aafc5](http://github.com/Differential/accounts-entry/commit/94aafc54f7932c29e92b5f3522e97c0346d74731) 19 | * Add profile to server account create user [d78ed24](http://github.com/Differential/accounts-entry/commit/d78ed248fbc6926145cc4d47888edbf3d0ba521c) 20 | * updated buttonText helper [31a5917](http://github.com/Differential/accounts-entry/commit/31a5917278a690f9d21918061a759905d48d7c89) 21 | * redirect user from sign-in if already signed in [8e952fb](http://github.com/Differential/accounts-entry/commit/8e952fb16f5ef8fa031f0bc51103f01f974b2bf5) 22 | * changed social signUp usage [faea789](http://github.com/Differential/accounts-entry/commit/faea7893ae767384351924114112131db700c295) 23 | * updated english language sign-up terms [9b774f1](http://github.com/Differential/accounts-entry/commit/9b774f1e5cafbeb3e33421a4f6bb7743d4735995) 24 | * Add showOtherLoginServices option [a3b61e7](http://github.com/Differential/accounts-entry/commit/a3b61e7900ffb2bbf75427478dad1dfe32f44288) 25 | * Allow template override using signedInTemplate [eaca425](http://github.com/Differential/accounts-entry/commit/eaca425e3a11e8d3fb4d3dc54d7f8ac8081be9a0) 26 | * Added translation for "Email is required" [8249664](http://github.com/Differential/accounts-entry/commit/8249664d5a11362fb2407c2a9ccca0c11ee7cc22) 27 | * Added t9n on error message [3af877b](http://github.com/Differential/accounts-entry/commit/3af877b1e2a0e9f48cf30ef7b9df20cd02afe598) 28 | * Added translation for "User not found" to error: [5e8aaea](http://github.com/Differential/accounts-entry/commit/5e8aaea6dcbb0bddfc1a653b1b48274692783f1d) 29 | * Translation for "Email already exists." [89feeba](http://github.com/Differential/accounts-entry/commit/89feeba821ee91ed7cff865394118d24725e63e7) 30 | * Updated male/female addressing messages [6c26f20](http://github.com/Differential/accounts-entry/commit/6c26f20776580f047b189ce691eeb7106a88cb56) 31 | * Added Incorrect password translation [ddeb56a](http://github.com/Differential/accounts-entry/commit/ddeb56a21874a4c7db9363d45b2a614a5d8b54fb) 32 | * added slovene language [6ddaea2](http://github.com/Differential/accounts-entry/commit/6ddaea29d2c9062e43cceed62d7fe8f72e5d8e98) 33 | * Add extra signup field support. [Fixes #179] [ea0667e](http://github.com/Differential/accounts-entry/commit/ea0667ea03aea3c17ca5093632513b590e38b5af) 34 | * Get meteor developer accounts working a bit better. [be97ac8](http://github.com/Differential/accounts-entry/commit/be97ac850259018b3fedca3d41dee5ca2cc98bc6) 35 | * added support for Portuguese. [d069af4](http://github.com/Differential/accounts-entry/commit/d069af48d2663ce91c2010f931d7bacd978395d8) 36 | * added correct jquery selector for getting the entry [589f668](http://github.com/Differential/accounts-entry/commit/589f668ceaed838a167dcce1eddd0b599c74825e) 37 | * Added support for Swedish. [28a4bc9](http://github.com/Differential/accounts-entry/commit/28a4bc9b5fe069187a5e1d011727daba0a8a9cfb) 38 | * Pause is now a function passed to the onBeforeAction method. [b3a8a6d](http://github.com/Differential/accounts-entry/commit/b3a8a6d094e018ed90d53a2b1b9bfe233bdb3e43) 39 | * Support Meteor accounts forbidClientAccountCreation. [4b64116](http://github.com/Differential/accounts-entry/commit/4b64116e05a419ba3448a7e4786ebb54d535933d) 40 | * audit argument package support [256d5ef](http://github.com/Differential/accounts-entry/commit/256d5ef96a0ca53e5d8ec5beaa53ef71d52b353d) 41 | * updating #143 which attempts to correct error #130 [09aaddd](http://github.com/Differential/accounts-entry/commit/09aaddd0651b72e13e3d20ebeee54b49e0c7ff5f) 42 | * added italian translation [e8f5e68](http://github.com/Differential/accounts-entry/commit/e8f5e68183e42d247d331b95c3ab681fa6f45182) 43 | * Update german.coffee [461991a](http://github.com/Differential/accounts-entry/commit/461991a37d6dcefe6f344e1382c8311a0b6339eb) 44 | 45 | ### 0.7.0 46 | 47 | * Do not pull in spark or just-i18n dependencies, neither are directly needed anymore. [fc994c1](https://github.com/BeDifferential/accounts-entry/commit/fc994c1afe10dfcbb54b7aae2b0cf9fc5ba1f5b6) 48 | * Add name attributes on signUp form to be consistent [#107](https://github.com/BeDifferential/accounts-entry/pull/107) 49 | * Add emailToLower and usernameToLower settings so you can set the package to lowercase email input [#101](https://github.com/BeDifferential/accounts-entry/pull/101) 50 | * Put autofocus on first field, not just on the email input. [#106](https://github.com/BeDifferential/accounts-entry/pull/106) 51 | * Include the wrapLinks html, duh [7fb0e8e](http://github.com/Differential/accounts-entry/commit/7fb0e8e745852feb441661285207302bfa1e8441) 52 | * Clean up wrapLinks for blaze, clean up test syntax now that include works, and add a new wrapLinks test. [7a3296c](http://github.com/Differential/accounts-entry/commit/7a3296cb044fe8c235fce0eab13f490456d67e6a) 53 | * Fix tests to work with blaze now. [9966e90](http://github.com/Differential/accounts-entry/commit/9966e903ac7a53c391786ef475419e8e226cef21) 54 | * Use the released version of just-i18n [d3d5185](http://github.com/Differential/accounts-entry/commit/d3d5185c5792db14050208e72dc167d97a42d943) 55 | * redirect to correct page after social login [8aecc9c](http://github.com/Differential/accounts-entry/commit/8aecc9cc7a1865d43c895a84a36586a41c880d64) 56 | * Oops, comma [77d7227](http://github.com/Differential/accounts-entry/commit/77d72275e54e3583294c15d915d5e1a6bc468e10) 57 | * Try to fix accounts-t9n issues. [df238e8](http://github.com/Differential/accounts-entry/commit/df238e82dcb898fa3f3f8247743013ac08525f66) 58 | * Fix just-i18n issues. Fixes #109 [c6daa42](http://github.com/Differential/accounts-entry/commit/c6daa42730a9001cbb166fb22a6f7b99e05a03c5) 59 | * Adding ability to override accountButtons signup [4e82743](http://github.com/Differential/accounts-entry/commit/4e82743377ffd8abb153f1c59fc7afd7cf058be4) 60 | * added sublime project files to gitignore and fix autofocus [9b10992](http://github.com/Differential/accounts-entry/commit/9b109922b54fd39c5284c91c9f1091dcaadab4d6) 61 | * Changing setting name to usernameToLower and emailToLower, just struggled with insensitive and casesensitive keeping what they ment in my head, i think this is clearer [962a7c5](http://github.com/Differential/accounts-entry/commit/962a7c59fe40f121cb05bd4a391f3769cf96f375) 62 | * Adding isStringEmail method to AccountsEntry [bafe044](http://github.com/Differential/accounts-entry/commit/bafe044bd564398e0cb342752caee6673c6a46c3) 63 | * Adding check to make sure username is not an email address [398065d](http://github.com/Differential/accounts-entry/commit/398065d60f92680d8b251d18a2a5b46677be4f28) 64 | * Adding error.usernameIsEmail to i18n, error text for different languages need check [c7ce0f6](http://github.com/Differential/accounts-entry/commit/c7ce0f68aa54dd6fca9b1005958be1e09204556d) 65 | * Adding new settings for username and email Insensitive, adding check to signUp to make the username and email insensitive if needed [c5cbb06](http://github.com/Differential/accounts-entry/commit/c5cbb06489abb6360375d3f395cf5604d00d3385) 66 | 67 | ### 0.6.2 68 | 69 | * Lock just-i18n to v0.1.1 since the refactors seem to break accounts-t9n which we rely on. [a58632](https://github.com/BeDifferential/accounts-entry/commit/a58632e95c0c59e72dd6edce71fa58fe50e8ce94) 70 | * Fix signup form to work with USERNAME_ONLY, email field was causing errors. [#93](https://github.com/BeDifferential/accounts-entry/issues/93) 71 | * Fix 'fromWhere' routing to work for both usernames and emails, was an oversight [#100](https://github.com/BeDifferential/accounts-entry/pull/100) 72 | * Add polish translations [#90](https://github.com/BeDifferential/accounts-entry/pull/90) 73 | 74 | ### 0.6.1 75 | 76 | * Bump iron-router version to 0.6.4. Still wish we had semvar support for dependencies [#96](https://github.com/BeDifferential/accounts-entry/issues/96) 77 | 78 | ### 0.6.0 79 | 80 | * Added first tests using TinyTest 81 | * Switch to using t9n so we get wrapped up translations for Meteor Core accounts-base errors [#86](https://github.com/BeDifferential/accounts-entry/pull/86) 82 | * Track redirects because of signInRequired and redirect back once sign in/sign up is completed [#13](https://github.com/BeDifferential/accounts-entry/issues/13) 83 | * Added signInRequired helper method 84 | * Fixed various langauge issues with translations [6086a1](https://github.com/BeDifferential/accounts-entry/commit/6086a17a3d3fe7fd1d4f2ab71d0ed9553756b1f0) 85 | * Usernames in sign up + sign in should not be case sensitive [#65](https://github.com/BeDifferential/accounts-entry/issues/65) 86 | * Add before hooks to the settings so you can tweak html before each accountButtons link (NEEDS DOCS) [8b9555](https://github.com/BeDifferential/accounts-entry/commit/8b9555ed33827fa16d15191377de5e8256be749e) 87 | * Fix template override to work correctly [#83](https://github.com/BeDifferential/accounts-entry/issues/83) 88 | * Fix redirect happening before login is finished processing [#78](https://github.com/BeDifferential/accounts-entry/pull/78) 89 | * Sign up code was being required by faulty logic, make it optional now. [#69](https://github.com/BeDifferential/accounts-entry/issues/69) 90 | * Add missed translations [cd7192](https://github.com/BeDifferential/accounts-entry/commit/cd719282796e76f1c431e526d650238af6da622d) 91 | * Add german support [#70](https://github.com/BeDifferential/accounts-entry/pull/70) 92 | 93 | ### 0.5.3 94 | 95 | ### 0.5.2 96 | 97 | ### 0.5.1 98 | 99 | ### 0.5.0 100 | 101 | * Use Accounts.createUser call instead of our own [c2b2cf](https://github.com/BeDifferential/accounts-entry/commit/c2b2cfca0be407cb90b8575a9c794549b0c5dbb3) 102 | * Fix calls to use proper settings for logo now [#47](https://github.com/BeDifferential/accounts-entry/issues/47) 103 | * Switch package to use i18n and add english and spanish translations [#46](https://github.com/BeDifferential/accounts-entry/pull/46) 104 | * Allow signupTemplate to be overridden [ad0381d](https://github.com/BeDifferential/accounts-entry/commit/ad0381d3fa80aa2247b9d6200d4489f1fd3430c8) 105 | * Refactor the folder structure of the package [ad0381d](https://github.com/BeDifferential/accounts-entry/commit/ad0381d3fa80aa2247b9d6200d4489f1fd3430c8) 106 | * Add an optional placeholder if email is marked as optional in the config. [#39](https://github.com/BeDifferential/accounts-entry/pull/39) 107 | 108 | ### v0.4.4 109 | 110 | * Switch to our own reset-password setup in IronRouter 111 | * Tweaked wording on forgot password header 112 | 113 | ### v0.4.3 114 | 115 | * Update to IronRouter 0.6.1 116 | * Switch to Font-Awesome 4.0 syntax 117 | * More IronRouter syntax changes 118 | * Fix typo in register handlebars helper 119 | * Return a string instead of a route from the helper 120 | 121 | ### v0.4.2 122 | 123 | * Fixed bug with missing helper (otherServicesLogin) on signup page. 124 | 125 | ### v0.4.1 126 | 127 | * Change version of iron-router we are pulling in, now use 0.6.0 128 | 129 | ### v0.4.0 130 | 131 | * Change configuration to be partially on client, partially on server. 132 | There were issues with getting the Session set based on a Meteor.call 133 | with the previous implementation, so most settings are back on the 134 | client, only signupCode and defaultProfile are set on server now. 135 | * Fixes bug to allow signup without signupCode 136 | 137 | ### v0.3.1 138 | 139 | * Fix various router redirects to use variables set in the config instead of hardcodings [#25](https://github.com/BeDifferential/accounts-entry/issues/25) and [#26](https://github.com/BeDifferential/accounts-entry/issues/26) 140 | 141 | ### v0.3.0 142 | 143 | * Fix client side login to happen after we create the user server side [#24](https://github.com/BeDifferential/accounts-entry/issues/24) 144 | * Fix an issue with event passing and Firefox/IE issues [#23](https://github.com/BeDifferential/accounts-entry/issues/23) 145 | * Optionally protect signup form with a signup code 146 | * Move configuration to server 147 | * Configuration is set by calling a method rather than setting an 148 | attribute of AccountsEntry object 149 | 150 | ### v0.2.10 151 | 152 | * Add a sign out route via iron router (/sign-out) 153 | * Make signedInAs a global helper instead of just in the accountButtons template 154 | 155 | ### v0.2.9 156 | 157 | * Return a string instead of true for the username on signup 158 | 159 | ### v0.2.8 160 | 161 | * Fix css targetting for signout link changes 162 | 163 | ### v0.2.7 164 | 165 | * Make Sign In header tag consistent with rest of package 166 | 167 | ### v0.2.6 168 | 169 | * Move create account header outside of the if logic so you see the header no matter what your settings. 170 | 171 | ### v0.2.5 172 | 173 | * Removed more differential naming from the package 174 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Differential 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #UNMAINTAINED 2 | Due to the adoption of React by the Meteor community and the continual updating of Meteor's own Account UI this project is no longer maintained. 3 | 4 | The last version of Meteor this package supports is `1.1.0.3` 5 | 6 | If you are looking for similar packages, take a look at [useraccounts:iron-routing](https://atmospherejs.com/useraccounts/iron-routing) 7 | 8 | --- 9 | 10 | [![Stories in Ready](https://badge.waffle.io/Differential/accounts-entry.png?label=ready&title=Ready)](https://waffle.io/Differential/accounts-entry) 11 | # Meteor accounts-entry [![Build Status](https://travis-ci.org/Differential/accounts-entry.png)](https://travis-ci.org/Differential/accounts-entry) 12 | 13 | accounts-entry is a meteor package that relies on Iron Router and provides an alternative interface to accounts-ui, with whole pages for sign up and sign in. 14 | 15 | ## Getting started 16 | 17 | Run: 18 | 19 | ``` 20 | meteor add joshowens:accounts-entry 21 | ``` 22 | 23 | You can install the `accounts-ui` package, as it is still used for OAuth setup. 24 | 25 | 26 | We wanted something to work with that used [Iron Router](https://github.com/EventedMind/iron-router), 27 | [Bootstrap 3](https://github.com/mangasocial/meteor-bootstrap-3), and didn't require the forcing of 28 | the dropdown box that didn't seem to be easily styled. But we love the ease of adding more packages like `accounts-facebook` or `accounts-twitter`, so we fully support the OAuth packages by adding buttons to let people sign-up/sign-in with those services if you add them. By default, accounts-entry doesn't offer email/password login functionality. If you `meteor add accounts-password`, accounts-entry will offer your users the option to sign-up/sign-in with a username and password. 29 | 30 | ![Example](http://github.differential.com/accounts-entry/images/Example.png) 31 | 32 | Examples of the package in action (check out the sign up or sign in 33 | links): 34 | 35 | * [https://linklyapp.com/](https://linklyapp.com/) 36 | * [https://carp.io/](https://carp.io/) 37 | * [https://getliquid.io/](https://getliquid.io/) 38 | * [http://support.unpolishedcr.com/](http://support.unpolishedcr.com/) 39 | * Submit PR with a description to add your project to the list. 40 | 41 | [Changelog](https://github.com/BeDifferential/accounts-entry/blob/master/CHANGELOG.md) 42 | 43 | ## Compatibility 44 | 45 | accounts-entry is presently compatible with Iron Router 1.0.3 and above. 46 | 47 | ## Provided routes 48 | 49 | You will get routes and the necessary templates for: 50 | 51 | ``` 52 | /sign-in 53 | /sign-out 54 | /sign-up 55 | /forgot-password 56 | /verification-pending 57 | ``` 58 | 59 | You can then either add links to those directly, or use the `{{ special }}` helper we provide to give you the apppropriate links for signed-in/signed-out users. The `{{ special }}` helper will display a sign-out link and the user's email address when they are signed-in. 60 | 61 | ## Ensuring signed in users for routes 62 | 63 | Simply add the following line of code: `AccountsEntry.signInRequired(this);` to require users be signed in for a route and to redirect the user to the included sign-in page and stop any rendering. Accounts-entry also tracks where the user was trying to go and will route them back after sign in. 64 | 65 | Here is an Iron-Router route example: 66 | 67 | ````js 68 | this.route('userProfile', { 69 | path: '/profile', 70 | template: 'profile', 71 | onBeforeAction: function () { 72 | AccountsEntry.signInRequired(this); 73 | } 74 | }); 75 | ```` 76 | 77 | ## Setting up password login 78 | 79 | Use `mrt add accounts-password` if you want to have email/username login authentication options. This is now optional and will only display if installed. You need to configure an OAuth option if you choose not to have password logins. 80 | 81 | ## Setting up OAuth/social integrations 82 | 83 | Use `accounts-ui` to configure your social/OAuth integrations (or manually create records in your database, if you have those skills). We don't have the nice instructions on how to configure the services built into this package, but if you choose to use {{ loginButtons }} elsewhere in your application (even temporarily), you can configure OAuth logins there. 84 | 85 | ## Configuration 86 | 87 | ### Signup codes 88 | 89 | We have added support for a signupCode in case you want to have a special code to handout to keep signups at a pace you want. This code is checked if you turn on the client and server side options listed below. 90 | 91 | **The signup code is only checked for accounts-password logins, so know that OAuth logins will still allow people in.** 92 | 93 | ### In CLIENT code only 94 | 95 | Since this is a young package, we are maintaining compatibility with accounts-ui (so if in a pinch accounts-entry is broken for you, you could easily switch to accounts-ui). We also use the UI for oauth configs from accounts-ui. 96 | 97 | ```js 98 | Meteor.startup(function () { 99 | AccountsEntry.config({ 100 | logo: 'logo.png' // if set displays logo above sign-in options 101 | privacyUrl: '/privacy-policy' // if set adds link to privacy policy and 'you agree to ...' on sign-up page 102 | termsUrl: '/terms-of-use' // if set adds link to terms 'you agree to ...' on sign-up page 103 | homeRoute: '/' // mandatory - path to redirect to after sign-out 104 | dashboardRoute: '/dashboard' // mandatory - path to redirect to after successful sign-in 105 | profileRoute: 'profile' 106 | passwordSignupFields: 'EMAIL_ONLY' 107 | showSignupCode: true 108 | showOtherLoginServices: true // Set to false to hide oauth login buttons on the signin/signup pages. Useful if you are using something like accounts-meld or want to oauth for api access 109 | extraSignUpFields: [{ // Add extra signup fields on the signup page 110 | field: "name", // The database property you want to store the data in 111 | name: "This Will Be The Initial Value", // An initial value for the field, if you want one 112 | label: "Full Name", // The html lable for the field 113 | placeholder: "John Doe", // A placeholder for the field 114 | type: "text", // The type of field you want 115 | required: true // Adds html 5 required property if true 116 | }] 117 | fluidLayout: false // Set to true to use bootstrap3 container-fluid and row-fluid classes. 118 | useContainer: true // Set to false to use an unstyled "accounts-entry-container" class instead of a bootstrap3 "container" or "container-fluid" class. 119 | signInAfterRegistration: true // Set to false to avoid prevent users being automatically signed up upon sign-up e.g. to wait until their email has been verified. 120 | emailVerificationPendingRoute: '/verification-pending' // The route to which users should be directed after sign-up. Only relevant if signInAfterRegistration is false. 121 | showSpinner: true // Show the spinner when the client is talking to the server (spin.js) 122 | spinnerOptions: { color: "#000", top: "80%" } // options as per [spin.js](http://fgnass.github.io/spin.js/) 123 | 124 | }); 125 | }); 126 | ``` 127 | 128 | ### In SERVER code only 129 | 130 | Call `AccountsEntry.config` with a hash of optional configuration: 131 | 132 | ```js 133 | Meteor.startup(function () { 134 | AccountsEntry.config({ 135 | signupCode: 's3cr3t', // only restricts username+password users, not OAuth 136 | defaultProfile: 137 | someDefault: 'default' 138 | }); 139 | }); 140 | ``` 141 | 142 | *Note: only set a signupCode if you want to use that feature.* 143 | 144 | The default configuration includes: 145 | 146 | ```js 147 | wrapLinks: true // wraps accounts-entry links in
  • for bootstrap compatability purposes 148 | homeRoute: '/' // MUST BE SET - redirect to this path after sign-out 149 | dashboardRoute: '/dashboard' // MUST BE SET - redirect to this path after sign-in 150 | ``` 151 | 152 | Remember, you must provide a route for home (used when signing out) and 153 | dashboard (used after signing in). 154 | 155 | ## Interested in building a quick meteor app that starts with Accounts-Entry? 156 | 157 | We've created a [meteor-boilerplate repo](http://github.differential.com/meteor-boilerplate/) that you can clone as a starting point for an app. It follows all our standards that we use for building apps for our clients. 158 | -------------------------------------------------------------------------------- /client/entry.coffee: -------------------------------------------------------------------------------- 1 | AccountsEntry = 2 | settings: 3 | wrapLinks: true 4 | homeRoute: '/' 5 | dashboardRoute: '/dashboard' 6 | passwordSignupFields: 'EMAIL_ONLY' 7 | emailToLower: true 8 | usernameToLower: false 9 | entrySignUp: '/sign-up' 10 | extraSignUpFields: [] 11 | showOtherLoginServices: true 12 | fluidLayout: false 13 | useContainer: true 14 | signInAfterRegistration: true 15 | emailVerificationPendingRoute: '/verification-pending' 16 | showSpinner: true 17 | spinnerOptions: { color: "#000", top: "80%" } 18 | 19 | isStringEmail: (email) -> 20 | emailPattern = /^([\w.-]+)@([\w.-]+)\.([a-zA-Z.]{2,6})$/i 21 | if email.match emailPattern then true else false 22 | 23 | config: (appConfig) -> 24 | @settings = _.extend(@settings, appConfig) 25 | 26 | T9n.defaultLanguage = "en" 27 | if appConfig.language 28 | T9n.language = appConfig.language 29 | 30 | if appConfig.signUpTemplate 31 | signUpRoute = Router.routes['entrySignUp'] 32 | signUpRoute.options.template = appConfig.signUpTemplate 33 | 34 | signInRequired: (router, extraCondition) -> 35 | extraCondition ?= true 36 | unless Meteor.loggingIn() 37 | if Meteor.user() and extraCondition 38 | router.next() 39 | else 40 | Session.set('fromWhere', router.url) 41 | Router.go('/sign-in') 42 | Session.set('entryError', t9n('error.signInRequired')) 43 | router.next() 44 | 45 | @AccountsEntry = AccountsEntry 46 | 47 | 48 | class @T9NHelper 49 | 50 | @translate: (code) -> 51 | T9n.get code, "error.accounts" 52 | 53 | @accountsError: (err) -> 54 | Session.set 'entryError', @translate err.reason 55 | -------------------------------------------------------------------------------- /client/entry.less: -------------------------------------------------------------------------------- 1 | .entry-logo { 2 | width: 300px; 3 | margin: auto; 4 | margin-top: 40px; 5 | } 6 | 7 | .entry { 8 | float: none; 9 | margin: auto; 10 | overflow: auto; 11 | margin-top: 20px; 12 | background: #fff; 13 | border-radius: 10px; 14 | padding: 15px; 15 | color: #444; 16 | 17 | h3 { 18 | margin-top: 0px; 19 | margin-bottom: 10px; 20 | font-size: 18px; 21 | font-weight: 800; 22 | text-align: center; 23 | } 24 | 25 | p { 26 | font-size: 15px; 27 | line-height: 20px; 28 | } 29 | 30 | fieldset { 31 | margin-top: 40px; 32 | } 33 | 34 | .entry-signin-cta { 35 | margin-bottom: 30px; 36 | text-align: center; 37 | } 38 | 39 | .entry-agreement { 40 | margin-top: 20px; 41 | font-size: 13px; 42 | } 43 | } 44 | 45 | .entry-social { 46 | margin-top: 10px; 47 | 48 | button { 49 | display: block; 50 | width: 280px; 51 | margin: auto; 52 | margin-bottom: 10px; 53 | padding: 8px 10px; 54 | border-radius: 5px; 55 | font-size: 16px; 56 | 57 | i { 58 | float: left; 59 | width: 40px; 60 | font-size: 20px; 61 | margin-top: 1px; 62 | padding-right: 15px; 63 | padding-left: 5px; 64 | border-right: 1px solid rgba(0,0,0,0.2); 65 | } 66 | 67 | &#entry-facebook { 68 | background: #3B5998; 69 | color: #fff; 70 | 71 | &:hover { 72 | background: #2C4780; 73 | } 74 | } 75 | 76 | &#entry-twitter { 77 | background: #4099FF; 78 | color: #fff; 79 | 80 | &:hover { 81 | background: #3288EB; 82 | } 83 | } 84 | 85 | &#entry-google { 86 | background: #db5a3c; 87 | color: #fff; 88 | 89 | &:hover { 90 | background: #CA4C2E; 91 | } 92 | } 93 | 94 | &#entry-github { 95 | background: #666; 96 | color: #fff; 97 | 98 | &:hover { 99 | background: #555; 100 | } 101 | } 102 | } 103 | } 104 | 105 | .email-option { 106 | text-align: center; 107 | font-size: 16px; 108 | font-weight: 500; 109 | 110 | .line-thru { 111 | display: block; 112 | margin-top: 40px; 113 | margin-bottom: 20px; 114 | font-size: 12px; 115 | position: relative; 116 | text-align: center; 117 | width: 100%; 118 | z-index: 1; 119 | 120 | &:before { 121 | width: 40px; 122 | height: 10px; 123 | background-color: #fff; 124 | content: ''; 125 | margin: -5px 0 0 -20px; 126 | left: 50%; 127 | position: absolute; 128 | top: 50%; 129 | z-index: -1; 130 | } 131 | 132 | &:after { 133 | border-bottom: 1px solid #999; 134 | content: ''; 135 | display: block; 136 | position: absolute; 137 | top: 49%; 138 | width: 100%; 139 | z-index: -2; 140 | } 141 | 142 | &.or-sign-in { 143 | margin-bottom: 30px; 144 | } 145 | } 146 | } 147 | 148 | .entry-form { 149 | margin-top: 20px; 150 | 151 | label { 152 | margin-bottom: 5px; 153 | font-weight: 500; 154 | } 155 | 156 | button.submit { 157 | font-size: 16px; 158 | padding: 10px 12px; 159 | margin-top: 25px; 160 | } 161 | } 162 | 163 | .entry-signup-cta { 164 | text-align: center; 165 | margin-top: 20px; 166 | font-size: 16px; 167 | } 168 | 169 | .entry-sign-out { 170 | cursor: pointer; 171 | } 172 | -------------------------------------------------------------------------------- /client/helpers.coffee: -------------------------------------------------------------------------------- 1 | if typeof Handlebars isnt "undefined" 2 | UI.registerHelper "signedInAs", (date) -> 3 | if Meteor.user().username 4 | Meteor.user().username 5 | else if Meteor.user().profile && Meteor.user().profile.name 6 | Meteor.user().profile.name 7 | else if Meteor.user().emails and Meteor.user().emails[0] 8 | Meteor.user().emails[0].address 9 | else 10 | "Signed In" 11 | 12 | UI.registerHelper 'accountButtons', -> 13 | Template.entryAccountButtons 14 | 15 | UI.registerHelper 'capitalize', (str) -> 16 | str.charAt(0).toUpperCase() + str.slice(1) 17 | 18 | UI.registerHelper 'signupClass', -> 19 | if AccountsEntry.settings.showOtherLoginServices && Accounts.oauth && Accounts.oauth.serviceNames().length > 0 20 | "collapse" 21 | 22 | UI.registerHelper 'signedIn', -> 23 | return true if Meteor.user() 24 | 25 | UI.registerHelper 'otherLoginServices', -> 26 | AccountsEntry.settings.showOtherLoginServices && 27 | Accounts.oauth && 28 | Accounts.oauth.serviceNames().length > 0 29 | 30 | UI.registerHelper 'loginServices', -> 31 | Accounts.oauth.serviceNames() 32 | 33 | UI.registerHelper 'showSignupCode', -> 34 | AccountsEntry.settings.showSignupCode is true 35 | 36 | UI.registerHelper 'passwordLoginService', -> 37 | !!Package['accounts-password'] 38 | 39 | UI.registerHelper 'showCreateAccountLink', -> 40 | return !Accounts._options.forbidClientAccountCreation 41 | 42 | UI.registerHelper 'fluidLayout', -> 43 | AccountsEntry.settings.fluidLayout is true 44 | 45 | UI.registerHelper 'talkingToServer', -> 46 | if AccountsEntry.settings.showSpinner is true 47 | Meteor.Spinner.options = AccountsEntry.settings.spinnerOptions 48 | return (Session.get('talkingToServer') is true) 49 | else 50 | return false 51 | 52 | UI.registerHelper 'containerCSSClass', -> 53 | if AccountsEntry.settings.useContainer is false 54 | "accounts-entry-container" 55 | else 56 | if AccountsEntry.settings.fluidLayout is true 57 | "container-fluid" 58 | else 59 | "container" 60 | 61 | UI.registerHelper 'rowCSSClass', -> 62 | if AccountsEntry.settings.fluidLayout is true 63 | "row-fluid" 64 | else 65 | "row" -------------------------------------------------------------------------------- /client/t9n/arabic.coffee: -------------------------------------------------------------------------------- 1 | ar = 2 | signIn: "تسجيل الدخول" 3 | signin: "تسجيل الدخول" 4 | signOut: "تسجيل الخروج" 5 | signUp: "افتح حساب جديد" 6 | OR: "او" 7 | forgotPassword: "نسيت كلمة السر؟" 8 | emailAddress: "البريد الالكترونى" 9 | emailResetLink: "اعادة تعيين البريد الالكترونى" 10 | dontHaveAnAccount: "ليس عندك حساب؟" 11 | resetYourPassword: "اعادة تعيين كلمة السر" 12 | updateYourPassword: "جدد كلمة السر" 13 | password: "كلمة السر" 14 | usernameOrEmail: "اسم المستخدم او البريد الالكترونى" 15 | email: "البريد الالكترونى" 16 | ifYouAlreadyHaveAnAccount: "اذا كان عندك حساب" 17 | signUpWithYourEmailAddress: "سجل ببريدك الالكترونى" 18 | username: "اسم المستخدم" 19 | optional: "اختيارى" 20 | signupCode: "رمز التسجيل" 21 | clickAgree: "بفتح حسابك انت توافق على" 22 | privacyPolicy: "سياسة الخصوصية" 23 | terms: "شروط الاستخدام" 24 | sign: "تسجيل" 25 | configure: "تعديل" 26 | with: "مع" 27 | createAccount: "افتح حساب جديد" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "و" 31 | "Match failed": "المطابقة فشلت" 32 | "User not found": "اسم المستخدم غير موجود" 33 | 34 | error: 35 | minChar: "سبعة حروف هو الحد الادنى لكلمة السر" 36 | pwOneLetter: "كلمة السر تحتاج الى حرف اخر" 37 | pwOneDigit: "كلمة السر يجب ان تحتوى على رقم واحد على الاقل" 38 | usernameRequired: "اسم المستخدم مطلوب" 39 | emailRequired: "البريد الالكترونى مطلوب" 40 | signupCodeRequired: "رمز التسجيل مطلوب" 41 | signupCodeIncorrect: "رمز التسجيل غير صحيح" 42 | signInRequired: "عليك بتسجبل الدخول لفعل ذلك" 43 | usernameIsEmail: "اسم المستخدم لا يمكن ان يكون بريد الكترونى" 44 | 45 | T9n.map "ar", ar 46 | -------------------------------------------------------------------------------- /client/t9n/english.coffee: -------------------------------------------------------------------------------- 1 | en = 2 | signIn: "Sign In" 3 | signin: "sign in" 4 | signOut: "Sign Out" 5 | signUp: "Register" 6 | OR: "OR" 7 | forgotPassword: "Forgot your password?" 8 | emailAddress: "Email Address" 9 | emailResetLink: "Email Reset Link" 10 | dontHaveAnAccount: "Don't have an account?" 11 | resetYourPassword: "Reset your password" 12 | updateYourPassword: "Update your password" 13 | password: "Password" 14 | usernameOrEmail: "Username or email" 15 | email: "Email" 16 | ifYouAlreadyHaveAnAccount: "If you already have an account" 17 | signUpWithYourEmailAddress: "Register with your email address" 18 | username: "Username" 19 | optional: "Optional" 20 | signupCode: "Registration Code" 21 | clickAgree: "By clicking Register, you agree to our" 22 | privacyPolicy: "Privacy Policy" 23 | terms: "Terms of Use" 24 | sign: "Sign" 25 | configure: "Configure" 26 | with: "with" 27 | createAccount: "Create an Account" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "and" 31 | "Match failed": "Match failed" 32 | "User not found": "User not found" 33 | 34 | error: 35 | minChar: "7 character minimum password." 36 | pwOneLetter: "Password requires 1 letter." 37 | pwOneDigit: "Password must have at least one digit." 38 | usernameRequired: "Username is required." 39 | emailRequired: "Email is required." 40 | signupCodeRequired: "Registration code is required." 41 | signupCodeIncorrect: "Registration code is incorrect." 42 | signInRequired: "You must be signed in to do that." 43 | usernameIsEmail: "Username cannot be an email address." 44 | 45 | T9n.map "en", en 46 | -------------------------------------------------------------------------------- /client/t9n/french.coffee: -------------------------------------------------------------------------------- 1 | fr = 2 | signIn: "Se Connecter" 3 | signin: "se connecter" 4 | signOut: "Se Deconnecter" 5 | signUp: "S'enregistrer" 6 | OR: "OU" 7 | forgotPassword: "Vous avez oublié votre mot de passe ?" 8 | emailAddress: "Adresse Email" 9 | emailResetLink: "Adresse pour reinitialiser votre mot de passe" 10 | dontHaveAnAccount: "Vous n'avez pas de compte ?" 11 | resetYourPassword: "Reinitialiser votre mot de passe" 12 | updateYourPassword: "Mettre à jour le mot de passe" 13 | password: "Mot de passe" 14 | usernameOrEmail: "Nom d'utilisateur ou email" 15 | email: "Email" 16 | ifYouAlreadyHaveAnAccount: "Si vous avez déjà un compte" 17 | signUpWithYourEmailAddress: "S'enregistrer avec votre adresse email" 18 | username: "Nom d'utilisateur" 19 | optional: "Optionnel" 20 | signupCode: "Code d'inscription" 21 | clickAgree: "En cliquant sur S'enregistrer, vous acceptez notre" 22 | privacyPolicy: "Politique de confidentialité" 23 | terms: "Conditions d'utilisation" 24 | sign: "S'enregistrer" 25 | configure: "Configurer" 26 | with: "avec" 27 | createAccount: "Créer un compte" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "et" 31 | 32 | error: 33 | minChar: "Votre mot de passe doit contenir au minimum 7 caractères." 34 | pwOneLetter: "Votre mot de passe doit contenir au moins une lettre." 35 | pwOneDigit: "Votre mot de passe doit contenir au moins un chiffre." 36 | usernameRequired: "Un nom d'utilisateur est requis." 37 | emailRequired: "Un email est requis." 38 | signupCodeRequired: "Un code d'inscription est requis." 39 | signupCodeIncorrect: "Le code d'enregistrement est incorrect." 40 | signInRequired: "Vous devez être connecté pour continuer." 41 | usernameIsEmail: "Le nom d'utilisateur ne peut être le même que l'adresse email." 42 | 43 | T9n.map "fr", fr 44 | -------------------------------------------------------------------------------- /client/t9n/german.coffee: -------------------------------------------------------------------------------- 1 | de = 2 | signIn: "Anmelden" 3 | signin: "anmelden" 4 | signOut: "Abmelden" 5 | signUp: "Registrieren" 6 | OR: "ODER" 7 | forgotPassword: "Passwort vergessen?" 8 | emailAddress: "E-Mail Adresse" 9 | emailResetLink: "Senden" 10 | dontHaveAnAccount: "Noch kein Konto?" 11 | resetYourPassword: "Passwort zurücksetzen" 12 | updateYourPassword: "Passwort aktualisieren" 13 | password: "Passwort" 14 | usernameOrEmail: "Benutzername oder E-Mail" 15 | email: "E-Mail" 16 | ifYouAlreadyHaveAnAccount: "Falls Sie ein Konto haben, bitte hier" 17 | signUpWithYourEmailAddress: "Mit E-Mail registrieren" 18 | username: "Benutzername" 19 | optional: "Optional" 20 | signupCode: "Registrierungscode" 21 | clickAgree: "Durch die Registrierung akzeptieren Sie unsere" 22 | privacyPolicy: "Datenschutzerklärung" 23 | terms: "Geschäftsbedingungen" 24 | sign: "Anmelden" 25 | configure: "Konfigurieren" 26 | with: "mit" 27 | createAccount: "Konto erzeugen" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "und" 31 | 32 | error: 33 | minChar: "Passwort muss mindesten 7 Zeichen lang sein." 34 | pwOneLetter: "Passwort muss mindestens einen Buchstaben enthalten." 35 | pwOneDigit: "Passwort muss mindestens eine Ziffer enthalten." 36 | usernameRequired: "Benutzername benötigt." 37 | emailRequired: "E-Mail benötigt." 38 | signupCodeRequired: "Registrierungscode benötigt." 39 | signupCodeIncorrect: "Registrierungscode ungültig." 40 | signInRequired: "Sie müssen sich anmelden." 41 | usernameIsEmail: "Benutzername kann nicht eine E-Mail." 42 | 43 | T9n.map "de", de 44 | -------------------------------------------------------------------------------- /client/t9n/hebrew.coffee: -------------------------------------------------------------------------------- 1 | he = 2 | signIn: "כניסה לחשבון" 3 | signin: "כניסה לחשבון" 4 | signOut: "יציאה" 5 | signUp: "חשבון חדש" 6 | OR: "או" 7 | forgotPassword: "שחכת סיסמא?" 8 | emailAddress: "כתובת Email" 9 | emailResetLink: "קישור לאיפוס Email" 10 | dontHaveAnAccount: "אין לך חשבון?" 11 | resetYourPassword: "איפוס סיסמא" 12 | updateYourPassword: "עדכון סיסמא" 13 | password: "סיסמא" 14 | usernameOrEmail: "שם משתמש או Email" 15 | email: "Email" 16 | ifYouAlreadyHaveAnAccount: "אם יש לך חשבון" 17 | signUpWithYourEmailAddress: "הירשם עם כתובת ה-Email" 18 | username: "שם משתמש" 19 | optional: "שדה רשות" 20 | signupCode: "קוד הרשמה" 21 | clickAgree: "על ידי סיום תהליך ההרשמה, הינך מסכים" 22 | privacyPolicy: "לתנאי הפרטיות" 23 | terms: "לתנאי השימוש" 24 | sign: "הירשם" 25 | configure: "הגדרות" 26 | with: "עם" 27 | createAccount: "חשבון חדש" 28 | and: "ו" 29 | "Match failed": "התאמה נכשלה (Match Failed)" 30 | "User not found": "המשתמש לא נמצא" 31 | 32 | error: 33 | minChar: "הסיסמה חייבת לכלול 7 תווים." 34 | pwOneLetter: "הסיסמה חייבת לכלות אות אחת." 35 | pwOneDigit: "הסיסמה חייבת לכלות מספר אחד." 36 | usernameRequired: "חובה להזין שם משתמש." 37 | emailRequired: "חובה להזין Email." 38 | signupCodeRequired: "חובה להזין קוד הרשמה." 39 | signupCodeIncorrect: "קוד ההרשמה שגוי." 40 | signInRequired: "אין לך רשות לבצע פעולה זאת." 41 | usernameIsEmail: "שם המשתמש לא יכול להיות כתובת Email." 42 | 43 | T9n.map "he", he 44 | -------------------------------------------------------------------------------- /client/t9n/italian.coffee: -------------------------------------------------------------------------------- 1 | it = 2 | signIn: "Accedi" 3 | signin: "accedi" 4 | signOut: "Esci" 5 | signUp: "Registrati" 6 | OR: "OPPURE" 7 | forgotPassword: "Hai dimenticato la password?" 8 | emailAddress: "Indirizzo Email" 9 | emailResetLink: "Invia Link di Reset" 10 | dontHaveAnAccount: "Non hai un account?" 11 | resetYourPassword: "Reimposta la password" 12 | updateYourPassword: "Aggiorna la password" 13 | password: "Password" 14 | usernameOrEmail: "Nome utente o email" 15 | email: "Email" 16 | ifYouAlreadyHaveAnAccount: "Se hai già un account" 17 | signUpWithYourEmailAddress: "Registrati con il tuo indirizzo email" 18 | username: "Username" 19 | optional: "Opzionale" 20 | signupCode: "Codice di Registrazione" 21 | clickAgree: "Cliccando Registrati, accetti la nostra" 22 | privacyPolicy: "Privacy Policy" 23 | terms: "Termini di Servizio" 24 | sign: "Accedi" 25 | configure: "Configura" 26 | with: "con" 27 | createAccount: "Crea un Account" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "e" 31 | "Match failed": "Riscontro fallito" 32 | "User not found": "Utente non trovato" 33 | 34 | error: 35 | minChar: "Password di almeno 7 caratteri." 36 | pwOneLetter: "La Password deve contenere 1 lettera." 37 | pwOneDigit: "La Password deve contenere almeno un numero." 38 | usernameRequired: "Il Nome utente è obbligatorio." 39 | emailRequired: "L'Email è obbligatoria." 40 | signupCodeRequired: "Il Codice di Registrazione è obbligatorio." 41 | signupCodeIncorrect: "Codice di Registrazione errato." 42 | signInRequired: "Per fare questo devi accedere." 43 | usernameIsEmail: "Il Nome Utente non può essere un indirizzo email." 44 | 45 | T9n.map "it", it 46 | -------------------------------------------------------------------------------- /client/t9n/polish.coffee: -------------------------------------------------------------------------------- 1 | pl = 2 | signIn: "Zaloguj się" 3 | signin: "zaloguj się" 4 | signOut: "Wyloguj się" 5 | signUp: "Zarejestruj się" 6 | OR: "LUB" 7 | forgotPassword: "Zapomniałeś hasła?" 8 | emailAddress: "Adres email" 9 | emailResetLink: "Wyślij email z linkiem do zmiany hasła" 10 | dontHaveAnAccount: "Nie masz konta?" 11 | resetYourPassword: "Ustaw nowe hasło" 12 | updateYourPassword: "Zaktualizuj swoje hasło" 13 | password: "Hasło" 14 | usernameOrEmail: "Nazwa użytkownika lub email" 15 | email: "Email" 16 | ifYouAlreadyHaveAnAccount: "Jeżeli już masz konto" 17 | signUpWithYourEmailAddress: "Zarejestruj się używając adresu email" 18 | username: "Nazwa użytkownika" 19 | optional: "Nieobowiązkowe" 20 | signupCode: "Kod rejestracji" 21 | clickAgree: "Klikając na Zarejestruj się zgadzasz się z naszą" 22 | privacyPolicy: "polityką prywatności" 23 | terms: "warunkami korzystania z serwisu" 24 | sign: "Podpisz" 25 | configure: "Konfiguruj" 26 | with: "z" 27 | createAccount: "Utwórz konto" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "i" 31 | 32 | error: 33 | minChar: "7 znaków to minimalna długość hasła." 34 | pwOneLetter: "Hasło musi zawierać 1 literę." 35 | pwOneDigit: "Hasło musi zawierać przynajmniej jedną cyfrę." 36 | usernameRequired: "Wymagana jest nazwa użytkownika." 37 | emailRequired: "Wymagany jest adres email." 38 | signupCodeRequired: "Wymagany jest kod rejestracji." 39 | signupCodeIncorrect: "Kod rejestracji jest nieprawidłowy." 40 | signInRequired: "Musisz być zalogowany, aby to zrobić." 41 | usernameIsEmail: "Nazwa użytkownika nie może być adres e-mail." 42 | 43 | T9n.map "pl", pl 44 | -------------------------------------------------------------------------------- /client/t9n/portuguese.coffee: -------------------------------------------------------------------------------- 1 | pt = 2 | signIn: "Entrar" 3 | signin: "Entrar" 4 | signOut: "Sair" 5 | signUp: "Registrar" 6 | OR: "OU" 7 | forgotPassword: "Esqueceu sua senha?" 8 | emailAddress: "Endereço de e-mail" 9 | emailResetLink: "Gerar nova senha" 10 | dontHaveAnAccount: "Não tem conta?" 11 | resetYourPassword: "Gerar nova senha" 12 | updateYourPassword: "Atualizar senha" 13 | password: "Senha" 14 | usernameOrEmail: "Usuario ou e-mail" 15 | email: "E-mail" 16 | ifYouAlreadyHaveAnAccount: "Se você já tem uma conta" 17 | signUpWithYourEmailAddress: "Entre usando seu endereço de e-mail" 18 | username: "Nome de usuário" 19 | optional: "Opcional" 20 | signupCode: "Código de acesso" 21 | clickAgree: "Ao clicar em Entrar, você aceita nosso" 22 | privacyPolicy: "Política de Privacidade" 23 | terms: "Termos de Uso" 24 | sign: "Entrar" 25 | configure: "Configurar" 26 | with: "com" 27 | createAccount: "Criar Conta" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "e" 31 | "Match failed": "Usuário ou senha não encontrado" 32 | "User not found": "Usuário não encontrado" 33 | 34 | error: 35 | minChar: "Senha requer um mínimo de 7 caracteres." 36 | pwOneLetter: "Senha deve conter pelo menos uma letra." 37 | pwOneDigit: "Senha deve conter pelo menos um digito." 38 | usernameRequired: "Nome de usuário é obrigatório." 39 | emailRequired: "E-mail é obrigatório." 40 | signupCodeRequired: "É necessário um código de acesso." 41 | signupCodeIncorrect: "Código de acesso incorreto." 42 | signInRequired: "Você precisa estar logado para fazer isso." 43 | usernameIsEmail: "Nome de usuário não pode ser um endereço de e-mail." 44 | 45 | T9n.map "pt", pt 46 | -------------------------------------------------------------------------------- /client/t9n/russian.coffee: -------------------------------------------------------------------------------- 1 | ru = 2 | signIn: "Войти" 3 | signin: "Войти" 4 | signOut: "Выйти" 5 | signUp: "Регистрация" 6 | OR: "ИЛИ" 7 | forgotPassword: "Забыли пароль?" 8 | emailAddress: "Email" 9 | emailResetLink: "Отправить ссылку для сброса" 10 | dontHaveAnAccount: "Нет аккаунта?" 11 | resetYourPassword: "Сбросить пароль" 12 | updateYourPassword: "Обновить пароль" 13 | password: "Пароль" 14 | usernameOrEmail: "Имя пользователя или email" 15 | email: "Email" 16 | ifYouAlreadyHaveAnAccount: "Если у вас уже есть аккаунт" 17 | signUpWithYourEmailAddress: "Зарегистрируйтесь с вашим email адресом" 18 | username: "Имя пользователя" 19 | optional: "Необязательно" 20 | signupCode: "Регистрационный код" 21 | clickAgree: "Нажав на Регистрация вы соглашаетесь с условиями" 22 | privacyPolicy: "Политики безопасности" 23 | terms: "Условиями пользования" 24 | sign: "Подпись" 25 | configure: "Конфигурировать" 26 | with: "с" 27 | createAccount: "Создать аккаунт" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "и" 31 | "Match failed": "Не совпадают" 32 | "User not found": "Пользователь не найден" 33 | 34 | error: 35 | minChar: "Минимальное кол-во символов для пароля 7." 36 | pwOneLetter: "В пароле должна быть хотя бы одна буква." 37 | pwOneDigit: "В пароле должна быть хотя бы одна цифра." 38 | usernameRequired: "Имя пользователя обязательно." 39 | emailRequired: "Email обязательно." 40 | signupCodeRequired: "Необходим регистрациооный код." 41 | signupCodeIncorrect: "Неправильный регистрационный код." 42 | signInRequired: "Необходимо войти для чтобы продолжить." 43 | usernameIsEmail: "Имя пользователя не может быть адресом email." 44 | 45 | T9n.map "ru", ru 46 | -------------------------------------------------------------------------------- /client/t9n/slovene.coffee: -------------------------------------------------------------------------------- 1 | sl = 2 | signIn: "Prijava" 3 | signin: "se prijavi" 4 | signOut: "Odjava" 5 | signUp: "Registracija" 6 | OR: "ALI" 7 | forgotPassword: "Pozabljeno geslo?" 8 | emailAddress: "Email naslov" 9 | emailResetLink: "Pošlji ponastavitveno povezavo" 10 | dontHaveAnAccount: "Nisi registriran(a)?" 11 | resetYourPassword: "Ponastavi geslo" 12 | updateYourPassword: "Spremeni geslo" 13 | password: "Geslo" 14 | usernameOrEmail: "Uporabniško ime ali email" 15 | email: "Email" 16 | ifYouAlreadyHaveAnAccount: "Če si že registriran(a)," 17 | signUpWithYourEmailAddress: "Prijava z email naslovom" 18 | username: "Uporabniško ime" 19 | optional: "Po želji" 20 | signupCode: "Prijavna koda" 21 | clickAgree: "S klikom na Registracija se strinjaš" 22 | privacyPolicy: "z našimi pogoji uporabe" 23 | terms: "Pogoji uporabe" 24 | sign: "Prijava" 25 | configure: "Nastavi" 26 | with: "z" 27 | createAccount: "Nova registracija" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "in" 31 | "Match failed": "Prijava neuspešna" 32 | "User not found": "Uporabnik ne obstaja" 33 | "Incorrect password": "Napačno geslo" 34 | "Email already exists.": "Email že obstaja." 35 | "Email is required": "Email je obvezen podatek" 36 | 37 | error: 38 | minChar: "Geslo mora imeti vsaj sedem znakov." 39 | pwOneLetter: "V geslu mora biti vsaj ena črka." 40 | pwOneDigit: "V geslu mora biti vsaj ena številka." 41 | usernameRequired: "Uporabniško ime je obvezen vnos." 42 | emailRequired: "Email je obvezen vnos." 43 | signupCodeRequired: "Prijavna koda je obvezen vnos." 44 | signupCodeIncorrect: "Prijavna koda je napačna." 45 | signInRequired: "Za to moraš biti prijavljen(a)." 46 | usernameIsEmail: "Uporabniško ime ne more biti email naslov." 47 | 48 | T9n.map "sl", sl 49 | -------------------------------------------------------------------------------- /client/t9n/spanish.coffee: -------------------------------------------------------------------------------- 1 | es = 2 | signIn: "Entrar" 3 | signOut: "Salir" 4 | signUp: "Suscribir" 5 | OR: "O" 6 | forgotPassword: "Contraseña olvidada?" 7 | emailAddress: "Dirección de Email" 8 | emailResetLink: "Reiniciar Email" 9 | dontHaveAnAccount: "No tenés una cuenta?" 10 | resetYourPassword: "Resetear tu contraseña" 11 | updateYourPassword: "Actualizar tu contraseña" 12 | password: "Contraseña" 13 | usernameOrEmail: "Usuario o email" 14 | email: "Email" 15 | ifYouAlreadyHaveAnAccount: "Si ya tenés una cuenta" 16 | signUpWithYourEmailAddress: "Suscribir con tu email" 17 | username: "Usuario" 18 | optional: "Opcional" 19 | signupCode: "Codigo para suscribir" 20 | clickAgree: "Si haces clic en Sucribir estas de acuerdo con la" 21 | privacyPolicy: "Póliza de Privacidad" 22 | terms: "Terminos de Uso" 23 | sign: "Ingresar" 24 | configure: "Disposición" 25 | with: "con" 26 | createAccount: "Crear cuenta" 27 | verificationPending: "Confirm your email address" 28 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 29 | and: "y" 30 | 31 | error: 32 | minChar: "7 carácteres mínimo." 33 | pwOneLetter: "mínimo una letra." 34 | pwOneDigit: "mínimo un dígito." 35 | usernameRequired: "Usuario es necesario." 36 | emailRequired: "Email es necesario." 37 | signupCodeRequired: "Código para suscribir es necesario." 38 | signupCodeIncorrect: "Código para suscribir no coincide." 39 | signInRequired: "Debes iniciar sesión para hacer eso." 40 | usernameIsEmail: "Usuario no puede ser Email." 41 | 42 | T9n.map "es", es 43 | -------------------------------------------------------------------------------- /client/t9n/swedish.coffee: -------------------------------------------------------------------------------- 1 | sv = 2 | signIn: "Logga in" 3 | signin: "logga in" 4 | signOut: "Logga ut" 5 | signUp: "Skapa konto" 6 | OR: "ELLER" 7 | forgotPassword: "Glömt din e-postadress?" 8 | emailAddress: "E-postadress" 9 | emailResetLink: "E-post återställningslänk" 10 | dontHaveAnAccount: "Har du inget konto?" 11 | resetYourPassword: "Återställ ditt lösenord" 12 | updateYourPassword: "Uppdatera ditt lösenord" 13 | password: "Lösenord" 14 | usernameOrEmail: "Användarnamn eller e-postadress" 15 | email: "E-postadress" 16 | ifYouAlreadyHaveAnAccount: "Om du redan har ett konto" 17 | signUpWithYourEmailAddress: "Skapa ett konto med din e-postadress" 18 | username: "Användarnamn" 19 | optional: "Valfri" 20 | signupCode: "Registreringskod" 21 | clickAgree: "När du väljer att skapa ett konto så godkänner du också vår" 22 | privacyPolicy: "integritetspolicy" 23 | terms: "användarvilkor" 24 | sign: "Logga" 25 | configure: "Konfigurera" 26 | with: "med" 27 | createAccount: "Skapa ett konto" 28 | verificationPending: "Confirm your email address" 29 | verificationPendingDetails: "A confirmation email has been sent to the email address you provided. Click on the confirmation link in the email to activate your account." 30 | and: "och" 31 | "Match failed": "Matchning misslyckades" 32 | "User not found": "Användaren hittades inte" 33 | 34 | error: 35 | minChar: "Det krävs minst 7 tecken i ditt lösenord." 36 | pwOneLetter: "Lösenordet måste ha minst 1 bokstav." 37 | pwOneDigit: "Lösenordet måste ha minst 1 siffra." 38 | usernameRequired: "Det krävs ett användarnamn." 39 | emailRequired: "Det krävs ett lösenord." 40 | signupCodeRequired: "Det krävs en registreringskod." 41 | signupCodeIncorrect: "Registreringskoden är felaktig." 42 | signInRequired: "Inloggning krävs här." 43 | usernameIsEmail: "Användarnamnet kan inte vara en e-postadress." 44 | 45 | T9n.map "sv", sv 46 | -------------------------------------------------------------------------------- /client/views/accountButtons/_wrapLinks.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /client/views/accountButtons/accountButtons.coffee: -------------------------------------------------------------------------------- 1 | entryAccountButtonsHelpers = { 2 | profileUrl: -> 3 | return false unless AccountsEntry.settings.profileRoute 4 | AccountsEntry.settings.profileRoute 5 | 6 | 7 | wrapLinksLi: -> 8 | if AccountsEntry.settings.wrapLinks 9 | Template.wrapLinks 10 | else 11 | Template.noWrapLinks 12 | 13 | wrapLinks: -> 14 | AccountsEntry.settings.wrapLinks 15 | 16 | beforeSignIn: -> 17 | AccountsEntry.settings.beforeSignIn 18 | 19 | beforeSignUp: -> 20 | AccountsEntry.settings.beforeSignUp 21 | 22 | beforeSignOut: -> 23 | AccountsEntry.settings.beforeSignOut 24 | 25 | beforeSignedInAs: -> 26 | AccountsEntry.settings.beforeSignedInAs 27 | 28 | entrySignUp: -> 29 | AccountsEntry.settings.entrySignUp 30 | 31 | profile: -> 32 | Meteor.user().profile 33 | } 34 | 35 | Template.entryAccountButtons.helpers entryAccountButtonsHelpers 36 | 37 | Template.entryAccountButtons.helpers 38 | signedInTemplate: -> 39 | if AccountsEntry.settings.signedInTemplate 40 | Template[AccountsEntry.settings.signedInTemplate].helpers(entryAccountButtonsHelpers) 41 | Template[AccountsEntry.settings.signedInTemplate] 42 | else 43 | Template.entrySignedIn 44 | 45 | Template.entrySignedIn.helpers entryAccountButtonsHelpers 46 | -------------------------------------------------------------------------------- /client/views/accountButtons/accountButtons.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /client/views/accountButtons/signedIn.html: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /client/views/enrollAccount/enrollAccount.coffee: -------------------------------------------------------------------------------- 1 | Template.entryEnrollAccount.helpers 2 | error: -> Session.get('entryError') 3 | 4 | logo: -> 5 | AccountsEntry.settings.logo 6 | 7 | Template.entryEnrollAccount.events 8 | 9 | 'submit #setPassword': (event) -> 10 | event.preventDefault() 11 | password = $('input[type="password"]').val() 12 | 13 | passwordErrors = do (password)-> 14 | errMsg = [] 15 | msg = false 16 | if password.length < 7 17 | errMsg.push t9n("error.minChar") 18 | if password.search(/[a-z]/i) < 0 19 | errMsg.push t9n("error.pwOneLetter") 20 | if password.search(/[0-9]/) < 0 21 | errMsg.push t9n("error.pwOneDigit") 22 | 23 | if errMsg.length > 0 24 | msg = "" 25 | errMsg.forEach (e) -> 26 | msg = msg.concat "#{e}\r\n" 27 | 28 | Session.set 'entryError', msg 29 | return true 30 | 31 | return false 32 | 33 | if passwordErrors then return 34 | 35 | Accounts.resetPassword Session.get('resetToken'), password, (error) -> 36 | if error 37 | Session.set('entryError', (error.reason || "Unknown error")) 38 | else 39 | Session.set('resetToken', null) 40 | Router.go AccountsEntry.settings.dashboardRoute 41 | -------------------------------------------------------------------------------- /client/views/enrollAccount/enrollAccount.html: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /client/views/error/error.coffee: -------------------------------------------------------------------------------- 1 | Template.entryError.helpers 2 | error: -> 3 | Session.get('entryError') 4 | -------------------------------------------------------------------------------- /client/views/error/error.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /client/views/forgotPassword/forgotPassword.coffee: -------------------------------------------------------------------------------- 1 | Template.entryForgotPassword.helpers 2 | error: -> t9n(Session.get('entryError')) 3 | 4 | logo: -> 5 | AccountsEntry.settings.logo 6 | 7 | Template.entryForgotPassword.events 8 | 'submit #forgotPassword': (event) -> 9 | event.preventDefault() 10 | Session.set('email', $('input[name="forgottenEmail"]').val()) 11 | 12 | if Session.get('email').length is 0 13 | Session.set('entryError', 'Email is required') 14 | return 15 | 16 | Session.set 'talkingToServer', true 17 | Accounts.forgotPassword({ 18 | email: Session.get('email') 19 | }, (error)-> 20 | Session.set 'talkingToServer', false 21 | if error 22 | Session.set('entryError', error.reason) 23 | else 24 | Router.go AccountsEntry.settings.homeRoute 25 | ) 26 | -------------------------------------------------------------------------------- /client/views/forgotPassword/forgotPassword.html: -------------------------------------------------------------------------------- 1 | 30 | 31 | -------------------------------------------------------------------------------- /client/views/resetPassword/resetPassword.coffee: -------------------------------------------------------------------------------- 1 | Template.entryResetPassword.helpers 2 | error: -> Session.get('entryError') 3 | 4 | logo: -> 5 | AccountsEntry.settings.logo 6 | 7 | Template.entryResetPassword.events 8 | 9 | 'submit #resetPassword': (event) -> 10 | event.preventDefault() 11 | password = $('input[type="password"]').val() 12 | 13 | passwordErrors = do (password)-> 14 | errMsg = [] 15 | msg = false 16 | if password.length < 7 17 | errMsg.push t9n("error.minChar") 18 | if password.search(/[a-z]/i) < 0 19 | errMsg.push t9n("error.pwOneLetter") 20 | if password.search(/[0-9]/) < 0 21 | errMsg.push t9n("error.pwOneDigit") 22 | 23 | if errMsg.length > 0 24 | msg = "" 25 | errMsg.forEach (e) -> 26 | msg = msg.concat "#{e}\r\n" 27 | 28 | Session.set 'entryError', msg 29 | return true 30 | 31 | return false 32 | 33 | if passwordErrors then return 34 | 35 | Session.set 'talkingToServer', true 36 | Accounts.resetPassword Session.get('resetToken'), password, (error) -> 37 | Session.set 'talkingToServer', false 38 | if error 39 | Session.set('entryError', (error.reason || "Unknown error")) 40 | else 41 | Session.set('resetToken', null) 42 | Router.go AccountsEntry.settings.dashboardRoute 43 | -------------------------------------------------------------------------------- /client/views/resetPassword/resetPassword.html: -------------------------------------------------------------------------------- 1 | 30 | -------------------------------------------------------------------------------- /client/views/signIn/signIn.coffee: -------------------------------------------------------------------------------- 1 | AccountsEntry.entrySignInHelpers = { 2 | emailInputType: -> 3 | if AccountsEntry.settings.passwordSignupFields is 'EMAIL_ONLY' 4 | 'email' 5 | else 6 | 'string' 7 | 8 | emailPlaceholder: -> 9 | fields = AccountsEntry.settings.passwordSignupFields 10 | 11 | if _.contains([ 12 | 'USERNAME_AND_EMAIL' 13 | 'USERNAME_AND_OPTIONAL_EMAIL' 14 | ], fields) 15 | return t9n("usernameOrEmail") 16 | else if fields == "USERNAME_ONLY" 17 | return t9n("username") 18 | 19 | return t9n("email") 20 | 21 | logo: -> 22 | AccountsEntry.settings.logo 23 | 24 | isUsernameOnly: -> 25 | return AccountsEntry.settings.passwordSignupFields == 'USERNAME_ONLY' 26 | 27 | } 28 | 29 | AccountsEntry.entrySignInEvents = { 30 | 'submit #signIn': (event) -> 31 | event.preventDefault() 32 | 33 | email = $('input[name="email"]').val() 34 | if (AccountsEntry.isStringEmail(email) and AccountsEntry.settings.emailToLower) or 35 | (not AccountsEntry.isStringEmail(email) and AccountsEntry.settings.usernameToLower) 36 | email = email.toLowerCase() 37 | 38 | Session.set('email', email) 39 | Session.set('password', $('input[name="password"]').val()) 40 | Session.set 'talkingToServer', true 41 | 42 | Meteor.loginWithPassword(Session.get('email'), Session.get('password'), (error)-> 43 | Session.set('password', undefined) 44 | Session.set 'talkingToServer', false 45 | if error 46 | T9NHelper.accountsError error 47 | else if Session.get('fromWhere') 48 | Router.go Session.get('fromWhere') 49 | Session.set('fromWhere', undefined) 50 | else 51 | Router.go AccountsEntry.settings.dashboardRoute 52 | ) 53 | } 54 | 55 | Template.entrySignIn.helpers(AccountsEntry.entrySignInHelpers) 56 | 57 | Template.entrySignIn.events(AccountsEntry.entrySignInEvents) 58 | -------------------------------------------------------------------------------- /client/views/signIn/signIn.html: -------------------------------------------------------------------------------- 1 | 52 | -------------------------------------------------------------------------------- /client/views/signUp/extraSignUpFields.coffee: -------------------------------------------------------------------------------- 1 | Template.entryExtraSignUpFields.helpers 2 | extraSignUpFields: -> 3 | AccountsEntry.settings.extraSignUpFields 4 | 5 | Template._entryExtraSignUpField.helpers 6 | isTextField: -> 7 | @type isnt "check_box" 8 | 9 | isCheckbox: -> 10 | @type is "check_box" 11 | -------------------------------------------------------------------------------- /client/views/signUp/extraSignUpFields.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | -------------------------------------------------------------------------------- /client/views/signUp/signUp.coffee: -------------------------------------------------------------------------------- 1 | AccountsEntry.hashPassword = (password) -> 2 | digest: SHA256(password), 3 | algorithm: "sha-256" 4 | 5 | AccountsEntry.entrySignUpHelpers = { 6 | showEmail: -> 7 | fields = AccountsEntry.settings.passwordSignupFields 8 | 9 | _.contains([ 10 | 'USERNAME_AND_EMAIL', 11 | 'USERNAME_AND_OPTIONAL_EMAIL', 12 | 'EMAIL_ONLY'], fields) 13 | 14 | showUsername: -> 15 | fields = AccountsEntry.settings.passwordSignupFields 16 | 17 | _.contains([ 18 | 'USERNAME_AND_EMAIL', 19 | 'USERNAME_AND_OPTIONAL_EMAIL', 20 | 'USERNAME_ONLY'], fields) 21 | 22 | showSignupCode: -> 23 | AccountsEntry.settings.showSignupCode 24 | 25 | logo: -> 26 | AccountsEntry.settings.logo 27 | 28 | privacyUrl: -> 29 | AccountsEntry.settings.privacyUrl 30 | 31 | termsUrl: -> 32 | AccountsEntry.settings.termsUrl 33 | 34 | both: -> 35 | AccountsEntry.settings.privacyUrl && 36 | AccountsEntry.settings.termsUrl 37 | 38 | neither: -> 39 | !AccountsEntry.settings.privacyUrl && 40 | !AccountsEntry.settings.termsUrl 41 | 42 | emailIsOptional: -> 43 | fields = AccountsEntry.settings.passwordSignupFields 44 | 45 | _.contains(['USERNAME_AND_OPTIONAL_EMAIL'], fields) 46 | 47 | emailAddress: -> 48 | Session.get('email') 49 | } 50 | 51 | AccountsEntry.entrySignUpEvents = { 52 | 'submit #signUp': (event, t) -> 53 | event.preventDefault() 54 | 55 | username = 56 | if t.find('input[name="username"]') 57 | t.find('input[name="username"]').value.toLowerCase() 58 | else 59 | undefined 60 | if username and AccountsEntry.settings.usernameToLower then username = username.toLowerCase() 61 | 62 | signupCode = 63 | if t.find('input[name="signupCode"]') 64 | t.find('input[name="signupCode"]').value 65 | else 66 | undefined 67 | 68 | trimInput = (val)-> 69 | val.replace /^\s*|\s*$/g, "" 70 | 71 | email = 72 | if t.find('input[type="email"]') 73 | trimInput t.find('input[type="email"]').value 74 | else 75 | undefined 76 | if AccountsEntry.settings.emailToLower and email then email = email.toLowerCase() 77 | 78 | formValues = SimpleForm.processForm(event.target) 79 | extraFields = _.pluck(AccountsEntry.settings.extraSignUpFields, 'field') 80 | filteredExtraFields = _.pick(formValues, extraFields) 81 | password = t.find('input[type="password"]').value 82 | 83 | fields = AccountsEntry.settings.passwordSignupFields 84 | 85 | 86 | passwordErrors = do (password)-> 87 | errMsg = [] 88 | msg = false 89 | if password.length < 7 90 | errMsg.push t9n("error.minChar") 91 | if password.search(/[a-z]/i) < 0 92 | errMsg.push t9n("error.pwOneLetter") 93 | if password.search(/[0-9]/) < 0 94 | errMsg.push t9n("error.pwOneDigit") 95 | 96 | if errMsg.length > 0 97 | msg = "" 98 | errMsg.forEach (e) -> 99 | msg = msg.concat "#{e}\r\n" 100 | 101 | Session.set 'entryError', msg 102 | return true 103 | 104 | return false 105 | 106 | if passwordErrors then return 107 | 108 | emailRequired = _.contains([ 109 | 'USERNAME_AND_EMAIL', 110 | 'EMAIL_ONLY'], fields) 111 | 112 | usernameRequired = _.contains([ 113 | 'USERNAME_AND_EMAIL', 114 | 'USERNAME_ONLY'], fields) 115 | 116 | if usernameRequired && username.length is 0 117 | Session.set('entryError', t9n("error.usernameRequired")) 118 | return 119 | 120 | if username && AccountsEntry.isStringEmail(username) 121 | Session.set('entryError', t9n("error.usernameIsEmail")) 122 | return 123 | 124 | if emailRequired && email.length is 0 125 | Session.set('entryError', t9n("error.emailRequired")) 126 | return 127 | 128 | if AccountsEntry.settings.showSignupCode && signupCode.length is 0 129 | Session.set('entryError', t9n("error.signupCodeRequired")) 130 | return 131 | 132 | 133 | Meteor.call 'entryValidateSignupCode', signupCode, (err, valid) -> 134 | if valid 135 | newUserData = 136 | username: username 137 | email: email 138 | password: AccountsEntry.hashPassword(password) 139 | profile: filteredExtraFields 140 | Session.set 'talkingToServer', true 141 | Meteor.call 'entryCreateUser', newUserData, (err, data) -> 142 | Session.set 'talkingToServer', false 143 | if err 144 | console.log err 145 | T9NHelper.accountsError err 146 | return 147 | #login on client 148 | isEmailSignUp = _.contains([ 149 | 'USERNAME_AND_EMAIL', 150 | 'EMAIL_ONLY'], AccountsEntry.settings.passwordSignupFields) 151 | if isEmailSignUp 152 | userCredential = email 153 | else 154 | userCredential = username 155 | if AccountsEntry.settings.signInAfterRegistration is true 156 | Session.set 'talkingToServer', true 157 | Meteor.loginWithPassword userCredential, password, (error) -> 158 | Session.set 'talkingToServer', false 159 | if error 160 | console.log error 161 | T9NHelper.accountsError error 162 | else if Session.get 'fromWhere' 163 | Router.go Session.get('fromWhere') 164 | Session.set 'fromWhere', undefined 165 | else 166 | Router.go AccountsEntry.settings.dashboardRoute 167 | 168 | else 169 | if AccountsEntry.settings.emailVerificationPendingRoute 170 | Router.go AccountsEntry.settings.emailVerificationPendingRoute 171 | else 172 | console.log err 173 | Session.set 'entryError', t9n("error.signupCodeIncorrect") 174 | return 175 | } 176 | 177 | Template.entrySignUp.helpers(AccountsEntry.entrySignUpHelpers) 178 | 179 | Template.entrySignUp.events(AccountsEntry.entrySignUpEvents) 180 | -------------------------------------------------------------------------------- /client/views/signUp/signUp.html: -------------------------------------------------------------------------------- 1 | 86 | -------------------------------------------------------------------------------- /client/views/social/social.coffee: -------------------------------------------------------------------------------- 1 | 2 | Template.entrySocial.helpers 3 | 4 | buttonText: -> 5 | buttonText = Session.get('buttonText') 6 | if buttonText == 'up' 7 | t9n 'signUp' 8 | else 9 | t9n 'signIn' 10 | 11 | unconfigured: -> 12 | ServiceConfiguration.configurations.find({service: @toString()}).fetch().length is 0 13 | 14 | google: -> 15 | if @[0] == 'g' && @[1] == 'o' 16 | true 17 | 18 | icon: -> 19 | switch @.toString() 20 | when 'google' then 'google-plus' 21 | when 'meteor-developer' then 'rocket' 22 | else @ 23 | 24 | Template.entrySocial.events 25 | 26 | 'click .btn': (event)-> 27 | event.preventDefault() 28 | serviceName = $(event.target).attr('id').replace 'entry-', '' 29 | callback = (err) -> 30 | Session.set 'talkingToServer', false 31 | if (!err) 32 | if Session.get('fromWhere') 33 | Router.go Session.get('fromWhere') 34 | Session.set('fromWhere', undefined) 35 | else 36 | Router.go AccountsEntry.settings.dashboardRoute 37 | else if (err instanceof Accounts.LoginCancelledError) 38 | # do nothing 39 | else if (err instanceof ServiceConfiguration.ConfigError) 40 | Accounts._loginButtonsSession.configureService(serviceName) 41 | else 42 | Accounts._loginButtonsSession.errorMessage(err.reason || t9n("error.unknown")) 43 | if serviceName is 'meteor-developer' 44 | loginWithService = Meteor["loginWithMeteorDeveloperAccount"] 45 | else 46 | loginWithService = Meteor["loginWith" + capitalize(serviceName)] 47 | options = {} 48 | 49 | if (Accounts.ui._options.requestPermissions[serviceName]) 50 | options.requestPermissions = Accounts.ui._options.requestPermissions[serviceName] 51 | 52 | if (Accounts.ui._options.requestOfflineToken and Accounts.ui._options.requestOfflineToken[serviceName]) 53 | options.requestOfflineToken = Accounts.ui._options.requestOfflineToken[serviceName] 54 | Session.set 'talkingToServer', true 55 | loginWithService(options, callback) 56 | 57 | capitalize = (str) -> 58 | str.charAt(0).toUpperCase() + str.slice(1) 59 | -------------------------------------------------------------------------------- /client/views/social/social.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /client/views/verificationPending/verificationPending.coffee: -------------------------------------------------------------------------------- 1 | Template.entryVerificationPending.helpers 2 | error: -> t9n(Session.get('entryError')) 3 | 4 | logo: -> 5 | AccountsEntry.settings.logo 6 | 7 | -------------------------------------------------------------------------------- /client/views/verificationPending/verificationPending.html: -------------------------------------------------------------------------------- 1 | 26 | 27 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | summary: "Make signin and signout their own pages with routes.", 3 | version: '1.0.4', 4 | name: "joshowens:accounts-entry", 5 | githubUrl: 'https://github.com/Differential/accounts-entry', 6 | }); 7 | 8 | Package.onUse(function(api) { 9 | api.versionsFrom("METEOR@1.2.0.1"); 10 | 11 | api.use(['iron:router@1.0.3', 'softwarerero:accounts-t9n@1.0.3', 'joshowens:simple-form@0.2.1', 'sacha:spin@2.0.4'], ['client', 'server']); 12 | // CLIENT 13 | api.use([ 14 | 'deps', 15 | 'service-configuration', 16 | 'accounts-base', 17 | 'underscore', 18 | 'templating', 19 | 'handlebars', 20 | 'session', 21 | 'coffeescript', 22 | 'less', 23 | 'sha'] 24 | , 'client'); 25 | 26 | 27 | api.addFiles([ 28 | 'client/entry.coffee', 29 | 'client/entry.less', 30 | 'client/helpers.coffee', 31 | 'client/views/signIn/signIn.html', 32 | 'client/views/signIn/signIn.coffee', 33 | 'client/views/signUp/signUp.html', 34 | 'client/views/signUp/signUp.coffee', 35 | 'client/views/signUp/extraSignUpFields.html', 36 | 'client/views/signUp/extraSignUpFields.coffee', 37 | 'client/views/forgotPassword/forgotPassword.html', 38 | 'client/views/forgotPassword/forgotPassword.coffee', 39 | 'client/views/resetPassword/resetPassword.html', 40 | 'client/views/resetPassword/resetPassword.coffee', 41 | 'client/views/enrollAccount/enrollAccount.html', 42 | 'client/views/enrollAccount/enrollAccount.coffee', 43 | 'client/views/social/social.html', 44 | 'client/views/social/social.coffee', 45 | 'client/views/error/error.html', 46 | 'client/views/error/error.coffee', 47 | 'client/views/accountButtons/accountButtons.html', 48 | 'client/views/accountButtons/_wrapLinks.html', 49 | 'client/views/accountButtons/signedIn.html', 50 | 'client/views/accountButtons/accountButtons.coffee', 51 | 'client/views/verificationPending/verificationPending.html', 52 | 'client/views/verificationPending/verificationPending.coffee', 53 | 'client/t9n/english.coffee', 54 | 'client/t9n/french.coffee', 55 | 'client/t9n/german.coffee', 56 | 'client/t9n/italian.coffee', 57 | 'client/t9n/polish.coffee', 58 | 'client/t9n/spanish.coffee', 59 | 'client/t9n/swedish.coffee', 60 | 'client/t9n/portuguese.coffee', 61 | 'client/t9n/slovene.coffee', 62 | 'client/t9n/russian.coffee', 63 | 'client/t9n/arabic.coffee', 64 | 'client/t9n/hebrew.coffee' 65 | ], 'client'); 66 | 67 | // SERVER 68 | api.use([ 69 | 'deps', 70 | 'service-configuration', 71 | 'accounts-password', 72 | 'accounts-base', 73 | 'underscore', 74 | 'coffeescript' 75 | ], 'server'); 76 | 77 | api.addFiles(['server/entry.coffee'], 'server'); 78 | 79 | // CLIENT and SERVER 80 | api.imply('accounts-base', ['client', 'server']); 81 | api.imply('accounts-password', ['client', 'server']); 82 | api.export('AccountsEntry', ['client', 'server']); 83 | api.addFiles(['shared/router.coffee'], ['client', 'server']); 84 | 85 | }); 86 | 87 | Package.onTest(function (api) { 88 | api.use(['tinytest', 89 | 'underscore', 90 | 'handlebars', 91 | 'test-helpers', 92 | 'templating', 93 | 'mongo-livedata', 94 | 'coffeescript' 95 | ]); 96 | api.use(['iron:router', 'softwarerero:accounts-t9n', 'joshowens:simple-form'], ['client', 'server']); 97 | api.use('joshowens:accounts-entry'); 98 | 99 | api.addFiles(['tests/route.coffee', 'tests/client.html', 'tests/client.coffee'], 'client'); 100 | }); 101 | -------------------------------------------------------------------------------- /server/entry.coffee: -------------------------------------------------------------------------------- 1 | Meteor.startup -> 2 | Accounts.urls.resetPassword = (token) -> 3 | Meteor.absoluteUrl('reset-password/' + token) 4 | 5 | Accounts.urls.enrollAccount = (token) -> 6 | Meteor.absoluteUrl('enroll-account/' + token) 7 | 8 | AccountsEntry = 9 | settings: {} 10 | 11 | config: (appConfig) -> 12 | @settings = _.extend(@settings, appConfig) 13 | 14 | @AccountsEntry = AccountsEntry 15 | 16 | Meteor.methods 17 | entryValidateSignupCode: (signupCode) -> 18 | check signupCode, Match.OneOf(String, null, undefined) 19 | not AccountsEntry.settings.signupCode or signupCode is AccountsEntry.settings.signupCode 20 | 21 | entryCreateUser: (user) -> 22 | check user, Object 23 | profile = AccountsEntry.settings.defaultProfile || {} 24 | if user.username 25 | userId = Accounts.createUser 26 | username: user.username, 27 | email: user.email, 28 | password: user.password, 29 | profile: _.extend(profile, user.profile) 30 | else 31 | userId = Accounts.createUser 32 | email: user.email 33 | password: user.password 34 | profile: _.extend(profile, user.profile) 35 | if (user.email && Accounts._options.sendVerificationEmail) 36 | Accounts.sendVerificationEmail(userId, user.email) 37 | -------------------------------------------------------------------------------- /shared/router.coffee: -------------------------------------------------------------------------------- 1 | Router.map -> 2 | 3 | @route "entrySignIn", 4 | path: "/sign-in" 5 | onBeforeAction: -> 6 | Session.set('entryError', undefined) 7 | Session.set('buttonText', 'in') 8 | @next() 9 | onRun: -> 10 | if Meteor.userId() 11 | Router.go AccountsEntry.settings.dashboardRoute 12 | 13 | if AccountsEntry.settings.signInTemplate 14 | @template = AccountsEntry.settings.signInTemplate 15 | 16 | # If the user has a custom template, and not using the helper, then 17 | # maintain the package Javascript so that OpenGraph tags and share 18 | # buttons still work. 19 | pkgRendered= Template.entrySignIn.rendered 20 | userRendered = Template[@template].rendered 21 | 22 | if userRendered 23 | Template[@template].rendered = -> 24 | pkgRendered.call(@) 25 | userRendered.call(@) 26 | else 27 | Template[@template].rendered = pkgRendered 28 | 29 | Template[@template].events(AccountsEntry.entrySignInEvents) 30 | Template[@template].helpers(AccountsEntry.entrySignInHelpers) 31 | @next() 32 | 33 | 34 | @route "entrySignUp", 35 | path: "/sign-up" 36 | onBeforeAction: -> 37 | Session.set('entryError', undefined) 38 | Session.set('buttonText', 'up') 39 | @next() 40 | onRun: -> 41 | if AccountsEntry.settings.signUpTemplate 42 | @template = AccountsEntry.settings.signUpTemplate 43 | 44 | # If the user has a custom template, and not using the helper, then 45 | # maintain the package Javascript so that OpenGraph tags and share 46 | # buttons still work. 47 | pkgRendered= Template.entrySignUp.rendered 48 | userRendered = Template[@template].rendered 49 | 50 | if userRendered 51 | Template[@template].rendered = -> 52 | pkgRendered.call(@) 53 | userRendered.call(@) 54 | else 55 | Template[@template].rendered = pkgRendered 56 | 57 | Template[@template].events(AccountsEntry.entrySignUpEvents) 58 | Template[@template].helpers(AccountsEntry.entrySignUpHelpers) 59 | @next() 60 | 61 | 62 | @route "entryForgotPassword", 63 | path: "/forgot-password" 64 | onBeforeAction: -> 65 | Session.set('entryError', undefined) 66 | @next() 67 | 68 | @route 'entrySignOut', 69 | path: '/sign-out' 70 | onBeforeAction: ()-> 71 | Session.set('entryError', undefined) 72 | if not AccountsEntry.settings.homeRoute 73 | @next() 74 | else 75 | Meteor.logout () -> 76 | Router.go AccountsEntry.settings.homeRoute 77 | 78 | @route 'entryVerificationPending', 79 | path: '/verification-pending' 80 | onBeforeAction: -> 81 | Session.set('entryError', undefined) 82 | @next() 83 | 84 | @route 'entryResetPassword', 85 | path: 'reset-password/:resetToken' 86 | onBeforeAction: -> 87 | Session.set('entryError', undefined) 88 | Session.set('resetToken', @params.resetToken) 89 | @next() 90 | 91 | @route 'entryEnrollAccount', 92 | path: 'enroll-account/:resetToken' 93 | onBeforeAction: -> 94 | Session.set('entryError', undefined) 95 | Session.set('resetToken', @params.resetToken) 96 | 97 | # Get all the accounts-entry routes one time 98 | exclusions = [] 99 | _.each Router.routes, (route)-> 100 | exclusions.push route.getName() 101 | # Change the fromWhere session variable when you leave a path 102 | Router.onStop -> 103 | # If the route is an entry route, no need to save it 104 | if (!_.contains(exclusions, Router.current().route?.getName())) 105 | Session.set('fromWhere', window.location.pathname) 106 | -------------------------------------------------------------------------------- /tests/client.coffee: -------------------------------------------------------------------------------- 1 | renderToDiv = (comp) -> 2 | div = document.createElement("DIV") 3 | Blaze.render(comp,div) 4 | div 5 | 6 | Tinytest.add "Accounts Entry - {{accountButtons}} helper", (test) -> 7 | div = renderToDiv(Template.test_helper_account_buttons) 8 | html = canonicalizeHtml(div.innerHTML) 9 | test.include html, "Sign In" 10 | test.include html, "Register" 11 | 12 | Tinytest.add "Accounts Entry - wrapLinks setting on should wrap links in li elements", (test) -> 13 | AccountsEntry.settings.wrapLinks = true 14 | div = renderToDiv(Template.test_helper_account_buttons) 15 | html = canonicalizeHtml(div.innerHTML) 16 | test.include html, '
  • Sign In
  • ' 17 | 18 | Tinytest.add "Accounts Entry - wrapLinks setting on should not show 'or span'", (test) -> 19 | AccountsEntry.settings.wrapLinks = true 20 | div = renderToDiv(Template.test_helper_account_buttons) 21 | html = canonicalizeHtml(div.innerHTML) 22 | scan = html.indexOf('or') 23 | test.equal(scan, -1, "Html output includes or span but shouldn't") 24 | 25 | Tinytest.add "Accounts Entry - wrapLinks setting off should not wrap links in li elements", (test) -> 26 | AccountsEntry.settings.wrapLinks = false 27 | div = renderToDiv(Template.test_helper_account_buttons) 28 | html = canonicalizeHtml(div.innerHTML) 29 | scan = html.indexOf('
  • ') 30 | test.equal(scan, -1, "Html output shouldn't have li tags") 31 | 32 | Tinytest.add "Accounts Entry - wrapLinks setting off should show 'or span'", (test) -> 33 | AccountsEntry.settings.wrapLinks = false 34 | div = renderToDiv(Template.test_helper_account_buttons) 35 | html = canonicalizeHtml(div.innerHTML) 36 | test.include html, 'or' 37 | 38 | Tinytest.add "Accounts Entry - forgot password link should not show up if username only is set", (test) -> 39 | AccountsEntry.settings.passwordSignupFields = "USERNAME_ONLY" 40 | div = renderToDiv(Template.test_helper_sign_in) 41 | html = canonicalizeHtml(div.innerHTML) 42 | scan = html.indexOf('') 43 | test.equal(scan, -1, "Forgot password link should not show up if username only is set") 44 | 45 | Tinytest.add "Accounts Entry - adding extra fields to the layout", (test) -> 46 | AccountsEntry.settings.extraSignUpFields = [{field: 'zipcode', required: true, type: 'number'}] 47 | Package['accounts-password'] = true 48 | div = renderToDiv(Template.test_helper_sign_up) 49 | html = canonicalizeHtml(div.innerHTML) 50 | test.include html, '
    ' 51 | -------------------------------------------------------------------------------- /tests/client.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | 9 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /tests/route.coffee: -------------------------------------------------------------------------------- 1 | Router.map -> 2 | @route 'test_helper_home', 3 | path: '/' 4 | -------------------------------------------------------------------------------- /tests/server.coffee: -------------------------------------------------------------------------------- 1 | # Put something here 2 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "accounts-base", 5 | "1.1.2" 6 | ], 7 | [ 8 | "accounts-password", 9 | "1.0.4" 10 | ], 11 | [ 12 | "application-configuration", 13 | "1.0.3" 14 | ], 15 | [ 16 | "base64", 17 | "1.0.1" 18 | ], 19 | [ 20 | "binary-heap", 21 | "1.0.1" 22 | ], 23 | [ 24 | "blaze", 25 | "2.0.3" 26 | ], 27 | [ 28 | "blaze-tools", 29 | "1.0.1" 30 | ], 31 | [ 32 | "boilerplate-generator", 33 | "1.0.1" 34 | ], 35 | [ 36 | "callback-hook", 37 | "1.0.1" 38 | ], 39 | [ 40 | "check", 41 | "1.0.2" 42 | ], 43 | [ 44 | "coffeescript", 45 | "1.0.4" 46 | ], 47 | [ 48 | "ddp", 49 | "1.0.11" 50 | ], 51 | [ 52 | "deps", 53 | "1.0.5" 54 | ], 55 | [ 56 | "ejson", 57 | "1.0.4" 58 | ], 59 | [ 60 | "email", 61 | "1.0.4" 62 | ], 63 | [ 64 | "follower-livedata", 65 | "1.0.2" 66 | ], 67 | [ 68 | "geojson-utils", 69 | "1.0.1" 70 | ], 71 | [ 72 | "handlebars", 73 | "1.0.1" 74 | ], 75 | [ 76 | "html-tools", 77 | "1.0.2" 78 | ], 79 | [ 80 | "htmljs", 81 | "1.0.2" 82 | ], 83 | [ 84 | "id-map", 85 | "1.0.1" 86 | ], 87 | [ 88 | "iron:controller", 89 | "1.0.3" 90 | ], 91 | [ 92 | "iron:core", 93 | "1.0.3" 94 | ], 95 | [ 96 | "iron:dynamic-template", 97 | "1.0.3" 98 | ], 99 | [ 100 | "iron:layout", 101 | "1.0.3" 102 | ], 103 | [ 104 | "iron:location", 105 | "1.0.3" 106 | ], 107 | [ 108 | "iron:middleware-stack", 109 | "1.0.3" 110 | ], 111 | [ 112 | "iron:router", 113 | "1.0.3" 114 | ], 115 | [ 116 | "iron:url", 117 | "1.0.3" 118 | ], 119 | [ 120 | "joshowens:simple-form", 121 | "0.2.1" 122 | ], 123 | [ 124 | "jquery", 125 | "1.0.1" 126 | ], 127 | [ 128 | "json", 129 | "1.0.1" 130 | ], 131 | [ 132 | "less", 133 | "1.0.11" 134 | ], 135 | [ 136 | "localstorage", 137 | "1.0.1" 138 | ], 139 | [ 140 | "logging", 141 | "1.0.5" 142 | ], 143 | [ 144 | "meteor", 145 | "1.1.3" 146 | ], 147 | [ 148 | "minifiers", 149 | "1.1.2" 150 | ], 151 | [ 152 | "minimongo", 153 | "1.0.5" 154 | ], 155 | [ 156 | "mongo", 157 | "1.0.8" 158 | ], 159 | [ 160 | "mrt:underscore-string-latest", 161 | "2.3.3" 162 | ], 163 | [ 164 | "npm-bcrypt", 165 | "0.7.7" 166 | ], 167 | [ 168 | "observe-sequence", 169 | "1.0.3" 170 | ], 171 | [ 172 | "ordered-dict", 173 | "1.0.1" 174 | ], 175 | [ 176 | "random", 177 | "1.0.1" 178 | ], 179 | [ 180 | "reactive-dict", 181 | "1.0.4" 182 | ], 183 | [ 184 | "reactive-var", 185 | "1.0.3" 186 | ], 187 | [ 188 | "retry", 189 | "1.0.1" 190 | ], 191 | [ 192 | "routepolicy", 193 | "1.0.2" 194 | ], 195 | [ 196 | "schnie:uploader", 197 | "2.0.3" 198 | ], 199 | [ 200 | "service-configuration", 201 | "1.0.2" 202 | ], 203 | [ 204 | "session", 205 | "1.0.4" 206 | ], 207 | [ 208 | "sha", 209 | "1.0.1" 210 | ], 211 | [ 212 | "softwarerero:accounts-t9n", 213 | "1.0.3" 214 | ], 215 | [ 216 | "spacebars", 217 | "1.0.3" 218 | ], 219 | [ 220 | "spacebars-compiler", 221 | "1.0.3" 222 | ], 223 | [ 224 | "srp", 225 | "1.0.1" 226 | ], 227 | [ 228 | "templating", 229 | "1.0.9" 230 | ], 231 | [ 232 | "tracker", 233 | "1.0.3" 234 | ], 235 | [ 236 | "ui", 237 | "1.0.4" 238 | ], 239 | [ 240 | "underscore", 241 | "1.0.1" 242 | ], 243 | [ 244 | "webapp", 245 | "1.1.4" 246 | ], 247 | [ 248 | "webapp-hashing", 249 | "1.0.1" 250 | ] 251 | ], 252 | "pluginDependencies": [], 253 | "toolVersion": "meteor-tool@1.0.35", 254 | "format": "1.0" 255 | } 256 | --------------------------------------------------------------------------------