diff --git commit_restrictions/commit_restrictions.module commit_restrictions/commit_restrictions.module
index 7fe66db..2fa39de 100644
--- commit_restrictions/commit_restrictions.module
+++ commit_restrictions/commit_restrictions.module
@@ -9,86 +9,98 @@
  */
 
 /**
- * Implementation of hook_form_alter(): Add commit restriction settings
- * to the add/edit repository form of the Version Control API module.
+ * Implementation of hook_form_FORM_ID_alter().
  */
-function commit_restrictions_form_alter(&$form, &$form_state, $form_id) {
-  if ($form['#id'] == 'versioncontrol-repository-form') {
-    $backends = versioncontrol_get_backends();
-    $backend_capabilities = $backends[$form['#vcs']]->capabilities;
-    $restrictions = array();
-
-    if (isset($form['#repository']) && !empty($form['#repository']['data']['commit_restrictions'])) {
-      $restrictions = $form['#repository']['data']['commit_restrictions'];
-    }
+function commit_restrictions_form_versioncontrol_repository_form_alter(&$form, &$form_state) {
+  // Add commit restriction settings to the add/edit repository form
 
-    if (in_array(VERSIONCONTROL_CAPABILITY_COMMIT_RESTRICTIONS, $backend_capabilities)) {
-      $form['commit_restrictions']['allowed_paths'] = array(
-        '#type' => 'textfield',
-        '#title' => t('Freely accessible paths'),
-        '#description' => t('A space-separated list of PHP regular expressions for directories or files that will always be granted commit access to everyone, no matter what other commit restrictions are imposed. Example: "@.*\.(po|pot)$@ @^/contributions/(docs|sandbox|tricks)/@"'),
-        '#default_value' => isset($restrictions['allowed_paths'])
-          ? implode(' ', $restrictions['allowed_paths'])
-          : '',
-        '#size' => 60,
-        '#weight' => 10,
-      );
-      $form['commit_restrictions']['deny_undefined_paths'] = array(
-        '#type' => 'checkbox',
-        '#title' => t('Deny access to all other paths'),
-        '#description' => t('If this is enabled, no paths other than the ones given above will be granted commit access, except if there is an exception that specifically allows the commit to happen.'),
-        '#default_value' => isset($restrictions['deny_undefined_paths'])
-          ? FALSE
-          : $restrictions['deny_undefined_paths'],
-        '#weight' => 11,
-      );
-      $form['commit_restrictions']['forbidden_paths'] = array(
-        '#type' => 'textfield',
-        '#title' => t('Forbidden paths'),
-        '#description' => t('A space-separated list of PHP regular expressions for directories or files that will be denied access to everyone, except if there is an exception that specifically allows the commit to happen. Example: "@^/contributions/profiles.*(?&lt;!\.profile|\.txt)$@ @^.*\.(gz|tgz|tar|zip)$@"'),
-        '#default_value' => isset($restrictions['forbidden_paths'])
-          ? implode(' ', $restrictions['forbidden_paths'])
-          : '',
-        '#size' => 60,
-        '#weight' => 12,
-      );
-    }
-    if (in_array(VERSIONCONTROL_CAPABILITY_BRANCH_TAG_RESTRICTIONS, $backend_capabilities)) {
-      $form['branch_tag_restrictions'] = array(
-        '#type' => 'fieldset',
-        '#title' => t('Branch and tag restrictions'),
-        '#collapsible' => TRUE,
-        '#collapsed' => TRUE,
-        '#weight' => 7,
-      );
-      $form['branch_tag_restrictions']['valid_branch_tag_paths'] = array(
-        '#type' => 'textfield',
-        '#title' => t('Allowed paths for branches and tags'),
-        '#description' => t('A space-separated list of PHP regular expressions for directories or files where it will be possible to create branches and tags. If empty, branches and tags may be created anywhere in the repository. Example: "@^(/[^/]+)?/(modules|themes|theme-engines|docs|translations)/@"'),
-        '#default_value' => isset($restrictions['valid_branch_tag_paths'])
-          ? implode(' ', $restrictions['valid_branch_tag_paths'])
-          : '',
-        '#size' => 60,
-      );
-      $form['branch_tag_restrictions']['valid_branches'] = array(
-        '#type' => 'textfield',
-        '#title' => t('Valid branches'),
-        '#description' => t('A space-separated list of PHP regular expressions for allowed branch names. If empty, all branch names will be allowed. Example: "@^HEAD$@ @^DRUPAL-5(--[2-9])?$@ @^DRUPAL-6--[1-9]$@"'),
-        '#default_value' => isset($restrictions['valid_branches'])
-          ? implode(' ', $restrictions['valid_branches'])
-          : '',
-        '#size' => 60,
-      );
-      $form['branch_tag_restrictions']['valid_tags'] = array(
-        '#type' => 'textfield',
-        '#title' => t('Valid tags'),
-        '#description' => t('A space-separated list of PHP regular expressions for allowed tag names. If empty, all tag names will be allowed. Example: "@^DRUPAL-[56]--(\d+)-(\d+)(-[A-Z0-9]+)?$@"'),
-        '#default_value' => isset($restrictions['valid_tags'])
-          ? implode(' ', $restrictions['valid_tags'])
-          : '',
-        '#size' => 60,
-      );
-    }
+  $backends = versioncontrol_get_backends();
+  $backend_capabilities = $backends[$form['#vcs']]->capabilities;
+  $restrictions = array();
+
+  if (isset($form['#repository']) && !empty($form['#repository']->data['commit_restrictions'])) {
+    $restrictions = $form['#repository']->data['commit_restrictions'];
+  }
+
+  $backend_can_restrict_commits = in_array(VERSIONCONTROL_CAPABILITY_COMMIT_RESTRICTIONS, $backend_capabilities);
+  $backend_can_restrict_tags    = in_array(VERSIONCONTROL_CAPABILITY_BRANCH_TAG_RESTRICTIONS, $backend_capabilities);
+
+  if ($backend_can_restrict_commits || $backend_can_restrict_tags) {
+    $form['commit_restrictions'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Commit restrictions'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#weight' => 10,
+    );
+  }
+
+  if ($backend_can_restrict_commits) {
+    $form['commit_restrictions']['allowed_paths'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Freely accessible paths'),
+      '#description' => t('A space-separated list of PHP regular expressions for directories or files that will always be granted commit access to everyone, no matter what other commit restrictions are imposed. Example: "@.*\.(po|pot)$@ @^/contributions/(docs|sandbox|tricks)/@"'),
+      '#default_value' => isset($restrictions['allowed_paths'])
+      ? implode(' ', $restrictions['allowed_paths'])
+      : '',
+      '#size' => 60,
+      '#weight' => 10,
+    );
+    $form['commit_restrictions']['deny_undefined_paths'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Deny access to all other paths'),
+      '#description' => t('If this is enabled, no paths other than the ones given above will be granted commit access, except if there is an exception that specifically allows the commit to happen.'),
+      '#default_value' => isset($restrictions['deny_undefined_paths'])
+      ? FALSE
+      : $restrictions['deny_undefined_paths'],
+      '#weight' => 11,
+    );
+    $form['commit_restrictions']['forbidden_paths'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Forbidden paths'),
+      '#description' => t('A space-separated list of PHP regular expressions for directories or files that will be denied access to everyone, except if there is an exception that specifically allows the commit to happen. Example: "@^/contributions/profiles.*(?&lt;!\.profile|\.txt)$@ @^.*\.(gz|tgz|tar|zip)$@"'),
+      '#default_value' => isset($restrictions['forbidden_paths'])
+      ? implode(' ', $restrictions['forbidden_paths'])
+      : '',
+      '#size' => 60,
+      '#weight' => 12,
+    );
+  }
+  if ($backend_can_restrict_tags) {
+    $form['branch_tag_restrictions'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Branch and tag restrictions'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#weight' => 7,
+    );
+    $form['branch_tag_restrictions']['valid_branch_tag_paths'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Allowed paths for branches and tags'),
+      '#description' => t('A space-separated list of PHP regular expressions for directories or files where it will be possible to create branches and tags. If empty, branches and tags may be created anywhere in the repository. Example: "@^(/[^/]+)?/(modules|themes|theme-engines|docs|translations)/@"'),
+      '#default_value' => isset($restrictions['valid_branch_tag_paths'])
+      ? implode(' ', $restrictions['valid_branch_tag_paths'])
+      : '',
+      '#size' => 60,
+    );
+    $form['branch_tag_restrictions']['valid_branches'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Valid branches'),
+      '#description' => t('A space-separated list of PHP regular expressions for allowed branch names. If empty, all branch names will be allowed. Example: "@^HEAD$@ @^DRUPAL-5(--[2-9])?$@ @^DRUPAL-6--[1-9]$@"'),
+      '#default_value' => isset($restrictions['valid_branches'])
+      ? implode(' ', $restrictions['valid_branches'])
+      : '',
+      '#size' => 60,
+    );
+    $form['branch_tag_restrictions']['valid_tags'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Valid tags'),
+      '#description' => t('A space-separated list of PHP regular expressions for allowed tag names. If empty, all tag names will be allowed. Example: "@^DRUPAL-[56]--(\d+)-(\d+)(-[A-Z0-9]+)?$@"'),
+      '#default_value' => isset($restrictions['valid_tags'])
+      ? implode(' ', $restrictions['valid_tags'])
+      : '',
+      '#size' => 60,
+    );
   }
 }
 
diff --git includes/VersioncontrolAccount.php includes/VersioncontrolAccount.php
deleted file mode 100644
index 91d6bdc..0000000
--- includes/VersioncontrolAccount.php
+++ /dev/null
@@ -1,154 +0,0 @@
-<?php
-// $Id: VersioncontrolAccount.php,v 1.12 2010/12/06 03:23:44 marvil07 Exp $
-/**
- * @file
- * Account class
- */
-
-/**
- * Account class
- *
- * This class provides the way to manage users accounts.
- */
-abstract class VersioncontrolAccount extends VersioncontrolEntity {
-  /**
-   * The username, as it is represented by the VCS.
-   *
-   * @var string
-   */
-  public $vcs_username = '';
-
-  /**
-   * The uid of the associated Drupal user.
-   *
-   * If 0, indicates that there is no known associated Drupal user. Code using
-   * this class should construct their behaviors to respect this magic value.
-   *
-   * @var int
-   */
-  public $uid = 0;
-
-  public $repo_id;
-
-  /**
-   * Update a VCS user account in the database, and call the necessary
-   * module hooks. The account repository and uid must stay the same values as
-   * the one given on account creation, whereas vcs_username and
-   * data data members can change.
-   *
-   * FIXME use same logic as in other classes, this probably would
-   * be changed only when we get account_id PK schema change in.
-   * TODO review performance impact of updating the vcs_username since
-   * original jpetso work try to avoid to update if not needed by passing
-   * it as parameter.
-   */
-  public function update($options = array()) {
-    // Append default options.
-    $options += $this->defaultCrudOptions['update'];
-
-    $repo_id = $this->repository->repo_id;
-
-    db_query("UPDATE {versioncontrol_accounts}
-      SET vcs_username = '%s'
-      WHERE uid = %d AND repo_id = %d",
-      $this->vcs_username, $this->uid, $repo_id
-    );
-
-    // Update operations table.
-    // this is assuming 1-1 relation between accounts and uid's
-    //   1. unassign all uid related operations
-    db_query('update {versioncontrol_operations}
-              set author_uid = 0
-              where author_uid = %d and repo_id = %d',
-              $this->uid, $this->repository->repo_id);
-    db_query('update {versioncontrol_operations}
-              set committer_uid = 0
-              where committer_uid = %d and repo_id = %d',
-              $this->uid, $this->repository->repo_id);
-    //   2. assingn all operations related to repo and vcs username
-    db_query("UPDATE {versioncontrol_operations}
-              SET author_uid = %d
-              WHERE author = '%s' AND repo_id = %d",
-              $this->uid, $this->vcs_username, $this->repository->repo_id);
-    db_query("UPDATE {versioncontrol_operations}
-              SET committer_uid = %d
-              WHERE committer = '%s' AND repo_id = %d",
-              $this->uid, $this->vcs_username, $this->repository->repo_id);
-    // not using data field for now, but backends can
-
-    // Let the backend take action.
-    $this->backendUpdate($options);
-
-    // Everything's done, invoke the hook.
-    module_invoke_all('versioncontrol_entity_account_update', $this);
-    return $this;
-  }
-
-  /**
-   * Insert a VCS user account into the database,
-   * and call the necessary module hooks.
-   *
-   * FIXME use same logic as in other classes, this probably would
-   * be changed only when we get account_id PK schema change in.
-   */
-  public function insert($options = array()) {
-    // Append default options.
-    $options += $this->defaultCrudOptions['insert'];
-
-    // not using data field for now, but backends can
-    db_query(
-      "INSERT INTO {versioncontrol_accounts} (uid, repo_id, vcs_username)
-       VALUES (%d, %d, '%s')", $this->uid, $this->repository->repo_id, $this->vcs_username
-    );
-
-    // Provide an opportunity for the backend to add its own stuff.
-    $this->backendInsert($options);
-
-    // Update the operations table.
-    db_query("UPDATE {versioncontrol_operations}
-              SET author_uid = %d
-              WHERE author = '%s' AND repo_id = %d",
-              $this->uid, $this->vcs_username, $this->repository->repo_id);
-    db_query("UPDATE {versioncontrol_operations}
-              SET committer_uid = %d
-              WHERE committer = '%s' AND repo_id = %d",
-              $this->uid, $this->vcs_username, $this->repository->repo_id);
-
-    // Everything's done, invoke the hook.
-    module_invoke_all('versioncontrol_entity_account_insert', $this);
-    return $this;
-  }
-
-  /**
-   * Delete a VCS user account from the database, set all commits with this
-   * account as author to user 0 (anonymous), and call the necessary hooks.
-   *
-   * FIXME use same logic as in other classes, this probably would
-   * be changed only when we get account_id PK schema change in.
-   */
-  public function delete($options = array()) {
-    // Append default options.
-    $options += $this->defaultCrudOptions['delete'];
-
-    // Update the operations table.
-    db_query('update {versioncontrol_operations}
-              set author_uid = 0
-              where author_uid = %d and repo_id = %d',
-              $this->uid, $this->repository->repo_id);
-    db_query('update {versioncontrol_operations}
-              set committer_uid = 0
-              where committer_uid = %d and repo_id = %d',
-              $this->uid, $this->repository->repo_id);
-
-    db_delete('versioncontrol_accounts')
-      ->condition('uid', $this->uid)
-      ->condition('repo_id', $this->repo_id)
-      ->execute();
-
-    // Provide an opportunity for the backend to delete its own stuff.
-    $this->backendDelete($options);
-
-    module_invoke_all('versioncontrol_entity_account_delete', $this);
-  }
-
-}
diff --git includes/VersioncontrolOperation.php includes/VersioncontrolOperation.php
index 35b8788..3b05f04 100644
--- includes/VersioncontrolOperation.php
+++ includes/VersioncontrolOperation.php
@@ -121,12 +121,6 @@ abstract class VersioncontrolOperation extends VersioncontrolEntity {
     'delete' => array('nested' => TRUE),
   );
 
-  /**
-   * Error messages used mainly to get descriptions of errors at
-   * hasWriteAccess().
-   */
-  private static $error_messages = array();
-
   public function loadItemRevisions($ids = array(), $conditions = array(), $options = array()) {
     $conditions['repo_id'] = $this->repo_id;
     $conditions['vc_op_id'] = $this->vc_op_id;
@@ -300,152 +294,6 @@ abstract class VersioncontrolOperation extends VersioncontrolEntity {
   }
 
   /**
-   * Retrieve the list of access errors.
-   *
-   * If versioncontrol_has_commit_access(), versioncontrol_has_branch_access()
-   * or versioncontrol_has_tag_access() returned FALSE, you can use this function
-   * to retrieve the list of error messages from the various access checks.
-   * The error messages do not include trailing linebreaks, it is expected that
-   * those are inserted by the caller.
-   */
-  private function getAccessErrors() {
-    return self::$error_messages;
-  }
-
-  /**
-   * Set the list of access errors.
-   */
-  private function setAccessErrors($new_messages) {
-    if (isset($new_messages)) {
-      self::$error_messages = $new_messages;
-    }
-  }
-
-  /**
-   * Determine if a commit, branch or tag operation may be executed or not.
-   * Call this function inside a pre-commit hook.
-   *
-   * @param $operation
-   *   A single operation array like the ones returned by
-   *   versioncontrol_get_operations(), but leaving out on a few details that
-   *   will instead be determined by this function. This array describes
-   *   the operation that is about to happen. Here's the allowed elements:
-   *
-   *   - 'type': The type of the operation - one of the
-   *        VERSIONCONTROL_OPERATION_{COMMIT,BRANCH,TAG} constants.
-   *   - 'repository': The repository where this operation occurs,
-   *        given as a structured array, like the return value
-   *        of versioncontrol_get_repository().
-   *        You can either pass this or 'repo_id'.
-   *   - 'repo_id': The repository where this operation occurs, given as a simple
-   *        integer id. You can either pass this or 'repository'.
-   *   - 'uid': The Drupal user id of the committer. Passing this is optional -
-   *        if it isn't set, this function will determine the uid.
-   *   - 'username': The system specific VCS username of the committer.
-   *   - 'message': The log message for the commit, tag or branch operation.
-   *        If a version control system doesn't support messages for the current
-   *        operation type, this element must not be set. Operations with
-   *        log messages that are set but empty will be denied access.
-   *
-   *   - 'labels': An array of branches or tags that will be affected by this
-   *        operation. Branch and tag operations are known to only affect one
-   *        branch or tag, so for these there will be only one element (with 0
-   *        as key) in 'labels'. Commits might affect any number of branches,
-   *        including none. Commits that emulate branches and/or tags (like
-   *        in Subversion, where they're not a native concept) can also include
-   *        add/delete/move operations for labels, as detailed below.
-   *        Mind that the main development branch - e.g. 'HEAD', 'trunk'
-   *        or 'master' - is also considered a branch. Each element in 'labels'
-   *        is a VersioncontrolLabel(VersioncontrolBranch VersioncontrolTag)
-   *
-   * @param $item_revisions
-   *   A structured array containing the exact details of what is about to happen
-   *   to each item in this commit. The structure of this array is the same as
-   *   the return value of VersioncontrolOperation::getItems() - that is,
-   *   elements for 'type', 'path', 'revision', 'action', 'source_items' and
-   *   'replaced_item' - but doesn't include the 'item_revision_id' element as
-   *   there's no relation to the database yet.
-   *
-   *   The 'action', 'source_items', 'replaced_item' and 'revision' elements
-   *   of each item are optional and may be left unset.
-   *
-   * @return
-   *   TRUE if the operation may happen, or FALSE if not.
-   *   If FALSE is returned, you can retrieve the concerning error messages
-   *   by calling versioncontrol_get_access_errors().
-   */
-  protected function hasWriteAccess($operation, $item_revisions) {
-
-    // If we can't determine this operation's repository,
-    // we can't really allow the operation in the first place.
-    if (!isset($operation['repository'])) {
-      switch ($operation['type']) {
-      case VERSIONCONTROL_OPERATION_COMMIT:
-        $type = t('commit');
-        break;
-      case VERSIONCONTROL_OPERATION_BRANCH:
-        $type = t('branch');
-        break;
-      case VERSIONCONTROL_OPERATION_TAG:
-        $type = t('tag');
-        break;
-      }
-      $this->setAccessErrors(array(t(
-        '** ERROR: Version Control API cannot determine a repository
-        ** for the !commit-branch-or-tag information given by the VCS backend.',
-        array('!commit-branch-or-tag' => $type)
-      )));
-      return FALSE;
-    }
-
-    // If the user doesn't have commit access at all, we can't allow this as well.
-    $repo_data = $operation->repository->data['versioncontrol'];
-
-    if (!$repo_data['allow_unauthorized_access']) {
-
-      if (!$operation->repository->isAccountAuthorized($operation->uid)) {
-        $this->setAccessErrors(array(t(
-          '** ERROR: !user does not have commit access to this repository.',
-          array('!user' => $operation->committer)
-        )));
-        return FALSE;
-      }
-    }
-
-    // Don't let people do empty log messages, that's as evil as it gets.
-    if (isset($operation['message']) && empty($operation['message'])) {
-      $this->setAccessErrors(array(
-        t('** ERROR: You have to provide a log message.'),
-      ));
-      return FALSE;
-    }
-
-    // Also see if other modules have any objections.
-    $error_messages = array();
-
-    foreach (module_implements('versioncontrol_write_access') as $module) {
-      $function = $module .'_versioncontrol_write_access';
-
-      // If at least one hook_versioncontrol_write_access returns TRUE,
-      // the commit goes through. (This is for admin or sandbox exceptions.)
-      $outcome = $function($operation, $item_revisions);
-      if ($outcome === TRUE) {
-        return TRUE;
-      }
-      else { // if !TRUE, $outcome is required to be an array with error messages
-        $error_messages = array_merge($error_messages, $outcome);
-      }
-    }
-
-    // Let the operation fail if there's more than zero error messages.
-    if (!empty($error_messages)) {
-    $this->setAccessErrors($error_messages);
-      return FALSE;
-    }
-    return TRUE;
-  }
-
-  /**
    * Convinience method to call backend analogue one.
    *
    * @param $format
diff --git includes/VersioncontrolRepository.php includes/VersioncontrolRepository.php
index 35d0cca..a4dca6a 100644
--- includes/VersioncontrolRepository.php
+++ includes/VersioncontrolRepository.php
@@ -96,10 +96,10 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
   /**
    * An array describing the plugins that will be used for this repository.
    *
-   * The current plugin types(array keys) are:
-   * - author_mapper
-   * - committer_mapper
-   * - auth_handler
+   * The current plugin types(array keys and expected values) are:
+   * - author_mapper => (string) name
+   * - committer_mapper => (string) name
+   * - auth_handlers => (array) list of names as strings
    *
    * @var array
    */
@@ -118,6 +118,12 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
     'delete' => array('nested' => TRUE),
   );
 
+  /**
+   * Store any errors messages about authorization as the output of
+   * VersioncontrolAuthHandlerInterface::getErrorMessages().
+   */
+  protected $authErrorMessages = array();
+
   public function __construct($backend = NULL) {
     if ($backend instanceof VersioncontrolBackend) {
       $this->backend = $backend;
@@ -227,17 +233,14 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
     return $this->backend->loadEntities('operation', $ids, $conditions, $options);
   }
 
-  public function loadAccounts($ids = array(), $conditions = array(), $options = array()) {
-    $conditions['repo_id'] = $this->repo_id;
-    return $this->backend->loadEntities('account', $ids, $conditions, $options);
-  }
-
   /**
    * Return TRUE if the account is authorized to commit in the actual
    * repository, or FALSE otherwise. Only call this function on existing
    * accounts or uid 0, the return value for all other
    * uid/repository combinations is undefined.
    *
+   * FIXME deprecate this in favour of a plugin implementation.
+   *
    * @param $uid
    *   The user id of the checked account.
    */
@@ -319,8 +322,8 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
 
   /**
    * Delete a repository from the database, and call the necessary hooks.
-   * Together with the repository, all associated commits and accounts are
-   * deleted as well.
+   * Together with the repository, all associated commits are deleted as
+   * well.
    */
   public function delete($options = array()) {
     // Append default options.
@@ -337,10 +340,6 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
       foreach ($this->loadCommits() as $commit) {
         $commit->delete();
       }
-      // FIXME accounts are changing significantly, this will need to, too
-      foreach ($this->loadAccounts() as $account) {
-        $account->delete();
-      }
     }
 
     db_delete('versioncontrol_repositories')
@@ -383,69 +382,6 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
   }
 
   /**
-   * Retrieve the Drupal user id for a given VCS username.
-   *
-   * @param $username
-   *   The VCS specific username (a string) corresponding to the Drupal
-   *   user.
-   * @param $include_unauthorized
-   *   If FALSE (which is the default), this function does not return
-   *   accounts that are pending, queued, disabled, blocked, or otherwise
-   *   non-approved. If TRUE, all accounts are returned, regardless of
-   *   their status.
-   *
-   * @return
-   *   The Drupal user id that corresponds to the given username and
-   *   repository, or NULL if no Drupal user could be associated to
-   *   those.
-   */
-  public function getAccountUidForUsername($username, $include_unauthorized = FALSE) {
-    $result = db_query("SELECT uid, repo_id
-      FROM {versioncontrol_accounts}
-      WHERE vcs_username = '%s' AND repo_id = %d",
-      $username, $this->repo_id);
-
-    while ($account = db_fetch_object($result)) {
-      // Only include approved accounts, except in case the caller said otherwise.
-      if ($include_unauthorized || $this->isAccountAuthorized($account->uid)) {
-        return $account->uid;
-      }
-    }
-    return NULL;
-  }
-
-  /**
-   * Retrieve the VCS username for the Drupal user id.
-   *
-   * @param $uid
-   *   The Drupal user id corresponding to the VCS account.
-   * @param $include_unauthorized
-   *   If FALSE (which is the default), this function does not return
-   *   accounts that are pending, queued, disabled, blocked, or otherwise
-   *   non-approved. If TRUE, all accounts are returned, regardless of
-   *   their status.
-   *
-   * @return
-   *   The VCS username (a string) that corresponds to the given Drupal
-   *   user and repository, or NULL if no VCS account could be associated
-   *   to those.
-   */
-  function getAccountUsernameForUid($uid, $include_unauthorized = FALSE) {
-    $result = db_query('SELECT uid, username, repo_id
-      FROM {versioncontrol_accounts}
-      WHERE uid = %d AND repo_id = %d',
-      $uid, $this->repo_id);
-
-    while ($account = db_fetch_object($result)) {
-      // Only include approved accounts, except in case the caller said otherwise.
-      if ($include_unauthorized || $this->isAccountAuthorized($account->uid)) {
-        return $account->vcs_username;
-      }
-    }
-    return NULL;
-  }
-
-  /**
    * Get an instantiated plugin object based on a requested plugin slot, and the
    * plugin this repository object has assigned to that slot.
    *
@@ -477,17 +413,33 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
     return new $class_name();
   }
 
-  public function getAuthHandler() {
-    if (!isset($this->pluginInstances['auth_handler'])) {
+  public function getAuthHandlers() {
+    ctools_include('plugins');
+
+    if (!isset($this->pluginInstances['auth_handlers'])) {
       // If no plugin is set, use the free-for-all plugin
-      if (empty($this->plugins['auth_handler'])) {
+      if (empty($this->plugins['auth_handlers'])) {
         // FIXME temporarily writing to a db-recorded field like this is very hacky
-        $this->plugins['auth_handler'] = 'ffa';
+        $this->plugins['auth_handlers'] = array('ffa');
       }
-      $this->pluginInstances['auth_handler'] = $this->getPluginClass('auth_handler', 'vcs_auth', 'handler');
-      $this->pluginInstances['auth_handler']->setRepository($this);
+      $plugin_instances = array();
+      foreach ($this->plugins['auth_handlers'] as $plugin_name) {
+        $plugin = ctools_get_plugins('versioncontrol', 'vcs_auth', $plugin_name);
+        if (!is_array($plugin)) {
+          throw new Exception("Attempted to get a plugin of type 'vcs_auth' named '$plugin_name', but no such plugin could be found.", E_WARNING);
+          return FALSE;
+        }
+        $class_name = ctools_plugin_get_class($plugin, 'handler');
+        if (!class_exists($class_name)) {
+          throw new Exception("Plugin '$plugin_name' of type 'vcs_auth' does not contain a valid class name in handler slot 'handler'", E_WARNING);
+          return FALSE;
+        }
+        $plugin_instances[$plugin_name] = new $class_name;
+        $plugin_instances[$plugin_name]->setRepository($this);
+      }
+      $this->pluginInstances['auth_handlers'] = $plugin_instances;
     }
-    return $this->pluginInstances['auth_handler'];
+    return $this->pluginInstances['auth_handlers'];
   }
 
   public function getAuthorMapper() {
@@ -517,6 +469,79 @@ abstract class VersioncontrolRepository implements VersioncontrolEntityInterface
     return $this->pluginInstances['committer_mapper'];
   }
 
+  public function getAuthErrorMessages() {
+    return $this->authErrorMessages;
+  }
+
+  public function authAccess($uid) {
+    foreach ($this->getAuthHandlers() as $auth_handler) {
+      if (!$auth_handler->authAccess($uid)) {
+        $this->authErrorMessages = $auth_handler->getErrorMessages();
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+
+  public function authBranchCreate($uid, VersioncontrolBranch $branch) {
+    foreach ($this->getAuthHandlers() as $auth_handler) {
+      if (!$auth_handler->authBranchCreate($uid, $branch)) {
+        $this->authErrorMessages = $auth_handler->getErrorMessages();
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+
+  public function authBranchDelete($uid, VersioncontrolBranch $branch) {
+    foreach ($this->getAuthHandlers() as $auth_handler) {
+      if (!$auth_handler->authBranchDelete($uid, $branch)) {
+        $this->authErrorMessages = $auth_handler->getErrorMessages();
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+
+  public function authBranchUpdate($uid, VersioncontrolBranch $branch) {
+    foreach ($this->getAuthHandlers() as $auth_handler) {
+      if (!$auth_handler->authBranchUpdate($uid, $branch)) {
+        $this->authErrorMessages = $auth_handler->getErrorMessages();
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+
+  public function authTagCreate($uid, VersioncontrolTag $tag) {
+    foreach ($this->getAuthHandlers() as $auth_handler) {
+      if (!$auth_handler->authTagCreate($uid, $tag)) {
+        $this->authErrorMessages = $auth_handler->getErrorMessages();
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+
+  public function authTagDelete($uid, VersioncontrolTag $tag) {
+    foreach ($this->getAuthHandlers() as $auth_handler) {
+      if (!$auth_handler->authTagDelete($uid, $tag)) {
+        $this->authErrorMessages = $auth_handler->getErrorMessages();
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+
+  public function authTagUpdate($uid, VersioncontrolTag $tag) {
+    foreach ($this->getAuthHandlers() as $auth_handler) {
+      if (!$auth_handler->authTagUpdate($uid, $tag)) {
+        $this->authErrorMessages = $auth_handler->getErrorMessages();
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
 
   //ArrayAccess interface implementation FIXME soooooooo deprecated
   public function offsetExists($offset) {
diff --git includes/controllers.inc includes/controllers.inc
index 7cd407d..f20f919 100644
--- includes/controllers.inc
+++ includes/controllers.inc
@@ -416,52 +416,6 @@ class VersioncontrolRepositoryController extends VersioncontrolEntityController
   protected function extendData(&$queried_entities) {}
 }
 
-class VersioncontrolAccountController extends VersioncontrolEntityController {
-  protected $entityType = 'account';
-  protected $baseTable = 'versioncontrol_accounts';
-  protected $idKey = 'uid';
-
-  protected function executeQuery(&$query) {
-    $result = $query->execute();
-    if ($this->options['repository'] instanceof VersioncontrolRepository) {
-      return $result->fetchAllAssoc('uid');
-    }
-    else { // No repository specified, create a specially-keyed array
-      $return = array();
-      foreach ($result as $row) {
-        if (!isset($return[$row->uid])) {
-          $return[$row->uid] = array();
-        }
-        $return[$row->uid][$row->repo_id] = $row;
-      }
-      return $return;
-    }
-  }
-
-  protected function buildEntities(&$queried_entities) {
-    // If a repository is attached, the default parent implementation is fine
-    if ($this->options['repository'] instanceof VersioncontrolRepository) {
-      return parent::buildEntities($queried_entities);
-    }
-    // Otherwise we need special handling for our two-level array.
-    $almost_built = array();
-    foreach ($queried_entities as $uid => $raw_accounts_per_repo) {
-      foreach ($raw_accounts_per_repo as $repo_id => $raw_account) {
-        $id = "$uid-$repo_id";
-        // load the repository object
-        $raw_account->repository = $this->backends[$raw_account->vcs]->loadEntity('repo', array($repo_id));
-        $almost_built[$id] = $raw_account;
-      }
-    }
-    return parent::buildEntities($almost_built);
-  }
-
-  protected function modifyReturn($entities) {
-    // by now, return the same
-    return $entities;
-  }
-}
-
 class VersioncontrolBranchController extends VersioncontrolEntityController {
   protected $entityType = 'branch';
   protected $baseTable = 'versioncontrol_labels';
diff --git includes/interfaces.inc includes/interfaces.inc
index 88b8722..792df68 100644
--- includes/interfaces.inc
+++ includes/interfaces.inc
@@ -226,11 +226,14 @@ interface VersioncontrolAuthHandlerInterface {
    *
    * @param int $uid
    *   The uid of the Drupal user to be checked.
+   * @param VersioncontrolBranch $branch
+   *   The VersioncontrolBranch object representing the branch against which
+   *   authorization checks should be made.
    *
    * @return bool
    *   Boolean indicating access approved (TRUE) or denied (FALSE)
    */
-  public function authBranchCreate($uid);
+  public function authBranchCreate($uid, VersioncontrolBranch $branch);
 
   /**
    * Determine whether the specified user has access to delete the specified
@@ -268,10 +271,14 @@ interface VersioncontrolAuthHandlerInterface {
    *
    * @param int $uid
    *   The uid of the Drupal user to be checked.
+   * @param VersioncontrolTag $tag
+   *   The VersioncontrolTag object representing the tag against which
+   *   authorization checks should be made.
+   *
    * @return bool
    *   Boolean indicating access approved (TRUE) or denied (FALSE)
    */
-  public function authTagCreate($uid);
+  public function authTagCreate($uid, VersioncontrolTag $tag);
 
   /**
    * Determine whether the specified user has access to delete the specified
diff --git includes/plugins/vcs_auth/VersioncontrolAuthHandlerFFA.class.php includes/plugins/vcs_auth/VersioncontrolAuthHandlerFFA.class.php
index 59157fc..fead4ff 100644
--- includes/plugins/vcs_auth/VersioncontrolAuthHandlerFFA.class.php
+++ includes/plugins/vcs_auth/VersioncontrolAuthHandlerFFA.class.php
@@ -7,7 +7,7 @@ class VersioncontrolAuthHandlerFFA implements VersioncontrolAuthHandlerInterface
     return TRUE;
   }
 
-  public function authBranchCreate($uid) {
+  public function authBranchCreate($uid, VersioncontrolBranch $branch) {
     return TRUE;
   }
   public function authBranchDelete($uid, VersioncontrolBranch $branch) {
@@ -16,7 +16,7 @@ class VersioncontrolAuthHandlerFFA implements VersioncontrolAuthHandlerInterface
   public function authBranchUpdate($uid, VersioncontrolBranch $branch) {
     return TRUE;
   }
-  public function authTagCreate($uid) {
+  public function authTagCreate($uid, VersioncontrolTag $tag) {
     return TRUE;
   }
   public function authTagDelete($uid, VersioncontrolTag $tag) {
diff --git includes/plugins/vcs_auth/VersioncontrolAuthHandlerMappedAccounts.class.php includes/plugins/vcs_auth/VersioncontrolAuthHandlerMappedAccounts.class.php
index dd12902..f3dee7e 100644
--- includes/plugins/vcs_auth/VersioncontrolAuthHandlerMappedAccounts.class.php
+++ includes/plugins/vcs_auth/VersioncontrolAuthHandlerMappedAccounts.class.php
@@ -189,7 +189,7 @@ class VersioncontrolAuthHandlerMappedAccounts implements VersioncontrolAuthHandl
     }
   }
 
-  public function authBranchCreate($uid) {
+  public function authBranchCreate($uid, VersioncontrolBranch $branch) {
     $base = $this->baseAuth($uid);
     if ($base == self::DENY) {
       // Zero access, deny.
@@ -222,7 +222,7 @@ class VersioncontrolAuthHandlerMappedAccounts implements VersioncontrolAuthHandl
     }
     return $access;
   }
-  public function authTagCreate($uid) {
+  public function authTagCreate($uid, VersioncontrolTag $tag) {
     $base = $this->baseAuth($uid);
     if ($base == self::DENY) {
       // Zero access, deny.
diff --git includes/plugins/vcs_auth/account.inc includes/plugins/vcs_auth/account.inc
index bb01820..6fbe23e 100644
--- includes/plugins/vcs_auth/account.inc
+++ includes/plugins/vcs_auth/account.inc
@@ -1,7 +1,7 @@
 <?php
 
 $plugin = array(
-  'title' => t('Free For All (unrestricted write access)'),
+  'title' => t('Account (restricted write access)'),
   'handler' => array(
     'class' => 'VersioncontrolAuthHandlerMappedAccounts',
   ),
diff --git includes/views/versioncontrol.views.inc includes/views/versioncontrol.views.inc
index f4a80c3..bcdcb96 100755
--- includes/views/versioncontrol.views.inc
+++ includes/views/versioncontrol.views.inc
@@ -140,10 +140,6 @@ function versioncontrol_views_data() {
       'left_field' => 'repo_id',
       'field' => 'repo_id',
     ),
-    'versioncontrol_accounts' => array(
-      'left_field' => 'repo_id',
-      'field' => 'repo_id',
-    ),
   );
 
   // VersionControl Operations
@@ -343,43 +339,6 @@ function versioncontrol_views_data() {
       'type'       => 'inner',
   );
 
-  // VersionControl Accounts
-  $data['versioncontrol_accounts']['table']['group'] = t("VersionControl Accounts");
-  $data['versioncontrol_accounts']['table']['base'] = array(
-    'field' => 'uid',
-    'title' => t('VersionControl Accounts'),
-    'help'  => t('The VersionControl accounts held by users.'),
-  );
-  $data['versioncontrol_accounts']['table']['join'] = array(
-    'user' => array(
-      'left_field' => 'uid',
-      'field' => 'uid',
-    ),
-    'versioncontrol_repositories' => array(
-      'left_field' => 'repo_id',
-      'field' => 'repo_id',
-    ),
-  );
-  $data['versioncontrol_accounts']['vcs_username'] = array(
-    'title' => t('Versioncontrol Name'),
-    'help' => t('The username of the committer, as known by the VCS.'),
-    'field' => array(
-      'handler' => 'views_handler_field',
-      'click sortable' => TRUE,
-    ),
-    'sort' => array(
-      'handler' => 'views_handler_sort',
-    ),
-    'argument' => array(
-      'handler' => 'views_handler_argument_string',
-    ),
-  );
-  $data['users']['table']['join']['versioncontrol_accounts'] = array(
-    'left_field' => 'uid',
-    'field' => 'uid',
-    'type' => 'inner',
-  );
-
   // VersionControl Labels
   $data['versioncontrol_labels']['table']['group'] = t("VersionControl Labels");
   $data['versioncontrol_labels']['table']['base'] = array(
diff --git tests/VersioncontrolAccountAuthPlugin.test tests/VersioncontrolAccountAuthPlugin.test
index 22ed5ab..1abf911 100644
--- tests/VersioncontrolAccountAuthPlugin.test
+++ tests/VersioncontrolAccountAuthPlugin.test
@@ -37,7 +37,7 @@ class VersioncontrolAccountAuthPlugin extends VersioncontrolTestCase {
 
     $repo_data = array(
       'plugins' => array(
-        'auth_handler' => 'account'
+        'auth_handlers' => array('account')
       ),
     );
 
@@ -107,7 +107,7 @@ class VersioncontrolAccountAuthPlugin extends VersioncontrolTestCase {
   }
 
   public function testMappedAccountsAuthPluginCrud() {
-    foreach ($this->repos as $repo) {
+    foreach ($this->repos as $backend_machine_name => $repo) {
       // Manually instantiate the plugin for the create portion
       $class_name = ctools_plugin_load_class('versioncontrol', 'vcs_auth', 'account', 'handler');
       $authplug = new $class_name();
@@ -121,7 +121,7 @@ class VersioncontrolAccountAuthPlugin extends VersioncontrolTestCase {
 
       // Now load the plugin using the provided method and retrieve the user data,
       // ensure it's what we sent in
-      $db_authplug = $repo->getAuthHandler();
+      $db_authplug = reset($repo->getAuthHandlers());
       $db_data = $db_authplug->getUserData($super_user->uid);
       $at_input = array_diff($super_user_data, $db_data);
       $this->assertTrue(empty($at_input), 'Authentication account database data is included on provided data');
@@ -132,7 +132,7 @@ class VersioncontrolAccountAuthPlugin extends VersioncontrolTestCase {
       $this->assertTrue(empty($at_db), 'Authentication account provided data is included on database data');
 
       // Now try test  logic
-      $authplug = $repo->getAuthHandler();
+      $authplug = reset($repo->getAuthHandlers());
       $branches = $repo->loadBranches(array(
         $this->branches[$repo->repo_id][0]->label_id,
         $this->branches[$repo->repo_id][1]->label_id,
@@ -148,8 +148,10 @@ class VersioncontrolAccountAuthPlugin extends VersioncontrolTestCase {
       // global
       $this->assertTrue($authplug->authAccess($super_user->uid), 'global auth validate correctly');
       // branches
-      $this->assertFalse($authplug->authBranchCreate($super_user->uid), 'branch create validate correctly');
-      $this->assertFalse($authplug->authTagCreate($super_user->uid), 'tag create validate correctly');
+      $test_branch = $this->versioncontrolCreateBranch($backend_machine_name, array(), FALSE);
+      $this->assertFalse($authplug->authBranchCreate($super_user->uid, $test_branch), 'branch create validate correctly');
+      $test_tag = $this->versioncontrolCreateTag($backend_machine_name, array(), FALSE);
+      $this->assertFalse($authplug->authTagCreate($super_user->uid, $test_tag), 'tag create validate correctly');
       $this->assertTrue($authplug->authBranchUpdate($super_user->uid, $this->branches[$repo->repo_id][0]), 'granular branch update validate correctly');
       $this->assertTrue($authplug->authBranchDelete($super_user->uid, $this->branches[$repo->repo_id][0]), 'granular branch delete validate correctly');
       $this->assertTrue($authplug->authBranchUpdate($super_user->uid, $this->branches[$repo->repo_id][1]), 'granular branch update validate correctly');
diff --git tests/VersioncontrolBackendTests.test tests/VersioncontrolBackendTests.test
index 6b5a54d..64869e9 100644
--- tests/VersioncontrolBackendTests.test
+++ tests/VersioncontrolBackendTests.test
@@ -31,7 +31,7 @@ class VersioncontrolBackendBaseUnitTest extends VersioncontrolTestCase {
     // As soon as the backend is initialized, the base class should have a bunch
     // of classes declared on it and available for factory operations. Check.
     // This also has the effect of ensuring autoload declarations are in place.
-    $types = array('repo', 'account', 'operation', 'item', 'branch', 'tag');
+    $types = array('repo', 'operation', 'item', 'branch', 'tag');
     foreach ($this->backends as $backend) { // Iterate over all available backends.
       foreach ($types as $type) { // Iterate over each entity type.
         $this->assertTrue(isset($backend->classesEntities[$type]), "$backend->name backend declares an entity class for type '$type'", 'PHP');
diff --git tests/VersioncontrolRepositoryUnitTestingTestCase.test tests/VersioncontrolRepositoryUnitTestingTestCase.test
index 23470ae..762fb15 100644
--- tests/VersioncontrolRepositoryUnitTestingTestCase.test
+++ tests/VersioncontrolRepositoryUnitTestingTestCase.test
@@ -39,7 +39,7 @@ class VersioncontrolRepositoryUnitTestingTestCase extends VersioncontrolTestCase
       'updated' => 0,
       'locked' => 0,
       'data' => array(),
-      'plugins' => array('auth_handler' => 'ffa', 'author_mapper' => 'simple_name', 'committer_mapper' => 'simple_mail'),
+      'plugins' => array('auth_handlers' => array('ffa'), 'author_mapper' => 'simple_name', 'committer_mapper' => 'simple_mail'),
     );
     $repo = $this->testBackend->buildEntity('repo', $data);
     $repo->insert();
@@ -88,7 +88,7 @@ class VersioncontrolRepositoryUnitTestingTestCase extends VersioncontrolTestCase
       'updated' => time(),
       //TODO $repo->update_method
       'locked' => TRUE,
-      'plugins' => array('auth_handler' => 'account') + $repo['plugins'],
+      'plugins' => array('auth_handlers' => array('account')) + $repo['plugins'],
     );
 
     $repo->name = $data['name'];
diff --git tests/VersioncontrolTestCase.test tests/VersioncontrolTestCase.test
index 8d409e6..dc59dbf 100644
--- tests/VersioncontrolTestCase.test
+++ tests/VersioncontrolTestCase.test
@@ -132,7 +132,7 @@ abstract class VersioncontrolTestCase extends DrupalWebTestCase {
    * @param string $backend_name
    * @param array  $data
    */
-  public function versioncontrolCreateRepository($backend_name = 'test', $data = array()) {
+  public function versioncontrolCreateRepository($backend_name = 'test', $data = array(), $insert=TRUE) {
     static $i = 0;
     $default_data = array(
       'name' => 'test_repo_' . ++$i,
@@ -146,7 +146,7 @@ abstract class VersioncontrolTestCase extends DrupalWebTestCase {
       'plugins' => array(),
     );
     $default_plugins = array(
-      'auth_handler' => 'ffa',
+      'auth_handlers' => array('ffa'),
       'author_mapper' => 'simple_mail',
       'committer_mapper' => 'simple_mail',
     );
@@ -159,13 +159,15 @@ abstract class VersioncontrolTestCase extends DrupalWebTestCase {
     }
     $backend = $this->backends[$backend_name];
     $repo = $backend->buildEntity('repo', $data);
-    $repo->insert();
-    $this->assertTrue(isset($repo->repo_id) && is_numeric($repo->repo_id), t('VersioncontrolRepository::insert() properly populates a new repository object with an integer repo_id.'));
+    if ($insert) {
+      $repo->insert();
+      $this->assertTrue(isset($repo->repo_id) && is_numeric($repo->repo_id), t('VersioncontrolRepository::insert() properly populates a new repository object with an integer repo_id.'));
+    }
 
     return $repo;
   }
 
-  public function versioncontrolCreateLabel($type, $backend_name = 'test', $data = array()) {
+  public function versioncontrolCreateLabel($type, $backend_name = 'test', $data = array(), $insert=TRUE) {
     $default_data = array(
       'name' => $this->randomName(32),
       'data' => array(),
@@ -180,24 +182,30 @@ abstract class VersioncontrolTestCase extends DrupalWebTestCase {
       }
     }
     $label = $backend->buildEntity($type, $data);
-    $label->insert();
+    if ($insert) {
+      $label->insert();
+    }
 
     return $label;
   }
 
-  public function versioncontrolCreateBranch($backend_name = 'test', $data = array()) {
-    $label = $this->versioncontrolCreateLabel('branch', $backend_name, $data);
-    $this->assertTrue(isset($label->label_id) && is_numeric($label->label_id), t('VersioncontrolBranch::insert() properly populates a new repository object with an integer label_id.'));
+  public function versioncontrolCreateBranch($backend_name = 'test', $data = array(), $insert=TRUE) {
+    $label = $this->versioncontrolCreateLabel('branch', $backend_name, $data, $insert);
+    if ($insert) {
+      $this->assertTrue(isset($label->label_id) && is_numeric($label->label_id), t('VersioncontrolBranch::insert() properly populates a new repository object with an integer label_id.'));
+    }
     return $label;
   }
 
-  public function versioncontrolCreateTag($backend_name = 'test', $data = array()) {
-    $label = $this->versioncontrolCreateLabel('tag', $backend_name, $data);
-    $this->assertTrue(isset($label->label_id) && is_numeric($label->label_id), t('VersioncontrolTag::insert() properly populates a new repository object with an integer label_id.'));
+  public function versioncontrolCreateTag($backend_name = 'test', $data = array(), $insert=TRUE) {
+    $label = $this->versioncontrolCreateLabel('tag', $backend_name, $data, $insert);
+    if ($insert) {
+      $this->assertTrue(isset($label->label_id) && is_numeric($label->label_id), t('VersioncontrolTag::insert() properly populates a new repository object with an integer label_id.'));
+    }
     return $label;
   }
 
-  public function versioncontrolCreateOperation($backend_name = 'test', $data = array()) {
+  public function versioncontrolCreateOperation($backend_name = 'test', $data = array(), $insert=TRUE) {
     static $i = 0;
     $name = $this->randomName(7);
     $default_data = array(
@@ -222,13 +230,15 @@ abstract class VersioncontrolTestCase extends DrupalWebTestCase {
       }
     }
     $operation = $backend->buildEntity('operation', $data);
-    $operation->insert();
-    $this->assertTrue(isset($operation->vc_op_id) && is_numeric($operation->vc_op_id), t('VersioncontrolOperation::insert() properly populates a new repository object with an integer vc_op_id.'));
+    if ($insert) {
+      $operation->insert();
+      $this->assertTrue(isset($operation->vc_op_id) && is_numeric($operation->vc_op_id), t('VersioncontrolOperation::insert() properly populates a new repository object with an integer vc_op_id.'));
+    }
 
     return $operation;
   }
 
-  public function versioncontrolCreateItem($backend_name = 'test', $data = array()) {
+  public function versioncontrolCreateItem($backend_name = 'test', $data = array(), $insert=TRUE) {
     static $i = 0;
     $default_data = array(
       'path' => sprintf('/%s/%s.inc', $this->randomName(4), $this->randomName(4)),
@@ -253,8 +263,10 @@ abstract class VersioncontrolTestCase extends DrupalWebTestCase {
       $data['vc_op_id'] = $operation->vc_op_id;
     }
     $item = $backend->buildEntity('item', $data);
-    $item->insert();
-    $this->assertTrue(isset($item->item_revision_id) && is_numeric($item->item_revision_id), t('VersioncontrolItem::insert() properly populates a new repository object with an integer item_revision_id.'));
+    if ($insert) {
+      $item->insert();
+      $this->assertTrue(isset($item->item_revision_id) && is_numeric($item->item_revision_id), t('VersioncontrolItem::insert() properly populates a new repository object with an integer item_revision_id.'));
+    }
 
     return $item;
   }
diff --git tests/versioncontrol_test.inc tests/versioncontrol_test.inc
index 000a934..15627da 100644
--- tests/versioncontrol_test.inc
+++ tests/versioncontrol_test.inc
@@ -19,7 +19,6 @@ class VersioncontrolTestBackend extends VersioncontrolBackend {
     );
     $this->classesEntities = array(
       'repo'      => 'VersioncontrolTestRepository',
-      'account'   => 'VersioncontrolTestAccount',
       'operation' => 'VersioncontrolTestOperation',
       'item'      => 'VersioncontrolTestItem',
       'branch'    => 'VersioncontrolTestBranch',
@@ -32,9 +31,6 @@ class VersioncontrolTestBackend extends VersioncontrolBackend {
 class VersioncontrolTestRepository extends VersioncontrolRepository {
 }
 
-class VersioncontrolTestAccount extends VersioncontrolAccount {
-}
-
 class VersioncontrolTestOperation extends VersioncontrolOperation {
 
   /**
diff --git versioncontrol.admin.inc versioncontrol.admin.inc
index 7ce6706..9087cc8 100644
--- versioncontrol.admin.inc
+++ versioncontrol.admin.inc
@@ -6,7 +6,7 @@
  * whose functionality is provided by pluggable back-end modules.
  *
  * This file contains the administrative user interface
- * for accounts and repositories.
+ * and repositories.
  *
  * Copyright 2006, 2007 Derek Wright ("dww" , http://drupal.org/user/46549)
  * Copyright 2007, 2008, 2009 by Jakob Petsovits ("jpetso", http://drupal.org/user/56020)
@@ -233,257 +233,6 @@ function versioncontrol_admin_views_sets_edit_submit($form, &$form_state) {
 }
 
 /**
- * Form callback for "admin/content/versioncontrol-accounts":
- * A list of accounts with filtering possibilities.
- *
- * TODO Completely reimplement in Views.
- */
-function versioncontrol_admin_account_list_form(&$form_state) {
-  // Retrieve a list of all repositories with registered VCS accounts.
-  $result = db_query('SELECT DISTINCT repo_id FROM {versioncontrol_accounts}');
-  $repo_ids = array();
-
-  while ($repo_id = db_result($result)) {
-    $repo_ids[] = $repo_id;
-  }
-  $repositories = versioncontrol_repository_load_multiple($repo_ids);
-
-  $filter_form = versioncontrol_admin_account_list_filter_form($form_state, $repositories);
-  $filter_form['#id'] = 'versioncontrol-account-filter-form';
-  drupal_alter('form', $filter_form, $form_state, 'versioncontrol_admin_account_list_filter_form');
-
-  $form = array();
-  $form['filters'] = array_merge($filter_form, array(
-    '#type' => 'fieldset',
-    '#title' => t('Filter'),
-    '#collapsible' => TRUE,
-    '#collapsed' => FALSE,
-    '#prefix' => '<div class="container-inline">',
-    '#suffix' => '</div>',
-  ));
-
-  // Filter the list of accounts.
-  $accounts = versioncontrol_user_accounts_load_multiple(array(), array(), array('include unauthorized' => TRUE));
-
-  foreach (module_implements('versioncontrol_filter_accounts') as $module) {
-    $function = $module .'_versioncontrol_filter_accounts';
-    $function($accounts);
-  }
-  $accounts = versioncontrol_admin_get_paged_accounts($accounts);
-  $users = array();
-
-  // Retrieve more info for the accounts that survived filtering.
-  foreach ($accounts as $uid => $usernames_by_repository) {
-    $user = user_load($uid);
-    if (!$user) {
-      unset($accounts[$uid]);
-      continue;
-    }
-    $users[$uid] = $user;
-  }
-  if (empty($users)) {
-    $form['empty'] = array(
-      '#type' => 'markup',
-      '#value' => '<p>'. t('No accounts could be found with the current filter settings.') .'</p>',
-    );
-    return $form;
-  }
-
-  // Retrieve total, first and last commits of each user.
-  $statistics = VersioncontrolOperationCache::getInstance()->getStatistics(array(
-    'types' => array(VERSIONCONTROL_OPERATION_COMMIT),
-    'uids' => array_keys($users),
-  ), array(
-    'group_by' => array('uid'),
-  ));
-
-  $total_operations = array();
-  $first_operation_dates = array();
-  $last_operation_dates = array();
-
-  foreach ($statistics as $user_stats) {
-    $total_operations[$user_stats->uid] = $user_stats->total_operations;
-    $first_operation_dates[$user_stats->uid] = t('!time ago', array(
-      '!time' => format_interval(time() - $user_stats->first_operation_date, 1))
-    );
-    $last_operation_dates[$user_stats->uid] = t('!time ago', array(
-      '!time' => format_interval(time() - $user_stats->last_operation_date, 1))
-    );
-    if (module_exists('commitlog')) {
-      $total_operations[$user_stats->uid] =
-        l($total_operations[$user_stats->uid], 'user/'. $user_stats->uid .'/track/code');
-    }
-  }
-
-  // Construct the user account table.
-  $header = array(t('User'), t('Accounts'), t('Commits'), t('First commit'), t('Last commit'));
-  $rows_by_uid = array();
-  foreach ($accounts as $uid => $usernames_by_repository) {
-    $user = $users[$uid];
-
-    // Present a list of all VCS usernames and the repository where they're in.
-    $repo_usernames = array();
-    foreach ($usernames_by_repository as $repo_id => $account) {
-      if (!isset($repositories[$repo_id])) { // happens if the backend isn't loaded
-        continue;
-      }
-      $formatted_username = theme('versioncontrol_account_username',
-        $uid, $account->vcs_username, $repositories[$repo_id],
-        array('prefer_drupal_username' => FALSE)
-      );
-      $repo_name = module_exists('commitlog')
-        ? theme('commitlog_repository', $repositories[$repo_id])
-        : check_plain($repositories[$repo_id]['name']);
-
-      $repo_usernames[] = t('!username in !repository (!edit)', array(
-        '!username' => $formatted_username,
-        '!repository' => $repo_name,
-        '!edit' => l(t('edit'),
-          'user/'. $uid .'/edit/versioncontrol/'. $repo_id .'/'. drupal_urlencode($account->vcs_username)
-        ),
-      ));
-    }
-    $vcs_usernames = empty($repo_usernames)
-      ? t('VCS backend is currently disabled')
-      : theme('item_list', $repo_usernames);
-
-    $rows_by_uid[$uid] = array(
-      theme('username', $user), $vcs_usernames,
-      isset($total_operations[$uid]) ? $total_operations[$uid] : 0,
-      isset($first_operation_dates[$uid]) ? $first_operation_dates[$uid] : t('n/a'),
-      isset($last_operation_dates[$uid]) ? $last_operation_dates[$uid] : t('n/a'),
-    );
-  }
-
-  // Provide a possibility for backends and other modules to modify the list.
-  foreach (module_implements('versioncontrol_alter_account_list') as $module) {
-    $function = $module .'_versioncontrol_alter_account_list';
-    $function($accounts, $repositories, $header, $rows_by_uid);
-  }
-  // We don't want the uids in the final $rows array.
-  $rows = array_values($rows_by_uid);
-
-  // The finished user account list with account filter.
-  $form['accounts'] = array(
-    '#type' => 'markup',
-    '#value' => theme('table', $header, $rows),
-  );
-
-  if ($pager = theme('pager', NULL, variable_get('versioncontrol_admin_account_pager', 20), 0)) {
-    $form['pager'] = array(
-      '#type' => 'markup',
-      '#value' => $pager,
-    );
-  }
-  return $form;
-}
-
-/**
- * Return a subset of the given accounts (10 Drupal users by default, and all
- * of their VCS usernames). Paging is also used by emulating pager_query().
- */
-function versioncontrol_admin_get_paged_accounts($accounts, $element = 0) {
-  global $pager_page_array, $pager_total, $pager_total_items;
-  $page = isset($_GET['page']) ? $_GET['page'] : '';
-  $pager_page_array = explode(',', $page);
-  $page = empty($pager_page_array[$element]) ? 0 : $pager_page_array[$element];
-
-  $limit = variable_get('versioncontrol_admin_account_pager', 20);
-  $i = 0;
-  $paged_accounts = array();
-
-  foreach ($accounts as $uid => $usernames_by_repository) {
-    if ($i >= ($page * $limit) && $i < (($page+1) * $limit)) {
-      $paged_accounts[$uid] = $usernames_by_repository;
-    }
-    ++$i;
-  }
-
-  // Emulate pager_query() in order to get a proper theme('pager').
-  $pager_total_items[$element] = count($accounts);
-  $pager_total[$element] = ceil($pager_total_items[$element] / $limit);
-  $pager_page_array[$element] = max(0, min((int)$pager_page_array[$element], ((int)$pager_total[$element]) - 1));
-
-  return $paged_accounts;
-}
-
-/**
- * A form for filtering accounts which is embedded in the account list page.
- */
-function versioncontrol_admin_account_list_filter_form(&$form_state, $repositories) {
-  $form = array();
-  $repository_names = array(0 => t('All'));
-
-  foreach ($repositories as $repo_id => $repository) {
-    $repository_names[$repo_id] = check_plain($repository['name']);
-  }
-  if (!isset($_SESSION['versioncontrol_filter_repo_id'])) {
-    $_SESSION['versioncontrol_filter_repo_id'] = 0;
-  }
-
-  $form['#id'] = 'versioncontrol-account-filter-form';
-
-  $form['repo_id'] = array(
-    '#type' => 'select',
-    '#title' => t('Repository'),
-    '#options' => $repository_names,
-    '#default_value' => $_SESSION['versioncontrol_filter_repo_id'],
-    '#weight' => 10,
-  );
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Filter'),
-    '#submit' => array('versioncontrol_admin_account_list_filter_form_submit'),
-    '#weight' => 100,
-  );
-  return $form;
-}
-
-/**
- * Submit handler for the account filter form.
- */
-function versioncontrol_admin_account_list_filter_form_submit($form, &$form_state) {
-  $_SESSION['versioncontrol_filter_repo_id'] = $form_state['values']['repo_id'];
-}
-
-/**
- * Implementation of hook_versioncontrol_filter_accounts():
- * Unset filtered accounts before they are even attempted to be displayed
- * on the account list.
- *
- * TODO remove, obsoleted by Views
- *
- * @param $accounts
- *   The accounts that would normally be displayed, in the same format as the
- *   return value of versioncontrol_user_accounts_load_multiple(). Entries in
- *   this list may be unset by this filter function.
- */
-function versioncontrol_versioncontrol_filter_accounts(&$accounts) {
-  if (empty($accounts)) {
-    return;
-  }
-  if (!isset($_SESSION['versioncontrol_filter_repo_id'])) {
-    $_SESSION['versioncontrol_filter_repo_id'] = 0;
-  }
-  $filter_repo_id = $_SESSION['versioncontrol_filter_repo_id'];
-
-  if ($filter_repo_id == 0) {
-    return; // Don't change the list if "All" repositories are selected.
-  }
-
-  foreach ($accounts as $uid => $usernames_by_repository) {
-    foreach ($usernames_by_repository as $repo_id => $username) {
-      if ($repo_id != $filter_repo_id) {
-        unset($accounts[$uid][$repo_id]);
-        if (empty($accounts[$uid])) {
-          unset($accounts[$uid]);
-        }
-      }
-    }
-  }
-}
-
-/**
  * Form callback for "admin/content/versioncontrol-repositories":
  * A simple list of repositories, sorted by version control system.
  */
@@ -591,6 +340,23 @@ function versioncontrol_admin_repository_edit(&$form_state, $repository, $vcs =
     '#options' => array(0 => '<em>' . t('Use Author mapping plugin') . '</em>') + versioncontrol_user_mapping_methods_get_names(),
   );
 
+  $form['user_authentication'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('User authentication'),
+    '#description' => t('Versioncontrol can authenticate/validate VCS information based on its entities and the user trying to perform the VCS operation. If the authentication is called from the VCS hooks it can prevent inserting undesired data.'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+    '#weight' => 5,
+  );
+
+  $form['user_authentication']['authentication_handlers'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Authentication handlers'),
+    '#description' => t('The list of authentication methods tha can be used. If more than one is selected, they will be processed one after the other to get a final answer about the auth question.'),
+    '#default_value' => $repository_exists ? $repository->plugins['auth_handlers'] : array(),
+    '#options' => versioncontrol_auth_handlers_get_names(),
+  );
+
   if ($repository_exists && isset($repository->data['versioncontrol']['registration_message'])) {
     $current_registration_message = $repository->data['versioncontrol']['registration_message'];
   }
@@ -634,22 +400,6 @@ function versioncontrol_admin_repository_edit(&$form_state, $repository, $vcs =
   $backend_capabilities = $backends[$form['#vcs']]->capabilities;
 
   if (in_array(VERSIONCONTROL_CAPABILITY_COMMIT_RESTRICTIONS, $backend_capabilities)) {
-    $form['commit_restrictions'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Commit restrictions'),
-      '#collapsible' => TRUE,
-     '#collapsed' => TRUE,
-      '#weight' => 10,
-    );
-    $form['commit_restrictions']['allow_unauthorized_access'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Allow repository access to unknown or unauthorized committers'),
-      '#description' => 'If this is enabled, users can commit to this repository even if no association of the VCS account to the Drupal user is known (assuming that no other commit restrictions apply). If it is disabled, only known and authorized users may commit. This setting only works if the appropriate pre-commit/pre-branch/pre-tag hook script is set up for this repository.',
-      '#default_value' => $repository_exists
-                          ? $repository->data['versioncontrol']['allow_unauthorized_access']
-                          : FALSE,
-      '#weight' => 0,
-    );
   }
 
   if ($repository_exists) {
@@ -760,6 +510,7 @@ function versioncontrol_admin_repository_edit_submit($form, &$form_state) {
     $repository->plugins              = array(
       'author_mapper' => $form_state['values']['author_mapper'],
       'committer_mapper' => $form_state['values']['committer_mapper'],
+      'auth_handlers' => $form_state['values']['authentication_handlers'],
     );
   }
   else {
@@ -773,6 +524,7 @@ function versioncontrol_admin_repository_edit_submit($form, &$form_state) {
       'plugins' => array(
         'author_mapper' => $form_state['values']['author_mapper'],
         'committer_mapper' => $form_state['values']['committer_mapper'],
+        'auth_handlers' => $form_state['values']['authentication_handlers'],
       ),
     );
     $repository = $backends[$form['#vcs']]->buildEntity('repo', $repository);
@@ -785,11 +537,6 @@ function versioncontrol_admin_repository_edit_submit($form, &$form_state) {
     'url_handler'          => new VersioncontrolRepositoryUrlHandler($repository, $repository_urls),
   );
 
-  if (isset($form_state['values']['allow_unauthorized_access'])) {
-    $repository->data['versioncontrol']['allow_unauthorized_access'] =
-      (bool) $form_state['values']['allow_unauthorized_access'];
-  }
-
   // Let other modules alter the repository array.
   foreach (module_implements('versioncontrol_repository_submit') as $module) {
     $function = $module .'_versioncontrol_repository_submit';
diff --git versioncontrol.api.php versioncontrol.api.php
index 6a348de..107e426 100644
--- versioncontrol.api.php
+++ versioncontrol.api.php
@@ -195,134 +195,6 @@ function hook_versioncontrol_operation_labels($op, $operation, $labels) {
   }
 }
 
-
-/**
- * Restrict, ignore or explicitly allow a commit, branch or tag operation
- * for a repository that is connected to the Version Control API
- * by VCS specific hook scripts.
- *
- * @param $operation
- *   A single operation array like the ones returned by
- *   versioncontrol_get_operations(), but leaving out on a few details that
- *   will instead be determined by this function. This array describes
- *   the operation that is about to happen. As it's not committed yet,
- *   it's also not in the database yet, which means that any information
- *   retrieval functions won't work on this operation array.
- *   It also means there's no 'vc_op_id', 'revision' and 'date' elements like
- *   in regular operation arrays. The 'message' element will not be set
- *   if the VCS doesn't support log messages for the current operation
- *   (e.g., most version control systems don't have branch messages).
- *
- *   Summed up, here's what this array contains for sure:
- *
- *   - 'type': The type of the operation - one of the
- *        VERSIONCONTROL_OPERATION_{COMMIT,BRANCH,TAG} constants.
- *   - 'repository': The repository where this operation occurs,
- *        given as a structured array, like the return value
- *        of versioncontrol_get_repository().
- *   - 'uid': The Drupal user id of the committer.
- *   - 'username': The system specific VCS username of the committer.
- *
- *   - 'labels': An array of branches or tags that will be affected by this
- *        operation. Branch and tag operations are known to only affect one
- *        branch or tag, so for these there will be only one element (with 0
- *        as key) in 'labels'. Commits might affect any number of branches,
- *        including none. Commits that emulate branches and/or tags (like
- *        in Subversion, where they're not a native concept) can also include
- *        add/delete/move operations for labels, as detailed below.
- *        Mind that the main development branch - e.g. 'HEAD', 'trunk'
- *        or 'master' - is also considered a branch. Each element in 'labels'
- *        is a structured array with the following keys:
- *
- *        - 'name': The branch or tag name (a string).
- *        - 'action': Specifies what happened to this label in this operation.
- *             For plain commits, this is always VERSIONCONTROL_ACTION_MODIFIED.
- *             For branch or tag operations (or commits that emulate those),
- *             it can be either VERSIONCONTROL_ACTION_ADDED or
- *             VERSIONCONTROL_ACTION_DELETED.
- *
- * @param $operation_items
- *   A structured array containing the exact details of what is about to happen
- *   to each item in this commit. The structure of this array is the same as
- *   the return value of VersioncontrolOperation::getItems() - that is,
- *   elements for 'type', 'path' and 'revision' - but doesn't include
- *   the 'item_revision_id' element as there's no relation to the database yet.
- *
- *   The 'action', 'source_items', 'replaced_item' and 'revision' elements
- *   of each item are optional for the VCS backend and may be left unset.
- *
- * @return
- *   An array with error messages (without trailing newlines) if the operation
- *   should not be allowed, or an empty array if you're indifferent,
- *   or TRUE if the operation should be allowed no matter what other
- *   write access callbacks say.
- *
- * @ingroup Operations
- * @ingroup Commit access
- * @ingroup Target audience: Commit access modules
- */
-function hook_versioncontrol_write_access($operation, $operation_items) {
-  // Only allow users with a registered Drupal user account to commit.
-  if ($operation['uid'] != 0) {
-    $user = user_load(array('uid' => $operation['uid']));
-  }
-  if (!$user) {
-    $error_message = t(
-"** ERROR: no Drupal user matches !vcs user '!user'.
-** Please contact a !vcs administrator for help.",
-      array('!vcs' => $operation->repository->getBackend()->name, '!user' => $operation->committer)
-    );
-    return array($error_message); // disallow the commit with an explanation
-  }
-
-  // Mind that also commits normally have labels, except for stuff like
-  // Subversion when the user commits outside of the trunk/branches/tags
-  // directories. Let's say we want to prevent such commits.
-  if (empty($operation['labels'])) {
-    $error_message = t("** ERROR: It is not allowed to commit without a branch or tag!");
-    return array($error_message);
-  }
-
-  // If an empty array is returned then that means we're indifferent:
-  // allow the operation if nobody else has objections.
-  $error_messages = array();
-
-  // Restrict disallowed branches and tags.
-  $valid_labels = array(
-    VERSIONCONTROL_LABEL_BRANCH => array('@^HEAD$@', '@^DRUPAL-5(--[2-9])?$@', '@^DRUPAL-6--[1-9]$@'),
-    VERSIONCONTROL_LABEL_TAG => array('@^DRUPAL-[56]--(\d+)-(\d+)(-[A-Z0-9]+)?$@'),
-  );
-
-  foreach ($operation['labels'] as $label) {
-    if ($label['type'] == VERSIONCONTROL_LABEL_TAG
-        && $label['action'] == VERSIONCONTROL_ACTION_DELETED) {
-      continue; // no restrictions, even invalid tags should be allowed to be deleted
-    }
-
-    // Make sure that the assigned branch or tag name is allowed.
-    $valid = FALSE;
-
-    foreach ($valid_labels[$label['type']] as $valid_label_regexp) {
-      if (preg_match($valid_label_regexp, $label['name'])) {
-        $valid = TRUE;
-        break;
-      }
-    }
-    if (!$valid) {
-      // No regexps match this label, so deny it.
-      $error_messages[] = t('** ERROR: the !name !labeltype is not allowed in this repository.', array(
-        '!name' => $label['name'],
-        '!labeltype' => ($label['type'] == VERSIONCONTROL_LABEL_BRANCH)
-                        ? t('branch')
-                        : t('tag'),
-      ));
-    }
-  }
-
-  return $error_messages;
-}
-
-
 /**
  * Extract repository data from the repository edit/add form's submitted
  * values, and add it to the @p $repository array. Later, that array will be
@@ -515,136 +387,6 @@ function hook_versioncontrol_is_account_authorized($repository, $uid) {
   return FALSE;
 }
 
-
-/**
- * Unset filtered accounts before they are even attempted to be displayed
- * on the account list ("admin/content/versioncontrol-accounts").
- * You'll most probably use this in conjunction with an additional filter
- * form element that is added to the account filter form
- * ($form['#id'] == 'versioncontrol-account-filter-form') with form_alter().
- *
- * @param $accounts
- *   The accounts that would normally be displayed, in the same format as the
- *   return value of VersioncontrolAccountCache::getInstance()->getAccounts(). Entries in this list
- *   may be unset by this filter function.
- *
- * @ingroup Accounts
- * @ingroup Form handling
- * @ingroup Target audience: Authorization control modules
- */
-function hook_versioncontrol_filter_accounts(&$accounts) {
-  if (empty($accounts)) {
-    return;
-  }
-  // Use a default value if the session variable hasn't yet been set.
-  if (!isset($_SESSION['mymodule_filter_username'])) {
-    $_SESSION['mymodule_filter_username'] = 'chx';
-  }
-  $mymodule_filter_username = $_SESSION['mymodule_filter_username'];
-
-  if ($mymodule_filter_username == '') {
-    return; // Don't change the list if no filtering should happen.
-  }
-
-  foreach ($accounts as $uid => $usernames_by_repository) {
-    foreach ($usernames_by_repository as $repo_id => $username) {
-      if ($username != $mymodule_filter_username) {
-        unset($accounts[$uid][$repo_id]);
-        if (empty($accounts[$uid])) {
-          unset($accounts[$uid]);
-        }
-      }
-    }
-  }
-}
-
-
-/**
- * Extract account data from the account  form's submitted
- * values, and add it to the @p $additional_data array. Later, that array
- * will be passed to hook_versioncontrol_account() as part of the account
- * insert/update procedure.
- *
- * @param $additional_data
- *   The additional account data array which is being passed by reference so
- *   that it can be written to.
- * @param $form
- *   The form array of the submitted account edit/register form, with
- *   $form['#id'] == 'versioncontrol-account-form' (amongst others).
- * @param $form_state
- *   The form state of the submitted account edit/register form.
- *   If you altered this form and added an additional form element then
- *   $form_state['values'] will also contain the value of this form element.
- *
- * @ingroup Accounts
- * @ingroup Form handling
- * @ingroup Target audience: Commit access modules
- * @ingroup Target audience: Authorization control modules
- * @ingroup Target audience: All modules with account specific settings
- */
-function hook_versioncontrol_account_submit(&$additional_data, $form, $form_state) {
-  if (empty($form_state['values']['mymodule_karma'])) {
-    return;
-  }
-  $additional_data['mymodule']['karma'] = $form_state['values']['mymodule_karma'];
-}
-
-/**
- * Act on database changes when VCS accounts are inserted, updated or deleted.
- *
- * @param $op
- *   Either 'insert' when the account has just been created, 'update'
- *   when it has been updated, or 'delete' if it will be deleted after
- *   this function has been called.
- * @param $uid
- *   The Drupal user id corresponding to the VCS account.
- * @param $username
- *   The VCS specific username (a string) of the account.
- * @param $repository
- *   The repository where the user has its VCS account.
- * @param $additional_data
- *   An array of additional author information. Modules can fill this array
- *   by implementing hook_versioncontrol_account_submit().
- *
- * @ingroup Accounts
- * @ingroup Form handling
- * @ingroup Target audience: Commit access modules
- * @ingroup Target audience: Authorization control modules
- * @ingroup Target audience: All modules with account specific settings
- */
-function hook_versioncontrol_account($op, $uid, $username, $repository, $additional_data = array()) {
-  switch ($op) {
-    case 'insert':
-    case 'update':
-      // Recap: if form_alter() wasn't applied, our array element is not set.
-      $mymodule_data = $additional_data['mymodule'];
-
-      if (!isset($mymodule_data)) {
-        // In most modules, form_alter() will always be applied to the
-        // account editing/creating form. If $mymodule_data is empty
-        // nevertheless then it means that the account has been created
-        // programmatically rather than with a form submit.
-        // In that case, we better assign a default value:
-        if ($op == 'insert') {
-          $mymodule_data = array('karma' => 50);
-        }
-        // Don't change the status for programmatical updates, though.
-        if ($op == 'update') {
-          break;
-        }
-      }
-
-      db_query("DELETE FROM {mymodule_karma} WHERE uid = %d", $uid);
-      db_query("INSERT INTO {mymodule_karma} (uid, karma) VALUES (%d, %d)",
-          $uid, $mymodule_data['karma']);
-      break;
-
-    case 'delete':
-      db_query("DELETE FROM {mymodule_karma} WHERE uid = %d", $uid);
-      break;
-  }
-}
-
 /**
  * Add additional columns into the list of VCS accounts.
  * By changing the @p $header and @p $rows_by_uid arguments,
diff --git versioncontrol.info versioncontrol.info
index 345a8bf..5820b2b 100644
--- versioncontrol.info
+++ versioncontrol.info
@@ -5,7 +5,6 @@ dependencies[] = autoload
 dependencies[] = dbtng
 dependencies[] = ctools
 dependencies[] = views
-files[] = includes/VersioncontrolAccount.php
 files[] = includes/VersioncontrolBackend.php
 files[] = includes/VersioncontrolBranch.php
 files[] = includes/VersioncontrolItem.php
diff --git versioncontrol.install versioncontrol.install
index 640610f..77172df 100644
--- versioncontrol.install
+++ versioncontrol.install
@@ -370,38 +370,6 @@ function versioncontrol_schema() {
     'primary key' => array('repo_id'),
   );
 
-  $schema['versioncontrol_accounts'] = array(
-    'description' =>
-      'Association table of VCS account usernames (in a specific repository) to Drupal user ids. A Drupal user can be associated to multiple VCS accounts. Ideally, multiple VCS accounts per repository should be possible too, but clumsy array data structures and assumptions in the admin interface (elsewhere, too? don\'t know) currently make it necessary to restrict the number of VCS accounts to a maximum of 1 per repository and Drupal user.',
-    'fields' => array(
-      'uid' => array(
-        'description' => 'The {users}.uid of the Drupal user associated with the VCS-specific username in {versioncontrol_accounts}.username.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'repo_id' => array(
-        'description' => 'Foreign key (referring to {versioncontrol_repositories}.repo_id) for the repository that contains the VCS account.',
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 0,
-      ),
-      'vcs_username' => array(
-        'description' => 'VCS-specific username of the VCS account associated with the Drupal user in {versioncontrol_accounts}.uid.',
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-        'default' => '',
-      ),
-    ),
-    'unique keys' => array(
-      'repo_id_username' => array('repo_id', 'vcs_username'),
-    ),
-    'primary key' => array('uid', 'repo_id'),
-  );
-
   $schema['versioncontrol_auth_account'] = array(
     'description' => 'ACL table, used by the VersioncontrolAuthHandlerMappedAccounts family of plugins, that stores ACL data on a per-uid/per-repo basis.',
     'fields' => array(
@@ -564,7 +532,6 @@ function versioncontrol_uninstall() {
     'versioncontrol_email_address',
     'versioncontrol_registration_message_unauthorized',
     'versioncontrol_registration_message_authorized',
-    'versioncontrol_admin_account_pager',
   );
   foreach ($variables as $variable) {
     variable_del($variable);
@@ -994,8 +961,7 @@ function versioncontrol_update_6308() {
 }
 
 /**
- * Remove the defunct versioncontrol_accounts table and replace it with ones
- * driven by auth plugins, specifically the
+ * Add tables for auth plugins, specifically the
  * VersioncontrolAuthHandlerMappedAccounts family of plugins.
  */
 function versioncontrol_update_6309() {
@@ -1150,4 +1116,68 @@ function versioncontrol_update_6310() {
   db_create_table($ret, 'versioncontrol_views_sets', $schema);
   
   return $ret;
-}
\ No newline at end of file
+}
+
+/**
+ * Change the main schema to let drupal users have more than one account.
+ */
+function versioncontrol_update_6311() {
+  $ret = array();
+  $account_id = array(
+    'description' => 'The primary identifier for an account.',
+    'type' => 'serial',
+    'unsigned' => TRUE,
+    'not null' => TRUE,
+  );
+  db_drop_primary_key($ret, 'versioncontrol_accounts');
+  db_add_field($ret, 'versioncontrol_accounts', 'account_id', $account_id, array('primary key' => array('account_id')));
+  return $ret;
+}
+
+/**
+ * Move vcs_username field to account status module and remove
+ * {versioncontrol_accounts} table.
+ */
+function versioncontrol_update_6312() {
+  $ret = array();
+
+  // Try to migrate data if possible.
+  if (module_exists('versioncontrol_account_status')) {
+    $vcs_username = array(
+      'description' => 'VCS-specific username.',
+      'type' => 'varchar',
+      'length' => 64,
+      'not null' => TRUE,
+      'default' => '',
+    );
+    db_add_field($ret, 'versioncontrol_account_status_users', 'vcs_username', $vcs_username);
+
+    // Move vcs usernames data to the new field.
+    $result = db_query("SELECT uid, repo_id, vcs_username FROM {versioncontrol_accounts}");
+    while ($row = db_fetch_object($result)) {
+      db_query("UPDATE {versioncontrol_account_status_users} SET vcs_username ='%s' WHERE uid = %d AND repo_id = %d", $row->vcs_username, $row->uid, $row->repo_id);
+    }
+  }
+
+  // Remove the table.
+  db_drop_table($ret, 'versioncontrol_accounts');
+
+  return $ret;
+}
+
+/**
+ * Remove allow_unauthorized_access from repository data.
+ */
+function versioncontrol_update_6313() {
+  $ret = array();
+  $result = db_query("SELECT repo_id, data FROM {versioncontrol_repositories}");
+
+  while ($row = db_fetch_object($result)) {
+    $data = unserialize($row->data);
+    unset($data['versioncontrol']['allow_unauthorized_access']);
+    $data = serialize($row->data);
+    db_query('UPDATE {versioncontrol_repositories} SET data = %s WHERE repo_id = %d', $row->data, $row->repo_id);
+  }
+
+  return $ret;
+}
diff --git versioncontrol.module versioncontrol.module
index 24e7a53..8a86309 100644
--- versioncontrol.module
+++ versioncontrol.module
@@ -95,8 +95,10 @@ define('VERSIONCONTROL_ITEM_FILE_DELETED',      3);
 define('VERSIONCONTROL_ITEM_DIRECTORY_DELETED', 4);
 //@}
 
-
-/** Used internally by the repository and account admin pages. Private constant. */
+/**
+ * Used internally by the repository and account admin pages. Private
+ * constant.
+ */
 define('VERSIONCONTROL_FORM_CREATE', FALSE);
 
 /**
@@ -130,35 +132,6 @@ function versioncontrol_theme() {
 }
 
 /**
- * Implementation of hook_user():
- * Register additional user account edit tabs,
- * and delete VCS accounts when the associated user account is deleted.
- */
-function versioncontrol_user($type, &$edit, &$user, $category = NULL) {
-  switch ($type) {
-    case 'categories':
-      $categories = array();
-      $categories[] = array(
-        'name' => 'versioncontrol',
-        // user_menu() pipes 'title' though check_plain() already.
-        'title' => 'Repository accounts',
-        'weight' => 99,
-      );
-      return $categories;
-
-    case 'delete':
-      $accounts = versioncontrol_user_accounts_load($user->uid, TRUE);
-      foreach ($accounts as $uid => $usernames_by_repository) {
-        foreach ($usernames_by_repository as $repo_id => $account) {
-          $account->delete();
-        }
-      }
-      break;
-
-  }
-}
-
-/**
  * Implementation of hook_menu().
  */
 function versioncontrol_menu() {
@@ -244,51 +217,6 @@ function versioncontrol_menu() {
     'type' => MENU_CALLBACK,
   ) + $admin;
 
-  $items['admin/content/versioncontrol-accounts'] = array(
-    'title' => 'VCS accounts',
-    'description' => 'Manage associations of Drupal users to VCS user accounts.',
-    'page arguments' => array('versioncontrol_admin_account_list_form'),
-    'type' => MENU_NORMAL_ITEM,
-  ) + $admin;
-  $items['admin/content/versioncontrol-accounts/list'] = array(
-    'title' => 'List',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'weight' => 0,
-  );
-
-  // Account registration and editing pages for the regular user.
-  $items['versioncontrol/register'] = array(
-    'title' => 'Get commit access',
-    'page callback' => 'versioncontrol_account_register_page',
-    'access callback' => TRUE, // access checking is done in the page callback
-    'file' => 'versioncontrol.pages.inc',
-    'type' => MENU_SUGGESTED_ITEM,
-  );
-  $items['user/%versioncontrol_user_accounts/edit/versioncontrol'] = array(
-    // Load with $include_unauthorized == TRUE, so that the user can inspect
-    // his/her VCS accounts even if they are not approved by the admin yet.
-    'load arguments' => array(TRUE),
-    'title callback' => 'versioncontrol_user_accounts_title_callback',
-    'title arguments' => array(1),
-    'page callback' => 'versioncontrol_account_page',
-    'page arguments' => array(1),
-    'access callback' => 'versioncontrol_private_account_access',
-    'access arguments' => array(1),
-    'file' => 'versioncontrol.pages.inc',
-    'weight' => 99,
-    'type' => MENU_LOCAL_TASK,
-  );
-
-  // Autocomplete callback for Drupal usernames that have access to
-  // the repo_id given in arg(3). (No need to fetch the full repository,
-  // as the callback uses a raw & safe database query anyways.)
-  $items['versioncontrol/user/autocomplete'] = array(
-    'title' => 'Version control user autocomplete',
-    'page callback' => 'versioncontrol_user_autocomplete',
-    'access callback' => 'versioncontrol_user_access',
-    'type' => MENU_CALLBACK,
-  );
-
   return $items;
 }
 
@@ -358,46 +286,6 @@ function versioncontrol_determine_backend_mode() {
 }
 
 /**
- * Custom access callback, determining if the current user (or the one given
- * in @p $account, if set) is permitted to view version control account
- * settings of the user specified the first user id in @p $vcs_accounts.
- * (We take that parameter because it's what the '%versioncontrol_user_accounts'
- * wildcard returns.)
- */
-function versioncontrol_private_account_access($vcs_accounts, $account = NULL) {
-  $viewed_uid = key($vcs_accounts);
-  if (!$viewed_uid) {
-    return FALSE;
-  }
-  if (is_null($account)) {
-    global $user;
-    $account = clone $user;
-  }
-  return ($viewed_uid == $account->uid && user_access('use version control systems', $account))
-    || user_access('administer version control systems', $account);
-}
-
-/**
- * Title callback for the "user/%versioncontrol_user_accounts/edit/versioncontrol" tab.
- */
-function versioncontrol_user_accounts_title_callback($accounts) {
-  $repo_ids = array();
-  foreach ($accounts as $account) {
-    $repo_ids[] = $account->repo_id;
-  }
-  $repositories = versioncontrol_repository_load_multiple($repo_ids);
-  $vcses = array();
-  foreach ($repositories as $repository) {
-    $vcses[$repository['vcs']] = TRUE;
-  }
-  if (count($vcses) == 1) {
-    $repo = array_shift($repositories);
-    return check_plain($repo->getBackend()->name);
-  }
-  return t('Repository accounts');
-}
-
-/**
  * Implementation of hook_perm().
  */
 function versioncontrol_perm() {
@@ -439,28 +327,6 @@ function versioncontrol_repository_load_multiple($ids = array(), $conditions = a
 }
 
 /**
- * Menu wildcard loader for '%versioncontrol_user_accounts':
- * Load and return all VCS accounts of a given user.
- *
- * @param $uid
- *   Drupal user id of the user whose VCS accounts should be loaded.
- * @param $include_unauthorized
- *   Will be passed on to VersioncontrolAccountCache::getInstance()->getAccounts(), see the
- *   API documentation of that function.
- */
-function versioncontrol_user_accounts_load($uid, $include_unauthorized = FALSE) {
-  return versioncontrol_user_accounts_load_multiple(array($uid), array(), array('include unauthorized' => $include_unauthorized));
-}
-
-function versioncontrol_user_accounts_load_multiple($ids = array(), $conditions = array(), $options = array()) {
-  static $controller;
-  if (!isset($controller)) {
-    $controller = new VersioncontrolAccountController();
-  }
-  return $controller->load($ids, $conditions, $options);
-}
-
-/**
  * Get a list of all backends with its detailed information.
  *
  * @param string $backend
@@ -839,7 +705,10 @@ function theme_versioncontrol_account_username($uid, $username, $repository, $op
     ));
   }
   if ($format == 'html' && module_exists('commitlog')) {
-    return l($username, commitlog_get_account_url($repository, $username));
+    $url = url('commitlog', array(
+      'query' => array('username' => $username, 'repo' => $repository['repo_id']),
+    ));
+    return l($username, $url);
   }
   return $username;
 }
@@ -1011,37 +880,6 @@ function versioncontrol_block_site_active_developers() {
   return $block;
 }
 
-
-/**
- * Returns a string of suggestions for Drupal usernames with accounts for
- * the given repository, formatted to be suitable for use with
- * JS autocomplete fields.
- */
-function versioncontrol_user_autocomplete($repo_id, $string = '') {
-  if (!is_numeric($repo_id) || empty($string)) {
-    drupal_json(array());
-    return;
-  }
-  $matches = array();
-  $result = db_query_range("SELECT u.uid, u.name
-                            FROM {users} u
-                             INNER JOIN {versioncontrol_accounts} a
-                              ON u.uid = a.uid
-                            WHERE repo_id = %d
-                             AND LOWER(u.name) LIKE LOWER('%s%%')",
-                            $repo_id, $string, 0, 10);
-
-  while ($user = db_fetch_object($result)) {
-    if (!isset($repository)) {
-      $repository = versioncontrol_repository_load($repo_id);
-    }
-    if ($repository->isAccountAuthorized($user->uid)) {
-      $matches[$user->name] = check_plain($user->name);
-    }
-  }
-  drupal_json($matches);
-}
-
 function versioncontrol_get_views_sets() {
   $sets = &ctools_static('versioncontrol_views_sets_assembled', array());
   $db_set_data = &ctools_static('versioncontrol_views_sets_db_data', array());
@@ -1164,3 +1002,18 @@ function versioncontrol_user_mapping_methods_get_names() {
   asort($names);
   return $names;
 }
+
+/**
+ * Load the names of all 'auth_handlers' for use at forms.
+ */
+function versioncontrol_auth_handlers_get_names() {
+  ctools_include('plugins');
+
+  $names = array();
+  foreach (ctools_get_plugins('versioncontrol', 'vcs_auth') as $name => $plugin) {
+    $names[$name] = $plugin['title'];
+  }
+
+  asort($names);
+  return $names;
+}
diff --git versioncontrol.pages.inc versioncontrol.pages.inc
index fb6ad38..1f4c3c3 100644
--- versioncontrol.pages.inc
+++ versioncontrol.pages.inc
@@ -11,121 +11,6 @@
  * Copyright 2007, 2009 by Jakob Petsovits ("jpetso", http://drupal.org/user/56020)
  */
 
-// The account registration form has a special demo mode to show the admin how
-// account registration will look like in the general case, mainly in order to
-// demonstrate how the various registration messages are being used.
-define('VERSIONCONTROL_REGISTER_DEMO', -1);
-
-/**
- * Form callback for "versioncontrol/register[/$register_uid[/$register_at_repo_id]]":
- * Provide an indirection that leads to an account registration form.
- */
-function versioncontrol_account_register_page($register_uid = FALSE, $register_at_repo_id = FALSE) {
-  global $user;
-
-  if ($user->uid == 0 || !versioncontrol_user_access()) {
-    $presets = _versioncontrol_get_string_presets();
-
-    return variable_get(
-      'versioncontrol_registration_message_unauthorized',
-      $presets['versioncontrol_registration_message_unauthorized']
-    );
-  }
-
-  if ($register_uid == 'demo') {
-    $register_uid = VERSIONCONTROL_REGISTER_DEMO;
-  }
-  else {
-    $register_uid = is_numeric($register_uid) ? $register_uid : $user->uid;
-  }
-
-  $admin_access = versioncontrol_admin_access();
-
-  if (!$admin_access && $register_uid != $user->uid) {
-    drupal_access_denied();
-    return;
-  }
-
-  $accounts = versioncontrol_user_accounts_load($register_uid, TRUE);
-  $repositories = versioncontrol_repository_load_multiple(FALSE);
-
-  // Construct the '#options' array.
-  $account_usernames = array();
-  foreach ($accounts as $uid => $usernames_by_repository) {
-    foreach ($usernames_by_repository as $repo_id => $account) {
-      $account_usernames[$repo_id][] = $account->vcs_username;
-    }
-  }
-
-  if ($register_uid == VERSIONCONTROL_REGISTER_DEMO) {
-    $account_usernames = array();
-  }
-
-  $repository_names = array();
-  foreach ($repositories as $repo_id => $repository) {
-    if (isset($account_usernames[$repo_id])
-        && $repository->isAccountAuthorized($register_uid)) {
-      // We only want repositories in the list of repositories that are open
-      // for registrations where no (authorized) account exists yet.
-      continue;
-    }
-    if (!isset($first_repo_id)) {
-      $first_repo_id = $repo_id;
-    }
-    $repository_names[$repo_id] = check_plain($repository['name']);
-  }
-
-  // Filter (and possibly change the caption of) the list of repositories to
-  // select. The admin has all the permissions and gets the uncensored list.
-  if (!$admin_access) {
-    foreach (module_implements('versioncontrol_alter_repository_selection') as $module) {
-      $function = $module .'_versioncontrol_alter_repository_selection';
-      $function($repository_names, $repositories);
-    }
-  }
-
-  // If there's just one repository on the site, redirect directly to this one.
-  if (count($repository_names) == 1) {
-    $only_repo_id = $first_repo_id;
-  }
-  elseif (count($repositories) == 1) {
-    $only_repo_id = reset(array_keys($repositories));
-  }
-
-  if ($register_uid == VERSIONCONTROL_REGISTER_DEMO) {
-    unset($only_repo_id);
-  }
-
-  if (is_numeric($register_at_repo_id) || isset($only_repo_id)) {
-    // If there is only one repository left to register, it doesn't matter
-    // whether or not the URL contains a repository (and which one), we always
-    // redirect to the remaining possible one. Otherwise, we try to register
-    // at the given repository.
-    $repo_id = isset($only_repo_id) ? $only_repo_id : $register_at_repo_id;
-
-    if (isset($account_usernames[$repo_id])) {
-      drupal_set_message(t('You already have a registered account.'));
-      drupal_goto('user/'. $user->uid .'/edit/versioncontrol/'. $repo_id
-                  .'/'. reset($account_usernames[$repo_id]));
-      // drupal_goto() calls exit() so script execution ends right here
-    }
-    elseif (isset($repository_names[$repo_id])) {
-      return drupal_get_form('versioncontrol_account_edit_form',
-        $register_uid, $repositories[$repo_id], VERSIONCONTROL_FORM_CREATE
-      );
-    }
-  }
-
-  if (!isset($first_repo_id)) {
-    // when there are no repos, this var is not set
-    $first_repo_id = NULL;
-  }
-
-  return drupal_get_form('versioncontrol_account_register_form',
-    $register_uid, $repository_names, $first_repo_id
-  );
-}
-
 /**
  * Implementation of hook_versioncontrol_alter_repository_selection():
  * Alter the list of repositories that are available for user registration
@@ -153,414 +38,3 @@ function versioncontrol_versioncontrol_alter_repository_selection(&$repository_n
     }
   }
 }
-
-/**
- * The actual form for "versioncontrol/register[/$register_uid]".
- */
-function versioncontrol_account_register_form(&$form_state, $register_uid, $repository_names, $first_repo_id) {
-  $form = array();
-
-  if (empty($repository_names)) {
-    drupal_set_title(t('No more registrations possible'));
-    $form['no_registration'] = array(
-      '#type' => 'markup',
-      '#value' => t('You already have an account for all the repositories where you can register. Go to your !user-account-page to configure repository account settings.',
-        array('!user-account-page' => l(t('user account page'), 'user/'. $register_uid .'/edit/versioncontrol'))
-      ),
-      '#prefix' => '<p>',
-      '#suffix' => '</p>',
-    );
-    return $form;
-  }
-
-  $form['#id'] = 'vcs-account-indirection-form';
-
-  $message = variable_get('versioncontrol_registration_message_authorized', FALSE);
-  if ($message == FALSE) {
-    $presets = _versioncontrol_get_string_presets();
-    $message = $presets['versioncontrol_registration_message_authorized'];
-  }
-  if (!empty($message)) {
-    $form['overview'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Overview'),
-      '#weight' => -100,
-    );
-    $form['overview']['overview'] = array(
-      '#type' => 'markup',
-      '#value' => $message,
-    );
-  }
-
-  $form['#uid'] = $register_uid;
-
-  $form['repository'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Select repository'),
-    '#weight' => 10,
-  );
-  $form['repository']['repo_id'] = array(
-    '#type' => 'select',
-    '#title' => t('Create user account in'),
-    '#options' => $repository_names,
-    '#default_value' => $first_repo_id,
-  );
-
-  if ($register_uid != VERSIONCONTROL_REGISTER_DEMO) {
-    $form['repository']['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Create account'),
-      '#weight' => 100,
-    );
-  }
-  return $form;
-}
-
-/**
- * Submit handler for the indirection form.
- * Surprisingly, all it does is redirect to the appropriate registration form.
- */
-function versioncontrol_account_register_form_submit($form, &$form_state) {
-  $form_state['redirect'] = 'versioncontrol/register/'. $form['#uid'] .'/'. $form_state['values']['repo_id'];
-}
-
-
-/**
- * Form callback for 'user/%versioncontrol_user_accounts/edit/versioncontrol':
- * Display a list of the given user's VCS accounts, or directly return the form
- * array from versioncontrol_account_edit_form() if only a single account
- * exists for that user (or if the account has been given in the URL).
- */
-function versioncontrol_account_page($vcs_accounts, $url_repo_id = NULL, $url_username = NULL) {
-  $selected_usernames = array();
-
-  foreach ($vcs_accounts as $key => $vcs_account) {
-    // The caller (menu system) ensures that there is only one uid.
-    $uid = $vcs_account->uid;
-    if (isset($url_repo_id) && $vcs_account->repo_id != $url_repo_id) {
-      unset($vcs_accounts[$key]);
-      continue; // disregard repositories that don't match the URL constraints
-    }
-    if (isset($url_username) && $vcs_account->vcs_username != $url_username) {
-      unset($vcs_accounts[$key]);
-      continue; // disregard usernames that don't match the URL constraints
-    }
-    $any_repo_id = $vcs_account->repo_id;
-    $selected_usernames[] = $vcs_account->vcs_username;
-  }
-
-  if (empty($selected_usernames)) {
-    drupal_not_found();
-    return;
-  }
-  elseif (count($selected_usernames) == 1) {
-    $repository = versioncontrol_repository_load($any_repo_id);
-    return drupal_get_form('versioncontrol_account_edit_form',
-      $uid, $repository, reset($selected_usernames)
-    );
-  }
-  else {
-    return drupal_get_form('versioncontrol_account_list_form', $vcs_accounts);
-  }
-}
-
-/**
- * Form callback for "admin/content/versioncontrol-accounts" and
- * (in certain cases) "user/%versioncontrol_user_accounts/edit/versioncontrol":
- * Show a list of VCS accounts to the admin or the user.
- *
- * @param $accounts
- *   The list of accounts to show, in versioncontrol_user_account_load_multiple format.
- */
-function versioncontrol_account_list_form(&$form_state, $accounts) {
-  $form = array();
-  $form['#id'] = 'versioncontrol-account-list-form';
-
-  $repositories = versioncontrol_repository_load_multiple(array_keys(reset($accounts)));
-
-  $header = array(t('Repository'), t('Username'), '');
-  $rows = array();
-
-  foreach ($accounts as $uid => $usernames_by_repository) {
-    foreach ($usernames_by_repository as $repo_id => $username) {
-      if (!isset($repositories[$repo_id])) { // happens if the backend isn't loaded
-        continue;
-      }
-      $usernames = array($username);
-
-      foreach ($usernames as $username) {
-        $formatted_username = theme('versioncontrol_account_username',
-          $uid, $username, $repositories[$repo_id],
-          array('prefer_drupal_username' => FALSE)
-        );
-        $repo_name = module_exists('commitlog')
-          ? theme('commitlog_repository', $repositories[$repo_id])
-          : check_plain($repositories[$repo_id]['name']);
-
-        $rows[] = array(
-          $repo_name,
-          $formatted_username,
-          l(t('Edit @vcs account', array('@vcs' => $repositories[$repo_id]->getBackend()->name)),
-            'user/'. $uid .'/edit/versioncontrol/'. $repo_id .'/'. drupal_urlencode($username)
-          ),
-        );
-      }
-    }
-  }
-
-  $form['accounts'] = array(
-    '#type' => 'markup',
-    '#value' => theme('table', $header, $rows, array('style' => 'width: 50%;')),
-  );
-  return $form;
-}
-
-/**
- * Form callback for (in certain cases) "versioncontrol/register"
- * and "user/%versioncontrol_user_accounts/edit/versioncontrol":
- * Provide a form to register or edit a VCS account.
- *
- * @param $uid
- *   The uid of the Drupal user whose account is being edited or registered.
- * @param $repository
- *   The repository of the added/edited account.
- * @param $vcs_username
- *   The user's VCS-specific username for the repository,
- *   or VERSIONCONTROL_FORM_CREATE if a new VCS account should be registered.
- */
-function versioncontrol_account_edit_form(&$form_state, $uid, $repository, $vcs_username) {
-  $form = array();
-  $create_account = ($vcs_username === VERSIONCONTROL_FORM_CREATE);
-  $vcs_name = $repository->getBackend()->name;
-
-  $user = ($uid === VERSIONCONTROL_REGISTER_DEMO) ? FALSE : user_load($uid);
-
-  if (!($user || ($uid === VERSIONCONTROL_REGISTER_DEMO && $create_account))) {
-    drupal_not_found(); // cannot edit/register accounts for non-existing users
-    return array();
-  }
-
-  // Set an appropriate page title.
-  if ($create_account) {
-    drupal_set_title(t(
-      'Create user account in @repository',
-      array('@repository' => $repository['name'])
-    ));
-  }
-  elseif ($user) {
-    drupal_set_title(check_plain($user->name));
-  }
-
-  $form['#id'] = 'versioncontrol-account-form';
-
-  $form['#repository'] = $repository;
-  $form['#vcs'] = $repository['vcs'];
-  $form['#vcs_name'] = $vcs_name;
-  $form['#uid'] = $uid;
-  $form['#original_username'] = $vcs_username;
-
-  $form['#validate'] = array('versioncontrol_account_edit_form_validate');
-  $form['#submit'] = array('versioncontrol_account_edit_form_submit');
-
-  if ($create_account) {
-    $registration_message = isset($repository->data['versioncontrol']['registration_message'])
-      ? $repository->data['versioncontrol']['registration_message']
-      : '';
-
-    if (!empty($registration_message)) {
-      $form['overview'] = array(
-        '#type' => 'fieldset',
-        '#title' => t('Overview'),
-        '#weight' => -100,
-      );
-      $form['overview']['overview'] = array(
-        '#type' => 'markup',
-        '#value' => $registration_message,
-      );
-    }
-  }
-
-  $form['account'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('@vcs account settings', array('@vcs' => $vcs_name)),
-    '#weight' => 0,
-  );
-
-  $admin_access = versioncontrol_admin_access();
-
-  if ($create_account || $admin_access) {
-    if ($create_account) {
-      $data = array(
-        'vcs_username' => $vcs_username,
-        'uid' => $uid,
-        'repository' => $repository,
-      );
-      $vcs_account = $repository->getBackend()->buildEntity('account', $data);
-      // Have a nice default value for the new VCS username.
-      $vcs_username = $repository->getBackend()->usernameSuggestion($user);
-    }
-
-    if ($admin_access) { // the admin version
-      $description = t('The @vcs username associated with the account of !user. This field is used to link commit messages to user accounts.', array('@vcs' => $vcs_name, '!user' => theme_username($user)));
-    }
-    else { // the account creation version
-      $description = t('Choose a username to access the @vcs repository with. @vcs usernames should be lowercase. Spaces or other special characters are not allowed.', array('@vcs' => $vcs_name));
-    }
-
-    $form['account']['account_name'] = array(
-      '#type' => 'textfield',
-      '#title' => t('@vcs username', array('@vcs' => $vcs_name)),
-      '#description' => $description,
-      '#default_value' => $vcs_username,
-      '#weight' => 0,
-      '#size' => 30,
-      '#maxlength' => 64,
-    );
-  }
-  else {
-    $form['account_name'] = array(
-      '#type' => 'value',
-      '#value' => $vcs_username,
-    );
-    $form['account']['account_name_display'] = array(
-      '#type' => 'item',
-      '#title' => t('@vcs username', array('@vcs' => $vcs_name)),
-      '#description' => t('Your @vcs username. This field can only be edited by administrators and is used to link your @vcs messages to your user account.', array('@vcs' => $vcs_name)),
-      '#value' => $vcs_username,
-      '#weight' => 0,
-    );
-  }
-
-  if ($uid !== VERSIONCONTROL_REGISTER_DEMO) {
-    $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => $create_account
-                  ? t('Create @vcs account', array('@vcs' => $vcs_name))
-                  : t('Update @vcs account', array('@vcs' => $vcs_name)),
-      '#weight' => 100,
-    );
-  }
-  return $form;
-}
-
-/**
- * Validate the edit/register user account form submission before it is submitted.
- */
-function versioncontrol_account_edit_form_validate($form, &$form_state) {
-  if (!isset($form_state['values']['account_name'])) {
-    return;
-  }
-  $uid = $form['#uid'];
-  $username = trim($form_state['values']['account_name']);
-  $repository = $form['#repository'];
-  $vcs_name = $form['#vcs_name'];
-
-  if (!isset($repository)) { // admin deletes repo while user fills in form
-    form_set_error('account',
-      t('The repository has been deleted.')
-    );
-    return;
-  }
-
-  if (empty($username)) {
-    form_set_error('account_name',
-      t('The @vcs username may not be empty.', array('@vcs' => $vcs_name))
-    );
-  }
-  else {
-    // Check for username validity - done by the backend, but with a fallback
-    // for alphanum-only characters.
-    $data = array(
-      'vcs_username' => $username,
-      'uid' => $uid,
-      'repository' => $repository,
-    );
-    $vcs_account = $repository->getBackend()->buildEntity('account', $data);
-    if (!$repository->getBackend()->isUsernameValid($username)) {
-      form_set_error('account_name',
-        t('The specified @vcs username is invalid.', array('@vcs' => $vcs_name))
-      );
-    }
-    // The username is passed by reference and might have changed. That's a bit
-    // uncomfortable as a caller API, but more convenient for the backends.
-    // (Plus it makes sense anyways since we have trimmed the username too.)
-    $form_state['values']['account_name'] = $username;
-
-    // Check for duplicates.
-    $existing_uid = $repository->getAccountUidForUsername($username, TRUE);
-    if ($existing_uid && $uid != $existing_uid) {
-      if ($existing_user = user_load(array('uid' => $existing_uid))) {
-        $existing_username = theme('username', $existing_user);
-      }
-      else {
-        $existing_username = t('user #!id', array('!id' => $existing_uid));
-      }
-      form_set_error('account_name',
-        t('The specified @vcs username is already in use by !existing-user.',
-          array('@vcs' => $vcs_name, '!existing-user' => $existing_username))
-      );
-    }
-  }
-}
-
-/**
- * Add or update the user account when the edit/register form is submitted.
- */
-function versioncontrol_account_edit_form_submit($form, &$form_state) {
-  // Reconstruct the user data from the $form_state that was passed.
-  $uid = $form['#uid'];
-  $vcs_username = $form_state['values']['account_name'];
-  $repository = $form['#repository'];
-  $vcs_name = $form['#vcs_name'];
-
-  // Let other modules provide additional account data.
-  $additional_data = array();
-  foreach (module_implements('versioncontrol_account_submit') as $module) {
-    $function = $module .'_versioncontrol_account_submit';
-    $function($additional_data, $form, $form_state);
-  }
-
-  if (empty($form['#original_username'])) {
-    $data = array(
-      'vcs_username' => $vcs_username,
-      'uid' => $uid,
-      'repository' => $repository,
-    );
-    $vcs_account = $repository->getBackend()->buildEntity('account', $data);
-    $vcs_account->additional_data = $additional_data;
-    $vcs_account->insert();
-    $message = drupal_set_message(t(
-      'The @vcs account %vcs_username has been registered.',
-      array('@vcs' => $vcs_name, '%vcs_username' => $vcs_username)
-    ));
-  }
-  else {
-    //FIXME why username are a required constraint? <-- shouldn't be anymore
-    //      uid and repo_id are the PK on the table getAccounts query
-    $conditions = array(
-      'repo_id' => array($repository->repo_id),
-      'vcs_username' => array($form['#original_username'])
-    );
-    $vcs_accounts = versioncontrol_user_accounts_load_multiple(array($uid), $conditions, array('include unauthorized' => TRUE));
-    // if we got an original_username we can trust on getting a value
-    $vcs_account = array_shift($vcs_accounts);
-
-    $vcs_account->vcs_username = $vcs_username;
-    $vcs_account->additional_data = $additional_data;
-    $vcs_account->update();
-
-    // Regular users cannot change the username, and will probably get
-    // a message for each of the other actions that hook into the form.
-    if (versioncontrol_admin_access()) {
-      $message = drupal_set_message(t(
-        'The @vcs account %username has been updated successfully.',
-        array('@vcs' => $vcs_name, '%username' => $vcs_username)
-      ));
-    }
-  }
-
-  $form_state['redirect'] = versioncontrol_admin_access()
-    ? 'admin/content/versioncontrol-accounts'
-    : 'user/'. $uid .'/edit/versioncontrol/'. $repository->repo_id
-        .'/'. drupal_urlencode($vcs_username);
-}
diff --git versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_field_account_link_edit.inc versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_field_account_link_edit.inc
new file mode 100644
index 0000000..24c7ff9
--- /dev/null
+++ versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_field_account_link_edit.inc
@@ -0,0 +1,15 @@
+<?php
+// $Id$
+
+/**
+ * Views Field handler to create a link to account edition form.
+ */
+class versioncontrol_account_status_handler_field_account_link_edit extends views_handler_field {
+  function render($values) {
+    $uid = $values->{$this->field_alias};
+    $repo_id = $values->{$this->aliases['repo_id']};
+    $vcs_username = $values->{$this->aliases['vcs_username']};
+    $link = sprintf('user/%d/edit/versioncontrol/%d/%s', $uid, $repo_id, drupal_urlencode($vcs_username));
+    return l(t('Edit'), $link);
+  }
+}
diff --git versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_field_account_status.inc versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_field_account_status.inc
new file mode 100755
index 0000000..501dbd5
--- /dev/null
+++ versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_field_account_status.inc
@@ -0,0 +1,18 @@
+<?php
+// $Id$
+
+/**
+ * Views Field handler map account status constants to strings.
+ */
+class versioncontrol_account_status_handler_field_account_status extends views_handler_field {
+  public $account_statuses;
+
+  function construct() {
+    parent::construct();
+    $this->account_statuses = _versioncontrol_account_status_get_status_options(TRUE);
+  }
+
+  function render($values) {
+    return $this->account_statuses[$values->{$this->field_alias}];
+  }
+}
diff --git versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_filter_account_status.inc versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_filter_account_status.inc
new file mode 100755
index 0000000..dbd8ba3
--- /dev/null
+++ versioncontrol_account_status/includes/handlers/versioncontrol_account_status_handler_filter_account_status.inc
@@ -0,0 +1,14 @@
+<?php
+// $Id$
+
+/**
+ * Views filter handler to allow filtering based on the account status.
+ */
+
+class versioncontrol_account_status_handler_filter_account_status extends views_handler_filter_in_operator {
+
+  function get_value_options() {
+    $this->value_options = _versioncontrol_account_status_get_status_options(TRUE);
+  }
+
+}
diff --git versioncontrol_account_status/includes/versioncontrol_account_status.views.inc versioncontrol_account_status/includes/versioncontrol_account_status.views.inc
new file mode 100755
index 0000000..db3dcb0
--- /dev/null
+++ versioncontrol_account_status/includes/versioncontrol_account_status.views.inc
@@ -0,0 +1,170 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ *
+ * Implement views hooks to provide views integration for Version Control
+ * Account statsus tables and define the requisite plugins for doing so.
+ */
+
+/**
+ * Implementation of hook_views_data().
+ */
+function versioncontrol_account_status_views_data() {
+  $data = array();
+  $data['versioncontrol_account_status_users']['table']['base'] = array(
+    'field' => 'account_id',
+    'title' => t('Versioncontrol account status accounts'),
+    'help' => t('A table describing the approval status of a user account in an associated repository. The Version Control Account Status module maps the approval status to the the Version Control API\'s concept of "authorized accounts".'),
+  );
+  $data['versioncontrol_account_status_users']['table']['group'] = t('Versioncontrol account status');
+  $data['versioncontrol_account_status_users']['account_id'] = array(
+    'title' => t('Account status account ID'),
+    'help' => t('The primary identifier for an account.'),
+    'field' => array(
+      'handler' => 'views_handler_field_numeric',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+      'allow empty' => TRUE,
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_numeric',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+  $data['versioncontrol_account_status_users']['uid'] = array(
+    'title' => t('User ID'),
+    'help' => t('The Drupal user id of the applying user, referring to both {users}.uid.'),
+    'relationship' => array(
+      'base'  => 'users',
+      'base field' => 'uid',
+      'handler' => 'views_handler_relationship',
+      'label' => t('User'),
+    ),
+    'field' => array(
+      'handler' => 'views_handler_field_numeric',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+      'allow empty' => TRUE,
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_numeric',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+  $data['versioncontrol_account_status_users']['repo_id'] = array(
+    'title' => t('Repository ID'),
+    'help' => t('The {versioncontrol_repositories}.repo_id where the user requested approval for a VCS account.'),
+    'relationship' => array(
+      'base'  => 'versioncontrol_repositories',
+      'base field' => 'repo_id',
+      'handler' => 'views_handler_relationship',
+      'label' => t('Repository'),
+    ),
+    'field' => array(
+      'handler' => 'views_handler_field_numeric',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+      'allow empty' => TRUE,
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_numeric',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+  $data['versioncontrol_account_status_users']['motivation'] = array(
+    'title' => t('Motivation'),
+    'help' => t('The motivation message entered by the applying user. This contains an explanation why the user thinks that (s)he should get a VCS account for this repository.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+      'allow empty' => TRUE,
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+  $data['versioncontrol_account_status_users']['status'] = array(
+    'title' => t('Status'),
+    'help' => t('The approval status of the applying user - one of the constants defined at the top of versioncontrol_account_status.module. If there is no entry for a user/repository combination, the module will assume the VERSIONCONTROL_ACCOUNT_STATUS_UNDEFINED constant when retrieving the status.'),
+    'field' => array(
+      'handler' => 'versioncontrol_account_status_handler_field_account_status',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'versioncontrol_account_status_handler_filter_account_status',
+      'allow empty' => TRUE,
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_numeric',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+  $data['versioncontrol_account_status_users']['edit_account'] = array(
+    'title' => t('Edit link'),
+    'field' => array(
+      'handler' => 'versioncontrol_account_status_handler_field_account_link_edit',
+      'real field' => 'uid',
+      'additional fields' => array(
+        'repo_id', 'vcs_username'
+      ),
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+  );
+
+  return $data;
+}
+
+/**
+ * Implement hook_views_handler().
+ */
+function versioncontrol_account_status_views_handlers() {
+  $ret = array(
+    'info' => array(
+      'path'       => drupal_get_path('module', 'versioncontrol_account_status') . '/includes/handlers',
+    ),
+    'handlers' => array(
+      // field handlers
+      'versioncontrol_account_status_handler_field_account_status' => array(
+        'parent' => 'views_handler_field',
+      ),
+      'versioncontrol_account_status_handler_field_account_link_edit' => array(
+        'parent' => 'views_handler_field',
+      ),
+      // filter handlers
+      'versioncontrol_account_status_handler_filter_account_status' => array(
+        'parent' => 'views_handler_filter_in_operator',
+      ),
+    ),
+  );
+  return $ret;
+}
diff --git versioncontrol_account_status/includes/versioncontrol_account_status.views_default.inc versioncontrol_account_status/includes/versioncontrol_account_status.views_default.inc
new file mode 100644
index 0000000..d7c9f78
--- /dev/null
+++ versioncontrol_account_status/includes/versioncontrol_account_status.views_default.inc
@@ -0,0 +1,285 @@
+<?php
+// $Id: commitlog.views_default.inc,v 1.5 2010/12/03 19:50:02 marvil07 Exp $
+
+/**
+ * @file
+ *   Provide default views for use by the account status module.
+ */
+
+/**
+ * Implementation of hook_views_default_views().
+ */
+function versioncontrol_account_status_views_default_views() {
+  $views = array();
+  //TODO add a repository filter by name
+
+  // View 'versioncontrol_account_status_accounts'
+  $view = new view;
+  $view->name = 'versioncontrol_account_status_acccounts';
+  $view->description = t('Accounts as defined by the versiocontrol_account_status module.');
+  $view->tag = 'Version Control Account Status';
+  $view->view_php = '';
+  $view->base_table = 'versioncontrol_account_status_users';
+  $view->is_cacheable = FALSE;
+  $view->api_version = 2;
+  $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
+  $handler = $view->new_display('default', 'Defaults', 'default');
+  $handler->override_option('relationships', array(
+    'repo_id' => array(
+      'label' => 'Repository',
+      'required' => 0,
+      'id' => 'repo_id',
+      'table' => 'versioncontrol_account_status_users',
+      'field' => 'repo_id',
+      'relationship' => 'none',
+    ),
+    'uid' => array(
+      'label' => 'User',
+      'required' => 0,
+      'id' => 'uid',
+      'table' => 'versioncontrol_account_status_users',
+      'field' => 'uid',
+      'relationship' => 'none',
+    ),
+  ));
+  $handler->override_option('fields', array(
+    'account_id' => array(
+      'label' => 'Account ID',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'target' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'html' => 0,
+        'strip_tags' => 0,
+      ),
+      'empty' => '',
+      'hide_empty' => 0,
+      'empty_zero' => 0,
+      'set_precision' => FALSE,
+      'precision' => 0,
+      'decimal' => '.',
+      'separator' => ',',
+      'prefix' => '',
+      'suffix' => '',
+      'exclude' => 0,
+      'id' => 'account_id',
+      'table' => 'versioncontrol_account_status_users',
+      'field' => 'account_id',
+      'relationship' => 'none',
+    ),
+    'vcs' => array(
+      'label' => 'Backend',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'target' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'html' => 0,
+        'strip_tags' => 0,
+      ),
+      'empty' => '',
+      'hide_empty' => 0,
+      'empty_zero' => 0,
+      'exclude' => 0,
+      'id' => 'vcs',
+      'table' => 'versioncontrol_repositories',
+      'field' => 'vcs',
+      'relationship' => 'repo_id',
+    ),
+    'name' => array(
+      'label' => 'Repository',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'target' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'html' => 0,
+        'strip_tags' => 0,
+      ),
+      'empty' => '',
+      'hide_empty' => 0,
+      'empty_zero' => 0,
+      'exclude' => 0,
+      'id' => 'name',
+      'table' => 'versioncontrol_repositories',
+      'field' => 'name',
+      'relationship' => 'repo_id',
+    ),
+    'name_1' => array(
+      'label' => 'Username',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'target' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'html' => 0,
+        'strip_tags' => 0,
+      ),
+      'empty' => '',
+      'hide_empty' => 0,
+      'empty_zero' => 0,
+      'link_to_user' => 1,
+      'overwrite_anonymous' => 0,
+      'anonymous_text' => '',
+      'exclude' => 0,
+      'id' => 'name_1',
+      'table' => 'users',
+      'field' => 'name',
+      'relationship' => 'uid',
+    ),
+    'status' => array(
+      'label' => 'Status',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'target' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'html' => 0,
+        'strip_tags' => 0,
+      ),
+      'empty' => '',
+      'hide_empty' => 0,
+      'empty_zero' => 0,
+      'exclude' => 0,
+      'id' => 'status',
+      'table' => 'versioncontrol_account_status_users',
+      'field' => 'status',
+      'relationship' => 'none',
+    ),
+    'edit_account' => array(
+      'label' => 'Edit link',
+      'alter' => array(
+        'alter_text' => 0,
+        'text' => '',
+        'make_link' => 0,
+        'path' => '',
+        'link_class' => '',
+        'alt' => '',
+        'prefix' => '',
+        'suffix' => '',
+        'target' => '',
+        'help' => '',
+        'trim' => 0,
+        'max_length' => '',
+        'word_boundary' => 1,
+        'ellipsis' => 1,
+        'html' => 0,
+        'strip_tags' => 0,
+      ),
+      'empty' => '',
+      'hide_empty' => 0,
+      'empty_zero' => 0,
+      'exclude' => 0,
+      'id' => 'edit_account',
+      'table' => 'versioncontrol_account_status_users',
+      'field' => 'edit_account',
+      'relationship' => 'none',
+    ),
+  ));
+  $handler->override_option('filters', array(
+    'status' => array(
+      'operator' => 'in',
+      'value' => array(),
+      'group' => '0',
+      'exposed' => TRUE,
+      'expose' => array(
+        'use_operator' => 0,
+        'operator' => 'status_op',
+        'identifier' => 'status',
+        'label' => 'Account status',
+        'optional' => 1,
+        'single' => 1,
+        'remember' => 1,
+        'reduce' => 0,
+      ),
+      'id' => 'status',
+      'table' => 'versioncontrol_account_status_users',
+      'field' => 'status',
+      'relationship' => 'none',
+    ),
+    'uid' => array(
+      'operator' => 'in',
+      'value' => '',
+      'group' => '0',
+      'exposed' => TRUE,
+      'expose' => array(
+        'use_operator' => 0,
+        'operator' => 'uid_op',
+        'identifier' => 'uid',
+        'label' => 'Usernames',
+        'optional' => 1,
+        'remember' => 1,
+        'reduce' => 0,
+      ),
+      'id' => 'uid',
+      'table' => 'users',
+      'field' => 'uid',
+      'relationship' => 'uid',
+    ),
+  ));
+  $handler->override_option('access', array(
+    'type' => 'perm',
+    'perm' => 'administer version control systems',
+  ));
+  $handler->override_option('cache', array(
+    'type' => 'none',
+  ));
+  $handler->override_option('title', 'Version Control Account Status Accounts');
+  $handler->override_option('items_per_page', 50);
+  $handler->override_option('use_pager', '1');
+  $handler->override_option('style_plugin', 'table');
+  $views[$view->name] = $view;
+
+  return $views;
+}
diff --git versioncontrol_account_status/includes/versioncontrol_plugins/vcs_auth/VersioncontrolAuthHandlerAccountStatus.class.php versioncontrol_account_status/includes/versioncontrol_plugins/vcs_auth/VersioncontrolAuthHandlerAccountStatus.class.php
new file mode 100644
index 0000000..87e6c57
--- /dev/null
+++ versioncontrol_account_status/includes/versioncontrol_plugins/vcs_auth/VersioncontrolAuthHandlerAccountStatus.class.php
@@ -0,0 +1,80 @@
+<?php
+
+class VersioncontrolAuthHandlerAccountStatus implements VersioncontrolAuthHandlerInterface {
+  /**
+   * Boolean indicating whether the object has already run its build routine.
+   *
+   * @var bool
+   */
+  protected $built = FALSE;
+
+  /**
+   * An array of error message strings returned by
+   * VersioncontrolAuthHandlerMappedAccounts::getErrorMessages().
+   *
+   * @var array
+   */
+  protected $errors = array();
+
+  public function setRepository(VersioncontrolRepository $repository) {
+    if ($this->repository !== $repository) {
+      throw new Exception('Cannot attach different repositories to a single VersioncontrolAuthHandlerAccountStatus instance. Instanciate a new object.', E_RECOVERABLE_ERROR);
+    }
+    $this->repository = $repository;
+    $this->build();
+  }
+
+  protected function build() {
+    if ($this->built) {
+      return; // already built, bail out
+    }
+    if (!$this->repository instanceof VersioncontrolRepository) {
+      throw new Exception('Cannot build the account status object until a repository has been attached.');
+    }
+
+    // Retrieve the base auth data
+    $conditions = array(
+      'repo_id' => $this->repository->repo_id,
+      'status' => VERSIONCONTROL_ACCOUNT_STATUS_APPROVED,
+    );
+    $this->userAccounts = versioncontrol_account_status_get($conditions);
+
+    $this->built = TRUE;
+  }
+
+  public function hasAccountApproved() {
+    // At least one account aproved to pass
+    if (!empty($this->userAccounts)) {
+      return TRUE;
+    }
+    $this->errors[] = t('The user do not still have an account approved on this repository');
+    return FALSE;
+  }
+
+  public function authAccess($uid) {
+    return $this->hasAccountApproved();
+  }
+
+  public function authBranchCreate($uid, VersioncontrolBranch $branch) {
+    return $this->hasAccountApproved();
+  }
+  public function authBranchDelete($uid, VersioncontrolBranch $branch) {
+    return $this->hasAccountApproved();
+  }
+  public function authBranchUpdate($uid, VersioncontrolBranch $branch) {
+    return $this->hasAccountApproved();
+  }
+  public function authTagCreate($uid, VersioncontrolTag $tag) {
+    return $this->hasAccountApproved();
+  }
+  public function authTagDelete($uid, VersioncontrolTag $tag) {
+    return $this->hasAccountApproved();
+  }
+  public function authTagUpdate($uid, VersioncontrolTag $tag) {
+    return $this->hasAccountApproved();
+  }
+
+  public function getErrorMessages() {
+    return $this->errors;
+  }
+}
diff --git versioncontrol_account_status/includes/versioncontrol_plugins/vcs_auth/account_status.inc versioncontrol_account_status/includes/versioncontrol_plugins/vcs_auth/account_status.inc
new file mode 100644
index 0000000..4d7240e
--- /dev/null
+++ versioncontrol_account_status/includes/versioncontrol_plugins/vcs_auth/account_status.inc
@@ -0,0 +1,9 @@
+<?php
+// $Id$
+
+$plugin = array(
+  'title' => t('Account status (only let pass if the user has an account)'),
+  'handler' => array(
+    'class' => 'VersioncontrolAuthHandlerAccountStatus',
+  ),
+);
diff --git versioncontrol_account_status/versioncontrol_account_status.info versioncontrol_account_status/versioncontrol_account_status.info
index 610b29e..8a1358a 100644
--- versioncontrol_account_status/versioncontrol_account_status.info
+++ versioncontrol_account_status/versioncontrol_account_status.info
@@ -2,5 +2,7 @@
 name = "Version Control Account Status"
 description = "Require users to submit a motivation text and meet approval of version control administrators before their VCS account is enabled."
 dependencies[] = versioncontrol
+dependencies[] = views
 package = Version Control
 core = 6.x
+files[] = includes/VersioncontrolAccount.php
diff --git versioncontrol_account_status/versioncontrol_account_status.install versioncontrol_account_status/versioncontrol_account_status.install
index 519a53d..ea338d3 100644
--- versioncontrol_account_status/versioncontrol_account_status.install
+++ versioncontrol_account_status/versioncontrol_account_status.install
@@ -19,8 +19,14 @@ function versioncontrol_account_status_schema() {
     'description' =>
       'A table describing the approval status of a user account in an associated repository. The Version Control Account Status module maps the approval status to the the Version Control API\'s concept of "authorized accounts".',
     'fields' => array(
+      'account_id' => array(
+        'description' => 'The primary identifier for an account.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
       'uid' => array(
-        'description' => 'The Drupal user id of the applying user, referring to both {users}.uid and {versioncontrol_accounts}.uid.',
+        'description' => 'The Drupal user id of the applying user, referring to {users}.uid.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
@@ -33,6 +39,13 @@ function versioncontrol_account_status_schema() {
         'not null' => TRUE,
         'default' => 0,
       ),
+      'vcs_username' => array(
+        'description' => 'VCS-specific username.',
+        'type' => 'varchar',
+        'length' => 64,
+        'not null' => TRUE,
+        'default' => '',
+      ),
       'motivation' => array(
         'description' => 'The motivation message entered by the applying user. This contains an explanation why the user thinks that (s)he should get a VCS account for this repository.',
         'type' => 'text',
@@ -47,7 +60,10 @@ function versioncontrol_account_status_schema() {
         'default' => 0,
       ),
     ),
-    'primary key' => array('uid', 'repo_id'),
+    'primary key' => array('account_id'),
+    'unique keys' => array(
+      'repo_id_username' => array('repo_id', 'vcs_username'),
+    ),
   );
 
   $schema['versioncontrol_account_status_strings'] = array(
@@ -128,3 +144,35 @@ function versioncontrol_account_status_uninstall() {
   // Remove tables.
   drupal_uninstall_schema('versioncontrol_account_status');
 }
+
+/**
+ * Change the main schema to let drupal users have more than one account.
+ */
+function versioncontrol_account_status_update_6301() {
+  $ret = array();
+  $account_id = array(
+    'description' => 'The primary identifier for an account.',
+    'type' => 'serial',
+    'unsigned' => TRUE,
+    'not null' => TRUE,
+  );
+  db_drop_primary_key($ret, 'versioncontrol_account_status_users');
+  db_add_field($ret, 'versioncontrol_account_status_users', 'account_id', $account_id, array('primary key' => array('account_id')));
+  return $ret;
+}
+
+/**
+ * Add data field to {versioncontrol_account_status_users}.
+ */
+function versioncontrol_account_status_update_6302() {
+  $ret = array();
+  $data = array(
+    'description' => 'A data field for account status.',
+    'type' => 'text',
+    'size' => 'medium',
+    'not null' => TRUE,
+    'serialize' => TRUE,
+  );
+  db_add_field($ret, 'versioncontrol_account_status_users', 'data', $data);
+  return $ret;
+}
diff --git versioncontrol_account_status/versioncontrol_account_status.module versioncontrol_account_status/versioncontrol_account_status.module
index 5db3a76..dd26a86 100644
--- versioncontrol_account_status/versioncontrol_account_status.module
+++ versioncontrol_account_status/versioncontrol_account_status.module
@@ -125,21 +125,23 @@ function _versioncontrol_account_status_get_conditions($default_condition_descri
  *         The application had been approved in the past, but was revoked.
  *         The user doesn't have repository access anymore.
  */
-function versioncontrol_account_status_get($uid, $repo_id) {
-  $result = db_query('SELECT uid, repo_id, motivation, status
-                      FROM {versioncontrol_account_status_users}
-                      WHERE uid = %d AND repo_id = %d', $uid, $repo_id);
-
-  while ($data = db_fetch_array($result)) {
-    return $data;
+function versioncontrol_account_status_get($conditions=array(), $include_unauthorized=FALSE) {
+  $select = db_select('versioncontrol_account_status_users', 'base')->fields('base');
+  foreach ($conditions as $key => $condition) {
+    if (is_array($condition)) {
+      $select->condition("base.$key", $condition, 'IN');
+    }
+    else {
+      $select->condition("base.$key", $condition);
+    }
   }
-  // If there is no entry, return a default result value.
-  return array(
-    'uid' => $uid,
-    'repo_id' => $repo_id,
-    'motivation' => '',
-    'status' => VERSIONCONTROL_ACCOUNT_STATUS_UNDEFINED,
-  );
+  //FIXME handle include_unauthorized
+  $result = $select->execute();
+  $accounts = array();
+  foreach ($result as $row) {
+    $accounts[$row->account_id] = $row;
+  }
+  return $accounts;
 }
 
 /**
@@ -151,14 +153,39 @@ function versioncontrol_account_status_get($uid, $repo_id) {
  *   of versioncontrol_account_status_get().
  */
 function versioncontrol_account_status_set($status_data) {
-  db_query('DELETE FROM {versioncontrol_account_status_users}
-            WHERE uid = %d AND repo_id = %d',
-            $status_data['uid'], $status_data['repo_id']);
-  db_query("INSERT INTO {versioncontrol_account_status_users}
-            (uid, repo_id, motivation, status)
-            VALUES (%d, %d, '%s', %d)",
-            $status_data['uid'], $status_data['repo_id'],
-            $status_data['motivation'], $status_data['status']);
+  if (!isset($status_data->data)) {
+    // Auto-approve the account if it was inserted programmatically and
+    // the caller doesn't know anything about this module.
+    $status_data->data = array(
+      'admin_message' => array('is_send' => FALSE, 'contents' => ''),
+      'send_application_mails' => FALSE,
+    );
+  }
+
+  if (!empty($status_data->account_id)) {
+    drupal_write_record('versioncontrol_account_status_users', $status_data, 'account_id');
+
+    if ($status_data->data['admin_message']['is_send']) {
+      $contents = $status_data->data['admin_message']['contents'];
+      _versioncontrol_account_status_send_status_update_mails($status_data, $contents);
+    }
+    if ($status_data->data['send_application_mails']) {
+      $is_reapplication = !empty($status_data->data['is_reapplication']);
+      _versioncontrol_account_status_send_application_mails($status_data, $is_reapplication);
+    }
+  }
+  else {
+    drupal_write_record('versioncontrol_account_status_users', $status_data);
+
+    if ($status_data->data['admin_message']['is_send']) {
+      $contents = $status_data->data['admin_message']['contents'];
+      _versioncontrol_account_status_send_status_update_mails($status_data, $contents);
+    }
+    if ($status_data->data['send_application_mails']) {
+      $is_reapplication = !empty($status_data->data['is_reapplication']);
+      _versioncontrol_account_status_send_application_mails($status_data, $is_reapplication);
+    }
+  }
 }
 
 /**
@@ -172,14 +199,12 @@ function versioncontrol_account_status_versioncontrol_is_account_authorized($rep
   if ($repository['authorization_method'] != 'versioncontrol_account_status_repository') {
     return TRUE;
   }
-  $result = db_query('SELECT status
-                      FROM {versioncontrol_account_status_users}
-                      WHERE uid = %d AND repo_id = %d',
-                      $uid, $repository['repo_id']);
 
-  while ($account = db_fetch_object($result)) {
+  $accounts = versioncontrol_account_status_get(array('uid' => $uid, 'repo_id' => $repository->repo_id));
+  foreach ($accounts as $account) {
     return ($account->status == VERSIONCONTROL_ACCOUNT_STATUS_APPROVED);
   }
+
   return FALSE;
 }
 
@@ -214,89 +239,6 @@ function versioncontrol_account_status_versioncontrol_alter_repository_selection
   }
 }
 
-
-/**
- * Implementation of hook_versioncontrol_alter_account_list():
- * Add additional columns into the list of VCS accounts.
- * By changing the @p $header and @p $rows_by_uid arguments,
- * the account list can be customized accordingly.
- *
- * @param $accounts
- *   The list of accounts that is being displayed in the account table. This is
- *   a structured array like the one returned by VersioncontrolAccountCache::getInstance()->getAccounts().
- * @param $repositories
- *   An array of repositories where the given users have a VCS account.
- *   Array keys are the repository ids, and array values are the
- *   repository arrays like returned from versioncontrol_get_repository().
- * @param $header
- *   A list of columns that will be passed to theme('table').
- * @param $rows_by_uid
- *   An array of existing table rows, with Drupal user ids as array keys.
- *   Each row already includes the generic column values, and for each row
- *   there is an account with the same uid given in the @p $accounts parameter.
- */
-function versioncontrol_account_status_versioncontrol_alter_account_list($accounts, $repositories, &$header, &$rows_by_uid) {
-  $accounts_column_index = 1;
-  $status_column_index = NULL;
-  $new_header = array();
-
-  // insert a new 'Account status' column after the 'Accounts' one
-  foreach ($header as $index => $column) {
-    if ($index == $accounts_column_index) {
-      $new_header[] = $column;
-      $new_header[] = t('Account status');
-    }
-    else {
-      $new_header[] = $column;
-    }
-  }
-  $header = $new_header;
-
-  // Same for the actual status field in each row.
-  foreach ($rows_by_uid as $uid => $row) {
-    $new_row = array();
-
-    foreach ($row as $index => $column) {
-      if ($index == $accounts_column_index) {
-        $new_row[] = $column;
-        $new_row[] = _versioncontrol_account_status_get_cell(
-          $uid, $accounts[$uid], $repositories
-        );
-      }
-      else {
-        $new_row[] = $column;
-      }
-    }
-    $rows_by_uid[$uid] = $new_row;
-  }
-}
-
-/**
- * The actual 'Status' cell for each row in the accounts list.
- */
-function _versioncontrol_account_status_get_cell($uid, $usernames_by_repository, $repositories) {
-  $status_options = _versioncontrol_account_status_get_status_options(TRUE);
-  $statuses = array();
-
-  foreach ($usernames_by_repository as $repo_id => $username) {
-    if ($repositories[$repo_id]['authorization_method'] == 'versioncontrol_account_status_repository') {
-      $status_data = versioncontrol_account_status_get($uid, $repo_id);
-      $statuses[] = t('@repository: !status', array(
-        '!status' => $status_options[$status_data['status']],
-        '@repository' => $repositories[$repo_id]['name'],
-      ));
-    }
-    else {
-      $statuses[] = t('@repository: !status', array(
-        '!status' => t('n/a'),
-        '@repository' => $repositories[$repo_id]['name'],
-      ));
-    }
-  }
-  return theme('item_list', $statuses);
-}
-
-
 /**
  * Implementation of hook_form_alter():
  * Change the form according to the user's account status.
@@ -314,90 +256,9 @@ function versioncontrol_account_status_form_alter(&$form, $form_state, $form_id)
         );
       }
       break;
-
-    case 'versioncontrol-account-filter-form':
-      versioncontrol_account_status_form_alter_account_filter($form);
-      break;
   }
 }
 
-
-/**
- * Implementation of hook_form_alter() for Version Control API's
- * account filtering form on the admin account list.
- */
-function versioncontrol_account_status_form_alter_account_filter(&$form) {
-  $options = array_merge(
-    array(VERSIONCONTROL_ACCOUNT_STATUS_ALL => t('All')),
-    _versioncontrol_account_status_get_status_options()
-  );
-
-  if (!isset($_SESSION['versioncontrol_account_status_filter'])) {
-    $_SESSION['versioncontrol_account_status_filter'] = VERSIONCONTROL_ACCOUNT_STATUS_QUEUED;
-  }
-
-  $form['submit']['#submit'][] = 'versioncontrol_account_status_account_filter_form_submit';
-
-  $form['versioncontrol_account_status'] = array(
-    '#type' => 'select',
-    '#title' => t('Status'),
-    '#options' => $options,
-    '#default_value' => $_SESSION['versioncontrol_account_status_filter'],
-    '#weight' => 0,
-  );
-}
-
-/**
- * Additional submit handler for the account filter form.
- */
-function versioncontrol_account_status_account_filter_form_submit($form, &$form_state) {
-  $_SESSION['versioncontrol_account_status_filter'] =
-    $form_state['values']['versioncontrol_account_status'];
-}
-
-/**
- * Implementation of hook_versioncontrol_filter_accounts():
- * Unset filtered accounts before they are even attempted to be displayed
- * on the account list.
- *
- * @param $accounts
- *   The accounts that would normally be displayed, in the same format as the
- *   return value of VersioncontrolAccountCache::getInstance()->getAccounts(). Entries in this list
- *   may be unset by this filter function.
- */
-function versioncontrol_account_status_versioncontrol_filter_accounts(&$accounts) {
-  if (empty($accounts)) {
-    return;
-  }
-  if (!isset($_SESSION['versioncontrol_account_status_filter'])) {
-    $_SESSION['versioncontrol_account_status_filter'] = 0;
-  }
-  $filter_status = $_SESSION['versioncontrol_account_status_filter'];
-
-  if ($filter_status == VERSIONCONTROL_ACCOUNT_STATUS_ALL) {
-    return; // Don't change the list if "All" statuses are selected.
-  }
-
-  $uid_constraints = array();
-  $params = array($filter_status);
-  foreach ($accounts as $uid => $usernames_by_repository) {
-    $uid_constraints[] = 'uid = %d';
-    $params[] = $uid;
-  }
-
-  // Retrieve all users with the given status.
-  $result = db_query('SELECT DISTINCT(uid) FROM {versioncontrol_account_status_users}
-                      WHERE status = %d
-                       AND ('. implode(' OR ', $uid_constraints) .')', $params);
-
-  $filtered_accounts = array();
-  while ($account = db_fetch_object($result)) {
-    $filtered_accounts[$account->uid] = $accounts[$account->uid];
-  }
-  $accounts = $filtered_accounts;
-}
-
-
 /**
  * Implementation of hook_form_alter() for Version Control API's
  * repository settings form.
@@ -410,9 +271,9 @@ function versioncontrol_account_status_form_alter_repository_settings(&$form) {
   $form['#versioncontrol_account_status'] = TRUE;
 
   // Get form and email messages (only the default ones for new repositories).
-  $strings = (empty($repository) || $repository['repo_id'] == 0)
+  $strings = (empty($repository) || $repository->repo_id == 0)
     ? _versioncontrol_account_status_get_presets()
-    : _versioncontrol_account_status_get_strings($repository['repo_id']);
+    : _versioncontrol_account_status_get_strings($repository->repo_id);
 
   // Save screen space as there are going to be more fieldsets in here.
   $form['account_registration']['repository_messages']['#collapsed'] = TRUE;
@@ -604,7 +465,19 @@ function versioncontrol_account_status_form_alter_account(&$form, $repo_id) {
   global $user;
 
   $uid = $form['#uid'];
-  $data = versioncontrol_account_status_get($uid, $repo_id);
+  $accounts = versioncontrol_account_status_get(array('uid' => $uid, 'repo_id' => $repo_id));
+  if (!empty($accounts)) {
+    //FIXME let UI support more than one account per repo
+    $data = reset($accounts);
+  }
+  else {
+    //FIXME this is not a good place for default data to be set
+    $data = new stdClass();
+    $data->status     = VERSIONCONTROL_ACCOUNT_STATUS_UNDEFINED;
+    $data->repo_id    = $repo_id;
+    $data->uid        = $uid;
+    $data->motivation = '';
+  }
 
   $admin_access = versioncontrol_admin_access();
   if ($admin_access) {
@@ -612,7 +485,7 @@ function versioncontrol_account_status_form_alter_account(&$form, $repo_id) {
     return;
   }
 
-  switch ($data['status']) {
+  switch ($data->status) {
     case VERSIONCONTROL_ACCOUNT_STATUS_QUEUED:
     case VERSIONCONTROL_ACCOUNT_STATUS_PENDING:
       versioncontrol_account_status_form_alter_pending($form, $data);
@@ -632,7 +505,7 @@ function versioncontrol_account_status_form_alter_account(&$form, $repo_id) {
       );
       $form['motivation_fieldset']['motivation_display'] = array(
         '#type' => 'item',
-        '#value' => check_markup($data['motivation']),
+        '#value' => check_markup($data->motivation),
       );
       break;
 
@@ -677,29 +550,25 @@ function versioncontrol_account_status_form_alter_account_edit(&$form, $status_d
     // drupal_goto() calls exit() so script execution ends right here
   }
 
-  if ($status_data['status'] == VERSIONCONTROL_ACCOUNT_STATUS_UNDEFINED) {
+  if ($status_data->status == VERSIONCONTROL_ACCOUNT_STATUS_UNDEFINED) {
     // The status will not stay undefined when submitting this form.
-    $status_data['status'] = VERSIONCONTROL_ACCOUNT_STATUS_QUEUED;
+    $status_data->status = VERSIONCONTROL_ACCOUNT_STATUS_QUEUED;
   }
 
-  // Remember a few values for later on.
-  $form['#versioncontrol_account_status_repo_id'] = $status_data['repo_id'];
-  $form['#versioncontrol_account_status_uid'] = $status_data['uid'];
-
   $is_reapplication = FALSE;
 
   $reapplication_statuses = array(
     VERSIONCONTROL_ACCOUNT_STATUS_DECLINED,
     VERSIONCONTROL_ACCOUNT_STATUS_DISABLED,
   );
-  if (!$admin_access && in_array($status_data['status'], $reapplication_statuses)) {
+  if (!$admin_access && in_array($status_data->status, $reapplication_statuses)) {
     $is_reapplication = TRUE;
     // let the user try again.
-    $status_data['status'] = VERSIONCONTROL_ACCOUNT_STATUS_QUEUED;
+    $status_data->status = VERSIONCONTROL_ACCOUNT_STATUS_QUEUED;
   }
-  $is_application = (empty($status_data['motivation']) || $is_reapplication);
+  $is_application = (empty($status_data->motivation) || $is_reapplication);
 
-  $strings = _versioncontrol_account_status_get_strings($status_data['repo_id']);
+  $strings = _versioncontrol_account_status_get_strings($status_data->repo_id);
 
   // Users with declined or disabled accounts can reapply.
   if ($is_reapplication) {
@@ -722,7 +591,7 @@ function versioncontrol_account_status_form_alter_account_edit(&$form, $status_d
     $form['#send_application_mails'] = TRUE;
 
     if (!isset($form['overview'])) {
-      $repository = versioncontrol_repository_load($status_data['repo_id']);
+      $repository = versioncontrol_repository_load($status_data->repo_id);
       $registration_message = isset($repository['data']['versioncontrol']['registration_message'])
         ? $repository['data']['versioncontrol']['registration_message']
         : '';
@@ -751,7 +620,7 @@ function versioncontrol_account_status_form_alter_account_edit(&$form, $status_d
     $form['motivation_fieldset']['motivation'] = array(
       '#type' => 'textarea',
       '#title' => t('Motivation'),
-      '#default_value' => $status_data['motivation'],
+      '#default_value' => $status_data->motivation,
       '#cols' => 60,
       '#rows' => 9,
       '#description' => $strings['motivation_description'],
@@ -762,12 +631,12 @@ function versioncontrol_account_status_form_alter_account_edit(&$form, $status_d
     $form['#skip_conditions_check'] = TRUE;
     $form['motivation_fieldset']['motivation'] = array(
       '#type' => 'value',
-      '#value' => $status_data['motivation'],
+      '#value' => $status_data->motivation,
     );
     $form['motivation_fieldset']['motivation_display'] = array(
       '#type' => 'item',
       '#title' => t('Motivation message'),
-      '#value' => check_markup($status_data['motivation']),
+      '#value' => check_markup($status_data->motivation),
     );
   }
 
@@ -779,7 +648,7 @@ function versioncontrol_account_status_form_alter_account_edit(&$form, $status_d
   else {
     $form['status'] = array(
       '#type' => 'value',
-      '#value' => $status_data['status'],
+      '#value' => $status_data->status,
     );
   }
 
@@ -832,7 +701,7 @@ function _versioncontrol_account_status_form_alter_status_admin(&$form, $status_
   $form['status_admin']['status'] = array(
     '#type' => 'radios',
     '#title' => t('Account status'),
-    '#default_value' => $status_data['status'],
+    '#default_value' => $status_data->status,
     '#options' => _versioncontrol_account_status_get_status_options(),
     '#description' => t('You can change the status of the user\'s VCS account.'),
   );
@@ -856,7 +725,7 @@ function _versioncontrol_account_status_form_alter_status_admin(&$form, $status_
  */
 function versioncontrol_account_status_application_validate($form, &$form_state) {
   $strings = _versioncontrol_account_status_get_strings(
-    $form['#versioncontrol_account_status_repo_id']
+    $form['#repository']->repo_id
   );
   $conditions = _versioncontrol_account_status_get_conditions(
     $strings['default_condition_description'], $strings['default_condition_error']
@@ -870,125 +739,6 @@ function versioncontrol_account_status_application_validate($form, &$form_state)
   }
 }
 
-
-/**
- * Implementation of hook_versioncontrol_account_submit():
- * Extract account status data from the account edit/register form's submitted
- * values, and add it to the @p $additional_data array. Later, that array
- * will be passed to hook_versioncontrol_account() as part of the account
- * insert/update procedure.
- */
-function versioncontrol_account_status_versioncontrol_account_submit(&$additional_data, $form, $form_state) {
-  // If the form wasn't altered at all, let it be.
-  if (!isset($form['#versioncontrol_account_status_uid'])) {
-    return;
-  }
-
-  $applicant_uid = $form['#versioncontrol_account_status_uid'];
-  $repo_id = $form['#versioncontrol_account_status_repo_id'];
-  $status_data = versioncontrol_account_status_get($applicant_uid, $repo_id);
-
-  if (isset($form_state['values']['send_admin_message'])) { // if status administration was on the form
-    if ($status_data['status'] == $form_state['values']['status']
-        && $status_data['status'] == VERSIONCONTROL_ACCOUNT_STATUS_QUEUED) {
-      // The QUEUED status should only indicate the initial status of an
-      // application. Once it has been replied to, it should be set to PENDING.
-      // In case the administrator forgets to do this, do it automatically.
-      $form_state['values']['status'] = VERSIONCONTROL_ACCOUNT_STATUS_PENDING;
-    }
-  }
-  $status_data['motivation'] = $form_state['values']['motivation'];
-  $status_data['status'] = $form_state['values']['status'];
-
-  $additional_data['versioncontrol_account_status'] = array(
-    'status_data' => $status_data,
-    'admin_message' => array(
-      'is_send' => isset($form_state['values']['send_admin_message'])
-        ? $form_state['values']['send_admin_message']
-        : FALSE,
-      'contents' => isset($form_state['values']['admin_message'])
-        ? $form_state['values']['admin_message']
-        : '',
-    ),
-    'is_reapplication' => !empty($form['#is_reapplication']),
-    'send_application_mails' => isset($form['#send_application_mails'])
-      ? $form['#send_application_mails']
-      : FALSE,
-  );
-}
-
-/**
- * Implementation of hook_versioncontrol_entity_account_insert().
- */
-function versioncontrol_account_status_versioncontrol_entity_account_insert($vcs_account) {
-  // Recap: if form_alter() wasn't applied, our array element is not set.
-  $additional_data = isset($vcs_account->additional_data['versioncontrol_account_status'])
-    ? $vcs_account->additional_data['versioncontrol_account_status']
-    : NULL;
-
-  if (!isset($additional_data)) {
-    // Auto-approve the account if it was inserted programmatically and
-    // the caller doesn't know anything about this module.
-    $additional_data = array(
-      'status_data' => array(
-        'uid' => $vcs_account->committer_uid,
-        'repo_id' => $vcs_account->repo_id,
-        'motivation' => 'Inserted programmatically.',
-        'status' => VERSIONCONTROL_ACCOUNT_STATUS_APPROVED,
-      ),
-      'admin_message' => array('is_send' => FALSE, 'contents' => ''),
-      'send_application_mails' => FALSE,
-    );
-  }
-
-  $status_data = $additional_data['status_data'];
-  versioncontrol_account_status_set($status_data);
-
-  if ($additional_data['admin_message']['is_send']) {
-    $contents = $additional_data['admin_message']['contents'];
-    _versioncontrol_account_status_send_status_update_mails($status_data, $contents);
-  }
-  if ($additional_data['send_application_mails']) {
-    $is_reapplication = !empty($additional_data['is_reapplication']);
-    _versioncontrol_account_status_send_application_mails($status_data, $is_reapplication);
-  }
-}
-
-/**
- * Implementation of hook_versioncontrol_entity_account_update().
- */
-function versioncontrol_account_status_versioncontrol_entity_account_update($vcs_account) {
-  // Recap: if form_alter() wasn't applied, our array element is not set.
-  $additional_data = isset($vcs_account->additional_data['versioncontrol_account_status'])
-    ? $vcs_account->additional_data['versioncontrol_account_status']
-    : NULL;
-
-  if (!isset($additional_data)) {
-    // Don't change the status for programmatical updates, though.
-    return;
-  }
-
-  $status_data = $additional_data['status_data'];
-  versioncontrol_account_status_set($status_data);
-
-  if ($additional_data['admin_message']['is_send']) {
-    $contents = $additional_data['admin_message']['contents'];
-    _versioncontrol_account_status_send_status_update_mails($status_data, $contents);
-  }
-  if ($additional_data['send_application_mails']) {
-    $is_reapplication = !empty($additional_data['is_reapplication']);
-    _versioncontrol_account_status_send_application_mails($status_data, $is_reapplication);
-  }
-}
-
-/**
- * Implementation of hook_versioncontrol_entity_account_delete().
- */
-function versioncontrol_account_status_versioncontrol_entity_account_delete($vcs_account) {
-  db_query('DELETE FROM {versioncontrol_account_status_users}
-    WHERE uid = %d', $vcs_account->uid);
-}
-
 /**
  * Send out notification mails in response to an application submission.
  */
@@ -998,13 +748,13 @@ function _versioncontrol_account_status_send_application_mails($status_data, $is
     return;
   }
   $admin_mail = variable_get('versioncontrol_email_address', 'versioncontrol@example.com');
-  $applicant = user_load($status_data['uid']);
+  $applicant = user_load($status_data->uid);
 
   $params = array(
     'applicant_user' => $applicant,
-    'repository' => versioncontrol_repository_load($status_data['repo_id']),
-    'motivation_message' => $status_data['motivation'],
-    'status' => $status_data['status'],
+    'repository' => versioncontrol_repository_load($status_data->repo_id),
+    'motivation_message' => $status_data->motivation,
+    'status' => $status_data->status,
     'is_reapplication' => $is_reapplication,
   );
 
@@ -1034,15 +784,15 @@ function _versioncontrol_account_status_send_application_mails($status_data, $is
 function _versioncontrol_account_status_send_status_update_mails($status_data, $admin_message) {
   global $user; // = the admin who submitted the update form
   $admin_mail = variable_get('versioncontrol_email_address', 'versioncontrol@example.com');
-  $applicant = user_load($status_data['uid']);
+  $applicant = user_load($status_data->uid);
 
   $params = array(
     'admin_user' => drupal_clone($user),
     'applicant_user' => $applicant,
-    'repository' => versioncontrol_repository_load($status_data['repo_id']),
+    'repository' => versioncontrol_repository_load($status_data->repo_id),
     'admin_message' => $admin_message,
-    'status' => $status_data['status'],
-    'motivation_message' => $status_data['motivation'],
+    'status' => $status_data->status,
+    'motivation_message' => $status_data->motivation,
   );
 
   // Send an e-mail to the user whose account status has been updated.
@@ -1301,3 +1051,741 @@ Motivation message:
 
   return $presets;
 }
+
+/**
+ * Implementation of hook_user():
+ */
+function versioncontrol_account_status_user($type, &$edit, &$user, $category = NULL) {
+  switch ($type) {
+    // Register additional user account edit tabs,
+    case 'categories':
+      $categories = array();
+      $categories[] = array(
+        'name' => 'versioncontrol',
+        // user_menu() pipes 'title' though check_plain() already.
+        'title' => t('Repository accounts'),
+        'weight' => 99,
+      );
+      return $categories;
+
+    // Delete VCS accounts when the associated user account is deleted.
+    case 'delete':
+      db_delete('versioncontrol_account_status_users')
+        ->condition('uid', $this->uid)
+        ->execute();
+      break;
+  }
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function versioncontrol_account_status_menu() {
+  $items = array();
+  $items['admin/content/versioncontrol-accounts'] = array(
+    'title' => 'VCS accounts',
+    'description' => 'Manage associations of Drupal users to VCS user accounts.',
+    'page callback' => 'versioncontrol_account_status_list_accounts',
+    'access arguments' => array('administer version control systems'),
+    'type' => MENU_NORMAL_ITEM,
+  );
+  $items['versioncontrol/register'] = array(
+    'title' => 'Get commit access',
+    'page callback' => 'versioncontrol_account_status_register_page',
+    'access callback' => TRUE, // access checking is done in the page callback
+    'type' => MENU_SUGGESTED_ITEM,
+  );
+  // Account registration and editing pages for the regular user.
+  $items['user/%versioncontrol_user_accounts/edit/versioncontrol'] = array(
+    // Load with $include_unauthorized == TRUE, so that the user can inspect
+    // his/her VCS accounts even if they are not approved by the admin yet.
+    'load arguments' => array(TRUE),
+    'title callback' => 'versioncontrol_user_accounts_title_callback',
+    'title arguments' => array(1),
+    'page callback' => 'versioncontrol_account_status_page',
+    'page arguments' => array(1),
+    'access callback' => 'versioncontrol_private_account_access',
+    'access arguments' => array(1),
+    'weight' => 99,
+    'type' => MENU_LOCAL_TASK,
+  );
+  // Autocomplete callback for Drupal usernames that have access to
+  // the repo_id given in arg(3). (No need to fetch the full repository,
+  // as the callback uses a raw & safe database query anyways.)
+  $items['versioncontrol/user/autocomplete'] = array(
+    'title' => 'Version control user autocomplete',
+    'page callback' => 'versioncontrol_user_autocomplete',
+    'access callback' => 'versioncontrol_user_access',
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
+/**
+ * Menu wildcard loader for '%versioncontrol_user_accounts':
+ * Load and return all VCS accounts of a given user.
+ *
+ * @param $uid
+ *   Drupal user id of the user whose VCS accounts should be loaded.
+ * @param $include_unauthorized
+ *   Will be passed on to VersioncontrolAccountCache::getInstance()->getAccounts(), see the
+ *   API documentation of that function.
+ */
+function versioncontrol_user_accounts_load($uid, $include_unauthorized = FALSE) {
+  return versioncontrol_account_status_get(array('uid' => $uid), $include_unauthorized);
+}
+
+/**
+ * Menu callback for 'admin/content/versioncontrol-accounts'.
+ */
+function versioncontrol_account_status_list_accounts() {
+  $view = views_get_view('versioncontrol_account_status_acccounts');
+  $view->override_path = 'admin/content/versioncontrol-accounts';
+  return $view->preview();
+}
+
+/**
+ * Form callback for "versioncontrol/register[/$register_uid[/$register_at_repo_id]]":
+ * Provide an indirection that leads to an account registration form.
+ */
+function versioncontrol_account_status_register_page($register_uid = FALSE, $register_at_repo_id = FALSE) {
+  global $user;
+
+  if ($user->uid == 0 || !versioncontrol_user_access()) {
+    $presets = _versioncontrol_get_string_presets();
+
+    return variable_get(
+      'versioncontrol_registration_message_unauthorized',
+      $presets['versioncontrol_registration_message_unauthorized']
+    );
+  }
+
+  $register_uid = is_numeric($register_uid) ? $register_uid : $user->uid;
+
+  $admin_access = versioncontrol_admin_access();
+
+  if (!$admin_access && $register_uid != $user->uid) {
+    drupal_access_denied();
+    return;
+  }
+
+  $accounts = versioncontrol_user_accounts_load($register_uid, TRUE);
+  $repositories = versioncontrol_repository_load_multiple(FALSE);
+
+  // Construct the '#options' array.
+  $account_usernames = array();
+  foreach ($accounts as $account) {
+    $account_usernames[$account->repo_id][] = $account->vcs_username;
+  }
+
+  $repository_names = array();
+  foreach ($repositories as $repo_id => $repository) {
+    if (isset($account_usernames[$repo_id])
+        && $repository->isAccountAuthorized($register_uid)) {
+      // We only want repositories in the list of repositories that are open
+      // for registrations where no (authorized) account exists yet.
+      continue;
+    }
+    if (!isset($first_repo_id)) {
+      $first_repo_id = $repo_id;
+    }
+    $repository_names[$repo_id] = check_plain($repository['name']);
+  }
+
+  // Filter (and possibly change the caption of) the list of repositories to
+  // select. The admin has all the permissions and gets the uncensored list.
+  if (!$admin_access) {
+    foreach (module_implements('versioncontrol_alter_repository_selection') as $module) {
+      $function = $module .'_versioncontrol_alter_repository_selection';
+      $function($repository_names, $repositories);
+    }
+  }
+
+  // If there's just one repository on the site, redirect directly to this one.
+  if (count($repository_names) == 1) {
+    $only_repo_id = $first_repo_id;
+  }
+  elseif (count($repositories) == 1) {
+    $only_repo_id = reset(array_keys($repositories));
+  }
+
+  if (is_numeric($register_at_repo_id) || isset($only_repo_id)) {
+    // If there is only one repository left to register, it doesn't matter
+    // whether or not the URL contains a repository (and which one), we always
+    // redirect to the remaining possible one. Otherwise, we try to register
+    // at the given repository.
+    $repo_id = isset($only_repo_id) ? $only_repo_id : $register_at_repo_id;
+
+    if (isset($account_usernames[$repo_id])) {
+      drupal_set_message(t('You already have a registered account.'));
+      drupal_goto('user/'. $user->uid .'/edit/versioncontrol/'. $repo_id
+                  .'/'. reset($account_usernames[$repo_id]));
+      // drupal_goto() calls exit() so script execution ends right here
+    }
+    elseif (isset($repository_names[$repo_id])) {
+      return drupal_get_form('versioncontrol_account_status_edit_form',
+        $register_uid, $repositories[$repo_id], VERSIONCONTROL_FORM_CREATE
+      );
+    }
+  }
+
+  if (!isset($first_repo_id)) {
+    // when there are no repos, this var is not set
+    $first_repo_id = NULL;
+  }
+
+  return drupal_get_form('versioncontrol_account_status_register_form',
+    $register_uid, $repository_names, $first_repo_id
+  );
+}
+
+/**
+ * Add or update the user account when the edit/register form is submitted.
+ */
+function versioncontrol_account_status_edit_form_submit($form, &$form_state) {
+  // Reconstruct the user data from the $form_state that was passed.
+  $uid = $form['#uid'];
+  $vcs_username = $form_state['values']['account_name'];
+  $repository = $form['#repository'];
+  $vcs_name = $form['#vcs_name'];
+
+  $accounts = versioncontrol_account_status_get(array('uid' => $uid, 'repo_id' => $repository->repo_id));
+  if (!empty($accounts)) {
+    //FIXME let UI support more than one account per repo per user
+    $status_data = reset($accounts);
+  }
+  else {
+    $status_data = new stdClass();
+    $status_data->status     = VERSIONCONTROL_ACCOUNT_STATUS_UNDEFINED;
+    $status_data->repo_id    = $repository->repo_id;
+    $status_data->uid        = $uid;
+    $status_data->motivation = '';
+  }
+
+  if (isset($form_state['values']['send_admin_message'])) { // if status administration was on the form
+    if ($status_data->status == $form_state['values']['status']
+        && $status_data->status == VERSIONCONTROL_ACCOUNT_STATUS_QUEUED) {
+      // The QUEUED status should only indicate the initial status of an
+      // application. Once it has been replied to, it should be set to PENDING.
+      // In case the administrator forgets to do this, do it automatically.
+      $form_state['values']['status'] = VERSIONCONTROL_ACCOUNT_STATUS_PENDING;
+    }
+  }
+
+  // Let other modules provide additional account data.
+  $data = array(
+    'admin_message' => array(
+      'is_send' => isset($form_state['values']['send_admin_message'])
+        ? $form_state['values']['send_admin_message']
+        : FALSE,
+      'contents' => isset($form_state['values']['admin_message'])
+        ? $form_state['values']['admin_message']
+        : '',
+    ),
+    'is_reapplication' => !empty($form['#is_reapplication']),
+    'send_application_mails' => isset($form['#send_application_mails'])
+      ? $form['#send_application_mails']
+      : FALSE,
+  );
+
+  if (empty($form['#original_username'])) {
+    $vcs_account = new stdClass();
+    $vcs_account->vcs_username = $vcs_username;
+    $vcs_account->uid = $uid;
+    $vcs_account->repo_id = $repository->repo_id;
+    $vcs_account->motivation = $form_state['values']['motivation'];
+    $vcs_account->status = $form_state['values']['status'];
+    $vcs_account->data = $data;
+    versioncontrol_account_status_set($vcs_account);
+    $message = drupal_set_message(t(
+      'The @vcs account %vcs_username has been registered.',
+      array('@vcs' => $vcs_name, '%vcs_username' => $vcs_username)
+    ));
+  }
+  else {
+    //FIXME why username are a required constraint? <-- shouldn't be anymore
+    //      uid and repo_id are the PK on the table getAccounts query
+    //FIXME use account_id PK to search?
+    $conditions = array(
+      'repo_id' => array($repository->repo_id),
+      'uid' => $uid,
+      'vcs_username' => array($form['#original_username'])
+    );
+    $vcs_accounts = versioncontrol_account_status_get($conditions, TRUE);
+    // if we got an original_username we can trust on getting a value
+    $vcs_account = array_shift($vcs_accounts);
+    $vcs_account->vcs_username = $vcs_username;
+    $vcs_account->data = $data;
+
+    // optional fields since they do not appear at 'user/uid/edit/versioncontrol/<repo_id>/<vcs_username>' form
+    foreach (array('status', 'motivation') as $op_field) {
+      if (isset($form_state['values'][$op_field])) {
+        $vcs_account->$op_field = $form_state['values'][$op_field];
+      }
+    }
+
+    versioncontrol_account_status_set($vcs_account);
+
+    // Regular users cannot change the username, and will probably get
+    // a message for each of the other actions that hook into the form.
+    if (versioncontrol_admin_access()) {
+      $message = drupal_set_message(t(
+        'The @vcs account %username has been updated successfully.',
+        array('@vcs' => $vcs_name, '%username' => $vcs_username)
+      ));
+    }
+  }
+
+  $form_state['redirect'] = versioncontrol_admin_access()
+    ? 'admin/content/versioncontrol-accounts'
+    : 'user/'. $uid .'/edit/versioncontrol/'. $repository->repo_id
+        .'/'. drupal_urlencode($vcs_username);
+}
+
+/**
+ * Form callback for 'user/%versioncontrol_user_accounts/edit/versioncontrol':
+ * Display a list of the given user's VCS accounts, or directly return the form
+ * array from versioncontrol_account_edit_form() if only a single account
+ * exists for that user (or if the account has been given in the URL).
+ */
+function versioncontrol_account_status_page($vcs_accounts, $url_repo_id = NULL, $url_username = NULL) {
+  $selected_usernames = array();
+
+  foreach ($vcs_accounts as $key => $vcs_account) {
+    // The caller (menu system) ensures that there is only one uid.
+    $uid = $vcs_account->uid;
+    if (isset($url_repo_id) && $vcs_account->repo_id != $url_repo_id) {
+      unset($vcs_accounts[$key]);
+      continue; // disregard repositories that don't match the URL constraints
+    }
+    if (isset($url_username) && $vcs_account->vcs_username != $url_username) {
+      unset($vcs_accounts[$key]);
+      continue; // disregard usernames that don't match the URL constraints
+    }
+    $any_repo_id = $vcs_account->repo_id;
+    $selected_usernames[] = $vcs_account->vcs_username;
+  }
+
+  if (empty($selected_usernames)) {
+    drupal_not_found();
+    return;
+  }
+  elseif (count($selected_usernames) == 1) {
+    $repository = versioncontrol_repository_load($any_repo_id);
+    return drupal_get_form('versioncontrol_account_status_edit_form',
+      $uid, $repository, reset($selected_usernames)
+    );
+  }
+  else {
+    return drupal_get_form('versioncontrol_account_status_list_form', $vcs_accounts);
+  }
+}
+
+/**
+ * Form callback for "admin/content/versioncontrol-accounts" and
+ * (in certain cases) "user/%versioncontrol_user_accounts/edit/versioncontrol":
+ * Show a list of VCS accounts to the admin or the user.
+ *
+ * @param $accounts
+ *   The list of accounts to show, in versioncontrol_user_account_load_multiple format.
+ */
+function versioncontrol_account_status_list_form(&$form_state, $accounts) {
+  $form = array();
+  $form['#id'] = 'versioncontrol-account-list-form';
+
+  $repo_ids = array();
+  foreach ($accounts as $account) {
+    $repo_ids[$account->repo_id] = TRUE;
+  }
+  $repositories = versioncontrol_repository_load_multiple(array_keys($repo_ids));
+
+  $header = array(t('Repository'), t('Username'), '');
+  $rows = array();
+
+  foreach ($accounts as $account) {
+    if (!isset($repositories[$account->repo_id])) { // happens if the backend isn't loaded
+      continue;
+    }
+    $formatted_username = theme('versioncontrol_account_username',
+      $account->uid, $account->vcs_username, $repositories[$account->repo_id],
+      array('prefer_drupal_username' => FALSE)
+    );
+    $repo_name = module_exists('commitlog')
+      ? l($repositories[$account->repo_id]->name, 'commitlog', array('query' => 'repos='. $account->repo_id))
+      : check_plain($repositories[$account->repo_id]->name);
+
+    $rows[] = array(
+      $repo_name,
+      $formatted_username,
+      l(t('Edit @vcs account', array('@vcs' => $repositories[$account->repo_id]->getBackend()->name)),
+      'user/'. $account->uid .'/edit/versioncontrol/'. $account->repo_id .'/'. drupal_urlencode($account->vcs_username)
+    ),
+  );
+  }
+
+  $form['accounts'] = array(
+    '#type' => 'markup',
+    '#value' => theme('table', $header, $rows, array('style' => 'width: 50%;')),
+  );
+  return $form;
+}
+
+/**
+ * Title callback for the "user/%versioncontrol_user_accounts/edit/versioncontrol" tab.
+ */
+function versioncontrol_user_accounts_title_callback($accounts) {
+  $repo_ids = array();
+  foreach ($accounts as $account) {
+    $repo_ids[] = $account->repo_id;
+  }
+  $repositories = versioncontrol_repository_load_multiple($repo_ids);
+  $vcses = array();
+  foreach ($repositories as $repository) {
+    $vcses[$repository['vcs']] = TRUE;
+  }
+  if (count($vcses) == 1) {
+    $repo = array_shift($repositories);
+    return check_plain($repo->getBackend()->name);
+  }
+  return t('Repository accounts');
+}
+
+/**
+ * Custom access callback, determining if the current user (or the one given
+ * in @p $account, if set) is permitted to view version control account
+ * settings of the user specified the first user id in @p $vcs_accounts.
+ * (We take that parameter because it's what the '%versioncontrol_user_accounts'
+ * wildcard returns.)
+ */
+function versioncontrol_private_account_access($vcs_accounts, $account = NULL) {
+  if (is_null($account)) {
+    global $user;
+    $account = clone $user;
+  }
+  if (user_access('administer version control systems', $account)) {
+    return TRUE;
+  }
+  if (!user_access('use version control systems', $account)) {
+    return FALSE;
+  }
+  foreach ($vcs_accounts as $vcs_account) {
+    if ($vcs_account->uid != $account->uid) {
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+/**
+ * Form callback for (in certain cases) "versioncontrol/register"
+ * and "user/%versioncontrol_user_accounts/edit/versioncontrol":
+ * Provide a form to register or edit a VCS account.
+ *
+ * @param $uid
+ *   The uid of the Drupal user whose account is being edited or registered.
+ * @param $repository
+ *   The repository of the added/edited account.
+ * @param $vcs_username
+ *   The user's VCS-specific username for the repository,
+ *   or VERSIONCONTROL_FORM_CREATE if a new VCS account should be registered.
+ */
+function versioncontrol_account_status_edit_form(&$form_state, $uid, $repository, $vcs_username) {
+  $form = array();
+  $create_account = ($vcs_username === VERSIONCONTROL_FORM_CREATE);
+  $vcs_name = $repository->getBackend()->name;
+
+  $user = user_load($uid);
+
+  if (!$user) {
+    drupal_not_found(); // cannot edit/register accounts for non-existing users
+    return array();
+  }
+
+  // Set an appropriate page title.
+  if ($create_account) {
+    drupal_set_title(t(
+      'Create user account in @repository',
+      array('@repository' => $repository->name)
+    ));
+  }
+  elseif ($user) {
+    drupal_set_title(check_plain($user->name));
+  }
+
+  $form['#id'] = 'versioncontrol-account-form';
+
+  $form['#repository'] = $repository;
+  $form['#vcs'] = $repository['vcs'];
+  $form['#vcs_name'] = $vcs_name;
+  $form['#uid'] = $uid;
+  $form['#original_username'] = $vcs_username;
+
+  $form['#validate'] = array('versioncontrol_account_status_edit_form_validate');
+  $form['#submit'] = array('versioncontrol_account_status_edit_form_submit');
+
+  if ($create_account) {
+    $registration_message = isset($repository->data['versioncontrol']['registration_message'])
+      ? $repository->data['versioncontrol']['registration_message']
+      : '';
+
+    if (!empty($registration_message)) {
+      $form['overview'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Overview'),
+        '#weight' => -100,
+      );
+      $form['overview']['overview'] = array(
+        '#type' => 'markup',
+        '#value' => $registration_message,
+      );
+    }
+  }
+
+  $form['account'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('@vcs account settings', array('@vcs' => $vcs_name)),
+    '#weight' => 0,
+  );
+
+  $admin_access = versioncontrol_admin_access();
+
+  if ($create_account || $admin_access) {
+    if ($create_account) {
+      $vcs_account = new stdClass();
+      $vcs_account->vcs_username = $vcs_username;
+      $vcs_account->uid = $uid;
+      $vcs_account->repo_id = $repository->repo_id;
+      // Have a nice default value for the new VCS username.
+      $vcs_username = $repository->getBackend()->usernameSuggestion($user);
+    }
+
+    if ($admin_access) { // the admin version
+      $description = t('The @vcs username associated with the account of !user. This field is used to link commit messages to user accounts.', array('@vcs' => $vcs_name, '!user' => theme_username($user)));
+    }
+    else { // the account creation version
+      $description = t('Choose a username to access the @vcs repository with. @vcs usernames should be lowercase. Spaces or other special characters are not allowed.', array('@vcs' => $vcs_name));
+    }
+
+    $form['account']['account_name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('@vcs username', array('@vcs' => $vcs_name)),
+      '#description' => $description,
+      '#default_value' => $vcs_username,
+      '#weight' => 0,
+      '#size' => 30,
+      '#maxlength' => 64,
+    );
+  }
+  else {
+    $form['account_name'] = array(
+      '#type' => 'value',
+      '#value' => $vcs_username,
+    );
+    $form['account']['account_name_display'] = array(
+      '#type' => 'item',
+      '#title' => t('@vcs username', array('@vcs' => $vcs_name)),
+      '#description' => t('Your @vcs username. This field can only be edited by administrators and is used to link your @vcs messages to your user account.', array('@vcs' => $vcs_name)),
+      '#value' => $vcs_username,
+      '#weight' => 0,
+    );
+  }
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => $create_account
+    ? t('Create @vcs account', array('@vcs' => $vcs_name))
+    : t('Update @vcs account', array('@vcs' => $vcs_name)),
+      '#weight' => 100,
+  );
+  return $form;
+}
+
+/**
+ * Validate the edit/register user account form submission before it is submitted.
+ */
+function versioncontrol_account_status_edit_form_validate($form, &$form_state) {
+  if (!isset($form_state['values']['account_name'])) {
+    return;
+  }
+  $uid = $form['#uid'];
+  $vcs_username = trim($form_state['values']['account_name']);
+  $repository = $form['#repository'];
+  $vcs_name = $form['#vcs_name'];
+
+  if (!isset($repository)) { // admin deletes repo while user fills in form
+    form_set_error('account',
+      t('The repository has been deleted.')
+    );
+    return;
+  }
+
+  if (empty($vcs_username)) {
+    form_set_error('account_name',
+      t('The @vcs username may not be empty.', array('@vcs' => $vcs_name))
+    );
+  }
+  else {
+    // Check for username validity - done by the backend, but with a fallback
+    // for alphanum-only characters.
+    $vcs_account = new stdClass();
+    $vcs_account->vcs_username = $vcs_username;
+    $vcs_account->uid = $uid;
+    $vcs_account->repo_id = $repository->repo_id;
+    if (!$repository->getBackend()->isUsernameValid($vcs_username)) {
+      form_set_error('account_name',
+        t('The specified @vcs username is invalid.', array('@vcs' => $vcs_name))
+      );
+    }
+    // The username is passed by reference and might have changed. That's a bit
+    // uncomfortable as a caller API, but more convenient for the backends.
+    // (Plus it makes sense anyways since we have trimmed the username too.)
+    $form_state['values']['account_name'] = $vcs_username;
+
+    // Check for duplicates.
+    $accounts_in_db = versioncontrol_account_status_get(array('vcs_username' => $vcs_username, 'repo_id' => $repository->repo_id), TRUE);
+    if (count($accounts_in_db) == 1) {
+      $account_in_db = reset($accounts_in_db);
+      $existing_uid = $account_in_db->uid;
+    }
+    elseif (count($accounts_in_db) == 0) {
+      $existing_uid = NULL;
+    }
+    else { // fail
+      form_set_error('account_name',
+        t('The specified @vcs username is already in use by more than one user.',
+          array('@vcs' => $vcs_name))
+        );
+      return;
+    }
+    if ($existing_uid && $uid != $existing_uid) {
+      if ($existing_user = user_load(array('uid' => $existing_uid))) {
+        $existing_username = theme('username', $existing_user);
+      }
+      else {
+        $existing_username = t('user #!id', array('!id' => $existing_uid));
+      }
+      form_set_error('account_name',
+        t('The specified @vcs username is already in use by !existing-user.',
+          array('@vcs' => $vcs_name, '!existing-user' => $existing_username))
+      );
+    }
+  }
+}
+
+/**
+ * The actual form for "versioncontrol/register[/$register_uid]".
+ */
+function versioncontrol_account_status_register_form(&$form_state, $register_uid, $repository_names, $first_repo_id) {
+  $form = array();
+
+  if (empty($repository_names)) {
+    drupal_set_title(t('No more registrations possible'));
+    $form['no_registration'] = array(
+      '#type' => 'markup',
+      '#value' => t('You already have an account for all the repositories where you can register. Go to your !user-account-page to configure repository account settings.',
+        array('!user-account-page' => l(t('user account page'), 'user/'. $register_uid .'/edit/versioncontrol'))
+      ),
+      '#prefix' => '<p>',
+      '#suffix' => '</p>',
+    );
+    return $form;
+  }
+
+  $form['#id'] = 'vcs-account-status-indirection-form';
+
+  $message = variable_get('versioncontrol_registration_message_authorized', FALSE);
+  if ($message == FALSE) {
+    $presets = _versioncontrol_get_string_presets();
+    $message = $presets['versioncontrol_registration_message_authorized'];
+  }
+  if (!empty($message)) {
+    $form['overview'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Overview'),
+      '#weight' => -100,
+    );
+    $form['overview']['overview'] = array(
+      '#type' => 'markup',
+      '#value' => $message,
+    );
+  }
+
+  $form['#uid'] = $register_uid;
+
+  $form['repository'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Select repository'),
+    '#weight' => 10,
+  );
+  $form['repository']['repo_id'] = array(
+    '#type' => 'select',
+    '#title' => t('Create user account in'),
+    '#options' => $repository_names,
+    '#default_value' => $first_repo_id,
+  );
+  $form['repository']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Create account'),
+    '#weight' => 100,
+  );
+
+  return $form;
+}
+
+/**
+ * Submit handler for the indirection form.
+ * Surprisingly, all it does is redirect to the appropriate registration form.
+ */
+function versioncontrol_account_status_register_form_submit($form, &$form_state) {
+  $form_state['redirect'] = 'versioncontrol/register/'. $form['#uid'] .'/'. $form_state['values']['repo_id'];
+}
+
+/**
+ * Returns a string of suggestions for Drupal usernames with accounts for
+ * the given repository, formatted to be suitable for use with
+ * JS autocomplete fields.
+ */
+function versioncontrol_user_autocomplete($repo_id, $string = '') {
+  if (!is_numeric($repo_id) || empty($string)) {
+    drupal_json(array());
+    return;
+  }
+  $matches = array();
+  $result = db_query_range("SELECT u.uid, u.name
+                            FROM {users} u
+                             INNER JOIN {versioncontrol_account_status_users} a
+                              ON u.uid = a.uid
+                            WHERE repo_id = %d
+                             AND LOWER(u.name) LIKE LOWER('%s%%')",
+                            $repo_id, $string, 0, 10);
+
+  while ($user = db_fetch_object($result)) {
+    if (!isset($repository)) {
+      $repository = versioncontrol_repository_load($repo_id);
+    }
+    if ($repository->isAccountAuthorized($user->uid)) {
+      $matches[$user->name] = check_plain($user->name);
+    }
+  }
+  drupal_json($matches);
+}
+
+/**
+ * Implementation of hook_views_api().
+ */
+function versioncontrol_account_status_views_api() {
+  return array(
+    'api' => 2,
+    'path' => drupal_get_path('module', 'versioncontrol_account_status'). '/includes',
+  );
+}
+
+/**
+ * Implementation of ctools hook_ctools_plugin_directory().
+ */
+function versioncontrol_account_status_ctools_plugin_directory($module, $plugin) {
+  if ($module == 'versioncontrol') {
+    return "includes/versioncontrol_plugins/$plugin";
+  }
+}
diff --git versioncontrol_fakevcs/includes/classes.inc versioncontrol_fakevcs/includes/classes.inc
index fc690d8..2b2a8d5 100644
--- versioncontrol_fakevcs/includes/classes.inc
+++ versioncontrol_fakevcs/includes/classes.inc
@@ -6,7 +6,6 @@ class VersioncontrolFakeBackend extends VersioncontrolBackend {
 
   public $classes = array(
     'repo'      => 'VersioncontrolFakeRepository',
-    'account'   => 'VersioncontrolFakeAccount',
     'operation' => 'VersioncontrolFakeOperation',
     'item'      => 'VersioncontrolFakeItem',
   );
@@ -78,65 +77,6 @@ class VersioncontrolFakeRepository extends VersioncontrolRepository implements V
 
 }
 
-class VersioncontrolFakeAccount extends VersioncontrolAccount {
-
-  /**
-   * Overwrite
-   */
-  public function usernameSuggestion($user) {
-    // For distributed version control systems, the user's email address
-    // might be a more appropriate username than the actual nick - it
-    // guarantees unique identification (= uid association for
-    // operations), even though it might need to be replaced by or
-    // amended with the full name on page display.
-    return $user->mail;
-  }
-
-  /**
-   * Overwrite
-   */
-  protected function _insert($additional_data) {
-    $fakevcs_specific = $additional_data['fakevcs_specific'];
-    if (!isset($fakevcs_specific) || !isset($fakevcs_specific['password'])) {
-      drupal_set_message(t('Error: no FakeVCS password given on account creation!'), 'error');
-      return;
-    }
-    db_query("INSERT INTO {versioncontrol_fakevcs_accounts}
-      (uid, repo_id, password)
-      VALUES (%d, %d, '%s')",
-      $this->uid, $this->repository->repo_id, $fakevcs_specific['password']);
-  }
-
-  /**
-   * Overwrite
-   */
-  protected function _update($additional_data) {
-    $fakevcs_specific = $additional_data['fakevcs_specific'];
-    if (!isset($fakevcs_specific) || !isset($fakevcs_specific['password'])) {
-      return; // the user didn't update the password in the process.
-    }
-    db_query("UPDATE {versioncontrol_fakevcs_accounts}
-      SET password = '%s'
-      WHERE uid = %d AND repo_id = %d",
-    $fakevcs_specific['password'], $this->uid, $this->repository->repo_id);
-
-    if (!versioncontrol_admin_access()) {
-      // Admins get "The account has been updated successfully" anyways.
-      drupal_set_message(t('The FakeVCS password has been updated successfully.'));
-    }
-  }
-
-  /**
-   * Overwrite
-   */
-  protected function _delete($additional_data) {
-   db_query('DELETE FROM {versioncontrol_fakevcs_accounts}
-     WHERE uid = %d AND repo_id = %d',
-     $this->uid, $this->repository->repo_id);
-  }
-
-}
-
 class VersioncontrolFakeOperation extends VersioncontrolOperation {
 
   /**
diff --git versioncontrol_fakevcs/versioncontrol_fakevcs.admin.inc versioncontrol_fakevcs/versioncontrol_fakevcs.admin.inc
index 91fd433..a6af8ba 100644
--- versioncontrol_fakevcs/versioncontrol_fakevcs.admin.inc
+++ versioncontrol_fakevcs/versioncontrol_fakevcs.admin.inc
@@ -143,17 +143,3 @@ function versioncontrol_fakevcs_account_form_validate($form, &$form_state) {
     form_set_error('account_password', t('The FakeVCS password you have chosen is too short (it must be at least !min characters long).', array('!min' => VERSIONCONTROL_FAKEVCS_MIN_PASSWORD_LENGTH)));
   }
 }
-
-/**
- * Implementation of hook_versioncontrol_account_submit():
- * Extract account data from the account edit/register form's submitted
- * values, and add it to the @p $additional_data array. Later, that array
- * will be passed to hook_versioncontrol_account() as part of the account
- * insert/update procedure.
- */
-function versioncontrol_fakevcs_versioncontrol_account_submit(&$additional_data, $form, $form_state) {
-  if (!isset($form['#versioncontrol_fakevcs']) || empty($form_state['values']['account_password'])) {
-    return;
-  }
-  $additional_data['fakevcs_specific']['password'] = crypt($form_state['values']['account_password']);
-}
diff --git versioncontrol_fakevcs/versioncontrol_fakevcs.module versioncontrol_fakevcs/versioncontrol_fakevcs.module
index 0a4935f..1ca61ca 100644
--- versioncontrol_fakevcs/versioncontrol_fakevcs.module
+++ versioncontrol_fakevcs/versioncontrol_fakevcs.module
@@ -76,43 +76,6 @@ function versioncontrol_fakevcs_operation($op, $operation, $operation_items) {
 }
 
 /**
- * Implementation of [versioncontrol_backend]_account():
- * Manage (insert, update or delete) additional FakeVCS user account data
- * in the database.
- *
- * @param $op
- *   Either 'insert' when the account is in the process of being created,
- *   or 'update' when username or VCS specific data change,
- *   or 'delete' if it will be deleted after this function has been called.
- * @param $uid
- *   The Drupal user id corresponding to the VCS account.
- * @param $username
- *   The VCS specific username (a string).
- * @param $repository
- *   The repository where the user has its VCS account.
- * @param $additional_data
- *   An array of additional author information.
- */
-function versioncontrol_fakevcs_account($op, $uid, $username, $repository, $additional_data = array()) {
-  // we need an example for this hook, since the one here is now
-  // implemented through account class method overrides
-  // VersioncontrolFakeAccount::_{insert,update,delete}()
-  // Probably a non-backend module fits better for implement it.
-  $fakevcs_specific = $additional_data['fakevcs_specific'];
-
-  switch ($op) {
-    case 'insert':
-      break;
-
-    case 'update':
-      break;
-
-    case 'delete':
-      break;
-  }
-}
-
-/**
  * Implementation of [versioncontrol_backend]_repository():
  * Manage (insert, update or delete) additional FakeVCS repository data
  * in the database.
