Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b99da301cd | ||
|
|
0a01885300 | ||
|
|
5cb1515235 |
@@ -20,3 +20,7 @@ mike:mocha
|
|||||||
dburles:mongo-collection-instances
|
dburles:mongo-collection-instances
|
||||||
percolate:migrations
|
percolate:migrations
|
||||||
ecwyne:mathjs
|
ecwyne:mathjs
|
||||||
|
useraccounts:polymer
|
||||||
|
accounts-google
|
||||||
|
splendido:accounts-meld
|
||||||
|
email
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
accounts-base@1.2.0
|
accounts-base@1.2.0
|
||||||
|
accounts-google@1.0.4
|
||||||
|
accounts-oauth@1.1.5
|
||||||
accounts-password@1.1.1
|
accounts-password@1.1.1
|
||||||
accounts-ui@1.1.5
|
accounts-ui@1.1.5
|
||||||
accounts-ui-unstyled@1.1.7
|
accounts-ui-unstyled@1.1.7
|
||||||
aldeed:collection2@2.3.3
|
aldeed:collection2@2.3.3
|
||||||
aldeed:simple-schema@1.3.2
|
aldeed:simple-schema@1.3.3
|
||||||
amplify@1.0.0
|
amplify@1.0.0
|
||||||
autoupdate@1.2.1
|
autoupdate@1.2.1
|
||||||
base64@1.0.3
|
base64@1.0.3
|
||||||
@@ -24,6 +26,7 @@ ejson@1.0.6
|
|||||||
email@1.0.6
|
email@1.0.6
|
||||||
fastclick@1.0.3
|
fastclick@1.0.3
|
||||||
geojson-utils@1.0.3
|
geojson-utils@1.0.3
|
||||||
|
google@1.1.5
|
||||||
html-tools@1.0.4
|
html-tools@1.0.4
|
||||||
htmljs@1.0.4
|
htmljs@1.0.4
|
||||||
http@1.1.0
|
http@1.1.0
|
||||||
@@ -44,20 +47,22 @@ less@1.0.14
|
|||||||
livedata@1.0.13
|
livedata@1.0.13
|
||||||
localstorage@1.0.3
|
localstorage@1.0.3
|
||||||
logging@1.0.7
|
logging@1.0.7
|
||||||
matb33:collection-hooks@0.7.11
|
matb33:collection-hooks@0.7.13
|
||||||
meteor@1.1.6
|
meteor@1.1.6
|
||||||
meteor-platform@1.2.2
|
meteor-platform@1.2.2
|
||||||
mike:mocha@0.5.3
|
mike:mocha@0.5.4
|
||||||
minifiers@1.1.5
|
minifiers@1.1.5
|
||||||
minimongo@1.0.8
|
minimongo@1.0.8
|
||||||
mobile-status-bar@1.0.3
|
mobile-status-bar@1.0.3
|
||||||
momentjs:moment@2.10.3
|
momentjs:moment@2.10.3
|
||||||
mongo@1.1.0
|
mongo@1.1.0
|
||||||
npm-bcrypt@0.7.8_2
|
npm-bcrypt@0.7.8_2
|
||||||
|
oauth@1.1.4
|
||||||
|
oauth2@1.1.3
|
||||||
observe-sequence@1.0.6
|
observe-sequence@1.0.6
|
||||||
ordered-dict@1.0.3
|
ordered-dict@1.0.3
|
||||||
package-version-parser@3.0.3
|
package-version-parser@3.0.3
|
||||||
percolate:migrations@0.7.3
|
percolate:migrations@0.7.5
|
||||||
practicalmeteor:chai@1.9.2_3
|
practicalmeteor:chai@1.9.2_3
|
||||||
practicalmeteor:loglevel@1.1.0_3
|
practicalmeteor:loglevel@1.1.0_3
|
||||||
random@1.0.3
|
random@1.0.3
|
||||||
@@ -72,16 +77,21 @@ sanjo:meteor-version@1.0.0
|
|||||||
service-configuration@1.0.4
|
service-configuration@1.0.4
|
||||||
session@1.1.0
|
session@1.1.0
|
||||||
sha@1.0.3
|
sha@1.0.3
|
||||||
|
softwarerero:accounts-t9n@1.0.9
|
||||||
spacebars@1.0.6
|
spacebars@1.0.6
|
||||||
spacebars-compiler@1.0.6
|
spacebars-compiler@1.0.6
|
||||||
|
splendido:accounts-emails-field@1.2.0
|
||||||
|
splendido:accounts-meld@1.3.0
|
||||||
srp@1.0.3
|
srp@1.0.3
|
||||||
templating@1.1.1
|
templating@1.1.1
|
||||||
tracker@1.0.7
|
tracker@1.0.7
|
||||||
ui@1.0.6
|
ui@1.0.6
|
||||||
underscore@1.0.3
|
underscore@1.0.3
|
||||||
url@1.0.4
|
url@1.0.4
|
||||||
|
useraccounts:core@1.9.1
|
||||||
|
useraccounts:polymer@1.9.1
|
||||||
velocity:chokidar@0.12.6_1
|
velocity:chokidar@0.12.6_1
|
||||||
velocity:core@0.6.0
|
velocity:core@0.6.1
|
||||||
velocity:html-reporter@0.5.3
|
velocity:html-reporter@0.5.3
|
||||||
velocity:meteor-internals@1.1.0_7
|
velocity:meteor-internals@1.1.0_7
|
||||||
velocity:shim@0.1.0
|
velocity:shim@0.1.0
|
||||||
|
|||||||
@@ -1,44 +1,23 @@
|
|||||||
Schema = {};
|
|
||||||
|
|
||||||
Schema.User = new SimpleSchema({
|
|
||||||
username: {
|
|
||||||
type: String,
|
|
||||||
regEx: /^[a-z0-9A-Z_]{3,15}$/,
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
emails: {
|
|
||||||
type: [Object],
|
|
||||||
// this must be optional if you also use other login services like facebook,
|
|
||||||
// but if you use only accounts-password, then it can be required
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
"emails.$.address": {
|
|
||||||
type: String,
|
|
||||||
regEx: SimpleSchema.RegEx.Email,
|
|
||||||
},
|
|
||||||
"emails.$.verified": {
|
|
||||||
type: Boolean
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
type: Date
|
|
||||||
},
|
|
||||||
services: {
|
|
||||||
type: Object,
|
|
||||||
optional: true,
|
|
||||||
blackbox: true,
|
|
||||||
},
|
|
||||||
roles: {
|
|
||||||
type: [String],
|
|
||||||
optional: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Meteor.users.attachSchema(Schema.User);
|
|
||||||
|
|
||||||
Meteor.users.allow({
|
Meteor.users.allow({
|
||||||
update: function(userId, doc, fields, modifier) {
|
update: function(userId, doc, fields, modifier) {
|
||||||
return userId === doc._id &&
|
if (
|
||||||
fields.length === 1 &&
|
doc._id === userId &&
|
||||||
fields[0] === "username";
|
_.contains(fields, "username") &&
|
||||||
|
_.contains(fields, "profile") &&
|
||||||
|
fields.length === 2 &&
|
||||||
|
_.keys(modifier).length === 1 &&
|
||||||
|
modifier.$set &&
|
||||||
|
modifier.$set["profile.username"] &&
|
||||||
|
modifier.$set.username &&
|
||||||
|
_.keys(modifier.$set).length === 2
|
||||||
|
){
|
||||||
|
var expectedUsername = modifier.$set["profile.username"];
|
||||||
|
expectedUsername = expectedUsername.toLowerCase().replace(/\s+/gm, "");
|
||||||
|
if (modifier.$set.username !== expectedUsername){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var foundUser = Meteor.call("getUserId", expectedUsername);
|
||||||
|
return !foundUser || foundUser === userId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ Router.configure({
|
|||||||
layoutTemplate: "layout",
|
layoutTemplate: "layout",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Router.plugin("ensureSignedIn", {
|
||||||
|
except: ["home", "atSignIn", "atSignUp", "atForgotPassword", "notFound"]
|
||||||
|
});
|
||||||
|
|
||||||
|
Router.plugin("dataNotFound", {notFoundTemplate: "notFound"});
|
||||||
|
|
||||||
Router.map(function() {
|
Router.map(function() {
|
||||||
this.route("/", {
|
this.route("/", {
|
||||||
name: "home",
|
name: "home",
|
||||||
@@ -56,4 +62,8 @@ Router.map(function() {
|
|||||||
document.title = appName + " Account";
|
document.title = appName + " Account";
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route("/loginButtons", {
|
||||||
|
name: "loginButtons",
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<template name="layout">
|
<template name="layout">
|
||||||
|
|
||||||
<core-drawer-panel>
|
<core-drawer-panel>
|
||||||
<core-header-panel drawer navigation flex mode="seamed" class="white">
|
<core-header-panel drawer navigation flex mode="seamed" class="white">
|
||||||
<div id="accountSummary">
|
<div id="accountSummary">
|
||||||
{{> loginButtons}}
|
|
||||||
{{#if currentUser}}
|
{{#if currentUser}}
|
||||||
<div id="profileLink" style="text-decoration: underline; cursor: pointer;">
|
<div id="profileLink" style="text-decoration: underline; cursor: pointer;">
|
||||||
My account
|
{{profileLink}}
|
||||||
</div>
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<a href="/sign-in" style="color: white;">Sign in</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div id="navPanel">
|
<div id="navPanel">
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ Template.layout.destroyed = function() {
|
|||||||
Template.layout.helpers({
|
Template.layout.helpers({
|
||||||
notSelected: function(){
|
notSelected: function(){
|
||||||
return Session.get("global.ui.detailShow") ? "not-selected" : null;
|
return Session.get("global.ui.detailShow") ? "not-selected" : null;
|
||||||
}
|
},
|
||||||
|
profileLink: function() {
|
||||||
|
var user = Meteor.user();
|
||||||
|
return user.profile && user.profile.username || user.username || "My Account";
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.layout.events({
|
Template.layout.events({
|
||||||
|
|||||||
11
rpg-docs/client/views/notFound/notFound.html
Normal file
11
rpg-docs/client/views/notFound/notFound.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template name="notFound">
|
||||||
|
<div layout vertical center center-justified fit>
|
||||||
|
<h2>The data for the page you requested could not be found.</h2>
|
||||||
|
{{#if currentUser}}
|
||||||
|
<h2>It might not exist, or you might not have permission to view it.</h2>
|
||||||
|
{{else}}
|
||||||
|
<h2>Perhaps you need to sign in first:</h2>
|
||||||
|
{{atForm}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -3,11 +3,7 @@
|
|||||||
<core-toolbar class="blue-grey white-text">
|
<core-toolbar class="blue-grey white-text">
|
||||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||||
<div id="username" class="clickable" flex>
|
<div id="username" class="clickable" flex>
|
||||||
{{#if username}}
|
{{profileName}}
|
||||||
{{username}}
|
|
||||||
{{else}}
|
|
||||||
Tap to set username
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</core-toolbar>
|
</core-toolbar>
|
||||||
<div id="userProfile" class="padded">
|
<div id="userProfile" class="padded">
|
||||||
@@ -20,5 +16,7 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{> atForm}}
|
||||||
|
{{> atNavButton }}
|
||||||
{{/with}}
|
{{/with}}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
Template.profile.helpers({
|
||||||
|
profileName: function() {
|
||||||
|
var user = Meteor.user();
|
||||||
|
return user.profile && user.profile.username ||
|
||||||
|
user.username ||
|
||||||
|
"Tap to set username";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Template.profile.events({
|
Template.profile.events({
|
||||||
"tap #username": function(){
|
"tap #username": function(){
|
||||||
if (this._id === Meteor.userId()){
|
if (this._id === Meteor.userId()){
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<template name="usernameDialog">
|
<template name="usernameDialog">
|
||||||
{{#with currentUser}}
|
<div>
|
||||||
<div>
|
<paper-input id="usernameInput" label="Username" value={{profileName}}></paper-input>
|
||||||
<paper-input id="usernameInput" label="Username" value={{username}}></paper-input>
|
</div>
|
||||||
</div>
|
<div style="color: red;" class="vertMargin">{{errorMessage}}</div>
|
||||||
{{/with}}
|
|
||||||
<paper-button id="cancelButton" affirmative> Cancel </paper-button>
|
<paper-button id="cancelButton" affirmative> Cancel </paper-button>
|
||||||
<paper-button id="changeButton" affirmative> Change Username </paper-button>
|
<paper-button id="changeButton" disabled={{invalid}} affirmative> Change Username </paper-button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,8 +1,49 @@
|
|||||||
|
var getUsername = function() {
|
||||||
|
var user = Meteor.user();
|
||||||
|
return user.profile && user.profile.username || user.username;
|
||||||
|
};
|
||||||
|
|
||||||
|
Template.usernameDialog.onCreated(function() {
|
||||||
|
this.errorMessage = new ReactiveVar("");
|
||||||
|
this.username = new ReactiveVar(getUsername());
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.usernameDialog.helpers({
|
||||||
|
profileName: function() {
|
||||||
|
return getUsername();
|
||||||
|
},
|
||||||
|
invalid: function() {
|
||||||
|
return !!Template.instance().errorMessage.get();
|
||||||
|
},
|
||||||
|
errorMessage: function() {
|
||||||
|
return Template.instance().errorMessage.get();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
Template.usernameDialog.events({
|
Template.usernameDialog.events({
|
||||||
|
"change #usernameInput, input #usernameInput": function(event, instance) {
|
||||||
|
var username = instance.find("#usernameInput").value;
|
||||||
|
username = username.trim().toLowerCase().replace(/\s+/gm, "");
|
||||||
|
if (username.length < 3){
|
||||||
|
instance.errorMessage.set("Username too short");
|
||||||
|
} else {
|
||||||
|
instance.errorMessage.set("Validating...");
|
||||||
|
Meteor.call("getUserId", username, function(err, userId){
|
||||||
|
if (userId && userId !== Meteor.userId())
|
||||||
|
instance.errorMessage.set("This username is taken");
|
||||||
|
else
|
||||||
|
instance.errorMessage.set("");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
"tap #changeButton": function(event, instance){
|
"tap #changeButton": function(event, instance){
|
||||||
|
var username = instance.find("#usernameInput").value;
|
||||||
|
username = username.trim().replace(/\s+/gm, " ");
|
||||||
|
var profileName = username;
|
||||||
|
username = username.toLowerCase().replace(/\s+/gm, "");
|
||||||
Meteor.users.update(
|
Meteor.users.update(
|
||||||
Meteor.userId(),
|
Meteor.userId(),
|
||||||
{$set: {username: instance.find("#usernameInput").value}}
|
{$set: {username: username, "profile.username": profileName}}
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
13
rpg-docs/client/views/user/titledAtForm/titledAtForm.html
Normal file
13
rpg-docs/client/views/user/titledAtForm/titledAtForm.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<template name="titledAtForm">
|
||||||
|
<core-toolbar class="blue-grey white-text">
|
||||||
|
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||||
|
<div flex>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</core-toolbar>
|
||||||
|
<div class="scroll-y padded" fit layout vertical center center-justified>
|
||||||
|
<paper-shadow class="white" style="max-width: 400px;">
|
||||||
|
{{> atForm}}
|
||||||
|
</paper-shadow>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
71
rpg-docs/lib/constants/useraccountsConfig.js
Normal file
71
rpg-docs/lib/constants/useraccountsConfig.js
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
AccountsTemplates.configure({
|
||||||
|
//behaviour
|
||||||
|
confirmPassword: true,
|
||||||
|
enablePasswordChange: true,
|
||||||
|
enforceEmailVerification: true,
|
||||||
|
overrideLoginErrors: false,
|
||||||
|
sendVerificationEmail: true,
|
||||||
|
lowercaseUsername: true,
|
||||||
|
//appearance
|
||||||
|
continuousValidation: true,
|
||||||
|
negativeValidation: true,
|
||||||
|
negativeFeedback: true,
|
||||||
|
showValidating: true,
|
||||||
|
showAddRemoveServices: true,
|
||||||
|
showForgotPasswordLink: true,
|
||||||
|
showResendVerificationEmailLink: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
AccountsTemplates.configureRoute("changePwd", {
|
||||||
|
template: "titledAtForm",
|
||||||
|
});
|
||||||
|
AccountsTemplates.configureRoute("enrollAccount", {
|
||||||
|
template: "titledAtForm",
|
||||||
|
});
|
||||||
|
AccountsTemplates.configureRoute("forgotPwd", {
|
||||||
|
template: "titledAtForm",
|
||||||
|
});
|
||||||
|
AccountsTemplates.configureRoute("resetPwd", {
|
||||||
|
template: "titledAtForm",
|
||||||
|
});
|
||||||
|
AccountsTemplates.configureRoute("signIn", {
|
||||||
|
template: "titledAtForm",
|
||||||
|
});
|
||||||
|
AccountsTemplates.configureRoute("signUp", {
|
||||||
|
template: "titledAtForm",
|
||||||
|
});
|
||||||
|
AccountsTemplates.configureRoute("verifyEmail", {
|
||||||
|
template: "titledAtForm",
|
||||||
|
});
|
||||||
|
AccountsTemplates.configureRoute("resendVerificationEmail", {
|
||||||
|
template: "titledAtForm",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Meteor.isServer){
|
||||||
|
Meteor.methods({
|
||||||
|
"userExists": function(username){
|
||||||
|
return !!Meteor.users.findOne({username: username});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountsTemplates.addField({
|
||||||
|
_id: "username",
|
||||||
|
type: "text",
|
||||||
|
required: true,
|
||||||
|
func: function(value){
|
||||||
|
if (Meteor.isClient) {
|
||||||
|
var self = this;
|
||||||
|
Meteor.call("userExists", value, function(err, userExists){
|
||||||
|
if (!userExists)
|
||||||
|
self.setSuccess();
|
||||||
|
else
|
||||||
|
self.setError("This username is taken");
|
||||||
|
self.setValidating(false);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Server
|
||||||
|
return Meteor.call("userExists", value);
|
||||||
|
},
|
||||||
|
});
|
||||||
27
rpg-docs/server/lib/configuration/accountsMeldConfig.js
Normal file
27
rpg-docs/server/lib/configuration/accountsMeldConfig.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
AccountsMeld.configure({
|
||||||
|
meldDBCallback: function(sourceUserId, destinationUserId){
|
||||||
|
// Here you can modify every collection you need for the document referencing
|
||||||
|
// to sourceUserId to be modified in order to point to destinationUserId
|
||||||
|
Characters.update(
|
||||||
|
{owner: sourceUserId},
|
||||||
|
{$set: {owner: destinationUserId}},
|
||||||
|
{multi: true}
|
||||||
|
);
|
||||||
|
Characters.update(
|
||||||
|
{writers: sourceUserId},
|
||||||
|
{
|
||||||
|
$pull: {writers: sourceUserId},
|
||||||
|
$addToSet: {writers: destinationUserId},
|
||||||
|
},
|
||||||
|
{multi: true}
|
||||||
|
);
|
||||||
|
Characters.update(
|
||||||
|
{readers: sourceUserId},
|
||||||
|
{
|
||||||
|
$pull: {readers: sourceUserId},
|
||||||
|
$addToSet: {readers: destinationUserId},
|
||||||
|
},
|
||||||
|
{multi: true}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user