Sails.js就是这样做的。
新建了一个sails应用 api有这几个目录 adapters controllers models policies services adapters policies services 这是干吗的 聊天的代码应该写在哪儿呢?
@yakczh 用的版本是0.9
还是0.10
?
@bnuhero v0.10.7
我用过Sails 0.9做开发,下面的信息供你参考。
1. adapter
/api/adapters
目录下部署自定义的数据库适配器。常用的数据库,如MongoDB或者MySQL等,已经有对应的适配器实现,所以一般这里不需要有自己的代码文件。
2. policy
Policy是Sails的授权机制,定义了外部用户对controller的访问权限。例如,如果你正在开发Dropbox,在允许用户上载文件之前,你首先要确定用户是否已经得到认证(isAuthenticated
),然后要确保他对文件夹有写的权限(canWrite
),最后你还要保证目标文件夹有足够的空余空间(hasEnoughSpace
)。
定义policy
所有policy都定义在api/policies
文件夹下面,每个policy文件只包含一个函数。
本质上,policy也是一个Connect/Express中间件,不过它们在controller之前运行。可以定义多个policy,它们以链式方式工作——理想情况下,每个中间件就应该只完成一项功能。
例如,编写一个canWrite
策略:
// policies/canWrite.js
module.exports = function canWrite (req, res, next) {
var targetFolderId = req.param('id');
var userId = req.session.user.id;
Permission
.findOneByFolderId( targetFolderId )
.exec( function foundPermission (err, permission) {
// 有未预料的错误发生—— 跳到默认的错误处理器 (状态码:500)
if (err) return next(err);
// 用户无权操作这个文件夹。
// 这可能是因为文件夹被删除了,或者用户本来就没有权限,等等。
if ( ! permission ) return res.redirect('/notAllowed');
// 检查是否有写的权限
if ( permission.type !== 'write' ) return res.redirect('/notAllowed');
// 如果用户对目标文件夹拥有写的权限,那就继续执行后续的代码。
next();
});
};
使用policy
Sails的默认访问控制列表(Access Controller List, ACL)定义在config/policies.js
,它的作用建立ACL和controller之间的映射。
config/policies.js
的风格是声明式的。任何在api/policies
下的文件,都可以在config/policies.js
中直接引用。例如,api/policies/authenticated.js
在config/policies.js
中直接引用为authenticated
。
Sails的内置策略:
true
- 公开访问。任何人都有权访问。false
- 禁止访问。任何人都不可以访问。
默认的访问控制列表是*: true
,即任何人都有权访问任意的controller和action。正式发布时(production
模式),应该设置为*: false
,以免暴露应用逻辑。
添加策略示例
RabbitController: {
// RabbitController的所有action的默认策略是`false`,
// 即任何人都不无权访问。
'*': false,
// 对于`nurture`,应用'isRabbitMother'策略
// (这会覆盖上面的`false`策略)
nurture : 'isRabbitMother',
// 只有满足`isNiceToAnimals` 和 `hasRabbitFood` 策略的用户,
// 才可以喂兔子
feed : ['isNiceToAnimals', 'hasRabbitFood']
}
其中的isNiceToAnimals
策略,
// api/policies/isNiceToAnimals.js
module.exports = function isNiceToAnimals (req, res, next) {
// `req.session` 包含了当前请求用户的历史数据。
if ( req.session.user.hasHistoryOfAnimalCruelty ) {
return res.redirect('http://PETA.org');
}
if ( req.session.user.frownsAtPuppies ) {
return res.redirect('http://www.dailypuppy.com/');
}
// 如果用户的记录良好,
// 继续下一策略验证,直到controller
next();
};
3. Service
什么是service?
不确定:从0.10版开始?
本质上,service就是库,即在应用其它地方被多次调用的代码。例如,把电子邮件服务包装成一个EmailService
,方便在其它代码中调用。
如何创建一个service?
仍然以EmailService
为例,
// api/services/EmailService.js
exports.sendInviteEmail = function(options) {
var opts = {"type":"messages","call":"send","message":
{
"subject": "YourIn!",
"from_email": "info@balderdash.co",
"from_name": "AmazingStartupApp",
"to":[
{"email": options.email, "name": options.name}
],
"text": "Dear "+options.name+",\nYou're in the Beta! Click <insert link> to verify your account"
}
};
myEmailSendingLibrary.send(opts);
};
Sails会自动把service暴露给其它代码,
// 在controller中调用
EmailService.sendInviteEmail({email: 'test@test.com', name: 'test'});
@yakczh 关于adapter
、policies
和services
,见下面的回复。
至于如何使用集成websocket的统一路由,注意/assets/js
目录下默认生成三个文件:
socket.io.js
sails.io.js
app.js
在视图文件或者HTML文档中包含头两个文件,然后像app.js
中的代码那样调用socket.get()
等方法。服务器端跟处理普通HTTP请求一样,可以用res.json()
等方法返回数据。
tks