Skip to content

Commit 9490362

Browse files
committed
feat: enhance auto source functionality with authentication and usage instructions
1 parent be178ab commit 9490362

File tree

14 files changed

+76
-151
lines changed

14 files changed

+76
-151
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,4 @@ Thumbs.db
7474

7575
# Ignore Astro cache
7676
/frontend/.astro/
77+
frontend/dist/

app.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,33 @@ def handle_health_check_auth(auth)
195195
credentials = Base64.decode64(auth[6..]).split(':')
196196
username, password = credentials
197197

198-
if username == ENV['HEALTH_CHECK_USERNAME'] &&
199-
password == ENV['HEALTH_CHECK_PASSWORD']
198+
if health_check_authenticated?(username, password)
200199
response['Content-Type'] = 'text/plain'
201200
HealthCheck.run
202201
else
203202
health_check_unauthorized
204203
end
205204
end
206205

206+
def health_check_authenticated?(username, password)
207+
expected_username, expected_password = health_check_credentials
208+
expected_username && expected_password &&
209+
username == expected_username && password == expected_password
210+
end
211+
212+
def health_check_credentials
213+
username = ENV.fetch('HEALTH_CHECK_USERNAME', nil)
214+
password = ENV.fetch('HEALTH_CHECK_PASSWORD', nil)
215+
216+
# In development, use default credentials if not set
217+
if username.nil? && ENV.fetch('RACK_ENV', nil) == 'development'
218+
username = 'admin'
219+
password = 'password'
220+
end
221+
222+
[username, password]
223+
end
224+
207225
def health_check_unauthorized
208226
response.status = 401
209227
response['WWW-Authenticate'] = 'Basic realm="Health Check"'

app/auto_source.rb

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ module AutoSource
99

1010
def enabled?
1111
# Enable by default in development, require explicit setting in production
12-
rack_env = ENV['RACK_ENV']
13-
auto_source_enabled = ENV['AUTO_SOURCE_ENABLED']
12+
rack_env = ENV.fetch('RACK_ENV', nil)
13+
auto_source_enabled = ENV.fetch('AUTO_SOURCE_ENABLED', nil)
1414

1515
if rack_env == 'development'
1616
auto_source_enabled != 'false'
@@ -26,26 +26,35 @@ def authenticate(request)
2626
credentials = Base64.decode64(auth[6..]).split(':')
2727
username, password = credentials
2828

29-
# Use default credentials in development if not set
30-
expected_username = ENV['AUTO_SOURCE_USERNAME'] || (ENV['RACK_ENV'] == 'development' ? 'admin' : nil)
31-
expected_password = ENV['AUTO_SOURCE_PASSWORD'] || (ENV['RACK_ENV'] == 'development' ? 'password' : nil)
32-
29+
expected_username, expected_password = expected_credentials
3330
return false unless expected_username && expected_password
3431

3532
username == expected_username && password == expected_password
3633
end
3734

35+
def expected_credentials
36+
# Use default credentials in development if not set
37+
username = ENV.fetch('AUTO_SOURCE_USERNAME', nil) ||
38+
(ENV.fetch('RACK_ENV', nil) == 'development' ? 'admin' : nil)
39+
password = ENV.fetch('AUTO_SOURCE_PASSWORD', nil) ||
40+
(ENV.fetch('RACK_ENV', nil) == 'development' ? 'password' : nil)
41+
[username, password]
42+
end
43+
3844
def allowed_origin?(request)
3945
origin = request.env['HTTP_HOST'] || request.env['HTTP_X_FORWARDED_HOST']
46+
origins = allowed_origins
47+
origins.empty? || origins.include?(origin)
48+
end
4049

41-
# In development, allow localhost origins by default
42-
if ENV['RACK_ENV'] == 'development'
43-
allowed_origins = (ENV['AUTO_SOURCE_ALLOWED_ORIGINS'] || 'localhost:3000,localhost:3001,127.0.0.1:3000,127.0.0.1:3001').split(',').map(&:strip)
50+
def allowed_origins
51+
if ENV.fetch('RACK_ENV', nil) == 'development'
52+
default_origins = 'localhost:3000,localhost:3001,127.0.0.1:3000,127.0.0.1:3001'
53+
origins = ENV.fetch('AUTO_SOURCE_ALLOWED_ORIGINS', default_origins)
4454
else
45-
allowed_origins = (ENV['AUTO_SOURCE_ALLOWED_ORIGINS'] || '').split(',').map(&:strip)
55+
origins = ENV.fetch('AUTO_SOURCE_ALLOWED_ORIGINS', '')
4656
end
47-
48-
allowed_origins.empty? || allowed_origins.include?(origin)
57+
origins.split(',').map(&:strip)
4958
end
5059

