diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 36cb5ed0b39a8b735c9071d43505f253d6b837b8..1cdadc2ae8ac07723f3ae7f42c6a330b06c38052 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -78,7 +78,7 @@ class Admin::UsersController < Admin::ApplicationController
 
   def user_params
     params.require(:user)
-          .permit(:email, :first_name, :last_name, :role, :password, :language_id, :picture, :picture_delete, :picture_infos, :mobile_phone, programs_to_manage_ids: [])
+          .permit(:email, :first_name, :last_name, :role, :password, :language_id, :picture, :picture_delete, :picture_infos, :mobile_phone, programs_to_manage_ids: [], websites_to_manage_ids: [])
           .merge(university_id: current_university.id)
   end
 
diff --git a/app/models/ability.rb b/app/models/ability.rb
index b43d5ffcc1670531bc9f6847a3213f9fbdbcc732..6c2f3d356078ac95873381ad366a5b5b64a320ec 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -50,6 +50,16 @@ class Ability
     can :manage, Communication::Website::Post, university_id: @user.university_id
   end
 
+  def website_manager
+    managed_websites_ids = @user.websites_to_manage.pluck(:communication_website_id)
+    can :read, Communication::Website, university_id: @user.university_id, id: managed_websites_ids
+    can :manage, Communication::Website::Page, university_id: @user.university_id, communication_website_id: managed_websites_ids
+    can :manage, Communication::Website::Post, university_id: @user.university_id, communication_website_id: managed_websites_ids
+    can :manage, Communication::Website::Category, university_id: @user.university_id, communication_website_id: managed_websites_ids
+    can [:read, :update, :reorder], Communication::Website::Menu, university_id: @user.university_id, communication_website_id: managed_websites_ids
+    can :manage, Communication::Website::Menu::Item, university_id: @user.university_id, website_id: managed_websites_ids
+  end
+
   def admin
     can :read, Administration::Qualiopi::Criterion
     can :read, Administration::Qualiopi::Indicator
diff --git a/app/models/user/with_roles.rb b/app/models/user/with_roles.rb
index aeced21b870114381519cb54074d7d648eaa9879..057f89407ace0cd08f96014b702fd766875e01c6 100644
--- a/app/models/user/with_roles.rb
+++ b/app/models/user/with_roles.rb
@@ -4,13 +4,18 @@ module User::WithRoles
   included do
     attr_accessor :modified_by
 
-    enum role: { visitor: 0, teacher: 10, program_manager: 12, admin: 20, server_admin: 30 }
+    enum role: { visitor: 0, teacher: 10, program_manager: 12, website_manager: 15, admin: 20, server_admin: 30 }
 
     has_and_belongs_to_many :programs_to_manage,
                             class_name: 'Education::Program',
                             join_table: 'education_programs_users',
                             association_foreign_key: 'education_program_id'
 
+    has_and_belongs_to_many :websites_to_manage,
+                            class_name: 'Communication::Website',
+                            join_table: 'communication_websites_users',
+                            association_foreign_key: 'communication_website_id'
+
     scope :for_role, -> (role) { where(role: role) }
 
     before_validation :set_default_role, on: :create
diff --git a/app/views/admin/dashboard/index.html.erb b/app/views/admin/dashboard/index.html.erb
index 06139d6319f2d2cd80d83698d1b671bde6bd88dc..4df287ce4de9a1685862a8367b2e03b4cc29e664 100644
--- a/app/views/admin/dashboard/index.html.erb
+++ b/app/views/admin/dashboard/index.html.erb
@@ -1,10 +1,10 @@
-<% content_for :title, 'Tableau de bord' %>
+<% content_for :title, t('admin.dashboard') %>
 
 <div class="row">
   <div class="col-md-4">
     <div class="card">
       <div class="card-body">
-        <h4>Bonjour <%= current_user.first_name %>&nbsp;!</h4>
+        <h4><%= t('hello', name: current_user.first_name) %></h4>
         <% if current_university.logo.attached? %>
           <%= image_tag current_university.logo, width: 120, class: 'float-end' %>
         <% else %>
@@ -19,13 +19,14 @@
   <h2 class="h4 my-4"><%= Research::Journal.model_name.human(count: 2) %></h2>
   <div class="row">
     <% current_university.research_journals.each do |journal| %>
+      <% next unless can?(:read, journal) %>
       <div class="col-md-4">
         <div class="card">
           <div class="card-body">
             <span class="float-end"><i class="fas fa-newspaper fa-2x"></i></span>
             <h4><%= journal %></h4>
             <p>&nbsp;</p>
-            <%= link_to 'Voir', [:admin, journal], class: button_classes('stretched-link') %>
+            <%= link_to t('show'), [:admin, journal], class: button_classes('stretched-link') %>
           </div>
         </div>
       </div>
@@ -37,13 +38,14 @@
   <h2 class="h4 my-4"><%= Communication::Website.model_name.human(count: 2) %></h2>
   <div class="row">
     <% current_university.communication_websites.each do |website| %>
