From 2c70903dfd1fb4b78318cf6251d28dad762272d8 Mon Sep 17 00:00:00 2001 From: Nicolas Florentin Date: Mon, 9 May 2016 18:15:04 +0200 Subject: [PATCH] admin open_api_client managing --- .../admin/open_api_clients.coffee.erb | 87 +++++++++++++++++++ .../controllers/main_nav.coffee.erb | 5 ++ app/assets/javascripts/router.coffee.erb | 15 +++- .../services/open_api_client.coffee | 11 +++ .../admin/open_api_clients/index.html.erb | 74 ++++++++++++++++ .../templates/shared/_member_form.html.erb | 2 - .../api/open_api_clients_controller.rb | 46 ++++++++++ app/policies/open_api/client_policy.rb | 21 +++++ .../open_api_clients/_client.json.jbuilder | 1 + .../api/open_api_clients/create.json.jbuilder | 1 + .../api/open_api_clients/index.json.jbuilder | 3 + .../reset_token.json.jbuilder | 1 + .../api/open_api_clients/update.json.jbuilder | 1 + config/locales/app.admin.fr.yml | 14 +++ config/locales/app.public.en.yml | 1 + config/locales/app.public.fr.yml | 1 + config/routes.rb | 3 + 17 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/controllers/admin/open_api_clients.coffee.erb create mode 100644 app/assets/javascripts/services/open_api_client.coffee create mode 100644 app/assets/templates/admin/open_api_clients/index.html.erb create mode 100644 app/controllers/api/open_api_clients_controller.rb create mode 100644 app/policies/open_api/client_policy.rb create mode 100644 app/views/api/open_api_clients/_client.json.jbuilder create mode 100644 app/views/api/open_api_clients/create.json.jbuilder create mode 100644 app/views/api/open_api_clients/index.json.jbuilder create mode 100644 app/views/api/open_api_clients/reset_token.json.jbuilder create mode 100644 app/views/api/open_api_clients/update.json.jbuilder diff --git a/app/assets/javascripts/controllers/admin/open_api_clients.coffee.erb b/app/assets/javascripts/controllers/admin/open_api_clients.coffee.erb new file mode 100644 index 000000000..2f2cd6e24 --- /dev/null +++ b/app/assets/javascripts/controllers/admin/open_api_clients.coffee.erb @@ -0,0 +1,87 @@ +Application.Controllers.controller "OpenAPIClientsController", ["$scope", 'clientsPromise', 'growl', 'OpenAPIClient', 'dialogs', '_t' +, ($scope, clientsPromise, growl, OpenAPIClient, dialogs, _t) -> + + + + ### PUBLIC SCOPE ### + + ## clients list + $scope.clients = clientsPromise + $scope.order = null + $scope.clientFormVisible = false + $scope.client = {} + + $scope.toggleForm = -> + $scope.clientFormVisible = !$scope.clientFormVisible + + + # Change the order criterion to the one provided + # @param orderBy {string} ordering criterion + ## + $scope.setOrder = (orderBy)-> + if $scope.order == orderBy + $scope.order = '-'+orderBy + else + $scope.order = orderBy + + $scope.saveClient = (client)-> + if client.id? + OpenAPIClient.update { id: client.id }, open_api_client: client, (clientResp)-> + client = clientResp + growl.success(_t('client_successfully_updated')) + else + OpenAPIClient.save open_api_client: client, (client)-> + $scope.clients.push client + growl.success(_t('client_successfully_created')) + + + $scope.clientFormVisible = false + $scope.clientForm.$setPristine() + $scope.client = {} + + $scope.editClient = (client)-> + $scope.clientFormVisible = true + $scope.client = client + + $scope.deleteClient = (index)-> + dialogs.confirm + resolve: + object: -> + title: _t('confirmation_required') + msg: _t('do_you_really_want_to_delete_this_open_api_client') + , -> + OpenAPIClient.delete { id: $scope.clients[index].id }, -> + $scope.clients.splice(index, 1) + growl.success(_t('client_successfully_deleted')) + + $scope.resetToken = (client)-> + dialogs.confirm + resolve: + object: -> + title: _t('confirmation_required') + msg: _t('do_you_really_want_to_revoke_this_open_api_access') + , -> + OpenAPIClient.resetToken { id: client.id }, {}, (clientResp)-> + client.token = clientResp.token + growl.success(_t('access_successfully_revoked')) + + + ## + # Ask for confirmation then delete the specified administrator + # @param admins {Array} full list of administrators + # @param admin {Object} administrator to delete + ## + $scope.destroyAdmin = (admins, admin)-> + dialogs.confirm + resolve: + object: -> + title: _t('confirmation_required') + msg: _t('do_you_really_want_to_delete_this_administrator_this_cannot_be_undone') + , -> # cancel confirmed + Admin.delete id: admin.id, -> + admins.splice(findAdminIdxById(admins, admin.id), 1) + growl.success(_t('administrator_successfully_deleted')) + , (error)-> + growl.error(_t('unable_to_delete_the_administrator')) + +] diff --git a/app/assets/javascripts/controllers/main_nav.coffee.erb b/app/assets/javascripts/controllers/main_nav.coffee.erb index 96b1c5775..f69cbbf67 100644 --- a/app/assets/javascripts/controllers/main_nav.coffee.erb +++ b/app/assets/javascripts/controllers/main_nav.coffee.erb @@ -95,5 +95,10 @@ Application.Controllers.controller "MainNavController", ["$scope", "$location", linkText: 'customization' linkIcon: 'gear' } + { + state: 'app.admin.open_api_clients' + linkText: 'open_api_clients' + linkIcon: 'cloud' + } ] ] diff --git a/app/assets/javascripts/router.coffee.erb b/app/assets/javascripts/router.coffee.erb index ed28c6779..a647a295a 100644 --- a/app/assets/javascripts/router.coffee.erb +++ b/app/assets/javascripts/router.coffee.erb @@ -352,7 +352,6 @@ angular.module('application.router', ['ui.router']). translations: [ 'Translations', (Translations) -> Translations.query(['app.admin.machines_edit', 'app.shared.machine']).$promise ] - # trainings .state 'app.logged.trainings_reserve', url: '/trainings/reserve' @@ -840,5 +839,19 @@ angular.module('application.router', ['ui.router']). Translations.query('app.admin.settings').$promise ] + # OpenAPI Clients + .state 'app.admin.open_api_clients', + url: '/open_api_clients' + views: + 'main@': + templateUrl: '<%= asset_path "admin/open_api_clients/index.html" %>' + controller: 'OpenAPIClientsController' + resolve: + clientsPromise: ['OpenAPIClient', (OpenAPIClient)-> + OpenAPIClient.query().$promise + ] + translations: [ 'Translations', (Translations) -> + Translations.query('app.admin.open_api_clients').$promise + ] ] diff --git a/app/assets/javascripts/services/open_api_client.coffee b/app/assets/javascripts/services/open_api_client.coffee new file mode 100644 index 000000000..03e0f0abc --- /dev/null +++ b/app/assets/javascripts/services/open_api_client.coffee @@ -0,0 +1,11 @@ +'use strict' + +Application.Services.factory 'OpenAPIClient', ["$resource", ($resource)-> + $resource "/api/open_api_clients/:id", + {id: "@id"}, + resetToken: + method: 'PATCH' + url: "/api/open_api_clients/:id/reset_token" + update: + method: 'PUT' +] diff --git a/app/assets/templates/admin/open_api_clients/index.html.erb b/app/assets/templates/admin/open_api_clients/index.html.erb new file mode 100644 index 000000000..d1ce762db --- /dev/null +++ b/app/assets/templates/admin/open_api_clients/index.html.erb @@ -0,0 +1,74 @@ +
+
+
+
+ +
+
+
+
+

{{ 'open_api_clients' }}

+
+
+ +
+
+ +
+
+
+
+ + + +
+
+ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
{{ 'name' | translate }} {{ 'calls_count' | translate }} {{ 'token' | translate }}{{ 'created_at' | translate }}
{{ client.name }}{{ client.calls_count }}{{ client.token }}{{ client.created_at | amDateFormat: 'LL' }} +
+ + + + + +
+
+
+
+
+
diff --git a/app/assets/templates/shared/_member_form.html.erb b/app/assets/templates/shared/_member_form.html.erb index a62e0cf64..6c8cd52f5 100644 --- a/app/assets/templates/shared/_member_form.html.erb +++ b/app/assets/templates/shared/_member_form.html.erb @@ -239,5 +239,3 @@ - - diff --git a/app/controllers/api/open_api_clients_controller.rb b/app/controllers/api/open_api_clients_controller.rb new file mode 100644 index 000000000..6a72ba4d1 --- /dev/null +++ b/app/controllers/api/open_api_clients_controller.rb @@ -0,0 +1,46 @@ +class API::OpenAPIClientsController < API::ApiController + before_action :authenticate_user! + + def index + authorize OpenAPI::Client + @clients = OpenAPI::Client.order(:created_at) + end + # add authorization + def create + @client = OpenAPI::Client.new(client_params) + authorize @client + if @client.save + render status: :created + else + render json: @client.errors, status: :unprocessable_entity + end + end + + def update + @client = OpenAPI::Client.find(params[:id]) + authorize @client + if @client.update(client_params) + render status: :ok + else + render json: @client.errors, status: :unprocessable_entity + end + end + + def reset_token + @client = OpenAPI::Client.find(params[:id]) + authorize @client + @client.regenerate_token + end + + def destroy + @client = OpenAPI::Client.find(params[:id]) + authorize @client + @client.destroy + head 204 + end + + private + def client_params + params.require(:open_api_client).permit(:name) + end +end diff --git a/app/policies/open_api/client_policy.rb b/app/policies/open_api/client_policy.rb new file mode 100644 index 000000000..f2c850eff --- /dev/null +++ b/app/policies/open_api/client_policy.rb @@ -0,0 +1,21 @@ +class OpenAPI::ClientPolicy < ApplicationPolicy + def index? + user.has_role? :admin + end + + def create? + user.has_role? :admin + end + + def update? + user.has_role? :admin + end + + def reset_token? + user.has_role? :admin + end + + def destroy? + user.has_role? :admin and record.calls_count == 0 + end +end diff --git a/app/views/api/open_api_clients/_client.json.jbuilder b/app/views/api/open_api_clients/_client.json.jbuilder new file mode 100644 index 000000000..d074fe8cb --- /dev/null +++ b/app/views/api/open_api_clients/_client.json.jbuilder @@ -0,0 +1 @@ +json.extract! client, :id, :name, :calls_count, :token, :created_at diff --git a/app/views/api/open_api_clients/create.json.jbuilder b/app/views/api/open_api_clients/create.json.jbuilder new file mode 100644 index 000000000..467fb8a7a --- /dev/null +++ b/app/views/api/open_api_clients/create.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'api/open_api_clients/client', client: @client diff --git a/app/views/api/open_api_clients/index.json.jbuilder b/app/views/api/open_api_clients/index.json.jbuilder new file mode 100644 index 000000000..c1b98a76b --- /dev/null +++ b/app/views/api/open_api_clients/index.json.jbuilder @@ -0,0 +1,3 @@ +json.array! @clients do |client| + json.partial! 'api/open_api_clients/client', client: client +end diff --git a/app/views/api/open_api_clients/reset_token.json.jbuilder b/app/views/api/open_api_clients/reset_token.json.jbuilder new file mode 100644 index 000000000..467fb8a7a --- /dev/null +++ b/app/views/api/open_api_clients/reset_token.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'api/open_api_clients/client', client: @client diff --git a/app/views/api/open_api_clients/update.json.jbuilder b/app/views/api/open_api_clients/update.json.jbuilder new file mode 100644 index 000000000..467fb8a7a --- /dev/null +++ b/app/views/api/open_api_clients/update.json.jbuilder @@ -0,0 +1 @@ +json.partial! 'api/open_api_clients/client', client: @client diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 6cbe34d37..7eee350bc 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -463,3 +463,17 @@ fr: reservations_cancelling: "Annulation des réservations" customization_of_SETTING_successfully_saved: "La personnalisation de {{SETTING}} a bien été enregistrée." # angular interpolation file_successfully_updated: "Le fichier a bien été mis à jour." + + open_api_clients: + add_new_client: "Créer un compte client" + open_api_clients: "Clients OpenAPI" + calls_count: "Nombre d'appels" + created_at: "Date de création" + reset_token: "Révoquer l'accès" + client_name: "Nom du client" + do_you_really_want_to_delete_this_open_api_client: "Voulez vous vraiment supprimer ce compte client OpenAPI ?" + do_you_really_want_to_revoke_this_open_api_access: "Voulez vous vraiment revoquer l'accès de ce compte OpenAPI ? Une confirmation aura pour effet la génération d'un nouveau token." + client_successfully_created: "Le compte client a bien été créé." + client_successfully_updated: "Les modifications ont été enregistrées." + client_successfully_deleted: "Le compte client a bien été supprimé." + access_successfully_revoked: "L'accès a bien été revoqué." diff --git a/config/locales/app.public.en.yml b/config/locales/app.public.en.yml index c5eba66da..09f5f1570 100644 --- a/config/locales/app.public.en.yml +++ b/config/locales/app.public.en.yml @@ -43,6 +43,7 @@ en: manage_the_projects_elements: "Manage the Projects Elements" statistics: "Statistics" customization: "Customization" + open_api_clients: "OpenAPI clients" # account creation modal create_your_account: "Create your account" diff --git a/config/locales/app.public.fr.yml b/config/locales/app.public.fr.yml index a3c513cb9..38352d261 100644 --- a/config/locales/app.public.fr.yml +++ b/config/locales/app.public.fr.yml @@ -43,6 +43,7 @@ fr: manage_the_projects_elements: "Gérer les éléments projets" statistics: "Statistiques" customization: "Personnalisation" + open_api_clients: "Clients OpenAPI" # fenêtre de création de compte create_your_account: "Créer votre compte" diff --git a/config/routes.rb b/config/routes.rb index 408ae44ff..e9a384f32 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -93,6 +93,9 @@ Rails.application.routes.draw do get 'active', action: 'active', on: :collection end resources :abuses, only: [:create] + resources :open_api_clients, only: [:index, :create, :update, :destroy] do + patch :reset_token, on: :member + end # i18n get 'translations/:locale/:state' => 'translations#show', :constraints => { :state => /[^\/]+/ } # allow dots in URL for 'state'