diff --git a/apps/api/Gemfile b/apps/api/Gemfile index aef3cd7..8fe540d 100644 --- a/apps/api/Gemfile +++ b/apps/api/Gemfile @@ -6,6 +6,7 @@ gem "puma", ">= 5.0" gem "rubyzip", "~> 2.3" gem "blueprinter" gem "bootsnap", require: false +gem "apipie-rails" gem "activeadmin" gem "activeadmin_blaze_theme" diff --git a/apps/api/app/controllers/api/downloads_controller.rb b/apps/api/app/controllers/api/downloads_controller.rb index 7fec1db..3b259ee 100644 --- a/apps/api/app/controllers/api/downloads_controller.rb +++ b/apps/api/app/controllers/api/downloads_controller.rb @@ -1,4 +1,14 @@ class Api::DownloadsController < ApiController + resource_description do + short "File downloads" + formats [ "binary" ] + end + + api :GET, "/api/download", "Download a file by path" + param :path, String, required: true, desc: "File path to download" + returns code: 200, desc: "File binary data" + error code: 400, desc: "Path is blank" + error code: 404, desc: "File not found" def show path = params[:path] return head :bad_request if path.blank? diff --git a/apps/api/app/controllers/api/events_controller.rb b/apps/api/app/controllers/api/events_controller.rb index c57ba64..fccb296 100644 --- a/apps/api/app/controllers/api/events_controller.rb +++ b/apps/api/app/controllers/api/events_controller.rb @@ -1,4 +1,10 @@ class Api::EventsController < ApiController + resource_description do + short "Events" + end + + api :GET, "/api/events", "List all events" + returns code: 200, desc: "Array of events" def index render json: EventService.new.index end diff --git a/apps/api/app/controllers/api/images_controller.rb b/apps/api/app/controllers/api/images_controller.rb index 05725c6..ae4a8ad 100644 --- a/apps/api/app/controllers/api/images_controller.rb +++ b/apps/api/app/controllers/api/images_controller.rb @@ -1,4 +1,13 @@ class Api::ImagesController < ApplicationController + resource_description do + short "Images" + formats [ "binary" ] + end + + api :GET, "/api/image/:id", "Get image by ID" + param :id, :number, required: true, desc: "Image ID" + returns code: 200, desc: "Image binary data" + error code: 404, desc: "Image not found" def show image = ImageService.new.show(ImageShowInputDto.new(id: params[:id])) send_file image.file_path, type: image.content_type, disposition: "inline" diff --git a/apps/api/app/controllers/api/members_controller.rb b/apps/api/app/controllers/api/members_controller.rb index a2f43db..27a75d2 100644 --- a/apps/api/app/controllers/api/members_controller.rb +++ b/apps/api/app/controllers/api/members_controller.rb @@ -1,4 +1,10 @@ class Api::MembersController < ApiController + resource_description do + short "Team members" + end + + api :GET, "/api/members", "List all team members" + returns code: 200, desc: "Array of team members" def index render json: MemberService.new.index end diff --git a/apps/api/app/controllers/api/rss_controller.rb b/apps/api/app/controllers/api/rss_controller.rb index 1ed59c3..50288d8 100644 --- a/apps/api/app/controllers/api/rss_controller.rb +++ b/apps/api/app/controllers/api/rss_controller.rb @@ -1,9 +1,18 @@ class Api::RssController < ApiController + resource_description do + short "RSS feeds" + formats [ "xml" ] + end + + api :GET, "/api/rss/blog", "Blog RSS feed" + returns code: 200, desc: "RSS XML feed of blog posts" def blog xml = RssService.new.blog_feed render xml: xml, content_type: "application/rss+xml" end + api :GET, "/api/rss/releases", "Software releases RSS feed" + returns code: 200, desc: "RSS XML feed of software releases" def releases xml = RssService.new.releases_feed render xml: xml, content_type: "application/rss+xml" diff --git a/apps/api/app/controllers/api/software_controller.rb b/apps/api/app/controllers/api/software_controller.rb index 01b8d15..c6275e1 100644 --- a/apps/api/app/controllers/api/software_controller.rb +++ b/apps/api/app/controllers/api/software_controller.rb @@ -1,4 +1,10 @@ class Api::SoftwareController < ApiController + resource_description do + short "Software catalog" + end + + api :GET, "/api/software", "List all software entries with releases" + returns code: 200, desc: "Array of software entries with nested releases" def index render json: SoftwareService.new.index end diff --git a/apps/api/app/controllers/api/software_highlighted_controller.rb b/apps/api/app/controllers/api/software_highlighted_controller.rb index 94f2ac6..88b7219 100644 --- a/apps/api/app/controllers/api/software_highlighted_controller.rb +++ b/apps/api/app/controllers/api/software_highlighted_controller.rb @@ -1,4 +1,11 @@ class Api::SoftwareHighlightedController < ApiController + resource_description do + short "Highlighted software" + end + + api :GET, "/api/software/highlighted", "Get currently highlighted software entry" + returns code: 200, desc: "Highlighted software entry with releases" + error code: 404, desc: "No highlighted software found" def index result = SoftwareHighlightedService.new.index if result diff --git a/apps/api/app/controllers/api/wiki_controller.rb b/apps/api/app/controllers/api/wiki_controller.rb index 474bcd1..48f7942 100644 --- a/apps/api/app/controllers/api/wiki_controller.rb +++ b/apps/api/app/controllers/api/wiki_controller.rb @@ -1,4 +1,13 @@ class Api::WikiController < ApiController + resource_description do + short "Wiki pages" + end + + api :GET, "/api/wiki/pages", "List wiki pages filtered by tag" + param :tag, String, required: false, desc: "Filter by tag (blog, howto)" + param :limit, :number, required: false, desc: "Limit number of results" + param :body, String, required: false, desc: "Include body content (1 = yes)" + returns code: 200, desc: "Array of wiki pages" # GET /api/wiki/pages?tag=blog|howto[&limit=30][&body=1] def index render json: WikiService.new.pages( diff --git a/apps/api/app/controllers/api_controller.rb b/apps/api/app/controllers/api_controller.rb index af65e22..5038606 100644 --- a/apps/api/app/controllers/api_controller.rb +++ b/apps/api/app/controllers/api_controller.rb @@ -1,2 +1,6 @@ class ApiController < ActionController::API + resource_description do + api_version "1.0" + formats [ "json" ] + end end diff --git a/apps/api/app/controllers/files_controller.rb b/apps/api/app/controllers/files_controller.rb index 1059098..fb023ac 100644 --- a/apps/api/app/controllers/files_controller.rb +++ b/apps/api/app/controllers/files_controller.rb @@ -1,6 +1,16 @@ class FilesController < ApplicationController skip_forgery_protection + resource_description do + short "Static files" + formats [ "binary" ] + end + + api :GET, "/file/*path", "Serve or redirect to a file" + param :path, String, required: true, desc: "File path" + returns code: 200, desc: "File binary data" + returns code: 301, desc: "Redirect to file URL" + error code: 404, desc: "File not found" def show result = FileService.new.show(FileShowInputDto.new(path: params[:path])) case result.type diff --git a/apps/api/app/controllers/update_controller.rb b/apps/api/app/controllers/update_controller.rb index 40432a9..051c432 100644 --- a/apps/api/app/controllers/update_controller.rb +++ b/apps/api/app/controllers/update_controller.rb @@ -1,4 +1,18 @@ class UpdateController < ApiController + resource_description do + short "Software updater" + formats [ "text" ] + end + + api :GET, "/update", "Update software version in database" + param :secret, String, required: true, desc: "Authorization secret" + param :platform, String, required: false, desc: "Platform name" + param :name, String, required: false, desc: "Software name" + param :version, String, required: true, desc: "Version string" + returns code: 200, desc: "'Updated' on success" + error code: 401, desc: "Invalid secret" + error code: 400, desc: "Version not provided or invalid arguments" + error code: 500, desc: "Internal server error" def update return render plain: "Unauthorized", status: :unauthorized unless authorized? return render plain: "Version not provided", status: :bad_request if params[:version].blank? diff --git a/apps/api/config/initializers/apipie.rb b/apps/api/config/initializers/apipie.rb new file mode 100644 index 0000000..11760f6 --- /dev/null +++ b/apps/api/config/initializers/apipie.rb @@ -0,0 +1,14 @@ +Apipie.configure do |config| + config.app_name = "Teletype Games API" + config.api_base_url = "" + config.doc_base_url = "/api/docs" + config.api_controllers_matcher = [ + "#{Rails.root}/app/controllers/api/**/*.rb", + "#{Rails.root}/app/controllers/update_controller.rb", + "#{Rails.root}/app/controllers/files_controller.rb" + ] + config.validate = false + config.translate = false + config.default_version = "1.0" + config.app_info = "Teletype Games retro game library API" +end diff --git a/apps/api/config/routes.rb b/apps/api/config/routes.rb index 4946f81..20f4df1 100644 --- a/apps/api/config/routes.rb +++ b/apps/api/config/routes.rb @@ -1,4 +1,5 @@ Rails.application.routes.draw do + apipie devise_for :admin_users, ActiveAdmin::Devise.config ActiveAdmin.routes(self)