Add organization membership functionality to internal (#3541)

This commit is contained in:
Andy Zhao 2019-07-31 14:38:36 -04:00 committed by Mac Siri
parent 5d13752e34
commit 96449fcc8f
15 changed files with 135 additions and 22 deletions

View file

@ -0,0 +1,6 @@
header.internal-edit-header {
display: flex;
h2 {
flex-grow: 1;
}
}

View file

@ -0,0 +1,43 @@
class Internal::OrganizationMembershipsController < Internal::ApplicationController
layout "internal"
def update
organization_membership = OrganizationMembership.find_by(id: params[:id])
if organization_membership.update(organization_membership_params)
flash[:success] = "User was successfully updated to #{organization_membership.type_of_user}"
else
flash[:danger] = organization_membership.errors.full_messages
end
redirect_to internal_user_path(organization_membership.user_id)
end
def create
organization_membership = OrganizationMembership.new(organization_membership_params)
organization = Organization.find_by(id: organization_membership_params[:organization_id])
if organization && organization_membership.save
flash[:success] = "User was successfully added to #{organization.name}"
elsif organization.blank?
flash[:danger] = "Organization ##{organization_membership_params[:organization_id]} does not exist. Perhaps a typo?"
else
flash[:danger] = organization_membership.errors.full_messages
end
redirect_to internal_user_path(organization_membership.user_id)
end
def destroy
organization_membership = OrganizationMembership.find_by(id: params[:id])
if organization_membership.destroy
flash[:success] = "User was successfully removed from org ##{organization_membership.organization_id}"
else
flash[:danger] = "Something wen wrong with removing the user from org ##{organization_membership.organization_id}"
end
redirect_to internal_user_path(organization_membership.user_id)
end
private
def organization_membership_params
allowed_params = %i[type_of_user user_title organization_id user_id]
params.require(:organization_membership).permit(allowed_params)
end
end

View file

@ -4,8 +4,19 @@ class Internal::ToolsController < Internal::ApplicationController
def index; end
def bust_cache
handle_dead_path if params[:dead_link]
handle_user_cache if params[:bust_user]
flash[:success] = if params[:dead_link]
handle_dead_path
"#{params[:dead_link]} was successfully busted"
elsif params[:bust_user]
handle_user_cache
"User ##{params[:bust_user]} was successfully busted"
elsif params[:bust_article]
handle_article_cache
"Article ##{params[:bust_article]} was successfully busted"
end
redirect_to "/internal/tools"
rescue StandardError => e
flash[:danger] = e
redirect_to "/internal/tools"
end
@ -22,7 +33,7 @@ class Internal::ToolsController < Internal::ApplicationController
end
def handle_article_cache
article = User.find(params[:bust_article].to_i)
article = Article.find(params[:bust_article].to_i)
article.touch(:last_commented_at)
CacheBuster.new.bust_article(article)
end

View file

@ -37,9 +37,9 @@ class Internal::UsersController < Internal::ApplicationController
@user = User.find(params[:id])
begin
Moderator::ManageActivityAndRoles.handle_user_roles(admin: current_user, user: @user, user_params: user_params)
flash[:notice] = "User has been udated"
flash[:success] = "User has been updated"
rescue StandardError => e
flash[:error] = e.message
flash[:danger] = e.message
end
redirect_to "/internal/users/#{@user.id}/edit"
end
@ -49,7 +49,7 @@ class Internal::UsersController < Internal::ApplicationController
begin
Moderator::BanishUser.call_banish(admin: current_user, user: @user)
rescue StandardError => e
flash[:error] = e.message
flash[:danger] = e.message
end
redirect_to "/internal/users/#{@user.id}/edit"
end
@ -58,9 +58,9 @@ class Internal::UsersController < Internal::ApplicationController
@user = User.find(params[:id])
begin
Moderator::DeleteUser.call_deletion(admin: current_user, user: @user, user_params: user_params)
flash[:notice] = "@" + @user.username + " (email: " + @user.email + ", user_id: " + @user.id.to_s + ") has been fully deleted. If requested, old content may have been ghostified. If this is a GDPR delete, delete them from Mailchimp & Google Analytics."
flash[:success] = "@" + @user.username + " (email: " + @user.email + ", user_id: " + @user.id.to_s + ") has been fully deleted. If requested, old content may have been ghostified. If this is a GDPR delete, delete them from Mailchimp & Google Analytics."
rescue StandardError => e
flash[:error] = e.message
flash[:danger] = e.message
end
redirect_to "/internal/users"
end
@ -70,7 +70,7 @@ class Internal::UsersController < Internal::ApplicationController
begin
Moderator::MergeUser.call_merge(admin: current_user, keep_user: @user, delete_user_id: user_params["merge_user_id"])
rescue StandardError => e
flash[:error] = e.message
flash[:danger] = e.message
end
redirect_to "/internal/users/#{@user.id}/edit"
end
@ -84,7 +84,7 @@ class Internal::UsersController < Internal::ApplicationController
@user.update("#{identity.provider}_username" => nil)
flash[:success] = "The #{identity.provider.capitalize} identity was successfully deleted and backed up."
rescue StandardError => e
flash[:error] = e.message
flash[:danger] = e.message
end
redirect_to "/internal/users/#{@user.id}/edit"
end
@ -96,7 +96,7 @@ class Internal::UsersController < Internal::ApplicationController
identity = backup.recover!
flash[:success] = "The #{identity.provider} identity was successfully recovered, and the backup was removed."
rescue StandardError => e
flash[:error] = e.message
flash[:danger] = e.message
end
redirect_to "/internal/users/#{@user.id}/edit"
end

View file

@ -9,7 +9,9 @@ class SponsorshipDashboard < Administrate::BaseDashboard
# on pages throughout the dashboard.
ATTRIBUTE_TYPES = {
user: Field::BelongsTo,
user_id: UserIdField,
organization: Field::BelongsTo,
organization_id: Field::Number,
id: Field::Number,
level: Field::String,
status: Field::String,
@ -63,8 +65,8 @@ class SponsorshipDashboard < Administrate::BaseDashboard
# an array of attributes that will be displayed
# on the model's form (`new` and `edit`) pages.
FORM_ATTRIBUTES = %i[
user
organization
user_id
organization_id
level
status
expires_at

View file

@ -4,7 +4,7 @@ class Organization < ApplicationRecord
acts_as_followable
has_many :job_listings
has_many :organization_memberships
has_many :organization_memberships, dependent: :delete_all
has_many :users, through: :organization_memberships
has_many :api_secrets, through: :users
has_many :articles

View file

@ -2,7 +2,7 @@ class ApplicationObserver < ActiveRecord::Observer
def warned_user_ping(activity)
return unless activity.user.warned == true
SlackBotPingJob.perform_later message: "Activity: https://dev.to/#{activity.path}\nManage @#{activity.user.username}: https://dev.to/internal/users/#{activity.user.id}",
SlackBotPingJob.perform_later message: "Activity: https://dev.to#{activity.path}\nManage @#{activity.user.username}: https://dev.to/internal/users/#{activity.user.id}",
channel: "warned-user-comments",
username: "sloan_watch_bot",
icon_emoji: ":sloan:"

View file

@ -0,0 +1,38 @@
<div class="row">
<h3><u>Organization Memberships</u></h3>
<% if @user.organization_memberships.size.positive? %>
<ul>
<% @user.organization_memberships.includes(:organization).each do |org_membership| %>
<li>
<u><b><%= org_membership.type_of_user.capitalize %> of:</b></u>
<a href="<%= org_membership.organization.path %>" target="_blank" rel="noopener">
<%= org_membership.organization.name %>
</a>
<%= form_for [:internal, org_membership] do |f| %>
<%= f.label "Change permission level:" %>
<%= f.select("type_of_user", options_for_select(%w[member admin], selected: org_membership.type_of_user)) %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
<%= form_for([:internal, org_membership], html: { method: :delete, onsubmit: "return confirm('Are you sure you want to remove them from #{org_membership.organization.name}?)" }) do |f| %>
<%= f.submit "Remove from org", class: "btn btn-danger" %>
<% end %>
</li>
<% end %>
</ul>
<% end %>
<h4>Add to New Organization</h4>
<ul>
<%= form_for [:internal, OrganizationMembership.new] do |f| %>
<%= f.hidden_field :user_id, value: @user.id %>
<li>
Organization ID:
<%= f.text_field :organization_id %>
</li>
<li>
Membership Level:
<%= f.select(:type_of_user, options_for_select(%w[member admin])) %>
<%= f.submit "Add to Org", class: "btn btn-primary" %>
</li>
<% end %>
</ul>
</div>

View file

@ -39,8 +39,11 @@
<% end %>
</div>
<%= render "notes" %>
<div class="row">
<header class="internal-edit-header">
<h2>Remove Identity</h2>
<button type="button" data-toggle="collapse" data-target="#identity-row">Toggle</button>
</header>
<div class="row collapse" id="identity-row">
<p>Removing a social account identity can solve certain sign in issues, for example:</p>
<ul>
<li>
@ -66,13 +69,13 @@
<%= form_for(@user, url: remove_identity_internal_user_path(@user), html: { method: :delete, onsubmit: "return confirm('Are you sure? This should only be done as a solution for the listed example(s).)" }) do |f| %>
<%= f.hidden_field :identity_id, value: identity.id %>
<p><b><%= identity.provider.capitalize %> UID: <%= identity.uid %> - Username: <%= identity.auth_data_dump["info"]["nickname"] %></b></p>
<%= f.submit "Delete #{identity.provider.capitalize} Identity" %>
<%= f.submit "Delete #{identity.provider.capitalize} Identity", class: "btn btn-danger" %>
<% end %>
<% end %>
<h3>This should be done only do this if you are certain the user is having the specific problem(s) listed above.</h3>
<hr>
<h2>Recover a deleted identity:</h2>
<% if @user.backup_data %>
<% if @user.backup_data.any? %>
<hr>
<h2>Recover a deleted identity:</h2>
<ul>
<% @user.backup_data.where(instance_type: "Identity").each do |data| %>
<li>

View file

@ -27,6 +27,7 @@
<div>Name</div>
<div>Twitter</div>
<div>GitHub</div>
<div>Email</div>
</div>
<% @users.each do |user| %>
@ -36,6 +37,7 @@
<div class="grid-item"><%= user.name %></div>
<div class="grid-item"><%= user.twitter_username %></div>
<div class="grid-item"><%= user.github_username %></div>
<div class="grid-item"><%= user.email %></div>
</div>
<% end %>
<%= paginate @users %>

View file

@ -44,6 +44,7 @@
<%= render "activity" %>
<%= render "credits" %>
<%= render "notes" %>
<%= render "user_organizations" %>
<div class="row">
<h2><u>Recent Emails</u></h2>
<ul>

View file

@ -63,6 +63,7 @@ Rails.application.routes.draw do
post "recover_identity"
end
end
resources :organization_memberships, only: %i[update destroy create]
resources :welcome, only: %i[index create]
resources :tools, only: %i[index create] do
collection do

View file

@ -43,7 +43,12 @@ User.clear_index!
token: i.to_s,
secret: i.to_s,
user: user,
auth_data_dump: { "extra" => { "raw_info" => { "lang" => "en" } } },
auth_data_dump: {
"extra" => {
"raw_info" => { "lang" => "en" }
},
"info" => { "nickname" => user.username }
},
)
end

View file

@ -5,6 +5,7 @@ RSpec.describe Organization, type: :model do
let(:organization) { create(:organization) }
it { is_expected.to have_many(:sponsorships) }
it { is_expected.to have_many(:organization_memberships).dependent(:delete_all) }
describe "#name" do
it "rejects names with over 50 characters" do

View file

@ -193,7 +193,7 @@ RSpec.describe "Internal::Users", type: :request do
it "expect flash message" do
post "/internal/users/#{user.id}/full_delete", params: { user: { ghostify: "false" } }
expect(request.flash.notice).to include("fully deleted")
expect(request.flash["success"]).to include("fully deleted")
end
end