Skip to content

Commit

Permalink
📝 (website) Improve documentation website with generic info
Browse files Browse the repository at this point in the history
Screenshots for the api_clients administration. Fix some UI/UX on the administration screen
  • Loading branch information
Hadrien Froger committed Nov 19, 2024
1 parent a64c955 commit c52553c
Show file tree
Hide file tree
Showing 24 changed files with 189 additions and 28 deletions.
2 changes: 1 addition & 1 deletion app/commands/decidim/rest_full/create_api_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def api_client_attributes
organization: @form.current_organization,
name: @form.name,
decidim_organization_id: @form.decidim_organization_id,
scopes: @form.scopes.join(",")
scopes: @form.scopes
}
end
end
Expand Down
13 changes: 10 additions & 3 deletions app/controllers/decidim/rest_full/system/api_clients_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@ module RestFull
module System
class ApiClientsController < Decidim::System::ApplicationController
helper Decidim::Admin::AttributesDisplayHelper
helper Decidim::Core::Engine.routes.url_helpers
helper_method :destroy_admin_session_path

def core_engine_routes
Decidim::Core::Engine.routes.url_helpers
end
def destroy_admin_session_path
Decidim::System::Engine.routes.url_helpers.destroy_admin_session_path
end

def destroy
@api_client = collection.find(params[:id])
@api_client.destroy
redirect_to core_engine_routes.system_api_clients_path, flash: {success: "Client Revoked"}
end
def index
@api_clients = collection.page(params[:page]).per(15)
end
Expand All @@ -35,7 +42,7 @@ def create
CreateApiClient.call(@form) do
on(:ok) do |api_client|
flash[:notice] = I18n.t("create.success", scope: "decidim.rest_full.system.api_clients")
redirect_to edit_system_api_client_path(api_client)
redirect_to core_engine_routes.edit_system_api_client_path(api_client)
end

on(:invalid) do
Expand Down
3 changes: 1 addition & 2 deletions app/forms/decidim/rest_full/api_client_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ module RestFull
# The form that validates the data to construct a valid OAuthApplication.
class ApiClientForm < Decidim::Form
mimic :system_api_client

attribute :name, String
attribute :decidim_organization_id, Integer
attribute :scopes, [String]
validates :name, :decidim_organization_id, presence: true

def organization
current_organization || Decidim::Organization.find_by(id: decidim_organization_id)
end
Expand Down
4 changes: 2 additions & 2 deletions app/views/decidim/rest_full/system/api_clients/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<h3 class="h5"><%= t('.scopes_label') %></h3>
<% scope_options = %w[system proposals meetings debates pages] %>
<% scope_options.each do |scope| %>
<label class="block py-2">
<%= form.check_box :scopes, { multiple: true, label: "", disabled: disabled, checked: (form.object.scopes.first || "").include?(scope)}, scope, nil %>
<label class="block py-2 <%= disabled && !form.object.scopes.to_a.include?(scope.to_s) ? "hidden" : "" %>">
<%= form.check_box :scopes, { multiple: true, label: "", disabled: disabled, checked: form.object.scopes.to_a.include?(scope.to_s) }, scope, nil %>
<span class="font-normal"><%= t("scope_#{scope}", scope: "decidim.rest_full.models.api_client.fields") %></span>
</label>
<% end %>
Expand Down
77 changes: 70 additions & 7 deletions app/views/decidim/rest_full/system/api_clients/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,75 @@
<%= decidim_form_for(@form) do |f| %>
<%= render partial: "form", object: f, locals: {disabled:true} %>
<% end %>
<div class="form__wrapper">
<h3 class="h5"><%= t('.keys_label') %></h3>
<label>
<span><%= t('.client_id') %></span>
<input type="text" value="<%= @api_client.client_id %>" name="unnamed" />
</label>
<label>
<span><%= t('.client_secret') %></span>
<input type="text" value="<%= @api_client.client_secret %>" name="unnamed" />
</label>
</div>
<h2 class="h2"><%= t(".permissions_title") %></h2>
<% if @api_client.scopes.exists?("system") %>
<h2 class="card-title" id="system_permissions">
<%= t("scope_system", scope: "decidim.rest_full.models.api_client.fields") %>
</h2>
<div id="system_permissions" class="card-section" >
Hello
</div>
<div>
<strong><%= t(".permissions_scopes") %></strong><code><%= @api_client.scopes.to_a %></code>
</div>

