Skip to content
Snippets Groups Projects
Commit 54b90de8 authored by Israel Barreto Sant'Anna's avatar Israel Barreto Sant'Anna
Browse files

Merge branch 'master' into learning_object-update-permissions

parents 778f3f5a eef0403a
No related branches found
No related tags found
No related merge requests found
Showing
with 552 additions and 32 deletions
......@@ -22,9 +22,9 @@ module PublisherController
include Paginator
included do
before_action :authenticate, only: [:show_all_drafts, :show_liked_learning_objects, :show_submitted_learning_objects, :show_liked_collections]
before_action :set_publisher, only: [:show_all_drafts, :show_all_learning_objects, :show_submitted_learning_objects, :show_all_collections, :show_liked_learning_objects, :show_liked_collections]
before_action -> { authorize @publisher }, only: [:show_all_drafts, :show_submitted_learning_objects, :show_liked_learning_objects, :show_liked_collections]
before_action :authenticate, only: [:show_all_drafts, :show_liked_learning_objects, :show_submissions, :show_liked_collections]
before_action :set_publisher, only: [:show_all_drafts, :show_all_learning_objects, :show_submissions, :show_all_collections, :show_liked_learning_objects, :show_liked_collections]
before_action -> { authorize @publisher }, only: [:show_all_drafts, :show_submissions, :show_liked_learning_objects, :show_liked_collections]
end
def show_all_drafts
......@@ -38,9 +38,20 @@ module PublisherController
render json: learning_objects
end
def show_submitted_learning_objects
learning_objects = paginate LearningObject.where(publisher: @publisher, state: LearningObject.states[:submitted])
render json: learning_objects
# GET /v1/users/:id/submissions
def show_submissions
status = params[:status]
if !status.nil? && !Submission.statuses.has_key?(status) && status != 'all'
render json: {"error": "Status not found."}, status: :unprocessable_entity
else
if current_user.is_curator?
submissions = current_user.assignments
else
submissions = current_user.submissions
end
submissions = submissions.where(status: status) unless status.nil? || status == 'all'
render json: paginate(submissions), status: :ok
end
end
def show_all_collections
......
......@@ -28,7 +28,6 @@ class V1::LearningObjectsController < ApplicationController
include ::HighlightsController
include ::SubjectableController
include ::StageableController
include ::SubmissionController
before_action :authenticate_user!, only: [:create, :update, :destroy, :tagging, :untagging, :submit, :submission, :show_submission]
before_action :set_learning_object, only: [:show, :update, :destroy, :subjecting, :unsubjecting, :add_stages, :remove_stages]
......
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
class V1::QuestionsController < ApplicationController
include ::Paginator
before_action :authenticate_user!, except: [:destroy, :index]
before_action :set_question, only: [:show, :update, :destroy]
before_action :authorize!, only: [ :update, :destroy ]
# GET /questions
def index
@questions = paginate Question.all
render json: @questions
end
# GET /questions/1
def show
render json: @question
end
# POST /questions
def create
@question = Question.new(question_params)
authorize @question
if @question.save
render json: @question, status: :created
else
render json: @question.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /questions/1
def update
if @question.update(question_params)
render json: @question
else
render json: @question.errors, status: :unprocessable_entity
end
end
# DELETE /questions/1
def destroy
@question.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
@question = Question.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def question_params
params.require(:question).permit(:description, :status)
end
def authorize!
authorize @question
end
end
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
class V1::SubmissionsController < ApplicationController
include ::Paginator
before_action :set_new_submission, only: :index
before_action :set_submission, only: [:show, :answer, :destroy]
before_action :authenticate_user!
before_action :authorize!, except: :create
def index
submissions = paginate Submission.all
render json: submissions
end
def show
render json: @submission
end
def create
learning_object = LearningObject.where(id: submission_params[:learning_object_id]).first
if learning_object.blank?
render :json, status: :not_found
else
@submission = Submission.new(learning_object: learning_object, submitter: current_user, status: :submitted)
authorize @submission
if @submission.save
CuratorAssignmentsService.new(@submission).assign
@submission.learning_object.submitted!
render json: @submission, status: :created
else
render json: @submission.errors, status: :unprocessable_entity
end
end
end
# GET /v1/submission/:id/answer
def answer
@submission.justification = answer_params[:justification]
answers = []
questions = Question.active.pluck(:id)
answers = answer_params[:answers]
if questions.size > answers.size
render json: { "error": "Active questions missing" }, status: :unprocessable_entity
else
answers.each do |answer|
if !questions.include?(answer[:question_id])
render json: {"error": "Inactive questions not permitted"}, status: :unprocessable_entity
return
else
@submission.answers << Answer.create(answer)
end
end
@submission.curator = current_user
if @submission.save
if @submission.accepted?
publisher = LearningObjectPublisher.new(DspaceService.create_client)
publisher.publish @submission.learning_object
else
@submission.learning_object.destroy
end
render json: @submission, status: :ok
else
render json: @submission.errors, status: :unprocessable_entity
end
end
end
def destroy
@submission.destroy
response = { 'status': 'deleted' }
render status: :ok, json: response
end
private
def answer_params
return nil if params[:submission].nil?
params[:submission].permit(:justification, answers: [:question_id, :accepted])
end
def submission_params
return nil if params[:submission].nil?
params[:submission].permit(:learning_object_id)
end
def set_new_submission
@submission ||= Submission.new
end
def set_submission
@submission ||= Submission.find_by_id(params[:id])
if @submission.blank?
render status: :not_found
end
end
def authorize!
authorize @submission
end
end
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
# == Schema Information
#
# Table name: answers
# t.integer "question_id"
# t.integer "submission_id"
# t.boolean "accepted"
# t.datetime "created_at", null: false
# t.datetime "updated_at", null: false
class Answer < ApplicationRecord
belongs_to :question
belongs_to :submission
validates :submission, :question, presence: true
end
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
# == Schema Information
#
# Table name: curator_assignments
# t.integer "submission_id"
# t.integer "user_id"
# t.integer "status", default: 0
# t.datetime "created_at", null: false
# t.datetime "updated_at", null: false
class CuratorAssignment < ApplicationRecord
include Trackable
enum status: [:assigned, :answered, :ignored]
belongs_to :submission
belongs_to :user
validates :submission, :user, presence: true
end
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
# == Schema Information
#
# Table name: questions
# t.string "description"
# t.integer "status", default: 0
# t.datetime "created_at", null: false
# t.datetime "updated_at", null: false
class Question < ApplicationRecord
enum status: [:inactive, :active]
has_many :answers
has_many :submissions, through: :answers
end
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
# == Schema Information
#
# Table name: submissions
# t.string "justification"
# t.integer "status", default: 0
# t.datetime "answered_at"
# t.integer "curator_id"
# t.integer "submitter_id", null: false
# t.integer "learning_object_id"
# t.datetime "created_at", null: false
# t.datetime "updated_at", null: false
class Submission < ApplicationRecord
include Trackable
enum status: [:submitted, :rejected, :accepted]
belongs_to :submitter, class_name: "User"
belongs_to :curator, class_name: "User"
belongs_to :learning_object
has_many :curator_assignments, dependent: :destroy
has_many :assignees, through: :curator_assignments, source: :user
has_many :answers, dependent: :destroy
has_many :questions, through: :answers
validates :submitter, :learning_object, presence: true
after_update :update_status
def update_status
if curator_id_changed?
curator_assignments.each do |ca|
if ca.user == curator
ca.answered!
else
ca.ignored!
end
end
status = answers.all? { |a| a.accepted? } ? :accepted : :rejected
self.update_columns(status: status, answered_at: Time.current)
end
end
def new_update_activity
return new_activity(:update, {status: self.status}) if status_changed?
nil
end
end
......@@ -90,6 +90,11 @@ class User < ApplicationRecord
has_many :applications
has_many :searches
has_many :submissions, class_name: "Submission", foreign_key: "submitter_id"
has_many :curations, class_name: "Submission", foreign_key: "curator_id"
has_many :curator_assignments
has_many :assignments, through: :curator_assignments, source: :submission
after_create :default_role
before_save :verify_teacher_id
after_save :verify_dspace_info
......
......@@ -61,7 +61,7 @@ class ApplicationPolicy
return false if user.nil?
return true if user_can_edit?
return owner.users.include?(user) if owner.is_a?(Institution)
# return owner.users.include?(user) if owner.is_a?(Institution)
owner == user
end
......
......@@ -23,7 +23,6 @@ class LearningObjectPolicy < ApplicationPolicy
include TaggablePolicy
include SubjectablePolicy
include StageablePolicy
include SubmissionPolicy
class Scope < Scope
def resolve
......@@ -70,10 +69,8 @@ class LearningObjectPolicy < ApplicationPolicy
end
def show?
return record if record.published? || ( !user.nil? && user_can_edit? )
return record if record.published? || ( !user.nil? && (user_can_edit? || user.is_curator?))
return record if user == record.publisher
## TODO: falta verificar se o +record.publisher+ é uma instituição e +user+ faz parte
# => return owner.users.include?(user) if owner.is_a?(Institution) (???)
end
def index?
......
......@@ -55,6 +55,10 @@ module PublisherPolicy
record if same_user? || user_can_edit?
end
def show_submissions?
record if user_can_edit? || (same_user? && (user.is_curator? || user.is_submitter?))
end
def same_user?
record == user
end
......
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
class QuestionPolicy < ApplicationPolicy
def index?
record
end
def show?
record
end
def create?
record if user_can_edit?
end
def update?
record if user_can_edit?
end
def destroy?
record if user.is_admin?
end
end
......@@ -16,20 +16,35 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
module SubmissionPolicy
def submit?
record if owns? && user.is_submitter?
end
class SubmissionPolicy < ApplicationPolicy
def submissions?
return false if user.nil?
def index?
record if user_can_curate?
end
def show_submission?
return false if user.nil?
def show?
record if user_can_curate? || owns?
end
def create?
record if user_can_create?
end
def answer?
record if user_can_curate?
end
def destroy?
record if record.submitted? && owns?
end
def owner
record.submitter
end
def user_can_create?
return user_exists? && user.is_submitter? && record.learning_object.draft? && record.learning_object.publisher == user
end
end
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
class QuestionSerializer < ActiveModel::Serializer
cache key: 'question', expires_in: 24.hours
attributes \
:id,
:description,
:status
end
# Copyright (C) 2015 Centro de Computacao Cientifica e Software Livre
# Departamento de Informatica - Universidade Federal do Parana
#
# This file is part of portalmec.
#
# portalmec is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# portalmec 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with portalmec. If not, see <http://www.gnu.org/licenses/>.
class SubmissionSerializer < ActiveModel::Serializer
cache key: 'submission', expires_in: 4.hours, except: [:status]
attributes :id, :status, :justification, :answered_at, :created_at
belongs_to :submitter
belongs_to :curator
belongs_to :learning_object
has_many :curator_assignments
has_many :answers
end
......@@ -34,6 +34,7 @@ module ActivitiesFilterService
'collection.create', 'collection.update', 'collection.destroy',
'collection_item.create', 'collection_item.update', 'collection_item.destroy',
'learning_object.create', 'learning_object.update', 'learning_object.destroy',
'submission.create', 'submission.update', 'submission.destroy',
'review.create',
'download.create',
'like.create', 'like.destroy'
......
class CuratorAssignmentsService
def initialize(submission, old_curators = nil)
@submission = submission
@old_curators = old_curators
end
def assign
curators = User.joins(:roles).where(roles: {name: "curator"}).left_joins(:curator_assignments).group('"users"."id"').order('COUNT("curator_assignments"."user_id") ASC').where.not(id: @old_curators).first(5)
@submission.assignees << curators
#TODO: notify curators (email?)
end
end
......@@ -77,16 +77,6 @@ Rails.application.routes.draw do
end
end
concern :submission do
collection do
get :submissions
get 'submissions/:id', action: :show_submission
end
member do
post :submit
end
end
concern :highlights do
collection do
get :this_week
......@@ -100,7 +90,7 @@ Rails.application.routes.draw do
get 'drafts', as: :get_drafts, action: :show_all_drafts
get 'learning_objects', as: :get_learning_objects, action: :show_all_learning_objects
get 'learning_objects/liked', as: :get_liked_learning_objects, action: :show_liked_learning_objects
get 'submissions', as: :get_submitted_learning_objects, action: :show_submitted_learning_objects
get 'submissions', as: :get_submissions, action: :show_submissions
get 'collections', as: :get_collections, action: :show_all_collections
get 'collections/liked', as: :get_liked_collections, action: :show_liked_collections
end
......@@ -166,7 +156,7 @@ Rails.application.routes.draw do
end
end
resources :learning_objects, concerns: [:sociable, :downloadable, :reviewable, :taggable, :versionable, :deletable, :highlights, :subjectable, :stageable, :submission] do
resources :learning_objects, concerns: [:sociable, :downloadable, :reviewable, :taggable, :versionable, :deletable, :highlights, :subjectable, :stageable] do
member do
resource :chunk, module: 'learning_objects', only: [:create, :show]
resource :upload, module: 'learning_objects', only: :create
......@@ -184,6 +174,12 @@ Rails.application.routes.draw do
end
end
resources :submissions, except: :update do
member do
post :answer
end
end
resources :complaints, only: [:index, :create], concerns: :deletable
resources :languages, except: [:new, :edit]
resources :licenses, except: [:new, :edit]
......@@ -195,6 +191,7 @@ Rails.application.routes.draw do
resources :contacts
resources :suggestions
resources :statistics, only: [:index]
resources :questions, except: [:destroy]
post '/package', to: 'packages#link'
get '/subjects', to: 'subjects#index'
......
......@@ -42,3 +42,8 @@
every 6.hours do
rake 'score:calculate_all'
end
#Reassign submitted LO that has expired
every :sunday, at: '3am' do
rake 'submission:reassign'
end
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment