Finished implementing useraccounts
This commit is contained in:
@@ -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({
|
||||
update: function(userId, doc, fields, modifier) {
|
||||
return userId === doc._id &&
|
||||
fields.length === 1 &&
|
||||
fields[0] === "username";
|
||||
if (
|
||||
doc._id === userId &&
|
||||
_.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;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -62,4 +62,8 @@ Router.map(function() {
|
||||
document.title = appName + " Account";
|
||||
},
|
||||
});
|
||||
|
||||
this.route("/loginButtons", {
|
||||
name: "loginButtons",
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template name="layout">
|
||||
|
||||
<core-drawer-panel>
|
||||
<core-header-panel drawer navigation flex mode="seamed" class="white">
|
||||
<div id="accountSummary">
|
||||
{{> loginButtons}}
|
||||
{{#if currentUser}}
|
||||
<div id="profileLink" style="text-decoration: underline; cursor: pointer;">
|
||||
My account
|
||||
{{profileLink}}
|
||||
</div>
|
||||
{{else}}
|
||||
<a href="/sign-in" style="color: white;">Sign in</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div id="navPanel">
|
||||
|
||||
@@ -9,7 +9,11 @@ Template.layout.destroyed = function() {
|
||||
Template.layout.helpers({
|
||||
notSelected: function(){
|
||||
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({
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
<core-toolbar class="blue-grey white-text">
|
||||
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
|
||||
<div id="username" class="clickable" flex>
|
||||
{{#if username}}
|
||||
{{username}}
|
||||
{{else}}
|
||||
Tap to set username
|
||||
{{/if}}
|
||||
{{profileName}}
|
||||
</div>
|
||||
</core-toolbar>
|
||||
<div id="userProfile" class="padded">
|
||||
@@ -20,5 +16,7 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{> atForm}}
|
||||
{{> atNavButton }}
|
||||
{{/with}}
|
||||
</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({
|
||||
"tap #username": function(){
|
||||
if (this._id === Meteor.userId()){
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<template name="usernameDialog">
|
||||
{{#with currentUser}}
|
||||
<div>
|
||||
<paper-input id="usernameInput" label="Username" value={{username}}></paper-input>
|
||||
</div>
|
||||
{{/with}}
|
||||
<div>
|
||||
<paper-input id="usernameInput" label="Username" value={{profileName}}></paper-input>
|
||||
</div>
|
||||
<div style="color: red;" class="vertMargin">{{errorMessage}}</div>
|
||||
<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>
|
||||
|
||||
@@ -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({
|
||||
"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){
|
||||
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.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>
|
||||
@@ -1,21 +1,45 @@
|
||||
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("enrollAccount");
|
||||
AccountsTemplates.configureRoute("forgotPwd");
|
||||
AccountsTemplates.configureRoute("resetPwd");
|
||||
AccountsTemplates.configureRoute("signIn");
|
||||
AccountsTemplates.configureRoute("signUp");
|
||||
AccountsTemplates.configureRoute("verifyEmail");
|
||||
AccountsTemplates.configureRoute("resendVerificationEmail");
|
||||
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({
|
||||
|
||||
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