diff --git a/app/assets/stylesheets/extranet/layout/_header.sass b/app/assets/stylesheets/extranet/layout/_header.sass index 0056fb05b3145cd6710ecc859bcbffd47197bd64..2f0442340d2f8c85e11c47180d252023ea544bf3 100644 --- a/app/assets/stylesheets/extranet/layout/_header.sass +++ b/app/assets/stylesheets/extranet/layout/_header.sass @@ -12,4 +12,10 @@ header, &__title @extend h1 p - margin-bottom: 0 \ No newline at end of file + margin-bottom: 0 +@include media-breakpoint-up(md) + .organizations-show, + .persons-show + .header + h1 + margin-right: 25% \ No newline at end of file diff --git a/app/controllers/extranet/account_controller.rb b/app/controllers/extranet/account_controller.rb index 56389029177958ffa40f8e7e89d89e2dbe2f7726..e7ef509d9eb38ba5f51d5efe30c32be3fc52af82 100644 --- a/app/controllers/extranet/account_controller.rb +++ b/app/controllers/extranet/account_controller.rb @@ -11,28 +11,39 @@ class Extranet::AccountController < Extranet::ApplicationController end def update - manage_password - current_user.update user_params - redirect_to account_path, notice: t('extranet.account.updated') + if update_user(user_params) + bypass_sign_in current_user, scope: :user if sign_in_after_change_password? + redirect_to account_path, notice: t('extranet.account.updated') + else + breadcrumb + add_breadcrumb t('extranet.account.edit') + render :edit, status: :unprocessable_entity + end end protected - def manage_password - # to prevent cognitive complexity (the bottom block should be in an if condition where password present) - # Password not provided when user from sso - params[:user][:password] ||= '' - - if params[:user][:password].blank? - params[:user].delete(:password) + def update_user(params) + if params[:password].blank? + params.delete(:current_password) + current_user.update_without_password(params) else - current_user.reset_password(params[:user][:password], params[:user][:password]) + current_user.update_with_password(params) end end def user_params params.require(:user) - .permit(:first_name, :last_name, :email, :mobile_phone, :language_id, :password, :picture, :picture_infos, :picture_delete) + .permit( + :first_name, :last_name, :email, :mobile_phone, :language_id, + :current_password, :password, :password_confirmation, + :picture, :picture_infos, :picture_delete + ) + end + + def sign_in_after_change_password? + return true if user_params[:password].blank? + Devise.sign_in_after_change_password end def breadcrumb diff --git a/app/models/communication/website/page/with_type.rb b/app/models/communication/website/page/with_type.rb index 40a787c771a007c85ed3a905be42430dc29b7a72..375794a9624e4636da5b4b01e2c615d50f53bf3f 100644 --- a/app/models/communication/website/page/with_type.rb +++ b/app/models/communication/website/page/with_type.rb @@ -103,8 +103,8 @@ module Communication::Website::Page::WithType def initialize_special_page i18n_key = "communication.website.pages.defaults.#{type_key}" - self.title = I18n.t("#{i18n_key}.title") - self.slug = I18n.t("#{i18n_key}.slug") + self.title = I18n.t("#{i18n_key}.title", locale: language.iso_code) + self.slug = I18n.t("#{i18n_key}.slug", locale: language.iso_code) self.parent = default_parent self.full_width = full_width_by_default? self.published = published_by_default? diff --git a/app/views/extranet/account/edit.html.erb b/app/views/extranet/account/edit.html.erb index 68ea4442d42e5683edfb31ee619ac3b9e13d8484..d9615f63d78a2a59ab849cb6b63f84ca39f62d06 100644 --- a/app/views/extranet/account/edit.html.erb +++ b/app/views/extranet/account/edit.html.erb @@ -22,9 +22,23 @@ <div class="col-lg-6"> <%= f.input :email %> <%= f.input :mobile_phone %> + </div> + </div> + + <h3 class="mt-5 mb-4"><%= t("devise.passwords.edit.new") %></h3> + + <div class="row"> + <div class="col-lg-6"> + <%= f.input :current_password, + as: :password, + input_html: { autocomplete: "current-password" } %> + </div> + </div> + + <div class="row"> + <div class="col-lg-6"> <%= f.input :password, as: :password_with_hints, - hint: t('admin.password_hint'), allow_password_uncloaking: true, validators: { length: Devise.password_length.first, @@ -33,9 +47,19 @@ numeric_char: true, special_char: Rails.application.config.allowed_special_chars }, + label: t('devise.passwords.edit.new_password'), + required: false, + input_html: { autocomplete: "new-password" } %> + </div> + <div class="col-lg-6"> + <%= f.input :password_confirmation, + as: :password_with_sync, + allow_password_uncloaking: true, + compare_with_field: :password, input_html: { autocomplete: "new-password" } %> </div> </div> + <%= submit f %> <% if current_user.visitor? %> diff --git a/db/schema.rb b/db/schema.rb index c5612a4210889058256602ed82919f6774a8ddd8..273908059c87ebee13490c026cb71884ab4de5d4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -16,7 +16,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do enable_extension "plpgsql" enable_extension "unaccent" - create_table "action_text_rich_texts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "action_text_rich_texts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name", null: false t.text "body" t.string "record_type", null: false @@ -26,7 +26,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true end - create_table "active_storage_attachments", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "active_storage_attachments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false t.uuid "record_id", null: false @@ -36,7 +36,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true end - create_table "active_storage_blobs", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "active_storage_blobs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "key", null: false t.string "filename", null: false t.string "content_type" @@ -50,13 +50,13 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_active_storage_blobs_on_university_id" end - create_table "active_storage_variant_records", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "active_storage_variant_records", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "blob_id", null: false t.string "variation_digest", null: false t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true end - create_table "administration_qualiopi_criterions", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "administration_qualiopi_criterions", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.integer "number" t.text "name" t.text "description" @@ -64,7 +64,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.datetime "updated_at", null: false end - create_table "administration_qualiopi_indicators", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "administration_qualiopi_indicators", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "criterion_id", null: false t.integer "number" t.text "name" @@ -95,7 +95,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_communication_block_headings_on_university_id" end - create_table "communication_blocks", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_blocks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "about_type" t.uuid "about_id" @@ -201,7 +201,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_communication_extranet_posts_on_university_id" end - create_table "communication_extranets", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_extranets", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name" t.uuid "university_id", null: false t.string "host" @@ -311,7 +311,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["website_id"], name: "index_communication_website_connections_on_website_id" end - create_table "communication_website_git_files", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_website_git_files", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "previous_path" t.string "about_type", null: false t.uuid "about_id", null: false @@ -323,7 +323,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["website_id"], name: "index_communication_website_git_files_on_website_id" end - create_table "communication_website_menu_items", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_website_menu_items", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "website_id", null: false t.uuid "menu_id", null: false @@ -343,7 +343,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["website_id"], name: "index_communication_website_menu_items_on_website_id" end - create_table "communication_website_menus", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_website_menus", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "communication_website_id", null: false t.string "title" @@ -359,7 +359,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_communication_website_menus_on_university_id" end - create_table "communication_website_pages", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_website_pages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "communication_website_id", null: false t.string "title" @@ -373,10 +373,10 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.boolean "published", default: false t.string "featured_image_alt" t.text "text" - t.text "summary" t.string "breadcrumb_title" t.text "header_text" t.integer "kind" + t.text "summary" t.string "bodyclass" t.uuid "language_id", null: false t.text "featured_image_credit" @@ -392,7 +392,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_communication_website_pages_on_university_id" end - create_table "communication_website_permalinks", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_website_permalinks", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "website_id", null: false t.string "about_type", null: false @@ -406,7 +406,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["website_id"], name: "index_communication_website_permalinks_on_website_id" end - create_table "communication_website_post_categories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_website_post_categories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "communication_website_id", null: false t.string "name" @@ -433,7 +433,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_communication_website_post_categories_on_university_id" end - create_table "communication_website_posts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_website_posts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "communication_website_id", null: false t.string "title" @@ -460,7 +460,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_communication_website_posts_on_university_id" end - create_table "communication_websites", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "communication_websites", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "name" t.string "url" @@ -531,7 +531,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["priority", "run_at"], name: "delayed_jobs_priority" end - create_table "education_academic_years", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "education_academic_years", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.integer "year" t.datetime "created_at", null: false @@ -546,7 +546,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_person_id", "education_academic_year_id"], name: "index_person_academic_year" end - create_table "education_cohorts", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "education_cohorts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "program_id", null: false t.uuid "academic_year_id", null: false @@ -567,7 +567,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_person_id", "education_cohort_id"], name: "index_person_cohort" end - create_table "education_diplomas", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "education_diplomas", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name" t.string "short_name" t.integer "level", default: 0 @@ -582,7 +582,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_education_diplomas_on_university_id" end - create_table "education_programs", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "education_programs", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "name" t.integer "capacity" @@ -643,7 +643,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["education_program_id", "user_id"], name: "index_education_programs_users_on_program_id_and_user_id" end - create_table "education_schools", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "education_schools", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "name" t.string "address" @@ -674,7 +674,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_emergency_messages_on_university_id", where: "(university_id IS NOT NULL)" end - create_table "imports", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "imports", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.integer "number_of_lines" t.jsonb "processing_errors" t.integer "kind" @@ -687,7 +687,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["user_id"], name: "index_imports_on_user_id" end - create_table "languages", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "languages", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name" t.string "iso_code" t.datetime "created_at", null: false @@ -763,7 +763,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_research_journal_paper_kinds_on_university_id" end - create_table "research_journal_papers", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "research_journal_papers", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "title" t.datetime "published_at", precision: nil t.uuid "university_id", null: false @@ -801,7 +801,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["researcher_id"], name: "index_research_journal_papers_researchers_on_researcher_id" end - create_table "research_journal_volumes", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "research_journal_volumes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "research_journal_id", null: false t.string "title" @@ -822,7 +822,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_research_journal_volumes_on_university_id" end - create_table "research_journals", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "research_journals", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "title" t.text "meta_description" @@ -833,7 +833,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_research_journals_on_university_id" end - create_table "research_laboratories", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "research_laboratories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "name" t.string "address" @@ -852,7 +852,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_person_id", "research_laboratory_id"], name: "person_laboratory" end - create_table "research_laboratory_axes", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "research_laboratory_axes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "research_laboratory_id", null: false t.string "name" @@ -866,7 +866,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_research_laboratory_axes_on_university_id" end - create_table "research_theses", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "research_theses", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "research_laboratory_id", null: false t.uuid "author_id", null: false @@ -884,7 +884,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_research_theses_on_university_id" end - create_table "universities", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "universities", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "name" t.string "identifier" t.string "address" @@ -931,7 +931,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_university_organization_categories_on_university_id" end - create_table "university_organizations", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "university_organizations", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "name" t.string "long_name" @@ -974,7 +974,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["organization_id"], name: "index_university_organizations_categories_on_organization_id" end - create_table "university_people", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "university_people", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "user_id" t.string "last_name" @@ -1031,7 +1031,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_university_person_categories_on_university_id" end - create_table "university_person_experiences", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "university_person_experiences", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "person_id", null: false t.uuid "organization_id", null: false @@ -1045,7 +1045,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_university_person_experiences_on_university_id" end - create_table "university_person_involvements", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "university_person_involvements", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.uuid "person_id", null: false t.integer "kind" @@ -1060,7 +1060,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["university_id"], name: "index_university_person_involvements_on_university_id" end - create_table "university_roles", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "university_roles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "target_type" t.uuid "target_id" @@ -1082,7 +1082,7 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_30_132952) do t.index ["user_id"], name: "index_user_favorites_on_user_id" end - create_table "users", id: :uuid, default: -> { "public.gen_random_uuid()" }, force: :cascade do |t| + create_table "users", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "university_id", null: false t.string "first_name" t.string "last_name" diff --git a/test/controllers/extranet/account_controller_test.rb b/test/controllers/extranet/account_controller_test.rb index 058100d742c8be09e59726de228462d0a0beaae2..dacce1be173e7ae06f6c42c50543414c7fa49a74 100644 --- a/test/controllers/extranet/account_controller_test.rb +++ b/test/controllers/extranet/account_controller_test.rb @@ -22,6 +22,6 @@ class Extranet::AccountControllerTest < ActionDispatch::IntegrationTest def test_update_password patch account_path, params: { user: { password: "NewPassw0rd!" } } - assert_redirected_to(account_path) + assert_response(:unprocessable_entity) end end diff --git a/test/fixtures/communication/extranets.yml b/test/fixtures/communication/extranets.yml index c4a72564511a4905256b44eff1b90d9ad95d76db..25967d83f8867a11d1eb0dd3553bcd918c4b285e 100644 --- a/test/fixtures/communication/extranets.yml +++ b/test/fixtures/communication/extranets.yml @@ -45,4 +45,5 @@ default_extranet: name: Extranet de test host: extranet.osuny.test about: default_program (Education::Program) + feature_alumni: true university: default_university diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 936741c8f2ca3149279d765c3a5494e31554020d..2012d80e38e93c1b4f53b5f537acc322a2e558ec 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -61,7 +61,7 @@ alumnus: email: alumnus@osuny.org first_name: Alumnus last_name: Osuny - role: user + role: visitor language: fr university: default_university