1

В нашем Rails 4 приложения, есть четыре модели:Приложение Rails 4: как разрешить пользователям приглашать других пользователей для совместной работы на конкретном экземпляре модели?

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.

Это создаст новый @administration между приглашенными @user и существующим @calendar.

Хитрая часть здесь - или, по крайней мере, размыто часть для нас - вроде бы обрабатывать как зарегистрированные, так и незарегистрированные пользователи:

  • Для незарегистрированных пользователей: когда «приглашает» user акций в calendar с «приглашен» user, как мы разрешаем последнему получать приглашение через адрес электронной почты, введенный первым, позволяя ему регистрироваться в приложении через адрес электронной почты по своему выбору (либо тот же, либо другой)?

  • Для зарегистрированных пользователей: если «приглашает» user акций в calendar с «приглашены» user, как мы позволяем последним, чтобы получить приглашение через адрес электронной почты, набранного в на прежний, позволяя ему либо войдите в приложение со своей существующей учетной записью (либо с тем же адресом, либо с другим адресом электронной почты, чем тот, который используется «приглашением» user) или зарегистрируйтесь с адресом электронной почты по его выбору (либо тот, который используется «приглашением» user или другой адрес)?

Самое главное, как мы упорствовать информацию, относящуюся к calendar (скажем calendar_id), так что, как только «пригласил» user имеет либо войти в систему или подписался, он имеет доступ к calendar в " приглашающий "пользователь хотел предоставить ему доступ?

Примечание: Мы в настоящее время с помощью пользовательской системы аутентификации/авторизации, как предложено в Michael Hartl's Rails Tutorial и не используют Devise или другой драгоценный камень по этому вопросу.

Теперь вопрос в том, как достичь этого:

  • Если мы просто создаем invite метод в Administration модели и использовать его в AdministrationsController#new?
  • Должны ли мы создать совершенно новое InvitationsController?
  • Следует ли использовать драгоценный камень, например Devise Invitable *?
  • Или есть совершенно другое, очевидное решение, которое нам не хватает?
+0

Используете ли вы какие-либо авторизации? Нужно ли приглашать пользователя в приложение? –

+0

Как указано в * Примечание *, мы используем систему аутентификации: «В настоящее время мы используем специальную систему аутентификации/авторизации, как это предложено в учебнике Rails Майкла Хартла и не используют Devise или другой камень в этом отношении». И да, пользователь должен пригласить другого пользователя из приложения. Но здесь это не «вирусный» механизм приглашений, который мы пытаемся реализовать: приглашение позволяет пользователям сотрудничать в одном экземпляре '@ calendar', если это имеет смысл. –

ответ

1

Хорошо, вот мои 2 цента. Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Поскольку вы создали пользовательскую аутентификацию и авторизацию, это решение может вам помочь.

enter image description here

Я предполагаю, что список доступа должен быть что-то вроде этого, как я не могу видеть список доступа в публикуемых миграциях.

В любом случае при регистрации вы назначаете токен каждому пользователю.

Что-то вроде этого:

before_create :generate_token 

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

Затем, когда пользователь приглашает просто передать этот маркер.

Теперь вам нужен метод при регистрации, чтобы просто распознать токен, а затем заполнить таблицу приглашения.

отдых должен быть легким.

Внутри модуля аутентификации просто метод, как это:

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

(я не люблю Rails find_by_ методы, которые вы можете использовать find_by_user_id - я немного старомоден;)

(Я предполагаю, что вы создали модуль, который вы можете использовать в своем приложении). Если нет, то дайте мне знать, что я помогу вам найти помощника.

Итак, теперь у вас есть пользователь, который пригласил вашего текущего пользователя. Теперь просто верните разрешения, которые вы выделили для пользователя, который приглашен вашему текущему пользователю, и продолжайте работу с приложением.

Надеюсь, это поможет. Дайте мне знать, если вам нужно больше направлений. Я использовал один и тот же метод для одного из моих приложений для партнерской программы и преимуществ члена от присоединения.

Cheers.

Update

Потому что вы спросили о модуле авторизации и у вас есть пользовательские проверки подлинности. Вот какой код. (Частично протестирован и должен быть переработан, пожалуйста, используйте его в качестве руководства, они имеют некоторые общие задачи, которые я мог думать)

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 

Update

После ваши комментарии относительно хороший источник для авторизации. Я бы предложил использовать Gems или по крайней мере один авторизованный Gem, который может обрабатывать сложные задания.

Одно из моих любимых возлюбленных Declarative Authorization.Я реализовал одну и ту же структуру БД с этим Gem на веб-сайте с 6 различными ACL-группами и загрузками с максимальным количеством разрешений с более чем 500K активных пользователей.

Посмотрите этот учебник: http://railscasts.com/episodes/188-declarative-authorization Очень хорошая отправная точка.

Поскольку у вас нет Devise или что-то в этом роде, просто убедитесь, что у вас есть current_user. Вы можете определить его в ApplicationController

Это руководство расскажет вам, как сделать текущий пользователь (платный учебник - это стоит - поверьте мне!) http://railscasts.com/episodes/250-authentication-from-scratch-revised

+0

Большое вам спасибо за подробный ответ. Это имеет большой смысл. Впрочем, пара деталей не соответствует нашей ситуации, я думаю. 1. У нас нет таблицы «Роль»: нельзя ли просто добавить столбец 'role' в таблицу' invite'? 2. У нас нет списка доступа: какова его цель, и на самом деле у нас его есть? 3. Система аутентификации, которую мы реализовали, основана на 'session', с набором соответствующего контроллера и помощника: вот что вы имели в виду, когда вы упомянули наш« модуль аутентификации »? Еще раз большое спасибо за то, что вы приложили столько усилий к ответу. –

+0

hmmmm. Поэтому позвольте мне сначала спросить вас, насколько велика ваша заявка? у вас есть уровни пользователей? как администратор, зарегистрированный, авторы и т. д.? у вас есть что-то вроде того, какая группа может или не может выполнить задачу или получить доступ к части сайта? Если да, то ВЫ ДОЛЖНЫ иметь список доступа, иначе у вас будет много дубликатов. AccessList - это то, где вы определяете группу и назначаете роль группе людей, тогда члены группы имеют определенный доступ к части сайтов. Сеансы - это аутентификация, а не авторизация. Аутентификация - это кто и как регистрироваться и выходить, а авторизация - это кто делает и что видит. –

+0

И без добавления роли пользователю будет слишком много дублирования. вам лучше реорганизовать его на свой собственный стол. Я также обновил свой ответ. –

Смежные вопросы