Commit 54cc928b324ad9cfdb6e45cf2995dd1310e5d2c6
Exists in
master
Merge branch 'feature/ES2015_#49' into v3.0.0
Closes #49
Showing
51 changed files
Show diff stats
.jshintrc
.meteor/packages
.meteor/versions
... | ... | @@ -17,6 +17,7 @@ caching-compiler@1.0.0 |
17 | 17 | caching-html-compiler@1.0.1 |
18 | 18 | callback-hook@1.0.4 |
19 | 19 | check@1.0.6 |
20 | +coffeescript@1.0.9 | |
20 | 21 | ddp@1.2.2 |
21 | 22 | ddp-client@1.2.1 |
22 | 23 | ddp-common@1.2.1 |
... | ... | @@ -24,6 +25,7 @@ ddp-rate-limiter@1.0.0 |
24 | 25 | ddp-server@1.2.1 |
25 | 26 | deps@1.0.9 |
26 | 27 | diff-sequence@1.0.1 |
28 | +digilord:faker@1.0.7 | |
27 | 29 | ecmascript@0.1.4 |
28 | 30 | ecmascript-collections@0.1.6 |
29 | 31 | ejson@1.0.7 | ... | ... |
both/methods/insert/collection.js
both/methods/insert/example.js
... | ... | @@ -1,20 +0,0 @@ |
1 | -/* | |
2 | -* Methods: Insert - Example | |
3 | -* Example of a method used for inserting into the database. | |
4 | -*/ | |
5 | - | |
6 | -Meteor.methods({ | |
7 | - exampleInsertMethod: function(argument){ | |
8 | - // Check the argument. Assuming an Object type here. | |
9 | - check(argument, Object); | |
10 | - | |
11 | - // Perform the insert. | |
12 | - try { | |
13 | - var exampleId = Example.insert(argument); | |
14 | - return exampleId; | |
15 | - } catch(exception) { | |
16 | - // If an error occurs, return it to the client. | |
17 | - return exception; | |
18 | - } | |
19 | - } | |
20 | -}); |
both/methods/read/collection.js
... | ... | @@ -0,0 +1,13 @@ |
1 | +Meteor.methods({ | |
2 | + readMethod( argument ) { | |
3 | + check( argument, String ); | |
4 | + | |
5 | + var document = Collection.findOne( argument ); | |
6 | + | |
7 | + if ( !document ) { | |
8 | + throw new Meteor.Error( 'document-not-found', 'No documents found matching this query.' ); | |
9 | + } | |
10 | + | |
11 | + return document; | |
12 | + } | |
13 | +}); | ... | ... |
both/methods/read/example.js
... | ... | @@ -1,22 +0,0 @@ |
1 | -/* | |
2 | -* Methods: Read - Example | |
3 | -* Example of a method used for reading from the database. | |
4 | -*/ | |
5 | - | |
6 | -Meteor.methods({ | |
7 | - exampleReadMethod: function(argument){ | |
8 | - // Check the argument. Assuming a String type here. | |
9 | - check(argument, String); | |
10 | - | |
11 | - // Perform the read. | |
12 | - var exampleItem = Example.findOne(argument); | |
13 | - | |
14 | - // If the read fails (no documents found), throw an error. | |
15 | - if (!exampleItem) { | |
16 | - throw new Meteor.Error(500, 'Error 500: Not Found', 'No documents found.'); | |
17 | - } | |
18 | - | |
19 | - // Return either the result or the error. | |
20 | - return exampleItem; | |
21 | - } | |
22 | -}); |
both/methods/remove/collection.js
both/methods/remove/example.js
... | ... | @@ -1,20 +0,0 @@ |
1 | -/* | |
2 | -* Methods: Remove - Example | |
3 | -* Example of a method used for removing a document from the database. | |
4 | -*/ | |
5 | - | |
6 | -Meteor.methods({ | |
7 | - exampleRemoveMethod: function(argument){ | |
8 | - // Check the argument. Assuming a String type here. | |
9 | - check(argument, String); | |
10 | - | |
11 | - // Perform the remove. | |
12 | - try { | |
13 | - var exampleId = Example.remove(argument); | |
14 | - return exampleId; | |
15 | - } catch(exception) { | |
16 | - // If an error occurs, return it to the client. | |
17 | - return exception; | |
18 | - } | |
19 | - } | |
20 | -}); |
both/methods/update/collection.js
... | ... | @@ -0,0 +1,14 @@ |
1 | +Meteor.methods({ | |
2 | + updateMethod( argument ) { | |
3 | + check( argument, Object ); | |
4 | + | |
5 | + try { | |
6 | + var documentId = Collection.update( argument._id, { | |
7 | + $set: { 'key': argument.key } | |
8 | + }); | |
9 | + return documentId; | |
10 | + } catch( exception ) { | |
11 | + return exception; | |
12 | + } | |
13 | + } | |
14 | +}); | ... | ... |
both/methods/update/example.js
... | ... | @@ -1,24 +0,0 @@ |
1 | -/* | |
2 | -* Methods: Update - Example | |
3 | -* Example of a method used for updating a document in the database. | |
4 | -*/ | |
5 | - | |
6 | -Meteor.methods({ | |
7 | - exampleUpdateMethod: function(argument){ | |
8 | - // Check the argument. Assuming an Object type here. | |
9 | - check(argument, Object); | |
10 | - | |
11 | - // Perform the update. | |
12 | - try { | |
13 | - var exampleId = Example.update(argument._id, { | |
14 | - $set: { | |
15 | - "someKey": argument.someKey | |
16 | - } | |
17 | - }); | |
18 | - return exampleId; | |
19 | - } catch(exception) { | |
20 | - // If an error occurs, return it to the client. | |
21 | - return exception; | |
22 | - } | |
23 | - } | |
24 | -}); |
both/modules/startup.js
both/startup.js
client/helpers/template.js
1 | -/* | |
2 | -* UI Helpers | |
3 | -* Define UI helpers for common template functionality. | |
4 | -*/ | |
5 | - | |
6 | -/* | |
7 | -* Current Route | |
8 | -* Return an active class if the currentRoute session variable name | |
9 | -* (set in the appropriate file in /client/routes/) is equal to the name passed | |
10 | -* to the helper in the template. | |
11 | -*/ | |
12 | - | |
13 | -UI.registerHelper('currentRoute', function(route){ | |
14 | - return Session.equals('currentRoute', route) ? 'active' : ''; | |
1 | +Template.registerHelper( 'currentRoute', ( route ) => { | |
2 | + return Session.equals( 'currentRoute', route ) ? 'active' : ''; | |
15 | 3 | }); | ... | ... |
client/modules/login.js
... | ... | @@ -0,0 +1,46 @@ |
1 | +let login = ( options ) => { | |
2 | + _validate( options.form, options.template ); | |
3 | +}; | |
4 | + | |
5 | +let _validate = ( form, template ) => { | |
6 | + $( form ).validate( validation( template ) ); | |
7 | +}; | |
8 | + | |
9 | +let validation = ( template ) => { | |
10 | + return { | |
11 | + rules: { | |
12 | + emailAddress: { | |
13 | + required: true, | |
14 | + email: true | |
15 | + }, | |
16 | + password: { | |
17 | + required: true | |
18 | + } | |
19 | + }, | |
20 | + messages: { | |
21 | + emailAddress: { | |
22 | + required: 'Need an email address here.', | |
23 | + email: 'Is this email address legit?' | |
24 | + }, | |
25 | + password: { | |
26 | + required: 'Need a password here.' | |
27 | + } | |
28 | + }, | |
29 | + submitHandler() { _handleLogin( template ); } | |
30 | + }; | |
31 | +}; | |
32 | + | |
33 | +let _handleLogin = ( template ) => { | |
34 | + let email = template.find( '[name="emailAddress"]' ).value, | |
35 | + password = template.find( '[name="password"]' ).value; | |
36 | + | |
37 | + Meteor.loginWithPassword( email, password, ( error ) => { | |
38 | + if ( error ) { | |
39 | + Bert.alert( error.reason, 'warning' ); | |
40 | + } else { | |
41 | + Bert.alert( 'Logged in!', 'success' ); | |
42 | + } | |
43 | + }); | |
44 | +}; | |
45 | + | |
46 | +Modules.client.login = login; | ... | ... |
client/modules/recover-password.js
... | ... | @@ -0,0 +1,39 @@ |
1 | +let recoverPassword = ( options ) => { | |
2 | + _validate( options.form, options.template ); | |
3 | +}; | |
4 | + | |
5 | +let _validate = ( form, template ) => { | |
6 | + $( form ).validate( validation( template ) ); | |
7 | +}; | |
8 | + | |
9 | +let validation = ( template ) => { | |
10 | + return { | |
11 | + rules: { | |
12 | + emailAddress: { | |
13 | + required: true, | |
14 | + email: true | |
15 | + } | |
16 | + }, | |
17 | + messages: { | |
18 | + emailAddress: { | |
19 | + required: 'Need an email address here.', | |
20 | + email: 'Is this email address legit?' | |
21 | + } | |
22 | + }, | |
23 | + submitHandler() { _handleRecovery( template ); } | |
24 | + }; | |
25 | +}; | |
26 | + | |
27 | +let _handleRecovery = ( template ) => { | |
28 | + let email = template.find( '[name="emailAddress"]' ).value; | |
29 | + | |
30 | + Accounts.forgotPassword( { email: email }, ( error ) => { | |
31 | + if ( error ) { | |
32 | + Bert.alert( error.reason, 'warning' ); | |
33 | + } else { | |
34 | + Bert.alert( 'Check your inbox for a reset link!', 'success' ); | |
35 | + } | |
36 | + }); | |
37 | +}; | |
38 | + | |
39 | +Modules.client.recoverPassword = recoverPassword; | ... | ... |
client/modules/reset-password.js
... | ... | @@ -0,0 +1,49 @@ |
1 | +let resetPassword = ( options ) => { | |
2 | + _validate( options.form, options.template ); | |
3 | +}; | |
4 | + | |
5 | +let _validate = ( form, template ) => { | |
6 | + $( form ).validate( validation( template ) ); | |
7 | +}; | |
8 | + | |
9 | +let validation = ( template ) => { | |
10 | + return { | |
11 | + rules: { | |
12 | + newPassword: { | |
13 | + required: true, | |
14 | + minlength: 6 | |
15 | + }, | |
16 | + repeatNewPassword: { | |
17 | + required: true, | |
18 | + minlength: 6, | |
19 | + equalTo: '[name="newPassword"]' | |
20 | + } | |
21 | + }, | |
22 | + messages: { | |
23 | + newPassword: { | |
24 | + required: "Enter a new password, please.", | |
25 | + minlength: "Use at least six characters, please." | |
26 | + }, | |
27 | + repeatNewPassword: { | |
28 | + required: "Repeat your new password, please.", | |
29 | + equalTo: "Hmm, your passwords don't match. Try again?" | |
30 | + } | |
31 | + }, | |
32 | + submitHandler() { _handleReset( template ); } | |
33 | + }; | |
34 | +}; | |
35 | + | |
36 | +let _handleReset = ( template ) => { | |
37 | + var token = "Test", | |
38 | + password = template.find( '[name="newPassword"]' ).value; | |
39 | + | |
40 | + Accounts.resetPassword( token, password, ( error ) => { | |
41 | + if ( error ) { | |
42 | + Bert.alert( error.reason, 'danger' ); | |
43 | + } else { | |
44 | + Bert.alert( 'Password reset!', 'success' ); | |
45 | + } | |
46 | + }); | |
47 | +}; | |
48 | + | |
49 | +Modules.client.resetPassword = resetPassword; | ... | ... |
client/modules/signup.js
... | ... | @@ -0,0 +1,50 @@ |
1 | +let signup = ( options ) => { | |
2 | + _validate( options.form, options.template ); | |
3 | +}; | |
4 | + | |
5 | +let _validate = ( form, template ) => { | |
6 | + $( form ).validate( validation( template ) ); | |
7 | +}; | |
8 | + | |
9 | +let validation = ( template ) => { | |
10 | + return { | |
11 | + rules: { | |
12 | + emailAddress: { | |
13 | + required: true, | |
14 | + email: true | |
15 | + }, | |
16 | + password: { | |
17 | + required: true, | |
18 | + minlength: 6 | |
19 | + } | |
20 | + }, | |
21 | + messages: { | |
22 | + emailAddress: { | |
23 | + required: 'Need an email address here.', | |
24 | + email: 'Is this email address legit?' | |
25 | + }, | |
26 | + password: { | |
27 | + required: 'Need a password here.', | |
28 | + minlength: 'Use at least six characters, please.' | |
29 | + } | |
30 | + }, | |
31 | + submitHandler() { _handleSignup( template ); } | |
32 | + }; | |
33 | +}; | |
34 | + | |
35 | +let _handleSignup = ( template ) => { | |
36 | + let user = { | |
37 | + email: template.find( '[name="emailAddress"]' ).value, | |
38 | + password: template.find( '[name="password"]' ).value | |
39 | + }; | |
40 | + | |
41 | + Accounts.createUser( user, ( error ) => { | |
42 | + if ( error ) { | |
43 | + Bert.alert( error.reason, 'danger' ); | |
44 | + } else { | |
45 | + Bert.alert( 'Welcome!', 'success' ); | |
46 | + } | |
47 | + }); | |
48 | +}; | |
49 | + | |
50 | +Modules.client.signup = signup; | ... | ... |
client/modules/startup.js
client/startup.js
client/stylesheets/application.scss
client/stylesheets/objects/_forms.scss
client/templates/authenticated/index.html
client/templates/authenticated/index.js
client/templates/globals/authenticated-navigation.html
... | ... | @@ -0,0 +1,10 @@ |
1 | +<template name="authenticatedNavigation"> | |
2 | + <ul class="nav navbar-nav navbar-right"> | |
3 | + <li class="dropdown"> | |
4 | + <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{currentUser.emails.[0].address}} <span class="caret"></span></a> | |
5 | + <ul class="dropdown-menu" role="menu"> | |
6 | + <li class="logout"><a href="#">Logout</a></li> | |
7 | + </ul> | |
8 | + </li> | |
9 | + </ul> | |
10 | +</template> | ... | ... |
client/templates/globals/header.html
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 | <nav class="navbar navbar-default" role="navigation"> |
3 | 3 | <div class="container"> |
4 | 4 | <div class="navbar-header"> |
5 | - <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> | |
5 | + <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse"> | |
6 | 6 | <span class="sr-only">Toggle navigation</span> |
7 | 7 | <span class="icon-bar"></span> |
8 | 8 | <span class="icon-bar"></span> |
... | ... | @@ -10,23 +10,13 @@ |
10 | 10 | </button> |
11 | 11 | <a class="navbar-brand" href="{{pathFor 'index'}}">Application Name</a> |
12 | 12 | </div> |
13 | - <div id="bs-example-navbar-collapse-1" class="collapse navbar-collapse"> | |
13 | + <div id="navbar-collapse" class="collapse navbar-collapse"> | |
14 | 14 | {{#if currentUser}} |
15 | - <ul class="nav navbar-nav navbar-right"> | |
16 | - <li class="dropdown"> | |
17 | - <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{currentUser.emails.[0].address}} <span class="caret"></span></a> | |
18 | - <ul class="dropdown-menu" role="menu"> | |
19 | - <li class="logout"><a href="#">Logout</a></li> | |
20 | - </ul> | |
21 | - </li> | |
22 | - </ul> | |
15 | + {{> authenticatedNavigation}} | |
23 | 16 | {{else}} |
24 | - <ul class="nav navbar-nav navbar-right"> | |
25 | - <li class="{{currentRoute 'login'}}"><a href="{{pathFor 'login'}}">Login</a></li> | |
26 | - <li class="{{currentRoute 'signup'}}"><a href="{{pathFor 'signup'}}">Sign Up</a></li> | |
27 | - </ul> | |
17 | + {{> publicNavigation}} | |
28 | 18 | {{/if}} |
29 | - </div> <!-- end .navbar-collapse --> | |
30 | - </div> <!-- end .container-fluid --> | |
19 | + </div> | |
20 | + </div> | |
31 | 21 | </nav> |
32 | 22 | </template> | ... | ... |
client/templates/globals/header.js
1 | -/* | |
2 | -* Controller: Header | |
3 | -* Template: /client/includes/_header.html | |
4 | -*/ | |
5 | - | |
6 | -/* | |
7 | -* Created | |
8 | -*/ | |
9 | - | |
10 | -Template.header.onCreated(function(){ | |
11 | - // Code to run when template is created goes here. | |
12 | -}); | |
13 | - | |
14 | -/* | |
15 | -* Rendered | |
16 | -*/ | |
17 | - | |
18 | -Template.header.onRendered(function() { | |
19 | - // Code to run when template is rendered goes here. | |
20 | -}); | |
21 | - | |
22 | -/* | |
23 | -* Helpers | |
24 | -*/ | |
25 | - | |
26 | -Template.header.helpers({ | |
27 | - example: function(){ | |
28 | - // Code to run for helper function. | |
29 | - } | |
30 | -}); | |
31 | - | |
32 | -/* | |
33 | -* Events | |
34 | -*/ | |
35 | - | |
36 | 1 | Template.header.events({ |
37 | - 'click .logout': function(){ | |
38 | - Meteor.logout(function(error){ | |
39 | - if(error){ | |
40 | - Bert.alert(error.reason, 'danger'); | |
2 | + 'click .logout' () { | |
3 | + Meteor.logout( ( error ) => { | |
4 | + if ( error ) { | |
5 | + Bert.alert( error.reason, 'warning' ); | |
41 | 6 | } else { |
42 | - Bert.alert('Succesfully logged out!', 'success'); | |
7 | + Bert.alert( 'Logged out!', 'success' ); | |
43 | 8 | } |
44 | 9 | }); |
45 | 10 | } | ... | ... |
client/templates/globals/loading.html
... | ... | @@ -0,0 +1,18 @@ |
1 | +<template name="loading"> | |
2 | + <svg version="1.1" id="loader-1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" | |
3 | + width="40px" height="40px" viewBox="0 0 40 40" enable-background="new 0 0 40 40" xml:space="preserve"> | |
4 | + <path opacity="1.0" fill="#eee" d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,14.946,14.946 | |
5 | + s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634 | |
6 | + c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z"/> | |
7 | + <path fill="#da5347" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0 | |
8 | + C22.32,8.481,24.301,9.057,26.013,10.047z"> | |
9 | + <animateTransform attributeType="xml" | |
10 | + attributeName="transform" | |
11 | + type="rotate" | |
12 | + from="0 20 20" | |
13 | + to="360 20 20" | |
14 | + dur="0.5s" | |
15 | + repeatCount="indefinite"/> | |
16 | + </path> | |
17 | + </svg> | |
18 | +</template> | ... | ... |
client/templates/globals/public-navigation.html
... | ... | @@ -0,0 +1,6 @@ |
1 | +<template name="publicNavigation"> | |
2 | + <ul class="nav navbar-nav navbar-right"> | |
3 | + <li class="{{currentRoute 'login'}}"><a href="{{pathFor 'login'}}">Login</a></li> | |
4 | + <li class="{{currentRoute 'signup'}}"><a href="{{pathFor 'signup'}}">Sign Up</a></li> | |
5 | + </ul> | |
6 | +</template> | ... | ... |
client/templates/public/loading.html
client/templates/public/login.html
1 | 1 | <template name="login"> |
2 | 2 | <div class="row"> |
3 | 3 | <div class="col-xs-12 col-sm-6 col-md-4"> |
4 | - <h3 class="page-header">Login</h3> | |
5 | - <form id="application-login" class="login"> | |
4 | + <h4 class="page-header">Login</h4> | |
5 | + <form id="login" class="login"> | |
6 | 6 | <div class="form-group"> |
7 | 7 | <label for="emailAddress">Email Address</label> |
8 | 8 | <input type="email" name="emailAddress" class="form-control" placeholder="Email Address"> |
9 | - </div> <!-- end .form-group --> | |
9 | + </div> | |
10 | 10 | <div class="form-group"> |
11 | 11 | <label for="password"><span class="pull-left">Password</span> <a class="pull-right" href="{{pathFor 'recover-password'}}">Forgot Password?</a></label> |
12 | 12 | <input type="password" name="password" class="form-control" placeholder="Password"> |
13 | - </div> <!-- end .form-group --> | |
13 | + </div> | |
14 | 14 | <div class="form-group"> |
15 | 15 | <input type="submit" class="btn btn-success" value="Login"> |
16 | - </div> <!-- end .form-group --> | |
16 | + </div> | |
17 | 17 | </form> |
18 | 18 | <p>Don't have an account? <a href="{{pathFor 'signup'}}">Sign Up</a>.</p> |
19 | - </div> <!-- end .col-xs-12 --> | |
20 | - </div> <!-- end .row --> | |
19 | + </div> | |
20 | + </div> | |
21 | 21 | </template> | ... | ... |
client/templates/public/login.js
1 | -/* | |
2 | -* Controller: Login | |
3 | -* Template: /client/views/public/login.html | |
4 | -*/ | |
5 | - | |
6 | -/* | |
7 | -* Created | |
8 | -*/ | |
9 | - | |
10 | -Template.login.onCreated(function(){ | |
11 | - // Code to run when template is created goes here. | |
12 | -}); | |
13 | - | |
14 | -/* | |
15 | -* Rendered | |
16 | -*/ | |
17 | - | |
18 | -Template.login.onRendered(function(){ | |
19 | - $('#application-login').validate({ | |
20 | - rules: { | |
21 | - emailAddress: { | |
22 | - required: true, | |
23 | - email: true | |
24 | - }, | |
25 | - password: { | |
26 | - required: true | |
27 | - } | |
28 | - }, | |
29 | - messages: { | |
30 | - emailAddress: { | |
31 | - required: "Please enter your email address to login.", | |
32 | - email: "Please enter a valid email address." | |
33 | - }, | |
34 | - password: { | |
35 | - required: "Please enter your password to login." | |
36 | - } | |
37 | - }, | |
38 | - submitHandler: function(){ | |
39 | - // Grab the user's details. | |
40 | - user = { | |
41 | - email: $('[name="emailAddress"]').val(), | |
42 | - password: $('[name="password"]').val() | |
43 | - } | |
44 | - | |
45 | - // Log the user in. | |
46 | - Meteor.loginWithPassword(user.email, user.password, function(error){ | |
47 | - if(error){ | |
48 | - Bert.alert(error.reason, 'danger'); | |
49 | - } else { | |
50 | - Bert.alert('Logged in!', 'success'); | |
51 | - } | |
52 | - }); | |
53 | - } | |
54 | - }); | |
1 | +Template.login.onRendered( () => { | |
2 | + Modules.client.login( { form: "#login", template: Template.instance() } ); | |
55 | 3 | }); |
56 | 4 | |
57 | -/* | |
58 | -* Helpers | |
59 | -*/ | |
60 | - | |
61 | -Template.login.helpers({ | |
62 | - example: function(){ | |
63 | - // Code to run for helper function. | |
64 | - } | |
65 | -}); | |
66 | - | |
67 | -/* | |
68 | -* Events | |
69 | -*/ | |
70 | - | |
71 | 5 | Template.login.events({ |
72 | - 'submit form': function(e){ | |
73 | - // Prevent form from submitting. | |
74 | - e.preventDefault(); | |
75 | - } | |
6 | + 'submit form': ( event ) => event.preventDefault() | |
76 | 7 | }); | ... | ... |
client/templates/public/recover-password.html
1 | 1 | <template name="recoverPassword"> |
2 | 2 | <div class="row"> |
3 | 3 | <div class="col-xs-12 col-sm-6 col-md-4"> |
4 | - <h3 class="page-header">Recover Password</h3> | |
5 | - <form id="application-recover-password" class="recover-password"> | |
6 | - <p>Enter the email address associated with your account below and click the "Recover Password" button. You will receive an email with further instructions on how to reset your password.</p> | |
4 | + <h4 class="page-header">Recover Password</h4> | |
5 | + <form id="recover-password" class="recover-password"> | |
6 | + <p class="alert alert-info">Enter your email address below to receive a link to reset your password.</p> | |
7 | 7 | <div class="form-group"> |
8 | 8 | <label for="emailAddress">Email Address</label> |
9 | 9 | <input type="email" name="emailAddress" class="form-control" placeholder="Email Address"> |
10 | - </div> <!-- end .form-group --> | |
10 | + </div> | |
11 | 11 | <div class="form-group"> |
12 | 12 | <input type="submit" class="btn btn-success" value="Recover Password"> |
13 | - </div> <!-- end .form-group --> | |
13 | + </div> | |
14 | 14 | </form> |
15 | - </div> <!-- end .col-xs-12 --> | |
16 | - </div> <!-- end .row --> | |
15 | + </div> | |
16 | + </div> | |
17 | 17 | </template> | ... | ... |
client/templates/public/recover-password.js
1 | -/* | |
2 | -* Controller: Recover Password | |
3 | -* Template: /client/views/public/recover-password.html | |
4 | -*/ | |
5 | - | |
6 | -/* | |
7 | -* Created | |
8 | -*/ | |
9 | - | |
10 | -Template.recoverPassword.onCreated(function(){ | |
11 | - // Code to run when template is created goes here. | |
12 | -}); | |
13 | - | |
14 | -/* | |
15 | -* Rendered | |
16 | -*/ | |
17 | - | |
18 | - | |
19 | -Template.recoverPassword.onRendered(function(){ | |
20 | - $('#application-recover-password').validate({ | |
21 | - rules: { | |
22 | - emailAddress: { | |
23 | - required: true, | |
24 | - email: true | |
25 | - } | |
26 | - }, | |
27 | - messages: { | |
28 | - emailAddress: { | |
29 | - required: "Please enter your email address to recover your password.", | |
30 | - email: "Please enter a valid email address." | |
31 | - } | |
32 | - }, | |
33 | - submitHandler: function(){ | |
34 | - // Grab the user's email address. | |
35 | - var email = $('[name="emailAddress"]').val(); | |
36 | - | |
37 | - // Call the send reset password email method. | |
38 | - Accounts.forgotPassword({email: email}, function(error){ | |
39 | - if(error){ | |
40 | - Bert.alert(error.reason, 'danger'); | |
41 | - } else { | |
42 | - Bert.alert('Check your inbox for a reset link!', 'success'); | |
43 | - } | |
44 | - }); | |
45 | - } | |
1 | +Template.recoverPassword.onRendered( () => { | |
2 | + Modules.client.recoverPassword({ | |
3 | + form: "#recover-password", | |
4 | + template: Template.instance() | |
46 | 5 | }); |
47 | 6 | }); |
48 | 7 | |
49 | -/* | |
50 | -* Helpers | |
51 | -*/ | |
52 | - | |
53 | -Template.recoverPassword.helpers({ | |
54 | - example: function(){ | |
55 | - // Code to run for helper function. | |
56 | - } | |
57 | -}); | |
58 | - | |
59 | -/* | |
60 | -* Events | |
61 | -*/ | |
62 | - | |
63 | 8 | Template.recoverPassword.events({ |
64 | - 'submit form': function(e){ | |
65 | - // Prevent form from submitting. | |
66 | - e.preventDefault(); | |
67 | - } | |
9 | + 'submit form': ( event ) => event.preventDefault() | |
68 | 10 | }); | ... | ... |
client/templates/public/reset-password.html
1 | 1 | <template name="resetPassword"> |
2 | 2 | <div class="row"> |
3 | 3 | <div class="col-xs-12 col-sm-6 col-md-4"> |
4 | - <h3 class="page-header">Reset Password</h3> | |
5 | - <form id="application-reset-password" class="reset-password"> | |
6 | - <p>Enter your new password below and repeat it to confirm. This will reset your password and log you into the application.</p> | |
4 | + <h4 class="page-header">Reset Password</h4> | |
5 | + <form id="reset-password" class="reset-password"> | |
6 | + <p class="alert alert-info">To reset your password, enter a new one below. You will be logged in with your new password.</p> | |
7 | 7 | <div class="form-group"> |
8 | 8 | <label for="newPassword">New Password</label> |
9 | 9 | <input type="password" name="newPassword" class="form-control" placeholder="New Password"> |
10 | - </div> <!-- end .form-group --> | |
10 | + </div> | |
11 | 11 | <div class="form-group"> |
12 | 12 | <label for="password">Repeat New Password</label> |
13 | 13 | <input type="password" name="repeatNewPassword" class="form-control" placeholder="Password"> |
14 | - </div> <!-- end .form-group --> | |
14 | + </div> | |
15 | 15 | <div class="form-group"> |
16 | 16 | <input type="submit" class="btn btn-success" value="Reset Password & Login"> |
17 | - </div> <!-- end .form-group --> | |
17 | + </div> | |
18 | 18 | </form> |
19 | - </div> <!-- end .col-xs-12 --> | |
20 | - </div> <!-- end .row --> | |
19 | + </div> | |
20 | + </div> | |
21 | 21 | </template> | ... | ... |
client/templates/public/reset-password.js
1 | -/* | |
2 | -* Controller: Reset Password | |
3 | -* Template: /client/views/public/reset-password.html | |
4 | -*/ | |
5 | - | |
6 | -/* | |
7 | -* Created | |
8 | -*/ | |
9 | - | |
10 | -Template.resetPassword.onCreated(function(){ | |
11 | - // Code to run when template is created goes here. | |
12 | -}); | |
13 | - | |
14 | -/* | |
15 | -* Rendered | |
16 | -*/ | |
17 | - | |
18 | -Template.resetPassword.onRendered(function(){ | |
19 | - $('#application-reset-password').validate({ | |
20 | - rules: { | |
21 | - newPassword: { | |
22 | - required: true, | |
23 | - minlength: 6 | |
24 | - }, | |
25 | - repeatNewPassword: { | |
26 | - required: true, | |
27 | - minlength: 6, | |
28 | - equalTo: "[name='newPassword']" | |
29 | - } | |
30 | - }, | |
31 | - messages: { | |
32 | - newPassword: { | |
33 | - required: "Please enter a new password.", | |
34 | - minlength: "Please use at least six characters." | |
35 | - }, | |
36 | - repeatNewPassword: { | |
37 | - required: "Please repeat your new password.", | |
38 | - equalTo: "Your password do not match. Please try again." | |
39 | - } | |
40 | - }, | |
41 | - submitHandler: function(){ | |
42 | - // Grab the user's reset token and new password. | |
43 | - var token = Session.get('resetPasswordToken'), | |
44 | - password = $('[name="newPassword"]').val(); | |
45 | - | |
46 | - // Reset the user's password. | |
47 | - Accounts.resetPassword(token, password, function(error){ | |
48 | - if(error){ | |
49 | - Bert.alert(error.reason, 'danger'); | |
50 | - } else { | |
51 | - Bert.alert('Password successfully reset!', 'success'); | |
52 | - Session.set('resetPasswordToken', null); | |
53 | - } | |
54 | - }); | |
55 | - } | |
1 | +Template.resetPassword.onRendered( () => { | |
2 | + Modules.client.resetPassword({ | |
3 | + form: "#reset-password", | |
4 | + template: Template.instance() | |
56 | 5 | }); |
57 | 6 | }); |
58 | 7 | |
59 | -/* | |
60 | -* Helpers | |
61 | -*/ | |
62 | - | |
63 | -Template.resetPassword.helpers({ | |
64 | - example: function(){ | |
65 | - // Code to run for helper function. | |
66 | - } | |
67 | -}); | |
68 | - | |
69 | -/* | |
70 | -* Events | |
71 | -*/ | |
72 | - | |
73 | 8 | Template.resetPassword.events({ |
74 | - 'submit form': function(e){ | |
75 | - // Prevent form from submitting. | |
76 | - e.preventDefault(); | |
77 | - } | |
9 | + 'submit form': ( event ) => event.preventDefault() | |
78 | 10 | }); | ... | ... |
client/templates/public/signup.html
1 | 1 | <template name="signup"> |
2 | 2 | <div class="row"> |
3 | 3 | <div class="col-xs-12 col-sm-6 col-md-4"> |
4 | - <h3 class="page-header">Sign Up</h3> | |
5 | - <form id="application-signup" class="signup"> | |
4 | + <h4 class="page-header">Sign Up</h4> | |
5 | + <form id="signup" class="signup"> | |
6 | 6 | <div class="form-group"> |
7 | 7 | <label for="emailAddress">Email Address</label> |
8 | 8 | <input type="email" name="emailAddress" class="form-control" placeholder="Email Address"> |
9 | - </div> <!-- end .form-group --> | |
9 | + </div> | |
10 | 10 | <div class="form-group"> |
11 | 11 | <label for="password">Password</label> |
12 | 12 | <input type="password" name="password" class="form-control" placeholder="Password"> |
13 | - </div> <!-- end .form-group --> | |
13 | + </div> | |
14 | 14 | <div class="form-group"> |
15 | 15 | <input type="submit" class="btn btn-success" value="Sign Up"> |
16 | - </div> <!-- end .form-group --> | |
16 | + </div> | |
17 | 17 | </form> |
18 | 18 | <p>Already have an account? <a href="{{pathFor 'login'}}">Log In</a>.</p> |
19 | - </div> <!-- end .col-xs-12 --> | |
20 | - </div> <!-- end .row --> | |
19 | + </div> | |
20 | + </div> | |
21 | 21 | </template> | ... | ... |
client/templates/public/signup.js
1 | -/* | |
2 | -* Controller: Signup | |
3 | -* Template: /client/views/public/signup.html | |
4 | -*/ | |
5 | - | |
6 | -/* | |
7 | -* Created | |
8 | -*/ | |
9 | - | |
10 | -Template.signup.onCreated(function(){ | |
11 | - // Code to run when template is created goes here. | |
12 | -}); | |
13 | - | |
14 | -/* | |
15 | -* Rendered | |
16 | -*/ | |
17 | - | |
18 | -Template.signup.onRendered(function(){ | |
19 | - $('#application-signup').validate({ | |
20 | - rules: { | |
21 | - emailAddress: { | |
22 | - required: true, | |
23 | - email: true | |
24 | - }, | |
25 | - password: { | |
26 | - required: true, | |
27 | - minlength: 6 | |
28 | - } | |
29 | - }, | |
30 | - messages: { | |
31 | - emailAddress: { | |
32 | - required: "Please enter your email address to sign up.", | |
33 | - email: "Please enter a valid email address." | |
34 | - }, | |
35 | - password: { | |
36 | - required: "Please enter a password to sign up.", | |
37 | - minlength: "Please use at least six characters." | |
38 | - } | |
39 | - }, | |
40 | - submitHandler: function(){ | |
41 | - // Grab the user's details. | |
42 | - user = { | |
43 | - email: $('[name="emailAddress"]').val(), | |
44 | - password: $('[name="password"]').val() | |
45 | - } | |
46 | - | |
47 | - // Create the user's account. | |
48 | - Accounts.createUser({email: user.email, password: user.password}, function(error){ | |
49 | - if(error){ | |
50 | - Bert.alert(error.reason, 'danger'); | |
51 | - } else { | |
52 | - Bert.alert('Welcome!', 'success'); | |
53 | - } | |
54 | - }); | |
55 | - } | |
1 | +Template.signup.onRendered( () => { | |
2 | + Modules.client.signup({ | |
3 | + form: "#signup", | |
4 | + template: Template.instance() | |
56 | 5 | }); |
57 | 6 | }); |
58 | 7 | |
59 | -/* | |
60 | -* Helpers | |
61 | -*/ | |
62 | - | |
63 | -Template.signup.helpers({ | |
64 | - example: function(){ | |
65 | - // Code to run for helper function. | |
66 | - } | |
67 | -}); | |
68 | - | |
69 | -/* | |
70 | -* Events | |
71 | -*/ | |
72 | - | |
73 | 8 | Template.signup.events({ |
74 | - 'submit form': function(e){ | |
75 | - // Prevent form from submitting. | |
76 | - e.preventDefault(); | |
77 | - } | |
9 | + 'submit form': ( event ) => event.preventDefault() | |
78 | 10 | }); | ... | ... |
collections/collection.js
... | ... | @@ -0,0 +1,13 @@ |
1 | +Collection = new Meteor.Collection( 'collection' ); | |
2 | + | |
3 | +Collection.allow({ | |
4 | + insert: () => false, | |
5 | + update: () => false, | |
6 | + remove: () => false | |
7 | +}); | |
8 | + | |
9 | +Collection.deny({ | |
10 | + insert: () => true, | |
11 | + update: () => true, | |
12 | + remove: () => true | |
13 | +}); | ... | ... |
collections/example.js
... | ... | @@ -1,39 +0,0 @@ |
1 | -Example = new Meteor.Collection('example'); | |
2 | - | |
3 | -/* | |
4 | -* Allow | |
5 | -*/ | |
6 | - | |
7 | -Example.allow({ | |
8 | - insert: function(){ | |
9 | - // Disallow inserts on the client by default. | |
10 | - return false; | |
11 | - }, | |
12 | - update: function(){ | |
13 | - // Disallow updates on the client by default. | |
14 | - return false; | |
15 | - }, | |
16 | - remove: function(){ | |
17 | - // Disallow removes on the client by default. | |
18 | - return false; | |
19 | - } | |
20 | -}); | |
21 | - | |
22 | -/* | |
23 | -* Deny | |
24 | -*/ | |
25 | - | |
26 | -Example.deny({ | |
27 | - insert: function(){ | |
28 | - // Deny inserts on the client by default. | |
29 | - return true; | |
30 | - }, | |
31 | - update: function(){ | |
32 | - // Deny updates on the client by default. | |
33 | - return true; | |
34 | - }, | |
35 | - remove: function(){ | |
36 | - // Deny removes on the client by default. | |
37 | - return true; | |
38 | - } | |
39 | -}); |
collections/users.js
1 | -/* | |
2 | -* Allow | |
3 | -*/ | |
4 | - | |
5 | 1 | Meteor.users.allow({ |
6 | - insert: function(){ | |
7 | - // Disallow user inserts on the client by default. | |
8 | - return false; | |
9 | - }, | |
10 | - update: function(){ | |
11 | - // Disallow user updates on the client by default. | |
12 | - return false; | |
13 | - }, | |
14 | - remove: function(){ | |
15 | - // Disallow user removes on the client by default. | |
16 | - return false; | |
17 | - } | |
2 | + insert: () => false, | |
3 | + update: () => false, | |
4 | + remove: () => false | |
18 | 5 | }); |
19 | 6 | |
20 | -/* | |
21 | -* Deny | |
22 | -*/ | |
23 | - | |
24 | 7 | Meteor.users.deny({ |
25 | - insert: function(){ | |
26 | - // Deny user inserts on the client by default. | |
27 | - return true; | |
28 | - }, | |
29 | - update: function(){ | |
30 | - // Deny user updates on the client by default. | |
31 | - return true; | |
32 | - }, | |
33 | - remove: function(){ | |
34 | - // Deny user removes on the client by default. | |
35 | - return true; | |
36 | - } | |
8 | + insert: () => true, | |
9 | + update: () => true, | |
10 | + remove: () => true | |
37 | 11 | }); | ... | ... |
server/admin/reset-password.js
... | ... | @@ -0,0 +1,12 @@ |
1 | +Accounts.emailTemplates.resetPassword.siteName = () => "Application Name"; | |
2 | +Accounts.emailTemplates.resetPassword.from = () => "Application Name <admin@application.com>"; | |
3 | +Accounts.emailTemplates.resetPassword.subject = () => "[Application Name] Reset Your Password"; | |
4 | + | |
5 | +Accounts.emailTemplates.resetPassword.text = ( user, url ) => { | |
6 | + let emailAddress = user.emails[0].address, | |
7 | + urlWithoutHash = url.replace( '#/', '' ), | |
8 | + supportEmail = "support@application.com", | |
9 | + emailBody = `A password reset has been requested for the account related to this address (${emailAddress}). To reset the password, visit the following link:\n\n${urlWithoutHash}\n\n If you did not request this reset, please ignore this email. If you feel something is wrong, please contact our support team: ${supportEmail}.`; | |
10 | + | |
11 | + return emailBody; | |
12 | +}; | ... | ... |
server/admin/startup-functions/browser-policies.js
server/admin/startup-functions/test-accounts.js
... | ... | @@ -1,29 +0,0 @@ |
1 | -/* | |
2 | -* Generate Test Accounts | |
3 | -* Creates a collection of test accounts automatically on startup. | |
4 | -*/ | |
5 | - | |
6 | -generateTestAccounts = function(){ | |
7 | - // Create an array of user accounts. | |
8 | - var users = [ | |
9 | - { name: "Admin", email: "admin@admin.com", password: "password" } | |
10 | - ] | |
11 | - | |
12 | - // Loop through array of user accounts. | |
13 | - for(i=0; i < users.length; i++){ | |
14 | - // Check if the user already exists in the DB. | |
15 | - var userEmail = users[i].email, | |
16 | - checkUser = Meteor.users.findOne({"emails.address": userEmail}); | |
17 | - | |
18 | - // If an existing user is not found, create the account. | |
19 | - if ( !checkUser ) { | |
20 | - Accounts.createUser({ | |
21 | - email: userEmail, | |
22 | - password: users[i].password, | |
23 | - profile: { | |
24 | - name: users[i].name | |
25 | - } | |
26 | - }); | |
27 | - } | |
28 | - } | |
29 | -} |
server/admin/startup.js
... | ... | @@ -1,15 +0,0 @@ |
1 | -/* | |
2 | -* Startup | |
3 | -* Functions to run on server startup. Note: this file is for calling functions | |
4 | -* only. Define functions in /server/admin/startup-functions. | |
5 | -*/ | |
6 | - | |
7 | -Meteor.startup(function(){ | |
8 | - | |
9 | - // Custom Browser Policies | |
10 | - customBrowserPolicies(); | |
11 | - | |
12 | - // Generate Test Accounts | |
13 | - generateTestAccounts(); | |
14 | - | |
15 | -}); |
server/email/templates/reset-password.js
... | ... | @@ -1,20 +0,0 @@ |
1 | -/* | |
2 | -* Reset Password Email Template | |
3 | -* Override Meteor defaults when sending a reset password email. | |
4 | -*/ | |
5 | - | |
6 | -// Set name and from email. | |
7 | -Accounts.emailTemplates.resetPassword.siteName = "Application Name"; | |
8 | -Accounts.emailTemplates.resetPassword.from = "Application Admin Email <admin@application.com>"; | |
9 | - | |
10 | -// Set a subject for the reset password email. | |
11 | -Accounts.emailTemplates.resetPassword.subject = function(user){ | |
12 | - return "[Application Name] Reset Your Password"; | |
13 | -} | |
14 | - | |
15 | -// Set the body of the reset password email. | |
16 | -Accounts.emailTemplates.resetPassword.text = function(user, url){ | |
17 | - var email = user.emails[0].address, | |
18 | - removeHash = url.replace('#/', ''); | |
19 | - return "A password reset has been requested for the account related to this address(" + email + "). To reset the password, visit the following link:\n\n" + removeHash + "\n\n If you did not request this reset, please ignore this email. If you feel something is wrong, please contact support: admin@application.com." | |
20 | -} |
server/modules/generate-accounts.js
... | ... | @@ -0,0 +1,63 @@ |
1 | +let administrators = [ | |
2 | + { | |
3 | + name: { first: 'Admin', last: 'McAdmin' }, | |
4 | + email: 'admin@admin.com', | |
5 | + password: 'password' | |
6 | + } | |
7 | +]; | |
8 | + | |
9 | +let generateAccounts = () => { | |
10 | + let fakeUserCount = 5, | |
11 | + usersExist = _checkIfAccountsExist( administrators.length + fakeUserCount ); | |
12 | + | |
13 | + if ( !usersExist ) { | |
14 | + _createUsers( administrators ); | |
15 | + _createUsers( _generateFakeUsers( fakeUserCount ) ); | |
16 | + } | |
17 | +}; | |
18 | + | |
19 | +let _checkIfAccountsExist = ( count ) => { | |
20 | + let userCount = Meteor.users.find().count(); | |
21 | + return userCount < count ? false : true; | |
22 | +}; | |
23 | + | |
24 | +let _createUsers = ( users ) => { | |
25 | + for ( let i = 0; i < users.length; i++ ) { | |
26 | + let user = users[ i ], | |
27 | + userExists = _checkIfUserExists( user.email ); | |
28 | + | |
29 | + if ( !userExists ) { | |
30 | + _createUser( user ); | |
31 | + } | |
32 | + } | |
33 | +}; | |
34 | + | |
35 | +let _checkIfUserExists = ( email ) => { | |
36 | + return Meteor.users.findOne( { 'emails.address': email } ); | |
37 | +}; | |
38 | + | |
39 | +let _createUser = ( user ) => { | |
40 | + Accounts.createUser({ | |
41 | + email: user.email, | |
42 | + password: user.password, | |
43 | + profile: { | |
44 | + name: user.name | |
45 | + } | |
46 | + }); | |
47 | +}; | |
48 | + | |
49 | +let _generateFakeUsers = ( count ) => { | |
50 | + let users = []; | |
51 | + | |
52 | + for ( let i = 0; i < count; i++ ) { | |
53 | + users.push({ | |
54 | + name: { first: faker.name.firstName(), last: faker.name.lastName() }, | |
55 | + email: faker.internet.email(), | |
56 | + password: 'password' | |
57 | + }); | |
58 | + } | |
59 | + | |
60 | + return users; | |
61 | +}; | |
62 | + | |
63 | +Modules.server.generateAccounts = generateAccounts; | ... | ... |
server/modules/startup.js
server/publications/example.js
... | ... | @@ -1,17 +0,0 @@ |
1 | -/* | |
2 | -* Publications: Example | |
3 | -* Data publications for the Example collection. | |
4 | -*/ | |
5 | - | |
6 | -Meteor.publish('examplePublication', function(){ | |
7 | - // If need be, Meteor gives us access to the current user via this.userId. | |
8 | - // Example below shows using this.userId to locate documents where the | |
9 | - // owner field is equal to a userId. Additionally, a fields projection is | |
10 | - // added to specify which fields you want to return (where 1 = true and | |
11 | - // 0 = false). | |
12 | - | |
13 | - var user = this.userId; | |
14 | - var data = Example.find({"owner": user}, {fields: {"owner": 1}}); | |
15 | - | |
16 | - return data; | |
17 | -}); |
server/publications/template.js
server/startup.js