Merge pull request #230 from joshua-arts/delete_accounts

Add option in settings to delete account.
This commit is contained in:
Joshua Arts 2018-07-27 16:05:06 -04:00 committed by GitHub
commit 8220a09aa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 144 additions and 61 deletions

View File

@ -63,6 +63,9 @@ gem 'http_accept_language'
# Use Capistrano for deployment # Use Capistrano for deployment
# gem 'capistrano-rails', group: :development # gem 'capistrano-rails', group: :development
# Markdown parsing.
gem 'redcarpet'
group :production do group :production do
# Use a postgres database in production. # Use a postgres database in production.
gem 'pg', '~> 0.18' gem 'pg', '~> 0.18'

View File

@ -189,6 +189,7 @@ GEM
rb-fsevent (0.10.3) rb-fsevent (0.10.3)
rb-inotify (0.9.10) rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2) ffi (>= 0.5.0, < 2)
redcarpet (3.4.0)
redis (3.3.5) redis (3.3.5)
ref (2.0.0) ref (2.0.0)
rspec-core (3.7.1) rspec-core (3.7.1)
@ -296,6 +297,7 @@ DEPENDENCIES
puma (~> 3.0) puma (~> 3.0)
rails (~> 5.0.7) rails (~> 5.0.7)
rails-controller-testing rails-controller-testing
redcarpet
redis (~> 3.0) redis (~> 3.0)
rspec-rails (~> 3.7) rspec-rails (~> 3.7)
rubocop rubocop

View File

@ -51,10 +51,6 @@ a {
min-height: calc(100% - #{$header-height} - #{$footer-height}); min-height: calc(100% - #{$header-height} - #{$footer-height});
} }
.flex-center {
transform: translateY(25%);
}
.footer { .footer {
height: $footer-height; height: $footer-height;
width: 100%; width: 100%;
@ -103,5 +99,4 @@ a {
.terms { .terms {
overflow: scroll; overflow: scroll;
height: 55vh; height: 55vh;
white-space: pre-line;
} }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class UsersController < ApplicationController class UsersController < ApplicationController
before_action :find_user, only: [:edit, :update] before_action :find_user, only: [:edit, :update, :destroy]
before_action :ensure_unauthenticated, only: [:new, :create] before_action :ensure_unauthenticated, only: [:new, :create]
# POST /u # POST /u
@ -72,6 +72,15 @@ class UsersController < ApplicationController
end end
end end
# DELETE /u/:user_uid
def destroy
if current_user && current_user == @user
@user.destroy
session.delete(:user_id)
end
redirect_to root_path
end
# GET /u/terms # GET /u/terms
def terms def terms
redirect_to root_path unless current_user redirect_to root_path unless current_user

View File

@ -25,7 +25,22 @@ module ApplicationHelper
Rails.configuration.allow_user_signup Rails.configuration.allow_user_signup
end end
# Determines if the BigBlueButton endpoint is the default.
def bigbluebutton_endpoint_default? def bigbluebutton_endpoint_default?
Rails.configuration.bigbluebutton_endpoint_default == Rails.configuration.bigbluebutton_endpoint Rails.configuration.bigbluebutton_endpoint_default == Rails.configuration.bigbluebutton_endpoint
end end
# Parses markdown for rendering.
def markdown(text)
markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML,
no_intra_emphasis: true,
fenced_code_blocks: true,
disable_indented_code_blocks: true,
autolink: true,
tables: true,
underline: true,
highlight: true)
markdown.render(text).html_safe
end
end end

View File

@ -3,6 +3,8 @@
class Room < ApplicationRecord class Room < ApplicationRecord
before_create :setup before_create :setup
before_destroy :delete_all_recordings
validates :name, presence: true validates :name, presence: true
belongs_to :owner, class_name: 'User', foreign_key: :user_id belongs_to :owner, class_name: 'User', foreign_key: :user_id
@ -155,6 +157,12 @@ class Room < ApplicationRecord
self.bbb_id = Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base] + Time.now.to_i.to_s).to_s self.bbb_id = Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base] + Time.now.to_i.to_s).to_s
end end
# Deletes all recordings associated with the room.
def delete_all_recordings
record_ids = recordings.map { |r| r[:recordID] }
delete_recording(record_ids) unless record_ids.empty?
end
# Generates a three character uid chunk. # Generates a three character uid chunk.
def uid_chunk def uid_chunk
charset = ("a".."z").to_a - %w(b i l o s) + ("2".."9").to_a - %w(5 8) charset = ("a".."z").to_a - %w(b i l o s) + ("2".."9").to_a - %w(5 8)

