* Allow user to have many orgs * Allow users to handle multi orgs in settings * Make rounded buttons inline * Add multi org function to dashboards * Fix merge conflicts * Fix mistake in merge conflict fix oops * Display the correct membership level * Fix accessibility issues * Display organizations for article editors * Handle submitting org id with preact editors * Make listings work with multiple organizations * Allow listings to have multiple orgs on create * Display the correct number of credits for each org * Move script tag to Webpack * Allow multi orgs for purchasing and viewing credits * Use OrganizationMembership as authorization check * Display multiple organizations for notifications * Allow dashboard to be viewable under multi-orgs * Remove unused method * Add multi-org functionality for article editors * Show pro dashboard buttons for member+ org levels * Leave the correct organization * Allow article API to change org id * Add left-out authorization method oops * Make nav buttons a bit more clear * Fix merge conflict * Fix adding org id for /api/articles and tests * Fix tests for org policy * Use proper logic for displaying org members * Update org actions with new authorization * Use correct org when creating a listing * Remove additional payment charge oops * Mark org notifications as read with authorization * Remove deprecated post_as_organization attribute * Use new org_admin syntax * Remove deprecated org logic for article create and update * Default all RSS posts to not belong to any org * Render org_member page for guest users * Update org policy spec to work with multi orgs * Use org_membership for org traits and move identity code * Use org_member trait * Update to work with multi-orgs * Validate article's org_id if param org_id is blank * Make a let variable * Remove unnecessary eager load for credits * Fix HTML structure and org logic for non-org users * Update credits spec for multi-org * Add test for failed payment when purchased by org * Lint listings_spec * Test that the listing was created under the user * Add tests for POST /listings multi-org * Use double quotes for classes * Fix /manage and a few other multi-org bugs * Fix test for multi org * Use correct method SQL exists? not Rails exist? * Fix reads spec for multi-org * Fix org_controller actions to work with multi org * Test only multi org and not old usage and fix leave_org * Fix org showing user profile img test for multi-org * Fix org logic for users with no orgs * Remove switch org functionality * Update tests and add hidden param for org id * Redirect to the specific organization * Test other org button actions * Use settings_notice instead of legacy notice and refactor * Fix weird extra end issue prob from merge conflicts * Test for with new flash key * Fix user_views_org tests for multi-org * Test for new flash message * Update snapshot with new a11y html * Move styling to stylesheet * Add site admins functionality * Move org_member? method in user model and refactor * Use unspent_credits_count for organizations * Add tests for /listings/new and minor bug fixes * Use .present? in case of empty array * Fix a lingering deprecated method * Use greater than 1 for random numbers * Add tests for counting spent and unspent credits
243 lines
7.9 KiB
Ruby
243 lines
7.9 KiB
Ruby
class UsersController < ApplicationController
|
|
before_action :set_no_cache_header
|
|
after_action :verify_authorized, except: %i[signout_confirm add_org_admin remove_org_admin remove_from_org]
|
|
|
|
# GET /settings/@tab
|
|
def edit
|
|
unless current_user
|
|
skip_authorization
|
|
return redirect_to "/enter"
|
|
end
|
|
set_user
|
|
set_tabs(params["tab"] || "profile")
|
|
handle_settings_tab
|
|
end
|
|
|
|
# PATCH/PUT /users/:id.:format
|
|
def update
|
|
set_user
|
|
set_tabs(params["user"]["tab"])
|
|
if @user.update(permitted_attributes(@user))
|
|
RssReader.new.delay.fetch_user(@user) if @user.feed_url.present?
|
|
notice = "Your profile was successfully updated."
|
|
if @user.export_requested?
|
|
notice += " The export will be emailed to you shortly."
|
|
ExportContentJob.perform_later(@user.id)
|
|
end
|
|
cookies.permanent[:user_experience_level] = @user.experience_level.to_s if @user.experience_level.present?
|
|
follow_hiring_tag(@user)
|
|
flash[:settings_notice] = notice
|
|
@user.touch(:profile_updated_at)
|
|
redirect_to "/settings/#{@tab}"
|
|
else
|
|
render :edit
|
|
end
|
|
end
|
|
|
|
def update_twitch_username
|
|
set_user
|
|
set_tabs("integrations")
|
|
new_twitch_username = params[:user][:twitch_username]
|
|
if @user.twitch_username != new_twitch_username
|
|
if @user.update(twitch_username: new_twitch_username)
|
|
@user.touch(:profile_updated_at)
|
|
Streams::TwitchWebhookRegistrationJob.perform_later(@user.id) if @user.twitch_username?
|
|
end
|
|
flash[:settings_notice] = "Your Twitch username was successfully updated."
|
|
end
|
|
redirect_to "/settings/#{@tab}"
|
|
end
|
|
|
|
def update_language_settings
|
|
set_user
|
|
set_tabs("misc")
|
|
@user.language_settings["preferred_languages"] = Languages::LIST.keys & params[:user][:preferred_languages].to_a
|
|
if @user.save
|
|
flash[:settings_notice] = "Your language settings were successfully updated."
|
|
@user.touch(:profile_updated_at)
|
|
redirect_to "/settings/#{@tab}"
|
|
else
|
|
render :edit
|
|
end
|
|
end
|
|
|
|
def destroy
|
|
set_user
|
|
set_tabs("account")
|
|
if @user.articles_count.zero? && @user.comments_count.zero?
|
|
@user.destroy!
|
|
NotifyMailer.account_deleted_email(@user).deliver
|
|
flash[:settings_notice] = "Your account has been deleted."
|
|
sign_out @user
|
|
redirect_to root_path
|
|
else
|
|
flash[:error] = "An error occurred. Try requesting an account deletion below."
|
|
redirect_to "/settings/#{@tab}"
|
|
end
|
|
end
|
|
|
|
def remove_association
|
|
set_user
|
|
provider = params[:provider]
|
|
identity = @user.identities.find_by(provider: provider)
|
|
set_tabs("account")
|
|
|
|
if @user.identities.size == 2 && identity
|
|
identity.destroy
|
|
|
|
identity_username = "#{provider}_username".to_sym
|
|
@user.update(identity_username => nil, profile_updated_at: Time.current)
|
|
|
|
flash[:settings_notice] = "Your #{provider.capitalize} account was successfully removed."
|
|
else
|
|
flash[:error] = "An error occurred. Please try again or send an email to: yo@dev.to"
|
|
end
|
|
redirect_to "/settings/#{@tab}"
|
|
end
|
|
|
|
def onboarding_update
|
|
current_user.update(JSON.parse(params[:user]).to_h) if params[:user]
|
|
current_user.saw_onboarding = true
|
|
authorize User
|
|
if current_user.save!
|
|
respond_to do |format|
|
|
format.json { render json: { outcome: "onboarding closed" } }
|
|
end
|
|
else
|
|
respond_to do |format|
|
|
format.json { render json: { outcome: "onboarding opened" } }
|
|
end
|
|
end
|
|
end
|
|
|
|
def join_org
|
|
authorize User
|
|
if (@organization = Organization.find_by(secret: params[:org_secret].strip))
|
|
OrganizationMembership.create(user_id: current_user.id, organization_id: @organization.id, type_of_user: "member")
|
|
flash[:settings_notice] = "You have joined the #{@organization.name} organization."
|
|
redirect_to "/settings/organization/#{@organization.id}"
|
|
else
|
|
flash[:error] = "The given organization secret was invalid."
|
|
redirect_to "/settings/organization/new"
|
|
end
|
|
end
|
|
|
|
def leave_org
|
|
org = Organization.find_by(id: params[:organization_id])
|
|
authorize org
|
|
OrganizationMembership.find_by(organization_id: org.id, user_id: current_user.id)&.delete
|
|
flash[:settings_notice] = "You have left your organization."
|
|
redirect_to "/settings/organization/new"
|
|
end
|
|
|
|
def add_org_admin
|
|
adminable = User.find(params[:user_id])
|
|
org = Organization.find_by(id: params[:organization_id])
|
|
|
|
not_authorized unless current_user.org_admin?(org) && OrganizationMembership.exists?(user: adminable, organization: org)
|
|
|
|
OrganizationMembership.find_by(user_id: adminable.id, organization_id: org.id).update(type_of_user: "admin")
|
|
flash[:settings_notice] = "#{adminable.name} is now an admin."
|
|
redirect_to "/settings/organization/#{org.id}"
|
|
end
|
|
|
|
def remove_org_admin
|
|
unadminable = User.find(params[:user_id])
|
|
org = Organization.find_by(id: params[:organization_id])
|
|
|
|
not_authorized unless current_user.org_admin?(org) && unadminable.org_admin?(org)
|
|
|
|
OrganizationMembership.find_by(user_id: unadminable.id, organization_id: org.id).update(type_of_user: "member")
|
|
flash[:settings_notice] = "#{unadminable.name} is no longer an admin."
|
|
redirect_to "/settings/organization/#{org.id}"
|
|
end
|
|
|
|
def remove_from_org
|
|
removable = User.find(params[:user_id])
|
|
org = Organization.find_by(id: params[:organization_id])
|
|
removable_org_membership = OrganizationMembership.find_by(user_id: removable.id, organization_id: org.id)
|
|
|
|
not_authorized unless current_user.org_admin?(org) && removable_org_membership
|
|
|
|
removable_org_membership.delete
|
|
flash[:settings_notice] = "#{removable.name} is no longer part of your organization."
|
|
redirect_to "/settings/organization/#{org.id}"
|
|
end
|
|
|
|
def signout_confirm; end
|
|
|
|
def follow_hiring_tag(user)
|
|
return unless user.looking_for_work?
|
|
|
|
user.delay.follow(Tag.find_by(name: "hiring"))
|
|
end
|
|
|
|
def handle_settings_tab
|
|
return @tab = "profile" if @tab.blank?
|
|
|
|
case @tab
|
|
when "organization"
|
|
handle_organization_tab
|
|
when "integrations"
|
|
if current_user.identities.where(provider: "github").any?
|
|
@client = Octokit::Client.
|
|
new(access_token: current_user.identities.where(provider: "github").last.token)
|
|
end
|
|
when "billing"
|
|
stripe_code = current_user.stripe_id_code
|
|
return if stripe_code == "special"
|
|
|
|
@customer = Stripe::Customer.retrieve(stripe_code) if stripe_code.present?
|
|
when "membership"
|
|
if current_user.monthly_dues.zero?
|
|
redirect_to "/membership"
|
|
return
|
|
end
|
|
when "account"
|
|
@email_body = <<~HEREDOC
|
|
Hello DEV Team,
|
|
%0A
|
|
%0A
|
|
I would like to delete my dev.to account.
|
|
%0A%0A
|
|
You can keep any comments and discussion posts under the Ghost account.
|
|
%0A
|
|
---OR---
|
|
%0A
|
|
Please delete all my personal information, including comments and discussion posts.
|
|
%0A
|
|
%0A
|
|
Regards,
|
|
%0A
|
|
YOUR-DEV-USERNAME-HERE
|
|
HEREDOC
|
|
else
|
|
not_found unless @tab_list.map { |t| t.downcase.tr(" ", "-") }.include? @tab
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def handle_organization_tab
|
|
@organizations = @current_user.organizations.order("name ASC")
|
|
if params[:org_id] == "new" || params[:org_id].blank? && @organizations.size.zero?
|
|
@organization = Organization.new
|
|
elsif params[:org_id].blank? || params[:org_id].match?(/\d/)
|
|
@organization = Organization.find_by(id: params[:org_id]) || @organizations.first
|
|
authorize @organization, :part_of_org?
|
|
|
|
@org_organization_memberships = @organization.organization_memberships.includes(:user)
|
|
@organization_membership = OrganizationMembership.find_by(user_id: current_user.id, organization_id: @organization.id)
|
|
end
|
|
end
|
|
|
|
def set_user
|
|
@user = current_user
|
|
authorize @user
|
|
end
|
|
|
|
def set_tabs(current_tab = "profile")
|
|
@tab_list = @user.settings_tab_list
|
|
@tab = current_tab
|
|
end
|
|
end
|