diff options
| author | mo khan <mo@mokhan.ca> | 2025-03-20 09:13:08 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-03-20 09:13:08 -0600 |
| commit | 4d0c6c388269d52eb20b5fc420965d124c38aa4b (patch) | |
| tree | 05f50c6b1496e90716228648fb1db2efceb7f33f | |
| parent | 136c4dfb645aff8a97e3c26fcc5b91ff9e32b3e7 (diff) | |
feat: add html pages to ui service that fetches data from rest api
| -rwxr-xr-x | bin/api | 8 | ||||
| -rwxr-xr-x | bin/idp | 2 | ||||
| -rwxr-xr-x | bin/ui | 144 | ||||
| -rw-r--r-- | policy.csv | 1 |
4 files changed, 145 insertions, 10 deletions
@@ -80,6 +80,7 @@ end module HTTPHelpers def authorized?(request, permission, resource) + raise [permission, resource].inspect if resource.nil? authorization = Rack::Auth::AbstractRequest.new(request.env) return false unless authorization.provided? @@ -138,7 +139,12 @@ class API when "/organizations", "/organizations.json" return json_ok(Organization.all.map(&:to_h)) when "/groups", "/groups.json" - return json_ok(Group.all.map(&:to_h)) + resource = Organization.default + if authorized?(request, :read_group, resource) + return json_ok(Group.all.map(&:to_h)) + else + return json_unauthorized(:read_group, resource) + end when "/projects", "/projects.json" resource = Organization.default if authorized?(request, :read_project, resource) @@ -328,6 +328,7 @@ module Authz condition(:owner) { true } rule { owner }.enable :read_project + rule { owner }.enable :read_group rule { owner }.enable :create_project end @@ -566,6 +567,7 @@ module Authz <head><title></title></head> <body> <h2>Authorize?</h2> + <p>Client ID: <%= oauth_params['client_id'] %></p> <form id="authorize-form" action="/oauth/authorize" method="post"> <input type="hidden" name="client_id" value="<%= oauth_params['client_id'] %>" /> <input type="hidden" name="scope" value="<%= oauth_params['scope'] %>" /> @@ -108,6 +108,10 @@ module OAuth end module HTTPHelpers + def current_user?(request) + request.session[:id_token] + end + def not_found [404, { 'X-Backend-Server' => 'UI' }, []] end @@ -119,7 +123,6 @@ module HTTPHelpers [302, { 'Location' => "http://ui.example.com:8080#{location}" }, []] end end - end class UI @@ -132,10 +135,22 @@ class UI end def call(env) - path = env['PATH_INFO'] - case env['REQUEST_METHOD'] - when 'GET' - case path + request = Rack::Request.new(env) + case request.request_method + when Rack::GET + case request.path + when "/groups.html" + if current_user?(request) + return get_groups(request) + else + return redirect_to("/oidc/new") + end + when /\A\/groups\/\d+\/projects.html\z/ + if current_user?(request) + return get_projects(request) + else + return redirect_to("/oidc/new") + end when "/oauth/callback" return oauth_callback(Rack::Request.new(env)) when "/oidc/new" @@ -147,8 +162,8 @@ class UI else return redirect_to("/saml/new") end - when 'POST' - case path + when Rack::POST + case request.path when "/saml/assertions" return saml_assertions(Rack::Request.new(env)) else @@ -177,7 +192,119 @@ class UI def oauth_callback(request) response = oauth_client.exchange(grant_type: "authorization_code", code: request.params['code']) - [response.code, response.header, [response.body]] + if response.code == "200" + tokens = JSON.parse(response.body, symbolize_names: true) + request.session[:access_token] = tokens[:access_token] + request.session[:id_token] = tokens[:id_token] + request.session[:refresh_token] = tokens[:access_token] + + template = <<~ERB + <!DOCTYPE html> + <html> + <head><title></title></head> + <body> + <pre style="display: none;"><%= response.body %></pre> + <pre><%= JSON.pretty_generate(request.session[:access_token]) %></pre> + <a href="/groups.html">Groups</a> + </body> + </html> + ERB + html = ERB.new(template, trim_mode: '-').result(binding) + [200, { 'Content-Type' => "text/html" }, [html]] + else + [response.code, response.header, [response.body]] + end + end + + def get_groups(request) + http = Net::Hippie::Client.new(headers: ::Net::Hippie::Client::DEFAULT_HEADERS.merge({ + 'Authorization' => Net::Hippie.bearer_auth(request.session[:access_token]) + })) + + response = http.get("http://api.example.com:8080/groups.json") + if response.code == "200" + groups = JSON.parse(response.body, symbolize_names: true) + template = <<~ERB + <!DOCTYPE html> + <html> + <head> + <title></title> + </head> + <body> + <a href="/groups.html">Groups</a> + <table> + <thead> + <tr> + <th>ID</th> + <th>Name</th> + <th>Organization ID</th> + <th>Parent ID</th> + <th> </th> + </tr> + </thead> + <tbody> + <%- groups.each do |group| -%> + <tr> + <td><%= group[:id] %></td> + <td><%= group[:name] %></td> + <td><%= group[:organization_id] %></td> + <td><%= group[:parent_id] %></td> + <td><a href="/groups/<%= group[:id] %>/projects.html">Projects</a></td> + </tr> + <%- end -%> + </tbody> + </table> + </body> + </html> + ERB + html = ERB.new(template, trim_mode: '-').result(binding) + [200, { 'Content-Type' => "text/html" }, [html]] + else + [response.code, response.header, [response.body]] + end + end + + def get_projects(request) + http = Net::Hippie::Client.new(headers: ::Net::Hippie::Client::DEFAULT_HEADERS.merge({ + 'Authorization' => Net::Hippie.bearer_auth(request.session[:access_token]) + })) + + response = http.get("http://api.example.com:8080/projects.json") + if response.code == "200" + projects = JSON.parse(response.body, symbolize_names: true) + + template = <<~ERB + <!DOCTYPE html> + <html> + <head> + <title></title> + </head> + <body> + <a href="/groups.html">Groups</a> + <table> + <thead> + <tr> + <th>Name</th> + <th>Group ID</th> + </tr> + </thead> + <tbody> + <%- projects.each do |project| -%> + <tr> + <td><%= project[:name] %></td> + <td><%= project[:group_id] %></td> + </tr> + <%- end -%> + </tbody> + </table> + </body> + </html> + ERB + html = ERB.new(template, trim_mode: '-').result(binding) + [200, { 'Content-Type' => "text/html" }, [html]] + else + [response.code, response.header, [response.body]] + end end def saml_post_to_idp(request) @@ -216,7 +343,6 @@ class UI saml_response = saml_binding.deserialize(request.params) raise saml_response.errors unless saml_response.valid? - request.session[:access_token] = saml_response.attributes[:access_token] template = <<~ERB <!doctype html> <html> @@ -9,3 +9,4 @@ p, *, idp.example.com, (GET)|(POST), /sessions* p, *, ui.example.com, (GET)|(POST), /oauth* p, *, ui.example.com, (GET)|(POST), /oidc* p, *, ui.example.com, (GET)|(POST), /saml* +p, *, ui.example.com, (GET), /*.html |