View File

@ -4,6 +4,8 @@ class User < ApplicationRecord
after_create :initialize_main_room after_create :initialize_main_room
before_save { email.try(:downcase!) } before_save { email.try(:downcase!) }
before_destroy :destroy_rooms
has_many :rooms has_many :rooms
belongs_to :main_room, class_name: 'Room', foreign_key: :room_id, required: false belongs_to :main_room, class_name: 'Room', foreign_key: :room_id, required: false
@ -83,6 +85,11 @@ class User < ApplicationRecord
private private
# Destory a users rooms when they are removed.
def destroy_rooms
rooms.destroy_all
end
# Initializes a room for the user and assign a BigBlueButton user id. # Initializes a room for the user and assign a BigBlueButton user id.
def initialize_main_room def initialize_main_room
self.uid = "gl-#{(0...12).map { (65 + rand(26)).chr }.join.downcase}" self.uid = "gl-#{(0...12).map { (65 + rand(26)).chr }.join.downcase}"

View File

@ -1,16 +1,12 @@
<div class="page mt-0"> <div class="container text-center pt-9">
<div class="page-content mt-0"> <i class="fas fa-database fa-6x mb-4"></i>
<div class="container text-center"> <h1 class="h3 mb-2"><%= t("errors.migration_error.notice").html_safe %></h1>
<i class="fas fa-database fa-6x mb-4"></i> <p class="h4 text-muted font-weight-normal mb-7"><%= t("errors.migration_error.contact_admin") %></p>
<h1 class="h3 mb-2"><%= t("errors.migration_error.notice") %></h1> <h1 class="h3 mb-3"><%= t("errors.migration_error.version") %></h1>
<p class="h4 text-muted font-weight-normal mb-7"><%= t("errors.migration_error.contact_admin") %></p> <a class="btn btn-success mt-3 mx-3" href="http://docs.bigbluebutton.org/install/greenlight-v2.html#upgrading-from-greenlight-10" target="_blank">
<h1 class="h3 mb-3"><%= t("errors.migration_error.version") %></h1> <i class="far fa-star mr-2"></i><%= t("errors.migration_error.upgrade") %>
<a class="btn btn-success mt-3 mx-3" href="http://docs.bigbluebutton.org/install/greenlight-v2.html#upgrading-from-greenlight-10" target="_blank"> </a>
<i class="far fa-star mr-2"></i><%= t("errors.migration_error.upgrade") %> <a class="btn btn-info mt-3 mx-3 w-20" href="http://docs.bigbluebutton.org/install/greenlight-v2.html#remaining-on-greenlight-10" target="_blank">
</a> <i class="far fa-hand-paper mr-2"></i><%= t("errors.migration_error.continue") %>
<a class="btn btn-info mt-3 mx-3 w-20" href="http://docs.bigbluebutton.org/install/greenlight-v2.html#remaining-on-greenlight-10" target="_blank"> </a>
<i class="far fa-hand-paper mr-2"></i><%= t("errors.migration_error.continue") %>
</a>
</div>
</div>
</div> </div>

View File

@ -1,12 +1,8 @@
<div class="page"> <div class="container text-center pt-9">
<div class="page-content"> <div class="display-1 text-muted mb-5">500</div>
<div class="container text-center"> <h1 class="h2 mb-3"><%= t("errors.internal.message") %></h1>
<div class="display-1 text-muted mb-5">500</div> <p class="h4 text-muted font-weight-normal mb-7"><%= t("errors.internal.help") %></p>
<h1 class="h2 mb-3"><%= t("errors.internal.message") %></h1> <a class="btn btn-primary" href="javascript:history.back()">
<p class="h4 text-muted font-weight-normal mb-7"><%= t("errors.internal.help") %></p> <i class="fas fa-arrow-left mr-2"></i><%= t("go_back") %>
<a class="btn btn-primary" href="javascript:history.back()"> </a>
<i class="fas fa-arrow-left mr-2"></i><%= t("go_back") %>
</a>
</div>
</div>
</div> </div>

