# frozen_string_literal: true class Client < ApplicationRecord def self.new_client(params) perm_string = params[:permission] || 'w' # create write client by default perm_rwx = Client.parse_perm_string(perm_string) new(params.except(:permission)).tap do |client| client.name_id = Digest::SHA1.hexdigest(client.name + SecureRandom.base64(8))[0, 8] client.perm_r = perm_rwx[:r] client.perm_w = perm_rwx[:w] client.perm_x = perm_rwx[:x] end end def update_client(params) perm_rwx = Client.parse_perm_string(params[:permission]) update(params.except(:permission)) return unless perm_rwx self.perm_r = perm_rwx[:r] self.perm_w = perm_rwx[:w] self.perm_x = perm_rwx[:x] end def gen_api_key api_key = SecureRandom.hex(32) self.api_key = api_key "#{RynDNS::Application::API_KEY_PREFIX}.#{self.name_id}.#{api_key}" end def api_key @api_key ||= BCrypt::Password.new(api_key_hash) end def api_key=(new_api_key) @api_key = BCrypt::Password.create(new_api_key) # TODO: benchmark cost on target hw self.api_key_hash = @api_key end def permission "#{'r' if perm_r}#{'w' if perm_w}#{'x' if perm_x}" end def read? perm_r end def write? perm_w end def admin? perm_x end def self.number_of_admins Client.where({ perm_x: true }).count end def self.admins? Client.number_of_admins >= 1 end # helper functions def self.parse_perm_string(perm_string) return nil unless perm_string.is_a?(String) perm_rwx = { r: false, w: false, x: false } return perm_rwx unless perm_string perm_string.each_char { |c| perm_rwx[c.to_sym] = true unless perm_rwx[c.to_sym].nil? } perm_rwx end # validations validates_presence_of :name, :name_id, :api_key_hash validates :name, length: { in: 3..20 }, uniqueness: true validates :name_id, length: { is: 8 }, uniqueness: true validates :description, length: { maximum: 200 } validates :ipv4, length: { maximum: 15 } validates_format_of :name, with: /\A([0-9a-zA-z_\-.@]){3,20}\z/i end