diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 428f16b..a85d8b6 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -420,31 +420,22 @@ function rdf_preprocess_username(&$variables) {
   $bundle_mapping = $mapping->getPreparedBundleMapping();
   if (!empty($bundle_mapping['types'])) {
     $attributes['typeof'] = $bundle_mapping['types'];
+
+  // The typeof attribute specifies the RDF type(s) of this resource. They
+  // are defined in the 'rdftype' property of the user RDF mapping.
+  if (!empty($rdf_mapping['rdftype'])) {
+    $variables['attributes']['typeof'] = $rdf_mapping['rdftype'];
   }
   // Annotate the username in RDFa. A property attribute is used with an empty
   // datatype attribute to ensure the username is parsed as a plain literal
   // in RDFa 1.0 and 1.1.
-  $name_mapping = $mapping->getPreparedFieldMapping('name');
-  if (!empty($name_mapping)) {
-    $attributes['property'] = $name_mapping['properties'];
-    $attributes['datatype'] = '';
+  if (!empty($rdf_mapping['name'])) {
+    $variables['attributes']['property'] = $rdf_mapping['name']['predicates'];
+    $variables['attributes']['datatype'] = '';
   }
   // Add the homepage RDFa markup if present.
-  $homepage_mapping = $mapping->getPreparedFieldMapping('homepage');
-  if (!empty($variables['homepage']) && !empty($homepage_mapping)) {
-    $attributes['rel'] = $homepage_mapping['properties'];
-  }
-  // The remaining attributes can have multiple values listed, with whitespace
-  // separating the values in the RDFa attributes
-  // (see http://www.w3.org/TR/rdfa-syntax/#rdfa-attributes).
-  // Therefore, merge rather than override so as not to clobber values set by
-  // earlier preprocess functions. These attributes will be placed in the a
-  // element if a link is rendered, or on a span element otherwise.
-  if (isset($variables['link_path'])) {
-    $variables['link_options']['attributes'] = array_merge_recursive($variables['link_options']['attributes'], $attributes);
-  }
-  else {
-    $variables['attributes'] = array_merge_recursive($variables['attributes'], $attributes);
+  if (!empty($variables['homepage']) && !empty($rdf_mapping['homepage'])) {
+    $variables['attributes']['rel'] = $rdf_mapping['homepage']['predicates'];
   }
 }
 
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 49e87a0..2117126 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -1465,19 +1465,9 @@ function hook_system_info_alter(&$info, $file, $type) {
  *     have inherent security risks across a variety of potential use cases
  *     (for example, the "administer filters" and "bypass node access"
  *     permissions provided by Drupal core). When set to TRUE, a standard
- *     warning message defined in user_admin_permissions() and output via
- *     theme_user_permission_description() will be associated with the
- *     permission and displayed with it on the permission administration page.
- *     Defaults to FALSE.
- *   - warning: (optional) A translated warning message to display for this
- *     permission on the permission administration page. This warning overrides
- *     the automatic warning generated by 'restrict access' being set to TRUE.
- *     This should rarely be used, since it is important for all permissions to
- *     have a clear, consistent security warning that is the same across the
- *     site. Use the 'description' key instead to provide any information that
- *     is specific to the permission you are defining.
- *
- * @see theme_user_permission_description()
+ *     warning message defined in user_admin_permissions() will be displayed
+ *     with the permission on the permission administration page. Defaults
+ *     to FALSE.
  */
 function hook_permission() {
   return array(
diff --git a/core/modules/user/templates/username.html.twig b/core/modules/user/templates/username.html.twig
new file mode 100644
index 0000000..35c64d3
--- /dev/null
+++ b/core/modules/user/templates/username.html.twig
@@ -0,0 +1,32 @@
+{#
+/**
+ * @file
+ * Default theme implementation for displaying a username.
+ *
+ * Available variables:
+ * - account: The full account information for the user.
+ * - name: The user's name, sanitized.
+ * - extra: Additional text to append to the user's name, sanitized.
+ * - link: The link fully generated by l() if link_path is set.
+ * - link_path: The path or URL of the user's profile page, home page,
+ *   or other desired page to link to for more information about the user.
+ * - link_options: Options to pass to the l() function's $options parameter if
+ *   linking the user's name to the user's page.
+ * - attributes: HTML attributes to be used if not linking to the user's page.
+ *
+ * @see template_preprocess()
+ * @see template_preprocess_username()
+ *
+ * @ingroup themeable
+ */
+#}
+{% if link %}
+  {{- link -}}
+{% else %}
+  {#
+    Modules may have added important attributes so they must be included
+    in the output. Additional classes may be added as array elements like
+    {% set attributes.class = attributes.class|merge(["myclass"]) %}
+  #}
+  <span{{ attributes }}>{{ name }}{{ extra }}</span>
+{% endif %}
diff --git a/core/modules/user/user.admin.inc b/core/modules/user/user.admin.inc
index 4caec43..ed1829f 100644
--- a/core/modules/user/user.admin.inc
+++ b/core/modules/user/user.admin.inc
@@ -86,7 +86,73 @@ function user_admin_account() {
   $form['pager'] = array(
     '#theme' =>'pager',
   );
+  // Render role/permission overview:
+  $options = array();
+  $module_info = system_get_info('module');
+  $hide_descriptions = system_admin_compact_mode();
 
+  // Get a list of all the modules implementing a hook_permission() and sort by
+  // display name.
+  $modules = array();
+  foreach (module_implements('permission') as $module) {
+    $modules[$module] = $module_info[$module]['name'];
+  }
+  asort($modules);
+
+  foreach ($modules as $module => $display_name) {
+    if ($permissions = module_invoke($module, 'permission')) {
+      $form['permission'][] = array(
+        '#markup' => $module_info[$module]['name'],
+        '#id' => $module,
+      );
+      foreach ($permissions as $perm => $perm_item) {
+        // Fill in default values for the permission.
+        $perm_item += array(
+          'description' => '',
+          'restrict access' => FALSE,
+        );
+        $options[$perm] = '';
+        // Show the permission description.
+        if (!$hide_descriptions) {
+          $description = $perm_item['description'];
+          // Append warning message.
+          if (!empty($perm_item['restrict access'])) {
+            $description .= ' <em class="permission-warning">' . t('Warning: Give to trusted roles only; this permission has security implications.') . '</em>';
+          }
+        }
+        else {
+          $description = '';
+        }
+        $form['permission'][$perm] = array(
+          '#type' => 'item',
+          '#markup' => $perm_item['title'],
+          '#description' => trim($description),
+        );
+        foreach ($role_names as $rid => $name) {
+          // Builds arrays for checked boxes for each role
+          if (isset($role_permissions[$rid][$perm])) {
+            $status[$rid][] = $perm;
+          }
+        }
+      }
+    }
+  }
+
+  // Have to build checkboxes here after checkbox arrays are built
+  foreach ($role_names as $rid => $name) {
+    $form['checkboxes'][$rid] = array(
+      '#type' => 'checkboxes',
+      '#options' => $options,
+      '#default_value' => isset($status[$rid]) ? $status[$rid] : array(),
+      '#attributes' => array('class' => array('rid-' . $rid)),
+    );
+    $form['role_names'][$rid] = array('#markup' => check_plain($name), '#tree' => TRUE);
+  }
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save permissions'));
+
+  $form['#attached']['library'][] = array('user', 'drupal.user.permissions');
   return $form;
 }
 
@@ -119,4 +185,81 @@ function theme_user_permission_description($variables) {
       return implode(' ', $description);
     }
   }
+/** Save permissions selected on the administer permissions page.
+ *
+ * @see user_admin_permissions()
+ */
+function user_admin_permissions_submit($form, &$form_state) {
+  foreach ($form_state['values']['role_names'] as $rid => $name) {
+    user_role_change_permissions($rid, $form_state['values'][$rid]);
+  }
+
+  drupal_set_message(t('The changes have been saved.'));
+
+  // Clear the cached pages and blocks.
+  cache_invalidate_tags(array('content' => TRUE));
+}
+
+/**
+ * Returns HTML for the administer permissions page.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - form: A render element representing the form.
+ *
+ * @ingroup themeable
+ */
+function theme_user_admin_permissions($variables) {
+  $form = $variables['form'];
+
+  $roles = user_role_names();
+  foreach (element_children($form['permission']) as $key) {
+    $row = array();
+    // Module name
+    if (is_numeric($key)) {
+      $row[] = array('data' => drupal_render($form['permission'][$key]), 'class' => array('module'), 'id' => 'module-' . $form['permission'][$key]['#id'], 'colspan' => count($form['role_names']['#value']) + 1);
+    }
+    else {
+      // Permission row.
+      $row[] = array(
+        'data' => drupal_render($form['permission'][$key]),
+        'class' => array('permission'),
+      );
+      foreach (element_children($form['checkboxes']) as $rid) {
+        $form['checkboxes'][$rid][$key]['#title'] = $roles[$rid] . ': ' . $form['permission'][$key]['#markup'];
+        $form['checkboxes'][$rid][$key]['#title_display'] = 'invisible';
+        $row[] = array('data' => drupal_render($form['checkboxes'][$rid][$key]), 'class' => array('checkbox'));
+      }
+    }
+    $rows[] = $row;
+  }
+  $header[] = (t('Permission'));
+  foreach (element_children($form['role_names']) as $rid) {
+    $header[] = array('data' => drupal_render($form['role_names'][$rid]), 'class' => array('checkbox'));
+  }
+  $output = theme('system_compact_link');
+  $output .= theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => array('id' => 'permissions')));
+  $output .= drupal_render_children($form);
+  return $output;
+}
+
+/**
+ * Page callback: Lists roles and allows to reorder them.
+ *
+ * @see user_menu()
+ */
+function user_admin_roles_list() {
+  return Drupal::entityManager()
+    ->getListController('user_role')->render();
+}
+
+/**
+ * Page callback: Presents the role creation form.
+ *
+ * @see user_menu()
+ */
+function user_admin_role_add() {
+  drupal_set_title(t('Add role'));
+  $role = entity_create('user_role', array());
+  return entity_get_form($role);
 }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 91e7ee1..7f2e476 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -98,15 +98,13 @@ function user_theme() {
       'file' => 'user.pages.inc',
       'template' => 'user',
     ),
-    'user_permission_description' => array(
-      'variables' => array('permission_item' => NULL, 'hide' => NULL),
+    'user_admin_permissions' => array(
+      'render element' => 'form',
       'file' => 'user.admin.inc',
     ),
-    'user_signature' => array(
-      'variables' => array('signature' => NULL),
-    ),
     'username' => array(
-      'variables' => array('account' => NULL, 'attributes' => array()),
+      'variables' => array('account' => NULL),
+      'template' => 'username',
     ),
   );
 }
@@ -668,7 +666,9 @@ function user_template_preprocess_default_variables_alter(&$variables) {
 }
 
 /**
- * Preprocesses variables for theme_username().
+ * Prepares variables for username templates.
+ *
+ * Default template: username.html.twig.
  *
  * Modules that make any changes to variables like 'name' or 'extra' must ensure
  * that the final string is safe to include directly in the output by using
@@ -714,40 +714,32 @@ function template_preprocess_username(&$variables) {
   // We do not want the l() function to check_plain() a second time.
   $variables['link_options']['html'] = TRUE;
   // Set a default class.
-  $variables['link_options']['attributes']['class'] = array('username');
+  $variables['attributes'] = array('class' => array('username'));
 }
 
 /**
- * Returns HTML for a username, potentially linked to the user's page.
- *
- * @param $variables
- *   An associative array containing:
- *   - account: The user object to format.
- *   - name: The user's name, sanitized.
- *   - extra: Additional text to append to the user's name, sanitized.
- *   - link_path: The path or URL of the user's profile page, home page, or
- *     other desired page to link to for more information about the user.
- *   - link_options: An array of options to pass to the l() function's $options
- *     parameter if linking the user's name to the user's page.
- *   - attributes: An array of attributes to instantiate the
- *     Drupal\Core\Template\Attribute class if not linking to the user's page.
+ * Processes variables for username templates.
  *
  * @see template_preprocess_username()
  */
-function theme_username($variables) {
+function template_process_username(&$variables) {
+  // Finalize the link_options array for passing to the l() function.
+  // This is done in the process phase so that attributes may be added by
+  // modules or the theme during the preprocess phase.
   if (isset($variables['link_path'])) {
-    // We have a link path, so we should generate a link using l().
-    // Additional classes may be added as array elements like
-    // $variables['link_options']['attributes']['class'][] = 'myclass';
-    $output = l($variables['name'] . $variables['extra'], $variables['link_path'], $variables['link_options']);
+    // $variables['attributes'] contains attributes that should be applied
+    // regardless of whether a link is being rendered or not.
+    // $variables['link_attributes'] contains attributes that should only be
+    // applied if a link is being rendered. Preprocess functions are encouraged
+    // to use the former unless they want to add attributes on the link only.
+    // If a link is being rendered, these need to be merged. Some attributes are
+    // themselves arrays, so the merging needs to be recursive.
+    // This purposefully does not use
+    // \Drupal\Component\Utility\NestedArray::mergeDeep() for performance
+    // reasons, since it is potentially called very often.
+    $variables['link_options']['attributes'] = array_merge_recursive($variables['link_attributes'], $variables['attributes']);
+    $variables['link'] = l($variables['name'] . $variables['extra'], $variables['link_path'], $variables['link_options']);
   }
-  else {
-    // Modules may have added important attributes so they must be included
-    // in the output. Additional classes may be added as array elements like
-    // $variables['attributes']['class'][] = 'myclass';
-    $output = '<span' . new Attribute($variables['attributes']) . '>' . $variables['name'] . $variables['extra'] . '</span>';
-  }
-  return $output;
 }
 
 /**
@@ -1413,8 +1405,8 @@ function user_view_page($account) {
  * - $page['content']['#user']:
  *   The user account of the profile being viewed.
  *
- * To theme user profiles, copy modules/user/user.tpl.php
- * to your theme directory, and edit it as instructed in that file's comments.
+ * To theme user profiles, copy modules/user/user.html.twig to your theme
+ * directory, and edit it as instructed in that file's comments.
  *
  * @param $account
  *   A user object.
@@ -1843,6 +1835,121 @@ function theme_user_signature($variables) {
 
   return $output;
 }
+/**
+ * List user administration filters that can be applied.
+ */
+function user_filters() {
+  // Regular filters
+  $filters = array();
+  $roles = user_role_names(TRUE);
+  unset($roles[DRUPAL_AUTHENTICATED_RID]); // Don't list authorized role.
+  if (count($roles)) {
+    $filters['role'] = array(
+      'title' => t('role'),
+      'field' => 'ur.rid',
+      'options' => array(
+        '[any]' => t('any'),
+      ) + $roles,
+    );
+  }
+
+  $options = array();
+  foreach (module_implements('permission') as $module) {
+    $function = $module . '_permission';
+    if ($permissions = $function()) {
+      asort($permissions);
+      foreach ($permissions as $permission => $description) {
+        $options[t('@module module', array('@module' => $module))][$permission] = t($permission);
+      }
+    }
+  }
+  ksort($options);
+  $filters['permission'] = array(
+    'title' => t('permission'),
+    'options' => array(
+      '[any]' => t('any'),
+    ) + $options,
+  );
+
+  $filters['status'] = array(
+    'title' => t('status'),
+    'field' => 'u.status',
+    'options' => array(
+      '[any]' => t('any'),
+      1 => t('active'),
+      0 => t('blocked'),
+    ),
+  );
+  return $filters;
+}
+
+/**
+ * Extends a query object for user administration filters based on session.
+ *
+ * @param $query
+ *   Query object that should be filtered.
+ */
+function user_build_filter_query(SelectInterface $query) {
+  $filters = user_filters();
+  // Extend Query with filter conditions.
+  foreach (isset($_SESSION['user_overview_filter']) ? $_SESSION['user_overview_filter'] : array() as $filter) {
+    list($key, $value) = $filter;
+    // This checks to see if this permission filter is an enabled permission for
+    // the authenticated role. If so, then all users would be listed, and we can
+    // skip adding it to the filter query.
+    if ($key == 'permission') {
+      $account = entity_create('user', array());
+      $account->uid = 'user_filter';
+      $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);
+      if (user_access($value, $account)) {
+        continue;
+      }
+      $users_roles_alias = $query->join('users_roles', 'ur', '%alias.uid = u.uid');
+      $permission_alias = $query->join('role_permission', 'p', $users_roles_alias . '.rid = %alias.rid');
+      $query->condition($permission_alias . '.permission', $value);
+    }
+    elseif ($key == 'role') {
+      $users_roles_alias = $query->join('users_roles', 'ur', '%alias.uid = u.uid');
+      $query->condition($users_roles_alias . '.rid' , $value);
+    }
+    else {
+      $query->condition($filters[$key]['field'], $value);
+    }
+  }
+}
+
+/**
+ * Get the language object preferred by the user. This user preference can
+ * be set on the user account editing page, and is only available if there
+ * are more than one languages enabled on the site. If the user did not
+ * choose a preferred language, or is the anonymous user, the $default
+ * value, or if it is not set, the site default language will be returned.
+ *
+ * @param $account
+ *   User account to look up language for.
+ * @param $type
+ *   Optional string to define which preferred langcode should be used.
+ *   Default to 'preferred_langcode' property.
+ *   If set 'preferred_$type_langcode' is used.
+ * @param $default
+ *   Optional default language code to return if the account
+ *   has no valid language.
+ */
+function user_preferred_langcode($account, $type = NULL, $default = NULL) {
+  $language_list = language_list();
+  if (isset($type)) {
+    $preferred_langcode = $account->{'preferred_' . $type . '_langcode'};
+  }
+  else {
+    $preferred_langcode = $account->preferred_langcode;
+  }
+  if (!empty($preferred_langcode) && isset($language_list[$preferred_langcode])) {
+    return $language_list[$preferred_langcode]->langcode;
+  }
+  else {
+    return $default ? $default : language_default()->langcode;
+  }
+}
 
 /**
  * Conditionally create and send a notification email when a certain
