Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • portalmec/portalmec
  • rfhferreira/cleanning-portalmec
2 results
Select Git revision
Show changes
Commits on Source (89)
Showing
with 915 additions and 284 deletions
.git
log/
tmp/
public/system/
public/assets/
vendor/
shared/
# '.env' file example for local development.
# Copy this file to a file named '.env' and make changes there.
# The final '.env' file should not be commited to version control.
# Set the *_PASSWORD variables with actual passwords.
# 'host.docker.internal' resolves to the IP of the host machine inside the docker network.
PORTALMEC_API_URL=localhost
PORTALMEC_DB_HOST=host.docker.internal
PORTALMEC_DB_POOL=25
PORTALMEC_DB_NAME=portalmec
PORTALMEC_DB_USERNAME=portalmec
PORTALMEC_DB_PASSWORD=
PORTALMEC_DSPACE_LOGIN=admin@mecdb3.c3sl.ufpr.br
PORTALMEC_DSPACE_PASSWORD=
PORTALMEC_DSPACE_PORT=8443
PORTALMEC_DSPACE_HOST=mecdb4.c3sl.ufpr.br
PORTALMEC_ELASTICSEARCH_PORT=9200
PORTALMEC_ELASTICSEARCH_HOST=host.docker.internal
PORTALMEC_ELASTICSEARCH_LOGIN=elastic
PORTALMEC_ELASTICSEARCH_PASSWORD=
PORTALMEC_ELASTICSEARCH_INDEX_PREFIX=
MEMCACHE_SERVERS=localhost
ACTION_MAILER_HOST=api.portalmectest.c3sl.ufpr.br
SMTP_ADDRESS=urquell.c3sl.ufpr.br
SMTP_PORT=587
GITLAB_PORTALMEC_PRIVATE_TOKEN=
RAILS_SERVE_STATIC_FILES=FALSE
RAILS_ENV=development
PORT=3000
WEB_CONCURRENCY=8
RAILS_MAX_THREADS=8
REDIS_HOST=redis
GOOGLE_KEY=
GOOGLE_SECRET=
......@@ -8,7 +8,6 @@
/.bundle
# Ignore all logfiles and tempfiles.
Gemfile.lock
/log/*
!/log/.keep
/tmp
......@@ -25,6 +24,7 @@ Gemfile.lock
/shared/*
dump.rdb
/public/system/*
/db/seeds/assets/*
# ignore server scripts
puma.sh
......@@ -38,3 +38,5 @@ autocomplete-server.service
# ignore configs
/config/database.yml
/config/sidekiq.yml
.env
.env.prod
FROM ruby:2.2.0
RUN apt-get update -qq && apt-get install -y build-essential nodejs
# syntax=docker/dockerfile:1
RUN mkdir /app
FROM ruby:3.1.0
WORKDIR /tmp
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN bundle install -j 3
ENV BUNDLER_VERSION=2.3.26
RUN gem install bundler -v 2.3.26
WORKDIR /app
CMD ["rails", "server", "-b", "0.0.0.0"]
COPY Gemfile Gemfile.lock ./
RUN apt update && \
apt install -y libarchive13 nodejs
# Prevent libxml2 and libxslt conflicts
RUN bundle config build.nokogiri --use-system-libraries
# Only install if Gemfile not satisfied
RUN bundle check || bundle install
COPY . ./
ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]
......@@ -11,6 +11,7 @@ gem 'sdoc', '>= 0.4.0', group: :doc
# Use ActiveModel has_secure_password
gem 'bcrypt', '>= 3.1.7'
# memcached
gem 'dalli'
......@@ -145,7 +146,11 @@ gem 'activerecord-import'
# social connect
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-google-oauth2', '~>0.8.2'
gem 'omniauth-google-oauth2', '0.8.2'
gem 'faraday'
gem 'net-http-persistent'
# get mime type
gem 'mimemagic'
......@@ -172,3 +177,14 @@ gem 'paranoia'
gem 'paper_trail'
gem 'acts_as_list'
gem 'faraday-net_http_persistent', '~> 2.0'
gem 'elasticsearch', '~> 8.6'
gem 'multipart-post', '~> 2.0'
gem 'faraday-multipart', '~> 1.0', '>= 1.0.4'
gem 'tzinfo-data'
This diff is collapsed.
......@@ -20,6 +20,43 @@ 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/>.
# Setup with Docker Compose
## Requirements
* `docker >= 20.10.5`
* `git`
* ElasticSearch instance
* PostgreSQL
## Steps
(Dependending in your docker version, you may need to use `docker-compose` instead of `docker compose`)
1. Clone the repository.
1. In the root of the repository run `docker compose build`. This will build the necessary images for running PortalMEC. If this command fails, check if you are behind a HTTP Proxy. If that's the case, clean any built images with `docker compose down --rmi all --remove-orphans` and then use
* `docker compose build --build-arg HTTP_PROXY="<http proxy url here> --build-arg HTTPS_PROXY="<https proxy url here>"`.
1. Make a copy of the `.env.dev` file named `.env` and change the necessary configuration. You will need to change at least:
* `PORTALMEC_DB_HOST`
* `PORTALMEC_DB_NAME`
* `PORTALMEC_DB_USERNAME`
* `PORTALMEC_DB_PASSWORD`
* `PORTALMEC_ELASTICSEARCH_HOST`
* `PORTALMEC_ELASTICSEARCH_LOGIN`
* `PORTALMEC_ELASTICSEARCH_PASSWORD`
* `PORTALMEC_ELASTICSEARCH_INDEX_PREFIX`
* `RAILS_ENV`
1. This step is only needed if you don't have a database. Run `docker compose run --entrypoint sh app`. This will instantiate a container from the `app` image built in the previous step and run a shell inside it. In the new shell:
1. Run `bundle exec rake db:create` to create the database.
* If you have a database dump, you should use it now. Run *in the host*: `psql -U <database user> -d <database name> < <dump name>.sql`
1. Run `bundle exec rake db:migrate` to create the database schema.
1. Run `bundle exec rake db:seed` to populate the database with default data.
1. Run `bundle exec rake searchkick:reindex:all` to index the data in ElasticSearch.
1. Run `exit` to exit the shell.
1. Run `docker compose up`.
## Local specific configuration
The URL `host.docker.internal` inside a docker container is configured to point to the host machine. When you need to use a service running in the host machine (for example a local PostgresSQL installation), you should use this address instead of `localhost`.
# Old Setup
## Requirements
* rvm
......@@ -104,6 +141,7 @@ After all gems were installed succesfuly. Please create the database using the f
* If you have the dump of the database, use it before db:migrate.
* To use the dump, run this commands: ```psql -U $DATABASE_USER -d $DATABASE_NAME < $DATABASE_PATH/dump_name.sql ```
* ``` rake db:migrate ```
* Then run `rake db:seed`.
``` Note ``` : You need to load the dump in the database_dev.
......
......@@ -28,8 +28,10 @@ class ApplicationController < ActionController::API
rescue_from Exception do |exception|
logger.fatal "The request raised an exception:"
http_request_headers = request.headers.select{|header_name, header_value| header_name.match("^HTTP.*")}
logger.fatal "#{request.method.inspect} request to #{request.url.inspect} from #{request.remote_ip.inspect} with headers #{http_request_headers.inspect} and params #{params.inspect} gave the following exception:"
logger.fatal exception
logger.fatal exception.backtrace.first(10).join("\n")
logger.fatal exception.backtrace.first(15).join("\n")
unless response_body
render status: :internal_server_error
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/>.
module ItemsFilter
extend ActiveSupport::Concern
def filter_items(items)
# filter by type
if !params[:item_type].blank?
items = items.where(item_type: params[:item_type])
end
# filter by price
if params[:op] == "lt" # less than
items = items.where("price < ?", params[:price])
elsif params[:op] == "gt" # greater than
items = items.where("price > ?", params[:price])
elsif params[:op] == "eq" # equals
items = items.where(price: params[:price])
end
# filter by the way it's unlocked
if params[:unlock_rule] == "achievement"
items = items.where.not(achievement_id: nil)
elsif params[:unlock_rule] == "purchase"
items = items.where(achievement_id: nil)
end
items
end
end
......@@ -27,6 +27,12 @@ module Paginator
return model[offset..limit]
end
#return paginate for select queries
def paginate_select(model, total)
total_count_select total
return model
end
private
def limit
......@@ -67,4 +73,7 @@ module Paginator
headers['X-Total-Count'] = model.count
end
def total_count_select(total)
headers['X-Total-Count'] = total
end
end
......@@ -28,7 +28,7 @@ module PublisherController
end
def show_all_drafts
learning_objects = paginate LearningObject.where(publisher: @publisher, state: LearningObject.states[:draft])
learning_objects = paginate LearningObject.where(publisher: @publisher, state: LearningObject.states[:draft]).order("created_at DESC")
render json: learning_objects
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::AchievementsController < ApplicationController
include ::Paginator
before_action :set_achievement, only: [:show, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
before_action :authorize!, only: [:update, :destroy]
# GET /v1/achievements
def index
achievements = paginate Achievement
render json: achievements
end
# GET /v1/achievements/1
def show
render json: @achievement
end
# POST /v1/achievements
def create
@achievement = Achievement.new(achievement_params)
authorize @achievement
if @achievement.save
@achievement.add_requirements(extra_params[:requirements])
render json: @achievement, status: :created
else
render json: @achievement.errors, status: :unprocessable_entity
end
end
# PUT/PATCH /v1/achievements/1
def update
if @achievement.update(achievement_params)
@achievement.update_requirements(extra_params[:requirements])
render json: @achievement, status: :ok
else
render json: @achievement.errors, status: :unprocessable_entity
end
end
# DELETE /v1/achievements/1
def destroy
if @achievement.update(state: 2)
render status: :ok, json: @achievement
else
render json: @achievement.errors, status: :unprocessable_entity
end
end
private
def set_achievement
@achievement ||= Achievement.find_by_id(params[:id])
if @achievement.blank?
render status: :not_found
end
end
def achievement_params
params.require(:achievement).permit(:name, :description, :reward_experience, :reward_points, :state, :repeatable, :resettable)
end
def extra_params
return {} if params[:achievement].nil?
params[:achievement].permit(requirements: [])
end
def authorize!
authorize @achievement
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::ActionCountersController < ApplicationController
include ::Paginator
before_action :set_action_counter, only: :show
def index
action_counters = paginate ActionCounter
render json: action_counters
end
def show
render json: @action_counter
end
private
def set_action_counter
@action_counter ||= ActionCounter.find_by_id(params[:id])
if @action_counter.blank?
render status: :not_found
end
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::ActionsController < ApplicationController
include ::Paginator
before_action :set_action, only: [:show, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
before_action :authorize!, only: [:update, :destroy]
# GET /v1/actions
def index
actions = paginate Action
render json: actions
end
# GET /v1/actions/1
def show
render json: @action
end
# POST /v1/actions
def create
@action = Action.new(action_params)
authorize @action
if @action.save
render json: @action, status: :created
else
render json: @action.errors, status: :unprocessable_entity
end
end
# PUT/PATCH /v1/actions/1
def update
if @action.update(action_params)
render json: @action, status: :ok
else
render json: @action.errors, status: :unprocessable_entity
end
end
# DELETE /v1/actions/1
def destroy
@action.destroy
response = { 'status': 'deleted' }
render status: :ok, json: response
end
private
def set_action
@action ||= Action.find_by_id(params[:id])
if @action.blank?
render status: :not_found
end
end
def action_params
params.require(:action_params).permit(:name, :description, :reward_experience)
end
def authorize!
authorize @action
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::ComplaintVotesController < ApplicationController
include ::DeletedObjectsController
include ::Paginator
before_action :set_complaint_vote, only: [:show, :update, :destroy]
# GET /v1/complaint_votes
def index
complaint_votes = paginate ComplaintVote
render json: complaint_votes
end
# GET /v1/complaint_votes/{id}
def show
render json: @complaint_vote
end
# POST /v1/complaint_votes
def create
@complaint_vote = ComplaintVote.new(complaint_vote_params)
if @complaint_vote.save
render json: @complaint_vote, status: :created
else
render json: @complaint_vote.errors, status: :unprocessable_entity
end
verify_votes(@complaint_vote)
end
# Set the params required for creating a complaint vote
def complaint_vote_params
params.require(:complaint_vote).permit(:complainable_type, :complainable_id, :pros, :cons, :user_id)
end
# PUT/PATCH /v1/complaint_votes/{id}
def update
if @complaint_vote.update(complaint_vote_params)
render json: @complaint_vote
else
render json: @complaint_vote.errors, status: :unprocessable_entity
end
end
# DELETE /v1/complaint_votes/{id}
def destroy
@complaint_vote.destroy
response = { 'status': 'deleted' }
render status: :ok, json: response
end
def set_complaint_vote
# @complaint_vote = ComplaintVote.where(id: params[:id]).first
# render status: :not_found if @complaint_vote.blank?
# @complaint_vote
@complaint_vote ||= ComplaintVote.find_by_id(params[:id]).first
if @complaint_vote.blank?
render status: :not_found
end
end
# if the difference between the pros and cons votes is more than 2, destroy the learning object
def verify_votes(complaint_vote)
data = ComplaintVote.select("complainable_id, sum(pros) as pros, sum(cons) as cons")
.where("complainable_id = ?", complaint_vote.complainable_id)
.group("complaint_votes.complainable_id")
data.each do |d|
if (d.complainable_id == complaint_vote.complainable_id)
if d.pros - d.cons > 2
ComplaintVote.where("complainable_id = ?", complaint_vote.complainable_id).destroy_all
Complaint.where("complainable_id = ?", complaint_vote.complainable_id).destroy_all
LearningObject.where(id: complaint_vote.complainable_id).update_all(state: LearningObject.states[:deleted])
LearningObject.where(id: complaint_vote.complainable_id).update_all(deleted_at: Time.now)
elsif d.cons - d.pros > 2
ComplaintVote.where("complainable_id = ?", complaint_vote.complainable_id).destroy_all
Complaint.where("complainable_id = ?", complaint_vote.complainable_id).update_all(state: Complaint.states[:rejected])
LearningObject.where(id: complaint_vote.complainable_id).update_all(state: LearningObject.states[:published])
end
end
end
end
end
......@@ -54,7 +54,9 @@ class V1::ComplaintsController < ApplicationController
if @complaint.save
ComplaintsMailer.new_complaint_received(@complaint, @current_user).deliver_now
@complaint.complainable.treat_complaintment
if (Complaint.where(complainable_id: @complaint.complainable_id).count >= 2)
LearningObject.where(id: @complaint.complainable_id).update_all(state: LearningObject.states[:suspended])
end
render json: @complaint, status: :created
else
......
......@@ -21,13 +21,28 @@ class V1::EmailController < ApplicationController
before_action :authenticate, only: [:create]
before_action -> { authorize current_user }, only: [:create]
def index
users_email = []
for u in User.all
users_email.push(u.email)
end
render json: users_email
end
def create
email = Email.new(email_params)
email.role_ids = roles_params[:roles]
users = User.joins(:roles).where(roles: { id: email.role_ids }).distinct
for u in users
email.emails.push(u.email)
end
email.user = current_user
if email.save
email.emails.each do |address|
EmailMailer.new_email(email, address).deliver_now
UserMailer.users_email_sender(address, email_params[:subject], email_params[:body]).deliver_now
end
render status: :ok
else
......
......@@ -40,7 +40,7 @@ class V1::FeedController < ApplicationController
current_user.watching.each do |watching|
if !watching.respond_to?(:state) || watching.state == "published"
if (watching.class == Submission || watching.class == CuratorAssignment)
query += " ((trackable_type = ? and trackable_id = ?) and (owner_type = 'User' and owner_id = #{current_user.id})"
query += " ( recipient_id != owner_id and (trackable_type = ? and trackable_id = ?) and (owner_type = 'User' and owner_id = #{current_user.id})"
values << watching.class.to_s
values << watching.id
if watching.class == CuratorAssignment
......@@ -59,9 +59,13 @@ class V1::FeedController < ApplicationController
end
end
if query[-1] == "r"
values[0] = query[0..-3] # remove trailing "or" on the query
else
values[0] = query
end
return [] if query.blank?
return PublicActivity::Activity.where(key: activities_filter).where(values).order(created_at: :desc)
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::ItemsController < ApplicationController
include ::Paginator
include ::ItemsFilter
before_action :set_item, only: [:show, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
before_action :authorize!, only: [:update, :destroy]
def index
items = paginate filter_items(policy_scope(Item))
render json: items
end
def show
render json: @item
end
def create
@item = Item.new(item_params)
authorize @item
if @item.save
render json: @item, status: :created
else
render json: @item.errors, status: :unprocessable_entity
end
end
# PUT/PATCH /v1/items/1
def update
if @item.update(item_params)
render json: @item, status: :ok
else
render json: @item.errors, status: :unprocessable_entity
end
end
# DELETE /v1/items/1
def destroy
if @item.update(state: 2)
render status: :ok, json: @item
else
render json: @item.errors, status: :unprocessable_entity
end
end
private
def set_item
@item ||= Item.find_by_id(params[:id])
if @item.blank?
render status: :not_found
end
end
def item_params
params.require(:item).permit(:name, :price, :discount, :description, :state, :item_type, :image, :achievement_id)
end
def authorize!
authorize @item
end
end