diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/assets/javascripts/pages/sessions/new/index.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/pages/sessions/new/username_validator.js | 148 | ||||
-rw-r--r-- | app/models/clusters/applications/knative.rb | 2 | ||||
-rw-r--r-- | app/services/git/wiki_push_service.rb | 9 | ||||
-rw-r--r-- | app/views/devise/shared/_signup_box.html.haml | 8 | ||||
-rw-r--r-- | app/workers/post_receive.rb | 23 |
6 files changed, 77 insertions, 115 deletions
diff --git a/app/assets/javascripts/pages/sessions/new/index.js b/app/assets/javascripts/pages/sessions/new/index.js index 3f5a3e15c2c..55bc93a2b13 100644 --- a/app/assets/javascripts/pages/sessions/new/index.js +++ b/app/assets/javascripts/pages/sessions/new/index.js @@ -7,8 +7,8 @@ import OAuthRememberMe from './oauth_remember_me'; import preserveUrlFragment from './preserve_url_fragment'; document.addEventListener('DOMContentLoaded', () => { - new LengthValidator(); // eslint-disable-line no-new new UsernameValidator(); // eslint-disable-line no-new + new LengthValidator(); // eslint-disable-line no-new new SigninTabsMemoizer(); // eslint-disable-line no-new new NoEmojiValidator(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/sessions/new/username_validator.js b/app/assets/javascripts/pages/sessions/new/username_validator.js index 7a41805bada..36d1e773134 100644 --- a/app/assets/javascripts/pages/sessions/new/username_validator.js +++ b/app/assets/javascripts/pages/sessions/new/username_validator.js @@ -1,133 +1,79 @@ -/* eslint-disable consistent-return, class-methods-use-this */ +import InputValidator from '~/validators/input_validator'; -import $ from 'jquery'; import _ from 'underscore'; import axios from '~/lib/utils/axios_utils'; import flash from '~/flash'; import { __ } from '~/locale'; const debounceTimeoutDuration = 1000; +const rootUrl = gon.relative_url_root; const invalidInputClass = 'gl-field-error-outline'; const successInputClass = 'gl-field-success-outline'; -const unavailableMessageSelector = '.username .validation-error'; -const successMessageSelector = '.username .validation-success'; -const pendingMessageSelector = '.username .validation-pending'; -const invalidMessageSelector = '.username .gl-field-error'; +const successMessageSelector = '.validation-success'; +const pendingMessageSelector = '.validation-pending'; +const unavailableMessageSelector = '.validation-error'; -export default class UsernameValidator { - constructor() { - this.inputElement = $('#new_user_username'); - this.inputDomElement = this.inputElement.get(0); - this.state = { - available: false, - valid: false, - pending: false, - empty: true, - }; +export default class UsernameValidator extends InputValidator { + constructor(opts = {}) { + super(); - const debounceTimeout = _.debounce(username => { - this.validateUsername(username); - }, debounceTimeoutDuration); - - this.inputElement.on('keyup.username_check', () => { - const username = this.inputElement.val(); - - this.state.valid = this.inputDomElement.validity.valid; - this.state.empty = !username.length; + const container = opts.container || ''; + const validateLengthElements = document.querySelectorAll(`${container} .js-validate-username`); - if (this.state.valid) { - return debounceTimeout(username); - } - - this.renderState(); - }); + this.debounceValidateInput = _.debounce(inputDomElement => { + UsernameValidator.validateUsernameInput(inputDomElement); + }, debounceTimeoutDuration); - // Override generic field validation - this.inputElement.on('invalid', this.interceptInvalid.bind(this)); + validateLengthElements.forEach(element => + element.addEventListener('input', this.eventHandler.bind(this)), + ); } - renderState() { - // Clear all state - this.clearFieldValidationState(); - - if (this.state.valid && this.state.available) { - return this.setSuccessState(); - } - - if (this.state.empty) { - return this.clearFieldValidationState(); - } - - if (this.state.pending) { - return this.setPendingState(); - } + eventHandler(event) { + const inputDomElement = event.target; - if (!this.state.valid) { - return this.setInvalidState(); - } - - if (!this.state.available) { - return this.setUnavailableState(); - } - } - - interceptInvalid(event) { - event.preventDefault(); - event.stopPropagation(); + UsernameValidator.resetInputState(inputDomElement); + this.debounceValidateInput(inputDomElement); } - validateUsername(username) { - if (this.state.valid) { - this.state.pending = true; - this.state.available = false; - this.renderState(); - axios - .get(`${gon.relative_url_root}/users/${username}/exists`) - .then(({ data }) => this.setAvailabilityState(data.exists)) + static validateUsernameInput(inputDomElement) { + const username = inputDomElement.value; + + if (inputDomElement.checkValidity() && username.length > 0) { + UsernameValidator.setMessageVisibility(inputDomElement, pendingMessageSelector); + UsernameValidator.fetchUsernameAvailability(username) + .then(usernameTaken => { + UsernameValidator.setInputState(inputDomElement, !usernameTaken); + UsernameValidator.setMessageVisibility(inputDomElement, pendingMessageSelector, false); + UsernameValidator.setMessageVisibility( + inputDomElement, + usernameTaken ? unavailableMessageSelector : successMessageSelector, + ); + }) .catch(() => flash(__('An error occurred while validating username'))); } } - setAvailabilityState(usernameTaken) { - if (usernameTaken) { - this.state.available = false; - } else { - this.state.available = true; - } - this.state.pending = false; - this.renderState(); + static fetchUsernameAvailability(username) { + return axios.get(`${rootUrl}/users/${username}/exists`).then(({ data }) => data.exists); } - clearFieldValidationState() { - this.inputElement.siblings('p').hide(); - - this.inputElement.removeClass(invalidInputClass).removeClass(successInputClass); + static setMessageVisibility(inputDomElement, messageSelector, isVisible = true) { + const messageElement = inputDomElement.parentElement.querySelector(messageSelector); + messageElement.classList.toggle('hide', !isVisible); } - setUnavailableState() { - const $usernameUnavailableMessage = this.inputElement.siblings(unavailableMessageSelector); - this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); - $usernameUnavailableMessage.show(); + static setInputState(inputDomElement, success = true) { + inputDomElement.classList.toggle(successInputClass, success); + inputDomElement.classList.toggle(invalidInputClass, !success); } - setSuccessState() { - const $usernameSuccessMessage = this.inputElement.siblings(successMessageSelector); - this.inputElement.addClass(successInputClass).removeClass(invalidInputClass); - $usernameSuccessMessage.show(); - } + static resetInputState(inputDomElement) { + UsernameValidator.setMessageVisibility(inputDomElement, successMessageSelector, false); + UsernameValidator.setMessageVisibility(inputDomElement, unavailableMessageSelector, false); - setPendingState() { - const $usernamePendingMessage = $(pendingMessageSelector); - if (this.state.pending) { - $usernamePendingMessage.show(); - } else { - $usernamePendingMessage.hide(); + if (inputDomElement.checkValidity()) { + inputDomElement.classList.remove(successInputClass, invalidInputClass); } } - - setInvalidState() { - const $inputErrorMessage = $(invalidMessageSelector); - this.inputElement.addClass(invalidInputClass).removeClass(successInputClass); - $inputErrorMessage.show(); - } } diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb index d5a3bd62e3d..5df4812bd25 100644 --- a/app/models/clusters/applications/knative.rb +++ b/app/models/clusters/applications/knative.rb @@ -3,7 +3,7 @@ module Clusters module Applications class Knative < ApplicationRecord - VERSION = '0.5.0'.freeze + VERSION = '0.6.0'.freeze REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze METRICS_CONFIG = 'https://storage.googleapis.com/triggermesh-charts/istio-metrics.yaml'.freeze FETCH_IP_ADDRESS_DELAY = 30.seconds diff --git a/app/services/git/wiki_push_service.rb b/app/services/git/wiki_push_service.rb new file mode 100644 index 00000000000..a053f133016 --- /dev/null +++ b/app/services/git/wiki_push_service.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Git + class WikiPushService < ::BaseService + def execute + # This is used in EE + end + end +end diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml index 5eba819172b..eae3ee6339f 100644 --- a/app/views/devise/shared/_signup_box.html.haml +++ b/app/views/devise/shared/_signup_box.html.haml @@ -10,10 +10,10 @@ = f.text_field :name, class: "form-control top qa-new-user-name js-block-emoji js-validate-length", :data => { :max_length => max_name_length, :max_length_message => s_("SignUp|Name is too long (maximum is %{max_length} characters).") % { max_length: max_name_length } }, required: true, title: _("This field is required.") .username.form-group = f.label :username, class: 'label-bold' - = f.text_field :username, class: "form-control middle qa-new-user-username js-block-emoji js-validate-length", :data => { :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length } }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.") - %p.validation-error.field-validation.hide= _('Username is already taken.') - %p.validation-success.field-validation.hide= _('Username is available.') - %p.validation-pending.field-validation.hide= _('Checking username availability...') + = f.text_field :username, class: "form-control middle qa-new-user-username js-block-emoji js-validate-length js-validate-username", :data => { :max_length => max_username_length, :max_length_message => s_("SignUp|Username is too long (maximum is %{max_length} characters).") % { max_length: max_username_length } }, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.") + %p.validation-error.gl-field-error-ignore.field-validation.hide= _('Username is already taken.') + %p.validation-success.gl-field-error-ignore.field-validation.hide= _('Username is available.') + %p.validation-pending.gl-field-error-ignore.field-validation.hide= _('Checking username availability...') .form-group = f.label :email, class: 'label-bold' = f.email_field :email, class: "form-control middle qa-new-user-email", required: true, title: _("Please provide a valid email address.") diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 3f1639ec2ed..dba7837bd12 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -30,15 +30,17 @@ class PostReceive private + def identify_user(post_received) + post_received.identify.tap do |user| + log("Triggered hook for non-existing user \"#{post_received.identifier}\"") unless user + end + end + def process_project_changes(post_received) changes = [] refs = Set.new - @user = post_received.identify - - unless @user - log("Triggered hook for non-existing user \"#{post_received.identifier}\"") - return false - end + user = identify_user(post_received) + return false unless user post_received.enum_for(:changes_refs).with_index do |(oldrev, newrev, ref), index| service_klass = @@ -51,7 +53,7 @@ class PostReceive if service_klass service_klass.new( post_received.project, - @user, + user, oldrev: oldrev, newrev: newrev, ref: ref, @@ -64,7 +66,7 @@ class PostReceive refs << ref end - after_project_changes_hooks(post_received, @user, refs.to_a, changes) + after_project_changes_hooks(post_received, user, refs.to_a, changes) end def after_project_changes_hooks(post_received, user, refs, changes) @@ -76,6 +78,11 @@ class PostReceive post_received.project.touch(:last_activity_at, :last_repository_updated_at) post_received.project.wiki.repository.expire_statistics_caches ProjectCacheWorker.perform_async(post_received.project.id, [], [:wiki_size]) + + user = identify_user(post_received) + return false unless user + + ::Git::WikiPushService.new(post_received.project, user, changes: post_received.enum_for(:changes_refs)).execute end def log(message) |