<commit_before>require 'hipaapotamus/accountability_error'

module Hipaapotamus
  module Protected
    extend ActiveSupport::Concern

    class_methods do
      def policy_class_name
        @policy_class_name ||= "#{name}Policy"
      end

      def policy_class
        @policy_class ||= policy_class_name.constantize
      end

      def policy_scoped
        policy_class.resolve_scope(AccountabilityContext.current_agent)
      end
    end

    included do
      delegate :policy_class, to: :class

      after_initialize :authorize_access!, unless: :new_record?
      after_create :authorize_creation!
      after_update :authorize_modification!
      after_destroy :authorize_destruction!
    end

    def hipaapotamus_display_name
      if new_record?
        "a new #{self.class.name}"
      else

        "#{self.class.name}(#{self.class.primary_key}=#{self[self.class.primary_key]})"
      end
    end

    def authorize_access!
      accountability_context = AccountabilityContext.current!

      begin
        policy_class.authorize!(accountability_context.agent, self, :access)

        accountability_context.record_action(self, :access)
      rescue AccountabilityError => error
        accountability_context.record_action(self, :attempted_access)

        raise error
      end
    end

    def authorize_creation!
      accountability_context = AccountabilityContext.current!

      begin
        policy_class.authorize!(accountability_context.agent, self, :creation)

        accountability_context.record_action(self, :creation, true)
      rescue AccountabilityError => error
        accountability_context.record_action(self, :attempted_creation)

        raise error
      end
    end

    def authorize_modification!
      accountability_context = AccountabilityContext.current!

      begin
        policy_class.authorize!(accountability_context.agent, self, :modification)

        accountability_context.record_action(self, :modification, true)
      rescue AccountabilityError => error
        accountability_context.record_action(self, :attempted_modification)

        raise error
      end
    end

    def authorize_destruction!
      accountability_context = AccountabilityContext.current!

      begin
        policy_class.authorize!(accountability_context.agent, self, :destruction)

        accountability_context.record_action(self, :destruction, true)
      rescue AccountabilityError => error
        accountability_context.record_action(self, :attempted_destruction)

        raise error
      end
    end

    protected

    def sanitize_for_mass_assignment(attributes)
      if attributes.respond_to?(:permitted?) && attributes.respond_to?(:permit)
        accountability_context = AccountabilityContext.current!

        super attributes.permit(policy_class.permitted_attributes(accountability_context.agent, self))
      else
        super attributes
      end
    end
  end
end<commit_msg>Adds permitted_attributes accessor to model instance<commit_after>require 'hipaapotamus/accountability_error'

module Hipaapotamus
  module Protected
    extend ActiveSupport::Concern

    class_methods do
      def policy_class_name
        @policy_class_name ||= "#{name}Policy"
      end

      def policy_class
        @policy_class ||= policy_class_name.constantize
      end

      def policy_scoped
        policy_class.resolve_scope(AccountabilityContext.current_agent)
      end
    end

    included do
      delegate :policy_class, to: :class

      after_initialize :authorize_access!, unless: :new_record?
      after_create :authorize_creation!
      after_update :authorize_modification!
      after_destroy :authorize_destruction!
    end

    def hipaapotamus_display_name
      if new_record?
        "a new #{self.class.name}"
      else

        "#{self.class.name}(#{self.class.primary_key}=#{self[self.class.primary_key]})"
      end
    end

    def authorize_access!
      accountability_context = AccountabilityContext.current!

      begin
        policy_class.authorize!(accountability_context.agent, self, :access)

        accountability_context.record_action(self, :access)
      rescue AccountabilityError => error
        accountability_context.record_action(self, :attempted_access)

        raise error
      end
    end

    def authorize_creation!
      accountability_context = AccountabilityContext.current!

      begin
        policy_class.authorize!(accountability_context.agent, self, :creation)

        accountability_context.record_action(self, :creation, true)
      rescue AccountabilityError => error
        accountability_context.record_action(self, :attempted_creation)

        raise error
      end
    end

    def authorize_modification!
      accountability_context = AccountabilityContext.current!

      begin
        policy_class.authorize!(accountability_context.agent, self, :modification)

        accountability_context.record_action(self, :modification, true)
      rescue AccountabilityError => error
        accountability_context.record_action(self, :attempted_modification)

        raise error
      end
    end

    def authorize_destruction!
      accountability_context = AccountabilityContext.current!

      begin
        policy_class.authorize!(accountability_context.agent, self, :destruction)

        accountability_context.record_action(self, :destruction, true)
      rescue AccountabilityError => error
        accountability_context.record_action(self, :attempted_destruction)

        raise error
      end
    end

    def permitted_attributes
      policy_class.permitted_attributes(AccountabilityContext.current!.agent, self)
    end

    protected

    def sanitize_for_mass_assignment(attributes)
      if attributes.respond_to?(:permitted?) && attributes.respond_to?(:permit)
        super attributes.permit permitted_attributes
      else
        super attributes
      end
    end
  end
end
{'fraction_non_alphanumeric': 0.06609195402298851, 'fraction_numerical': 0.0, 'mean_word_length': 3.232474964234621, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3840881', 'n_tokens_mistral': 1652, 'n_tokens_neox': 1576, 'n_words': 307}