Skip to content

Commit

Permalink
GRN2-6: Added the ability for admins to specify registration method (b…
Browse files Browse the repository at this point in the history
…igbluebutton#520)

* Added the ability to invite users

* Small bug fix

* Added the ability to approve/decline users

* Small bug fixes

* More bug fixes

* More minor changes

* Final changes
  • Loading branch information
farhatahmad authored and jfederico committed May 17, 2019
1 parent 3855074 commit 02d5465
Show file tree
Hide file tree
Showing 37 changed files with 927 additions and 100 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -35,6 +35,8 @@ env
# IDEs
.idea
.idea/**
.vscode
.vscode/**

config/terms.md
coverage*
4 changes: 4 additions & 0 deletions .rubocop.yml
Expand Up @@ -41,6 +41,10 @@ Style/MixinUsage:
Style/SymbolArray:
Enabled: false

# Don't use begin blocks when they are not needed.
Style/RedundantBegin:
Enabled: false

# Use `%`-literal delimiters consistently
Style/PercentLiteralDelimiters:
Enabled: false
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Expand Up @@ -215,7 +215,7 @@ GEM
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
rake (12.3.1)
rake (12.3.2)
random_password (0.1.1)
rb-fsevent (0.10.3)
rb-inotify (0.9.10)
Expand Down
3 changes: 2 additions & 1 deletion app/assets/javascripts/header.js
Expand Up @@ -17,7 +17,8 @@
$(document).on('turbolinks:load', function(){
// Stores the current url when the user clicks the sign in button
$(".sign-in-button").click(function(){
document.cookie ="return_to=" + window.location.href
var url = [location.protocol, '//', location.host, location.pathname].join('');
document.cookie ="return_to=" + url
})

// Checks to see if the user provided an image url and displays it if they did
Expand Down
10 changes: 8 additions & 2 deletions app/assets/stylesheets/utilities/_primary_themes.scss
Expand Up @@ -9,14 +9,20 @@
.btn-primary:active,
.btn-primary:active:focus,
.btn-primary:active:hover,
.btn-primary:focus,
.btn-primary:hover,
.btn-primary:hover i {
background-color: $primary-color-darken !important;
border-color: $primary-color-darken !important;
color: white !important;
}

.btn-primary:focus {
background-color: $primary-color-darken !important;
border-color: $primary-color-darken !important;
color: white !important;
box-shadow: 0 0 0 2px $primary-color-lighten !important;
}

a {
color: $primary-color !important;
}
Expand All @@ -39,7 +45,7 @@ a {
}

&:focus {
box-shadow: 0 0 0 2px $primary-color-lighten;
box-shadow: 0 0 0 2px $primary-color-lighten !important;
}
}

Expand Down
4 changes: 4 additions & 0 deletions app/controllers/account_activations_controller.rb
Expand Up @@ -32,6 +32,10 @@ def edit
if @user && !@user.activated? && @user.authenticated?(:activation, params[:token])
@user.activate

# Redirect user to root with account pending flash if account is still pending
return redirect_to root_path,
flash: { success: I18n.t("registration.approval.signup") } if @user.has_role?(:pending)

flash[:success] = I18n.t("verify.activated") + " " + I18n.t("verify.signin")
redirect_to signin_path
else
Expand Down
121 changes: 97 additions & 24 deletions app/controllers/admins_controller.rb
Expand Up @@ -18,30 +18,27 @@

class AdminsController < ApplicationController
include Pagy::Backend
include Emailer

manage_users = [:edit_user, :promote, :demote, :ban_user, :unban_user, :approve]
site_settings = [:branding, :coloring, :registration_method]

authorize_resource class: false
before_action :find_user, only: [:edit_user, :promote, :demote, :ban_user, :unban_user]
before_action :verify_admin_of_user, only: [:edit_user, :promote, :demote, :ban_user, :unban_user]
before_action :find_setting, only: [:branding, :coloring]
before_action :find_user, only: manage_users
before_action :verify_admin_of_user, only: manage_users
before_action :find_setting, only: site_settings

# GET /admins
def index
@search = params[:search] || ""
@order_column = params[:column] && params[:direction] != "none" ? params[:column] : "created_at"
@order_direction = params[:direction] && params[:direction] != "none" ? params[:direction] : "DESC"

if Rails.configuration.loadbalanced_configuration
@pagy, @users = pagy(User.without_role(:super_admin)
.where(provider: user_settings_provider)
.where.not(id: current_user.id)
.admins_search(@search)
.admins_order(@order_column, @order_direction))
else
@pagy, @users = pagy(User.where.not(id: current_user.id)
.admins_search(@search)
.admins_order(@order_column, @order_direction))
end
@pagy, @users = pagy(user_list)
end

# MANAGE USERS

# GET /admins/edit/:user_uid
def edit_user
render "admins/index", locals: { setting_id: "account" }
Expand All @@ -59,6 +56,48 @@ def demote
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.demoted") }
end

# POST /admins/ban/:user_uid
def ban_user
@user.remove_role :pending if @user.has_role? :pending
@user.add_role :denied
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.banned") }
end

# POST /admins/unban/:user_uid
def unban_user
@user.remove_role :denied
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.unbanned") }
end

# POST /admins/approve/:user_uid
def approve
@user.remove_role :pending

send_user_approved_email(@user)

redirect_to admins_path, flash: { success: I18n.t("administrator.flash.approved") }
end

# POST /admins/invite
def invite
email = params[:invite_user][:email]

begin
invitation = create_or_update_invite(email)

send_invitation_email(current_user.name, email, invitation.invite_token)
rescue => e
logger.error "Error in email delivery: #{e}"
flash[:alert] = I18n.t(params[:message], default: I18n.t("delivery_error"))
else
flash[:success] = I18n.t("administrator.flash.invite", email: email)
end

redirect_to admins_path
end

# SITE SETTINGS

# POST /admins/branding
def branding
@settings.update_value("Branding Image", params[:url])
Expand All @@ -68,19 +107,22 @@ def branding
# POST /admins/color
def coloring
@settings.update_value("Primary Color", params[:color])
redirect_to admins_path(setting: "site_settings")
redirect_to admins_path
end

# POST /admins/ban/:user_uid
def ban_user
@user.add_role :denied
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.banned") }
end
# POST /admins/registration_method/:method
def registration_method
new_method = Rails.configuration.registration_methods[params[:method].to_sym]

# POST /admins/unban/:user_uid
def unban_user
@user.remove_role :denied
redirect_to admins_path, flash: { success: I18n.t("administrator.flash.unbanned") }
# Only allow change to Join by Invitation if user has emails enabled
if !Rails.configuration.enable_email_verification && new_method == Rails.configuration.registration_methods[:invite]
redirect_to admins_path,
flash: { alert: I18n.t("administrator.flash.invite_email_verification") }
else
@settings.update_value("Registration Method", new_method)
redirect_to admins_path,
flash: { success: I18n.t("administrator.flash.registration_method_updated") }
end
end

private
Expand All @@ -97,4 +139,35 @@ def verify_admin_of_user
redirect_to admins_path,
flash: { alert: I18n.t("administrator.flash.unauthorized") } unless current_user.admin_of?(@user)
end

# Gets the list of users based on your configuration
def user_list
if Rails.configuration.loadbalanced_configuration
User.without_role(:super_admin)
.where(provider: user_settings_provider)
.where.not(id: current_user.id)
.admins_search(@search)
.admins_order(@order_column, @order_direction)
else
User.where.not(id: current_user.id)
.admins_search(@search)
.admins_order(@order_column, @order_direction)
end
end

# Creates the invite if it doesn't exist, or updates the updated_at time if it does
def create_or_update_invite(email)
invite = Invitation.find_by(email: email, provider: @user_domain)

# Invite already exists
if invite.present?
# Updates updated_at to now
invite.touch
else
# Creates invite
invite = Invitation.create(email: email, provider: @user_domain)
end

invite
end
end
16 changes: 10 additions & 6 deletions app/controllers/application_controller.rb
Expand Up @@ -19,14 +19,15 @@
require 'bigbluebutton_api'

class ApplicationController < ActionController::Base
include ApplicationHelper
include SessionsHelper
include ThemingHelper

before_action :migration_error?
before_action :set_locale
before_action :check_admin_password
before_action :set_user_domain
before_action :check_if_unbanned
before_action :check_user_role

# Force SSL for loadbalancer configurations.
before_action :redirect_to_https
Expand Down Expand Up @@ -84,7 +85,7 @@ def recording_thumbnails?
helper_method :recording_thumbnails?

def allow_greenlight_users?
Rails.configuration.greenlight_accounts
allow_greenlight_accounts?
end
helper_method :allow_greenlight_users?

Expand Down Expand Up @@ -136,11 +137,14 @@ def set_user_domain
helper_method :set_user_domain

# Checks if the user is banned and logs him out if he is
def check_if_unbanned
if current_user&.has_role?(:denied)
def check_user_role
if current_user&.has_role? :denied
session.delete(:user_id)
redirect_to unauthorized_path
redirect_to root_path, flash: { alert: I18n.t("registration.banned.fail") }
elsif current_user&.has_role? :pending
session.delete(:user_id)
redirect_to root_path, flash: { alert: I18n.t("registration.approval.fail") }
end
end
helper_method :check_if_unbanned
helper_method :check_user_role
end
24 changes: 22 additions & 2 deletions app/controllers/concerns/emailer.rb
Expand Up @@ -31,12 +31,32 @@ def send_password_reset_email(user)
UserMailer.password_reset(@user, reset_link, logo_image, user_color).deliver_now
end

# Sends inivitation to join
def send_invitation_email(name, email, token)
@token = token
UserMailer.invite_email(name, email, invitation_link, logo_image, user_color).deliver_now
end

def send_user_approved_email(user)
UserMailer.approve_user(user, root_url, logo_image, user_color).deliver_now
end

private

# Returns the link the user needs to click to verify their account
def user_verification_link
request.base_url + edit_account_activation_path(token: @user.activation_token, email: @user.email)
edit_account_activation_url(token: @user.activation_token, email: @user.email)
end

def reset_link
request.base_url + edit_password_reset_path(@user.reset_token, email: @user.email)
edit_password_reset_url(@user.reset_token, email: @user.email)
end

def invitation_link
if allow_greenlight_users?
signup_url(invite_token: @token)
else
root_url(invite_token: @token)
end
end
end
54 changes: 54 additions & 0 deletions app/controllers/concerns/registrar.rb
@@ -0,0 +1,54 @@
# frozen_string_literal: true

# BigBlueButton open source conferencing system - http://www.bigbluebutton.org/.
#
# Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
#
# This program is free software; you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free Software
# Foundation; either version 3.0 of the License, or (at your option) any later
# version.
#
# BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.

module Registrar
extend ActiveSupport::Concern

def registration_method
Setting.find_or_create_by!(provider: user_settings_provider).get_value("Registration Method")
end

def open_registration
registration_method == Rails.configuration.registration_methods[:open]
end

def approval_registration
registration_method == Rails.configuration.registration_methods[:approval]
end

def invite_registration
registration_method == Rails.configuration.registration_methods[:invite]
end

# Returns a hash containing whether the user has been invited and if they
# signed up with the same email that they were invited with
def check_user_invited(email, token, domain)
return { present: true, verified: false } unless invite_registration
return { present: false, verified: false } if token.nil?

invite = Invitation.valid.find_by(invite_token: token, provider: domain)
if invite.present?
# Check if they used the same email to sign up
same_email = email.casecmp(invite.email).zero?
invite.destroy
{ present: true, verified: same_email }
else
{ present: false, verified: false }
end
end
end
3 changes: 3 additions & 0 deletions app/controllers/main_controller.rb
Expand Up @@ -17,7 +17,10 @@
# with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.

class MainController < ApplicationController
include Registrar
# GET /
def index
# Store invite token
session[:invite_token] = params[:invite_token] if params[:invite_token] && invite_registration
end
end

0 comments on commit 02d5465

Please sign in to comment.