Commit 1cfb48dd authored by Guilherme Garnier's avatar Guilherme Garnier

Merge remote-tracking branch 'upstream/master'

parents 848d7b2a 662f8af4
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.1.0 (unreleased) v 8.1.0 (unreleased)
- Fix bug where transferring a project would result in stale commit links (Stan Hu)
- Include full path of source and target branch names in New Merge Request page (Stan Hu) - Include full path of source and target branch names in New Merge Request page (Stan Hu)
- Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu) - Fix Message-ID header to be RFC 2111-compliant to prevent e-mails being dropped (Stan Hu)
- Add user preference to view activities as default dashboard (Stan Hu) - Add user preference to view activities as default dashboard (Stan Hu)
...@@ -26,6 +27,8 @@ v 8.1.0 (unreleased) ...@@ -26,6 +27,8 @@ v 8.1.0 (unreleased)
- Show additions/deletions stats on merge request diff - Show additions/deletions stats on merge request diff
- Remove footer text in emails (Zeger-Jan van de Weg) - Remove footer text in emails (Zeger-Jan van de Weg)
- Ensure code blocks are properly highlighted after a note is updated - Ensure code blocks are properly highlighted after a note is updated
- Fix wrong access level badge on MR comments
- Hide password in the service settings form
v 8.0.3 v 8.0.3
- Fix URL shown in Slack notifications - Fix URL shown in Slack notifications
......
...@@ -270,6 +270,8 @@ group :development, :test do ...@@ -270,6 +270,8 @@ group :development, :test do
gem 'rubocop', '~> 0.28.0', require: false gem 'rubocop', '~> 0.28.0', require: false
gem 'coveralls', '~> 0.8.2', require: false gem 'coveralls', '~> 0.8.2', require: false
gem 'simplecov', '~> 0.10.0', require: false gem 'simplecov', '~> 0.10.0', require: false
gem 'benchmark-ips', require: false
end end
group :test do group :test do
......
...@@ -66,6 +66,7 @@ GEM ...@@ -66,6 +66,7 @@ GEM
ice_nine (~> 0.11.0) ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1) thread_safe (~> 0.3, >= 0.3.1)
bcrypt (3.1.10) bcrypt (3.1.10)
benchmark-ips (2.3.0)
better_errors (1.0.1) better_errors (1.0.1)
coderay (>= 1.0.0) coderay (>= 1.0.0)
erubis (>= 2.6.6) erubis (>= 2.6.6)
...@@ -795,6 +796,7 @@ DEPENDENCIES ...@@ -795,6 +796,7 @@ DEPENDENCIES
asciidoctor (~> 1.5.2) asciidoctor (~> 1.5.2)
attr_encrypted (~> 1.3.4) attr_encrypted (~> 1.3.4)
awesome_print (~> 1.2.0) awesome_print (~> 1.2.0)
benchmark-ips
better_errors (~> 1.0.1) better_errors (~> 1.0.1)
binding_of_caller (~> 0.7.2) binding_of_caller (~> 0.7.2)
bootstrap-sass (~> 3.0) bootstrap-sass (~> 3.0)
......
html { html {
overflow-y: scroll; overflow-y: scroll;
height: 100%;
margin: 0;
&.touch .tooltip { display: none !important; } &.touch .tooltip { display: none !important; }
body { body {
padding-top: $header-height; padding-top: $header-height;
height: 100%;
margin: 0;
} }
} }
.container { .container {
padding-top: 0; padding-top: 0;
height: 100%;
width: 100%;
z-index: 5; z-index: 5;
} }
.content {
height: 100%;
width: 100%;
}
.content section {
height: 100%;
display: table-row;
}
.container .content { .container .content {
margin: 0 0; margin: 0 0;
} }
...@@ -24,3 +40,9 @@ html { ...@@ -24,3 +40,9 @@ html {
.container-limited { .container-limited {
max-width: $fixed-layout-width; max-width: $fixed-layout-width;
} }
.max-height {
height: 100%;
display: table;
width: 100%;
}
\ No newline at end of file
...@@ -94,6 +94,7 @@ body { ...@@ -94,6 +94,7 @@ body {
@mixin btn-info { @mixin btn-info {
@include border-radius(2px); @include border-radius(2px);
@include transition (all 0.2s ease 0s);
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
...@@ -116,6 +117,7 @@ body { ...@@ -116,6 +117,7 @@ body {
&:active { &:active {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12)); @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
} }
...@@ -123,6 +125,7 @@ body { ...@@ -123,6 +125,7 @@ body {
@mixin btn-middle { @mixin btn-middle {
@include border-radius(2px); @include border-radius(2px);
@include transition (all 0.2s ease 0s);
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
...@@ -145,6 +148,7 @@ body { ...@@ -145,6 +148,7 @@ body {
&:active { &:active {
@include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12)); @include box-shadow(inset 0 0 4px rgba(0, 0, 0, 0.12));
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
} }
......
.page-with-sidebar { .page-with-sidebar {
min-height: 100%;
height: 100%;
.sidebar-wrapper { .sidebar-wrapper {
position: fixed; position: fixed;
top: 0; top: 0;
...@@ -18,15 +21,19 @@ ...@@ -18,15 +21,19 @@
} }
.content-wrapper { .content-wrapper {
min-height: 100vh; min-height: 900px;
display: table;
width: 100%; width: 100%;
padding: 20px; padding: 20px;
background: #EAEBEC; background: #EAEBEC;
height: 100%;
width: 100%;
.container-fluid { .container-fluid {
background: #FFF; background: #FFF;
padding: $gl-padding; padding: $gl-padding;
min-height: 90vh; height: 100%;
min-height: 100%;
&.container-blank { &.container-blank {
background: none; background: none;
......
...@@ -510,4 +510,3 @@ pre.light-well { ...@@ -510,4 +510,3 @@ pre.light-well {
.inline-form { .inline-form {
display: inline-block; display: inline-block;
} }
...@@ -20,6 +20,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -20,6 +20,7 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
@projects = current_user.starred_projects @projects = current_user.starred_projects
@projects = @projects.includes(:namespace, :forked_from_project, :tags) @projects = @projects.includes(:namespace, :forked_from_project, :tags)
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
@last_push = current_user.recent_push
@groups = [] @groups = []
respond_to do |format| respond_to do |format|
......
class PasswordsController < Devise::PasswordsController class PasswordsController < Devise::PasswordsController
before_action :resource_from_email, only: [:create]
def create before_action :prevent_ldap_reset, only: [:create]
email = resource_params[:email] before_action :throttle_reset, only: [:create]
resource_found = resource_class.find_by_email(email)
if resource_found && resource_found.ldap_user?
flash[:alert] = "Cannot reset password for LDAP user."
respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name)) and return
end
self.resource = resource_class.send_reset_password_instructions(resource_params)
if successfully_sent?(resource)
respond_with({}, location: after_sending_reset_password_instructions_path_for(resource_name))
else
respond_with(resource)
end
end
def edit def edit
super super
...@@ -35,4 +22,25 @@ class PasswordsController < Devise::PasswordsController ...@@ -35,4 +22,25 @@ class PasswordsController < Devise::PasswordsController
end end
end end
end end
protected
def resource_from_email
email = resource_params[:email]
self.resource = resource_class.find_by_email(email)
end
def prevent_ldap_reset
return unless resource && resource.ldap_user?
redirect_to after_sending_reset_password_instructions_path_for(resource_name),
alert: "Cannot reset password for LDAP user."
end
def throttle_reset
return unless resource && resource.recently_sent_password_reset?
redirect_to new_password_path(resource_name),
alert: I18n.t('devise.passwords.recently_reset')
end
end end
...@@ -58,6 +58,8 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -58,6 +58,8 @@ class Projects::ServicesController < Projects::ApplicationController
end end
def service_params def service_params
params.require(:service).permit(ALLOWED_PARAMS) service_params = params.require(:service).permit(ALLOWED_PARAMS)
service_params.delete("password") if service_params["password"].blank?
service_params
end end
end end
...@@ -296,7 +296,7 @@ module ProjectsHelper ...@@ -296,7 +296,7 @@ module ProjectsHelper
def readme_cache_key def readme_cache_key
sha = @project.commit.try(:sha) || 'nil' sha = @project.commit.try(:sha) || 'nil'
[@project.id, sha, "readme"].join('-') [@project.path_with_namespace, sha, "readme"].join('-')
end end
def round_commit_count(project) def round_commit_count(project)
......
...@@ -751,13 +751,9 @@ class Project < ActiveRecord::Base ...@@ -751,13 +751,9 @@ class Project < ActiveRecord::Base
gitlab_ci_project || create_gitlab_ci_project gitlab_ci_project || create_gitlab_ci_project
end end
def enable_ci(user) def enable_ci
# Enable service
service = gitlab_ci_service || create_gitlab_ci_service service = gitlab_ci_service || create_gitlab_ci_service
service.active = true service.active = true
service.save service.save
# Create Ci::Project
Ci::CreateProjectService.new.execute(user, self)
end end
end end
...@@ -22,12 +22,17 @@ class GitlabCiService < CiService ...@@ -22,12 +22,17 @@ class GitlabCiService < CiService
include Gitlab::Application.routes.url_helpers include Gitlab::Application.routes.url_helpers
after_save :compose_service_hook, if: :activated? after_save :compose_service_hook, if: :activated?
after_save :ensure_gitlab_ci_project, if: :activated?
def compose_service_hook def compose_service_hook
hook = service_hook || build_service_hook hook = service_hook || build_service_hook
hook.save hook.save
end end
def ensure_gitlab_ci_project
project.ensure_gitlab_ci_project
end
def supported_events def supported_events
%w(push tag_push) %w(push tag_push)
end end
...@@ -67,21 +72,6 @@ class GitlabCiService < CiService ...@@ -67,21 +72,6 @@ class GitlabCiService < CiService
:error :error
end end
def fork_registration(new_project, current_user)
params = OpenStruct.new({
id: new_project.id,
default_branch: new_project.default_branch
})
ci_project = Ci::Project.find_by!(gitlab_id: project.id)
Ci::CreateProjectService.new.execute(
current_user,
params,
ci_project
)
end
def commit_coverage(sha, ref) def commit_coverage(sha, ref)
get_ci_commit(sha, ref).coverage get_ci_commit(sha, ref).coverage
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
......
...@@ -135,6 +135,10 @@ class ProjectTeam ...@@ -135,6 +135,10 @@ class ProjectTeam
!!find_member(user_id) !!find_member(user_id)
end end
def human_max_access(user_id)
Gitlab::Access.options.key max_member_access(user_id)
end
def max_member_access(user_id) def max_member_access(user_id)
access = [] access = []
access << project.project_members.find_by(user_id: user_id).try(:access_field) access << project.project_members.find_by(user_id: user_id).try(:access_field)
......
...@@ -328,6 +328,10 @@ class User < ActiveRecord::Base ...@@ -328,6 +328,10 @@ class User < ActiveRecord::Base
@reset_token @reset_token
end end
def recently_sent_password_reset?
reset_password_sent_at.present? && reset_password_sent_at >= 1.minute.ago
end
def disable_two_factor! def disable_two_factor!
update_attributes( update_attributes(
two_factor_enabled: false, two_factor_enabled: false,
......
module Ci
class CreateProjectService
include Gitlab::Application.routes.url_helpers
def execute(current_user, params, forked_project = nil)
@project = Ci::Project.parse(params)
Ci::Project.transaction do
@project.save!
gl_project = ::Project.find(@project.gitlab_id)
gl_project.build_missing_services
gl_project.gitlab_ci_service.update_attributes(active: true)
end
if forked_project
# Copy settings
settings = forked_project.attributes.select do |attr_name, value|
["public", "shared_runners_enabled", "allow_git_fetch"].include? attr_name
end
@project.update(settings)
end
Ci::EventService.new.create_project(current_user, @project)
@project
end
end
end
...@@ -58,7 +58,7 @@ class GitPushService ...@@ -58,7 +58,7 @@ class GitPushService
# If CI was disabled but .gitlab-ci.yml file was pushed # If CI was disabled but .gitlab-ci.yml file was pushed
# we enable CI automatically # we enable CI automatically
if !project.gitlab_ci? && gitlab_ci_yaml?(newrev) if !project.gitlab_ci? && gitlab_ci_yaml?(newrev)
project.enable_ci(user) project.enable_ci
end end
EventCreateService.new.push(project, user, @push_data) EventCreateService.new.push(project, user, @push_data)
......
...@@ -18,7 +18,13 @@ module Projects ...@@ -18,7 +18,13 @@ module Projects
if new_project.persisted? if new_project.persisted?
if @project.gitlab_ci? if @project.gitlab_ci?
@project.gitlab_ci_service.fork_registration(new_project, @current_user) new_project.enable_ci
settings = @project.gitlab_ci_project.attributes.select do |attr_name, value|
["public", "shared_runners_enabled", "allow_git_fetch"].include? attr_name
end
new_project.gitlab_ci_project.update(settings)
end end
end end
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
= render 'dashboard/projects_head' = render 'dashboard/projects_head'
- if @last_push
= render "events/event_last_push", event: @last_push
- if @projects.any? - if @projects.any?
= render 'projects' = render 'projects'
- else - else
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.devise-errors .devise-errors
= devise_error_messages! = devise_error_messages!
.clearfix.append-bottom-20 .clearfix.append-bottom-20
= f.email_field :email, placeholder: "Email", class: "form-control", required: true, value: params[:user_email] = f.email_field :email, placeholder: "Email", class: "form-control", required: true, value: params[:user_email], autofocus: true
.clearfix .clearfix
= f.submit "Reset password", class: "btn-primary btn" = f.submit "Reset password", class: "btn-primary btn"
......
...@@ -25,5 +25,5 @@ ...@@ -25,5 +25,5 @@
= render "layouts/flash" = render "layouts/flash"
%div{ class: container_class } %div{ class: container_class }
.content .content
.clearfix .clearfix.max-height
= yield = yield
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
- note_count = notes.user.count - note_count = notes.user.count
- ci_commit = project.ci_commit(commit.sha) - ci_commit = project.ci_commit(commit.sha)
- cache_key = [project.id, commit.id, note_count] - cache_key = [project.path_with_namespace, commit.id, note_count]
- cache_key.push(ci_commit.status) if ci_commit - cache_key.push(ci_commit.status) if ci_commit
= cache(cache_key) do = cache(cache_key) do
......
...@@ -14,10 +14,10 @@ ...@@ -14,10 +14,10 @@
= icon('trash-o') = icon('trash-o')
- unless note.system - unless note.system
- member = note.project.team.find_member(note.author.id) - access = note.project.team.human_max_access(note.author.id)
- if member - if access
%span.note-role.label %span.note-role.label
= member.human_access = access
= link_to_member(note.project, note.author, avatar: false) = link_to_member(note.project, note.author, avatar: false)
......
...@@ -8,7 +8,10 @@ ...@@ -8,7 +8,10 @@
- help = field[:help] - help = field[:help]
.form-group .form-group
= form.label name, title, class: "control-label" - if type == "password" && value.present?
= form.label name, "Change #{title}", class: "control-label"
- else
= form.label name, title, class: "control-label"
.col-sm-10 .col-sm-10
- if type == 'text' - if type == 'text'
= form.text_field name, class: "form-control", placeholder: placeholder = form.text_field name, class: "form-control", placeholder: placeholder
...@@ -19,6 +22,6 @@ ...@@ -19,6 +22,6 @@
- elsif type == 'select' - elsif type == 'select'
= form.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" } = form.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" }
- elsif type == 'password' - elsif type == 'password'
= form.password_field name, value: value, class: 'form-control' = form.password_field name, autocomplete: "new-password", class: 'form-control'
- if help - if help
%span.help-block= help %span.help-block= help
# Additional translations at http://github.com/plataformatec/devise/wiki/I18n # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en: en:
devise:
confirmations:
confirmed: "Your email address has been successfully confirmed."
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
failure:
already_authenticated: "You are already signed in."
inactive: "Your account is not activated yet."
invalid: "Invalid %{authentication_keys} or password."
locked: "Your account is locked."
last_attempt: "You have one more attempt before your account is locked."
not_found_in_database: "Invalid %{authentication_keys} or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
unconfirmed: "You have to confirm your email address before continuing."
mailer:
confirmation_instructions:
subject: "Confirmation instructions"
reset_password_instructions:
subject: "Reset password instructions"
unlock_instructions:
subject: "Unlock instructions"
password_change:
subject: "Password Changed"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
passwords:
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
recently_reset: "Instructions about how to reset your password have already been sent recently. Please wait a few minutes to try again."
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
updated: "Your password has been changed successfully. You are now signed in."
updated_not_active: "Your password has been changed successfully."
registrations:
destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
signed_up: "Welcome! You have signed up successfully."
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
updated: "Your account has been updated successfully."
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
already_signed_out: "Signed out successfully."
unlocks:
send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
errors: errors:
messages: messages:
already_confirmed: "was already confirmed, please try signing in"
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
expired: "has expired, please request a new one" expired: "has expired, please request a new one"
not_found: "not found" not_found: "not found"
already_confirmed: "was already confirmed, please try signing in"
not_locked: "was not locked" not_locked: "was not locked"
not_saved: not_saved:
one: "1 error prohibited this %{resource} from being saved:" one: "1 error prohibited this %{resource} from being saved:"
other: "%{count} errors prohibited this %{resource} from being saved:" other: "%{count} errors prohibited this %{resource} from being saved:"
devise:
failure:
already_authenticated: 'You are already signed in.'
unauthenticated: 'You need to sign in before continuing.'
unconfirmed: 'You have to confirm your account before continuing.'
locked: 'Your account is locked.'
not_found_in_database: 'Invalid email or password.'
invalid: 'Invalid email or password.'
invalid_token: 'Invalid authentication token.'
timeout: 'Your session expired, please sign in again to continue.'
inactive: 'Your account was not activated yet.'
sessions:
signed_in: ''
signed_out: ''
users_sessions:
user:
signed_in: 'Signed in successfully.'
passwords:
send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.'
updated: 'Your password was changed successfully. You are now signed in.'
updated_not_active: 'Your password was changed successfully.'
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
confirmations:
send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.'
send_paranoid_instructions: 'If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes.'
confirmed: 'Your account was successfully confirmed. You are now signed in.'
registrations:
signed_up: 'Welcome! You have signed up successfully.'
updated: 'You updated your account successfully.'
destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.'
signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.'
signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.'
signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.'
unlocks:
send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.'
unlocked: 'Your account was successfully unlocked. You are now signed in.'
send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.'
omniauth_callbacks:
success: 'Successfully authorized from %{kind} account.'
failure: 'Could not authorize you from %{kind} because "%{reason}".'
mailer:
confirmation_instructions:
subject: 'Confirmation instructions'
reset_password_instructions:
subject: 'Reset password instructions'
unlock_instructions:
subject: 'Unlock Instructions'
...@@ -182,6 +182,7 @@ will need this file later. ...@@ -182,6 +182,7 @@ will need this file later.
``` ```
# On your CI server: # On your CI server:
# Omnibus # Omnibus
sudo chown gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
sudo gitlab-ci-rake backup:create sudo gitlab-ci-rake backup:create
# Source # Source
...@@ -228,6 +229,7 @@ be no CI data yet because you turned CI on the GitLab server off earlier. ...@@ -228,6 +229,7 @@ be no CI data yet because you turned CI on the GitLab server off earlier.
``` ```
# On your GitLab server: # On your GitLab server:
# Omnibus # Omnibus
sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
sudo gitlab-rake ci:migrate sudo gitlab-rake ci:migrate
# Source # Source
...@@ -342,7 +344,12 @@ The fix for this is to update to Omnibus 7.14 first and then update it to 8.0. ...@@ -342,7 +344,12 @@ The fix for this is to update to Omnibus 7.14 first and then update it to 8.0.
#### Permission denied when accessing /var/opt/gitlab/gitlab-ci/builds #### Permission denied when accessing /var/opt/gitlab/gitlab-ci/builds
To fix that issue you have to change builds/ folder permission before doing final backup: To fix that issue you have to change builds/ folder permission before doing final backup:
``` ```
chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds sudo chown -R gitlab-ci:gitlab-ci /var/opt/gitlab/gitlab-ci/builds
```
Then before executing `ci:migrate` you need to fix builds folder permission:
```
sudo chown git:git /var/opt/gitlab/gitlab-ci/builds
``` ```
#### Problems when importing CI database to GitLab #### Problems when importing CI database to GitLab
......
...@@ -72,6 +72,7 @@ Feature: Project Services ...@@ -72,6 +72,7 @@ Feature: Project Services
And I click Atlassian Bamboo CI service link And I click Atlassian Bamboo CI service link
And I fill Atlassian Bamboo CI settings And I fill Atlassian Bamboo CI settings
Then I should see Atlassian Bamboo CI service settings saved Then I should see Atlassian Bamboo CI service settings saved
And I should see empty field Change Password
Scenario: Activate jetBrains TeamCity CI service Scenario: Activate jetBrains TeamCity CI service
When I visit project "Shop" services page When I visit project "Shop" services page
......
...@@ -103,7 +103,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps ...@@ -103,7 +103,7 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
end end
step 'commit has ci status' do step 'commit has ci status' do
@project.enable_ci(@user) @project.enable_ci
create :ci_commit, gl_project: @project, sha: sample_commit.id create :ci_commit, gl_project: @project, sha: sample_commit.id
end end
......
...@@ -202,6 +202,10 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps ...@@ -202,6 +202,10 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
expect(find_field('Username').value).to eq 'user' expect(find_field('Username').value).to eq 'user'
end end
step 'I should see empty field Change Password' do
expect(find_field('Change Password').value).to be_nil
end
step 'I click JetBrains TeamCity CI service link' do step 'I click JetBrains TeamCity CI service link' do
click_link 'JetBrains TeamCity CI' click_link 'JetBrains TeamCity CI'
end end
......
...@@ -199,7 +199,7 @@ module SharedProject ...@@ -199,7 +199,7 @@ module SharedProject
step 'project "Shop" has CI enabled' do step 'project "Shop" has CI enabled' do
project = Project.find_by(name: "Shop") project = Project.find_by(name: "Shop")
project.enable_ci(@user) project.enable_ci
end end
step 'project "Shop" has CI build' do step 'project "Shop" has CI build' do
......
...@@ -95,7 +95,7 @@ feature 'Login', feature: true do ...@@ -95,7 +95,7 @@ feature 'Login', feature: true do
user = create(:user, password: 'not-the-default') user = create(:user, password: 'not-the-default')
login_with(user) login_with(user)
expect(page).to have_content('Invalid email or password.') expect(page).to have_content('Invalid login or password.')
end end
end end
end end
require 'spec_helper' require 'spec_helper'
feature 'Password reset', feature: true do feature 'Password reset', feature: true do
describe 'with two-factor authentication' do describe 'throttling' do
let(:user) { create(:user, :two_factor) } it 'sends reset instructions when not previously sent' do
it 'requires login after password reset' do
visit root_path visit root_path
forgot_password(create(:user))
forgot_password expect(page).to have_content(I18n.t('devise.passwords.send_instructions'))
reset_password
expect(page).to have_content("Your password was changed successfully.")
expect(page).not_to have_content("You are now signed in.")
expect(current_path).to eq new_user_session_path expect(current_path).to eq new_user_session_path
end end
end
describe 'without two-factor authentication' do it 'sends reset instructions when previously sent more than a minute ago' do
let(:user) { create(:user) } user = create(:user)
user.send_reset_password_instructions
user.update_attribute(:reset_password_sent_at, 5.minutes.ago)
it 'requires login after password reset' do
visit root_path visit root_path
forgot_password(user)
forgot_password expect(page).to have_content(I18n.t('devise.passwords.send_instructions'))
reset_password
expect(page).to have_content("Your password was changed successfully.")
expect(current_path).to eq new_user_session_path expect(current_path).to eq new_user_session_path
end end
it "throttles multiple resets in a short timespan" do
user = create(:user)
user.send_reset_password_instructions
visit root_path
forgot_password(user)
expect(page).to have_content(I18n.t('devise.passwords.recently_reset'))
expect(current_path).to eq new_user_password_path
end
end end
def forgot_password def forgot_password(user)
click_on 'Forgot your password?' click_on 'Forgot your password?'
fill_in 'Email', with: user.email fill_in 'Email', with: user.email
click_button 'Reset password' click_button 'Reset password'
user.reload user.reload
end end
def get_reset_token
mail = ActionMailer::Base.deliveries.last
body = mail.body.encoded
body.scan(/reset_password_token=(.+)\"/).flatten.first
end
def reset_password(password = 'password')
visit edit_user_password_path(reset_password_token: get_reset_token)
fill_in 'New password', with: password
fill_in 'Confirm new password', with: password
click_button 'Change your password'
end
end end
...@@ -61,13 +61,13 @@ describe ProjectsHelper do ...@@ -61,13 +61,13 @@ describe ProjectsHelper do
end end
it "returns a valid cach key" do it "returns a valid cach key" do
expect(helper.send(:readme_cache_key)).to eq("#{project.id}-#{project.commit.id}-readme") expect(helper.send(:readme_cache_key)).to eq("#{project.path_with_namespace}-#{project.commit.id}-readme")
end end
it "returns a valid cache key if HEAD does not exist" do it "returns a valid cache key if HEAD does not exist" do
allow(project).to receive(:commit) { nil } allow(project).to receive(:commit) { nil }
expect(helper.send(:readme_cache_key)).to eq("#{project.id}-nil-readme") expect(helper.send(:readme_cache_key)).to eq("#{project.path_with_namespace}-nil-readme")
end end
end end
end end
...@@ -55,25 +55,4 @@ describe GitlabCiService do ...@@ -55,25 +55,4 @@ describe GitlabCiService do
end end
end end
end end
describe "Fork registration" do
before do
@old_project = create(:ci_project).gl_project
@project = create(:empty_project)
@user = create(:user)
@service = GitlabCiService.new
allow(@service).to receive_messages(
service_hook: true,
project_url: 'http://ci.gitlab.org/projects/2',
token: 'verySecret',
project: @old_project
)
end
it "creates fork on CI" do
expect_any_instance_of(Ci::CreateProjectService).to receive(:execute)
@service.fork_registration(@project, @user)
end
end
end end
...@@ -417,9 +417,8 @@ describe Project do ...@@ -417,9 +417,8 @@ describe Project do
describe :enable_ci do describe :enable_ci do
let(:project) { create :project } let(:project) { create :project }
let(:user) { create :user }
before { project.enable_ci(user) } before { project.enable_ci }
it { expect(project.gitlab_ci?).to be_truthy } it { expect(project.gitlab_ci?).to be_truthy }
it { expect(project.gitlab_ci_project).to be_a(Ci::Project) } it { expect(project.gitlab_ci_project).to be_a(Ci::Project) }
......
...@@ -66,4 +66,16 @@ describe ProjectTeam do ...@@ -66,4 +66,16 @@ describe ProjectTeam do
it { expect(project.team.member?(guest)).to be_truthy } it { expect(project.team.member?(guest)).to be_truthy }
end end
end end
describe "#human_max_access" do
it "return master role" do
user = create :user
group = create :group
group.add_users([user.id], GroupMember::MASTER)
project = create(:project, namespace: group)
project.team << [user, :guest]
expect(project.team.human_max_access(user.id)).to eq("Master")
end
end
end end
...@@ -228,6 +228,26 @@ describe User do ...@@ -228,6 +228,26 @@ describe User do
end end
end end
describe '#recently_sent_password_reset?' do
it 'is false when reset_password_sent_at is nil' do
user = build_stubbed(:user, reset_password_sent_at: nil)
expect(user.recently_sent_password_reset?).to eq false
end
it 'is false when sent more than one minute ago' do
user = build_stubbed(:user, reset_password_sent_at: 5.minutes.ago)
expect(user.recently_sent_password_reset?).to eq false
end
it 'is true when sent less than one minute ago' do
user = build_stubbed(:user, reset_password_sent_at: Time.now)
expect(user.recently_sent_password_reset?).to eq true
end
end
describe '#disable_two_factor!' do describe '#disable_two_factor!' do
it 'clears all 2FA-related fields' do it 'clears all 2FA-related fields' do
user = create(:user, :two_factor) user = create(:user, :two_factor)
......
require 'spec_helper'
describe Ci::CreateProjectService do
let(:service) { Ci::CreateProjectService.new }
let(:current_user) { double.as_null_object }
let(:project) { FactoryGirl.create :project }
describe :execute do
context 'valid params' do
subject { service.execute(current_user, project) }
it { is_expected.to be_kind_of(Ci::Project) }
it { is_expected.to be_persisted }
end
context 'without project dump' do
it 'should raise exception' do
expect { service.execute(current_user, '', '') }.
to raise_error(NoMethodError)
end
end
context "forking" do
let(:ci_origin_project) do
FactoryGirl.create(:ci_project, shared_runners_enabled: true, public: true, allow_git_fetch: true)
end
subject { service.execute(current_user, project, ci_origin_project) }
it "uses project as a template for settings and jobs" do
expect(subject.shared_runners_enabled).to be_truthy
expect(subject.public).to be_truthy
expect(subject.allow_git_fetch).to be_truthy
end
end
end
end
...@@ -43,14 +43,10 @@ describe Projects::ForkService do ...@@ -43,14 +43,10 @@ describe Projects::ForkService do
end end
context 'GitLab CI is enabled' do context 'GitLab CI is enabled' do
it "calls fork registrator for CI" do it "fork and enable CI for fork" do
create(:ci_project, gl_project: @from_project) @from_project.enable_ci
@from_project.build_missing_services @to_project = fork_project(@from_project, @to_user)
@from_project.gitlab_ci_service.update_attributes(active: true) expect(@to_project.gitlab_ci?).to be_truthy
expect_any_instance_of(Ci::CreateProjectService).to receive(:execute)
fork_project(@from_project, @to_user)
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment