7:添加用户账户

7.1:密码认证

Meteor 自带了基本的认证和账户管理系统,因此您只需要添加 accounts-password 即可启用用户名和密码认证。

meteor add accounts-password

还支持许多其他认证方法。您可以阅读有关账户系统的更多信息 此处

我们还建议您安装 bcrypt 节点模块,否则您将看到一条警告,提示您正在使用其纯 JavaScript 实现。

meteor npm install --save bcrypt

您应该始终使用 meteor npm 而不是仅使用 npm,这样您才能始终使用 Meteor 指定的 npm 版本,这有助于避免因不同版本的 npm 安装不同模块而导致的问题。

7.2:创建用户账户

现在您可以为我们的应用创建一个默认用户,我们将使用 meteorite 作为用户名,如果我们在数据库中找不到它,我们只需在服务器启动时创建一个新用户。

server/main.js

import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { TasksCollection } from '/imports/api/TasksCollection';

..

const SEED_USERNAME = 'meteorite';
const SEED_PASSWORD = 'password';

Meteor.startup(() => {
  if (!Accounts.findUserByUsername(SEED_USERNAME)) {
    Accounts.createUser({
      username: SEED_USERNAME,
      password: SEED_PASSWORD,
    });
  }
  ..
});

您现在在应用 UI 中不应该看到任何不同。

7.3:登录表单

您需要为用户提供输入凭据和进行身份验证的方法,为此我们需要一个表单。

创建一个名为 LoginForm.svelte 的新文件并在其中添加一个表单。您应该使用 Meteor.loginWithPassword(username, password); 来使用提供的输入对用户进行身份验证。

imports/ui/LoginForm.svelte

<script>
    import { Meteor } from 'meteor/meteor';

    let username = "";
    let password = "";

    const handleSubmit = () => {
        Meteor.loginWithPassword(username, password);
    }
</script>

<form class="login-form" on:submit|preventDefault={handleSubmit}>
    <div>
        <label htmlFor="username">Username</label>

        <input
                type="text"
                placeholder="Username"
                name="username"
                required
                bind:value={username}
        />
    </div>

    <div>
        <label htmlFor="password">Password</label>

        <input
                type="password"
                placeholder="Password"
                name="password"
                required
                bind:value={password}
        />
    </div>
    <div>
        <button type="submit">Log In</button>
    </div>
</form>

好的,现在您有了表单,让我们使用它。

7.4:要求进行身份验证

我们的应用应该只允许经过身份验证的用户访问其任务管理功能。

当我们没有经过身份验证的用户时,我们可以通过渲染 LoginForm 组件来实现这一点,否则我们将返回表单、筛选器和列表组件。

您可以从 Meteor.user() 获取经过身份验证的用户或 null。然后,您可以验证您是否有一个已登录的用户,如果有,则渲染应用,否则,您渲染 LoginForm

imports/ui/App.svelte

<script>
    import { TasksCollection } from '../api/TasksCollection';
    import { Meteor } from 'meteor/meteor';
    ..
    let user = null;

    $m: {
        user = Meteor.user();
        ..
    }
</script>

