Files
ubicloud/clover_api.rb
Jeremy Evans f4f33c119c Add CloverBase#current_user
Instead of setting @current_user twice in the main CloverWeb
route block and once in the CloverApi route block, add a method
that accesses it lazily, and sets it if it has not already been set.

This broke one spec that expected create_account when Account.[]
raised an error.  Remove the mocking and define a route only in
the test environment that can be used when you want to simulate
an exception.

Changes to the routes and views made with:

```
sed -i -e 's/@current_user/current_user/' `git grep -l '@current_user' routes views`
```

This is potentially slower, as method calls are slower than
instance variable accesses.  However, this avoids multiple
queries for users logged in via the remember token, and queries
are way more expensive than either method calls or instance
variable accesses.

For CloverApi, since the user was only set once, there is
no performance benefit from doing this.  However, since the
long term plan is to merge CloverWeb and CloverApi, and this
change would be necessary in that case, I took care of CloverApi
in this commit.
2024-10-28 14:40:13 -07:00

93 lines
2.2 KiB
Ruby
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# frozen_string_literal: true
require "roda"
require_relative "model"
class CloverApi < Roda
include CloverBase
plugin :default_headers,
"Content-Type" => "application/json"
plugin :hash_branches
plugin :json
plugin :json_parser
NAME_OR_UBID = /([a-z0-9](?:[a-z0-9\-]{0,61}[a-z0-9])?)|_([a-z0-9]{26})/
autoload_routes("api")
plugin :not_found do
response["Content-Type"] = "application/json"
{
error: {
code: 404,
type: "ResourceNotFound",
message: "Sorry, we couldnt find the resource youre looking for."
}
}.to_json
end
plugin :error_handler do |e|
response["Content-Type"] = "application/json"
error = parse_error(e)
{error: error}.to_json
end
plugin :rodauth do
enable :argon2, :json, :jwt, :active_sessions, :login
only_json? true
use_jwt? true
# Converting rodauth error response to the common error format of the API
json_response_body do |hash|
# In case of an error, rodauth returns the error in the following format
# {
# (required) "error": "There was an error logging in"
# (optional) "field-error": [
# "password",
# "invalid password"
# ]
# }
if json_response_error?
error_message = hash["error"]
type, code = case error_message
when "There was an error logging in"
["InvalidCredentials", 401]
when "invalid JWT format or claim in Authorization header"
["InvalidRequest", 400]
when "Please login to continue"
["LoginRequired", 401]
else
# :nocov:
["AuthenticationError", 401]
# :nocov:
end
hash.clear
hash["error"] = {
"code" => code,
"type" => type,
"message" => error_message
}
end
hash.to_json
end
hmac_secret Config.clover_session_secret
jwt_secret Config.clover_session_secret
argon2_secret { Config.clover_session_secret }
require_bcrypt? false
end
route do |r|
r.rodauth
rodauth.check_active_session
rodauth.require_authentication
r.hash_branches("")
end
end