Commit e3588e8c authored by Taico Aerts's avatar Taico Aerts
Browse files

Merge branch 'development' into 214-a-page-for-submitting-internship-offers

parents 39c32db7 0828624c
......@@ -36,6 +36,7 @@ dependency-check-report.html
# Ignore file uploads
/public/system/**/*
/private/uploads/*
# Ignore PDF file generated by rails-erd
erd.pdf
......
1. Give a short description of the bug
2. Explain the steps you took to trigger the bug
3. What is the *expected* behavior?
4. What is the *actual* behavior?
1. Please provide a description of the feature you would like to see added.
2. To which users would this feature be relevant? (All / Students / Coordinators / External / Coaches / Clients / ...)
......@@ -36,7 +36,6 @@ install_plugin Capistrano::SCM::Git
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/passenger/no_hook'
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
......@@ -40,7 +40,7 @@ gem 'image_processing', '>= 1.2'
# Mysql for production, sqlite for development
gem 'sqlite3', group: %i[development test]
gem 'mysql2', group: :production
gem 'mysql2', group: %i[production staging]
# Implement multiple-table-inheritance(MTI) for tables alike projects and internships
gem 'active_record-acts_as'
......@@ -233,9 +233,6 @@ end
group :development do
gem 'capistrano', '~> 3.16', require: false
# Ran as separate service, so gem not needed
gem 'capistrano-passenger', '~> 0.2', require: false
# Rails (db migrations and assets) support
gem 'capistrano-rails', '~> 1.6', require: false
......
......@@ -118,8 +118,8 @@ GEM
sshkit (>= 1.6.1, != 1.7.0)
ansi (1.5.0)
ast (2.4.2)
autoprefixer-rails (10.2.5.1)
execjs (> 0)
autoprefixer-rails (10.3.1.0)
execjs (~> 2)
bcrypt (3.1.16)
bindex (0.8.1)
bootstrap-kaminari-views (0.0.5)
......@@ -149,8 +149,6 @@ GEM
capistrano (~> 3.1)
capistrano-locally (0.2.7)
capistrano (~> 3.0)
capistrano-passenger (0.2.1)
capistrano (~> 3.0)
capistrano-rails (1.6.1)
capistrano (~> 3.1)
capistrano-bundler (>= 1.1, < 3)
......@@ -209,7 +207,7 @@ GEM
execjs (2.8.1)
faker (2.18.0)
i18n (>= 1.6, < 2)
faraday (1.5.1)
faraday (1.6.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
......@@ -217,6 +215,7 @@ GEM
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
multipart-post (>= 1.2, < 3)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
......@@ -226,11 +225,12 @@ GEM
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
ffi (1.15.3)
font-awesome-sass (5.15.1)
sassc (>= 1.11)
generator (0.0.1)
globalid (0.5.1)
globalid (0.5.2)
activesupport (>= 5.0)
hashie (4.1.0)
htmlentities (4.3.4)
......@@ -280,7 +280,7 @@ GEM
listen (3.6.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.10.0)
loofah (2.11.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
......@@ -308,7 +308,7 @@ GEM
net-ssh (>= 2.6.5, < 7.0.0)
net-ssh (6.1.0)
nio4r (2.5.7)
nokogiri (1.11.7-x86_64-linux)
nokogiri (1.12.0-x86_64-linux)
racc (~> 1.4)
orm_adapter (0.5.0)
paper_trail (11.1.0)
......@@ -508,7 +508,6 @@ DEPENDENCIES
cancancan
capistrano (~> 3.16)
capistrano-locally
capistrano-passenger (~> 0.2)
capistrano-rails (~> 1.6)
capybara (~> 3.18)
caxlsx
......
module Admin
##
# The super class for all controllers for the admin interface.
class ApplicationController < ActionController::Base
include Notifyable
......@@ -7,7 +6,9 @@ module Admin
protect_from_forgery with: :exception
# Before any action happens, do the following (in this order):
before_action :authenticate_user!
before_action :set_sentry_context
before_action :check_access_to_admin!
check_authorization unless: :devise_controller?
helper_method :page_title
......@@ -22,7 +23,14 @@ module Admin
layout: false
end
##
# Identifies the +current_user+ to sentry
def set_sentry_context
return unless signed_in?
Sentry.set_user(email: current_user.email)
Sentry.set_tags('management panel': true)
end
# Checks whether the +current_user+ has acces to view the admin interface.
def check_access_to_admin!
return if current_user.access_to_admin?
......
......@@ -7,20 +7,15 @@ module Admin
add_breadcrumb ThemeAssociatedUser.model_name.human(count: 2), :admin_theme_associated_users_path
def create
@theme = Theme.find_by(id: theme_associated_user_params[:theme_id])
raise(ActionController::BadRequest.new, 'Theme not found') if @theme.nil?
authorize! :update, @theme
@theme_associated_user = ThemeAssociatedUser.create theme_associated_user_params
if @theme_associated_user.persisted?
respond_to do |format|
format.html do
flash[:success] = 'Succesfully added the associated user'
redirect_to admin_theme_url(@theme_associated_user.theme_id)
end
format.js do
render plain: "
Turbolinks.visit(window.location);
"
end
end
flash[:success] = 'Succesfully added the associated user'
redirect_to admin_theme_url(@theme_associated_user.theme_id)
else
respond_to do |format|
format.html do
......@@ -44,7 +39,6 @@ module Admin
format.js do
render plain: "
$(\"[data-item]#theme_associated_user-#{@theme_associated_user.id}\").remove();
Turbolinks.visit(window.location);
"
end
end
......
......@@ -4,104 +4,21 @@ module Admin
load_and_authorize_resource
add_breadcrumb ThemeInterest.model_name.human(count: 2), :admin_theme_associated_users_path
def index; end
def create
@theme_interest = ThemeInterest.create theme_interest_params
if @theme_interest.persisted?
respond_to do |format|
format.html do
flash[:success] = "Succesfully added the interested researcher"
redirect_to admin_theme_url(@theme_interest.theme_id)
end
format.js do
render plain: "
Turbolinks.visit(window.location);
"
end
end
else
respond_to do |format|
format.html do
flash[:danger] = "Failed to add the interested researcher"
redirect_to admin_theme_url(@theme_interest.theme_id)
end
format.js do
render plain: "alert(\"Failed to add the interested researcher\");"
end
end
end
end
def destroy
if @theme_interest.destroy
respond_to do |format|
format.html do
flash[:success] = 'Succesfully removed the interested researcher'
redirect_to admin_theme_url(@theme_interest.theme_id)
end
format.js do
render plain: "
$(\"[data-item]#theme_interest-#{@theme_interest.id}\").remove();
Turbolinks.visit(window.location);
"
end
end
else
respond_to do |format|
format.html do
flash[:danger] = 'Failed to remove the interested researcher'
redirect_to admin_theme_url(@theme_interest.theme_id)
end
format.js do
render plain: 'alert(\"Failed to remove the interested researcher\");'
end
end
end
end
def reject_interest
authorize! :destroy, @theme_interest
if @theme_interest.destroy
send_notifications(current_user, theme_interest_reject_params[:message])
respond_to do |format|
format.html do
flash[:success] = 'Successfully rejected interested student'
redirect_to admin_theme_url(@theme_interest.theme_id)
end
format.js do
render plain: "
$(\"[data-item]#theme_interest-#{@theme_interest.id}\").remove();
Turbolinks.visit(window.location);
"
end
end
flash[:success] = 'Successfully rejected interested student'
else
respond_to do |format|
format.html do
flash[:danger] = 'Failed to reject interested student'
redirect_to admin_theme_url(@theme_interest.theme_id)
end
format.js do
render plain: 'alert(\"Failed to reject the interested student\");'
end
end
flash[:danger] = 'Failed to reject interested student'
end
redirect_to admin_theme_url(@theme_interest.theme_id)
end
protected
def theme_interest_params
params.require(:theme_interest).permit(
:theme_id,
:user_id
)
end
def theme_interest_reject_params
params.permit(
:message
......
......@@ -7,20 +7,15 @@ module Admin
add_breadcrumb ThesisProjectAssociatedUser.model_name.human(count: 2), :admin_thesis_project_associated_users_path
def create
@thesis_project = ThesisProject.find_by(id: thesis_project_associated_user_params[:thesis_project_id])
raise(ActionController::BadRequest.new, 'Thesis project not found') if @thesis_project.nil?
authorize! :update, @thesis_project
@thesis_project_associated_user = ThesisProjectAssociatedUser.create thesis_project_associated_user_params
if @thesis_project_associated_user.persisted?
respond_to do |format|
format.html do
flash[:success] = 'Succesfully added the associated user'
redirect_to admin_thesis_project_url(@thesis_project_associated_user.thesis_project_id)
end
format.js do
render plain: "
Turbolinks.visit(window.location);
"
end
end
flash[:success] = 'Succesfully added the associated user'
redirect_to admin_thesis_project_url(@thesis_project_associated_user.thesis_project_id)
else
respond_to do |format|
format.html do
......@@ -44,7 +39,6 @@ module Admin
format.js do
render plain: "
$(\"[data-item]#thesis_project_associated_user-#{@thesis_project_associated_user.id}\").remove();
Turbolinks.visit(window.location);
"
end
end
......
......@@ -9,29 +9,12 @@ module Admin
if @thesis_project_interest.destroy
send_notifications(current_user, thesis_project_interest_params[:message])
respond_to do |format|
format.html do
flash[:success] = 'Successfully rejected interested student'
redirect_to admin_thesis_project_url(@thesis_project_interest.thesis_project_id)
end
format.js do
render plain: "
$(\"[data-item]#thesis_project_interest-#{@thesis_project_interest.id}\").remove();
Turbolinks.visit(window.location);
"
end
end
flash[:success] = 'Successfully rejected interested student'
else
respond_to do |format|
format.html do
flash[:danger] = 'Failed to reject interested student'
redirect_to admin_thesis_project_url(@thesis_project_interest.thesis_project_id)
end
format.js do
render plain: 'alert(\"Failed to reject the interested student\");'
end
end
flash[:danger] = 'Failed to reject interested student'
end
redirect_to admin_thesis_project_url(@thesis_project_interest.thesis_project_id)
end
protected
......
......@@ -3,11 +3,12 @@ class ApplicationController < ActionController::Base
before_action :store_user_location!, if: :storable_location?
before_action :authenticate_user!
before_action :count_unread_notifications
helper_method :page_title
before_action :set_sentry_context
check_authorization unless: :devise_controller?
helper_method :page_title
rescue_from CanCan::AccessDenied do |exception|
Rails.logger.error("An access denied exception was triggered: #{exception.action} #{exception.subject.inspect}")
Rails.logger.error(exception.backtrace)
......@@ -29,10 +30,12 @@ class ApplicationController < ActionController::Base
end
end
def count_unread_notifications
# Identifies the +current_user+ to sentry
def set_sentry_context
return unless signed_in?
@notification_count = current_user.notifications.unread.count
Sentry.set_user(email: current_user.email)
Sentry.set_tags('management panel': false)
end
protected
......
module NotificationsHelper
def notifications_badge(user = nil)
user ||= current_user
count = @notification_count
count ||= user.notifications.unread.count
count = user.notifications.unread.count
return '' unless count.positive?
content_tag :span,
......
......@@ -36,12 +36,14 @@ class AdminAbility
thesis_projects = user.associated_thesis_projects.ids
unless thesis_projects.empty?
can :manage, ThesisProject, id: thesis_projects
can :manage, ThesisProjectInterest, thesis_project_id: thesis_projects
can :manage, ThesisProjectAssociatedUser, thesis_project_id: thesis_projects
end
themes = user.associated_themes.ids
unless themes.empty?
can :manage, Theme, id: themes
can :manage, ThemeInterest, theme_id: themes
can :manage, ThemeAssociatedUser, theme_id: themes
end
......@@ -76,7 +78,7 @@ class AdminAbility
# Department coordinators can see details of all staff users.
# They can read the faculty and department they coordinate and can read/create/update research groups in their
# department. They can manage roles within research groups in their department.
# They can manage themes and theme interests and read thesis projects, but cannot create or edit thesis projects.
# They can manage themes and read thesis projects, but cannot create or edit thesis projects.
#
# @param [User] user
def department_coordinator_rights(user)
......@@ -91,7 +93,6 @@ class AdminAbility
thesis_projects = ThesisProject.where(theme_id: Theme.where(research_group: user.coordinated_research_groups).ids).ids
can :manage, Theme, research_group_id: user.coordinated_research_groups.ids
can :manage, ThemeInterest, theme_id: Theme.where(research_group: user.coordinated_research_groups).ids
can :manage, ThemeAssociatedUser, theme_id: Theme.where(research_group: user.coordinated_research_groups).ids
can :manage, ThesisProject, id: thesis_projects
can :manage, ThesisProject, theme_id: nil # TODO: Eventually get rid of thesis projects outside themes?
......@@ -118,6 +119,7 @@ class AdminAbility
thesis_projects = ThesisProject.where(theme_id: Theme.where(research_group: user.rg_manager_research_groups).ids).ids
can :manage, ThesisProject, id: thesis_projects
can :manage, ThesisProjectInterest, thesis_project_id: thesis_projects
can :manage, ThesisProjectAssociatedUser, thesis_project_id: thesis_projects
can :create, ThesisProject
end
......@@ -140,6 +142,7 @@ class AdminAbility
thesis_projects = ThesisProject.where(theme_id: Theme.where(research_group: user.member_research_groups).ids).ids
can %i[read update], ThesisProject, id: thesis_projects
can :manage, ThesisProjectInterest, thesis_project_id: thesis_projects
can :manage, ThesisProjectAssociatedUser, thesis_project_id: thesis_projects
can :create, ThesisProject
end
......
......@@ -2,7 +2,7 @@ class Attachment < ApplicationRecord
belongs_to :user
belongs_to :group
has_attached_file\
has_attached_file \
:file,
path: 'private/uploads/:class/:id/:basename.:extension',
url: '/attachments/:id/:basename.:extension'
......@@ -11,15 +11,33 @@ class Attachment < ApplicationRecord
:file,
presence: true,
content_type: { content_type: %w[
image/jpeg image/png image/gif
text/plain application/x-latex application/pdf
application/rtf application/msword
application/vnd.ms-excel application/vnd.ms-powerpoint
image/jpeg
image/png
image/gif
image/svg+xml
text/plain
application/x-latex
application/pdf
application/rtf
application/msword
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/vnd.oasis.opendocument.text
text/csv
application/vnd.ms-excel
application/vnd.oasis.opendocument.spreadsheet
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
application/vnd.ms-powerpoint
application/vnd.oasis.opendocument.presentation
application/vnd.openxmlformats-officedocument.presentationml.presentation
application/vnd.openxmlformats-officedocument.presentationml.slideshow
application/vnd.rar
application/zip
] },
size: { in: 0..10.megabytes }
size: { in: 0..20.megabytes }
)
end
......@@ -3,5 +3,10 @@ class ThemeInterest < ApplicationRecord
belongs_to :theme
belongs_to :course_edition, optional: true
validates :thesis_start, presence: true, if: -> { user.role_student? }
validates :thesis_start, presence: true
# @return the theme this interest belongs to
def resource
theme
end
end
......@@ -10,6 +10,7 @@ class ThesisProject < ApplicationRecord
belongs_to :creator, class_name: 'User'
has_many :thesis_project_interests, dependent: :destroy
accepts_nested_attributes_for :thesis_project_interests, allow_destroy: true
has_many :interested_students, through: :thesis_project_interests, class_name: 'User', source: :user
has_many :copies, inverse_of: :original, class_name: 'ThesisProject', foreign_key: :original_id, dependent: :nullify
......
......@@ -4,4 +4,9 @@ class ThesisProjectInterest < ApplicationRecord
has_one :course_edition, through: :thesis_project
validates :thesis_start, presence: true
# @return The thesis project this interest belongs to
def resource
thesis_project
end
end
......@@ -217,11 +217,10 @@
</thead>
<tbody>
<% @research_group.visible_themes.each do |theme| %>
<% theme.interested_students.each do |student| %>
<% theme.theme_interested_students.each do |student| %>
<tr>
<td><%= student.full_name %></td>
<td><a href="mailto:<%= student.email %>"><%= student.email %></a></td>
<td><%= fa_icon_link_to :palette, theme.name, admin_theme_path(theme) %></td>
</tr>
<% end %>
......
......@@ -247,7 +247,7 @@
<% end %>
<td>
<% if can? :destroy, theme_interest %>
<%= render 'admin/themes/show/reject_student', theme_interest: theme_interest %>
<%= render 'admin/thesis/shared/reject_student', interest: theme_interest %>
<% end %>
</td>
</tr>
......@@ -263,7 +263,7 @@
</td>
<td>
<% if can? :destroy, thesis_project_interest %>
<%= render 'admin/thesis_projects/show/reject_student', thesis_project_interest: thesis_project_interest %>
<%= render 'admin/thesis/shared/reject_student', interest: thesis_project_interest %>
<% end %>
</td>
</tr>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment