我正在考虑一个多租户应用程序 - 共享数据库,共享模式。租户标识符(租户键)将每一行与正确的租户相关联。
我不确定如何将tenant_id 加载到某种全局范围内。这应该怎么发生?我假设我会解析域,然后根据域查找tenant_id。
我的问题:
- 在 rails 应用程序中查找会发生在哪里?在初始化程序中?这样做有更好的点吗?
- 一旦我确定了tenant_id,保存它的最佳方法是什么 - 一个简单的 session_id?
我正在考虑一个多租户应用程序 - 共享数据库,共享模式。租户标识符(租户键)将每一行与正确的租户相关联。
我不确定如何将tenant_id 加载到某种全局范围内。这应该怎么发生?我假设我会解析域,然后根据域查找tenant_id。
我的问题:
我为这个功能的控制器使用了一个前置过滤器。
您还可以对控制器类进行子类化以干燥控制器中的重复代码。
请注意,对给定租户信息的访问需要在每个用户的基础上进行身份验证。您需要确定给定用户是否可以访问多个租户。例如,用户“joe”是否应该有权访问租户 1 和 2?或者,Joe 是否需要按租户登录?
登录的授权应该控制对租户信息的访问。不要依赖域名来授予授权。
回复:在哪里保存tenant_id?存储在会话中。如果对会话的访问成本很高(存储在 DBMS 中),则在控制器启动期间将内存中的副本作为实例变量。谷歌了解 user_ids 的存储方式。
如果/何时用户想要访问不同的租户,您还应该确定用户体验。
添加要在用户登录之前查看要加载的欢迎屏幕,查看子域名是一个不错的选择。要查看传入请求使用的子域,请解析request.fullpath()
Docs。在控制器过滤器中执行此操作。
由于授权来自user_id,记得测试joe在tenant1.app.com登录但只能访问tenant2.app.com的情况
奖励答案正在寻找一个模板系统,使您的客户能够完全控制其租户的用户界面?查看Liquid 模板。我非常成功地使用它们使我的客户能够以安全的方式完全控制他们的外观和感觉。
重新评论中的其他问题
Re helper -- 如果您的意思是视图助手,那么我不建议将其作为确定租户的主要位置。制作@user
并@tenant
成为您查找一次的轻量级模型,然后在同一会话的其他请求期间从会话中检索。模型将由控制器使用,并且可能会传递给模型。视图层也将能够看到它们并在必要时使用它们。
If the UI may look/will look completely different for the different tenants, then add a "tenant-display" layer in addition to the view. Eg have the view gather the instance variables, find the right Liquid template, then express the view via the template.
You don't want the view to be computing "if tenant_a then x else y"