33require 'time'
44require 'json'
55
6- require_relative '../../security/auth'
7- require_relative '../../domain/auto_source'
8- require_relative '../../errors/exceptions'
9- require_relative '../../security/url_validator'
10- require_relative '../../telemetry/observability'
11- require_relative 'feed_metadata'
12- require_relative 'response'
13-
146module Html2rss
157 module Web
168 module Api
179 module V1
1810 ##
1911 # Creates stable feed records from authenticated API requests.
20- module CreateFeed
12+ module CreateFeed # rubocop:disable Metrics/ModuleLength
2113 FEED_ATTRIBUTE_KEYS =
2214 %i[ id name url strategy feed_token public_url json_public_url created_at updated_at ] . freeze
23- class << self
15+ class << self # rubocop:disable Metrics/ClassLength
2416 # Creates a feed and returns a normalized API success payload.
2517 #
2618 # @param request [Rack::Request] HTTP request with auth context.
@@ -41,14 +33,14 @@ def call(request)
4133
4234 # @return [void]
4335 def ensure_auto_source_enabled!
44- raise ForbiddenError , Contract ::MESSAGES [ :auto_source_disabled ] unless AutoSource . enabled?
36+ raise Html2rss :: Web :: ForbiddenError , Contract ::MESSAGES [ :auto_source_disabled ] unless AutoSource . enabled?
4537 end
4638
4739 # @param request [Rack::Request]
4840 # @return [Hash]
4941 def require_account ( request )
5042 account = Auth . authenticate ( request )
51- raise UnauthorizedError , 'Authentication required' unless account
43+ raise Html2rss :: Web :: UnauthorizedError , 'Authentication required' unless account
5244
5345 account
5446 end
@@ -57,25 +49,35 @@ def require_account(request)
5749 # @param account [Hash]
5850 # @return [Html2rss::Web::Api::V1::FeedMetadata::CreateParams]
5951 def build_create_params ( params , account )
60- url = params [ 'url' ] . to_s . strip
61- raise BadRequestError , 'URL parameter is required' if url . empty?
62- raise BadRequestError , 'Invalid URL format' unless UrlValidator . valid_url? ( url )
63- raise ForbiddenError , 'URL not allowed for this account' unless UrlValidator . url_allowed? ( account , url )
64-
52+ url = validated_url ( params [ 'url' ] , account )
6553 FeedMetadata ::CreateParams . new (
6654 url : url ,
6755 name : FeedMetadata . site_title_for ( url ) ,
6856 strategy : normalize_strategy ( params [ 'strategy' ] )
6957 )
7058 end
7159
60+ # @param raw_url [String, nil]
61+ # @param account [Hash]
62+ # @return [String]
63+ def validated_url ( raw_url , account )
64+ url = raw_url . to_s . strip
65+ raise Html2rss ::Web ::BadRequestError , 'URL parameter is required' if url . empty?
66+ raise Html2rss ::Web ::BadRequestError , 'Invalid URL format' unless UrlValidator . valid_url? ( url )
67+ unless UrlValidator . url_allowed? ( account , url )
68+ raise Html2rss ::Web ::ForbiddenError , 'URL not allowed for this account'
69+ end
70+
71+ url
72+ end
73+
7274 # @param raw_strategy [String, nil]
7375 # @return [String]
7476 def normalize_strategy ( raw_strategy )
7577 strategy = raw_strategy . to_s . strip
7678 strategy = default_strategy if strategy . empty?
7779
78- raise BadRequestError , 'Unsupported strategy' unless supported_strategies . include ?( strategy )
80+ raise Html2rss :: Web :: BadRequestError , 'Unsupported strategy' unless supported_strategy ?( strategy )
7981
8082 strategy
8183 end
@@ -85,6 +87,12 @@ def supported_strategies
8587 Html2rss ::RequestService . strategy_names . map ( &:to_s )
8688 end
8789
90+ # @param strategy [String]
91+ # @return [Boolean]
92+ def supported_strategy? ( strategy )
93+ supported_strategies . include? ( strategy )
94+ end
95+
8896 # @return [String] default strategy identifier.
8997 def default_strategy
9098 Html2rss ::RequestService . default_strategy_name . to_s
@@ -95,7 +103,6 @@ def default_strategy
95103 def feed_attributes ( feed_data )
96104 timestamp = Time . now . iso8601
97105 typed_feed = feed_metadata ( feed_data )
98-
99106 typed_feed_attributes ( typed_feed , timestamp ) . slice ( *FEED_ATTRIBUTE_KEYS )
100107 end
101108
@@ -109,11 +116,11 @@ def request_params(request)
109116 return request . params if raw_body . strip . empty?
110117
111118 parsed = JSON . parse ( raw_body )
112- raise BadRequestError , 'Invalid JSON payload' unless parsed . is_a? ( Hash )
119+ raise Html2rss :: Web :: BadRequestError , 'Invalid JSON payload' unless parsed . is_a? ( Hash )
113120
114121 request . params . merge ( parsed )
115122 rescue JSON ::ParserError
116- raise BadRequestError , 'Invalid JSON payload'
123+ raise Html2rss :: Web :: BadRequestError , 'Invalid JSON payload'
117124 end
118125
119126 # @param request [Rack::Request]
@@ -131,7 +138,7 @@ def build_feed_from_request(request)
131138 params = build_create_params ( request_params ( request ) , account )
132139
133140 feed_data = AutoSource . create_stable_feed ( params . name , params . url , account , params . strategy )
134- raise InternalServerError , 'Failed to create feed' unless feed_data
141+ raise Html2rss :: Web :: InternalServerError , 'Failed to create feed' unless feed_data
135142
136143 [ params , feed_data ]
137144 end
0 commit comments