Skip to content

Commit 00d4a66

Browse files
authored
fix(drivers): readme endpoint (#425)
* test(drivers): test the readme endpoint * fix(drivers): test the readme endpoint * refactor: fix ameba issues
1 parent 4c3a2cb commit 00d4a66

File tree

5 files changed

+83
-26
lines changed

5 files changed

+83
-26
lines changed

.ameba.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Naming/AccessorMethodName:
1616
Enabled: false
1717
Lint/SpecFilename:
1818
Enabled: false
19+
Lint/UselessAssign:
20+
Enabled: false
1921

2022
Documentation/DocumentationAdmonition:
2123
Enabled: false

spec/controllers/drivers_spec.cr

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require "../helper"
22

33
module PlaceOS::Api
4-
describe Drivers do
4+
describe Drivers, tags: "drivers" do
55
describe "index", tags: "search" do
66
Spec.test_base_index(klass: Model::Driver, controller_klass: Drivers)
77

@@ -74,6 +74,65 @@ module PlaceOS::Api
7474
end
7575
end
7676

77+
describe "readme" do
78+
it "returns the readme content for a driver" do
79+
# Create a repository pointing to the real PlaceOS/drivers repo
80+
repository = Model::Generator.repository(type: Model::Repository::Type::Driver)
81+
repository.uri = "https://github.com/PlaceOS/drivers"
82+
repository.save!
83+
84+
# Create a driver with a real file path that has a readme
85+
driver = Model::Driver.new(
86+
name: "Auto Release",
87+
role: Model::Driver::Role::Logic,
88+
commit: "HEAD",
89+
module_name: "AutoRelease",
90+
file_name: "drivers/place/auto_release.cr",
91+
)
92+
driver.repository = repository
93+
driver.save!
94+
95+
id = driver.id.as(String)
96+
path = File.join(Drivers.base_route, id, "readme")
97+
98+
result = client.get(
99+
path: path,
100+
headers: Spec::Authentication.headers,
101+
)
102+
103+
result.success?.should be_true
104+
result.body.should contain("Auto Release")
105+
end
106+
107+
it "returns 404 when readme does not exist" do
108+
# Create a repository pointing to the real PlaceOS/drivers repo
109+
repository = Model::Generator.repository(type: Model::Repository::Type::Driver)
110+
repository.uri = "https://github.com/PlaceOS/drivers"
111+
repository.save!
112+
113+
# Create a driver with a file path that does NOT have a readme
114+
driver = Model::Driver.new(
115+
name: "No Readme Driver",
116+
role: Model::Driver::Role::Logic,
117+
commit: "HEAD",
118+
module_name: "NoReadme",
119+
file_name: "drivers/place/nonexistent_driver.cr",
120+
)
121+
driver.repository = repository
122+
driver.save!
123+
124+
id = driver.id.as(String)
125+
path = File.join(Drivers.base_route, id, "readme")
126+
127+
result = client.get(
128+
path: path,
129+
headers: Spec::Authentication.headers,
130+
)
131+
132+
result.status_code.should eq 404
133+
end
134+
end
135+
77136
describe "scopes" do
78137
before_each do
79138
HttpMocks.core_compiled

src/placeos-rest-api/controllers/drivers.cr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ module PlaceOS::Api
9191
driver_file_name = current_driver.file_name
9292
readme_path = driver_file_name.chomp(".cr") + "_readme.md"
9393

94-
# Create GitRepository instance
95-
repository_path = File.join(Repositories.repository_dir, repository.folder_name)
96-
git_repo = GitRepository.new(repository_path)
94+
# Create GitRepository instance using the repository's remote URI
95+
password = repository.decrypt_password if repository.password.presence
96+
git_repo = GitRepository.new(repository.uri, repository.username, password)
9797

9898
# Check if the readme file exists using the driver's commit
9999
files = git_repo.file_list(ref: current_driver.commit, path: readme_path)

src/placeos-rest-api/utilities/current-user.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module PlaceOS::Api
4343
begin
4444
# peek the token to determine type
4545
token_info = Utils::MSTokenExchange.peek_token_info(token)
46-
if token_info.is_ms_token?
46+
if token_info.ms_token?
4747
user = Utils::MSTokenExchange.obtain_place_user(token, token_info)
4848
raise "MS token could not be exchanged" unless user
4949
@current_user = user

src/placeos-rest-api/utilities/ms-token-exchange.cr

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module PlaceOS::Api
2626
version : TokenVersion,
2727
kid : String? do
2828
# Basic heuristic to detect Microsoft Entra / Azure AD issuers
29-
def is_ms_token? : Bool
29+
def ms_token? : Bool
3030
iss_val = iss_host
3131
return false unless iss_val
3232
iss_val = iss_val.downcase
@@ -119,14 +119,14 @@ module PlaceOS::Api
119119

120120
# if not existing or refresh failed, get a token using this token and on behalf of
121121
# https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-on-behalf-of-flow#example
122-
form = URI::Params.build do |form|
123-
form.add "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"
124-
form.add "client_id", oauth.client_id
125-
form.add "client_secret", oauth.client_secret
126-
form.add "assertion", token
127-
form.add "scope", oauth.scope
128-
form.add "requested_token_use", "on_behalf_of"
129-
form.add "resource", "https://graph.microsoft.com/"
122+
form = URI::Params.build do |builder|
123+
builder.add "grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"
124+
builder.add "client_id", oauth.client_id
125+
builder.add "client_secret", oauth.client_secret
126+
builder.add "assertion", token
127+
builder.add "scope", oauth.scope
128+
builder.add "requested_token_use", "on_behalf_of"
129+
builder.add "resource", "https://graph.microsoft.com/"
130130
end
131131

132132
uri = token_info.token_endpoint
@@ -163,23 +163,19 @@ module PlaceOS::Api
163163
# ---------- Audience Parsing ----------
164164

165165
def extract_aud_host(aud_raw : String) : String
166-
begin
167-
uri = URI.parse(aud_raw)
168-
uri.host || aud_raw
169-
rescue
170-
aud_raw
171-
end
166+
uri = URI.parse(aud_raw)
167+
uri.host || aud_raw
168+
rescue
169+
aud_raw
172170
end
173171

174172
# ---------- Issuer Parsing ----------
175173

176174
def extract_issuer_host(iss_raw : String) : String?
177-
begin
178-
uri = URI.parse(iss_raw)
179-
uri.host
180-
rescue
181-
nil
182-
end
175+
uri = URI.parse(iss_raw)
176+
uri.host
177+
rescue
178+
nil
183179
end
184180

185181
# ---------- Validation (JWKS) ----------

0 commit comments

Comments
 (0)