foreman_x509 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +619 -0
  3. data/README.md +38 -0
  4. data/Rakefile +47 -0
  5. data/app/controllers/foreman_x509/api/v2/base_controller.rb +12 -0
  6. data/app/controllers/foreman_x509/api/v2/certificates_controller.rb +59 -0
  7. data/app/controllers/foreman_x509/api/v2/generations_controller.rb +58 -0
  8. data/app/controllers/foreman_x509/api/v2/issuers_controller.rb +41 -0
  9. data/app/controllers/foreman_x509/api/v2/requests_controller.rb +32 -0
  10. data/app/controllers/foreman_x509/certificates_controller.rb +82 -0
  11. data/app/controllers/foreman_x509/generations_controller.rb +71 -0
  12. data/app/controllers/foreman_x509/issuers_controller.rb +49 -0
  13. data/app/controllers/foreman_x509/requests_controller.rb +17 -0
  14. data/app/helpers/foreman_x509/certificates_helper.rb +49 -0
  15. data/app/models/concerns/foreman_x509/digest.rb +11 -0
  16. data/app/models/concerns/foreman_x509/extensions.rb +20 -0
  17. data/app/models/concerns/foreman_x509/subject.rb +23 -0
  18. data/app/models/foreman_x509/certificate.rb +75 -0
  19. data/app/models/foreman_x509/generation.rb +61 -0
  20. data/app/models/foreman_x509/issuer.rb +87 -0
  21. data/app/models/foreman_x509/request.rb +40 -0
  22. data/app/services/foreman_x509/builder.rb +86 -0
  23. data/app/services/foreman_x509/serializer/big_number.rb +13 -0
  24. data/app/services/foreman_x509/serializer/certificate.rb +15 -0
  25. data/app/services/foreman_x509/serializer/certificate_revocation_list.rb +14 -0
  26. data/app/services/foreman_x509/serializer/configuration.rb +13 -0
  27. data/app/services/foreman_x509/serializer/key.rb +13 -0
  28. data/app/services/foreman_x509/serializer/request.rb +13 -0
  29. data/app/views/foreman_x509/api/v2/certificates/base.json.rabl +3 -0
  30. data/app/views/foreman_x509/api/v2/certificates/index.json.rabl +3 -0
  31. data/app/views/foreman_x509/api/v2/certificates/show.json.rabl +9 -0
  32. data/app/views/foreman_x509/api/v2/generations/base.json.rabl +11 -0
  33. data/app/views/foreman_x509/api/v2/generations/index.json.rabl +0 -0
  34. data/app/views/foreman_x509/api/v2/generations/show.json.rabl +7 -0
  35. data/app/views/foreman_x509/api/v2/issuers/base.json.rabl +3 -0
  36. data/app/views/foreman_x509/api/v2/issuers/index.json.rabl +3 -0
  37. data/app/views/foreman_x509/api/v2/requests/show.json.rabl +16 -0
  38. data/app/views/foreman_x509/certificates/_form.html.erb +12 -0
  39. data/app/views/foreman_x509/certificates/_generations.html.erb +32 -0
  40. data/app/views/foreman_x509/certificates/index.html.erb +34 -0
  41. data/app/views/foreman_x509/certificates/new.html.erb +3 -0
  42. data/app/views/foreman_x509/certificates/show.html.erb +31 -0
  43. data/app/views/foreman_x509/generations/edit.html.erb +8 -0
  44. data/app/views/foreman_x509/issuers/index.html.erb +24 -0
  45. data/app/views/foreman_x509/issuers/new.html.erb +0 -0
  46. data/app/views/foreman_x509/issuers/show.html.erb +52 -0
  47. data/app/views/foreman_x509/requests/show.html.erb +15 -0
  48. data/config/routes.rb +68 -0
  49. data/db/migrate/20250201155706_initialize_foreman_x509_schema.rb +37 -0
  50. data/db/migrate/20250401083842_create_foreman_x509_requests.rb +14 -0
  51. data/lib/foreman_x509/engine.rb +47 -0
  52. data/lib/foreman_x509/plugin.rb +30 -0
  53. data/lib/foreman_x509/version.rb +3 -0
  54. data/lib/foreman_x509.rb +4 -0
  55. data/lib/tasks/foreman_x509_tasks.rake +31 -0
  56. data/locale/Makefile +73 -0
  57. data/locale/en/foreman_x509.po +19 -0
  58. data/locale/foreman_x509.pot +19 -0
  59. data/locale/gemspec.rb +2 -0
  60. data/package.json +41 -0
  61. data/test/factories/foreman_x509_factories.rb +5 -0
  62. data/test/test_plugin_helper.rb +6 -0
  63. data/test/unit/foreman_x509_test.rb +11 -0
  64. data/webpack/global_index.js +17 -0
  65. data/webpack/global_test_setup.js +11 -0
  66. data/webpack/index.js +8 -0
  67. data/webpack/src/Components/EmptyState/Constants.js +2 -0
  68. data/webpack/src/Components/EmptyState/EmptyStateReducer.js +19 -0
  69. data/webpack/src/Components/EmptyState/ExtendedEmptyState.js +43 -0
  70. data/webpack/src/Components/EmptyState/__tests__/ExtendedEmptyState.test.js +37 -0
  71. data/webpack/src/Extends/index.js +15 -0
  72. data/webpack/src/Router/WelcomePage/Welcome.js +9 -0
  73. data/webpack/src/Router/WelcomePage/index.js +1 -0
  74. data/webpack/src/Router/routes.js +12 -0
  75. data/webpack/src/reducers.js +10 -0
  76. data/webpack/test_setup.js +17 -0
  77. metadata +168 -0
