diff --git a/.github/workflows/ci.build.prerelease.yml b/.github/workflows/ci.build.prerelease.yml index 2fbe331d..4fc19859 100644 --- a/.github/workflows/ci.build.prerelease.yml +++ b/.github/workflows/ci.build.prerelease.yml @@ -47,7 +47,7 @@ jobs: - name: Build and Push pre-release if: contains(env.DOCKER_BUILD_ENABLED, 'true') - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: push: true tags: | diff --git a/.github/workflows/ci.build.push.yml b/.github/workflows/ci.build.push.yml index 3990b149..b00104f1 100644 --- a/.github/workflows/ci.build.push.yml +++ b/.github/workflows/ci.build.push.yml @@ -60,7 +60,7 @@ jobs: - name: Build and Push branch if: contains(env.DOCKER_BUILD_ENABLED, 'true') - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: push: true tags: | diff --git a/.github/workflows/ci.build.release.yml b/.github/workflows/ci.build.release.yml index c06ca447..50333a41 100644 --- a/.github/workflows/ci.build.release.yml +++ b/.github/workflows/ci.build.release.yml @@ -47,7 +47,7 @@ jobs: - name: Build and Push release if: contains(env.DOCKER_BUILD_ENABLED, 'true') - uses: docker/build-push-action@v3 + uses: docker/build-push-action@v5 with: push: true tags: | diff --git a/lib/tasks/apps.rake b/lib/tasks/apps.rake new file mode 100644 index 00000000..cf204688 --- /dev/null +++ b/lib/tasks/apps.rake @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require 'securerandom' +require 'uri' +require 'bbb_lti_broker/helpers' + +namespace :apps do + desc 'Add a new blti app - add[name,hostname,uid,secret]' + task :add, [:name, :hostname, :uid, :secret] => :environment do |_t, args| + include BbbLtiBroker::Helpers + Rake::Task['environment'].invoke + ActiveRecord::Base.connection + unless args[:name] + puts('No app name provided') + exit(1) + end + blti_apps = Doorkeeper::Application.where(name: args[:name]) + unless blti_apps.empty? + puts("App '#{args[:name]}' already exists, it can not be added") + exit(1) + end + unless args[:hostname] + puts("Parameters hostname is required, app '#{args[:name]}' can not be added") + exit(1) + end + puts("Adding '#{args.to_hash}'") + uid = args.[](:uid) || SecureRandom.hex(32) + secret = args.[](:secret) || SecureRandom.hex(32) + + redirect_uri = (args[:hostname]).to_s + app = Doorkeeper::Application.create!(name: args[:name], uid: uid, secret: secret, \ + redirect_uri: redirect_uri, scopes: 'api') + app1 = app.attributes.select { |key, _value| %w[name uid secret redirect_uri].include?(key) } + puts("Added '#{app1.to_json}'") + rescue StandardError => e + puts(e.backtrace) + exit(1) + end + + desc 'Update an existent blti app if exists - update[name,redirect_uris,uid,secret]. redirect_uris is a list of callback uris separated by "\,"' + task :update, [:name, :redirect_uris, :uid, :secret] => :environment do |_t, args| + include BbbLtiBroker::Helpers + Rake::Task['environment'].invoke + ActiveRecord::Base.connection + unless args[:name] + puts('No app name provided') + exit(1) + end + app = Doorkeeper::Application.find_by(name: args[:name]) + if app.nil? + puts("App '#{args[:name]}' does not exist, it can not be updated") + exit(1) + end + puts("Updating '#{args.to_hash}'") + app.update!(uid: args[:uid]) if args.[](:uid) + app.update!(secret: args[:secret]) if args.[](:secret) + + redirect_uri = (args[:redirect_uris]).gsub(',', "\r\n") + puts("redirect_uri:\n#{redirect_uri}") + app.update!(redirect_uri: redirect_uri) if args.[](:redirect_uris) + app_updated = app.attributes.select { |key, _value| %w[name uid secret redirect_uri].include?(key) } + puts("Updated '#{app_updated.to_json}'") + rescue StandardError => e + puts(e.backtrace) + exit(1) + end + + desc 'Delete an existent blti app if exists - delete[name]' + task :delete, [:name] => :environment do |_t, args| + include BbbLtiBroker::Helpers + Rake::Task['environment'].invoke + ActiveRecord::Base.connection + unless args[:name] + puts('No app name provided') + exit(1) + end + blti_apps = Doorkeeper::Application.where(name: args[:name]) + if blti_apps.empty? + puts("App '#{args[:name]}' does not exist, it can not be deleted") + exit(1) + end + blti_apps.each(&:destroy) + puts("Apps with name '#{args[:name]}' were successfully destroyed") + rescue StandardError => e + puts(e.backtrace) + exit(1) + end + + desc 'Show an existent blti app if exists - show[name]' + task :show, [:name] => :environment do |_t, args| + include BbbLtiBroker::Helpers + Rake::Task['environment'].invoke + ActiveRecord::Base.connection + unless args[:name] + puts('No app name provided') + exit(1) + end + apps = Doorkeeper::Application.where(name: args[:name]) + if apps.empty? + puts("App '#{args[:name]}' does not exist, it can not be shown") + exit(1) + end + apps.each do |app| + app1 = app.attributes.select { |key, _value| %w[name uid secret redirect_uri].include?(key) } + puts(app1.to_json) + end + rescue StandardError => e + puts(e.backtrace) + exit(1) + end + + desc 'Delete all existent blti apps' + task :deleteall, [] => :environment do + include BbbLtiBroker::Helpers + Rake::Task['environment'].invoke + ActiveRecord::Base.connection + Doorkeeper::Application.delete_all + puts('All the registered apps were deleted') + rescue StandardError => e + puts(e.backtrace) + exit(1) + end + + desc 'Show all existent blti apps' + task :showall, [] => :environment do + include BbbLtiBroker::Helpers + Rake::Task['environment'].invoke + ActiveRecord::Base.connection + apps = Doorkeeper::Application.all + apps.each do |app| + app1 = app.attributes.select { |key, _value| %w[name uid secret redirect_uri].include?(key) } + puts(app1.to_json) + end + rescue ApplicationRedisRecord::RecordNotFound + puts(e.backtrace) + exit(1) + end +end diff --git a/lib/tasks/db_exists.rake b/lib/tasks/db.rake similarity index 100% rename from lib/tasks/db_exists.rake rename to lib/tasks/db.rake diff --git a/lib/tasks/db_apps.rake b/lib/tasks/db_apps.rake deleted file mode 100644 index 02863b4f..00000000 --- a/lib/tasks/db_apps.rake +++ /dev/null @@ -1,140 +0,0 @@ -# frozen_string_literal: true - -require 'securerandom' -require 'uri' -require 'bbb_lti_broker/helpers' - -namespace :db do - namespace :apps do - desc 'Add a new blti app - add[name,hostname,uid,secret]' - task :add, [:name, :hostname, :uid, :secret] => :environment do |_t, args| - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - unless args[:name] - puts('No app name provided') - exit(1) - end - blti_apps = Doorkeeper::Application.where(name: args[:name]) - unless blti_apps.empty? - puts("App '#{args[:name]}' already exists, it can not be added") - exit(1) - end - unless args[:hostname] - puts("Parameters hostname is required, app '#{args[:name]}' can not be added") - exit(1) - end - puts("Adding '#{args.to_hash}'") - uid = args.[](:uid) || SecureRandom.hex(32) - secret = args.[](:secret) || SecureRandom.hex(32) - - redirect_uri = (args[:hostname]).to_s - app = Doorkeeper::Application.create!(name: args[:name], uid: uid, secret: secret, \ - redirect_uri: redirect_uri, scopes: 'api') - app1 = app.attributes.select { |key, _value| %w[name uid secret redirect_uri].include?(key) } - puts("Added '#{app1.to_json}'") - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc 'Update an existent blti app if exists - update[name,redirect_uris,uid,secret]. redirect_uris is a list of callback uris separated by "\,"' - task :update, [:name, :redirect_uris, :uid, :secret] => :environment do |_t, args| - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - unless args[:name] - puts('No app name provided') - exit(1) - end - app = Doorkeeper::Application.find_by(name: args[:name]) - if app.nil? - puts("App '#{args[:name]}' does not exist, it can not be updated") - exit(1) - end - puts("Updating '#{args.to_hash}'") - app.update!(uid: args[:uid]) if args.[](:uid) - app.update!(secret: args[:secret]) if args.[](:secret) - - redirect_uri = (args[:redirect_uris]).gsub(',', "\r\n") - puts("redirect_uri:\n#{redirect_uri}") - app.update!(redirect_uri: redirect_uri) if args.[](:redirect_uris) - app_updated = app.attributes.select { |key, _value| %w[name uid secret redirect_uri].include?(key) } - puts("Updated '#{app_updated.to_json}'") - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc 'Delete an existent blti app if exists - delete[name]' - task :delete, [:name] => :environment do |_t, args| - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - unless args[:name] - puts('No app name provided') - exit(1) - end - blti_apps = Doorkeeper::Application.where(name: args[:name]) - if blti_apps.empty? - puts("App '#{args[:name]}' does not exist, it can not be deleted") - exit(1) - end - blti_apps.each(&:destroy) - puts("Apps with name '#{args[:name]}' were successfully destroyed") - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc 'Show an existent blti app if exists - show[name]' - task :show, [:name] => :environment do |_t, args| - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - unless args[:name] - puts('No app name provided') - exit(1) - end - apps = Doorkeeper::Application.where(name: args[:name]) - if apps.empty? - puts("App '#{args[:name]}' does not exist, it can not be shown") - exit(1) - end - apps.each do |app| - app1 = app.attributes.select { |key, _value| %w[name uid secret redirect_uri].include?(key) } - puts(app1.to_json) - end - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc 'Delete all existent blti apps' - task :deleteall, [] => :environment do - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - Doorkeeper::Application.delete_all - puts('All the registered apps were deleted') - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc 'Show all existent blti apps' - task :showall, [] => :environment do - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - apps = Doorkeeper::Application.all - apps.each do |app| - app1 = app.attributes.select { |key, _value| %w[name uid secret redirect_uri].include?(key) } - puts(app1.to_json) - end - rescue ApplicationRedisRecord::RecordNotFound - puts(e.backtrace) - exit(1) - end - end -end diff --git a/lib/tasks/db_tenant_settings.rake b/lib/tasks/db_tenant_settings.rake deleted file mode 100644 index 4148e335..00000000 --- a/lib/tasks/db_tenant_settings.rake +++ /dev/null @@ -1,87 +0,0 @@ -# frozen_string_literal: true - -require 'bbb_lti_broker/helpers' - -namespace :db do - namespace :tenants do - namespace :settings do - desc 'Show all settings for a tenant. If no id is specified, settings for all tenants will be shown' - task :showall, [:uid] => :environment do |_t, args| - tenant_id = args[:uid] || '' - - if tenant_id.present? - tenant = RailsLti2Provider::Tenant.find_by(uid: tenant_id) - if tenant.nil? - puts("Tenant '#{tenant_id}' does not exist.") - exit(1) - end - - puts("Settings for tenant #{tenant_id}: \n #{tenant.settings}") - else - tenants = RailsLti2Provider::Tenant.all - tenants_list = tenants.map do |t| - { - tenant: t.uid, - settings: t.settings, - } - end - puts(tenants_list) - end - end - - desc 'Add a new tenant setting' - task :upsert, [:uid, :key, :value] => :environment do |_t, args| - tenant_id = args[:uid] || '' - key = args[:key] - value = args[:value] - - unless key.present? && value.present? - puts('Error: key and value are required to create a tenant setting') - exit(1) - end - - tenant = RailsLti2Provider::Tenant.find_by(uid: tenant_id) - if tenant.nil? - puts("Tenant '#{tenant_id}' does not exist.") - exit(1) - end - - # Add the setting - tenant.settings[key] = value - tenant.save! - - puts("Added setting #{key}=#{value} to tenant #{tenant_id}") - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc 'Delete a setting' - task :delete, [:uid, :key] => :environment do |_t, args| - tenant_id = args[:uid] || '' - key = args[:key] - - if key.blank? - puts('Error: The setting key is required to delete a tenant setting') - exit(1) - end - - tenant = RailsLti2Provider::Tenant.find_by(uid: tenant_id) - if tenant.nil? - puts("Tenant '#{tenant_id}' does not exist.") - exit(1) - end - - puts("Key '#{key}' not found for tenant #{tenant}") unless tenant.settings[key] - - tenant.settings.delete(key) - tenant.save! - - puts("Setting #{key} for tenant '#{tenant_id}' has been deleted") - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - end - end -end diff --git a/lib/tasks/db_tenants.rake b/lib/tasks/db_tenants.rake deleted file mode 100644 index 5a22bbec..00000000 --- a/lib/tasks/db_tenants.rake +++ /dev/null @@ -1,85 +0,0 @@ -# frozen_string_literal: true - -require 'bbb_lti_broker/helpers' - -namespace :db do - namespace :tenants do - desc 'Add a new tenant - add[uid]' - task :add, [:uid] => :environment do |_t, args| - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - unless args[:uid] - puts('No uid provided') - exit(1) - end - tenant = RailsLti2Provider::Tenant.find_by(uid: args[:uid]) - unless tenant.nil? - puts("Tenant '#{args[:uuid]}' already exists, it can not be added") - exit(1) - end - RailsLti2Provider::Tenant.create!(uid: args[:uid]) - puts("Added '#{args[:uid]}' tenant") - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc "Delete an existent tenant and associated keys if exists [uid]'" - task :delete, [:uid] => :environment do |_t, args| - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - unless args[:uid] - puts('No uid provided') - puts("Tenant '#{args[:uid]}' can not be removed because it is used by default") - exit(1) - end - tenant = RailsLti2Provider::Tenant.find_by(uid: args[:uid]) - if tenant.nil? - puts("Key '#{args[:uid]}' does not exist, it can not be deleted") - exit(1) - end - puts("Deleting keys for tenant '#{tenant.uid}'") - RailsLti2Provider::Tool.delete_all(tenant: tenant) - puts("Deleting tenant '#{tenant.uid}'") - tenant.delete - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc 'Delete all existent tenants and all associated keys' - task :deleteall, [] => :environment do |_t| - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - tenants = RailsLti2Provider::Tenant.all - tenants.each do |tenant| - next if tenant.uid.empty? - - puts("Deleting keys for tenant '#{tenant.uid}'") - RailsLti2Provider::Tool.delete_all(tenant: tenant) - puts("Deleting tenant '#{tenant.uid}'") - tenant.delete - end - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - - desc 'Show all existent tenants' - task :showall, [] => :environment do |_t| - include BbbLtiBroker::Helpers - Rake::Task['environment'].invoke - ActiveRecord::Base.connection - tenants = RailsLti2Provider::Tenant.all - tenants.each do |tenant| - puts("Tenant with uid '#{tenant.uid}' has key '#{tenant.id}'") - end - rescue StandardError => e - puts(e.backtrace) - exit(1) - end - end -end diff --git a/lib/tasks/tool.rake b/lib/tasks/tool.rake index ab82e284..1ace4152 100644 --- a/lib/tasks/tool.rake +++ b/lib/tasks/tool.rake @@ -67,7 +67,7 @@ namespace :tool do token: key_pair_token ) - reg = { + tool_settings = { issuer: issuer, client_id: client_id, key_set_url: key_set_url, @@ -80,7 +80,7 @@ namespace :tool do tool = RailsLti2Provider::Tool.create( uuid: issuer, shared_secret: client_id, - tool_settings: reg.to_json, + tool_settings: tool_settings.to_json, lti_version: '1.3.0', tenant: tenant ) @@ -289,7 +289,6 @@ namespace :tool do $stdout.puts("tool:keys:show[#{args[:id]}]") - $stdout.puts('tool:show[id]') tool = RailsLti2Provider::Tool.find_by(lti_version: '1.3.0', id: id) abort("The tool with ID #{id} does not exist") if tool.blank? @@ -311,6 +310,36 @@ namespace :tool do puts(e.backtrace) exit(1) end + + desc 'Generate new key pair for existing Tool configuration' + task :reset, [:id] => :environment do |_t, args| + id = args[:id] + abort('The ID is required') if id.blank? + + $stdout.puts("tool:keys:reset[#{args[:id]}]") + + tool = RailsLti2Provider::Tool.find_by(lti_version: '1.3.0', id: id) + abort("The tool with ID #{id} does not exist") if tool.blank? + + # Setting keys + private_key = OpenSSL::PKey::RSA.generate(4096) + public_key = private_key.public_key + key_pair_token = Digest::MD5.hexdigest(SecureRandom.uuid) + + tool_settings = JSON.parse(tool.tool_settings) + key_pair_id = tool_settings['rsa_key_pair_id'] + key_pairs = RsaKeyPair.find(key_pair_id) + key_pairs.update({ private_key: private_key, public_key: public_key, token: key_pair_token }) + + tool_settings['rsa_key_pair_token'] = key_pair_token + tool.update(tool_settings: tool_settings.to_json) + tool.save + + Rake::Task['tool:keys:show'].invoke(id) + rescue StandardError => e + puts(e.backtrace) + exit(1) + end end desc 'Show keys for tool by ID [id].' @@ -362,30 +391,6 @@ namespace :tool do exit(1) end - desc 'Generate new key pair for existing Tool configuration' - task :keygen, [] => :environment do |_t| - $stdout.puts('What is the issuer for the tool?') - issuer = $stdin.gets.strip - - $stdout.puts('What is the client ID for the tool?') - client_id = $stdin.gets.strip - - options = {} - options['client_id'] = client_id if client_id.present? - tool = RailsLti2Provider::Tool.find_by_issuer(issuer, options) - abort('The tool must be valid.') if tool.blank? - - # Setting keys - private_key = OpenSSL::PKey::RSA.generate(4096) - public_key = private_key.public_key - - key_pair_id = JSON.parse(tool.tool_settings)['rsa_key_pair_id'] - key_pairs = RsaKeyPair.find(key_pair_id) - key_pairs.update({ private_key: private_key, public_key: public_key }) - - puts(public_key) - end - desc 'Lists the Registration Configuration URLs need to register an app [app]' task :url, [] => :environment do |_t| $stdout.puts("Tool URL:\n#{openid_launch_url(protocol: 'https')}")