<commit_before>module TentD
  class API

    class GetAttachment < Middleware
      def action(env)
        params = env['params']
        request_proxy_manager = env['request_proxy_manager']

        if (params[:entity] != env['current_user'].entity) && !request_proxy_manager.can_read?(params[:entity])
          halt!(404, "Not Found")
        end

        proxy_condition = if (params[:entity] == env['current_user'].entity)
          :never
        else
          request_proxy_manager.proxy_condition
        end

        unless proxy_condition == :always
          attachment, post_attachment = lookup_attachment(env)
        else
          attachment = nil
        end

        if !attachment && proxy_condition != :never && request_proxy_manager.can_proxy?(params[:entity])
          # proxy request
          proxy_client = request_proxy_manager.proxy_client(params[:entity])

          begin
            res = proxy_client.attachment.get(params[:entity], params[:digest])

            body = res.body.respond_to?(:each) ? res.body : [res.body]
            return [res.status, res.headers, body]
          rescue Faraday::Error::TimeoutError
            halt!(504, "Failed to proxy request: #{res.env[:method].to_s.upcase} #{res.env[:url].to_s}")
          rescue Faraday::Error::ConnectionFailed
            halt!(502, "Failed to proxy request: #{res.env[:method].to_s.upcase} #{res.env[:url].to_s}")
          end
        elsif !attachment
          halt!(404, "Not Found")
        end

        env['response'] = attachment.data.lit
        (env['response.headers'] ||= {})['Content-Length'] = attachment.data.bytesize.to_s
        env['response.headers']['Content-Type'] = post_attachment.content_type
        env
      end

      private

      def lookup_attachment(env)
        params = env['params']

        attachment = Model::Attachment.where(:digest => params[:digest]).first
        return unless attachment

        post_attachment = Model::PostsAttachment.where(:attachment_id => attachment.id).first
        return unless post_attachment

        post = Model::Post.where(:id => post_attachment.post_id, :user_id => env['current_user'].id).first
        return unless post

        if env['current_auth'] && (app_auth = env['current_auth.resource']) && TentType.new(app_auth.type).base == %(https://tent.io/types/app-auth)
          post_type = TentType.new(post.type)
          unless app_auth.content['post_types']['read'].any? { |uri|
            type = TentType.new(uri)
            uri == 'all' || (type.base == post_type.base && (type.has_fragment? ? type.fragment == post_type.fragment : true))
          }
            return
          end
        else
          unless post.public
            return
          end
        end

        [attachment, post_attachment]
      end
    end

  end
end
<commit_msg>Fix permissions for GET attachment<commit_after>module TentD
  class API

    class GetAttachment < Middleware
      def action(env)
        params = env['params']
        request_proxy_manager = env['request_proxy_manager']

        if (params[:entity] != env['current_user'].entity) && !request_proxy_manager.can_read?(params[:entity])
          halt!(404, "Not Found")
        end

        proxy_condition = if (params[:entity] == env['current_user'].entity)
          :never
        else
          request_proxy_manager.proxy_condition
        end

        unless proxy_condition == :always
          attachment, post_attachment = lookup_attachment(env)
        else
          attachment = nil
        end

        if !attachment && proxy_condition != :never && request_proxy_manager.can_proxy?(params[:entity])
          # proxy request
          proxy_client = request_proxy_manager.proxy_client(params[:entity])

          begin
            res = proxy_client.attachment.get(params[:entity], params[:digest])

            body = res.body.respond_to?(:each) ? res.body : [res.body]
            return [res.status, res.headers, body]
          rescue Faraday::Error::TimeoutError
            halt!(504, "Failed to proxy request: #{res.env[:method].to_s.upcase} #{res.env[:url].to_s}")
          rescue Faraday::Error::ConnectionFailed
            halt!(502, "Failed to proxy request: #{res.env[:method].to_s.upcase} #{res.env[:url].to_s}")
          end
        elsif !attachment
          halt!(404, "Not Found")
        end

        env['response'] = attachment.data.lit
        (env['response.headers'] ||= {})['Content-Length'] = attachment.data.bytesize.to_s
        env['response.headers']['Content-Type'] = post_attachment.content_type
        env
      end

      private

      def lookup_attachment(env)
        params = env['params']

        attachment = Model::Attachment.where(:digest => params[:digest]).first
        return unless attachment

        post_attachment = Model::PostsAttachment.where(:attachment_id => attachment.id).first
        return unless post_attachment

        post = Model::Post.where(:id => post_attachment.post_id, :user_id => env['current_user'].id).first
        return unless post

        unless Authorizer.new(env).read_authorized?(post)
          return
        end

        [attachment, post_attachment]
      end
    end

  end
end

{'fraction_non_alphanumeric': 0.12342135476463835, 'fraction_numerical': 0.004592422502870264, 'mean_word_length': 2.466180371352785, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 1, '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': '812734', 'n_tokens_mistral': 1463, 'n_tokens_neox': 1423, 'n_words': 287}