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

Commit

Permalink
Implemented user removal
Browse files Browse the repository at this point in the history
Fixes #198

Signed-off-by: Miquel Sabaté Solà <[email protected]>
  • Loading branch information
mssola committed Sep 1, 2016
1 parent 3499bae commit d9d6e3a
Show file tree
Hide file tree
Showing 59 changed files with 293 additions and 82 deletions.
5 changes: 4 additions & 1 deletion app/assets/stylesheets/images.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ i.user-picture {
padding-top: 5px;
}

.activitie-container .user-picture {
margin-right: 0;
}

.user-picture {
background-color: #fff;
display: inline-block;
Expand All @@ -18,4 +22,3 @@ i.user-picture {
border: 4px solid darken($header-user-bg, 15%);
border-radius: 100px;
}

19 changes: 18 additions & 1 deletion app/controllers/admin/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Admin::UsersController < Admin::BaseController
respond_to :html, :js
before_action :another_user_access, only: [:edit, :update]
before_action :another_user_access, only: [:edit, :update, :destroy]

def index
@users = User.not_portus.page(params[:page])
Expand Down Expand Up @@ -42,6 +42,23 @@ def update
end
end

# DELETE /admin/user/:id
def destroy
return if @user.nil?

PublicActivity::Activity.where(owner_id: @user.id).update_all(
owner_id: nil,
owner_type: nil,
parameters: { owner_name: @user.username }
)
@user.create_activity :delete,
owner: current_user,
parameters: { username: @user.username }
@user.destroy!

redirect_to admin_users_path, notice: "User removed successfully", float: true
end

# PATCH/PUT /admin/user/1/toggle_admin
def toggle_admin
user = User.find(params[:id])
Expand Down
13 changes: 13 additions & 0 deletions app/helpers/activities_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Common methods for activities used in other helpers.
module ActivitiesHelper
# Returns a string containing the username of the owner of the activity.
def activity_owner(activity)
if activity.owner
activity.owner.display_username
elsif activity.parameters[:owner_name].blank?
"Someone"
else
activity.parameters[:owner_name]
end
end
end
6 changes: 5 additions & 1 deletion app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
module ApplicationHelper
include ActivitiesHelper

# Render the user profile picture depending on the gravatar configuration.
def user_image_tag(email)
def user_image_tag(owner)
email = owner.nil? ? nil : owner.email

if APP_CONFIG.enabled?("gravatar") && !email.nil? && !email.empty?
gravatar_image_tag(email)
else
Expand Down
9 changes: 3 additions & 6 deletions app/helpers/repositories_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# them, dangling repositories that used to contain them. Because of this, this
# helper renders the proper HTML for push activities, while being safe at it.
module RepositoriesHelper
include ActivitiesHelper

# Renders a push activity, that is, a repository/tag has been pushed.
def render_push_activity(activity)
render_repo_activity(activity, "pushed")
Expand All @@ -22,19 +24,14 @@ def can_destroy?(repository)

# General method for rendering an activity regarding repositories.
def render_repo_activity(activity, action)
owner = content_tag(:strong, "#{fetch_owner(activity)} #{action} ")
owner = content_tag(:strong, "#{activity_owner(activity)} #{action} ")

namespace = render_namespace(activity)
namespace += " / " unless namespace.empty?

owner + namespace + render_repository(activity)
end

# Fetches the owner of the activity in a safe way.
def fetch_owner(activity)
activity.owner.nil? ? "Someone" : activity.owner.username
end

# Renders the namespace part of the activity in a safe manner. If the
# namespace still exists, it will be taken as the target for the created
# link. Otherwise, it will try to fetch the name of the namespace and put it
Expand Down
12 changes: 12 additions & 0 deletions app/models/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# digest :string(255)
# image_id :string(255) default("")
# marked :boolean default("0")
# username :string(255)
#
# Indexes
#
Expand All @@ -30,6 +31,17 @@ class Tag < ActiveRecord::Base
# and that's guaranteed to have a good format.
validates :name, uniqueness: { scope: "repository_id" }

# Returns a string containing the username of the user that pushed this tag.
def owner
if author
author.display_username
elsif username.blank?
"someone"
else
username
end
end

# Delete all the tags that match the given digest. Call this method if you
# want to:
#
Expand Down
10 changes: 10 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#

class User < ActiveRecord::Base
include PublicActivity::Common

devise :database_authenticatable, :registerable, :lockable,
:recoverable, :rememberable, :trackable, :validatable, authentication_keys: [:username]

Expand All @@ -44,6 +46,9 @@ class User < ActiveRecord::Base
validate :private_namespace_and_team_available, on: :create
after_create :create_personal_namespace!

# Actions performed before destroy
before_destroy :update_tags!

belongs_to :namespace
has_many :team_users
has_many :teams, through: :team_users
Expand Down Expand Up @@ -178,6 +183,11 @@ def application_token_valid?(plain_token)
false
end

# Update the tags owned by this user before this user gets destroyed.
def update_tags!
Tag.where(user_id: id).update_all(user_id: nil, username: username)
end

protected

# Returns whether the given user can be disabled or not. The following rules
Expand Down
21 changes: 20 additions & 1 deletion app/views/admin/users/edit.html.slim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.panel.panel-default
.panel-heading
h5 Edit User
h5 <b>Edit</b> #{@user.display_username}
.panel-body
= form_for [:admin, @user], html: {class: 'form-horizontal', role: 'form'} do |f|
.form-group
Expand All @@ -18,3 +18,22 @@
.col-md-offset-2.col-md-7
= f.submit('Update', class: 'btn btn-primary')

.panel.panel-default
.panel-heading
h5 <b>Remove</b> #{@user.display_username}
.panel-body
= form_for @user, url: admin_user_path(@user), method: :delete, html: {id: "delete_user_#{@user.id}", class: 'form-horizontal', role: "form"} do |f|
.form-group
.col-md-offset-2.col-md-7
p
| As an administrator, you can remove this user. That being said, be aware that doing this has its consequences:
ul
li
| The namespace and the repositories of this user won't be removed. You will still be able to access them and manage them.
li
| The user will be lost forever, so you won't be able to recover the data.
p
| With this in mind, if you want to remove this user, just click the button below.
.form-group
.col-md-offset-2.col-md-7
= f.submit('Remove', class: 'btn btn-danger')
21 changes: 19 additions & 2 deletions app/views/admin/users/index.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
.panel-body
.table-responsive
table.table.table-stripped.table-hover
col.col-20
col.col-30
col.col-30
col.col-10
col.col-10
col.col-10
col.col-10
Expand All @@ -25,6 +26,7 @@
th Namespaces
th Teams
th Enabled
th Remove
tbody
- @users.each do |user|
tr[id="user_#{user.id}"]
Expand All @@ -45,7 +47,7 @@
href=url_for(toggle_admin_admin_user_path(user))]
i.fa.fa-lg[class="fa-toggle-#{user.admin? ? 'on': 'off'}"]

