Interaction
创建 Interaction
Interaction 是用户可以执行的交互动作,近似等于一个 post api。 和其他 Web 框架不同的是,我们不需要声明当 interaction 发生时,应该如何处理数据。 而是在数据定义中反向引用 Interaction,具体见 Use Computed Data
一个简单的交友 interaction 如下:
const sendInteraction = Interaction.create({
name: 'sendRequest',
action: Action.create({name: 'sendRequest'}),
payload: Payload.create({
items: [
PayloadItem.create({
name: 'to',
base: UserEntity,
itemRef: userRefB
})
]
})
})
使用 Condition
Condition 用于限制当前用户执行 Interaction。在 Condition 的条件判断中可以获取到当前用户、 payload 等所有信息,可以用来做复杂的判断。 例如,我们限制年龄小于 20 的用户不能 sendRequest 给年龄大于 50 的用户:
const shouldNotSendCondition = Condition.create({
name: 'shouldNotSend',
content: async function (this: Controller, event: InteractionEventArgs) {
const BoolExp = this.global.BoolExp
const match = BoolExp.atom({key: 'id', value: ['=', event.payload.to.id]})
const toUser = await this.system.storage.get('User', match)
return !(event.user.age < 20 && toUser.age > 50)
}
})
const sendInteraction = Interaction.create({
name: 'sendRequest',
action: Action.create({name: 'sendRequest'}),
conditions: shouldNotSendCondition,
payload: Payload.create({
items: [
PayloadItem.create({
name: 'to',
base: UserEntity,
itemRef: userRefB
})
]
}),
})
在 Condition 中常常会使用到 Controller.system.storage
来获取数据,具体的 API 参考 reference/storage。
使用 BoolExp 来连接 Conditions
当 Condition 条件比较复杂时,我们可以通过 BoolExp
来连接多个 Condition 建立逻辑组合,然后再通过 boolExpToConditions
转化成 Condition。
例如,我们在刚才的例子中加上,用户不能发送给和自己 role 不相同的用户。然后使用 BoolExp
来连接两个条件:
import {bool} from "prop-types";
const shouldNotSendCondition2 = Condition.create({
name: 'shouldNotSend2',
content: async function (this: Controller, event: InteractionEventArgs) {
const BoolExp = this.global.BoolExp
const match = BoolExp.atom({key: 'id', value: ['=', event.payload.to.id]})
const toUser = await this.system.storage.get('User', match)
return event.user.role === toUser.role
}
})
const sendInteraction = Interaction.create({
// 使用 boolExpToConditions 将 boolExp 转换成 Conditions
conditions: boolExpToConditions(
// 使用 and 连接两个条件
BoolExp.and(shouldNotSendCondition, shouldNotSendCondition2)
),
//...
})
使用 Attribute
Attributive 可以限制可以执行当前 Interaction 的用户,也可以用来限制 Payload。 它可以看做是 Condition 的更具体的用法。
创建 Attributive
不要在 Attributive 中使用外部变量,应该保持 Attributive 是个纯函数。不然会在序列化和反序列化时失效。
一个声明 “我的” 的 Attributive 如下:
const Mine = Attributive.create({
name: 'Mine',
content: function (this: Controller, request, {user}) {
return request.owner === user.id
}
})
在 Interaqt/runtime 中我们为你内置了一个 createUserRoleAttributive
函数帮助你快速创建角色定语:
const adminRole = createUserRoleAttributive({name: 'admin'})
注意,它假定了你的 User Entity 中含有一个 string[]
类型的 roles
字段。
在 Attributive 中使用到的 Controller.system.storage
API 请参考 reference/storage。
创建通用的 Attributive
可以在业务上规定一些固定的定语,例如上面例子中 “我的”:它会检查实体上的 owner 字段是不是指向当前 interaction
请求的用户。那么只有有 owner
字段,并且确实是 UserEntity 类型,就可以使用这个定语。
当然,如果你不想固定用 owner
这个名字,但又想使用通用的定语,我们可以把字段信息和相应的实体细心通过 controller.globals
注入到 attributive 中让它动态判断。