View File

@ -1,12 +1,8 @@
<div class="page"> <div class="container text-center pt-9">
<div class="page-content"> <div class="display-1 text-muted mb-5">404</div>
<div class="container text-center"> <h1 class="h2 mb-3"><%= t("errors.not_found.message") %></h1>
<div class="display-1 text-muted mb-5">404</div> <p class="h4 text-muted font-weight-normal mb-7"><%= t("errors.not_found.help") %></p>
<h1 class="h2 mb-3"><%= t("errors.not_found.message") %></h1> <a class="btn btn-primary" href="javascript:history.back()">
<p class="h4 text-muted font-weight-normal mb-7"><%= t("errors.not_found.help") %></p> <i class="fas fa-arrow-left mr-2"></i><%= t("go_back") %>
<a class="btn btn-primary" href="javascript:history.back()"> </a>
<i class="fas fa-arrow-left mr-2"></i><%= t("go_back") %>
</a>
</div>
</div>
</div> </div>

View File

@ -1,12 +1,8 @@
<div class="page"> <div class="container text-center pt-9">
<div class="page-content"> <div class="display-1 text-muted mb-5">422</div>
<div class="container text-center"> <h1 class="h2 mb-3"><%= t("errors.unprocessable.message") %></h1>
<div class="display-1 text-muted mb-5">422</div> <p class="h4 text-muted font-weight-normal mb-7"><%= t("errors.unprocessable.help") %></p>
<h1 class="h2 mb-3"><%= t("errors.unprocessable.message") %></h1> <a class="btn btn-primary" href="javascript:history.back()">
<p class="h4 text-muted font-weight-normal mb-7"><%= t("errors.unprocessable.help") %></p> <i class="fas fa-arrow-left mr-2"></i><%= t("go_back") %>
<a class="btn btn-primary" href="javascript:history.back()"> </a>
<i class="fas fa-arrow-left mr-2"></i><%= t("go_back") %>
</a>
</div>
</div>
</div> </div>

View File

@ -0,0 +1,25 @@
<div class="modal fade" id="deleteAccountModal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content text-center">
<div class="modal-body">
<div class="card-body p-6">
<div class="card-title">
<h3><%= t("modal.delete_account.confirm") %></h3>
</div>
<button type="button" class="btn btn-pill btn-info my-1 btn-del-room" data-dismiss="modal">
<%= t("modal.delete_account.keep") %>
</button>
<%= button_to delete_user_path, method: :delete, id: "delete-confirm", class: "btn btn-pill btn-danger my-1 btn-del-room" do %>
<%= t("modal.delete_account.delete") %>
<% end %>
</div>
<div class="card-footer">
<p><%= t("modal.delete_account.warning").html_safe %></p>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,15 @@
<div class="form-group">
<div class="row">
<div class="col-12">
<center>
<%= t("settings.delete.disclaimer").html_safe %>
<br>
<a href="" data-toggle="modal" data-target="#deleteAccountModal" class="btn btn-danger mt-6">
<%= t("settings.delete.button") %>
</a>
</center>
</div>
</div>
</div>
<%= render "shared/modals/delete_account_modal" %>

View File

@ -1,4 +1,4 @@
<div class="container mt-8"> <div class="container pt-8">
<%= render "shared/components/subtitle", subtitle: t("settings.title"), search: false %> <%= render "shared/components/subtitle", subtitle: t("settings.title"), search: false %>
<div class="row"> <div class="row">
@ -17,6 +17,10 @@
<button id="design" class="list-group-item list-group-item-action setting-btn"> <button id="design" class="list-group-item list-group-item-action setting-btn">
<span class="icon mr-3"><i class="fas fa-edit"></i></span><%= t("settings.design.title") %> <span class="icon mr-3"><i class="fas fa-edit"></i></span><%= t("settings.design.title") %>
</button> </button>
<button id="delete" class="list-group-item list-group-item-action setting-btn">
<span class="icon mr-3"><i class="fas fa-trash-alt"></i></span><%= t("settings.delete.title") %>
</button>
</div> </div>
<% if @user.errors.any? %> <% if @user.errors.any? %>
@ -42,6 +46,8 @@
<% end %> <% end %>
<%= render "shared/settings/setting_view", setting_id: "design", setting_title: t("settings.design.subtitle") %> <%= render "shared/settings/setting_view", setting_id: "design", setting_title: t("settings.design.subtitle") %>
<%= render "shared/settings/setting_view", setting_id: "delete", setting_title: t("settings.delete.subtitle") %>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,5 +1,5 @@
<div class="container"> <div class="container">
<div class="row mt-6"> <div class="row pt-7">
<div class="col col-4 offset-4"> <div class="col col-4 offset-4">
<div class="card"> <div class="card">
<div class="card-header background"> <div class="card-header background">

