From baf8cfb4876556bb47055af3253d15697cc2f516 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 27 Nov 2019 17:05:19 +0100 Subject: [PATCH] iCalendar server api & db model --- .../controllers/admin/calendar.js.erb | 6 +- .../javascripts/controllers/calendar.js | 2 +- app/assets/javascripts/router.js.erb | 1 + app/assets/javascripts/services/ical.js | 5 -- app/assets/javascripts/services/icalendar.js | 12 ++++ app/controllers/api/i_calendar_controller.rb | 55 +++++++++++++++++++ app/controllers/api/ical_controller.rb | 19 ------- app/models/i_calendar.rb | 5 ++ app/policies/i_calendar_policy.rb | 12 ++++ .../api/i_calendar/_i_calendar.json.jbuilder | 3 + .../events.json.jbuilder} | 4 +- app/views/api/i_calendar/index.json.jbuilder | 5 ++ app/views/api/i_calendar/show.json.jbuilder | 3 + config/routes.rb | 4 +- .../20191127153729_create_i_calendars.rb | 16 ++++++ db/schema.rb | 11 +++- test/fixtures/i_calendars.yml | 13 +++++ test/models/i_calendar_test.rb | 7 +++ 18 files changed, 152 insertions(+), 31 deletions(-) delete mode 100644 app/assets/javascripts/services/ical.js create mode 100644 app/assets/javascripts/services/icalendar.js create mode 100644 app/controllers/api/i_calendar_controller.rb delete mode 100644 app/controllers/api/ical_controller.rb create mode 100644 app/models/i_calendar.rb create mode 100644 app/policies/i_calendar_policy.rb create mode 100644 app/views/api/i_calendar/_i_calendar.json.jbuilder rename app/views/api/{ical/externals.json.jbuilder => i_calendar/events.json.jbuilder} (74%) create mode 100644 app/views/api/i_calendar/index.json.jbuilder create mode 100644 app/views/api/i_calendar/show.json.jbuilder create mode 100644 db/migrate/20191127153729_create_i_calendars.rb create mode 100644 test/fixtures/i_calendars.yml create mode 100644 test/models/i_calendar_test.rb diff --git a/app/assets/javascripts/controllers/admin/calendar.js.erb b/app/assets/javascripts/controllers/admin/calendar.js.erb index 569d7a35d..e41157041 100644 --- a/app/assets/javascripts/controllers/admin/calendar.js.erb +++ b/app/assets/javascripts/controllers/admin/calendar.js.erb @@ -762,10 +762,10 @@ Application.Controllers.controller('DeleteRecurrentAvailabilityController', ['$s * Controller used in the iCalendar (ICS) imports management page */ -Application.Controllers.controller('AdminICalendarController', ['$scope', - function ($scope) { +Application.Controllers.controller('AdminICalendarController', ['$scope', 'iCalendars', + function ($scope, iCalendars) { // list of ICS sources - $scope.calendars = []; + $scope.calendars = iCalendars; // configuration of a new ICS source $scope.newCalendar = { diff --git a/app/assets/javascripts/controllers/calendar.js b/app/assets/javascripts/controllers/calendar.js index e46eb8db1..33d811f55 100644 --- a/app/assets/javascripts/controllers/calendar.js +++ b/app/assets/javascripts/controllers/calendar.js @@ -41,7 +41,7 @@ Application.Controllers.controller('CalendarController', ['$scope', '$state', '$ // add availabilities source to event sources $scope.eventSources = []; $scope.eventSources.push({ - url: '/api/ical/externals', + url: '/api/i_calendar/events', textColor: 'black' }); diff --git a/app/assets/javascripts/router.js.erb b/app/assets/javascripts/router.js.erb index f0476c79c..62503a9cf 100644 --- a/app/assets/javascripts/router.js.erb +++ b/app/assets/javascripts/router.js.erb @@ -668,6 +668,7 @@ angular.module('application.router', ['ui.router']) } }, resolve: { + iCalendars: ['ICalendar', function (ICalendar) { return ICalendar.query().$promise; }], translations: ['Translations', function (Translations) { return Translations.query('app.admin.icalendar').$promise; }] } }) diff --git a/app/assets/javascripts/services/ical.js b/app/assets/javascripts/services/ical.js deleted file mode 100644 index dec1ed635..000000000 --- a/app/assets/javascripts/services/ical.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -Application.Services.factory('Ical', ['$resource', function ($resource) { - return $resource('/api/ical/externals'); -}]); diff --git a/app/assets/javascripts/services/icalendar.js b/app/assets/javascripts/services/icalendar.js new file mode 100644 index 000000000..21d30843e --- /dev/null +++ b/app/assets/javascripts/services/icalendar.js @@ -0,0 +1,12 @@ +'use strict'; + +Application.Services.factory('ICalendar', ['$resource', function ($resource) { + return $resource('/api/i_calendar/:id', + { id: '@id' }, { + events: { + method: 'GET', + url: '/api/i_calendar/events' + } + } + ); +}]); diff --git a/app/controllers/api/i_calendar_controller.rb b/app/controllers/api/i_calendar_controller.rb new file mode 100644 index 000000000..f004a13ab --- /dev/null +++ b/app/controllers/api/i_calendar_controller.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +# API Controller for resources of type iCalendar +class API::ICalendarController < API::ApiController + before_action :authenticate_user!, except: %i[index events] + before_action :set_i_cal, only: [:destroy] + respond_to :json + + def index + @i_cals = ICalendar.all + end + + def create + authorize ICalendar + @i_cal = ICalendar.new(i_calendar_params) + if @i_cal.save + render :show, status: :created, location: @i_cal + else + render json: @i_cal.errors, status: :unprocessable_entity + end + end + + def destroy + authorize ICalendar + @i_cal.destroy + head :no_content + end + + def events + require 'net/http' + require 'uri' + require 'icalendar' + + @events = [] + + @i_cals = ICalendar.all.each do |i_cal| + ics = Net::HTTP.get(URI.parse(i_cal.url)) + cals = Icalendar::Calendar.parse(ics) + + cals.first.events.each do |evt| + @events.push(evt.merge!(color: i_cal.color)) + end + end + end + + private + + def set_i_cal + @i_cal = ICalendar.find(params[:id]) + end + + def i_calendar_params + params.require(:i_calendar).permit(:url, :color, :text_color, :text_hidden) + end +end diff --git a/app/controllers/api/ical_controller.rb b/app/controllers/api/ical_controller.rb deleted file mode 100644 index dc3307d85..000000000 --- a/app/controllers/api/ical_controller.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -# API Controller for resources of type iCalendar -class API::IcalController < API::ApiController - respond_to :json - - def externals - require 'net/http' - require 'uri' - - ics = Net::HTTP.get(URI.parse('https://calendar.google.com/calendar/ical/sylvain%40sleede.com/public/basic.ics')) - - require 'icalendar' - require 'icalendar/tzinfo' - - cals = Icalendar::Calendar.parse(ics) - @events = cals.first.events - end -end \ No newline at end of file diff --git a/app/models/i_calendar.rb b/app/models/i_calendar.rb new file mode 100644 index 000000000..17d630cae --- /dev/null +++ b/app/models/i_calendar.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# iCalendar (RFC 5545) files, stored by URL and kept with their display configuration +class ICalendar < ActiveRecord::Base +end diff --git a/app/policies/i_calendar_policy.rb b/app/policies/i_calendar_policy.rb new file mode 100644 index 000000000..fd4021814 --- /dev/null +++ b/app/policies/i_calendar_policy.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# Check the access policies for API::ICalendarController +class ICalendarPolicy < ApplicationPolicy + def create? + user.admin? + end + + def destroy? + user.admin? + end +end diff --git a/app/views/api/i_calendar/_i_calendar.json.jbuilder b/app/views/api/i_calendar/_i_calendar.json.jbuilder new file mode 100644 index 000000000..23b68df1d --- /dev/null +++ b/app/views/api/i_calendar/_i_calendar.json.jbuilder @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +json.extract! i_cal, :id, :url, :color, :text_color, :text_hidden diff --git a/app/views/api/ical/externals.json.jbuilder b/app/views/api/i_calendar/events.json.jbuilder similarity index 74% rename from app/views/api/ical/externals.json.jbuilder rename to app/views/api/i_calendar/events.json.jbuilder index faedb232b..5078729e7 100644 --- a/app/views/api/ical/externals.json.jbuilder +++ b/app/views/api/i_calendar/events.json.jbuilder @@ -1,8 +1,10 @@ +# frozen_string_literal: true + json.array!(@events) do |event| json.id event.uid json.title event.summary json.start event.dtstart.iso8601 json.end event.dtend.iso8601 json.backgroundColor 'white' - json.borderColor '#214712' + json.borderColor event.color end diff --git a/app/views/api/i_calendar/index.json.jbuilder b/app/views/api/i_calendar/index.json.jbuilder new file mode 100644 index 000000000..a517d6997 --- /dev/null +++ b/app/views/api/i_calendar/index.json.jbuilder @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +json.array!(@i_cals) do |i_cal| + json.partial! 'api/i_calendar/i_calendar', i_cal: i_cal +end diff --git a/app/views/api/i_calendar/show.json.jbuilder b/app/views/api/i_calendar/show.json.jbuilder new file mode 100644 index 000000000..8e787f030 --- /dev/null +++ b/app/views/api/i_calendar/show.json.jbuilder @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +json.partial! 'api/i_calendar/i_calendar', i_cal: @i_cal diff --git a/config/routes.rb b/config/routes.rb index 9e0b5e095..bcb92b44c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -112,7 +112,9 @@ Rails.application.routes.draw do get 'first', action: 'first', on: :collection end - get 'ical/externals' => 'ical#externals' + resources :i_calendar, only: %i[index create destroy] do + get 'events', on: :collection + end # for admin resources :trainings do diff --git a/db/migrate/20191127153729_create_i_calendars.rb b/db/migrate/20191127153729_create_i_calendars.rb new file mode 100644 index 000000000..289e93b94 --- /dev/null +++ b/db/migrate/20191127153729_create_i_calendars.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# From this migration, we store URL to iCalendar files and a piece of configuration about them. +# This allows to display the events of these external calendars in fab-manager +class CreateICalendars < ActiveRecord::Migration + def change + create_table :i_calendars do |t| + t.string :url + t.string :color + t.string :text_color + t.boolean :text_hidden + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 6e2ed6b2c..bd9579e7f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20191113103352) do +ActiveRecord::Schema.define(version: 20191127153729) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -251,6 +251,15 @@ ActiveRecord::Schema.define(version: 20191113103352) do add_index "history_values", ["invoicing_profile_id"], name: "index_history_values_on_invoicing_profile_id", using: :btree add_index "history_values", ["setting_id"], name: "index_history_values_on_setting_id", using: :btree + create_table "i_calendars", force: :cascade do |t| + t.string "url" + t.string "color" + t.string "text_color" + t.boolean "text_hidden" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "imports", force: :cascade do |t| t.integer "user_id" t.string "attachment" diff --git a/test/fixtures/i_calendars.yml b/test/fixtures/i_calendars.yml new file mode 100644 index 000000000..d3406e7cf --- /dev/null +++ b/test/fixtures/i_calendars.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + url: MyString + color: MyString + text_color: MyString + text_hidden: false + +two: + url: MyString + color: MyString + text_color: MyString + text_hidden: false diff --git a/test/models/i_calendar_test.rb b/test/models/i_calendar_test.rb new file mode 100644 index 000000000..0ab530e7c --- /dev/null +++ b/test/models/i_calendar_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class ICalendarTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end