我们首先来实现用户的注册功能。修改 default.scheme.js ,添加如下代码:
var validator = require('validator');
var crypto = require('crypto');
module.exports = {
"(GET|POST) /signup": {
"request": {
"session": checkNotLogin
}
},
"POST /signup": {
"request": {
"body": checkSignupBody
}
}
};
function md5 (str) {
return crypto.createHash('md5').update(str).digest('hex');
}
function checkNotLogin() {
if (this.session && this.session.user) {
this.flash = {error: '已登录!'};
this.redirect('back');
return false;
}
return true;
}
function checkLogin() {
if (!this.session || !this.session.user) {
this.flash = {error: '未登录!'};
this.redirect('/signin');
return false;
}
return true;
}
function checkSignupBody() {
var body = this.request.body;
var flash;
if (!body || !body.name) {
flash = {error: '请填写用户名!'};
}
else if (!body.email || !validator.isEmail(body.email)) {
flash = {error: '请填写正确邮箱地址!'};
}
else if (!body.password) {
flash = {error: '请填写密码!'};
}
else if (body.password !== body.re_password) {
flash = {error: '两次密码不匹配!'};
}
else if (!body.gender || !~['男', '女'].indexOf(body.gender)) {
flash = {error: '请选择性别!'};
}
else if (body.signature && body.signature.length > 50) {
flash = {error: '个性签名不能超过50字!'};
}
if (flash) {
this.flash = flash;
this.redirect('back');
return false;
}
body.name = validator.trim(body.name);
body.email = validator.trim(body.email);
body.password = md5(validator.trim(body.password));
return true;
}
这里我们定义了两个函数 checkNotLogin 和 checkLogin 用于检查用户的登录状态,并规定只有非登录状态才能访问 signup 页或者提交注册信息。当用户提交注册信息后,koa-scheme 会对请求体做严格的验证,验证失败则直接返回,验证通过则对请求体做过滤和格式化(将密码 md5 加密),然后请求才会传递到下一个中间件。
修改 signup.js ,添加如下代码:
var Models = require('../lib/core');
var $User = Models.$User;
exports.get = function* () {
yield this.render('signup');
};
exports.post = function* () {
var data = this.request.body;
var userExist = yield $User.getUserByName(data.name);
if (userExist) {
this.flash = {error: '用户名已存在!'};
return this.redirect('/');
}
yield $User.addUser(data);
this.session.user = {
name: data.name,
email: data.email
};
this.flash = {success: '注册成功!'};
this.redirect('/');
};
以上代码的意思是:当用户访问 /signup 时,渲染 signup.ejs 并返回页面;当用户提交注册信息时,首先检查用户名是否存在,存在则返回 '用户名已存在!'
的错误提示,不存在则添加该用户,并将该用户的信息保存到 session 中,返回 '注册成功!'
的提示。接下来我们完成模版文件和基本的 css 代码。
header.ejs
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>N-club</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/1.12.0/semantic.min.css">
<link rel="stylesheet" href="/css/style.css">
<script src="/js/jquery-1.11.2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/1.12.0/semantic.min.js"></script>
</head>
<body>
<div class="ui fixed menu navbar">
<div class="container">
<a href="/" class="item"><%= $app.name %></a>
<div class="item"><%= $app.description %></div>
<div class="right menu">
<% if ($this.session.user) { %>
<a href="/logout" class="item">登出</a>
<% } else { %>
<a href="/signup" class="item">注册</a>
<a href="/signin" class="item">登录</a>
<% } %>
</div>
</div>
</div>
<% if ($this.flash && $this.flash.success) { %>
<div class="flash">
<div class="ui green message"><i class="close icon"></i><%= $this.flash.success %></div>
</div>
<% } %>
<% if ($this.flash && $this.flash.error) { %>
<div class="flash">
<div class="ui red message"><i class="close icon"></i><%= $this.flash.error %></div>
</div>
<% } %>
<script type="text/javascript">
$('.message .close').on('click', function() {
$(this).closest('.message').fadeOut();
});
</script>
footer.ejs
</body>
</html>
signup.ejs
<% include header %>
<div class="container">
<div class="ui form segment" style="width:400px;margin:40px auto">
<form method="post">
<div class="two fields">
<div class="field required">
<label>用户名</label>
<input placeholder="用户名" type="text" name="name">
</div>
<div class="field required">
<label>性别</label>
<div class="ui selection dropdown">
<div class="default text">选择性别</div>
<i class="dropdown icon"></i>
<input type="hidden" name="gender">
<div class="menu">
<div class="item" data-value="男">男</div>
<div class="item" data-value="女">女</div>
</div>
</div>
</div>
</div>
<div class="two fields">
<div class="field required">
<label>密码</label>
<input placeholder="密码" type="password" name="password">
</div>
<div class="field required">
<label>重复密码</label>
<input placeholder="重复密码" type="password" name="re_password">
</div>
</div>
<div class="field required">
<label>邮箱</label>
<input placeholder="邮箱" type="email" name="email">
</div>
<div class="field">
<label>个人签名</label>
<input type="text" placeholder="限制在50字以内" name="signature">
</div>
<input type="submit" class="ui button fluid" value="注册">
</form>
</div>
</div>
<script type="text/javascript">
$('.ui.dropdown').dropdown();
</script>
<% include footer %>
style.css
body{background-color:#f9f9f7;padding-top:100px}
.container{width:100%;max-width:1100px;margin:0 auto}
.navbar{height:60px;line-height:60px;background-color:rgba(255,255,255,.9) !important}
.flash{max-width:1100px;margin:0 auto 20px}
.summary{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.topic{margin-top:10px;color:rgba(0,0,0,.4);font-size:.9rem}
.content{font-size:16px;line-height:24px}
.userCard{height:48px;margin-bottom:10px}
.userCard img{width:48px!important;height:48px;float:left;margin-right:15px}
.userCard .info{line-height:48px}
.list img{width:40px}
.ui.pagination{margin-top:10px !important}
.ui.comments{max-width:100%;font-size:16px}
.ui.menu .item:before{width:0}
至此我们就完成了用户注册的功能,启动 mongodb 并运行 npm start
试试吧。