bard-api 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c2588f15b3c76ced859daca1811cc720b29ff99fcc3d2e143551dc85537c631
4
- data.tar.gz: 24ec3a71ba250f6244b1ce63b274dbfb1076cce389ba17738e7558df58e345b3
3
+ metadata.gz: 70f38ef8f674aefa2cdcfba3586e87d644c10026943625bd82cb2be180f0035b
4
+ data.tar.gz: 1fd66c7e938efe753797d99e594c03f802948c004adafe0991b2b5577a00fb73
5
5
  SHA512:
6
- metadata.gz: b8c85085fb7bd21251da9e5ccea4194bc0b513805587dbb74a0f7716a26101db544c11ba1b3dc54543844b555e391badd799eab61a89f44c30356a860a71b543
7
- data.tar.gz: 98df9cb6b2909f99e7fe91b611b7494924d5f058c94e6c6f3935b1c1a876708f9891c848a6ccb161a00b65d3bcd0cd175b5be532919584aabebe9fc82d37d40a
6
+ metadata.gz: 6ce89073234248cf2a6ec1cc628bb97fcbf8f8d96e8be9d46dd117f54b1f18277e4c81cd9ec3ba2fb7fbd6fc1ef53bed84532f603db84ffda376cbd87b08f28e
7
+ data.tar.gz: 1119c0bc33153aeb74d53ec585c59b7bade8c410eda343962e9c2d5cf04bb017e8d2cb7e441c31c89c1dd4b687dcccc0ed1121e5fc7de2d8fbe158ce7ac34e8e
data/README.md CHANGED
@@ -80,17 +80,24 @@ Authorization: Bearer <jwt-token>
80
80
  ```json
81
81
  {
82
82
  "timestamp": "2025-12-06T10:30:00Z",
83
- "size": 123456789,
84
83
  "destinations": [
85
84
  {
86
85
  "name": "primary",
87
86
  "type": "s3",
88
- "status": "success"
87
+ "path": "bard-backup/my-app",
88
+ "region": "us-west-2"
89
89
  }
90
90
  ]
91
91
  }
92
92
  ```
93
93
 
94
+ **Response (404 Not Found):**
95
+ ```json
96
+ {
97
+ "error": "No backups found"
98
+ }
99
+ ```
100
+
94
101
  ### Authentication
95
102
 
96
103
  The API uses JWT with asymmetric RSA keys for authentication. The public key is embedded in the gem, and only BARD Tracker with the private key can create valid tokens.
data/lib/bard/api/app.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  require "rack"
4
4
  require "json"
5
5
  require_relative "auth"
6
- require_relative "backup"
6
+ require "bard/backup"
7
7
 
8
8
  module Bard
9
9
  module Api
@@ -24,7 +24,7 @@ module Bard
24
24
  not_found
25
25
  end
26
26
  rescue => e
27
- internal_error(e)
27
+ json_response(500, { error: e.message })
28
28
  end
29
29
 
30
30
  private
@@ -35,34 +35,22 @@ module Bard
35
35
 
36
36
  def create_backup(request)
37
37
  with_auth(request) do |payload|
38
- # Extract URLs from the JWT payload
39
- urls = payload["urls"]
40
- raise "Missing 'urls' in token payload" if urls.nil? || urls.empty?
41
-
42
- # Perform the backup
43
- backup = Backup.new
44
- result = backup.perform(urls)
45
-
46
- json_response(200, result)
38
+ backup = Bard::Backup.create!({
39
+ name: "bard",
40
+ type: :upload,
41
+ urls: payload["urls"]
42
+ })
43
+ json_response(200, backup.as_json)
47
44
  end
48
- rescue => e
49
- json_response(500, { error: "Backup failed: #{e.message}" })
50
45
  end
51
46
 
52
47
  def latest_backup(request)
53
48
  with_auth(request) do
54
- # Get the latest backup status
55
- backup = Backup.new
56
- result = backup.latest
57
-
58
- if result
59
- json_response(200, result)
60
- else
61
- json_response(404, { error: "No backups found" })
62
- end
49
+ backup = Bard::Backup.latest
50
+ json_response(200, backup.as_json)
63
51
  end
64
- rescue => e
65
- json_response(500, { error: e.message })
52
+ rescue Bard::Backup::NotFound => e
53
+ json_response(404, { error: e.message })
66
54
  end
67
55
 
68
56
  def with_auth(request)
@@ -79,10 +67,6 @@ module Bard
79
67
  def not_found
80
68
  json_response(404, { error: "Not found" })
81
69
  end
