Commit 533c4977 authored by Fran Garcia-Linares's avatar Fran Garcia-Linares Committed by Neil Drumm
Browse files

Issue #3302622: Isolate the logic to validate a gitlab username so it can be reused

parent 05fcc4ce
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -35,6 +35,12 @@ define('DRUPALORG_GIT_GATECTL_SANDBOXES', 0x04);
// defining this constant in hopeful anticipation :)
// define('DRUPALORG_GIT_GATECTL_ISSUES', 0x08);

define('DRUPALORG_GIT_USERNAME_TAKEN', 'username_taken');
define('DRUPALORG_GIT_USERNAME_INVALID_PATTERN', 'username_invalid_pattern');
define('DRUPALORG_GIT_USERNAME_INVALID_CONTAINS_RESERVED_NAME', 'username_invalid_reserved_name');
define('DRUPALORG_GIT_USERNAME_INVALID_CONTAINS_FILE_EXTENSION', 'username_invalid_file_extension');
define('DRUPALORG_GIT_USERNAME_VALID', 'username_valid');

/**
 * Implements hook_menu().
 */
@@ -324,3 +330,45 @@ function drupalorg_git_gateway_mail($key, &$message, $params = array()) {
    return;
  }
}

/**
 * Validation of username.
 *
 * @param string $username
 *   Username to check.
 * @param int $uid
 *   Id of the user the username is attached to.
 *
 * @return int
 *   Code that explains if it's a valid username or not, and why.
 */
function drupalorg_git_gateway_username_check($username, $uid) {
  // Ensure the requested ID isn't taken.
  if ($uid = db_query("SELECT uid FROM {users} WHERE git_username = :git_username AND uid <> :uid", [':git_username' => $username, ':uid' => $uid])->fetchField()) {
    return DRUPALORG_GIT_USERNAME_TAKEN;
  }
  // And is a valid pattern. Adapted from NAMESPACE_FORMAT_REGEX in
  // https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/path_regex.rb
  // and project_name_regex in
  // https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/regex.rb
  // since Git usernames are used in sandbox project names.
  elseif (!preg_match('/^(?:[a-zA-Z0-9_][a-zA-Z0-9_\-\.]*[a-zA-Z0-9_\-]|[a-zA-Z0-9_])(?<!\.git|\.atom)$/', $username)) {
    return DRUPALORG_GIT_USERNAME_INVALID_PATTERN;
  }
  elseif (in_array(drupal_strtolower($username), variable_get('drupalorg_git_reserved_names', []))) {
    return DRUPALORG_GIT_USERNAME_INVALID_CONTAINS_RESERVED_NAME;
  }
  elseif (preg_match('/\.([^.]*)$/', $username, $match) && in_array($match[1], ['html', 'xhtml', 'text', 'txt', 'js', 'css', 'ics', 'csv', 'vcf', 'vtt', 'png', 'jpeg', 'jpg', 'jpe', 'pjpeg', 'gif', 'bmp', 'tiff', 'tif', 'svg', 'mpeg', 'mpg', 'mpe', 'mp3', 'mp1', 'mp2', 'ogg', 'oga', 'spx', 'opus', 'm4a', 'mpg4', 'aac', 'webm', 'mp4', 'm4v', 'otf', 'ttf', 'woff', 'woff2', 'xml', 'rss', 'atom', 'yaml', 'yml', 'multipart_form', 'url_encoded_form', 'pdf', 'zip', 'gzip', 'gz', 'diff', 'patch', 'markdown', 'md', 'mov', 'ogv', 'json', 'ico'])) {
    return DRUPALORG_GIT_USERNAME_INVALID_CONTAINS_FILE_EXTENSION;
  }

  return DRUPALORG_GIT_USERNAME_VALID;
}

/**
 * Suggest a valid gitlab username.
 */
function drupalorg_git_gateway_username_prepare($username) {
  $username = drupal_strtolower($username);
  return preg_replace('/[^A-Za-z0-9\._-]/', '', $username);
}
+5 −10
Original line number Diff line number Diff line
@@ -359,22 +359,17 @@ function drupalorg_git_gateway_user_form_base_validate($form, &$form_state) {
 * Element validate callback.
 */
function drupalorg_git_gateway_username_validate($element, $form_state) {
  // Ensure the requested ID isn't taken.
  if ($uid = db_query("SELECT uid FROM {users} WHERE git_username = :git_username AND uid <> :uid", [':git_username' => $element['#value'], ':uid' => $form_state['account']->uid])->fetchField()) {
  $username_check = drupalorg_git_gateway_username_check($element['#value'], $form_state['account']->uid);
  if ($username_check == DRUPALORG_GIT_USERNAME_TAKEN) {
    form_set_error('git_username', t('The requested Git username is already taken.'));
  }
  // And is a valid pattern. Adapted from NAMESPACE_FORMAT_REGEX in
  // https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/path_regex.rb
  // and project_name_regex in
  // https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/regex.rb
  // since Git usernames are used in sandbox project names.
  elseif (!preg_match('/^(?:[a-zA-Z0-9_][a-zA-Z0-9_\-\.]*[a-zA-Z0-9_\-]|[a-zA-Z0-9_])(?<!\.git|\.atom)$/', $element['#value'])) {
  elseif ($username_check == DRUPALORG_GIT_USERNAME_INVALID_PATTERN) {
    form_set_error('git_username', t('The requested username contains invalid characters.'));
  }
  elseif (in_array(drupal_strtolower($element['#value']), variable_get('drupalorg_git_reserved_names', []))) {
  elseif ($username_check == DRUPALORG_GIT_USERNAME_INVALID_CONTAINS_RESERVED_NAME) {
    form_set_error('git_username', t('The requested username is reserved, please choose a different Git username.'));
  }
  elseif (preg_match('/\.([^.]*)$/', $element['#value'], $match) && in_array($match[1], ['html', 'xhtml', 'text', 'txt', 'js', 'css', 'ics', 'csv', 'vcf', 'vtt', 'png', 'jpeg', 'jpg', 'jpe', 'pjpeg', 'gif', 'bmp', 'tiff', 'tif', 'svg', 'mpeg', 'mpg', 'mpe', 'mp3', 'mp1', 'mp2', 'ogg', 'oga', 'spx', 'opus', 'm4a', 'mpg4', 'aac', 'webm', 'mp4', 'm4v', 'otf', 'ttf', 'woff', 'woff2', 'xml', 'rss', 'atom', 'yaml', 'yml', 'multipart_form', 'url_encoded_form', 'pdf', 'zip', 'gzip', 'gz', 'diff', 'patch', 'markdown', 'md', 'mov', 'ogv', 'json', 'ico'])) {
  elseif ($username_check == DRUPALORG_GIT_USERNAME_INVALID_CONTAINS_FILE_EXTENSION) {
    form_set_error('git_username', t('The requested username is reserved, please choose a different Git username.'));
  }
}