首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多租户web应用: Devise inside Devise?

多租户web应用: Devise inside Devise?
EN

Stack Overflow用户
提问于 2015-12-27 09:10:36
回答 2查看 1.2K关注 0票数 0

我正在尝试建立一个多租户应用程序,其中用户可以有自己的网站,并在网站内,访问者可以创建帐户和登录等。

我将在此应用程序中使用Postgresql模式。

现在,用户可以创建一个基本的网站,添加内容等。但我希望游客能够注册这些网站的帐户。

例如,用户创建了一个网站,他可以登录到site.app.com /site.app.com来管理他的网站。

这是令人困惑的,如果有人做过这样的事情,请帮助我实现这一点。

谢谢

EN

回答 2

Stack Overflow用户

发布于 2015-12-27 19:38:22

我以前也做过类似的事情。

我需要解释一下。

标准意义上的Multi Tenancy表示对单个应用程序使用多个环境。作为explained

软件多租户是指中的一种软件体系结构,其中软件的单个实例在服务器上运行,并为多个租户提供服务。租户是一组用户,他们共享对软件实例具有特定权限的公共访问权限。多租户与多实例架构不同,在多实例架构中,独立的软件实例代表不同的租户运行。

简而言之,这意味着一个真正的多租户应用程序应该能够使用相同的资源为许多不同的用户提供服务。就Rails而言,这非常简单,因为它都是基于HTTP -a protocol构建的。

一个很好的例子就是RPG游戏,它将你所有的数据存储在服务器上。

--

尽管Rails本质上是多租户的,但它的数据库却不是。

How to create a multi-tenant database with shared table structures?

在我看来--也许我是“错的”--一个真正的多租户应用程序应该为每个用户分配一个单独的数据库,共享一个中央数据存储库,比如“账户”等:

代码语言:javascript
复制
-- database
  -- accounts
  -- invoices
  -- users
   -- 1
     -- pictures
     -- users
     -- etc
   -- 2
     -- pictures
     -- users
     -- etc

这看起来可能很复杂,但如果处理得当,它将使您能够安全地存储每个用户的数据等。

对于您的应用程序,这意味着您将把所有数据存储在单个数据库中,并链接到单个应用程序。

这意味着可以使用sessionsroles创建用户身份验证结构

  • 每个“子域”仅存储该子域的会话
  • 每个“子域”(帐户)根据分配给该帐户的用户进行验证
  • 每个用户将具有分配给其在

中参与的角色

模型的简单实现:

代码语言:javascript
复制
#app/models/account.rb
class Account < ActiveRecord::Base
   # This is for the "site" -- will create the subdomain etc
   has_many :memberships
   has_many :users, through: :memberships
end

#app/models/membership.rb
class Membership < ActiveRecord::Base
   belongs_to :account
   belongs_to :user
   belongs_to :role
end

#app/models/user.rb
class User < ActiveRecord::Base
   has_many :memberships
   has_many :accounts, thorugh: :memberships
end

#app/models/role.rb
class Role < ActiveRecord::Base
   has_many :memberships
end

这将允许您创建帐户,将用户分配给这些帐户,并在成员模型中存储不同的信息(如角色等)。

--

您还可以执行其他各种操作,但之后的主要操作是会话(因此用户只能登录到单个子域):

Share session (cookies) between subdomains in Rails?

这是缺省处理的;如果你想在子域之间“共享”会话,你必须在你的session_store.rb中添加tld_length: 2

--

为了处理子域,just set it up in the routes (就像Ryan Bates用他的Railscast做的那样):

代码语言:javascript
复制
#config/routes.rb
scope constraints: AccountManager do

    #This is from an app we're working on..... put what you want here.

    #Users
    devise_for :users, path: "", controllers: { sessions: "auth/sessions" }, path_names: { sign_in: "login", password: "forgot", confirmation: "confirm", unlock: "unblock", sign_up: "", invitation: "add", accept: "", registration: "register", sign_out: "logout" }

    #Authentication
    authenticate :user do
      root "transactions#index", as: :authenticated
    end

    #Core
    authenticated :user do
      resource  :settings, controller: :users, only: [:show, :update], constraints: { format: :js }         # User profile & settings (doubles up as options editor)
      resources :transactions, path: "", only: [:index, :update, :destroy], constraints: { format: :js } do # CRUD transactions
        scope format: true do #-> for constraints
          get :new, on: :new, constraints: { format: :js }
        end
        match "search(/:query)", action: :search, as: :search, on: :collection, via: [:get, :post]
      end
    end

end

#lib/account_manager.rb
module AccountManager

    # Refs
    # https://viget.com/extend/using-routing-constraints-to-root-your-app
    # https://stackoverflow.com/questions/5192175/how-to-set-in-a-middleware-a-variable-accessible-in-all-my-application

    def initializer(router)
        @router = router
    end

    def self.matches?(request)
        Account.exists? request.subdomain
    end

end

这将允许您登录etc (您必须修改Devise以仅接受帐户的members )。

代码语言:javascript
复制
#config/routes.rb
scope constraint: AccountManager do
   namespace :admin do #-> account.app.com/admin
      # stuff here
   end
end

这将允许您在管理控制器中使用基本授权:

代码语言:javascript
复制
#app/controllers/admin/application_controller.rb
class Admin::ApplicationController < ActionController::Base
   before_action :is_admin?

   private

   def is_admin?
      redirect_to root_path, notice: "Admin Only" unless current_user.admin? #-> has to check membership if is admin
   end
end

你也可以在app.com/admins或其他什么地方创建一个单独的管理界面;在那里你只能让管理员登录,等等。

票数 2
EN

Stack Overflow用户

发布于 2015-12-27 09:15:19

有几种方法可以做到这一点。如果您正在使用模式并在有人访问特定页面或登录到特定上下文时切换应用程序的作用域,那么这应该是您需要做的全部工作。

大多数人只需在用户(如Account)上添加一个模型,然后当有人新注册到您的站点时创建帐户,然后将用户与account_id关联为外键,即可实现此目的。在此之后,您可以将应用程序中的活动范围设置为适当的帐户,其他一切都是一样的。下面是如何使用devise来实现这一点。下面是一个示例,说明如何在RegistrationsController中使用devise来完成此操作。

http://www.austinstory.com/category/programming/rubyonrails/devise/

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34476765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档