82
-
83
- def internal_error(e)
84
- json_response(500, { error: "Internal server error: #{e.message}" })
85
- end
86
70
  end
87
71
  end
88
72
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bard
4
4
  module Api
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.1"
6
6
  end
7
7
  end
data/lib/bard/api.rb CHANGED
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "api/version"
4
- require_relative "api/auth"
5
- require_relative "api/backup"
6
4
  require_relative "api/app"
7
5
 
8
6
  module Bard
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bard-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micah Geisel
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 2025-12-07 00:00:00.000000000 Z
11
+ date: 2025-12-11 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: jwt
@@ -51,6 +52,34 @@ dependencies:
51
52
  - - ">="
52
53
  - !ruby/object:Gem::Version
53
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bard-backup
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
54
83
  - !ruby/object:Gem::Dependency
55
84
  name: rack-test
56
85
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +111,6 @@ files:
82
111
  - lib/bard/api.rb
83
112
  - lib/bard/api/app.rb
84
113
  - lib/bard/api/auth.rb
85
- - lib/bard/api/backup.rb
86
114
  - lib/bard/api/version.rb
87
115
  homepage: https://github.com/botandrose/bard-api
88
116
  licenses:
@@ -90,6 +118,7 @@ licenses:
90
118
  metadata:
91
119
  homepage_uri: https://github.com/botandrose/bard-api
92
120
  source_code_uri: https://github.com/botandrose/bard-api
121
+ post_install_message:
93
122
  rdoc_options: []
94
123
  require_paths:
95
124
  - lib
@@ -104,7 +133,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
133
  - !ruby/object:Gem::Version
105
134
  version: '0'
106
135
  requirements: []
107
- rubygems_version: 3.6.2
136
+ rubygems_version: 3.5.11
137
+ signing_key:
108
138
  specification_version: 4
109
139
  summary: REST API for BARD-managed Rails projects
110
140
  test_files: []
@@ -1,104 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "backhoe"
4
- require "net/http"
5
- require "uri"
6
- require "time"
7
- require "fileutils"
8
-
9
- module Bard
10
- module Api
11
- class Backup
12
- class BackupError < StandardError; end
13
-
14
- # Perform a backup to the specified URLs
15
- def perform(urls)
16
- raise BackupError, "No URLs provided" if urls.nil? || urls.empty?
17
-
18
- timestamp = Time.now.utc
19
- destinations = []
20
- errors = []
21
-
22
- # Create temp file with timestamp
23
- filename = "#{timestamp.iso8601}.sql.gz"
24
- temp_path = "/tmp/#{filename}"
25
-
26
- begin
27
- # Dump database to temp file using Backhoe
28
- Backhoe.dump(temp_path)
29
-
30
- # Get file size
31
- file_size = File.size(temp_path)
32
-
33
- # Upload to all URLs in parallel
34
- threads = urls.map do |url|
35
- Thread.new do
36
- begin
37
- upload_to_url(url, temp_path)
38
- {
39
- name: "bard",
40
- type: "bard",
41
- status: "success"
42
- }
43
- rescue => e
44
- errors << e
45
- {
46
- name: "bard",
47
- type: "bard",
48
- status: "failed",
49
- error: e.message
50
- }
51
- end
52
- end
53
- end
54
-
55
- # Wait for all uploads to complete
56
- destinations = threads.map(&:value)
57
- ensure
58
- # Clean up temp file
59
- FileUtils.rm_f(temp_path)
60
- end
61
-
62
- # Store backup metadata
63
- @last_backup = {
64
- timestamp: timestamp.iso8601,
65
- size: file_size,
66
- destinations: destinations
67
- }
68
-
69
- # Raise error if any destination failed
70
- unless errors.empty?
71
- raise BackupError, "Some destinations failed: #{errors.map(&:message).join(", ")}"
72
- end
73
-
74
- @last_backup
75
- end
76
-
77
- # Get the latest backup status
78
- def latest
79
- # TODO: Retrieve from database instead of instance variable
80
- @last_backup
81
- end
82
-
83
- private
84
-
85
- def upload_to_url(url, file_path)
86
- uri = URI.parse(url)
87
-
88
- File.open(file_path, "rb") do |file|
89
- request = Net::HTTP::Put.new(uri)
90
- request.body = file.read
91
- request.content_type = "application/octet-stream"
92
-
93
- response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
94
- http.request(request)
95
- end
96
-
97
- unless response.is_a?(Net::HTTPSuccess)
98
- raise BackupError, "Upload failed with status #{response.code}: #{response.body}"
99
- end
100
- end
101
- end
102
- end
103
- end
104
- end