Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
user: do not allow the update of the portus user
Browse files Browse the repository at this point in the history
The only exception is on the password, that may change depending on
whether the given secret changed or not. For this case, Portus will
always update the password of the portus user on start.

Fixes #1878

Signed-off-by: Miquel Sabaté Solà <[email protected]>
  • Loading branch information
mssola committed Jul 24, 2018
1 parent eaab41d commit b1c803a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 3 deletions.
16 changes: 13 additions & 3 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class User < ActiveRecord::Base
# Actions performed before/after create.
validates :username, presence: true, uniqueness: true
validate :private_namespace_and_team_available, on: :create
validate :portus_user_validation, on: :update
after_create :create_personal_namespace!

# Actions performed before destroy
Expand All @@ -83,16 +84,25 @@ def email_required?
!(Portus::LDAP.enabled? && email.blank?)
end

# Adds an error if the user to be updated is the portus one. This is a
# validation on update, so it can be skipped when strictly required.
def portus_user_validation
return unless portus? || portus?(username_was)
errors.add(:username, "cannot be updated")
end

# It adds an error if the username clashes with either a namespace or a team.
def private_namespace_and_team_available
ns = Namespace.make_valid(username)
return if ns
errors.add(:username, "'#{username}' cannot be transformed into a valid namespace name")
end

# Returns true if the current user is the Portus user.
def portus?
username == "portus"
# Returns true if the current user is the Portus user. You can provide a value
# as an alternative to the value of `username`.
def portus?(field = nil)
f = field.nil? ? username : field
f == "portus"
end

# Returns the username to be displayed.
Expand Down
20 changes: 20 additions & 0 deletions config/initializers/portus_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# This file updates the password of the portus hidden user if this
# exists and the secret is given.

portus_exists = false
begin
portus_exists = User.exists?(username: "portus")
rescue StandardError
# We will ignore any error and skip this initializer. This is done this way
# because it can get really tricky to catch all the myriad of exceptions that
# might be raised on database errors.
portus_exists = false
end

password = Rails.application.secrets.portus_password
if portus_exists && password.present?
portus = User.find_by(username: "portus")
portus&.update_attribute("password", Rails.application.secrets.portus_password)
end
9 changes: 9 additions & 0 deletions spec/api/grape_api/v1/users_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@
expect(response).to have_http_status(:not_found)
end
end

context "portus user" do
it "does not allow portus user to be updated" do
create :user, username: "portus", email: "[email protected]"
portus = User.find_by(username: "portus")
put "/api/v1/users/#{portus.id}", { user: user_data }, @header
expect(response).to have_http_status(:unprocessable_entity)
end
end
end

context "DELETE /api/v1/users/:id" do
Expand Down

0 comments on commit b1c803a

Please sign in to comment.