View File

@ -1,4 +1,4 @@
<div class="container mt-5"> <div class="container pt-5">
<div class="col-md-8 offset-2"> <div class="col-md-8 offset-2">
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
@ -6,9 +6,9 @@
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="terms"> <div class="terms">
<p><%= Rails.configuration.terms %></p> <%= markdown(Rails.configuration.terms) %>
</div> </div>
<div class="btn-list mt-4 text-right mt-8"> <div class="btn-list text-right pt-8">
<%= button_to t("terms.accept"), terms_path, params: {accept: true}, class: "btn btn-primary btn-space" %> <%= button_to t("terms.accept"), terms_path, params: {accept: true}, class: "btn btn-primary btn-space" %>
</div> </div>
</form> </form>

View File

@ -2,7 +2,7 @@
# Load terms and conditions. # Load terms and conditions.
terms = "#{Rails.root}/config/terms.txt" terms = "#{Rails.root}/config/terms.md"
Rails.configuration.terms = if File.exist?(terms) Rails.configuration.terms = if File.exist?(terms)
File.read(terms) File.read(terms)

View File

@ -18,6 +18,8 @@ en:
notice: > notice: >
Greenlight encountered a database migration error.<br> Greenlight encountered a database migration error.<br>
This may be because you haven't updated to Greenlight 2.0. This may be because you haven't updated to Greenlight 2.0.
upgrade: Show me how to upgrade to 2.0!
version: We've released a new version of Greenlight, but your database isn't compatible.
not_found: not_found:
message: Whoops! Looks like we can't find that. message: Whoops! Looks like we can't find that.
help: Is it possible its been removed? help: Is it possible its been removed?
@ -61,6 +63,11 @@ en:
name_placeholder: Enter a room name... name_placeholder: Enter a room name...
not_blank: Room name cannot be blank. not_blank: Room name cannot be blank.
title: Create New Room title: Create New Room
delete_account:
confirm: Are you sure you want to delete your account?
delete: I'm sure, delete my account.
keep: Actually, I'll keep it.
warning: This decision is final. You will <b>not</b> be able to recover associated data.
delete_room: delete_room:
confirm: Are you sure you want to delete %{room}? confirm: Are you sure you want to delete %{room}?
delete: I'm sure, delete this room. delete: I'm sure, delete this room.
@ -106,7 +113,12 @@ en:
image: Image image: Image
image_url: Profile Image URL image_url: Profile Image URL
subtitle: Update your Account Info subtitle: Update your Account Info
title: Account title: Account Info
delete:
button: Yes, I would like to delete my account.
disclaimer: If you choose to delete your account, it will <b>NOT</b> be recoverable. All information regarding your account, including settings, rooms, and recording will be removed.
subtitle: Permanently Delete your Account
title: Delete Account
design: design:
not_supported: Customization not currently supported. not_supported: Customization not currently supported.
subtitle: Customize Greenlight subtitle: Customize Greenlight

View File

@ -20,8 +20,10 @@ Rails.application.routes.draw do
# Log the user out of the session. # Log the user out of the session.
get '/logout', to: 'sessions#destroy' get '/logout', to: 'sessions#destroy'
# Account management.
get '/:user_uid/edit', to: 'users#edit', as: :edit_user get '/:user_uid/edit', to: 'users#edit', as: :edit_user
patch '/:user_uid/edit', to: 'users#update', as: :update_user patch '/:user_uid/edit', to: 'users#update', as: :update_user
delete '/:user_uid', to: 'users#destroy', as: :delete_user
end end
# Handles Omniauth authentication. # Handles Omniauth authentication.