1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-26 20:54:21 +01:00

(wip) move slot status request

This commit is contained in:
Sylvain 2023-01-18 17:44:58 +01:00
parent 986a663c40
commit d0239a0e25
11 changed files with 141 additions and 59 deletions

View File

@ -29,6 +29,7 @@ class API::AvailabilitiesController < API::ApiController
{ machines: machine_ids, spaces: params[:s], trainings: params[:t] }, { machines: machine_ids, spaces: params[:s], trainings: params[:t] },
events: (params[:evt] && params[:evt] == 'true') events: (params[:evt] && params[:evt] == 'true')
) )
@user = current_user
@title_filter = { machine_ids: machine_ids.map(&:to_i) } @title_filter = { machine_ids: machine_ids.map(&:to_i) }
@availabilities = filter_availabilites(@availabilities) @availabilities = filter_availabilites(@availabilities)

View File

@ -37,8 +37,6 @@ class Availability < ApplicationRecord
scope :trainings, -> { includes(:trainings).where(available_type: 'training') } scope :trainings, -> { includes(:trainings).where(available_type: 'training') }
scope :spaces, -> { includes(:spaces).where(available_type: 'space') } scope :spaces, -> { includes(:spaces).where(available_type: 'space') }
attr_accessor :is_reserved, :current_user_slots_reservations_ids, :current_user_pending_reservations_ids, :can_modify
validates :start_at, :end_at, presence: true validates :start_at, :end_at, presence: true
validate :length_must_be_slot_multiple, unless: proc { end_at.blank? or start_at.blank? } validate :length_must_be_slot_multiple, unless: proc { end_at.blank? or start_at.blank? }
validate :should_be_associated validate :should_be_associated
@ -114,6 +112,7 @@ class Availability < ApplicationRecord
# check if the reservations are complete? # check if the reservations are complete?
# if a nb_total_places hasn't been defined, then places are unlimited # if a nb_total_places hasn't been defined, then places are unlimited
# @return [Boolean]
def full? def full?
return false if nb_total_places.blank? && available_type != 'machines' return false if nb_total_places.blank? && available_type != 'machines'
@ -124,6 +123,15 @@ class Availability < ApplicationRecord
end end
end end
# @return [Array<Integer>] Collection of User's IDs
def reserved_users
slots.map(&:reserved_users).flatten
end
def reserved?
slots.map(&:reserved?).reduce(:&)
end
# check availability don't have any reservation # check availability don't have any reservation
def empty? def empty?
slots.map(&:empty?).reduce(:&) slots.map(&:empty?).reduce(:&)
@ -140,7 +148,7 @@ class Availability < ApplicationRecord
when 'machines' when 'machines'
reservable.nil? ? machines.count : 1 reservable.nil? ? machines.count : 1
else else
raise TypeError raise TypeError, "unknown available type #{available_type} for availability #{id}"
end end
end end

View File

@ -17,28 +17,55 @@ class Slot < ApplicationRecord
attr_accessor :is_reserved, :machine, :space, :title, :can_modify, :current_user_slots_reservations_ids, :current_user_pending_reservations_ids attr_accessor :is_reserved, :machine, :space, :title, :can_modify, :current_user_slots_reservations_ids, :current_user_pending_reservations_ids
# @param reservable [Machine,Space,Training,Event,NilClass] # @param reservable [Machine,Space,Training,Event,NilClass]
# @return [Integer] the total number of reserved places
def reserved_places(reservable = nil)
if reservable.nil?
places.pluck('reserved_places').reduce(:+)
else
places.detect { |p| p['reservable_type'] == reservable.class.name && p['reservable_id'] == reservable.id }['reserved_places']
end
end
# @param reservables [Array<Machine,Space,Training,Event>,NilClass]
# @return [Array<Integer>] Collection of User's IDs
def reserved_users(reservables = nil)
if reservable.nil?
places.pluck('user_ids').flatten
else
r_places = places.select do |p|
reservables.any? { |r| r.class.name == p['reservable_type'] && r.id == p['reservable_id'] } # rubocop:disable Style/ClassEqualityComparison
end
r_places.pluck('user_ids').flatten
end
end
# @param reservable [Machine, Space, Training, Event, NilClass]
# @return [Boolean] enough reservation to fill the whole slot?
def full?(reservable = nil) def full?(reservable = nil)
availability_places = availability.available_places_per_slot(reservable) availability_places = availability.available_places_per_slot(reservable)
return false if availability_places.nil? return false if availability_places.nil?
reserved_places = if reservable.nil? reserved_places(reservable) >= availability_places
places.pluck('reserved_places').reduce(:+)
else
rp = places.detect do |p|
p['reservable_type'] == reservable.class.name && p['reservable_id'] == reservable&.id
end
rp['reserved_places']
end end
reserved_places >= availability_places # @param reservable [Machine,Space,Training,Event,NilClass]
# @return [Boolean] any reservation or none?
def reserved?(reservable = nil)
reserved_places(reservable).positive?
end end
# @param reservable [Machine,Space,Training,Event,NilClass]
# @return [Boolean] no reservations at all?
def empty?(reservable = nil) def empty?(reservable = nil)
if reservable.nil? reserved_places(reservable).zero?
slots_reservations.where(canceled_at: nil).count.zero?
else
slots_reservations.includes(:reservation).where(canceled_at: nil).where('reservations.reservable': reservable).count.zero?
end end
# @param operator_role [String,NilClass] 'admin' | 'manager' | 'member'
# @param user_id [Integer]
# @param reservable [Machine,Space,Training,Event,NilClass]
# @return [Boolean] the reservation on this slot can be modified?
def modifiable?(operator_role, user_id, reservable = nil)
%w[admin manager].include?(operator_role) || reserved_users([reservable]).include?(user_id)
end end
def duration def duration

