{"action":"created","comment":{"url":"https://api.github.com/repos/meteor/guide/pulls/comments/47865764","id":47865764,"diff_hunk":"@@ -0,0 +1,700 @@\n+---\n+title: Users and Accounts\n+---\n+\n+After reading this article, you'll know:\n+\n+1. What features in core Meteor enable user accounts\n+1. How to use accounts-ui for a quick prototype\n+1. How to use the useraccounts family of packages to build your login UI\n+1. How to build a fully-featured password login experience\n+1. How to enable login through OAuth providers like Facebook\n+1. How to add custom data to Meteor's users collection\n+1. How to manage user roles and permissions\n+\n+<h2 id=\"core-meteor\">Features in core Meteor</h2>\n+\n+Before we get into all of the different user-facing accounts functionality you can add with Meteor, let's go over some of the features built into the Meteor DDP protocol and `accounts-base` package. These are the parts of Meteor that you'll definitely need to be aware of if you have any user accounts in your app; most of everything else is optional and added/removed via packages.\n+\n+<h3 id=\"userid-ddp\">userId in DDP</h3>\n+\n+DDP is Meteor's built-in pub/sub and RPC protocol. You can read about how to use it in the [Data Loading](data-loading.html) and [Methods](methods.html) chapters. In addition to the concepts of data loading and remote method calls, DDP has one more feature built in - the idea of a `userId` field on a connection. This is the place where login state is tracked, regardless of which accounts UI package or login service you are using.\n+\n+This built-in feature means that you always get `this.userId` inside Methods and Publications, and can access the user ID on the client. This is a great starting point for building your own custom accounts system, but most developers won't need to worry about the mechanics, since you'll mostly be interacting with the `accounts-base` package instead.\n+\n+<h3 id=\"accounts-base\">`accounts-base`</h3>\n+\n+This package is the core of Meteor's developer-facing user accounts functionality. This includes:\n+\n+1. A users collection with a standard schema, accessed through [`Meteor.users`](http://docs.meteor.com/#/full/meteor_users), and the client-side singletons [`Meteor.userId()`](http://docs.meteor.com/#/full/meteor_userid) and [`Meteor.user()`](http://docs.meteor.com/#/full/meteor_user), which represent the login state on the client\n+2. A variety of helpful other generic methods to keep track of login state, log out, validate users, etc. Visit the [Accounts section of the docs](http://docs.meteor.com/#/full/accounts_api) to find a complete list.\n+3. An API for registering new login handlers, which is used by all of the other accounts packages to integrate with the accounts system. There isn't any official documentation for this API, but you can [read more about it on the MeteorHacks blog](https://meteorhacks.com/extending-meteor-accounts).\n+\n+Usually, you don't need to include `accounts-base` yourself since it's added for you if you use `accounts-password` or similar, but it's good to be aware of what is what.\n+\n+<h2 id=\"accounts-ui\">Fast prototyping with `accounts-ui`</h2>\n+\n+Often, a complicated accounts system is not the first thing you want to build when you're starting out with a new app, so it's useful to have something you can just drop in quickly. This is where `accounts-ui` comes in - it's just one line that you drop into your app to get an accounts system. To add it:\n+\n+```js\n+meteor add accounts-ui\n+```\n+\n+Then just include it anywhere in a Blaze template:\n+\n+```html\n+{{> loginButtons}}\n+```\n+\n+Then, make sure to pick a login provider; they will automatically integrate with `accounts-ui`:\n+\n+```sh\n+# pick one or more of the below\n+meteor add accounts-password\n+meteor add accounts-facebook\n+meteor add accounts-google\n+meteor add accounts-github\n+meteor add accounts-twitter\n+meteor add accounts-meetup\n+meteor add accounts-meteor-developer\n+```\n+\n+[XXX screenshot of accounts ui in action]\n+\n+Now just open your app, follow the configuration steps, and you're good to go - if you've done the [Meteor tutorial](https://www.meteor.com/tutorials/blaze/adding-user-accounts), you've already seen this in action. Of course, in a production application, you probably want a more custom user interface and some logic to have a more tailored UX, but that's why we have the rest of this guide.\n+\n+<h2 id=\"useraccounts\">Customizable UI: useraccounts</h2>\n+\n+Once you've gotten your initial prototype up and running with `accounts-ui`, you'll want to move to something more powerful and configurable so that you can better integrate your login flow with the rest of your app. The [`useraccounts` family of packages](http://useraccounts.meteor.com/) is the most powerful set of accounts management UI controls available for Meteor today. If you need even more customization, you can also roll your own system, but it's worth trying `useraccounts` first.\n+\n+<h3 id=\"useraccounts-flexibility\">Use any router or UI framework</h3>\n+\n+The first thing to understand about `useraccounts` is that the core accounts management logic is independent of the HTML templates and routing packages. This means you can use [`useraccounts:core`](https://atmospherejs.com/useraccounts/core) to build your own set of login templates. Generally, you'll want to pick one login template package and one login routing package. The options for templates include:\n+\n+- [`useraccounts:unstyled`](https://atmospherejs.com/useraccounts/unstyled) which lets you bring your own CSS; this one is used in the Todos example app to make the login UI blend seamlessly with the rest of the app.\n+- Pre-built templates for [Bootstrap, Semantic UI, Materialize, and more](http://useraccounts.meteor.com/). These templates don't come with the actual CSS framework, so you can pick your favorite Bootstrap package, for example.\n+\n+While it's optional and the basic functionality will work without it, it's also a good idea to pick a router integration:\n+\n+- [Flow Router](https://atmospherejs.com/useraccounts/flow-routing), the router [recommended in this guide](routing.html).\n+- [Iron Router](https://atmospherejs.com/useraccounts/iron-routing), another popular router in the Meteor community.\n+\n+In the example app we are using the Flow Router integration with great success. Some of the later sections will cover how to customize the routes and templates to fit your app better.\n+\n+<h3 id=\"useraccounts-drop-in\">Drop-in UI without routing</h3>\n+\n+If you don't want to configure routing for your login flow, you can just drop in a self-managing accounts screen. Wherever you want the accounts UI template to render, just include the `atForm` template, like so:\n+\n+```html\n+{{> atForm}}\n+```\n+\n+Once you configure routing according to the section below, you'll want to remove this inclusion.\n+\n+<h3 id=\"useraccounts-customizing-templates\">Customizing templates</h3>\n+\n+For some apps, the off-the-shelf login templates provided by the various `useraccounts` UI packages will work as-is, but most apps will want to customize some of the presentation. There's a simple way to do that using the template replacement functionality of the `aldeed:template-extension` package.\n+\n+First, figure out which template you want to replace by looking at the source code of the package. For example, in the `useraccounts:unstyled` package, the templates are listed [in this directory on GitHub](https://github.com/meteor-useraccounts/unstyled/tree/master/lib). By squinting at the file names and looking for some of the HTML strings, we can figure out that we might be interested in replacing the `atPwdFormBtn` template. Let's take a look at the original template:\n+\n+```html\n+<template name=\"atPwdFormBtn\">\n+  <button type=\"submit\" class=\"at-btn submit {{submitDisabled}}\" id=\"at-btn\">\n+    {{buttonText}}\n+  </button>\n+</template>\n+```\n+\n+Once you've identified which template you need to replace, define a new template. In this case, we want to modify the class on the button to work with the CSS for the rest of the app. Make sure that it renders the helpers you need just like the original, for example `buttonText`:\n+\n+```html\n+<template name=\"override-atPwdFormBtn\">\n+  <button type=\"submit\" class=\"btn-primary\">\n+    {{buttonText}}\n+  </button>\n+</template>\n+```\n+\n+Then, use the `replaces` function on the template to override the existing template from `useraccounts`:\n+\n+```js\n+Template['override-atPwdFormBtn'].replaces('atPwdFormBtn');\n+```\n+\n+<h3 id=\"useraccounts-customizing-routes\">Customizing routes</h3>\n+\n+In addition to having control over the templates, you'll want to be able to control the routing and URLs for the different views offered by `useraccounts`. Since Flow Router is the officially recommended routing option for Meteor, we'll go over that in particular.\n+\n+First, we need to configure the layout we want to use when rendering the accounts templates:\n+\n+```js\n+AccountsTemplates.configure({\n+  defaultTemplate: 'authPage',\n+  defaultLayout: 'appBody',\n+  defaultContentRegion: 'main',\n+  defaultLayoutRegions: {}\n+});\n+```\n+\n+In this case, we want to use the `appBody` layout template for all of the accounts-related pages. This template has a content region called `main`. Now, let's configure some routes:\n+\n+```js\n+AccountsTemplates.configureRoute('signIn', {\n+  name: 'signin',\n+  path: '/signin'\n+});\n+\n+AccountsTemplates.configureRoute('signUp', {\n+  name: 'join',\n+  path: '/join'\n+});\n+\n+AccountsTemplates.configureRoute('forgotPwd');\n+\n+AccountsTemplates.configureRoute('resetPwd', {\n+  name: 'resetPwd',\n+  path: '/reset-password'\n+});\n+```\n+\n+Now, we can easily render links to our login page like so:\n+\n+```html\n+<div class=\"btns-group\">\n+  <a href=\"{{pathFor 'signin'}}\" class=\"btn-secondary\">Sign In</a>\n+  <a href=\"{{pathFor 'join'}}\" class=\"btn-secondary\">Join</a>\n+</div>\n+```\n+\n+Note that we have specified a password reset route. For this URL to be sent in Meteor's password reset email, we need to configure it:\n+\n+```js\n+Accounts.urls.resetPassword = (token) => {\n+  return `${Meteor.absoluteUrl()}reset-password/${token}`;","path":"content/accounts.md","position":null,"original_position":173,"commit_id":"101de8c69e9e28fce7c740c24aca2778bd56da0d","original_commit_id":"2a28ff2142c0f511dc9865c181991bed55a208ec","user":{"login":"stubailo","id":448783,"avatar_url":"https://avatars.githubusercontent.com/u/448783?v=3","gravatar_id":"","url":"https://api.github.com/users/stubailo","html_url":"https://github.com/stubailo","followers_url":"https://api.github.com/users/stubailo/followers","following_url":"https://api.github.com/users/stubailo/following{/other_user}","gists_url":"https://api.github.com/users/stubailo/gists{/gist_id}","starred_url":"https://api.github.com/users/stubailo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stubailo/subscriptions","organizations_url":"https://api.github.com/users/stubailo/orgs","repos_url":"https://api.github.com/users/stubailo/repos","events_url":"https://api.github.com/users/stubailo/events{/privacy}","received_events_url":"https://api.github.com/users/stubailo/received_events","type":"User","site_admin":false},"body":":+1:","created_at":"2015-12-17T03:28:33Z","updated_at":"2015-12-17T03:28:33Z","html_url":"https://github.com/meteor/guide/pull/154#discussion_r47865764","pull_request_url":"https://api.github.com/repos/meteor/guide/pulls/154","_links":{"self":{"href":"https://api.github.com/repos/meteor/guide/pulls/comments/47865764"},"html":{"href":"https://github.com/meteor/guide/pull/154#discussion_r47865764"},"pull_request":{"href":"https://api.github.com/repos/meteor/guide/pulls/154"}}},"pull_request":{"url":"https://api.github.com/repos/meteor/guide/pulls/154","id":53194011,"html_url":"https://github.com/meteor/guide/pull/154","diff_url":"https://github.com/meteor/guide/pull/154.diff","patch_url":"https://github.com/meteor/guide/pull/154.patch","issue_url":"https://api.github.com/repos/meteor/guide/issues/154","number":154,"state":"open","locked":false,"title":"WIP on accounts content","user":{"login":"stubailo","id":448783,"avatar_url":"https://avatars.githubusercontent.com/u/448783?v=3","gravatar_id":"","url":"https://api.github.com/users/stubailo","html_url":"https://github.com/stubailo","followers_url":"https://api.github.com/users/stubailo/followers","following_url":"https://api.github.com/users/stubailo/following{/other_user}","gists_url":"https://api.github.com/users/stubailo/gists{/gist_id}","starred_url":"https://api.github.com/users/stubailo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stubailo/subscriptions","organizations_url":"https://api.github.com/users/stubailo/orgs","repos_url":"https://api.github.com/users/stubailo/repos","events_url":"https://api.github.com/users/stubailo/events{/privacy}","received_events_url":"https://api.github.com/users/stubailo/received_events","type":"User","site_admin":false},"body":"<a href='#crh-start'></a><a href='#crh-data-%7B%22processed%22%3A%20%5B%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47210059%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47210071%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47210275%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47211456%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47211502%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47211624%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47211640%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47262381%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47262582%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47262853%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47278355%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47304404%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47304412%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47304432%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47304434%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47304912%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47852461%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47854212%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47854239%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47855686%22%2C%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47860997%22%5D%2C%20%22comments%22%3A%20%7B%22Pull%20452b7afe27616c37483d470f9114ed77cb9cadc6%20content/accounts.md%20146%22%3A%20%7B%22html_url%22%3A%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47210275%22%2C%20%22comments%22%3A%20%5B%7B%22body%22%3A%20%22Do%20you%20think%20we%20should%20show%20how%20you%27d%20do%20this%20with%20FR%20or%20is%20it%20too%20boring%3F%22%2C%20%22created_at%22%3A%20%222015-12-10T10%3A32%3A14Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22The%20%5C%22real%5C%22%20version%20of%20this%20will%20be%20covered%20in%20the%20%60useraccounts%60%20section.%20Here%27s%20the%20relevant%20code%20in%20todos%3A%5Cr%5Cn%5Cr%5Cnhttps%3A//github.com/meteor/todos/blob/c6ee2af75b3405e16f08cdd788692e3c5dd7c7c2/packages/todos-main/routes.js%23L36-L39%5Cr%5Cn%5Cr%5CnI%27m%20thinking%20I%20should%20rearrange%20this%20to%20put%20the%20%60useraccounts%60%20version%20_first_%2C%20since%20that%27s%20the%20most%20sane%20way%20to%20do%20things.%22%2C%20%22created_at%22%3A%20%222015-12-10T18%3A16%3A57Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/448783%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/stubailo%22%7D%7D%2C%20%7B%22body%22%3A%20%22Gotcha.%22%2C%20%22created_at%22%3A%20%222015-12-10T23%3A49%3A16Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22%3A%2B1%3A%20%22%2C%20%22created_at%22%3A%20%222015-12-10T23%3A49%3A19Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%5D%2C%20%22title%22%3A%20%22File%3A%20content/accounts.md%3AL1-229%22%7D%2C%20%22Pull%202a28ff2142c0f511dc9865c181991bed55a208ec%20content/accounts.md%20173%22%3A%20%7B%22html_url%22%3A%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47860997%22%2C%20%22comments%22%3A%20%5B%7B%22body%22%3A%20%22Would%20this%20be%20better%20as%20%60Meteor.absoluteUrl%28%60reset-password/%24%7Btoken%7D%60%29%3B%60%3F%22%2C%20%22created_at%22%3A%20%222015-12-17T01%3A53%3A35Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%5D%2C%20%22title%22%3A%20%22File%3A%20content/accounts.md%3AL1-701%22%7D%2C%20%22Pull%20452b7afe27616c37483d470f9114ed77cb9cadc6%20content/accounts.md%20227%22%3A%20%7B%22html_url%22%3A%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47211624%22%2C%20%22comments%22%3A%20%5B%7B%22body%22%3A%20%22I%20think%20it%20needs%20a%20protocol%20typically.%20I%20guess%20you%20should%20say%20%5C%22replace%20example.com%5C%22%20with%20your%20domain%20too%3F%22%2C%20%22created_at%22%3A%20%222015-12-10T10%3A46%3A10Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22Should%20we%20say%20something%20about%20oauth%20in%20development%20too%3F%22%2C%20%22created_at%22%3A%20%222015-12-10T10%3A46%3A26Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22%3A%2B1%3A%22%2C%20%22created_at%22%3A%20%222015-12-17T00%3A00%3A11Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/448783%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/stubailo%22%7D%7D%5D%2C%20%22title%22%3A%20%22File%3A%20content/accounts.md%3AL1-229%22%7D%2C%20%22Pull%20452b7afe27616c37483d470f9114ed77cb9cadc6%20content/accounts.md%2083%22%3A%20%7B%22html_url%22%3A%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47210071%22%2C%20%22comments%22%3A%20%5B%7B%22body%22%3A%20%22I%20would%20have%20thought%20so%22%2C%20%22created_at%22%3A%20%222015-12-10T10%3A30%3A04Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22%3A%2B1%3A%22%2C%20%22created_at%22%3A%20%222015-12-17T00%3A21%3A53Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/448783%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/stubailo%22%7D%7D%5D%2C%20%22title%22%3A%20%22File%3A%20content/accounts.md%3AL1-229%22%7D%2C%20%22Pull%20452b7afe27616c37483d470f9114ed77cb9cadc6%20content/accounts.md%2079%22%3A%20%7B%22html_url%22%3A%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47210059%22%2C%20%22comments%22%3A%20%5B%7B%22body%22%3A%20%22Do%20you%20need%20to%20do%20this%3F%20I%20guess%20this%20stops%20creating%20a%20user%20in%20some%20other%20way%20on%20the%20server%3F%22%2C%20%22created_at%22%3A%20%222015-12-10T10%3A29%3A58Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22No%20I%20think%20you%20can%20actually%20call%20%60Accounts.createUser%60%20from%20the%20client%20with%20either%20username%20or%20email%20arbitrarily.%20So%20you%20might%20be%20expecting%20only%20emails%2C%20but%20a%20malicious%20user%20could%20create%20an%20account%20with%20no%20email%20address%20from%20the%20client.%20Who%20knows%20what%20issues%20that%20could%20lead%20to.%22%2C%20%22created_at%22%3A%20%222015-12-10T18%3A15%3A25Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/448783%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/stubailo%22%7D%7D%2C%20%7B%22body%22%3A%20%22%3A%2B1%3A%22%2C%20%22created_at%22%3A%20%222015-12-10T20%3A11%3A40Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/448783%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/stubailo%22%7D%7D%2C%20%7B%22body%22%3A%20%22Oh%20so%20the%20setting%20simply%20controls%20the%20UI%3F%20Didn%27t%20know%20that..%22%2C%20%22created_at%22%3A%20%222015-12-10T23%3A48%3A43Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22%3A%2B1%3A%20%22%2C%20%22created_at%22%3A%20%222015-12-10T23%3A48%3A47Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%5D%2C%20%22title%22%3A%20%22File%3A%20content/accounts.md%3AL1-229%22%7D%2C%20%22Pull%20452b7afe27616c37483d470f9114ed77cb9cadc6%20content/accounts.md%20187%22%3A%20%7B%22html_url%22%3A%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47211502%22%2C%20%22comments%22%3A%20%5B%7B%22body%22%3A%20%22Show%20how%20to%20set%20the%20actual%20HTML%20property%20of%20the%20email%3F%22%2C%20%22created_at%22%3A%20%222015-12-10T10%3A45%3A01Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22%3A%2B1%3A%20%22%2C%20%22created_at%22%3A%20%222015-12-17T00%3A22%3A16Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/448783%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/stubailo%22%7D%7D%5D%2C%20%22title%22%3A%20%22File%3A%20content/accounts.md%3AL1-229%22%7D%2C%20%22Pull%20452b7afe27616c37483d470f9114ed77cb9cadc6%20content/accounts.md%20157%22%3A%20%7B%22html_url%22%3A%20%22https%3A//github.com/meteor/guide/pull/154%23discussion_r47211456%22%2C%20%22comments%22%3A%20%5B%7B%22body%22%3A%20%22I%27m%20not%20sure%20what%20this%20%60done%60%20thing%20is%20about%20but%20I%27ve%20never%20heard%20of%20it%20and%20it%27s%20not%20in%20in%20the%20docs%3F%22%2C%20%22created_at%22%3A%20%222015-12-10T10%3A44%3A29Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22It%27s%20one%20of%20the%20arguments%20to%20the%20callback%3A%20http%3A//docs.meteor.com/%23/full/Accounts-onResetPasswordLink%5Cr%5Cn%5Cr%5CnIt%27s%20like%20a%20really%20janky%20API%20%28that%20I%20wrote%2C%20sorry%20%3A%5D%20%29.%20Basically%20it%20looks%20like%20this%3A%5Cr%5Cn%5Cr%5Cn%60%60%60js%5Cr%5CnAccounts.onResetPasswordLink%28%28token%2C%20done%29%20%3D%3E%20%7B%5Cr%5Cn%20%20//%20show%20reset%20password%20UI%5Cr%5Cn%20%20Accounts.resetPassword%28token%2C%20%28err%29%20%3D%3E%20%7B%5Cr%5Cn%20%20%20%20if%20%28%21%20err%29%20%7B%5Cr%5Cn%20%20%20%20%20%20done%28%29%3B%5Cr%5Cn%20%20%20%20%7D%5Cr%5Cn%20%20%7D%29%3B%5Cr%5Cn%7D%29%3B%5Cr%5Cn%60%60%60%5Cr%5Cn%5Cr%5CnKinda%20crappy.%22%2C%20%22created_at%22%3A%20%222015-12-10T18%3A19%3A10Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/448783%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/stubailo%22%7D%7D%2C%20%7B%22body%22%3A%20%22Oh%2C%20I%20see.%20How%20interesting.%20I%20guess%20maybe%20you%20could%20just%20make%20it%20clearer%20what%20you%20mean%20then%20%28%5C%22you%20got%20in%20the%20link%20callback%5C%22%20is%20maybe%20a%20bit%20unclear%29%22%2C%20%22created_at%22%3A%20%222015-12-10T23%3A55%3A01Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/132554%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/tmeasday%22%7D%7D%2C%20%7B%22body%22%3A%20%22%3A%2B1%3A%22%2C%20%22created_at%22%3A%20%222015-12-17T00%3A38%3A24Z%22%2C%20%22user%22%3A%20%7B%22avatar_url%22%3A%20%22https%3A//avatars.githubusercontent.com/u/448783%3Fv%3D3%22%2C%20%22html_url%22%3A%20%22https%3A//github.com/stubailo%22%7D%7D%5D%2C%20%22title%22%3A%20%22File%3A%20content/accounts.md%3AL1-229%22%7D%7D%7D'></a>\r\n<a href='https://www.codereviewhub.com/'><img src='http://www.codereviewhub.com/site/github-bar.png' height=40></a>\r\n- [x] <a href='#crh-comment-Pull 2a28ff2142c0f511dc9865c181991bed55a208ec content/accounts.md 173'></a> <img src='http://www.codereviewhub.com/site/github-remaining.png' height=16 width=60>&nbsp;<b><a href='https://github.com/meteor/guide/pull/154#discussion_r47860997'>File: content/accounts.md:L1-701</a></b>\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> Would this be better as `Meteor.absoluteUrl(`reset-password/${token}`);`?\r\n- [x] <a href='#crh-comment-Pull 452b7afe27616c37483d470f9114ed77cb9cadc6 content/accounts.md 79'></a> <img src='http://www.codereviewhub.com/site/github-completed.png' height=16 width=60>&nbsp;<b><a href='https://github.com/meteor/guide/pull/154#discussion_r47210059'>File: content/accounts.md:L1-229</a></b>\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> Do you need to do this? I guess this stops creating a user in some other way on the server?\r\n- <a href='https://github.com/stubailo'><img border=0 src='https://avatars.githubusercontent.com/u/448783?v=3' height=16 width=16'></a> No I think you can actually call `Accounts.createUser` from the client with either username or email arbitrarily. So you might be expecting only emails, but a malicious user could create an account with no email address from the client. Who knows what issues that could lead to.\r\n- <a href='https://github.com/stubailo'><img border=0 src='https://avatars.githubusercontent.com/u/448783?v=3' height=16 width=16'></a> :+1:\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> Oh so the setting simply controls the UI? Didn't know that..\r\n- [x] <a href='#crh-comment-Pull 452b7afe27616c37483d470f9114ed77cb9cadc6 content/accounts.md 83'></a> <img src='http://www.codereviewhub.com/site/github-completed.png' height=16 width=60>&nbsp;<b><a href='https://github.com/meteor/guide/pull/154#discussion_r47210071'>File: content/accounts.md:L1-229</a></b>\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> I would have thought so\r\n- [x] <a href='#crh-comment-Pull 452b7afe27616c37483d470f9114ed77cb9cadc6 content/accounts.md 146'></a> <img src='http://www.codereviewhub.com/site/github-completed.png' height=16 width=60>&nbsp;<b><a href='https://github.com/meteor/guide/pull/154#discussion_r47210275'>File: content/accounts.md:L1-229</a></b>\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> Do you think we should show how you'd do this with FR or is it too boring?\r\n- <a href='https://github.com/stubailo'><img border=0 src='https://avatars.githubusercontent.com/u/448783?v=3' height=16 width=16'></a> The \"real\" version of this will be covered in the `useraccounts` section. Here's the relevant code in todos:\r\nhttps://github.com/meteor/todos/blob/c6ee2af75b3405e16f08cdd788692e3c5dd7c7c2/packages/todos-main/routes.js#L36-L39\r\nI'm thinking I should rearrange this to put the `useraccounts` version _first_, since that's the most sane way to do things.\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> Gotcha.\r\n- [x] <a href='#crh-comment-Pull 452b7afe27616c37483d470f9114ed77cb9cadc6 content/accounts.md 157'></a> <img src='http://www.codereviewhub.com/site/github-completed.png' height=16 width=60>&nbsp;<b><a href='https://github.com/meteor/guide/pull/154#discussion_r47211456'>File: content/accounts.md:L1-229</a></b>\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> I'm not sure what this `done` thing is about but I've never heard of it and it's not in in the docs?\r\n- <a href='https://github.com/stubailo'><img border=0 src='https://avatars.githubusercontent.com/u/448783?v=3' height=16 width=16'></a> It's one of the arguments to the callback: http://docs.meteor.com/#/full/Accounts-onResetPasswordLink\r\nIt's like a really janky API (that I wrote, sorry :] ). Basically it looks like this:\r\n```js\r\nAccounts.onResetPasswordLink((token, done) => {\r\n// show reset password UI\r\nAccounts.resetPassword(token, (err) => {\r\nif (! err) {\r\ndone();\r\n}\r\n});\r\n});\r\n```\r\nKinda crappy.\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> Oh, I see. How interesting. I guess maybe you could just make it clearer what you mean then (\"you got in the link callback\" is maybe a bit unclear)\r\n- [x] <a href='#crh-comment-Pull 452b7afe27616c37483d470f9114ed77cb9cadc6 content/accounts.md 187'></a> <img src='http://www.codereviewhub.com/site/github-completed.png' height=16 width=60>&nbsp;<b><a href='https://github.com/meteor/guide/pull/154#discussion_r47211502'>File: content/accounts.md:L1-229</a></b>\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> Show how to set the actual HTML property of the email?\r\n- [x] <a href='#crh-comment-Pull 452b7afe27616c37483d470f9114ed77cb9cadc6 content/accounts.md 227'></a> <img src='http://www.codereviewhub.com/site/github-completed.png' height=16 width=60>&nbsp;<b><a href='https://github.com/meteor/guide/pull/154#discussion_r47211624'>File: content/accounts.md:L1-229</a></b>\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> I think it needs a protocol typically. I guess you should say \"replace example.com\" with your domain too?\r\n- <a href='https://github.com/tmeasday'><img border=0 src='https://avatars.githubusercontent.com/u/132554?v=3' height=16 width=16'></a> Should we say something about oauth in development too?\r\n\r\n\r\n<a href='https://www.codereviewhub.com/meteor/guide/pull/154?mark_as_completed=1'><img src='http://www.codereviewhub.com/site/github-mark-as-completed.png' height=26></a>&nbsp;<a href='https://www.codereviewhub.com/meteor/guide/pull/154?approve=1'><img src='http://www.codereviewhub.com/site/github-approve.png' height=26></a>&nbsp;<a href='https://github.com/meteor/guide/pull/154'><img src='http://www.codereviewhub.com/site/github-refresh.png' height=26></a>\r\n<a href='#crh-end'></a>","created_at":"2015-12-09T23:23:57Z","updated_at":"2015-12-17T03:28:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5c6b679f55cb2aa9b92344131b9935f033169a3f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/meteor/guide/pulls/154/commits","review_comments_url":"https://api.github.com/repos/meteor/guide/pulls/154/comments","review_comment_url":"https://api.github.com/repos/meteor/guide/pulls/comments{/number}","comments_url":"https://api.github.com/repos/meteor/guide/issues/154/comments","statuses_url":"https://api.github.com/repos/meteor/guide/statuses/101de8c69e9e28fce7c740c24aca2778bd56da0d","head":{"label":"meteor:accounts-content","ref":"accounts-content","sha":"101de8c69e9e28fce7c740c24aca2778bd56da0d","user":{"login":"meteor","id":789528,"avatar_url":"https://avatars.githubusercontent.com/u/789528?v=3","gravatar_id":"","url":"https://api.github.com/users/meteor","html_url":"https://github.com/meteor","followers_url":"https://api.github.com/users/meteor/followers","following_url":"https://api.github.com/users/meteor/following{/other_user}","gists_url":"https://api.github.com/users/meteor/gists{/gist_id}","starred_url":"https://api.github.com/users/meteor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meteor/subscriptions","organizations_url":"https://api.github.com/users/meteor/orgs","repos_url":"https://api.github.com/users/meteor/repos","events_url":"https://api.github.com/users/meteor/events{/privacy}","received_events_url":"https://api.github.com/users/meteor/received_events","type":"Organization","site_admin":false},"repo":{"id":43717321,"name":"guide","full_name":"meteor/guide","owner":{"login":"meteor","id":789528,"avatar_url":"https://avatars.githubusercontent.com/u/789528?v=3","gravatar_id":"","url":"https://api.github.com/users/meteor","html_url":"https://github.com/meteor","followers_url":"https://api.github.com/users/meteor/followers","following_url":"https://api.github.com/users/meteor/following{/other_user}","gists_url":"https://api.github.com/users/meteor/gists{/gist_id}","starred_url":"https://api.github.com/users/meteor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meteor/subscriptions","organizations_url":"https://api.github.com/users/meteor/orgs","repos_url":"https://api.github.com/users/meteor/repos","events_url":"https://api.github.com/users/meteor/events{/privacy}","received_events_url":"https://api.github.com/users/meteor/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/meteor/guide","description":"How do I use Meteor? (Work in progress)","fork":false,"url":"https://api.github.com/repos/meteor/guide","forks_url":"https://api.github.com/repos/meteor/guide/forks","keys_url":"https://api.github.com/repos/meteor/guide/keys{/key_id}","collaborators_url":"https://api.github.com/repos/meteor/guide/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/meteor/guide/teams","hooks_url":"https://api.github.com/repos/meteor/guide/hooks","issue_events_url":"https://api.github.com/repos/meteor/guide/issues/events{/number}","events_url":"https://api.github.com/repos/meteor/guide/events","assignees_url":"https://api.github.com/repos/meteor/guide/assignees{/user}","branches_url":"https://api.github.com/repos/meteor/guide/branches{/branch}","tags_url":"https://api.github.com/repos/meteor/guide/tags","blobs_url":"https://api.github.com/repos/meteor/guide/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/meteor/guide/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/meteor/guide/git/refs{/sha}","trees_url":"https://api.github.com/repos/meteor/guide/git/trees{/sha}","statuses_url":"https://api.github.com/repos/meteor/guide/statuses/{sha}","languages_url":"https://api.github.com/repos/meteor/guide/languages","stargazers_url":"https://api.github.com/repos/meteor/guide/stargazers","contributors_url":"https://api.github.com/repos/meteor/guide/contributors","subscribers_url":"https://api.github.com/repos/meteor/guide/subscribers","subscription_url":"https://api.github.com/repos/meteor/guide/subscription","commits_url":"https://api.github.com/repos/meteor/guide/commits{/sha}","git_commits_url":"https://api.github.com/repos/meteor/guide/git/commits{/sha}","comments_url":"https://api.github.com/repos/meteor/guide/comments{/number}","issue_comment_url":"https://api.github.com/repos/meteor/guide/issues/comments{/number}","contents_url":"https://api.github.com/repos/meteor/guide/contents/{+path}","compare_url":"https://api.github.com/repos/meteor/guide/compare/{base}...{head}","merges_url":"https://api.github.com/repos/meteor/guide/merges","archive_url":"https://api.github.com/repos/meteor/guide/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/meteor/guide/downloads","issues_url":"https://api.github.com/repos/meteor/guide/issues{/number}","pulls_url":"https://api.github.com/repos/meteor/guide/pulls{/number}","milestones_url":"https://api.github.com/repos/meteor/guide/milestones{/number}","notifications_url":"https://api.github.com/repos/meteor/guide/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/meteor/guide/labels{/name}","releases_url":"https://api.github.com/repos/meteor/guide/releases{/id}","created_at":"2015-10-05T22:26:02Z","updated_at":"2015-12-16T16:23:03Z","pushed_at":"2015-12-17T03:28:20Z","git_url":"git://github.com/meteor/guide.git","ssh_url":"git@github.com:meteor/guide.git","clone_url":"https://github.com/meteor/guide.git","svn_url":"https://github.com/meteor/guide","homepage":"http://guide.meteor.com/","size":4326,"stargazers_count":422,"watchers_count":422,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":35,"mirror_url":null,"open_issues_count":71,"forks":35,"open_issues":71,"watchers":422,"default_branch":"master"}},"base":{"label":"meteor:master","ref":"master","sha":"1de3c5f4220fd61bf8778994de02fc7cecd7a3f9","user":{"login":"meteor","id":789528,"avatar_url":"https://avatars.githubusercontent.com/u/789528?v=3","gravatar_id":"","url":"https://api.github.com/users/meteor","html_url":"https://github.com/meteor","followers_url":"https://api.github.com/users/meteor/followers","following_url":"https://api.github.com/users/meteor/following{/other_user}","gists_url":"https://api.github.com/users/meteor/gists{/gist_id}","starred_url":"https://api.github.com/users/meteor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meteor/subscriptions","organizations_url":"https://api.github.com/users/meteor/orgs","repos_url":"https://api.github.com/users/meteor/repos","events_url":"https://api.github.com/users/meteor/events{/privacy}","received_events_url":"https://api.github.com/users/meteor/received_events","type":"Organization","site_admin":false},"repo":{"id":43717321,"name":"guide","full_name":"meteor/guide","owner":{"login":"meteor","id":789528,"avatar_url":"https://avatars.githubusercontent.com/u/789528?v=3","gravatar_id":"","url":"https://api.github.com/users/meteor","html_url":"https://github.com/meteor","followers_url":"https://api.github.com/users/meteor/followers","following_url":"https://api.github.com/users/meteor/following{/other_user}","gists_url":"https://api.github.com/users/meteor/gists{/gist_id}","starred_url":"https://api.github.com/users/meteor/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/meteor/subscriptions","organizations_url":"https://api.github.com/users/meteor/orgs","repos_url":"https://api.github.com/users/meteor/repos","events_url":"https://api.github.com/users/meteor/events{/privacy}","received_events_url":"https://api.github.com/users/meteor/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/meteor/guide","description":"How do I use Meteor? (Work in progress)","fork":false,"url":"https://api.github.com/repos/meteor/guide","forks_url":"https://api.github.com/repos/meteor/guide/forks","keys_url":"https://api.github.com/repos/meteor/guide/keys{/key_id}","collaborators_url":"https://api.github.com/repos/meteor/guide/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/meteor/guide/teams","hooks_url":"https://api.github.com/repos/meteor/guide/hooks","issue_events_url":"https://api.github.com/repos/meteor/guide/issues/events{/number}","events_url":"https://api.github.com/repos/meteor/guide/events","assignees_url":"https://api.github.com/repos/meteor/guide/assignees{/user}","branches_url":"https://api.github.com/repos/meteor/guide/branches{/branch}","tags_url":"https://api.github.com/repos/meteor/guide/tags","blobs_url":"https://api.github.com/repos/meteor/guide/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/meteor/guide/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/meteor/guide/git/refs{/sha}","trees_url":"https://api.github.com/repos/meteor/guide/git/trees{/sha}","statuses_url":"https://api.github.com/repos/meteor/guide/statuses/{sha}","languages_url":"https://api.github.com/repos/meteor/guide/languages","stargazers_url":"https://api.github.com/repos/meteor/guide/stargazers","contributors_url":"https://api.github.com/repos/meteor/guide/contributors","subscribers_url":"https://api.github.com/repos/meteor/guide/subscribers","subscription_url":"https://api.github.com/repos/meteor/guide/subscription","commits_url":"https://api.github.com/repos/meteor/guide/commits{/sha}","git_commits_url":"https://api.github.com/repos/meteor/guide/git/commits{/sha}","comments_url":"https://api.github.com/repos/meteor/guide/comments{/number}","issue_comment_url":"https://api.github.com/repos/meteor/guide/issues/comments{/number}","contents_url":"https://api.github.com/repos/meteor/guide/contents/{+path}","compare_url":"https://api.github.com/repos/meteor/guide/compare/{base}...{head}","merges_url":"https://api.github.com/repos/meteor/guide/merges","archive_url":"https://api.github.com/repos/meteor/guide/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/meteor/guide/downloads","issues_url":"https://api.github.com/repos/meteor/guide/issues{/number}","pulls_url":"https://api.github.com/repos/meteor/guide/pulls{/number}","milestones_url":"https://api.github.com/repos/meteor/guide/milestones{/number}","notifications_url":"https://api.github.com/repos/meteor/guide/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/meteor/guide/labels{/name}","releases_url":"https://api.github.com/repos/meteor/guide/releases{/id}","created_at":"2015-10-05T22:26:02Z","updated_at":"2015-12-16T16:23:03Z","pushed_at":"2015-12-17T03:28:20Z","git_url":"git://github.com/meteor/guide.git","ssh_url":"git@github.com:meteor/guide.git","clone_url":"https://github.com/meteor/guide.git","svn_url":"https://github.com/meteor/guide","homepage":"http://guide.meteor.com/","size":4326,"stargazers_count":422,"watchers_count":422,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":35,"mirror_url":null,"open_issues_count":71,"forks":35,"open_issues":71,"watchers":422,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/meteor/guide/pulls/154"},"html":{"href":"https://github.com/meteor/guide/pull/154"},"issue":{"href":"https://api.github.com/repos/meteor/guide/issues/154"},"comments":{"href":"https://api.github.com/repos/meteor/guide/issues/154/comments"},"review_comments":{"href":"https://api.github.com/repos/meteor/guide/pulls/154/comments"},"review_comment":{"href":"https://api.github.com/repos/meteor/guide/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/meteor/guide/pulls/154/commits"},"statuses":{"href":"https://api.github.com/repos/meteor/guide/statuses/101de8c69e9e28fce7c740c24aca2778bd56da0d"}}}}