<div class="app">
    ..
    <div class="main">
        {#if user}
            <TaskForm user={user}/>

            <div class="filter">
                <button on:click={() => setHideCompleted(!hideCompleted)}>
                {hideCompleted ? 'Show All' : 'Hide Completed'}
                </button>
            </div>
            <ul class="tasks">
                {#each tasks as task (task._id)}
                    <Task task={task} />
                {/each}
            </ul>
        {:else}
            <LoginForm />
        {/if}
    </div>
</div>

7.5:登录表单样式

好的,现在让我们为登录表单设置样式。

client/main.css

.login-form {
  display: flex;
  flex-direction: column;
  height: 100%;

  justify-content: center;
  align-items: center;
}

.login-form > div {
  margin: 8px;
}

.login-form > div > label {
  font-weight: bold;
}

.login-form > div  > input {
  flex-grow: 1;
  box-sizing: border-box;
  padding: 10px 6px;
  background: transparent;
  border: 1px solid #aaa;
  width: 100%;
  font-size: 1em;
  margin-right: 16px;
  margin-top: 4px;
}

.login-form > div > input:focus {
  outline: 0;
}

.login-form > div > button {
  background-color: #62807e;
}

现在您的登录表单应该居中显示并美观。

7.6:服务器启动

从现在开始,每个任务都应该有一个所有者。因此,请转到您的数据库,如您之前所学,并从中删除所有任务。

db.tasks.remove({});

更改您的 server/main.js 以使用您的 meteorite 用户作为所有者添加种子任务。

确保在此更改后重新启动服务器,以便 Meteor.startup 块可以再次运行。当您在服务器端代码中进行更改时,这可能会自动发生。

server/main.js

import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { TasksCollection } from '/imports/api/TasksCollection';

const insertTask = (taskText, user) =>
  TasksCollection.insert({
    text: taskText,
    userId: user._id,
    createdAt: new Date(),
  });

const SEED_USERNAME = 'meteorite';
const SEED_PASSWORD = 'password';

Meteor.startup(() => {
  if (!Accounts.findUserByUsername(SEED_USERNAME)) {
    Accounts.createUser({
      username: SEED_USERNAME,
      password: SEED_PASSWORD,
    });
  }

  const user = Accounts.findUserByUsername(SEED_USERNAME);

  if (TasksCollection.find().count() === 0) {
    [
      'First Task',
      'Second Task',
      'Third Task',
      'Fourth Task',
      'Fifth Task',
      'Sixth Task',
      'Seventh Task',
    ].forEach(taskText => insertTask(taskText, user));
  }
});

请注意,我们正在使用一个名为 userId 的新字段以及我们的用户 _id 字段,我们还设置了 createdAt 字段。

7.7:任务所有者

现在,您可以通过经过身份验证的用户在 UI 中筛选任务。在从 Mini Mongo 获取任务时,使用用户 _id 将字段 userId 添加到您的 Mongo 选择器中。

imports/ui/App.svelte

<script>
    ..
    $m: {
        user = Meteor.user();

        const userFilter = user ? { userId: user._id } : {};
        const pendingOnlyFilter = { ...hideCompletedFilter, ...userFilter };


        tasks = user
                ? TasksCollection.find(
                        hideCompleted ? pendingOnlyFilter : userFilter,
                        { sort: { createdAt: -1 } }
                ).fetch()
                : [];

        incompleteCount = user
                ? TasksCollection.find(pendingOnlyFilter).count()
                : 0;

        ..
    }
</script>

<div class="app">
    ..
    <div class="main">
        ..
            <ul class="tasks">
                {#each tasks as task (task._id)}
                    <Task task={task} />
                {/each}
            </ul>
        ..
    </div>
</div>

还要更新 insert 调用,以在 TaskForm 中包含字段 userId。您应该将用户从 App 组件传递到 TaskForm

imports/ui/TaskForm.svelte

<script>
    ..
    export let user = null;
    ..
    const handleSubmit = () => {
        // Insert a task into the collection
        TasksCollection.insert({
            text: newTask,
            createdAt: new Date(), // current time
            userId: user._id,
        });
        ..
    }
</script>

7.8:注销

我们还可以通过在应用栏下方显示所有者的用户名来更好地组织我们的任务。让我们添加一个新的 div,用户可以在其中点击并退出应用。

imports/ui/App.svelte

<script>
  ..
  const logout = () => Meteor.logout();
</script>
..
<div class="app">
    ..
    <div class="main">
        {#if user}
            <div class="user" on:click={logout}>
                {user.username} 🚪
            </div>
..

请记住也要设置用户名的样式。

client/main.css

.user {
  display: flex;

  align-self: flex-end;

  margin: 8px 16px 0;
  font-weight: bold;
}

呼!您在此步骤中做了很多事情。对用户进行身份验证,在任务中设置用户并为用户提供退出应用的方法。

您的应用现在应该如下所示

回顾:您可以查看此步骤结束时代码应如何编写 此处

在下一步中,我们将开始使用方法,以便仅在检查某些条件后更改数据。

在 GitHub 上编辑
// 搜索框