asxpio/lib/s3.rb
Sergei Poljanski bdb3682e18
Some checks failed
Tests / test (push) Successful in 18s
Build and Deploy to Production / test (push) Successful in 18s
Build and Deploy to Production / build (push) Failing after 2s
Build and Deploy to Production / deploy (push) Has been skipped
bingo: serve datacenter bingo on bingo.asxp.io
Add a second public site to the same process: a 5x5 card of the 25
largest Russian datacenters where a cell is crossed out once an incident
with a public source is recorded (Yandex Sasovo and Kaluga drone strikes
on 2026-10-08/09 are seeded). config.ru dispatches by Host, so it rides
the existing container, DB and bucket instead of a new deploy.

The card is localized ru/en/uk with per-locale columns falling back to
ru. Content is managed from /admin/bingo on asxp.io, reusing AdminAuth
and CSRF. Photos go to the existing bucket under bingo/ and are proxied
by the app, so the bucket stays private and storage needs no change.

The seed data was fact-checked against operator sites and press on
2026-10-10; several entries in the original list were wrong or vague.

Assisted-by: Claude:opus-5
2026-10-10 04:51:26 +04:00

61 lines
1.6 KiB
Ruby

require 'aws-sdk-s3'
module S3
module_function
def client
@client ||= Aws::S3::Client.new(
region: ENV.fetch('S3_REGION', 'us-east-1'),
endpoint: ENV.fetch('S3_ENDPOINT'),
access_key_id: ENV.fetch('S3_ACCESS_KEY'),
secret_access_key: ENV.fetch('S3_SECRET_KEY'),
force_path_style: true
)
end
# Separate client whose endpoint is the public hostname; used only to mint
# presigned URLs that a browser can dereference. Bytes never travel through
# this client.
def presign_client
@presign_client ||= Aws::S3::Client.new(
region: ENV.fetch('S3_REGION', 'us-east-1'),
endpoint: ENV.fetch('S3_PUBLIC_ENDPOINT'),
access_key_id: ENV.fetch('S3_ACCESS_KEY'),
secret_access_key: ENV.fetch('S3_SECRET_KEY'),
force_path_style: true
)
end
def bucket
ENV.fetch('S3_BUCKET')
end
def put(key, bytes, content_type: 'application/pdf')
client.put_object(
bucket: bucket,
key: key,
body: bytes,
content_type: content_type
)
key
end
def get(key)
client.get_object(bucket: bucket, key: key).body.read
end
def exists?(key)
client.head_object(bucket: bucket, key: key)
true
rescue Aws::S3::Errors::NotFound, Aws::S3::Errors::NoSuchKey
false
end
def presigned_url(key, expires_in: 300, filename: nil)
params = { bucket: bucket, key: key }
if filename
params[:response_content_disposition] = %(attachment; filename="#{filename}")
end
Aws::S3::Presigner.new(client: presign_client).presigned_url(:get_object, **params, expires_in: expires_in)
end
end