From 7ac6f087de5ef1b940b56de8d84597dc5059b264 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 2 Aug 2022 14:38:03 +0200 Subject: [PATCH 01/21] New translations en.yml (Portuguese) --- config/locales/pt.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 5e0b6614f..8e9a1d2ac 100755 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -19,9 +19,9 @@ pt: extension_whitelist_error: "Você não tem permissão para fazer o upload de arquivos com esta extensão %{extension}, tipos permitidos: %{allowed_types}" extension_blacklist_error: "Você não tem permissão para carregar arquivos %{extension}, tipos proibidos: %{prohibited_types}" content_type_whitelist_error: "Você não tem permissão para enviar arquivos %{content_type}, tipos permitidos: %{allowed_types}" - rmagick_processing_error: "Failed to manipulate with rmagick, maybe it is not an image?" - mime_types_processing_error: "Failed to process file with MIME::Types, maybe not valid content-type?" - mini_magick_processing_error: "Failed to manipulate the file, maybe it is not an image?" + rmagick_processing_error: "Falha ao manipular com rmagick, talvez não seja uma imagem?" + mime_types_processing_error: "Falha ao processar arquivo com MIME::Types, talvez tipo de conteúdo inválido?" + mini_magick_processing_error: "Falha ao manipular o arquivo, talvez não seja uma imagem?" wrong_size: "é o tamanho errado (deveria ser %{file_size})" size_too_small: "é muito pequeno (deve ser pelo menos %{file_size})" size_too_big: "é muito grande (deve ser no máximo %{file_size})" From 3c6535ffe35d03f699f0080e09d4476d1685ded5 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 2 Aug 2022 14:38:04 +0200 Subject: [PATCH 02/21] New translations app.public.en.yml (Portuguese) --- config/locales/app.public.pt.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/config/locales/app.public.pt.yml b/config/locales/app.public.pt.yml index c3a7f769f..efd003eb1 100755 --- a/config/locales/app.public.pt.yml +++ b/config/locales/app.public.pt.yml @@ -71,9 +71,9 @@ pt: email_is_required: "E-mail é obrigatório." your_password: "Sua senha" password_is_required: "Senha é obrigatório." - password_is_too_short: "Password is too short (minimum 12 characters)" - password_is_too_weak: "Password is too weak:" - password_is_too_weak_explanations: "minimum 12 characters, at least one uppercase letter, one lowercase letter, one number and one special character" + password_is_too_short: "Senha muito curta (mínimo 12 caracteres)" + password_is_too_weak: "A senha é muito fraca:" + password_is_too_weak_explanations: "mínimo de 12 caracteres, pelo menos uma letra maiúscula, uma letra minúscula, um número e um caractere especial" type_your_password_again: "Digite sua senha novamente" password_confirmation_is_required: "Confirmação de senha é obrigatório." password_does_not_match_with_confirmation: "A senha não é igual ao da confirmação." @@ -103,7 +103,7 @@ pt: used_for_reservation: "Estes dados serão utilizados em caso de alteração em uma das suas reservas" used_for_profile: "Estes dados serão exibidos apenas no seu perfil" public_profile: "Você terá um perfil público e outros usuários poderão associá-lo em seus projetos" - you_will_receive_confirmation_instructions_by_email_detailed: "If your e-mail address is valid, you will receive an email with instructions about how to confirm your account in a few minutes." + you_will_receive_confirmation_instructions_by_email_detailed: "Se seu endereço de e-mail for válido, você receberá em breve um e-mail com instruções sobre como confirmar sua conta." #password modification modal change_your_password: "Mudar sua senha" your_new_password: "Sua nova senha" @@ -119,7 +119,7 @@ pt: #confirmation modal you_will_receive_confirmation_instructions_by_email: "Você receberá instruções de confirmação por e-mail." #forgotten password modal - you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password: "If your e-mail address is valid, you will receive in a moment an e-mail with instructions to reset your password." + you_will_receive_in_a_moment_an_email_with_instructions_to_reset_your_password: "Se o seu endereço de e-mail for válido, você receberá em breve um e-mail com instruções para redefinir sua senha." #Fab-manager's version version: "Versão:" upgrade_fabmanager: "Atualizar Fab-manager" From c3cdccfb74d0a65f8aa3883d17fd12b6ff24081a Mon Sep 17 00:00:00 2001 From: vincent Date: Wed, 3 Aug 2022 09:12:57 +0200 Subject: [PATCH 03/21] Adjust connection modals' style --- app/frontend/src/stylesheets/app.components.scss | 10 +++++++++- app/frontend/src/stylesheets/modules/signup.scss | 5 ++--- app/frontend/templates/shared/deviseModal.html | 6 +++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/frontend/src/stylesheets/app.components.scss b/app/frontend/src/stylesheets/app.components.scss index c3334eda1..2431241e2 100644 --- a/app/frontend/src/stylesheets/app.components.scss +++ b/app/frontend/src/stylesheets/app.components.scss @@ -588,10 +588,18 @@ .checkbox-group { display: flex; justify-content: flex-start; + align-items: flex-start; input[type=checkbox] { - font-size: 16px; + flex-shrink: 0; width: 2em; + height: 2rem; + margin-right: 0.5rem; + font-size: 16px; + } + label { + margin: 0; + font-weight: 500; } } diff --git a/app/frontend/src/stylesheets/modules/signup.scss b/app/frontend/src/stylesheets/modules/signup.scss index 712d28d35..0455349b1 100644 --- a/app/frontend/src/stylesheets/modules/signup.scss +++ b/app/frontend/src/stylesheets/modules/signup.scss @@ -1,8 +1,7 @@ .signup-form { .names-row { - input.form-control { - width: 89%; - display: inline-block; + & > div { + display: flex; } } diff --git a/app/frontend/templates/shared/deviseModal.html b/app/frontend/templates/shared/deviseModal.html index a2a58a5b1..57a3403b9 100644 --- a/app/frontend/templates/shared/deviseModal.html +++ b/app/frontend/templates/shared/deviseModal.html @@ -42,9 +42,9 @@ translate-attr="{ placeholder: 'app.public.common.your_password' }" ng-minlength="8"/> - {{ 'app.public.common.password_forgotten' }} + {{ 'app.public.common.password_forgotten' }} -
{{ 'app.public.common.confirm_my_account' }} +
{{ 'app.public.common.confirm_my_account' }}
From 9b44492971c95b1fb80047301ffc0cede51623d1 Mon Sep 17 00:00:00 2001 From: Guilherme Chaguri Date: Tue, 16 Aug 2022 11:02:25 -0300 Subject: [PATCH 04/21] (bug) Fix user reference for admin check Fix user variable reference when verifying whether the user is an administrator --- app/models/concerns/single_sign_on_concern.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/single_sign_on_concern.rb b/app/models/concerns/single_sign_on_concern.rb index f23a6985c..fb5bffadc 100644 --- a/app/models/concerns/single_sign_on_concern.rb +++ b/app/models/concerns/single_sign_on_concern.rb @@ -124,7 +124,7 @@ module SingleSignOnConcern logger.debug "mapping sso field #{field} with value=#{value}" # we do not merge the email field if its end with the special value '-duplicate' as this means # that the user is currently merging with the account that have the same email than the sso - set_data_from_sso_mapping(field, value) unless (field == 'user.email' && value.end_with?('-duplicate')) || (field == 'user.group_id' && user.admin?) + set_data_from_sso_mapping(field, value) unless (field == 'user.email' && value.end_with?('-duplicate')) || (field == 'user.group_id' && sso_user.admin?) end # run the account transfer in an SQL transaction to ensure data integrity From 86791869267fa2791f67de1372f7838a0fb68bf7 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Mon, 22 Aug 2022 13:35:36 +0200 Subject: [PATCH 05/21] updated changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80bea673a..1e70c2c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## next release +- Updated portuguese translations +- Fix a bug: wrong variable reference in `SingleSignOnConcern:Merge_form_sso` + ## v5.4.15 2022 August 1 - Improved security: adds redis-session-store to store session From 5f8a15bcbbc5c0503e6a9e3e2a4947be7ffdb1b6 Mon Sep 17 00:00:00 2001 From: vincent Date: Mon, 22 Aug 2022 15:25:00 +0200 Subject: [PATCH 06/21] Fix [form-rich-text] focus --- CHANGELOG.md | 1 + .../components/form/abstract-form-item.tsx | 19 +++++++++++-------- .../components/form/form-rich-text.tsx | 3 ++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e70c2c35..4c491cea2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Updated portuguese translations - Fix a bug: wrong variable reference in `SingleSignOnConcern:Merge_form_sso` +- Fix a bug: wrong focus behavior on text editor ## v5.4.15 2022 August 1 diff --git a/app/frontend/src/javascript/components/form/abstract-form-item.tsx b/app/frontend/src/javascript/components/form/abstract-form-item.tsx index 679c2bde9..afa91a07a 100644 --- a/app/frontend/src/javascript/components/form/abstract-form-item.tsx +++ b/app/frontend/src/javascript/components/form/abstract-form-item.tsx @@ -9,15 +9,16 @@ export interface AbstractFormItemProps extends PropsWithChildren boolean), - onLabelClick?: (event: React.MouseEvent) => void, + onLabelClick?: (event: React.MouseEvent) => void, inLine?: boolean, + containerType?: 'label' | 'div' } /** * This abstract component should not be used directly. * Other forms components that are intended to be used with react-hook-form must extend this component. */ -export const AbstractFormItem = ({ id, label, tooltip, className, disabled, error, warning, rules, formState, onLabelClick, inLine, children }: AbstractFormItemProps) => { +export const AbstractFormItem = ({ id, label, tooltip, className, disabled, error, warning, rules, formState, onLabelClick, inLine, containerType, children }: AbstractFormItemProps) => { const [isDirty, setIsDirty] = useState(false); const [fieldError, setFieldError] = useState<{ message: string }>(error); const [isDisabled, setIsDisabled] = useState(false); @@ -52,16 +53,16 @@ export const AbstractFormItem = ({ id, label, * This function is called when the label is clicked. * It is used to focus the input. */ - function handleLabelClick (event: React.MouseEvent) { + function handleLabelClick (event: React.MouseEvent) { if (typeof onLabelClick === 'function') { onLabelClick(event); } } - return ( -
- } onChange={handleCurrencyUpdate} diff --git a/app/frontend/src/javascript/components/payment/select-gateway-modal.tsx b/app/frontend/src/javascript/components/payment/select-gateway-modal.tsx index cdd8dc3df..23d48df7d 100644 --- a/app/frontend/src/javascript/components/payment/select-gateway-modal.tsx +++ b/app/frontend/src/javascript/components/payment/select-gateway-modal.tsx @@ -38,7 +38,7 @@ export const SelectGatewayModal: React.FC = ({ isO // request the configured gateway to the API useEffect(() => { - SettingAPI.get(SettingName.PaymentGateway).then(gateway => { + SettingAPI.get('payment_gateway').then(gateway => { setSelectedGateway(gateway.value ? gateway.value : ''); }); }, []); @@ -73,8 +73,8 @@ export const SelectGatewayModal: React.FC = ({ isO const handleValidStripeKeys = (publicKey: string, secretKey: string): void => { setGatewayConfig((prev) => { const newMap = new Map(prev); - newMap.set(SettingName.StripeSecretKey, secretKey); - newMap.set(SettingName.StripePublicKey, publicKey); + newMap.set('stripe_secret_key', secretKey); + newMap.set('stripe_public_key', publicKey); return newMap; }); setPreventConfirmGateway(false); @@ -100,7 +100,7 @@ export const SelectGatewayModal: React.FC = ({ isO */ const updateSettings = (): void => { const settings = new Map(gatewayConfig); - settings.set(SettingName.PaymentGateway, selectedGateway); + settings.set('payment_gateway', selectedGateway); SettingAPI.bulkUpdate(settings, true).then(result => { const errorResults = Array.from(result.values()).filter(item => !item.status); diff --git a/app/frontend/src/javascript/components/payment/stripe/stripe-elements.tsx b/app/frontend/src/javascript/components/payment/stripe/stripe-elements.tsx index 68a912733..803140f63 100644 --- a/app/frontend/src/javascript/components/payment/stripe/stripe-elements.tsx +++ b/app/frontend/src/javascript/components/payment/stripe/stripe-elements.tsx @@ -14,7 +14,7 @@ export const StripeElements: React.FC = memo(({ children }) => { * When this component is mounted, we initialize the tag with the Stripe's public key */ useEffect(() => { - SettingAPI.get(SettingName.StripePublicKey).then(key => { + SettingAPI.get('stripe_public_key').then(key => { if (key?.value) { const promise = loadStripe(key.value); setStripe(promise); diff --git a/app/frontend/src/javascript/components/payment/stripe/stripe-keys-form.tsx b/app/frontend/src/javascript/components/payment/stripe/stripe-keys-form.tsx index ee01742ce..9c96ae6fe 100644 --- a/app/frontend/src/javascript/components/payment/stripe/stripe-keys-form.tsx +++ b/app/frontend/src/javascript/components/payment/stripe/stripe-keys-form.tsx @@ -42,9 +42,9 @@ const StripeKeysForm: React.FC = ({ onValidKeys, onInvalidK useEffect(() => { mounted.current = true; - SettingAPI.query([SettingName.StripePublicKey, SettingName.StripeSecretKey]).then(stripeKeys => { - setPublicKey(stripeKeys.get(SettingName.StripePublicKey)); - setSecretKey(stripeKeys.get(SettingName.StripeSecretKey)); + SettingAPI.query(['stripe_public_key', 'stripe_secret_key']).then(stripeKeys => { + setPublicKey(stripeKeys.get('stripe_public_key')); + setSecretKey(stripeKeys.get('stripe_secret_key')); }).catch(error => console.error(error)); // when the component unmounts, mark it as unmounted diff --git a/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx b/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx index 1723bddc8..ea5682538 100644 --- a/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx +++ b/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx @@ -44,10 +44,10 @@ const PacksSummary: React.FC = ({ item, itemType, customer, o const [isPackOnlyForSubscription, setIsPackOnlyForSubscription] = useState(true); useEffect(() => { - SettingAPI.get(SettingName.RenewPackThreshold) + SettingAPI.get('renew_pack_threshold') .then(data => setThreshold(parseFloat(data.value))) .catch(error => onError(error)); - SettingAPI.get(SettingName.PackOnlyForSubscription) + SettingAPI.get('pack_only_for_subscription') .then(data => setIsPackOnlyForSubscription(data.value === 'true')) .catch(error => onError(error)); }, []); diff --git a/app/frontend/src/javascript/components/profile-completion/completion-header-info.tsx b/app/frontend/src/javascript/components/profile-completion/completion-header-info.tsx index fc6085873..7b66a8d9e 100644 --- a/app/frontend/src/javascript/components/profile-completion/completion-header-info.tsx +++ b/app/frontend/src/javascript/components/profile-completion/completion-header-info.tsx @@ -6,7 +6,7 @@ import { Loader } from '../base/loader'; import { react2angular } from 'react2angular'; import { IApplication } from '../../models/application'; import SettingAPI from '../../api/setting'; -import { SettingName } from '../../models/setting'; +import { SettingName, titleSettings } from '../../models/setting'; import UserLib from '../../lib/user'; declare const Application: IApplication; @@ -27,7 +27,7 @@ export const CompletionHeaderInfo: React.FC = ({ user const userLib = new UserLib(user); useEffect(() => { - SettingAPI.query([SettingName.NameGenre, SettingName.FablabName]).then(setSettings).catch(onError); + SettingAPI.query(titleSettings).then(setSettings).catch(onError); }, []); return ( @@ -39,8 +39,8 @@ export const CompletionHeaderInfo: React.FC = ({ user

{t('app.logged.profile_completion.completion_header_info.sso_intro', { - GENDER: settings?.get(SettingName.NameGenre), - NAME: settings?.get(SettingName.FablabName) + GENDER: settings?.get('name_genre'), + NAME: settings?.get('fablab_name') })} diff --git a/app/frontend/src/javascript/components/settings/user-validation-setting.tsx b/app/frontend/src/javascript/components/settings/user-validation-setting.tsx index 414d016a2..9c65b5ed3 100644 --- a/app/frontend/src/javascript/components/settings/user-validation-setting.tsx +++ b/app/frontend/src/javascript/components/settings/user-validation-setting.tsx @@ -36,7 +36,7 @@ export const UserValidationSetting: React.FC = ({ on const updateSetting = (name: SettingName, value: string) => { SettingAPI.update(name, value) .then(() => { - if (name === SettingName.UserValidationRequired) { + if (name === 'user_validation_required') { onSuccess(t('app.admin.settings.account.user_validation_setting.customization_of_SETTING_successfully_saved', { SETTING: t(`app.admin.settings.account.${name}`) // eslint-disable-line fabmanager/scoped-translation })); @@ -45,7 +45,7 @@ export const UserValidationSetting: React.FC = ({ on if (err.status === 304) return; if (err.status === 423) { - if (name === SettingName.UserValidationRequired) { + if (name === 'user_validation_required') { onError(t('app.admin.settings.account.user_validation_setting.error_SETTING_locked', { SETTING: t(`app.admin.settings.account.${name}`) // eslint-disable-line fabmanager/scoped-translation })); @@ -62,19 +62,19 @@ export const UserValidationSetting: React.FC = ({ on * Callback triggered when the 'save' button is clicked. */ const handleSave = () => { - updateSetting(SettingName.UserValidationRequired, userValidationRequired); + updateSetting('user_validation_required', userValidationRequired); if (userValidationRequiredList !== null) { if (userValidationRequired === 'true') { - updateSetting(SettingName.UserValidationRequiredList, userValidationRequiredList); + updateSetting('user_validation_required_list', userValidationRequiredList); } else { - updateSetting(SettingName.UserValidationRequiredList, null); + updateSetting('user_validation_required_list', null); } } }; return (

- = ({ on {t('app.admin.settings.account.user_validation_setting.user_validation_required_list_other_info')} - = ({ show = false, onError, onSuccess }) => { const { t } = useTranslation('shared'); - // regular expression to validate the the input fields + // regular expression to validate the input fields const urlRegex = /^(https?:\/\/)([\da-z.-]+)\.([-a-z\d.]{2,30})([/\w .-]*)*\/?$/; const { handleSubmit, register, setValue, formState } = useForm(); diff --git a/app/frontend/src/javascript/components/user/user-profile-form.tsx b/app/frontend/src/javascript/components/user/user-profile-form.tsx index 18feb3570..1c449c0e5 100644 --- a/app/frontend/src/javascript/components/user/user-profile-form.tsx +++ b/app/frontend/src/javascript/components/user/user-profile-form.tsx @@ -99,7 +99,7 @@ export const UserProfileForm: React.FC = ({ action, size, }); setValue('invoicing_profile_attributes.user_profile_custom_fields_attributes', userProfileCustomFields); }).catch(error => onError(error)); - SettingAPI.query([SettingName.PhoneRequired, SettingName.AddressRequired]) + SettingAPI.query(['phone_required', 'address_required']) .then(settings => setRequiredFieldsSettings(settings)) .catch(error => onError(error)); }, []); @@ -219,7 +219,7 @@ export const UserProfileForm: React.FC = ({ action, size, value: phoneRegex, message: t('app.shared.user_profile_form.phone_number_invalid') }, - required: requiredFieldsSettings.get(SettingName.PhoneRequired) === 'true' + required: requiredFieldsSettings.get('phone_required') === 'true' }} disabled={isDisabled} formState={formState} @@ -232,7 +232,7 @@ export const UserProfileForm: React.FC = ({ action, size,
diff --git a/app/frontend/src/javascript/models/setting.ts b/app/frontend/src/javascript/models/setting.ts index 84eb6ed02..144c53631 100644 --- a/app/frontend/src/javascript/models/setting.ts +++ b/app/frontend/src/javascript/models/setting.ts @@ -1,144 +1,242 @@ import { HistoryValue } from './history-value'; import { TDateISO } from '../typings/date-iso'; -export enum SettingName { - AboutTitle = 'about_title', - AboutBody = 'about_body', - AboutContacts = 'about_contacts', - PrivacyDraft = 'privacy_draft', - PrivacyBody = 'privacy_body', - PrivacyDpo = 'privacy_dpo', - TwitterName = 'twitter_name', - HomeBlogpost = 'home_blogpost', - MachineExplicationsAlert = 'machine_explications_alert', - TrainingExplicationsAlert = 'training_explications_alert', - TrainingInformationMessage = 'training_information_message', - SubscriptionExplicationsAlert = 'subscription_explications_alert', - InvoiceLogo = 'invoice_logo', - InvoiceReference = 'invoice_reference', - InvoiceCodeActive = 'invoice_code-active', - InvoiceCodeValue = 'invoice_code-value', - InvoiceOrderNb = 'invoice_order-nb', - InvoiceVATActive = 'invoice_VAT-active', - InvoiceVATRate = 'invoice_VAT-rate', - InvoiceVATRateMachine = 'invoice_VAT-rate_Machine', - InvoiceVATRateTraining = 'invoice_VAT-rate_Training', - InvoiceVATRateSpace = 'invoice_VAT-rate_Space', - InvoiceVATRateEvent = 'invoice_VAT-rate_Event', - InvoiceVATRateSubscription = 'invoice_VAT-rate_Subscription', - InvoiceText = 'invoice_text', - InvoiceLegals = 'invoice_legals', - BookingWindowStart = 'booking_window_start', - BookingWindowEnd = 'booking_window_end', - BookingMoveEnable = 'booking_move_enable', - BookingMoveDelay = 'booking_move_delay', - BookingCancelEnable = 'booking_cancel_enable', - BookingCancelDelay = 'booking_cancel_delay', - MainColor = 'main_color', - SecondaryColor = 'secondary_color', - FablabName = 'fablab_name', - NameGenre = 'name_genre', - ReminderEnable = 'reminder_enable', - ReminderDelay = 'reminder_delay', - EventExplicationsAlert = 'event_explications_alert', - SpaceExplicationsAlert = 'space_explications_alert', - VisibilityYearly = 'visibility_yearly', - VisibilityOthers = 'visibility_others', - DisplayNameEnable = 'display_name_enable', - MachinesSortBy = 'machines_sort_by', - AccountingJournalCode = 'accounting_journal_code', - AccountingCardClientCode = 'accounting_card_client_code', - AccountingCardClientLabel = 'accounting_card_client_label', - AccountingWalletClientCode = 'accounting_wallet_client_code', - AccountingWalletClientLabel = 'accounting_wallet_client_label', - AccountingOtherClientCode = 'accounting_other_client_code', - AccountingOtherClientLabel = 'accounting_other_client_label', - AccountingWalletCode = 'accounting_wallet_code', - AccountingWalletLabel = 'accounting_wallet_label', - AccountingVATCode = 'accounting_VAT_code', - AccountingVATLabel = 'accounting_VAT_label', - AccountingSubscriptionCode = 'accounting_subscription_code', - AccountingSubscriptionLabel = 'accounting_subscription_label', - AccountingMachineCode = 'accounting_Machine_code', - AccountingMachineLabel = 'accounting_Machine_label', - AccountingTrainingCode = 'accounting_Training_code', - AccountingTrainingLabel = 'accounting_Training_label', - AccountingEventCode = 'accounting_Event_code', - AccountingEventLabel = 'accounting_Event_label', - AccountingSpaceCode = 'accounting_Space_code', - AccountingSpaceLabel = 'accounting_Space_label', - HubLastVersion = 'hub_last_version', - HubPublicKey = 'hub_public_key', - FabAnalytics = 'fab_analytics', - LinkName = 'link_name', - HomeContent = 'home_content', - HomeCss = 'home_css', - Origin = 'origin', - Uuid = 'uuid', - PhoneRequired = 'phone_required', - TrackingId = 'tracking_id', - BookOverlappingSlots = 'book_overlapping_slots', - SlotDuration = 'slot_duration', - EventsInCalendar = 'events_in_calendar', - SpacesModule = 'spaces_module', - PlansModule = 'plans_module', - InvoicingModule = 'invoicing_module', - FacebookAppId = 'facebook_app_id', - TwitterAnalytics = 'twitter_analytics', - RecaptchaSiteKey = 'recaptcha_site_key', - RecaptchaSecretKey = 'recaptcha_secret_key', - FeatureTourDisplay = 'feature_tour_display', - EmailFrom = 'email_from', - DisqusShortname = 'disqus_shortname', - AllowedCadExtensions = 'allowed_cad_extensions', - AllowedCadMimeTypes = 'allowed_cad_mime_types', - OpenlabAppId = 'openlab_app_id', - OpenlabAppSecret = 'openlab_app_secret', - OpenlabDefault = 'openlab_default', - OnlinePaymentModule = 'online_payment_module', - StripePublicKey = 'stripe_public_key', - StripeSecretKey = 'stripe_secret_key', - StripeCurrency = 'stripe_currency', - InvoicePrefix = 'invoice_prefix', - ConfirmationRequired = 'confirmation_required', - WalletModule = 'wallet_module', - StatisticsModule = 'statistics_module', - UpcomingEventsShown = 'upcoming_events_shown', - PaymentSchedulePrefix = 'payment_schedule_prefix', - TrainingsModule = 'trainings_module', - AddressRequired = 'address_required', - PaymentGateway = 'payment_gateway', - PayZenUsername = 'payzen_username', - PayZenPassword = 'payzen_password', - PayZenEndpoint = 'payzen_endpoint', - PayZenPublicKey = 'payzen_public_key', - PayZenHmacKey = 'payzen_hmac', - PayZenCurrency = 'payzen_currency', - PublicAgendaModule = 'public_agenda_module', - RenewPackThreshold = 'renew_pack_threshold', - PackOnlyForSubscription = 'pack_only_for_subscription', - OverlappingCategories = 'overlapping_categories', - ExtendedPricesInSameDay = 'extended_prices_in_same_day', - PublicRegistrations = 'public_registrations', - SocialsFacebook = 'facebook', - SocialsTwitter = 'twitter', - SocialsViadeo = 'viadeo', - SocialsLinkedin = 'linkedin', - SocialsInstagram = 'instagram', - SocialsYoutube = 'youtube', - SocialsVimeo = 'vimeo', - SocialsDailymotion = 'dailymotion', - SocialsGithub = 'github', - SocialsEchosciences = 'echosciences', - SocialsPinterest = 'pinterest', - SocialsLastfm = 'lastfm', - SocialsFlickr = 'flickr', - MachinesModule = 'machines_module', - UserChangeGroup = 'user_change_group', - UserValidationRequired = 'user_validation_required', - UserValidationRequiredList = 'user_validation_required_list', - ShowUsernameInAdminList = 'show_username_in_admin_list' -} +export const homePageSettings = [ + 'twitter_name', + 'home_blogpost', + 'home_content', + 'home_css', + 'upcoming_events_shown' +]; + +export const privacyPolicySettings = [ + 'privacy_draft', + 'privacy_body', + 'privacy_dpo' +]; + +export const aboutPageSettings = [ + 'about_title', + 'about_body', + 'about_contacts', + 'link_name' +]; + +export const socialNetworksSettings = [ + 'facebook', + 'twitter', + 'viadeo', + 'linkedin', + 'instagram', + 'youtube', + 'vimeo', + 'dailymotion', + 'github', + 'echosciences', + 'pinterest', + 'lastfm', + 'flickr' +]; + +export const messagesSettings = [ + 'machine_explications_alert', + 'training_explications_alert', + 'training_information_message', + 'subscription_explications_alert', + 'event_explications_alert', + 'space_explications_alert' +]; + +export const invoicesSettings = [ + 'invoice_logo', + 'invoice_reference', + 'invoice_code-active', + 'invoice_code-value', + 'invoice_order-nb', + 'invoice_VAT-active', + 'invoice_VAT-rate', + 'invoice_VAT-rate_Machine', + 'invoice_VAT-rate_Training', + 'invoice_VAT-rate_Space', + 'invoice_VAT-rate_Event', + 'invoice_VAT-rate_Subscription', + 'invoice_text', + 'invoice_legals', + 'invoice_prefix', + 'payment_schedule_prefix' +]; + +export const bookingSettings = [ + 'booking_window_start', + 'booking_window_end', + 'booking_move_enable', + 'booking_move_delay', + 'booking_cancel_enable', + 'booking_cancel_delay', + 'reminder_enable', + 'reminder_delay', + 'visibility_yearly', + 'visibility_others', + 'display_name_enable', + 'book_overlapping_slots', + 'slot_duration', + 'overlapping_categories' +]; + +export const themeSettings = [ + 'main_color', + 'secondary_color' +]; + +export const titleSettings = [ + 'fablab_name', + 'name_genre' +]; + +export const accountingSettings = [ + 'accounting_journal_code', + 'accounting_card_client_code', + 'accounting_card_client_label', + 'accounting_wallet_client_code', + 'accounting_wallet_client_label', + 'accounting_other_client_code', + 'accounting_other_client_label', + 'accounting_wallet_code', + 'accounting_wallet_label', + 'accounting_VAT_code', + 'accounting_VAT_label', + 'accounting_subscription_code', + 'accounting_subscription_label', + 'accounting_Machine_code', + 'accounting_Machine_label', + 'accounting_Training_code', + 'accounting_Training_label', + 'accounting_Event_code', + 'accounting_Event_label', + 'accounting_Space_code', + 'accounting_Space_label' +]; + +export const modulesSettings = [ + 'spaces_module', + 'plans_module', + 'wallet_module', + 'statistics_module', + 'trainings_module', + 'machines_module', + 'online_payment_module', + 'public_agenda_module', + 'invoicing_module' +]; + +export const stripeSettings = [ + 'stripe_public_key', + 'stripe_secret_key', + 'stripe_currency' +]; + +export const payzenSettings = [ + 'payzen_username', + 'payzen_password', + 'payzen_endpoint', + 'payzen_public_key', + 'payzen_hmac', + 'payzen_currency' +]; + +export const openLabSettings = [ + 'openlab_app_id', + 'openlab_app_secret', + 'openlab_default' +]; + +export const accountSettings = [ + 'phone_required', + 'confirmation_required', + 'address_required', + 'user_change_group', + 'user_validation_required', + 'user_validation_required_list' +]; + +export const analyticsSettings = [ + 'tracking_id', + 'facebook_app_id', + 'twitter_analytics' +]; + +export const fabHubSettings = [ + 'hub_last_version', + 'hub_public_key', + 'fab_analytics', + 'origin', + 'uuid' +]; + +export const projectsSettings = [ + 'allowed_cad_extensions', + 'allowed_cad_mime_types', + 'disqus_shortname' +]; + +export const prepaidPacksSettings = [ + 'renew_pack_threshold', + 'pack_only_for_subscription' +]; + +export const registrationSettings = [ + 'public_registrations', + 'recaptcha_site_key', + 'recaptcha_secret_key' +]; + +export const adminSettings = [ + 'feature_tour_display', + 'show_username_in_admin_list' +]; + +export const pricingSettings = [ + 'extended_prices_in_same_day' +]; + +export const poymentSettings = [ + 'payment_gateway' +]; + +export const displaySettings = [ + 'machines_sort_by', + 'events_in_calendar', + 'email_from' +]; + +export const allSettings = [ + ...homePageSettings, + ...privacyPolicySettings, + ...aboutPageSettings, + ...socialNetworksSettings, + ...messagesSettings, + ...invoicesSettings, + ...bookingSettings, + ...themeSettings, + ...titleSettings, + ...accountingSettings, + ...modulesSettings, + ...stripeSettings, + ...payzenSettings, + ...openLabSettings, + ...accountSettings, + ...analyticsSettings, + ...fabHubSettings, + ...projectsSettings, + ...prepaidPacksSettings, + ...registrationSettings, + ...adminSettings, + ...pricingSettings, + ...poymentSettings, + ...displaySettings +] as const; + +export type SettingName = typeof allSettings[number]; export type SettingValue = string|boolean|number; @@ -153,7 +251,7 @@ export interface Setting { export interface SettingError { error: string, id: number, - name: string + name: SettingName } export interface SettingBulkResult { From faae719fefac0034d9f48c6acb95b097bf5275f5 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 23 Aug 2022 15:15:49 +0200 Subject: [PATCH 10/21] Removed unused imports --- app/frontend/src/javascript/components/group/change-group.tsx | 1 - .../src/javascript/components/machines/reserve-button.tsx | 1 - .../components/payment-schedule/payment-schedules-table.tsx | 2 +- .../javascript/components/payment/abstract-payment-modal.tsx | 1 - .../src/javascript/components/payment/card-payment-modal.tsx | 2 +- .../components/payment/local-payment/local-payment-form.tsx | 1 - .../src/javascript/components/payment/payzen/payzen-form.tsx | 1 - .../javascript/components/payment/stripe/stripe-elements.tsx | 1 - .../javascript/components/payment/stripe/stripe-keys-form.tsx | 1 - .../src/javascript/components/prepaid-packs/packs-summary.tsx | 1 - 10 files changed, 2 insertions(+), 10 deletions(-) diff --git a/app/frontend/src/javascript/components/group/change-group.tsx b/app/frontend/src/javascript/components/group/change-group.tsx index d8a59f80f..653f65931 100644 --- a/app/frontend/src/javascript/components/group/change-group.tsx +++ b/app/frontend/src/javascript/components/group/change-group.tsx @@ -11,7 +11,6 @@ import { useForm } from 'react-hook-form'; import { FormSelect } from '../form/form-select'; import MemberAPI from '../../api/member'; import SettingAPI from '../../api/setting'; -import { SettingName } from '../../models/setting'; import UserLib from '../../lib/user'; declare const Application: IApplication; diff --git a/app/frontend/src/javascript/components/machines/reserve-button.tsx b/app/frontend/src/javascript/components/machines/reserve-button.tsx index 2d0cdd6f6..40381c61d 100644 --- a/app/frontend/src/javascript/components/machines/reserve-button.tsx +++ b/app/frontend/src/javascript/components/machines/reserve-button.tsx @@ -10,7 +10,6 @@ import { Machine } from '../../models/machine'; import { User } from '../../models/user'; import { IApplication } from '../../models/application'; import SettingAPI from '../../api/setting'; -import { SettingName } from '../../models/setting'; declare const Application: IApplication; diff --git a/app/frontend/src/javascript/components/payment-schedule/payment-schedules-table.tsx b/app/frontend/src/javascript/components/payment-schedule/payment-schedules-table.tsx index 719c70ec3..b9fba4fbd 100644 --- a/app/frontend/src/javascript/components/payment-schedule/payment-schedules-table.tsx +++ b/app/frontend/src/javascript/components/payment-schedule/payment-schedules-table.tsx @@ -12,7 +12,7 @@ import FormatLib from '../../lib/format'; import { PaymentScheduleItemActions, TypeOnce } from './payment-schedule-item-actions'; import { StripeElements } from '../payment/stripe/stripe-elements'; import SettingAPI from '../../api/setting'; -import { Setting, SettingName } from '../../models/setting'; +import { Setting } from '../../models/setting'; interface PaymentSchedulesTableProps { paymentSchedules: Array, diff --git a/app/frontend/src/javascript/components/payment/abstract-payment-modal.tsx b/app/frontend/src/javascript/components/payment/abstract-payment-modal.tsx index 61ebb67f1..45e80c9f7 100644 --- a/app/frontend/src/javascript/components/payment/abstract-payment-modal.tsx +++ b/app/frontend/src/javascript/components/payment/abstract-payment-modal.tsx @@ -13,7 +13,6 @@ import PriceAPI from '../../api/price'; import WalletAPI from '../../api/wallet'; import { Invoice } from '../../models/invoice'; import SettingAPI from '../../api/setting'; -import { SettingName } from '../../models/setting'; import { GoogleTagManager } from '../../models/gtm'; import { ComputePriceResult } from '../../models/price'; import { Wallet } from '../../models/wallet'; diff --git a/app/frontend/src/javascript/components/payment/card-payment-modal.tsx b/app/frontend/src/javascript/components/payment/card-payment-modal.tsx index 9263eddb5..525dd4d4d 100644 --- a/app/frontend/src/javascript/components/payment/card-payment-modal.tsx +++ b/app/frontend/src/javascript/components/payment/card-payment-modal.tsx @@ -7,7 +7,7 @@ import { IApplication } from '../../models/application'; import { ShoppingCart } from '../../models/payment'; import { User } from '../../models/user'; import { PaymentSchedule } from '../../models/payment-schedule'; -import { Setting, SettingName } from '../../models/setting'; +import { Setting } from '../../models/setting'; import { Invoice } from '../../models/invoice'; import SettingAPI from '../../api/setting'; import { useTranslation } from 'react-i18next'; diff --git a/app/frontend/src/javascript/components/payment/local-payment/local-payment-form.tsx b/app/frontend/src/javascript/components/payment/local-payment/local-payment-form.tsx index aa0009b26..e8f5f5799 100644 --- a/app/frontend/src/javascript/components/payment/local-payment/local-payment-form.tsx +++ b/app/frontend/src/javascript/components/payment/local-payment/local-payment-form.tsx @@ -5,7 +5,6 @@ import { GatewayFormProps } from '../abstract-payment-modal'; import LocalPaymentAPI from '../../../api/local-payment'; import FormatLib from '../../../lib/format'; import SettingAPI from '../../../api/setting'; -import { SettingName } from '../../../models/setting'; import { CardPaymentModal } from '../card-payment-modal'; import { PaymentSchedule } from '../../../models/payment-schedule'; import { HtmlTranslate } from '../../base/html-translate'; diff --git a/app/frontend/src/javascript/components/payment/payzen/payzen-form.tsx b/app/frontend/src/javascript/components/payment/payzen/payzen-form.tsx index bae1b18e3..0c5bf8e86 100644 --- a/app/frontend/src/javascript/components/payment/payzen/payzen-form.tsx +++ b/app/frontend/src/javascript/components/payment/payzen/payzen-form.tsx @@ -2,7 +2,6 @@ import React, { FormEvent, FunctionComponent, useEffect, useRef, useState } from import KRGlue from '@lyracom/embedded-form-glue'; import { GatewayFormProps } from '../abstract-payment-modal'; import SettingAPI from '../../../api/setting'; -import { SettingName } from '../../../models/setting'; import PayzenAPI from '../../../api/payzen'; import { CreateTokenResponse, diff --git a/app/frontend/src/javascript/components/payment/stripe/stripe-elements.tsx b/app/frontend/src/javascript/components/payment/stripe/stripe-elements.tsx index 803140f63..8ed376168 100644 --- a/app/frontend/src/javascript/components/payment/stripe/stripe-elements.tsx +++ b/app/frontend/src/javascript/components/payment/stripe/stripe-elements.tsx @@ -1,7 +1,6 @@ import React, { memo, useEffect, useState } from 'react'; import { Elements } from '@stripe/react-stripe-js'; import { loadStripe, Stripe } from '@stripe/stripe-js'; -import { SettingName } from '../../../models/setting'; import SettingAPI from '../../../api/setting'; /** diff --git a/app/frontend/src/javascript/components/payment/stripe/stripe-keys-form.tsx b/app/frontend/src/javascript/components/payment/stripe/stripe-keys-form.tsx index 9c96ae6fe..1804cf922 100644 --- a/app/frontend/src/javascript/components/payment/stripe/stripe-keys-form.tsx +++ b/app/frontend/src/javascript/components/payment/stripe/stripe-keys-form.tsx @@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next'; import { HtmlTranslate } from '../../base/html-translate'; import { FabInput } from '../../base/fab-input'; import { Loader } from '../../base/loader'; -import { SettingName } from '../../../models/setting'; import StripeAPI from '../../../api/external/stripe'; import SettingAPI from '../../../api/setting'; diff --git a/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx b/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx index ea5682538..1f4abde1b 100644 --- a/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx +++ b/app/frontend/src/javascript/components/prepaid-packs/packs-summary.tsx @@ -5,7 +5,6 @@ import { User } from '../../models/user'; import { UserPack } from '../../models/user-pack'; import UserPackAPI from '../../api/user-pack'; import SettingAPI from '../../api/setting'; -import { SettingName } from '../../models/setting'; import { FabButton } from '../base/fab-button'; import { useTranslation } from 'react-i18next'; import { ProposePacksModal } from './propose-packs-modal'; From f7261043b5372e57ac75d5a06e7b6254e5223aa9 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 23 Aug 2022 15:54:37 +0200 Subject: [PATCH 11/21] Fix a bug: trainings monitoring is not available --- CHANGELOG.md | 1 + app/controllers/api/trainings_controller.rb | 8 +++++- .../trainings/availabilities.json.jbuilder | 10 ++++--- .../trainings/availabilities_test.rb | 26 +++++++++++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 test/integration/trainings/availabilities_test.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 280f90907..1484945a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Use union type instead of enum for SettingName - Fix a bug: wrong variable reference in `SingleSignOnConcern:Merge_form_sso` - Fix a bug: wrong focus behavior on text editor +- Fix a bug: trainings monitoring is not available ## v5.4.15 2022 August 1 diff --git a/app/controllers/api/trainings_controller.rb b/app/controllers/api/trainings_controller.rb index b8902da78..83240a232 100644 --- a/app/controllers/api/trainings_controller.rb +++ b/app/controllers/api/trainings_controller.rb @@ -52,7 +52,13 @@ class API::TrainingsController < API::ApiController authorize Training @training = Training.find(params[:id]) @availabilities = @training.availabilities - .includes(slots: { slots_reservations: { reservations: { statistic_profile: [:trainings, user: [:profile]] } } }) + .includes(slots: { + slots_reservations: { + reservation: { + statistic_profile: [:trainings, { user: [:profile] }] + } + } + }) .where('slots_reservations.canceled_at': nil) .order('availabilities.start_at DESC') end diff --git a/app/views/api/trainings/availabilities.json.jbuilder b/app/views/api/trainings/availabilities.json.jbuilder index b3701a28e..e4163caa1 100644 --- a/app/views/api/trainings/availabilities.json.jbuilder +++ b/app/views/api/trainings/availabilities.json.jbuilder @@ -1,11 +1,13 @@ +# frozen_string_literal: true + json.extract! @training, :id, :name, :description, :machine_ids, :nb_total_places, :public_page json.availabilities @availabilities do |a| json.id a.id json.start_at a.start_at.iso8601 json.end_at a.end_at.iso8601 - json.reservation_users a.slots.map do |slot| - json.id slot.reservations.first.statistic_profile.user_id - json.full_name slot.reservations.first.statistic_profile&.user&.profile&.full_name - json.is_valid slot.reservations.first.statistic_profile.trainings.include?(@training) + json.reservation_users a.slots.map(&:slots_reservations).flatten.map do |sr| + json.id sr.reservation.statistic_profile.user_id + json.full_name sr.reservation.statistic_profile.user&.profile&.full_name + json.is_valid sr.reservation.statistic_profile.trainings&.include?(@training) end end diff --git a/test/integration/trainings/availabilities_test.rb b/test/integration/trainings/availabilities_test.rb new file mode 100644 index 000000000..6e0c31450 --- /dev/null +++ b/test/integration/trainings/availabilities_test.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require 'test_helper' + +module Trainings; end + +class Trainings::AvailabilitiesTest < ActionDispatch::IntegrationTest + def setup + @admin = User.find_by(username: 'admin') + login_as(@admin, scope: :user) + end + + test 'get trainings availabilities list' do + training = Training.find(1) + get "/api/trainings/#{training.id}/availabilities" + + # Check response format & status + assert_equal 200, response.status, response.body + assert_equal Mime[:json], response.content_type + + # Check the correct training was returned + result = json_response(response.body) + assert_equal training.id, result[:id], 'training id does not match' + assert_not_empty result[:availabilities], 'no training availabilities were returned' + end +end From a31f3555a18cb01ef5c3fc23677ed2128ad5df3a Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 23 Aug 2022 17:35:12 +0200 Subject: [PATCH 12/21] (Bug) password verification during setup --- CHANGELOG.md | 1 + .../templates/shared/_member_form.html | 566 ------------------ setup/setup.sh | 8 +- 3 files changed, 7 insertions(+), 568 deletions(-) delete mode 100644 app/frontend/templates/shared/_member_form.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a82a630a..0c392f29b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fix a bug: wrong focus behavior on text editor - Fix a bug: trainings monitoring is not available - Fix a bug: invalid password length verification in profile edtion form +- Fix a bug: invalid password verification in setup script ## v5.4.15 2022 August 1 diff --git a/app/frontend/templates/shared/_member_form.html b/app/frontend/templates/shared/_member_form.html deleted file mode 100644 index 0b0690626..000000000 --- a/app/frontend/templates/shared/_member_form.html +++ /dev/null @@ -1,566 +0,0 @@ -{{alert.msg}} - - - - - - -
-
-
-
-
- -
-
- -
-
- - - - {{ 'app.shared.user.add_an_avatar' }} - {{ 'app.shared.buttons.change' }} - - - - -
-
-
- -
-
- -
- - - - - {{ 'app.shared.user.gender_is_required' }} -
- - -
-
- - - -
- {{ 'app.shared.user.pseudonym_is_required' }} -
- - - -
-
- - -
- {{ 'app.shared.user.surname_is_required' }} -
- -
-
- - -
- {{ 'app.shared.user.first_name_is_required' }} -
- -
-
- - -
- {{ 'app.shared.user.email_address_is_required' }} -
- -
- -
- - -
-
- - -
- {{ 'app.shared.user.password_is_required' }} - {{ 'app.shared.user.password_is_too_short' }} -
- -
-
- - -
- {{ 'app.shared.user.confirmation_of_password_is_required' }} - {{ 'app.shared.user.confirmation_of_password_is_too_short' }} - {{ 'app.shared.user.confirmation_mismatch_with_password' }} -
- -
-
- - - -
- {{ 'app.shared.user.organization_name_is_required' }} -
- -
-
- - - -
- {{ 'app.shared.user.organization_address_is_required' }} -
- -
-
- - - -
- {{ 'app.shared.user.date_of_birth_is_required' }} -
- -
-
- - - -
-
- -
-
- - -
- {{ 'app.shared.user.phone_number_is_required' }} -
- -
-
- - -
-
- -
-
- - -
-
- -
- - -
- -
- - -
- - -
- - - -
- - -
- - - -
- -
-
-
- - -
-
- -
-
- - -
-
- -
-
- - -
-
- -
-
- - -
-
- -
-
- - -
-
- -
-
- - -
-
- -
-
- - -
-
- -
-
- - -
-
- -
-
- d - -
-
- - -
-
- - -
-
- -
-
- d - -
-
- -
-
- - -
-
- -
-
- - -
-
- -
-
- - -
-
- - -
- -
- -
diff --git a/setup/setup.sh b/setup/setup.sh index 2bd954455..3d7ae6f80 100755 --- a/setup/setup.sh +++ b/setup/setup.sh @@ -412,8 +412,12 @@ read_password() local password confirmation >&2 echo "Please input a password for this administrator's account" read -rsp " > " password &2 printf "\nError: password is too short (minimal length: 8 characters)\n" + if [ ${#password} -lt 12 ]; then + >&2 printf "\nError: password is too short (minimal length: 12 characters)\n" + password=$(read_password 'no-confirm') + fi + if [[ ! $password =~ [0-9] || ! $password =~ [a-z] || ! $password =~ [A-Z] || ! $password =~ [[:punct:]] ]]; then + >&2 printf "\nError: password is too weak (should contain uppercases, lowercases, digits and special characters)\n" password=$(read_password 'no-confirm') fi if [ "$1" != 'no-confirm' ]; then From cbefb702a566018424b0febc247a117cc6bef627 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 24 Aug 2022 10:29:11 +0200 Subject: [PATCH 13/21] (Bug) setup cannot chown installation folder --- CHANGELOG.md | 1 + setup/setup.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c392f29b..8e992bd07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Fix a bug: trainings monitoring is not available - Fix a bug: invalid password length verification in profile edtion form - Fix a bug: invalid password verification in setup script +- Fix a bug: during setup, unable to chown the installation folder, if the current user does not have a self-named group ## v5.4.15 2022 August 1 diff --git a/setup/setup.sh b/setup/setup.sh index 3d7ae6f80..4277ef61f 100755 --- a/setup/setup.sh +++ b/setup/setup.sh @@ -198,7 +198,7 @@ prepare_files() if [[ "$confirm" = "n" ]]; then exit 1; fi elevate_cmd mkdir -p "$FABMANAGER_PATH" - elevate_cmd chown -R "$(whoami):$(whoami)" "$FABMANAGER_PATH" + elevate_cmd chown -R "$(whoami)" "$FABMANAGER_PATH" # create folders before starting the containers, otherwise root will own them local folders=(accounting config elasticsearch/config exports imports invoices log payment_schedules plugins postgresql \ From 19e76d700f379bdda3e3d823254a198ec13e765d Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 24 Aug 2022 10:53:13 +0200 Subject: [PATCH 14/21] (style) check commit message rules enabled rule to check commit prefixing and disabled CapitalizedSubject --- .overcommit.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.overcommit.yml b/.overcommit.yml index 625994a5b..c5ea9cf19 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -6,3 +6,13 @@ PreCommit: TrailingWhitespace: enabled: true +CommitMsg: + CapitalizedSubject: + enabled: false + + MessageFormat: + enabled: true + pattern: ^\([a-z]+\) [\w ]+(\n\n.+)? + expected_pattern_message: (type) title\n\ndescription + sample_message: (bug) no validation on date\n\nThe birthdate was not validated... + From e5df3ae633126894aed3a0d24fdcdc225baf8532 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 24 Aug 2022 11:05:36 +0200 Subject: [PATCH 15/21] (bug) current env values not shown --- CHANGELOG.md | 1 + setup/setup.sh | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e992bd07..1223e8bb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Fix a bug: invalid password length verification in profile edtion form - Fix a bug: invalid password verification in setup script - Fix a bug: during setup, unable to chown the installation folder, if the current user does not have a self-named group +- Fix a bug: during setup, the current value in config/env is not shown ## v5.4.15 2022 August 1 diff --git a/setup/setup.sh b/setup/setup.sh index 4277ef61f..3035eff5d 100755 --- a/setup/setup.sh +++ b/setup/setup.sh @@ -384,7 +384,7 @@ configure_env_file() var_doc=$(get_md_anchor "$doc" "$variable") current=$(grep "$variable=" "$FABMANAGER_PATH/config/env") echo "$var_doc" | bat --file-name "$variable" --language md --color=always - printf "- \e[1mCurrent value: %s\e[21m\n- New value? (leave empty to keep the current value)\n" "$current" + printf -- "- \e[1mCurrent value: %s\e[21m\n- New value? (leave empty to keep the current value)\n" "$current" read -rep " > " value Date: Wed, 24 Aug 2022 11:07:07 +0200 Subject: [PATCH 16/21] (doc) Clarified documentation about default values --- CHANGELOG.md | 1 + doc/environment.md | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1223e8bb8..f465df120 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Updated portuguese translations - Added automatic RuboCop validation on pre-commit - Use union type instead of enum for SettingName +- Clarified documentation about default values for environment variables - Fix a bug: wrong variable reference in `SingleSignOnConcern:Merge_form_sso` - Fix a bug: wrong focus behavior on text editor - Fix a bug: trainings monitoring is not available diff --git a/doc/environment.md b/doc/environment.md index 9d9f69166..47b9dffcc 100644 --- a/doc/environment.md +++ b/doc/environment.md @@ -192,7 +192,7 @@ _Eg.: configuring **es-ES** will set the currency symbol to **€** but **es-MX* Available values: `en, en-AU-CA, en-GB, en-IE, en-IN, en-NZ, en-US, en-ZA, fr, fa-CA, fr-CH, fr-CM, fr-FR, es, es-419, es-AR, es-CL, es-CO, es-CR, es-DO, es-EC, es-ES, es-MX, es-MX, es-PA, es-PE, es-US, es-VE, no, pt, pt-BR, zu`. -Default is **en**. +When not defined, it defaults to **en**. If your locale is not present in that list or any locale doesn't have your exact expectations, please open a pull request to share your modifications with the community and obtain a rebuilt docker image. You can find templates of these files at https://github.com/svenfuchs/rails-i18n/tree/rails-5-x/rails/locale. @@ -203,7 +203,7 @@ You can find templates of these files at https://github.com/svenfuchs/rails-i18n Configure the moment.js library for l10n. See [github.com/moment/momentlocale/*.js](https://github.com/moment/moment/tree/2.22.2/locale) for a list of available locales. -Default is **en** (even if it's not listed). +When not defined, it defaults to **en** (even if it's not listed).
SUMMERNOTE_LOCALE @@ -211,7 +211,7 @@ Default is **en** (even if it's not listed). Configure the javascript summernote editor for l10n. See [github.com/summernote/summernote/lang/summernote-*.js](https://github.com/summernote/summernote/tree/v0.8.18/lang) for a list of available locales. -Default is **en-US** (even if it's not listed). +When not defined, it defaults to **en-US** (even if it's not listed). ANGULAR_LOCALE @@ -222,14 +222,14 @@ Please, be aware that **the configured locale will imply the CURRENCY displayed _Eg.: configuring **fr-fr** will set the currency symbol to **€** but **fr-ca** will set **$** as currency symbol, so setting the `ANGULAR_LOCALE` to simple **fr** (without country indication) will probably not do what you expect._ -See [code.angularjs.org/i18n/angular-locale_*.js](https://code.angularjs.org/1.8.2/i18n/) for a list of available locales. Default is **en**. +See [code.angularjs.org/i18n/angular-locale_*.js](https://code.angularjs.org/1.8.2/i18n/) for a list of available locales. When not defined, it defaults to **en**. FULLCALENDAR_LOCALE Configure the fullCalendar JS agenda library. -See [github.com/fullcalendar/fullcalendar/locale/*.js](https://github.com/fullcalendar/fullcalendar/tree/v3.10.2/locale) for a list of available locales. Default is **en**. +See [github.com/fullcalendar/fullcalendar/locale/*.js](https://github.com/fullcalendar/fullcalendar/tree/v3.10.2/locale) for a list of available locales. When not defined, it defaults to **en**. INTL_LOCALE @@ -256,7 +256,7 @@ Available values: `danish, dutch, english, finnish, french, german, hungarian, i TIME_ZONE In Rails: set Time.zone default to the specified zone and make Active Record auto-convert to this zone. Run `rails time:zones:all` for a list of available time zone names. -Default is **UTC**. +When not defined, it defaults to **UTC**. WEEK_STARTING_DAY From 9674c4cddf085ff7634341eff1ba8c64b7faa638 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 24 Aug 2022 11:13:41 +0200 Subject: [PATCH 17/21] (doc) Minimum RAM required #385 --- CHANGELOG.md | 1 + doc/production_readme.md | 26 ++++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f465df120..cdcefca5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Added automatic RuboCop validation on pre-commit - Use union type instead of enum for SettingName - Clarified documentation about default values for environment variables +- Updated documentation about the minimum RAM required (#385) - Fix a bug: wrong variable reference in `SingleSignOnConcern:Merge_form_sso` - Fix a bug: wrong focus behavior on text editor - Fix a bug: trainings monitoring is not available diff --git a/doc/production_readme.md b/doc/production_readme.md index 0ed30cb83..b74ea267c 100644 --- a/doc/production_readme.md +++ b/doc/production_readme.md @@ -35,7 +35,9 @@ Choose one, depending on your budget, on the server's location, on the uptime gu #### System requirements ##### Memory -If you do not plan to use the statistics module, you will need at least 2 GB of addressable memory (RAM + swap) to install and use Fab-manager. +To install or upgrade Fab-manager you need at least 4 GB of RAM + 2 GB of swap to be able to compile the assets. + +Once installed, if you do not plan to use the statistics module, you will need at least 2 GB of addressable memory (RAM + swap) to use Fab-manager. We recommend 4 GB of RAM to take full advantage of Fab-manager and be able to use the statistics module. If you have a large community (~ 200 active membres), we recommend 4 GB of RAM, even without the statistics module. @@ -47,10 +49,10 @@ Supported operating systems are Ubuntu LTS 16.04+ and Debian 8+ with an x86 64-b This might work on other linux systems, and CPU architectures but this is untested for now, and we do not recommend for production purposes. #### Software requirements -`curl` and `bash` are needed to retrieve and run the automated deployment scripts. +`curl` and `bash` are needed to retrieve and run the automated deployment scripts. Then the various scripts will check for their own dependencies. -Moreover, the main software dependencies to run fab-manager are [Docker](https://docs.docker.com/engine/installation/linux/docker-ce/debian/) v20.10 or above and [Docker Compose](https://docs.docker.com/compose/install/) +Moreover, the main software dependencies to run fab-manager are [Docker](https://docs.docker.com/engine/installation/linux/docker-ce/debian/) v20.10 or above and [Docker Compose](https://docs.docker.com/compose/install/) They can be easily installed using the [`prepare-vps.sleede.com` script below](#prepare-the-server). @@ -109,7 +111,7 @@ Then, you can remove the `elasticsearch` service from the [docker-compose.yml](. docker compose down && docker compose up -d ``` -Disabling ElasticSearch will save up to 800 Mb of memory. +Disabling ElasticSearch will save up to 800 Mb of memory. ## Useful commands @@ -143,7 +145,7 @@ When a new version is available, follow this procedure to update Fab-manager in You can subscribe to [this atom feed](https://github.com/sleede/fab-manager/releases.atom) to get notified when a new release comes out. -### Scripted update +### Scripted update Starting with Fab-manager v4.5.0, you can upgrade Fab-manager in one single easy command, specified in the GitHub releases notes. To upgrade multiple versions at once, read the GitHub release notes of all versions between your current version, and the target version. @@ -164,7 +166,7 @@ Then, you'll need to perform the upgrade with the following command: ```bash \curl -sSL upgrade.fab.mn | bash -s -- -e "VAR=value" -p "rails fablab:do:things" -c "rails fablab:setup:command" ``` -> ⚠ Do not confuse commands prefixed with `-p` and with `-c` because they are not intended to run at the same moment of the upgrade process. +> ⚠ Do not confuse commands prefixed with `-p` and with `-c` because they are not intended to run at the same moment of the upgrade process. ### Update manually @@ -190,7 +192,7 @@ Then, you'll need to perform the upgrade with the following command: `cd /apps/fabmanager` -2. Pull last docker images +2. Pull last docker images `docker compose pull` @@ -208,9 +210,9 @@ Then, you'll need to perform the upgrade with the following command: 6. Run specific commands - **Do not forget** to check if there are commands to run for your upgrade. Those commands + **Do not forget** to check if there are commands to run for your upgrade. Those commands are always specified in the [CHANGELOG](https://github.com/sleede/fab-manager/blob/master/CHANGELOG.md) and prefixed by **[TODO DEPLOY]**. - + Those commands execute specific tasks and have to be run manually. You must prefix the commands starting by `rails...` or `rake...` with: `docker compose run --rm fabmanager bundle exec`. In any other cases, the other commands (like those invoking curl `\curl -sSL... | bash`) must not be prefixed. @@ -228,8 +230,8 @@ You can check that all containers are running with `docker compose ps`. ### Upgrade to the last version -It's the default behaviour as `docker compose pull` command will fetch the latest versions of the docker images. -Be sure to run all the specific commands listed in the [CHANGELOG](https://github.com/sleede/fab-manager/blob/master/CHANGELOG.md) between your actual, and the new version in sequential order. +It's the default behaviour as `docker compose pull` command will fetch the latest versions of the docker images. +Be sure to run all the specific commands listed in the [CHANGELOG](https://github.com/sleede/fab-manager/blob/master/CHANGELOG.md) between your actual, and the new version in sequential order. __Example:__ to update from v2.4.0 to v2.4.3, you will run the specific commands for the v2.4.1, v2.4.2 and v2.4.3. @@ -252,4 +254,4 @@ For example, here we want to use the v3.1.2: ```yaml image: sleede/fab-manager:release-v3.1.2 ``` -Then run the normal upgrade procedure. +Then run the normal upgrade procedure. From 9caf40141214dc6d66e2a993e4c7b14cfd541039 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 24 Aug 2022 12:18:42 +0200 Subject: [PATCH 18/21] (bug) disabling/removing groups When disabling a group, another unrelated group maybe disabled/enabled; When deleting a group, another unrelated group may be deleted, instead of the requested one --- CHANGELOG.md | 1 + .../src/javascript/controllers/admin/groups.js | 15 +++++++++------ app/frontend/templates/admin/groups/index.html | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdcefca5f..eb392ed61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Fix a bug: invalid password verification in setup script - Fix a bug: during setup, unable to chown the installation folder, if the current user does not have a self-named group - Fix a bug: during setup, the current value in config/env is not shown +- Fix a bug: disabling/removing a group has side effects on other groups ## v5.4.15 2022 August 1 diff --git a/app/frontend/src/javascript/controllers/admin/groups.js b/app/frontend/src/javascript/controllers/admin/groups.js index a93e05caf..3de88cfb4 100644 --- a/app/frontend/src/javascript/controllers/admin/groups.js +++ b/app/frontend/src/javascript/controllers/admin/groups.js @@ -70,20 +70,23 @@ Application.Controllers.controller('GroupsController', ['$scope', 'groupsPromise /** * Deletes the group at the specified index - * @param index {number} group index in the $scope.groups array + * @param groupId {number} group id to delete */ - $scope.removeGroup = index => - Group.delete({ id: $scope.groups[index].id }, function (resp) { + $scope.removeGroup = (groupId) => { + Group.delete({ id: groupId }, function (resp) { growl.success(_t('app.admin.members.group_form.group_successfully_deleted')); - return $scope.groups.splice(index, 1); + const index = $scope.groups.findIndex(e => e.id === groupId); + $scope.groups.splice(index, 1); } , () => growl.error(_t('app.admin.members.group_form.unable_to_delete_group_because_some_users_and_or_groups_are_still_linked_to_it'))); + }; /** * Enable/disable the group at the specified index - * @param index {number} group index in the $scope.groups array + * @param groupId {number} id of the group to enable/disable */ - return $scope.toggleDisableGroup = function (index) { + return $scope.toggleDisableGroup = function (groupId) { + const index = $scope.groups.findIndex(e => e.id === groupId); const group = $scope.groups[index]; if (!group.disabled && (group.users > 0)) { return growl.error(_t('app.admin.members.group_form.unable_to_disable_group_with_users', { USERS: group.users })); diff --git a/app/frontend/templates/admin/groups/index.html b/app/frontend/templates/admin/groups/index.html index 2a2ec1cf4..6cb85780e 100644 --- a/app/frontend/templates/admin/groups/index.html +++ b/app/frontend/templates/admin/groups/index.html @@ -41,11 +41,11 @@ - -