5160
def allowed_url?(url)

frontend/astro.config.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ export default defineConfig({
99
vite: {
1010
server: {
1111
proxy: {
12-
'/auto_source': {
13-
target: 'http://localhost:3000',
12+
"/auto_source": {
13+
target: "http://localhost:3000",
1414
changeOrigin: true,
1515
},
16-
'/health_check.txt': {
17-
target: 'http://localhost:3000',
16+
"/health_check.txt": {
17+
target: "http://localhost:3000",
1818
changeOrigin: true,
1919
},
2020
},

frontend/dist/auto-source/index.html

Lines changed: 0 additions & 6 deletions
This file was deleted.

frontend/dist/gallery/index.html

Lines changed: 0 additions & 6 deletions
This file was deleted.

frontend/dist/index.html

Lines changed: 0 additions & 2 deletions
This file was deleted.

frontend/dist/styles.css

Lines changed: 0 additions & 103 deletions
This file was deleted.

frontend/scripts/test-with-server.cjs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,20 @@ const MAX_WAIT_TIME = 30000 // 30 seconds
1313
let rubyServer = null
1414
let astroServer = null
1515

16-
async function waitForServer(url, maxWait = MAX_WAIT_TIME) {
16+
async function waitForServer(url, maxWait = MAX_WAIT_TIME, auth = null) {
1717
const startTime = Date.now()
1818

1919
while (Date.now() - startTime < maxWait) {
2020
try {
21+
const headers = {}
22+
if (auth) {
23+
headers.Authorization = `Basic ${Buffer.from(auth).toString("base64")}`
24+
}
25+
2126
const response = await fetch(url, {
2227
method: "GET",
2328
signal: AbortSignal.timeout(1000),
29+
headers,
2430
})
2531

2632
if (response.ok) {
@@ -51,6 +57,8 @@ async function startRubyServer() {
5157
AUTO_SOURCE_PASSWORD: "changeme",
5258
AUTO_SOURCE_ALLOWED_ORIGINS: "localhost:3000",
5359
AUTO_SOURCE_ALLOWED_URLS: "https://github.com/*,https://example.com/*",
60+
HEALTH_CHECK_USERNAME: "admin",
61+
HEALTH_CHECK_PASSWORD: "password",
5462
},
5563
})
5664

@@ -266,7 +274,11 @@ async function main() {
266274

267275
// Wait for servers to be ready
268276
console.log("⏳ Waiting for servers to be ready...")
269-
const rubyReady = await waitForServer(`http://localhost:${RUBY_SERVER_PORT}/health_check.txt`)
277+
const rubyReady = await waitForServer(
278+
`http://localhost:${RUBY_SERVER_PORT}/health_check.txt`,
279+
MAX_WAIT_TIME,
280+
"admin:password",
281+
)
270282
const astroReady = await waitForServer(`http://localhost:${ASTRO_SERVER_PORT}/api/feeds.json`)
271283

272284
if (!rubyReady && !astroReady) {

frontend/src/__tests__/api-integration.test.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import { describe, it, expect, beforeAll } from "vitest"
55
describe("Auto Source API Integration Tests", () => {
66
const RUBY_BACKEND_URL = "http://localhost:3000"
77
const ASTRO_BACKEND_URL = "http://localhost:4321"
8-
const auth = Buffer.from("admin:changeme").toString("base64")
8+
const auth = Buffer.from("admin:password").toString("base64")
99

1010
let backendUrl
1111

1212
beforeAll(async () => {
1313
// Set up test environment variables
1414
process.env.AUTO_SOURCE_ENABLED = "true"
1515
process.env.AUTO_SOURCE_USERNAME = "admin"
16-
process.env.AUTO_SOURCE_PASSWORD = "changeme"
16+
process.env.AUTO_SOURCE_PASSWORD = "password"
1717
process.env.AUTO_SOURCE_ALLOWED_ORIGINS = "localhost:3000,localhost:4321"
1818
process.env.AUTO_SOURCE_ALLOWED_URLS = "https://github.com/*,https://example.com/*"
1919

@@ -22,6 +22,9 @@ describe("Auto Source API Integration Tests", () => {
2222
const rubyResponse = await fetch(`${RUBY_BACKEND_URL}/health_check.txt`, {
2323
method: "GET",
2424
signal: AbortSignal.timeout(1000),
25+
headers: {
26+
Authorization: `Basic ${Buffer.from("admin:password").toString("base64")}`,
27+
},
2528
})
2629

2730
if (rubyResponse.ok) {

0 commit comments

Comments
 (0)