Rails 4 应用程序:如何让用户邀请其他用户在特定模型实例上进行协作?

Rails 4 app: how to allow users to invite other users to collaborate on a particular model instance?

在我们的Rails4 app中,有四种模式:

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
  has_many :posts, dependent: :destroy
end

class Post < ActiveRecord::Base
    belongs_to :calendar
end

以下是相应的迁移:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :first_name
      t.string :last_name
      t.string :email
      t.integer :total_calendar_count
      t.integer :owned_calendar_count

      t.timestamps null: false
    end
  end
end

class CreateAdministrations < ActiveRecord::Migration
  def change
    create_table :administrations do |t|
      t.references :user, index: true, foreign_key: true
      t.references :calendar, index: true, foreign_key: true
      t.string :role

      t.timestamps null: false
    end
  end
end

class CreateCalendars < ActiveRecord::Migration
  def change
    create_table :calendars do |t|
      t.string :name

      t.timestamps null: false
    end
  end
end

class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
        t.references :calendar, index: true, foreign_key: true
        t.date :date
        t.time :time
        t.string :focus
        t.string :format
        t.string :blog_title
        t.text :long_copy
        t.text :short_copy
        t.string :link
        t.string :hashtag
        t.string :media
        t.float :promotion
        t.string :target
        t.integer :approval
        t.text :comment

      t.timestamps null: false
    end
  end
end

所以基本上,一个 user 可以有很多 calendar 而一个 calendar 可以有很多 user.

@user 创建一个新的 @calendar 时,我们会生成一个新的 @administration:目前正在运行。

我们现在想做的是允许 @user 邀请其他 @user(无论是否已注册)加入现有的 @calendar

这将在受邀 @user 和现有 @calendar 之间创建一个新的 @administration

这里棘手的部分——或者至少对我们来说是模糊的部分——似乎是处理注册用户和未注册用户:

最重要的是,我们如何保存与 calendar(比方说 calendar_id)相关的信息,以便一旦 "invited" user 登录或已注册,他可以访问 calendar "inviting" 用户想要授予他访问权限的权限?

注意:我们目前正在使用 Michael Hartl's Rails Tutorial 中建议的自定义 authentication/authorization 系统,而不是使用 Devise 或其他 gem 就此而言。

现在,问题是如何实现:

好的,这是我的 2 美分。如果您需要更多信息,请告诉我。

因为您已经进行了自定义身份验证和授权,所以此解决方案可能会对您有所帮助。

我假设您的访问列表应该是这样的,因为我在发布的迁移中看不到您的访问列表。

无论如何,在注册时,您会为每个用户分配一个令牌。

像这样:

before_create :generate_token

private
  def generate_token
    begin
      self.a_token = SecureRandom.hex
    end while self.class.exists?(a_token: access_token)
  end

然后当用户邀请时简单地分配这个令牌。

现在你需要一个方法在注册时简单地识别令牌,然后填写邀请table。

休息应该很容易。

在您的身份验证模块中只需使用如下方法:

 def invited_by
   Invite.where(:user_id => current_user.id).first
 end

( 我不喜欢 Rails find_by_ 你可以使用的方法 find_by_user_id - 我有点老套;)

(我假设你制作了一个模块,你可以在整个应用程序中使用它)如果没有那么让我知道我会帮助你。

现在您得到了邀请您当前用户的用户。现在只需 return 您为邀请您当前用户的用户分配的权限并继续该应用程序。

希望对您有所帮助。如果您需要更多指导,请告诉我。我对我的会员计划和成为会员的会员权益的申请之一使用了相同的方法。

干杯。

更新

因为您询问了授权模块并且您有自定义身份验证。这里有一些代码。 (部分测试和需要重构请使用它作为指南,它们是我能想到的一些常见任务)

module AuthorisationRelated
  def what_are_current_user_roles
    objArray = []
    current_user.roles.each do |role|
      objArray.push role.name
    end
    return objArray
  end


  def does_user_have_this_role?(role_name)
    result = false
    obj_array = what_are_current_user_roles
    obj_array.each do |a_role|
      if a_role == role_name
        result = true
      end
    end
    result
  end

  def is_admin?
    athu = false
    if  signed_in?
      current_user.roles.each do |role|
        if role.name == 'admin'
          athu = true
        end
      end
    end
    return athu
  end


#  class_instance MUST be a parent class
# If you need to Authenticate Model then your class_instance has to be @instance
  def user_allowed_create_and_edit?(class_model, class_instance)
    user_is_allowed = false
    if permitted_to? :create, class_model.new and has_user_own_this(class_instance)
      user_is_allowed = true
    else
      user_is_allowed = false
    end
    # Override everything if user is admin
    if is_admin?
      user_is_allowed = true
    end

    return user_is_allowed

  end

# relation has to be set to access_list
  def has_user_own_this(model)

    user_who_owns_this = model.access_list.user_id
    if current_user.id == user_who_owns_this
      return true
    else
      return false
    end
  end

  def find_current_user_acls
    acl = []
    acls = AccessList.joins(:user).where("users.id = ?",current_user.id)
    acls.each do |an_acl|
     acl.push an_acl.id
    end
    acl
  end

end

更新

根据您对授权的良好来源的评论。 我建议使用 Gems 或至少一个可以处理复杂分配的授权 Gem。

我一直以来的情人之一Declarative Authorization。我在一个具有 6 个不同的组 ACL 和桶负载的网站上使用此 Gem 实现了相同的数据库结构,并且拥有超过 500K 的活跃用户。

看看这个教程:http://railscasts.com/episodes/188-declarative-authorization很好的起点。

因为您没有 Devise 或类似的东西,请确保您手边有 current_user。您可以在 ApplicationController

中定义它

本教程将告诉您如何制作当前用户(付费教程-值得-相信我!)http://railscasts.com/episodes/250-authentication-from-scratch-revised