+      <% next unless can?(:read, website) %>
       <div class="col-md-4">
         <div class="card">
           <div class="card-body">
             <span class="float-end"><i class="fas fa-sitemap fa-2x"></i></span>
             <h4><%= website %></h4>
             <p class="small"><%= website.url %></p>
-            <%= link_to 'Voir', [:admin, website], class: button_classes('stretched-link') %>
+            <%= link_to t('show'), [:admin, website], class: button_classes('stretched-link') %>
           </div>
         </div>
       </div>
diff --git a/app/views/admin/users/_form.html.erb b/app/views/admin/users/_form.html.erb
index 6123085cb096c77b6e8ceca267f5e6f78b83db83..98e997371856936bff52590bca508a2f863f0526 100644
--- a/app/views/admin/users/_form.html.erb
+++ b/app/views/admin/users/_form.html.erb
@@ -37,6 +37,12 @@
                               label_method: ->(p) { sanitize p[:label] },
                               value_method: ->(p) { p[:id] } %>
           </div>
+          <div data-show-for-roles="website_manager">
+            <%= f.association :websites_to_manage,
+                              as: :check_boxes,
+                              collection: current_university.communication_websites.ordered
+                               %>
+          </div>
         </div>
       </div>
     </div>
diff --git a/app/views/admin/users/show.html.erb b/app/views/admin/users/show.html.erb
index 9215009724a355b91993f4fbfde5be18e0f947bb..462cb95476da9120e8e2809aac27756f30ddde6e 100644
--- a/app/views/admin/users/show.html.erb
+++ b/app/views/admin/users/show.html.erb
@@ -13,12 +13,16 @@
           <td><%= User.human_attribute_name('email') %></td>
           <td class="text-end"><%= link_to @user.email, "mailto:#{@user.email}" %></td>
         </tr>
-        <% ['first_name', 'last_name', 'role', 'mobile_phone'].each do |variable| %>
+        <% ['first_name', 'last_name', 'mobile_phone'].each do |variable| %>
           <tr>
             <td><%= User.human_attribute_name(variable) %></td>
             <td class="text-end"><%= @user.public_send variable %></td>
           </tr>
         <% end %>
+        <tr>
+          <td><%= User.human_attribute_name('role') %></td>
+          <td class="text-end"><%= t("activerecord.attributes.user.roles.#{@user.role.to_s}") %></td>
+        </tr>
         <tr>
           <td><%= User.human_attribute_name('language') %></td>
           <td class="text-end"><%= t("languages.#{@user.language.iso_code.to_s}") %></td>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 8538d27eb48f587533903c9e0aaf7453a2edba81..6234469eb7ede1299f0c38c743937ab6b855f258 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -20,6 +20,7 @@ en:
           server_admin: Server admin
           teacher: Teacher
           visitor: Visitor
+          website_manager: Website manager
     errors:
       models:
         user:
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 9cd2fafc670f3327bcac2c4f1b85ec7319a61361..5d3348026e9b0d18552f458dae4867bff8d04ee7 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -20,6 +20,7 @@ fr:
           server_admin: Administrateur du serveur
           teacher: Enseignant·e
           visitor: Visiteur
+          website_manager: Responsable de site web
     errors:
       models:
         user:
diff --git a/db/migrate/20220303145900_create_join_table_communication_websites_users.rb b/db/migrate/20220303145900_create_join_table_communication_websites_users.rb
new file mode 100644
index 0000000000000000000000000000000000000000..742d66025e622acde37d5463ad661a7f7fb0d06a
--- /dev/null
+++ b/db/migrate/20220303145900_create_join_table_communication_websites_users.rb
@@ -0,0 +1,8 @@
+class CreateJoinTableCommunicationWebsitesUsers < ActiveRecord::Migration[6.1]
+  def change
+    create_join_table :communication_websites, :users, column_options: {type: :uuid} do |t|
+      t.index [:communication_website_id, :user_id], name: 'website_user'
+      t.index [:user_id, :communication_website_id], name: 'user_website'
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0c898ee2263531f05ff0dfa7129422c3a4f893e6..3853ceb6311cd03761f3624ce0cae9fc392cebf0 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 2022_03_03_125819) do
+ActiveRecord::Schema.define(version: 2022_03_03_145900) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
@@ -362,6 +362,13 @@ ActiveRecord::Schema.define(version: 2022_03_03_125819) do
     t.index ["university_id"], name: "index_communication_websites_on_university_id"
   end
 
+  create_table "communication_websites_users", id: false, force: :cascade do |t|
+    t.uuid "communication_website_id", null: false
+    t.uuid "user_id", null: false
+    t.index ["communication_website_id", "user_id"], name: "website_user"
+    t.index ["user_id", "communication_website_id"], name: "user_website"
+  end
+
   create_table "delayed_jobs", force: :cascade do |t|
     t.integer "priority", default: 0, null: false
     t.integer "attempts", default: 0, null: false