<% if @api_client.scopes.to_a.include?("system") %>
<div class="border border-black ">
<h2 class="border-b-4 h5 p-4" id="system_permissions">
<%= t("scope_system", scope: "decidim.rest_full.models.api_client.fields") %>
</h2>
<div id="system_permissions" class="p-4 " >
<div class="mt-2">
<div class="font-bold py-2"><%= t('.auth_type') %></div>
<div class="flex gap-6 flex-wrap">
<label>
<input type="checkbox" />
<span class="pre">impersonate</span>
</label>
<label>
<input type="checkbox" />
<span class="pre">login</span>
</label>
</div>
</div>
<div class="mt-2">
<div class="font-bold py-2"><%= t('.organization_perm') %></div>
<div class="flex gap-6 flex-wrap">
<label>
<input type="checkbox" />
<span class="pre">list</span>
</label>
<label>
<input type="checkbox" />
<span class="pre">detail</span>
</label>
<label>
<input type="checkbox" />
<span class="pre">update</span>
</label>
<label>
<input type="checkbox" />
<span class="pre">destroy</span>
</label>
</div>
</div>
<div class="mt-2">
<div class="font-bold py-2"><%= t('.rails_perm') %></div>
<div class="flex gap-6 flex-wrap">
<label>
<input type="checkbox" />
<span class="pre">restart</span>
</label>
<label>
<input type="checkbox" />
<span class="pre">execute task</span>
</label>
</div>
</div>
</div>
</div>
<% end %>
7 changes: 7 additions & 0 deletions config/locales/decidim_rest_full.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ en:
save: "Save"
go_back: "Back to the list"
permissions_title: "Permissions"
permissions_scopes: "Allowed scopes"
keys_label: "Credentials"
client_id: "Client Id"
client_secret: "Client Secret"
auth_type: "Auth Type"
organization_perm: "Organization"
rails_perm: "Ruby on Rails"
show:
go_back: "Back to the list"
create:
Expand Down
9 changes: 2 additions & 7 deletions config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
# frozen_string_literal: true

# config/routes.rb
Decidim::RestFull::Engine.routes.draw do
get "/api/rest/docs", to: "pages#show", as: :documentation_root

Decidim::Core::Engine.routes.draw do
authenticate(:admin) do
namespace "system" do
resources :api_clients
resources :api_clients, controller: "/decidim/rest_full/system/api_clients"
end
end

root to: "system/api_clients#index"
end

Decidim::Core::Engine.routes.draw do
namespace :api do
namespace :rest_full do
scope "v#{Decidim::RestFull.major_minor_version}" do
Expand Down
2 changes: 1 addition & 1 deletion lib/decidim/rest_full/menu.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def self.register_system_menu!
Decidim.menu :system_menu do |menu|
menu.add_item :api_clients,
I18n.t("menu.api_clients", scope: "decidim.rest_full.admin"),
Decidim::RestFull.decidim_rest_full.system_api_clients_path,
Decidim::Core::Engine.routes.url_helpers.system_api_clients_path,
position: 4
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/swagger_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,13 @@
type: :http,
scheme: :bearer,
bearerFormat: :JWT,
description: "Authorization via service-to-service credentials flow. Use this for machine clients. [Learn more here](#{Decidim::RestFull.docs_url}/auth/client-credential-flow)"
description: "Authorization via service-to-service credentials flow. Use this for machine clients. [Learn more here](#{Decidim::RestFull.docs_url}/user_documentation/auth/client-credential-flow)"
},
resourceOwnerFlowBearer: {
type: :http,
scheme: :bearer,
bearerFormat: :JWT,
description: "Authorization via resource owner flow. Use this for user-based authentication [Learn more here](#{Decidim::RestFull.docs_url}/auth/user-credentials-flow)"
description: "Authorization via resource owner flow. Use this for user-based authentication [Learn more here](#{Decidim::RestFull.docs_url}/user_documentation/auth/user-credentials-flow)"

}
},
Expand Down
Binary file added website/docs/client_cred.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions website/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,41 @@ slug: /
---