data/config/routes.rb ADDED
@@ -0,0 +1,68 @@
1
+ ForemanX509::Engine.routes.draw do
2
+ namespace :api do
3
+ scope '(:apiv)', module: :v2, defaults: { apiv: 'v2' }, apiv: /v1|v2/, constraints: ApiConstraints.new(version: 2, default: true) do
4
+
5
+ resources :issuers, only: [:index, :create, :show, :update, :destroy] do
6
+ member do
7
+ get :bundle
8
+ end
9
+ end
10
+
11
+ resources :requests, only: [:index, :show]
12
+
13
+ resources :certificates, only: [], param: :owner_id do
14
+ member do
15
+ resources :generations, only: [:index, :create, :update, :destroy] do
16
+ member do
17
+ get :certificate
18
+ get :key
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ resources :certificates, only: [:index, :create, :show, :update, :destroy] do
25
+ member do
26
+ get :chain
27
+ get :certificate
28
+ get :key
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ constraints(id: /[^\/]+/) do
35
+ resources :issuers, only: [:index, :new, :create, :show, :destroy ] do
36
+ member do
37
+ get :bundle
38
+ end
39
+ end
40
+
41
+ resources :requests, only: [:show]
42
+
43
+ constraints(owner_id: /[^\/]+/) do
44
+ resources :certificates, only: [], param: :owner_id do
45
+ member do
46
+ resources :generations, only: [:new, :create, :update, :destroy] do
47
+ member do
48
+ get :certificate
49
+ get :key
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ resources :certificates do
57
+ member do
58
+ get :chain
59
+ get :certificate
60
+ get :key
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ Foreman::Application.routes.draw do
67
+ mount ForemanX509::Engine, at: '/foreman_x509'
68
+ end
@@ -0,0 +1,37 @@
1
+ class InitializeForemanX509Schema < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :foreman_x509_certificates do |t|
4
+ t.string :name, null: false
5
+ t.string :description
6
+ t.bigint :issuer_id
7
+ t.text :configuration
8
+
9
+ t.timestamps
10
+ end
11
+
12
+ add_index :foreman_x509_certificates, :name, unique: true, name: :foreman_x509_certificates_by_name
13
+
14
+ create_table :foreman_x509_generations do |t|
15
+ t.bigint :owner_id, null: false
16
+ t.boolean :active, null: false, default: false
17
+ t.text :certificate
18
+ t.text :request
19
+ t.text :key
20
+
21
+ t.timestamps
22
+ end
23
+
24
+ create_table :foreman_x509_issuers do |t|
25
+ t.bigint :certificate_id, null: false
26
+ t.string :serial
27
+ t.bigint :crl_number
28
+ t.text :certificate_revocation_list
29
+
30
+ t.timestamps
31
+ end
32
+
33
+ add_foreign_key :foreman_x509_certificates, :foreman_x509_issuers, column: :issuer_id, name: :foreman_x509_issuer_for_certificate, on_delete: :nullify
34
+ add_foreign_key :foreman_x509_generations, :foreman_x509_certificates, column: :owner_id, name: :foreman_x509_owner_for_generation, on_delete: :cascade
35
+ add_foreign_key :foreman_x509_issuers, :foreman_x509_certificates, column: :certificate_id, name: :foreman_x509_certificate_for_issuer
36
+ end
37
+ end
@@ -0,0 +1,14 @@
1
+ class CreateForemanX509Requests < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :foreman_x509_requests do |t|
4
+ t.bigint :certificate_id, null: false
5
+ t.bigint :generation_id, null: false
6
+ t.text :request
7
+ end
8
+
9
+ add_foreign_key :foreman_x509_requests, :foreman_x509_certificates, column: :certificate_id, name: :foreman_x509_request_for_certificate, on_delete: :cascade
10
+ add_foreign_key :foreman_x509_requests, :foreman_x509_generations, column: :generation_id, name: :foreman_x509_request_for_generation, on_delete: :cascade
11
+
12
+ remove_column :foreman_x509_generations, :request, :text
13
+ end
14
+ end
@@ -0,0 +1,47 @@
1
+ module ForemanX509
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace ForemanX509
4
+ engine_name 'foreman_x509'
5
+
6
+ config.autoload_paths += Dir["#{config.root}/app/models/concerns"]
7
+
8
+ # Add any db migrations
9
+ initializer 'foreman_x509.load_app_instance_data' do |app|
10
+ ForemanX509::Engine.paths['db/migrate'].existent.each do |path|
11
+ app.config.paths['db/migrate'] << path
12
+ end
13
+ end
14
+
15
+ initializer 'foreman_x509.register_mime_tyeps' do |app|
16
+ Mime::Type.register_alias "application/x-pem-file", :pem
17
+ Mime::Type.register_alias "application/x-x509-ca-cert", :der
18
+ end
19
+
20
+ initializer 'foreman_x509.register_plugin', :before => :finisher_hook do |app|
21
+ require 'foreman_x509/plugin'
22
+ end
23
+
24
+ # Include concerns in this config.to_prepare block
25
+ # config.to_prepare do
26
+ # Host::Managed.include ForemanX509::HostExtensions
27
+ # HostsHelper.include ForemanX509::HostsHelperExtensions
28
+ # rescue StandardError => e
29
+ # Rails.logger.warn "ForemanX509: skipping engine hook (#{e})"
30
+ # end
31
+
32
+ rake_tasks do
33
+ Rake::Task['db:seed'].enhance do
34
+ ForemanX509::Engine.load_seed
35
+ end
36
+ end
37
+ end
38
+
39
+ def self.table_name_prefix
40
+ 'foreman_x509_'
41
+ end
42
+
43
+
44
+ def self.use_relative_model_naming
45
+ true
46
+ end
47
+ end
@@ -0,0 +1,30 @@
1
+ Foreman::Plugin.register :foreman_x509 do
2
+ requires_foreman '>= 3.1.1'
3
+
4
+ # Add Global files for extending foreman-core components and routes
5
+ # register_global_js_file 'global'
6
+
7
+ # Add permissions
8
+ security_block :foreman_x509 do
9
+ # permission :view_foreman_x509_certificates, { :certificates => [:index, :show, :certificate, :key] }
10
+ # permission :create_foreman_x509_certificates, { :certificates => [:new, :create] }
11
+ # permission :destroy_foreman_x509_certificates, { :certificates => [:destroy] }
12
+ end
13
+
14
+ # Add a new role called 'Discovery' if it doesn't exist
15
+ #role 'ForemanX509', [:view_foreman_x509]
16
+
17
+ # add menu entries
18
+ divider :top_menu, caption: N_('Certificates'), parent: :infrastructure_menu
19
+ menu :top_menu, :issuers,
20
+ caption: N_('Issuers'),
21
+ engine: ForemanX509::Engine,
22
+ parent: :infrastructure_menu
23
+ menu :top_menu, :certificates,
24
+ caption: N_('Certificates'),
25
+ engine: ForemanX509::Engine,
26
+ parent: :infrastructure_menu
27
+
28
+ # add dashboard widget
29
+ # widget 'foreman_x509_widget', name: N_('Foreman plugin template widget'), sizex: 4, sizey: 1
30
+ end
@@ -0,0 +1,3 @@
1
+ module ForemanX509
2
+ VERSION = '0.0.1'.freeze
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'foreman_x509/engine'
2
+
3
+ module ForemanX509
4
+ end
@@ -0,0 +1,31 @@
1
+ require 'rake/testtask'
2
+
3
+ # Tasks
4
+ namespace :foreman_x509 do
5
+ namespace :example do
6
+ desc 'Example Task'
7
+ task task: :environment do
8
+ # Task goes here
9
+ end
10
+ end
11
+ end
12
+
13
+ # Tests
14
+ namespace :test do
15
+ desc 'Test ForemanX509'
16
+ Rake::TestTask.new(:foreman_x509) do |t|
17
+ test_dir = File.expand_path('../../test', __dir__)
18
+ t.libs << 'test'
19
+ t.libs << test_dir
20
+ t.pattern = "#{test_dir}/**/*_test.rb"
21
+ t.verbose = true
22
+ t.warning = false
23
+ end
24
+ end
25
+
26
+ Rake::Task[:test].enhance ['test:foreman_x509']
27
+
28
+ load 'tasks/jenkins.rake'
29
+ if Rake::Task.task_defined?(:'jenkins:unit')
30
+ Rake::Task['jenkins:unit'].enhance ['test:foreman_x509', 'foreman_x509:rubocop']
31
+ end
data/locale/Makefile ADDED
@@ -0,0 +1,73 @@
1
+ #
2
+ # Makefile for PO merging and MO generation. More info in the README.
3
+ #
4
+ # make all-mo (default) - generate MO files
5
+ # make check - check translations using translate-tool
6
+ # make tx-update - download and merge translations from Transifex
7
+ # make clean - clean everything
8
+ #
9
+ DOMAIN = $(shell ruby -rrubygems -e 'puts Gem::Specification::load(Dir.glob("../*.gemspec")[0]).name')
10
+ VERSION = $(shell ruby -rrubygems -e 'puts Gem::Specification::load(Dir.glob("../*.gemspec")[0]).version')
11
+ POTFILE = $(DOMAIN).pot
12
+ MOFILE = $(DOMAIN).mo
13
+ POFILES = $(shell find . -name '$(DOMAIN).po')
14
+ MOFILES = $(patsubst %.po,%.mo,$(POFILES))
15
+ POXFILES = $(patsubst %.po,%.pox,$(POFILES))
16
+ EDITFILES = $(patsubst %.po,%.edit.po,$(POFILES))
17
+ JSFILES = $(shell find ../app/assets/javascripts/*/locale -name '$(DOMAIN).js')
18
+
19
+ %.mo: %.po
20
+ mkdir -p $(shell dirname $@)/LC_MESSAGES
21
+ msgfmt -o $(shell dirname $@)/LC_MESSAGES/$(MOFILE) $<
22
+
23
+ # Generate MO files from PO files
24
+ all-mo: $(MOFILES)
25
+
26
+ # Check for malformed strings
27
+ %.pox: %.po
28
+ msgfmt -c $<
29
+ pofilter --nofuzzy -t variables -t blank -t urls -t emails -t long -t newlines \
30
+ -t endwhitespace -t endpunc -t puncspacing -t options -t printf -t validchars --gnome $< > $@
31
+ cat $@
32
+ ! grep -q msgid $@
33
+
34
+ %.edit.po: %.po.time_stamp
35
+ touch $@
36
+
37
+ # gettext will trash the .edit.po file if the time stamp doesn't exist or is older than the po file
38
+ %.po.time_stamp: %.po
39
+ touch --reference $< $@
40
+
41
+ # Prevent make from treating this as an intermediate file to be cleaned up
42
+ .PRECIOUS: %.po.time_stamp
43
+
44
+ check: $(POXFILES)
45
+
46
+ # Unify duplicate translations
47
+ uniq-po:
48
+ for f in $(shell find ./ -name "*.po") ; do \
49
+ msguniq $$f -o $$f ; \
50
+ done
51
+
52
+ tx-pull: $(EDITFILES)
53
+ # Initialize new languages
54
+ cd .. && tx pull -f --all --minimum-perc 50
55
+ # Force update all existing languages
56
+ cd .. && tx pull -f --minimum-perc 0
57
+ for f in $(EDITFILES) ; do \
58
+ sed -i 's/^\("Project-Id-Version: \).*$$/\1$(DOMAIN) $(VERSION)\\n"/' $$f; \
59
+ done
60
+
61
+ tx-update: tx-pull
62
+ @echo
63
+ @echo Run rake plugin:gettext[$(DOMAIN)] from the Foreman installation
64
+ @echo then run rake plugin:po_to_json[$(DOMAIN)] from the Foreman installation
65
+ @echo then run make -C locale mo-files to finish
66
+ @echo
67
+
68
+ mo-files: $(MOFILES)
69
+ git add $(POFILES) $(POTFILE) $(JSFILES) ../locale/*/LC_MESSAGES
70
+ git commit -m "i18n - pulling from tx"
71
+ @echo
72
+ @echo Changes commited!
73
+ @echo
@@ -0,0 +1,19 @@
1
+ # foreman_x509
2
+ #
3
+ # This file is distributed under the same license as foreman_x509.
4
+ #
5
+ #, fuzzy
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: version 0.0.1\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2014-08-20 08:46+0100\n"
11
+ "PO-Revision-Date: 2014-08-20 08:54+0100\n"
12
+ "Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
13
+ "Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
14
+ "Language: \n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
19
+
@@ -0,0 +1,19 @@
1
+ # foreman_x509
2
+ #
3
+ # This file is distributed under the same license as foreman_x509.
4
+ #
5
+ #, fuzzy
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: version 0.0.1\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2014-08-20 08:46+0100\n"
11
+ "PO-Revision-Date: 2014-08-20 08:46+0100\n"
12
+ "Last-Translator: Foreman Team <foreman-dev@googlegroups.com>\n"
13
+ "Language-Team: Foreman Team <foreman-dev@googlegroups.com>\n"
14
+ "Language: \n"
15
+ "MIME-Version: 1.0\n"
16
+ "Content-Type: text/plain; charset=UTF-8\n"
17
+ "Content-Transfer-Encoding: 8bit\n"
18
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
19
+
data/locale/gemspec.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Matches foreman_x509.gemspec
2
+ _('TODO: Description of ForemanX509.')
data/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "foreman_x509",
3
+ "version": "1.0.0",
4
+ "description": "DESCRIPTION",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "lint": "tfm-lint --plugin -d /webpack",
8
+ "test": "tfm-test --config jest.config.js",
9
+ "test:watch": "tfm-test --plugin --watchAll",
10
+ "test:current": "tfm-test --plugin --watch",
11
+ "publish-coverage": "tfm-publish-coverage",
12
+ "create-react-component": "yo react-domain"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/theforeman/foreman_x509.git"
17
+ },
18
+ "bugs": {
19
+ "url": "http://projects.theforeman.org/projects/foreman_x509/issues"
20
+ },
21
+ "peerDependencies": {
22
+ "@theforeman/vendor": ">= 6.0.0"
23
+ },
24
+ "dependencies": {
25
+ "react-intl": "^2.8.0"
26
+ },
27
+ "devDependencies": {
28
+ "@babel/core": "^7.7.0",
29
+ "@sheerun/mutationobserver-shim": "^0.3.3",
30
+ "@theforeman/builder": "^6.0.0",
31
+ "@theforeman/eslint-plugin-foreman": "6.0.0",
32
+ "@theforeman/find-foreman": "^4.8.0",
33
+ "@theforeman/test": "^8.0.0",
34
+ "@theforeman/vendor-dev": "^6.0.0",
35
+ "babel-eslint": "^10.0.3",
36
+ "eslint": "^6.7.2",
37
+ "prettier": "^1.19.1",
38
+ "stylelint-config-standard": "^18.0.0",
39
+ "stylelint": "^9.3.0"
40
+ }
41
+ }
@@ -0,0 +1,5 @@
1
+ FactoryBot.define do
2
+ factory :host do
3
+ name 'foreman_x509'
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ # This calls the main test_helper in Foreman-core
2
+ require 'test_helper'
3
+
4
+ # Add plugin to FactoryBot's paths
5
+ FactoryBot.definition_file_paths << File.join(File.dirname(__FILE__), 'factories')
6
+ FactoryBot.reload
@@ -0,0 +1,11 @@
1
+ require 'test_plugin_helper'
2
+
3
+ class ForemanX509Test < ActiveSupport::TestCase
4
+ setup do
5
+ User.current = User.find_by_login 'admin'
6
+ end
7
+
8
+ test 'the truth' do
9
+ assert true
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ import { registerReducer } from 'foremanReact/common/MountingService';
2
+ import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
3
+ import { registerRoutes } from 'foremanReact/routes/RoutingService';
4
+ import Routes from './src/Router/routes'
5
+ import reducers from './src/reducers';
6
+
7
+ // register reducers
8
+ Object.entries(reducers).forEach(([key, reducer]) =>
9
+ registerReducer(key, reducer)
10
+ );
11
+
12
+ // register client routes
13
+ registerRoutes('PluginTemplate', Routes);
14
+
15
+ // register fills for extending foreman core
16
+ // http://foreman.surge.sh/?path=/docs/introduction-slot-and-fill--page
17
+ addGlobalFill('<slotId>', '<fillId>', <div key='plugin-template-example' />, 300);
@@ -0,0 +1,11 @@
1
+ // runs before each test to make sure console.error output will
2
+ // fail a test (i.e. default PropType missing). Check the error
3
+ // output and traceback for actual error.
4
+ global.console.error = (error, stack) => {
5
+ /* eslint-disable-next-line no-console */
6
+ if (stack) console.log(stack); // Prints out original stack trace
7
+ throw new Error(error);
8
+ };
9
+
10
+ // Increase jest timeout as some tests using multiple http mocks can time out on CI systems.
11
+ jest.setTimeout(10000);
data/webpack/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import componentRegistry from 'foremanReact/components/componentRegistry';
2
+ import ExtendedEmptyState from './src/Components/EmptyState/ExtendedEmptyState';
3
+
4
+ // register components for erb mounting
5
+ componentRegistry.register({
6
+ name: 'ExtendedEmptyState',
7
+ type: ExtendedEmptyState,
8
+ });
@@ -0,0 +1,2 @@
1
+ export const GENERAL_ACTION_TYPE = '[PLUGIN_TEMPLATE] GENERAL ACTION';
2
+ export const FOREMAN_STORYBOOK = 'https://foreman.surge.sh';
@@ -0,0 +1,19 @@
1
+ // This is an example for a generic redux's reducer
2
+ // Reducers should be registered to foreman-core
3
+ // For a further registration demonstration, have a look in `webpack/global_index.js`
4
+
5
+ import Immutable from 'seamless-immutable';
6
+ import { GENERAL_ACTION_TYPE } from './Constants';
7
+
8
+ const initialState = Immutable({});
9
+
10
+ export default (state = initialState, action) => {
11
+ const { payload } = action;
12
+
13
+ switch (action.type) {
14
+ case GENERAL_ACTION_TYPE:
15
+ return state.set('generalProprty', payload);
16
+ default:
17
+ return state;
18
+ }
19
+ };
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import { Button, Alert } from '@patternfly/react-core';
3
+ import EmptyState from 'foremanReact/components/common/EmptyState/EmptyStatePattern';
4
+ import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader';
5
+ import PropTypes from 'prop-types';
6
+
7
+ import { STATUS } from 'foremanReact/constants'
8
+ import { useAPI } from 'foremanReact/common/hooks/API/APIHooks'
9
+ import { translate as __ } from 'foremanReact/common/I18n';
10
+ import { FOREMAN_STORYBOOK } from './Constants';
11
+
12
+ const ExtendedEmptyState = ({ header }) => {
13
+ // AJAX request using useAPI hook
14
+ const { response: { description }, status } = useAPI('get', '/foreman_x509/plugin_template_description')
15
+
16
+
17
+ const storybookBtn = (
18
+ <Button onClick={() => window.open(FOREMAN_STORYBOOK, '_blank')}>
19
+ Storybook
20
+ </Button>
21
+ );
22
+
23
+ switch (status) {
24
+ case STATUS.ERROR:
25
+ return (<Alert variant="danger" title={__("Loading description has failed")} />);
26
+ case STATUS.RESOLVED: return (
27
+ <EmptyState
28
+ icon="add-circle-o"
29
+ action={storybookBtn}
30
+ header={header}
31
+ description={description}
32
+ documentation={false}
33
+ />
34
+ )
35
+ default:
36
+ return (<SkeletonLoader isLoading={status === STATUS.PENDING} count={5} />);
37
+ }
38
+ };
39
+ ExtendedEmptyState.PropTypes = {
40
+ header: PropTypes.string.isRequired
41
+ };
42
+
43
+ export default ExtendedEmptyState;
@@ -0,0 +1,37 @@
1
+ // Tests work with react-testing-library or enzyme
2
+ // This test uses react testing library
3
+ // https://testing-library.com/docs/react-testing-library/api
4
+
5
+ // For more information, test utils, and snapshots testing examples:
6
+ // https://github.com/theforeman/foreman-js/tree/master/packages/test
7
+
8
+
9
+ import React from 'react';
10
+ import { createStore, applyMiddleware, combineReducers } from 'redux';
11
+ import { render, waitFor, screen } from '@testing-library/react'
12
+ import { Provider } from 'react-redux';
13
+
14
+ import { reducers as APIReducer } from 'foremanReact/redux/API';
15
+ import { middlewares } from 'foremanReact/redux/middlewares';
16
+ import APIHelper from 'foremanReact/redux/API/API';
17
+ import ExtendedEmptyState from '../ExtendedEmptyState';
18
+
19
+ jest.mock('foremanReact/redux/API/API');
20
+
21
+ const reducers = combineReducers(APIReducer);
22
+ const store = createStore(reducers, applyMiddleware(...middlewares));
23
+ const wrapper = ({ children }) => (
24
+ <Provider store={store}>{children}</Provider>
25
+ );
26
+ describe('foreman plugin template', () => {
27
+ it('should render an error alert', async () => {
28
+ APIHelper.get.mockRejectedValue({ error: new Error() });
29
+ render(<ExtendedEmptyState />, { wrapper });
30
+ await waitFor(() => expect(screen.getByText('Loading description has failed')).toBeInTheDocument());
31
+ });
32
+ it('should render an empty state with custom description', async () => {
33
+ APIHelper.get.mockResolvedValue({ data: { description: 'some description' } });
34
+ render(<ExtendedEmptyState />, { wrapper });
35
+ await waitFor(() => expect(screen.getByText('some description')).toBeInTheDocument());
36
+ });
37
+ });
@@ -0,0 +1,15 @@
1
+ // This is an example of extending foreman-core's component via slot&fill
2
+ // http://foreman.surge.sh/?path=/docs/introduction-slot-and-fill--page
3
+ /*
4
+ import React from 'react';
5
+ import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
6
+
7
+ addGlobalFill('slotId', 'fillId', <SomeComponent key="some-key" />, 300);
8
+
9
+ addGlobalFill(
10
+ 'slotId',
11
+ 'fillId',
12
+ { someProp: 'this is an override prop' },
13
+ 300
14
+ );
15
+ */
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import ExtendedEmptyState from '../../Components/EmptyState/ExtendedEmptyState';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+
5
+ const WelcomePage = () => (
6
+ <ExtendedEmptyState header={__("Welcome to the plugin template")} />
7
+ );
8
+
9
+ export default WelcomePage;
@@ -0,0 +1 @@
1
+ export { default } from './Welcome';
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import WelcomePage from './WelcomePage';
3
+
4
+ const routes = [
5
+ {
6
+ path: '/foreman_x509/welcome',
7
+ exact: true,
8
+ render: (props) => <WelcomePage {...props} />,
9
+ },
10
+ ];
11
+
12
+ export default routes;
@@ -0,0 +1,10 @@
1
+ import { combineReducers } from 'redux';
2
+ import EmptyStateReducer from './Components/EmptyState/EmptyStateReducer';
3
+
4
+ const reducers = {
5
+ foremanX509: combineReducers({
6
+ emptyState: EmptyStateReducer,
7
+ }),
8
+ };
9
+
10
+ export default reducers;
@@ -0,0 +1,17 @@
1
+ import 'core-js/shim';
2
+ import 'regenerator-runtime/runtime';
3
+ import MutationObserver from '@sheerun/mutationobserver-shim';
4
+
5
+ import { configure } from 'enzyme';
6
+ import Adapter from 'enzyme-adapter-react-16';
7
+
8
+ configure({ adapter: new Adapter() });
9
+
10
+ // Mocking translation function
11
+ global.__ = text => text; // eslint-disable-line
12
+
13
+ // Mocking locales to prevent unnecessary fallback messages
14
+ window.locales = { en: { domain: 'app', locale_data: { app: { '': {} } } } };
15
+
16
+ // see https://github.com/testing-library/dom-testing-library/releases/tag/v7.0.0
17
+ window.MutationObserver = MutationObserver;