diff options
author | Eugen Rochko <eugen@zeonfederated.com> | 2017-11-27 16:07:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-27 16:07:59 +0100 |
commit | 740f8a95a905e949b6a74bc69dcaf638d2d46248 (patch) | |
tree | 8e09ff52b47c0cd303a9681014b34e68b5e28c51 /app/models/invite.rb | |
parent | 0ea4478b68e60e442e5b254c2d2bc511e27fea83 (diff) |
Add consumable invites (#5814)
* Add consumable invites * Add UI for generating invite codes * Add tests * Display max uses and expiration in invites table, delete invite * Remove unused column and redundant validator - Default follows not used, probably bad idea - InviteCodeValidator is redundant because RegistrationsController checks invite code validity * Add admin setting to disable invites * Add admin UI for invites, configurable role for invite creation - Admin UI that lists everyone's invites, always available - Admin setting min_invite_role to control who can invite people - Non-admin invite UI only visible if users are allowed to * Do not remove invites from database, expire them instantly
Diffstat (limited to 'app/models/invite.rb')
-rw-r--r-- | app/models/invite.rb | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/app/models/invite.rb b/app/models/invite.rb new file mode 100644 index 000000000..ceca04686 --- /dev/null +++ b/app/models/invite.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true +# == Schema Information +# +# Table name: invites +# +# id :integer not null, primary key +# user_id :integer +# code :string default(""), not null +# expires_at :datetime +# max_uses :integer +# uses :integer default(0), not null +# created_at :datetime not null +# updated_at :datetime not null +# + +class Invite < ApplicationRecord + belongs_to :user, required: true + has_many :users, inverse_of: :invite + + before_validation :set_code + + attr_reader :expires_in + + def expires_in=(interval) + self.expires_at = interval.to_i.seconds.from_now unless interval.blank? + @expires_in = interval + end + + def valid_for_use? + (max_uses.nil? || uses < max_uses) && (expires_at.nil? || expires_at >= Time.now.utc) + end + + def expire! + touch(:expires_at) + end + + private + + def set_code + loop do + self.code = ([*('a'..'z'), *('A'..'Z'), *('0'..'9')] - %w(0 1 I l O)).sample(8).join + break if Invite.find_by(code: code).nil? + end + end +end |