From 0a0188530098a77d71264d51570bde35890f9fc2 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Mon, 11 May 2015 12:15:00 +0200 Subject: [PATCH] Finished implementing useraccounts --- rpg-docs/Model/Users/Users.js | 59 ++++++------------- rpg-docs/Routes/Routes.js | 4 ++ rpg-docs/client/views/layout/layout.html | 6 +- rpg-docs/client/views/layout/layout.js | 6 +- .../client/views/user/profile/profile.html | 8 +-- rpg-docs/client/views/user/profile/profile.js | 9 +++ .../views/user/profile/usernameDialog.html | 11 ++-- .../views/user/profile/usernameDialog.js | 45 +++++++++++++- .../views/user/titledAtForm/titledAtForm.html | 13 ++++ rpg-docs/lib/constants/useraccountsConfig.js | 38 +++++++++--- .../lib/configuration/accountsMeldConfig.js | 27 +++++++++ 11 files changed, 162 insertions(+), 64 deletions(-) create mode 100644 rpg-docs/client/views/user/titledAtForm/titledAtForm.html create mode 100644 rpg-docs/server/lib/configuration/accountsMeldConfig.js diff --git a/rpg-docs/Model/Users/Users.js b/rpg-docs/Model/Users/Users.js index 73ae3909..f9011409 100644 --- a/rpg-docs/Model/Users/Users.js +++ b/rpg-docs/Model/Users/Users.js @@ -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; + } } }); diff --git a/rpg-docs/Routes/Routes.js b/rpg-docs/Routes/Routes.js index ffed9def..e2552e6c 100644 --- a/rpg-docs/Routes/Routes.js +++ b/rpg-docs/Routes/Routes.js @@ -62,4 +62,8 @@ Router.map(function() { document.title = appName + " Account"; }, }); + + this.route("/loginButtons", { + name: "loginButtons", + }) }); diff --git a/rpg-docs/client/views/layout/layout.html b/rpg-docs/client/views/layout/layout.html index c08ba454..7e2028d4 100644 --- a/rpg-docs/client/views/layout/layout.html +++ b/rpg-docs/client/views/layout/layout.html @@ -1,13 +1,13 @@ diff --git a/rpg-docs/client/views/user/profile/profile.js b/rpg-docs/client/views/user/profile/profile.js index d0aa2ef7..e274fd00 100644 --- a/rpg-docs/client/views/user/profile/profile.js +++ b/rpg-docs/client/views/user/profile/profile.js @@ -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()){ diff --git a/rpg-docs/client/views/user/profile/usernameDialog.html b/rpg-docs/client/views/user/profile/usernameDialog.html index e8f7db89..3b83dbd4 100644 --- a/rpg-docs/client/views/user/profile/usernameDialog.html +++ b/rpg-docs/client/views/user/profile/usernameDialog.html @@ -1,9 +1,8 @@ diff --git a/rpg-docs/client/views/user/profile/usernameDialog.js b/rpg-docs/client/views/user/profile/usernameDialog.js index eb04c8ec..964e8380 100644 --- a/rpg-docs/client/views/user/profile/usernameDialog.js +++ b/rpg-docs/client/views/user/profile/usernameDialog.js @@ -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}} ); - } + }, }); diff --git a/rpg-docs/client/views/user/titledAtForm/titledAtForm.html b/rpg-docs/client/views/user/titledAtForm/titledAtForm.html new file mode 100644 index 00000000..d436ff09 --- /dev/null +++ b/rpg-docs/client/views/user/titledAtForm/titledAtForm.html @@ -0,0 +1,13 @@ + diff --git a/rpg-docs/lib/constants/useraccountsConfig.js b/rpg-docs/lib/constants/useraccountsConfig.js index 31e2f38d..9824b2d4 100644 --- a/rpg-docs/lib/constants/useraccountsConfig.js +++ b/rpg-docs/lib/constants/useraccountsConfig.js @@ -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({ diff --git a/rpg-docs/server/lib/configuration/accountsMeldConfig.js b/rpg-docs/server/lib/configuration/accountsMeldConfig.js new file mode 100644 index 00000000..71bbb17b --- /dev/null +++ b/rpg-docs/server/lib/configuration/accountsMeldConfig.js @@ -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} + ); + }, +});