diff --git a/imports/api/Documents/server/publications.js b/imports/api/Documents/server/publications.js
index 721a522..670f13e 100644
--- a/imports/api/Documents/server/publications.js
+++ b/imports/api/Documents/server/publications.js
@@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor';
import { check } from 'meteor/check';
import Documents from '../Documents';
-Meteor.publish('documents', function documentsView() {
+Meteor.publish('documents', function documents() {
return Documents.find({ owner: this.userId });
});
diff --git a/imports/api/Users/server/methods.js b/imports/api/Users/server/methods.js
new file mode 100644
index 0000000..85d4bdd
--- /dev/null
+++ b/imports/api/Users/server/methods.js
@@ -0,0 +1,33 @@
+import { Meteor } from 'meteor/meteor';
+import { check, Match } from 'meteor/check';
+import editProfile from '../../../modules/server/edit-profile';
+import rateLimit from '../../../modules/rate-limit';
+
+Meteor.methods({
+ 'users.editProfile': function usersEditProfile(profile) {
+ check(profile, {
+ emailAddress: String,
+ password: Match.Optional(Object),
+ profile: {
+ name: {
+ first: String,
+ last: String,
+ },
+ },
+ });
+
+ return editProfile({ userId: this.userId, profile })
+ .then(response => response)
+ .catch((exception) => {
+ throw new Meteor.Error('500', exception);
+ });
+ },
+});
+
+rateLimit({
+ methods: [
+ 'users.editProfile',
+ ],
+ limit: 5,
+ timeRange: 1000,
+});
diff --git a/imports/api/Users/server/publications.js b/imports/api/Users/server/publications.js
new file mode 100644
index 0000000..1b0acec
--- /dev/null
+++ b/imports/api/Users/server/publications.js
@@ -0,0 +1,10 @@
+import { Meteor } from 'meteor/meteor';
+
+Meteor.publish('users.editProfile', function usersProfile() {
+ return Meteor.users.find(this.userId, {
+ fields: {
+ emails: 1,
+ profile: 1,
+ },
+ });
+});
diff --git a/imports/modules/server/edit-profile.js b/imports/modules/server/edit-profile.js
new file mode 100644
index 0000000..b065fc9
--- /dev/null
+++ b/imports/modules/server/edit-profile.js
@@ -0,0 +1,43 @@
+/* eslint-disable consistent-return */
+import { Meteor } from 'meteor/meteor';
+import { Accounts } from 'meteor/accounts-base';
+
+let action;
+
+const updatePassword = (userId, newPassword) => {
+ try {
+ Accounts.setPassword(userId, newPassword, { logout: false });
+ } catch (exception) {
+ action.reject(`[editProfile.updatePassword] ${exception}`);
+ }
+};
+
+const updateUser = (userId, { emailAddress, profile }) => {
+ try {
+ Meteor.users.update(userId, {
+ $set: {
+ 'emails.0.address': emailAddress,
+ profile,
+ },
+ });
+ } catch (exception) {
+ action.reject(`[editProfile.updateUser] ${exception}`);
+ }
+};
+
+const editProfile = ({ userId, profile }, promise) => {
+ try {
+ action = promise;
+
+ updateUser(userId, profile);
+ if (profile.password) updatePassword(userId, profile.password);
+
+ action.resolve();
+ } catch (exception) {
+ action.reject(`[editProfile.handler] ${exception}`);
+ }
+};
+
+export default options =>
+new Promise((resolve, reject) =>
+editProfile(options, { resolve, reject }));
diff --git a/imports/startup/server/api.js b/imports/startup/server/api.js
index 2311511..c39fc72 100644
--- a/imports/startup/server/api.js
+++ b/imports/startup/server/api.js
@@ -1,2 +1,5 @@
import '../../api/Documents/methods';
import '../../api/Documents/server/publications';
+
+import '../../api/Users/server/methods';
+import '../../api/Users/server/publications';
diff --git a/imports/ui/layouts/App/App.js b/imports/ui/layouts/App/App.js
index acc05d3..014d9b4 100644
--- a/imports/ui/layouts/App/App.js
+++ b/imports/ui/layouts/App/App.js
@@ -17,6 +17,7 @@ import Signup from '../../pages/Signup/Signup';
import Login from '../../pages/Login/Login';
import RecoverPassword from '../../pages/RecoverPassword/RecoverPassword';
import ResetPassword from '../../pages/ResetPassword/ResetPassword';
+import Profile from '../../pages/Profile/Profile';
import NotFound from '../../pages/NotFound/NotFound';
const App = props => (
@@ -30,6 +31,7 @@ const App = props => (