td= user.teams.reduce(0){ |sum, t| sum += t.namespaces.count}
td= user.teams.reduce(0) { |sum, t| sum += t.namespaces.count}
td= user.teams.all_non_special.count
td.enabled-btn
- if current_user.id == user.id && @admin_count == 1
Expand All @@ -57,4 +59,19 @@
rel="nofollow"
href=url_for(toggle_enabled_path(user))]
i.fa.fa-lg[class="fa-toggle-#{user.enabled? ? 'on': 'off'}"]
td.remove-btn
- if current_user == user
a[class="btn btn-default" disabled=true]
i.fa.fa-trash.fa-lg
- else
a[class="btn btn-default"
data-placement="left"
data-toggle="popover"
data-title="Please confirm"
data-content='<p>Are you sure you want to remove this user?</p><a class="btn btn-default">No</a> <a class="btn btn-primary btn-confirm-remove" data-method="delete" rel="nofollow" href="#{admin_user_path(user)}">Yes</a>'
data-html="true"
tabindex="0"
role="button"
]
i.fa.fa-trash.fa-lg
.panel-footer= paginate(@users)
2 changes: 1 addition & 1 deletion app/views/comments/_comment.html.slim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.comment-row id="comment_#{comment.id}"
.comment-thumbnail
.user-image
= user_image_tag(comment.author.email)
= user_image_tag(comment.author)
.comment-content
.row
.col-xs-8
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
= CSV.generate_line(["application token", "#{activity.parameters[:application]}", "create", "-", activity.owner.display_username, activity.created_at, "-"])
= CSV.generate_line(["application token", "#{activity.parameters[:application]}", "create", "-", activity_owner(activity), activity.created_at, "-"])
4 changes: 2 additions & 2 deletions app/views/public_activity/application_token/_create.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ li
.activity-type.application-token-created
i.fa.fa-key
.user-image
= user_image_tag(activity.owner.email)
= user_image_tag(activity.owner)
.description
h6
strong
= "#{activity.owner.display_username} created a token"
= "#{activity_owner(activity)} created a token"
= " for the application "
strong
= activity.parameters[:application]
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
= CSV.generate_line(["application token", "#{activity.parameters[:application]}", "destroy", "-", activity.owner.display_username, activity.created_at, "-"])
= CSV.generate_line(["application token", "#{activity.parameters[:application]}", "destroy", "-", activity_owner(activity), activity.created_at, "-"])
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ li
.activity-type.application-token-destroyed
i.fa.fa-key
.user-image
= user_image_tag(activity.owner.email)
= user_image_tag(activity.owner)
.description
h6
strong
= "#{activity.owner.display_username} removed the token"
= "#{activity_owner(activity)} removed the token"
= " for the application "
strong
= activity.parameters[:application]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
activity.trackable.name,
'change the description of the namespace',
activity.recipient.name,
activity.owner.display_username,
activity_owner(activity),
activity.created_at,
"from #{activity.parameters[:old_description]} to \
#{activity.parameters[:new_description]}"])
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ li
.activity-type.change-description
i.fa.fa-list-alt
.user-image
= user_image_tag(activity.owner.email)
= user_image_tag(activity.owner)
.description
h6
- if activity.parameters[:new].blank?
strong
= "#{activity.owner.display_username} deleted the description of the namespace "
= "#{activity_owner(activity)} deleted the description of the namespace "
- else
strong
= "#{activity.owner.display_username} edited the description of the namespace "
= "#{activity_owner(activity)} edited the description of the namespace "
= link_to activity.trackable.name, activity.trackable
small
i.fa.fa-clock-o
Expand Down
2 changes: 1 addition & 1 deletion app/views/public_activity/namespace/_change_team.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ li
.activity-type.change-team
i.fa.fa-arrow-right
.user-image
= user_image_tag(activity.owner.email)
= user_image_tag(activity.owner)
.description
h6
strong
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
= CSV.generate_line(['namespace', activity.trackable.name, 'change visibility', '-', activity.owner.display_username, activity.created_at, "is #{activity.parameters[:visibility].sub('visibility_', '')}"])
= CSV.generate_line(['namespace', activity.trackable.name, 'change visibility', '-', activity_owner(activity), activity.created_at, "is #{activity.parameters[:visibility].sub('visibility_', '')}"])
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ li
.activity-type.change-namespace-visibility
i.fa.fa-unlock
.user-image
= user_image_tag(activity.owner.email)
= user_image_tag(activity.owner)
.description
h6
strong
= "#{activity.owner.display_username} set the "
= "#{activity_owner(activity)} set the "
= link_to activity.trackable.name, activity.trackable
= " namespace as #{activity.parameters[:visibility].sub('visibility_', '')}"
small
Expand Down
2 changes: 1 addition & 1 deletion app/views/public_activity/namespace/_create.csv.slim
Original file line number Diff line number Diff line change
@@ -1 +1 @@
= CSV.generate_line(['namespace', activity.trackable.name, 'create', '-', activity.owner.display_username, activity.created_at, "owned by team #{activity.trackable.team.name}"])
= CSV.generate_line(['namespace', activity.trackable.name, 'create', '-', activity_owner(activity), activity.created_at, "owned by team #{activity.trackable.team.name}"])
4 changes: 2 additions & 2 deletions app/views/public_activity/namespace/_create.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ li
.activity-type.create-namespace
i.fa.fa-ship
.user-image
= user_image_tag(activity.owner.email)
= user_image_tag(activity.owner)
.description
h6
strong
= "#{activity.owner.display_username} created the "
= "#{activity_owner(activity)} created the "
= link_to activity.trackable.name , activity.trackable
= " namespace under the "
= link_to activity.trackable.team.name, activity.trackable.team
Expand Down
4 changes: 2 additions & 2 deletions app/views/public_activity/namespace/_delete.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ li
.activity-type.repo-deleted
i.fa.fa-ship
.user-image
= user_image_tag(activity.owner.email)
= user_image_tag(activity.owner)
.description
h6
strong
= " #{activity.owner.display_username} deleted "
= " #{activity_owner(activity)} deleted "
- if activity.parameters[:repository_name]
= link_to activity.trackable.clean_name, activity.trackable
= " / #{activity.parameters[:repository_name]}"
Expand Down
2 changes: 1 addition & 1 deletion app/views/public_activity/namespace/_private.csv.slim
Original file line number Diff line number Diff line change
@@ -1 +1 @@
= CSV.generate_line(['namespace', activity.trackable.name, 'make private', '-', activity.owner.display_username, activity.created_at, '-'])
= CSV.generate_line(['namespace', activity.trackable.name, 'make private', '-', activity_owner(activity), activity.created_at, '-'])
4 changes: 2 additions & 2 deletions app/views/public_activity/namespace/_private.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ li
.activity-type.change-namespace-visibility
i.fa.fa-lock
.user-image
= user_image_tag(activity.owner.email)
= user_image_tag(activity.owner)
.description
h6
strong
= "#{activity.owner.display_username} set the "
= "#{activity_owner(activity)} set the "
= link_to activity.trackable.name, activity.trackable
= " namespace as private"
small
Expand Down
2 changes: 1 addition & 1 deletion app/views/public_activity/namespace/_public.csv.slim
Original file line number Diff line number Diff line change
@@ -1 +1 @@
= CSV.generate_line(['namespace', activity.trackable.name, 'make public', '-', activity.owner.display_username, activity.created_at, '-'])
= CSV.generate_line(['namespace', activity.trackable.name, 'make public', '-', activity_owner(activity), activity.created_at, '-'])
Loading

0 comments on commit d9d6e3a

Please sign in to comment.