# How does it work?
This module expose API Rest endpoint for Decidim. It uses secure workflows from OAuth2.0, leveraging the famous `doorkeeper` and `devise` gem.

This module:
- Manages from system administration new client credential
- Supports machine-to-machine and user tokens

It exposes for now only a _set of endpoints_, but the goal of this module is to support all the resources and actions available in Decidim. ([See Supported Resources](#supported-resources))

## Authentication flows

Machine-to-machine flow (Client Credential Flow):

![Client Credentials](./client_cred.png)

User token flow (Resource Owner Password Credential Flow)

![ROPC](./ropc.png)

## Supported Resources

| Scopes | Resource | Supported operations |
|------------ |------------------------- |---------------------- |
| `system` | organizations | Read |
| `public` | search | Read |
| `spaces` | assemblies | - |
| `spaces` | participatory_processes | - |
| `spaces` | conferences | - |
| `components` | components | - |
| `proposals` | proposals | - |
| `proposals` | proposal_drafts | - |
| `proposals` | proposal_amendments | - |
| `proposals` | proposal_comments | - |
| `proposals` | proposal_votes | - |

:::info
Each scope has its sets of fine-grained permissions, allowing to
cherry-pick what the authenticated system can do in the Decidim application.
:::
Binary file added website/docs/ropc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion website/docs/user_documentation/_category_.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"position": 3,
"link": {
"type": "generated-index",
"description": "How to configure rest-full with Decidim"
"description": "How to configure the Rest API for Decidim"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"position": 4,
"link": {
"type": "generated-index",
"description": "How to authenticate with the rest api"
"description": "Get tokens with your credentials."
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ title: Machine-to-Machine Token
description: How to authenticate a service to Decidim.
---

![Client Credentials](../../client_cred.png)

# Machine-to-Machine Authentication (Client Credentials Flow)

This flow is used for service-to-service authentication in Decidim, allowing systems to interact with the Decidim API without user involvement.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ sidebar_position: 4
title: User Token
description: How to authenticate a user to Decidim API.
---
![ROPC](../../ropc.png)

# User Authentication (Resource Owner Password Flow)

Expand Down
50 changes: 50 additions & 0 deletions website/docs/user_documentation/client-api-admin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
sidebar_position: 1
title: Administration
---

# Administrate your API Client credentials
Administrate your credentials in the `/system` administration panel. You will be able there to
- Create new credentials
- Edit credentials permissions
- Revoke credentials

## Create new credentials

To create new credentials, goes on the `Api Clients` menu.

![System Administration Dashboard of Decidim](./client-api-admin/2024-11-19_11-38.png)


You can then create a new credential clicking on `New Api Client`

![client Credential admin on Decidim](./client-api-admin/2024-11-19_11-40.png)

Now, define a name for credentials, to easily locate it later. Select an organization, to bind the credentials to one of the Decidim Organization (multi-tenant).

Finaly, define **scopes** to give the credential access to some part of your Decidim Data.

![client Credential admin on Decidim](./client-api-admin/2024-11-19_11-42.png)


Once created, you lend on the edition screen of the credentials.

## Edit a credential
You can define fine-grained permissions on the created credentials.
In this screen, you can also use the `client_id` and `client_secret` used to authenticate you.



![client Credential edition admin on Decidim](./client-api-admin/2024-11-19_11-45.png)
:::info
Fine-grained permissions are editable after the credential creation,
**scopes** are not. If you need to add a new scope, you need to revoke the credentials, and create a new one.
:::

## Revoke a credential
At anytime, you can revoke a credentials. This will permantly and immediatly remove access of this client.
Generated token by this credentials won't be valid anymore, even they are still before date of expiration.

![Revoke client credential](./client-api-admin/2024-11-19_11-46.png)

![Revoke client credential](./client-api-admin/2024-11-19_11-47.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion website/src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}

img{
max-width:520px;
max-width:720px;
}
.full > p > img {
max-width: 100%;;
Expand Down

0 comments on commit c52553c

Please sign in to comment.