View File

@ -3,7 +3,7 @@
# List all Availability's slots for the given resources # List all Availability's slots for the given resources
class Availabilities::AvailabilitiesService class Availabilities::AvailabilitiesService
# @param current_user [User] # @param current_user [User]
# @param level [String] # @param level [String] 'slot' | 'availability'
def initialize(current_user, level = 'slot') def initialize(current_user, level = 'slot')
@current_user = current_user @current_user = current_user
@maximum_visibility = { @maximum_visibility = {
@ -39,16 +39,16 @@ class Availabilities::AvailabilitiesService
# @param window [Hash] the time window the look through: {start: xxx, end: xxx} # @param window [Hash] the time window the look through: {start: xxx, end: xxx}
# @option window [ActiveSupport::TimeWithZone] :start the beginning of the time window # @option window [ActiveSupport::TimeWithZone] :start the beginning of the time window
# @option window [ActiveSupport::TimeWithZone] :end the end of the time window # @option window [ActiveSupport::TimeWithZone] :end the end of the time window
def machines(machines, user, window) # @param no_status [Boolean] should the availability/slot reservation status be computed?
ma_availabilities = Availability.includes(:machines_availabilities, :availability_tags, :machines, :slots_reservations, def machines(machines, user, window, no_status: false)
slots: [:slots_reservations]) ma_availabilities = Availability.includes(:machines_availabilities)
.where('machines_availabilities.machine_id': machines.map(&:id)) .where('machines_availabilities.machine_id': machines.map(&:id))
availabilities = availabilities(ma_availabilities, 'machines', user, window[:start], window[:end]) availabilities = availabilities(ma_availabilities, 'machines', user, window[:start], window[:end])
if @level == 'slot' if @level == 'slot'
availabilities.map(&:slots).flatten.map { |s| @service.slot_reserved_status(s, user, (machines & s.availability.machines)) } availabilities.map(&:slots).flatten.map { |s| no_status ? s : @service.slot_reserved_status(s, user, (machines & s.availability.machines)) }
else else
availabilities.map { |a| @service.availability_reserved_status(a, user, (machines & a.machines)) } no_status ? availabilities : availabilities.map { |a| @service.availability_reserved_status(a, user, (machines & a.machines)) }
end end
end end
@ -58,15 +58,16 @@ class Availabilities::AvailabilitiesService
# @param window [Hash] the time window the look through: {start: xxx, end: xxx} # @param window [Hash] the time window the look through: {start: xxx, end: xxx}
# @option window [ActiveSupport::TimeWithZone] :start # @option window [ActiveSupport::TimeWithZone] :start
# @option window [ActiveSupport::TimeWithZone] :end # @option window [ActiveSupport::TimeWithZone] :end
def spaces(spaces, user, window) # @param no_status [Boolean] should the availability/slot reservation status be computed?
def spaces(spaces, user, window, no_status: false)
sp_availabilities = Availability.includes('spaces_availabilities') sp_availabilities = Availability.includes('spaces_availabilities')
.where('spaces_availabilities.space_id': spaces.map(&:id)) .where('spaces_availabilities.space_id': spaces.map(&:id))
availabilities = availabilities(sp_availabilities, 'space', user, window[:start], window[:end]) availabilities = availabilities(sp_availabilities, 'space', user, window[:start], window[:end])
if @level == 'slot' if @level == 'slot'
availabilities.map(&:slots).flatten.map { |s| @service.slot_reserved_status(s, user, (spaces & s.availability.spaces)) } availabilities.map(&:slots).flatten.map { |s| no_status ? s : @service.slot_reserved_status(s, user, (spaces & s.availability.spaces)) }
else else
availabilities.map { |a| @service.availability_reserved_status(a, user, (spaces & a.spaces)) } no_status ? availabilities : availabilities.map { |a| @service.availability_reserved_status(a, user, (spaces & a.spaces)) }
end end
end end
@ -76,15 +77,15 @@ class Availabilities::AvailabilitiesService
# @param window [Hash] the time window the look through: {start: xxx, end: xxx} # @param window [Hash] the time window the look through: {start: xxx, end: xxx}
# @option window [ActiveSupport::TimeWithZone] :start # @option window [ActiveSupport::TimeWithZone] :start
# @option window [ActiveSupport::TimeWithZone] :end # @option window [ActiveSupport::TimeWithZone] :end
def trainings(trainings, user, window) def trainings(trainings, user, window, no_status: false)
tr_availabilities = Availability.includes('trainings_availabilities') tr_availabilities = Availability.includes('trainings_availabilities')
.where('trainings_availabilities.training_id': trainings.map(&:id)) .where('trainings_availabilities.training_id': trainings.map(&:id))
availabilities = availabilities(tr_availabilities, 'training', user, window[:start], window[:end]) availabilities = availabilities(tr_availabilities, 'training', user, window[:start], window[:end])
if @level == 'slot' if @level == 'slot'
availabilities.map(&:slots).flatten.map { |s| @service.slot_reserved_status(s, user, (trainings & s.availability.trainings)) } availabilities.map(&:slots).flatten.map { |s| no_status ? s : @service.slot_reserved_status(s, user, (trainings & s.availability.trainings)) }
else else
availabilities.map { |a| @service.availability_reserved_status(a, user, (trainings & a.trainings)) } no_status ? availabilities : availabilities.map { |a| @service.availability_reserved_status(a, user, (trainings & a.trainings)) }
end end
end end
@ -94,18 +95,18 @@ class Availabilities::AvailabilitiesService
# @param window [Hash] the time window the look through: {start: xxx, end: xxx} # @param window [Hash] the time window the look through: {start: xxx, end: xxx}
# @option window [ActiveSupport::TimeWithZone] :start # @option window [ActiveSupport::TimeWithZone] :start
# @option window [ActiveSupport::TimeWithZone] :end # @option window [ActiveSupport::TimeWithZone] :end
def events(events, user, window) def events(events, user, window, no_status: false)
ev_availabilities = Availability.includes('event').where('events.id': events.map(&:id)) ev_availabilities = Availability.includes('event').where('events.id': events.map(&:id))
availabilities = availabilities(ev_availabilities, 'event', user, window[:start], window[:end]) availabilities = availabilities(ev_availabilities, 'event', user, window[:start], window[:end])
if @level == 'slot' if @level == 'slot'
availabilities.map(&:slots).flatten.map { |s| @service.slot_reserved_status(s, user, [s.availability.event]) } availabilities.map(&:slots).flatten.map { |s| no_status ? s : @service.slot_reserved_status(s, user, [s.availability.event]) }
else else
availabilities.map { |a| @service.availability_reserved_status(a, user, [a.event]) } no_status ? availabilities : availabilities.map { |a| @service.availability_reserved_status(a, user, [a.event]) }
end end
end end
private protected
# @param user [User] # @param user [User]
def subscription_year?(user) def subscription_year?(user)
@ -131,7 +132,7 @@ class Availabilities::AvailabilitiesService
# 1) an admin (he can see all availabilities from 1 month ago to anytime in the future) # 1) an admin (he can see all availabilities from 1 month ago to anytime in the future)
if @current_user&.admin? || @current_user&.manager? if @current_user&.admin? || @current_user&.manager?
window_start = [range_start, 1.month.ago].max window_start = [range_start, 1.month.ago].max
availabilities.includes(:tags, :plans, :slots) availabilities.includes(:tags, :slots)
.joins(:slots) .joins(:slots)
.where('availabilities.start_at <= ? AND availabilities.end_at >= ? AND available_type = ?', range_end, window_start, type) .where('availabilities.start_at <= ? AND availabilities.end_at >= ? AND available_type = ?', range_end, window_start, type)
.where('slots.start_at > ? AND slots.end_at < ?', window_start, range_end) .where('slots.start_at > ? AND slots.end_at < ?', window_start, range_end)
@ -143,7 +144,7 @@ class Availabilities::AvailabilitiesService
end_at = @maximum_visibility[:year] if show_more_trainings?(user) && type == 'training' end_at = @maximum_visibility[:year] if show_more_trainings?(user) && type == 'training'
window_end = [end_at, range_end].min window_end = [end_at, range_end].min
window_start = [range_start, @minimum_visibility].max window_start = [range_start, @minimum_visibility].max
availabilities.includes(:tags, :plans, :slots) availabilities.includes(:tags, :slots)
.joins(:slots) .joins(:slots)
.where('availabilities.start_at <= ? AND availabilities.end_at >= ? AND available_type = ?', window_end, window_start, type) .where('availabilities.start_at <= ? AND availabilities.end_at >= ? AND available_type = ?', window_end, window_start, type)
.where('slots.start_at > ? AND slots.end_at < ?', window_start, window_end) .where('slots.start_at > ? AND slots.end_at < ?', window_start, window_end)

View File

@ -11,10 +11,18 @@ class Availabilities::PublicAvailabilitiesService
level = in_same_day(window[:start], window[:end]) ? 'slot' : 'availability' level = in_same_day(window[:start], window[:end]) ? 'slot' : 'availability'
service = Availabilities::AvailabilitiesService.new(@current_user, level) service = Availabilities::AvailabilitiesService.new(@current_user, level)
machines_slots = Setting.get('machines_module') ? service.machines(Machine.where(id: ids[:machines]), @current_user, window) : [] machines_slots = if Setting.get('machines_module')
spaces_slots = Setting.get('spaces_module') ? service.spaces(Space.where(id: ids[:spaces]), @current_user, window) : [] service.machines(Machine.where(id: ids[:machines]), @current_user, window, no_status: true)
trainings_slots = Setting.get('trainings_module') ? service.trainings(Training.where(id: ids[:trainings]), @current_user, window) : [] else
events_slots = events ? service.events(Event.all, @current_user, window) : [] []
end
spaces_slots = Setting.get('spaces_module') ? service.spaces(Space.where(id: ids[:spaces]), @current_user, window, no_status: true) : []
trainings_slots = if Setting.get('trainings_module')
service.trainings(Training.where(id: ids[:trainings]), @current_user, window, no_status: true)
else
[]
end
events_slots = events ? service.events(Event.all, @current_user, window, no_status: true) : []
[].concat(trainings_slots).concat(events_slots).concat(machines_slots).concat(spaces_slots) [].concat(trainings_slots).concat(events_slots).concat(machines_slots).concat(spaces_slots)
end end

View File

@ -1,5 +1,5 @@
# frozen_string_literal: true # frozen_string_literal: true
# TODO, remove this
# Provides helper methods checking reservation status of any availabilities # Provides helper methods checking reservation status of any availabilities
class Availabilities::StatusService class Availabilities::StatusService
# @param current_user_role [String] # @param current_user_role [String]
@ -22,7 +22,7 @@ class Availabilities::StatusService
places = places(slot, reservables) places = places(slot, reservables)
is_reserved = places.any? { |p| p['reserved_places'].positive? } is_reserved = places.any? { |p| p['reserved_places'].positive? }
is_reserved_by_user = is_reserved && places.select { |p| p['user_ids'].include?(user.id) }.length.positive? is_reserved_by_user = is_reserved && user && places.select { |p| p['user_ids'].include?(user.id) }.length.positive?
slot.is_reserved = is_reserved slot.is_reserved = is_reserved
slot.title = slot_title(slot, is_reserved, is_reserved_by_user, reservables) slot.title = slot_title(slot, is_reserved, is_reserved_by_user, reservables)
slot.can_modify = true if %w[admin manager].include?(@current_user_role) || is_reserved slot.can_modify = true if %w[admin manager].include?(@current_user_role) || is_reserved

View File

@ -0,0 +1,37 @@
# frozen_string_literal: true
# Build the title of the provided slot
class Slots::TitleService
def initialize(operator_role, user)
@user = user
@show_name = (%w[admin manager].include?(operator_role) || (operator_role && Setting.get('display_name_enable')))
end
# @param slot [Slot]
# @param reservables [Array<Machine, Space, Training, Event>]
def slot_title(slot, reservables)
is_reserved = slot.reserved?
is_reserved_by_user = slot.reserved_users(reservables).include?(@user.id)
name = reservables.map(&:name).join(', ')
if !is_reserved && !is_reserved_by_user
name
elsif is_reserved && !is_reserved_by_user
"#{name} #{@show_name ? "- #{Slots::TitleService.slot_users_names(slot, reservables)}" : ''}"
else
"#{name} - #{I18n.t('availabilities.i_ve_reserved')}"
end
end
private
# @param slot [Slot]
# @param reservables [Array<Machine, Space, Training, Event>]
# @return [String]
def slot_users_names(slot, reservables)
user_ids = slot.reserved_users(reservables)
User.where(id: user_ids).includes(:profile)
.map { |u| u&.profile&.full_name || I18n.t('availabilities.deleted_user') }
.join(', ')
end
end

View File

@ -1,16 +1,16 @@
# frozen_string_literal: true # frozen_string_literal: true
json.slot_id slot.id json.slot_id slot.id
json.can_modify slot.can_modify json.can_modify slot.modifiable?(operator_role, @user.id, reservable)
json.title slot.title json.title Slots::TitleService.new(operator_role, @user).slot_title(slot, [reservable])
json.start slot.start_at.iso8601 json.start slot.start_at.iso8601
json.end slot.end_at.iso8601 json.end slot.end_at.iso8601
json.is_reserved slot.is_reserved json.is_reserved slot.reserved?(reservable)
json.is_completed slot.full?(reservable) json.is_completed slot.full?(reservable)
json.backgroundColor 'white' json.backgroundColor 'white'
json.availability_id slot.availability_id json.availability_id slot.availability_id
json.slots_reservations_ids slot.current_user_slots_reservations_ids json.slots_reservations_ids slot.current_user_slots_reservations_ids #TODO, move this out of attr_accessor
json.tag_ids slot.availability.tag_ids json.tag_ids slot.availability.tag_ids
json.tags slot.availability.tags do |t| json.tags slot.availability.tags do |t|

View File

@ -21,9 +21,9 @@ json.array!(@availabilities) do |availability|
end end
json.is_completed availability.full? json.is_completed availability.full?
json.is_reserved availability.is_reserved json.is_reserved availability.reserved?
json.borderColor availability_border_color(availability) json.borderColor availability_border_color(availability)
if availability.is_reserved && !availability.current_user_slots_reservations_ids.empty? if availability.reserved? && !@user.nil? && availability.reserved_users.include?(@user.id)
json.title "#{availability.title}' - #{t('trainings.i_ve_reserved')}" json.title "#{availability.title}' - #{t('trainings.i_ve_reserved')}"
elsif availability.full? elsif availability.full?
json.title "#{availability.title} - #{t('trainings.completed')}" json.title "#{availability.title} - #{t('trainings.completed')}"
@ -38,7 +38,7 @@ json.array!(@availabilities) do |availability|
json.id t.id json.id t.id
json.name t.name json.name t.name
end end
json.is_reserved availability.is_reserved json.is_reserved availability.reserved?
json.is_completed availability.full? json.is_completed availability.full?
case availability.availability.available_type case availability.availability.available_type
when 'machines' when 'machines'

View File

@ -19,8 +19,8 @@ ActiveRecord::Schema.define(version: 2023_01_31_104958) do
enable_extension "unaccent" enable_extension "unaccent"
create_table "abuses", id: :serial, force: :cascade do |t| create_table "abuses", id: :serial, force: :cascade do |t|
t.string "signaled_type"
t.integer "signaled_id" t.integer "signaled_id"
t.string "signaled_type"
t.string "first_name" t.string "first_name"
t.string "last_name" t.string "last_name"
t.string "email" t.string "email"
@ -68,8 +68,8 @@ ActiveRecord::Schema.define(version: 2023_01_31_104958) do
t.string "locality" t.string "locality"
t.string "country" t.string "country"
t.string "postal_code" t.string "postal_code"
t.string "placeable_type"
t.integer "placeable_id" t.integer "placeable_id"
t.string "placeable_type"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
end end
@ -93,8 +93,8 @@ ActiveRecord::Schema.define(version: 2023_01_31_104958) do
end end
create_table "assets", id: :serial, force: :cascade do |t| create_table "assets", id: :serial, force: :cascade do |t|
t.string "viewable_type"
t.integer "viewable_id" t.integer "viewable_id"
t.string "viewable_type"
t.string "attachment" t.string "attachment"
t.string "type" t.string "type"
t.datetime "created_at" t.datetime "created_at"
@ -281,8 +281,8 @@ ActiveRecord::Schema.define(version: 2023_01_31_104958) do
end end
create_table "credits", id: :serial, force: :cascade do |t| create_table "credits", id: :serial, force: :cascade do |t|
t.string "creditable_type"
t.integer "creditable_id" t.integer "creditable_id"
t.string "creditable_type"
t.integer "plan_id" t.integer "plan_id"
t.integer "hours" t.integer "hours"
t.datetime "created_at" t.datetime "created_at"
@ -524,15 +524,15 @@ ActiveRecord::Schema.define(version: 2023_01_31_104958) do
create_table "notifications", id: :serial, force: :cascade do |t| create_table "notifications", id: :serial, force: :cascade do |t|
t.integer "receiver_id" t.integer "receiver_id"
t.string "attached_object_type"
t.integer "attached_object_id" t.integer "attached_object_id"
t.string "attached_object_type"
t.integer "notification_type_id" t.integer "notification_type_id"
t.boolean "is_read", default: false t.boolean "is_read", default: false
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "receiver_type" t.string "receiver_type"
t.boolean "is_send", default: false t.boolean "is_send", default: false
t.jsonb "meta_data", default: "{}" t.jsonb "meta_data", default: {}
t.index ["notification_type_id"], name: "index_notifications_on_notification_type_id" t.index ["notification_type_id"], name: "index_notifications_on_notification_type_id"
t.index ["receiver_id"], name: "index_notifications_on_receiver_id" t.index ["receiver_id"], name: "index_notifications_on_receiver_id"
end end
@ -772,8 +772,8 @@ ActiveRecord::Schema.define(version: 2023_01_31_104958) do
create_table "prices", id: :serial, force: :cascade do |t| create_table "prices", id: :serial, force: :cascade do |t|
t.integer "group_id" t.integer "group_id"
t.integer "plan_id" t.integer "plan_id"
t.string "priceable_type"
t.integer "priceable_id" t.integer "priceable_id"
t.string "priceable_type"
t.integer "amount" t.integer "amount"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
@ -976,8 +976,8 @@ ActiveRecord::Schema.define(version: 2023_01_31_104958) do
t.text "message" t.text "message"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "reservable_type"
t.integer "reservable_id" t.integer "reservable_id"
t.string "reservable_type"
t.integer "nb_reserve_places" t.integer "nb_reserve_places"
t.integer "statistic_profile_id" t.integer "statistic_profile_id"
t.index ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id" t.index ["reservable_type", "reservable_id"], name: "index_reservations_on_reservable_type_and_reservable_id"
@ -986,8 +986,8 @@ ActiveRecord::Schema.define(version: 2023_01_31_104958) do
create_table "roles", id: :serial, force: :cascade do |t| create_table "roles", id: :serial, force: :cascade do |t|
t.string "name" t.string "name"
t.string "resource_type"
t.integer "resource_id" t.integer "resource_id"
t.string "resource_type"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id" t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id"

View File

@ -32,7 +32,7 @@ Especially, if you have an automatic redirection (e.g. from example.org to examp
Once you have reconfigured these variables, please switch back the active authentication provider to FabManager, restart the application, then delete the OIDC provider you configured and re-create a new one for the new settings to be used. Once you have reconfigured these variables, please switch back the active authentication provider to FabManager, restart the application, then delete the OIDC provider you configured and re-create a new one for the new settings to be used.
``` ```
Unable to decode ID token JSON::JWK::Set::KidNotFound (JSON::JWK::Set::KidNotFound)
``` ```
This issue may occur if the ID Token signature algorithm is not set to `RSxxx` on your IDP. This issue may occur if the ID Token signature algorithm is not set to `RSxxx` on your IDP.
Especially, this is not the default option when using LemonLDAP::NG, which uses `HSxxx` as the default algorithm, but you can configure it in `OpenID Connect Relaying Parties` > `my-fab-manager` > `Options` > `Security` > `ID Token signature algorithm`. Especially, this is not the default option when using LemonLDAP::NG, which uses `HSxxx` as the default algorithm, but you can configure it in `OpenID Connect Relaying Parties` > `my-fab-manager` > `Options` > `Security` > `ID Token signature algorithm`.