Add links plugin
This can be used to link to external services related to the foodcoop. With the indirect mode it is possible to implement a secure login to other services. In that case Foodsoft will send a HTTP GET request and redirect the user to the returned Location header. This allows the generation of a one-time login URL. A typical use-case would be that a workgroup, which is responsible for the email account, does not need to share the login credentials and can use a link within the Foodsoft instead.
This commit is contained in:
parent
e16f03eebf
commit
7657b05787
16 changed files with 211 additions and 0 deletions
1
Gemfile
1
Gemfile
|
@ -61,6 +61,7 @@ gem 'foodsoft_wiki', path: 'plugins/wiki'
|
||||||
gem 'foodsoft_messages', path: 'plugins/messages'
|
gem 'foodsoft_messages', path: 'plugins/messages'
|
||||||
gem 'foodsoft_documents', path: 'plugins/documents'
|
gem 'foodsoft_documents', path: 'plugins/documents'
|
||||||
gem 'foodsoft_discourse', path: 'plugins/discourse'
|
gem 'foodsoft_discourse', path: 'plugins/discourse'
|
||||||
|
gem 'foodsoft_links', path: 'plugins/links'
|
||||||
gem 'foodsoft_polls', path: 'plugins/polls'
|
gem 'foodsoft_polls', path: 'plugins/polls'
|
||||||
|
|
||||||
# plugins not enabled by default
|
# plugins not enabled by default
|
||||||
|
|
|
@ -26,6 +26,13 @@ PATH
|
||||||
rails
|
rails
|
||||||
ruby-filemagic
|
ruby-filemagic
|
||||||
|
|
||||||
|
PATH
|
||||||
|
remote: plugins/links
|
||||||
|
specs:
|
||||||
|
foodsoft_links (0.0.1)
|
||||||
|
deface (~> 1.0)
|
||||||
|
rails
|
||||||
|
|
||||||
PATH
|
PATH
|
||||||
remote: plugins/messages
|
remote: plugins/messages
|
||||||
specs:
|
specs:
|
||||||
|
@ -534,6 +541,7 @@ DEPENDENCIES
|
||||||
faker
|
faker
|
||||||
foodsoft_discourse!
|
foodsoft_discourse!
|
||||||
foodsoft_documents!
|
foodsoft_documents!
|
||||||
|
foodsoft_links!
|
||||||
foodsoft_messages!
|
foodsoft_messages!
|
||||||
foodsoft_polls!
|
foodsoft_polls!
|
||||||
foodsoft_wiki!
|
foodsoft_wiki!
|
||||||
|
|
11
db/migrate/20181203000000_create_links.foodsoft_links.rb
Normal file
11
db/migrate/20181203000000_create_links.foodsoft_links.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class CreateLinks < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :links do |t|
|
||||||
|
t.string :name, null: false
|
||||||
|
t.string :url, null: false
|
||||||
|
t.references :workgroup
|
||||||
|
t.boolean :indirect, null: false, default: false
|
||||||
|
t.string :authorization
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -235,6 +235,14 @@ ActiveRecord::Schema.define(version: 20181205010000) do
|
||||||
|
|
||||||
add_index "invoices", ["supplier_id"], name: "index_invoices_on_supplier_id", using: :btree
|
add_index "invoices", ["supplier_id"], name: "index_invoices_on_supplier_id", using: :btree
|
||||||
|
|
||||||
|
create_table "links", force: :cascade do |t|
|
||||||
|
t.string "name", null: false
|
||||||
|
t.string "url", null: false
|
||||||
|
t.integer "workgroup_id"
|
||||||
|
t.boolean "indirect", default: false, null: false
|
||||||
|
t.string "authorization"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "mail_delivery_status", force: :cascade do |t|
|
create_table "mail_delivery_status", force: :cascade do |t|
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.string "email", limit: 255, null: false
|
t.string "email", limit: 255, null: false
|
||||||
|
|
25
plugins/links/README.md
Normal file
25
plugins/links/README.md
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
FoodsoftLinks
|
||||||
|
=================
|
||||||
|
|
||||||
|
This plugin adds links to foodsoft. A new 'Links' menu entry is added in the
|
||||||
|
navigation bar, if there are visible links for the user.
|
||||||
|
|
||||||
|
This plugin is enabled by default in foodsoft, so you don't need to do anything
|
||||||
|
to install it. If you still want to, for example when it has been disabled,
|
||||||
|
add the following to foodsoft's Gemfile:
|
||||||
|
|
||||||
|
```Gemfile
|
||||||
|
gem 'foodsoft_links', path: 'lib/foodsoft_links'
|
||||||
|
```
|
||||||
|
|
||||||
|
It can be used to link to external services related to the foodcoop.
|
||||||
|
With the indirect mode it is possible to implement a secure login to other
|
||||||
|
services. In that case Foodsoft will send a HTTP GET request and redirect
|
||||||
|
the user to the returned Location header. This allows the generation of
|
||||||
|
a one-time login URL.
|
||||||
|
A typical use-case would be that a workgroup, which is responsible for
|
||||||
|
the email account, does not need to share the login credentials and can
|
||||||
|
use a link within the Foodsoft instead.
|
||||||
|
|
||||||
|
This plugin is part of the foodsoft package and uses the AGPL-3 license (see
|
||||||
|
foodsoft's LICENSE for the full license text).
|
40
plugins/links/Rakefile
Normal file
40
plugins/links/Rakefile
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#!/usr/bin/env rake
|
||||||
|
begin
|
||||||
|
require 'bundler/setup'
|
||||||
|
rescue LoadError
|
||||||
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
||||||
|
end
|
||||||
|
begin
|
||||||
|
require 'rdoc/task'
|
||||||
|
rescue LoadError
|
||||||
|
require 'rdoc/rdoc'
|
||||||
|
require 'rake/rdoctask'
|
||||||
|
RDoc::Task = Rake::RDocTask
|
||||||
|
end
|
||||||
|
|
||||||
|
RDoc::Task.new(:rdoc) do |rdoc|
|
||||||
|
rdoc.rdoc_dir = 'rdoc'
|
||||||
|
rdoc.title = 'FoodsoftLinks'
|
||||||
|
rdoc.options << '--line-numbers'
|
||||||
|
rdoc.rdoc_files.include('README.rdoc')
|
||||||
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||||
|
end
|
||||||
|
|
||||||
|
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
||||||
|
load 'rails/tasks/engine.rake'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Bundler::GemHelper.install_tasks
|
||||||
|
|
||||||
|
require 'rake/testtask'
|
||||||
|
|
||||||
|
Rake::TestTask.new(:test) do |t|
|
||||||
|
t.libs << 'lib'
|
||||||
|
t.libs << 'test'
|
||||||
|
t.pattern = 'test/**/*_test.rb'
|
||||||
|
t.verbose = false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
task :default => :test
|
29
plugins/links/app/controllers/links_controller.rb
Normal file
29
plugins/links/app/controllers/links_controller.rb
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
require 'net/http'
|
||||||
|
|
||||||
|
class LinksController < ApplicationController
|
||||||
|
def show
|
||||||
|
link = Link.find(params[:id])
|
||||||
|
url = link.url
|
||||||
|
|
||||||
|
if link.workgroup && !current_user.role_admin? && !link.workgroup.member?(current_user)
|
||||||
|
return deny_access
|
||||||
|
end
|
||||||
|
|
||||||
|
if link.indirect
|
||||||
|
uri = URI.parse url
|
||||||
|
request = Net::HTTP::Get.new uri
|
||||||
|
request['Authorization'] = link.authorization if link.authorization
|
||||||
|
result = Net::HTTP.start uri.host, uri.port, use_ssl: uri.scheme == 'https' do |http|
|
||||||
|
http.request request
|
||||||
|
end
|
||||||
|
|
||||||
|
url = result.header['Location']
|
||||||
|
|
||||||
|
unless url
|
||||||
|
return redirect_to root_url, alert: t('.indirect_no_location')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
redirect_to url, status: 302
|
||||||
|
end
|
||||||
|
end
|
5
plugins/links/app/models/link.rb
Normal file
5
plugins/links/app/models/link.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
class Link < ApplicationRecord
|
||||||
|
belongs_to :workgroup
|
||||||
|
|
||||||
|
scope :ordered, -> { order(:name) }
|
||||||
|
end
|
6
plugins/links/config/locales/de.yml
Normal file
6
plugins/links/config/locales/de.yml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
de:
|
||||||
|
links:
|
||||||
|
show:
|
||||||
|
indirect_no_location: Die konfigurierte URL hat keinen Location Header für die Weiterleitung zurück gegeben.
|
||||||
|
navigation:
|
||||||
|
links: Links
|
6
plugins/links/config/locales/en.yml
Normal file
6
plugins/links/config/locales/en.yml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
en:
|
||||||
|
links:
|
||||||
|
show:
|
||||||
|
indirect_no_location: The configured URL did not return a Location header for redirection.
|
||||||
|
navigation:
|
||||||
|
links: Links
|
9
plugins/links/config/routes.rb
Normal file
9
plugins/links/config/routes.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
Rails.application.routes.draw do
|
||||||
|
|
||||||
|
scope '/:foodcoop' do
|
||||||
|
|
||||||
|
resources :links, only: [:show]
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
11
plugins/links/db/migrate/20181203000000_create_links.rb
Normal file
11
plugins/links/db/migrate/20181203000000_create_links.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class CreateLinks < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :links do |t|
|
||||||
|
t.string :name, null: false
|
||||||
|
t.string :url, null: false
|
||||||
|
t.references :workgroup
|
||||||
|
t.boolean :indirect, null: false, default: false
|
||||||
|
t.string :authorization
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
21
plugins/links/foodsoft_links.gemspec
Normal file
21
plugins/links/foodsoft_links.gemspec
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
$:.push File.expand_path("../lib", __FILE__)
|
||||||
|
|
||||||
|
# Maintain your gem's version:
|
||||||
|
require "foodsoft_links/version"
|
||||||
|
|
||||||
|
# Describe your gem and declare its dependencies:
|
||||||
|
Gem::Specification.new do |s|
|
||||||
|
s.name = "foodsoft_links"
|
||||||
|
s.version = FoodsoftLinks::VERSION
|
||||||
|
s.authors = ["paroga"]
|
||||||
|
s.email = ["paroga@paroga.com"]
|
||||||
|
s.homepage = "https://github.com/foodcoops/foodsoft"
|
||||||
|
s.summary = "Links plugin for foodsoft."
|
||||||
|
s.description = "Adds simple link management to foodsoft."
|
||||||
|
|
||||||
|
s.files = Dir["{app,config,db,lib}/**/*"] + ["Rakefile", "README.md"]
|
||||||
|
s.test_files = Dir["test/**/*"]
|
||||||
|
|
||||||
|
s.add_dependency "rails"
|
||||||
|
s.add_dependency "deface", "~> 1.0"
|
||||||
|
end
|
1
plugins/links/lib/foodsoft_links.rb
Normal file
1
plugins/links/lib/foodsoft_links.rb
Normal file
|
@ -0,0 +1 @@
|
||||||
|
require 'foodsoft_links/engine'
|
27
plugins/links/lib/foodsoft_links/engine.rb
Normal file
27
plugins/links/lib/foodsoft_links/engine.rb
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
module FoodsoftLinks
|
||||||
|
class Engine < ::Rails::Engine
|
||||||
|
def navigation(primary, context)
|
||||||
|
primary.item :links, I18n.t('navigation.links'), '#', if: Proc.new { visble_links(context).any? } do |subnav|
|
||||||
|
visble_links(context).each do |link|
|
||||||
|
subnav.item link.id, link.name, context.link_path(link)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# move to left before admin item
|
||||||
|
if i = primary.items.index(primary[:admin])
|
||||||
|
primary.items.insert(i, primary.items.delete_at(-1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def visble_links(context)
|
||||||
|
ret = Link.ordered
|
||||||
|
|
||||||
|
current_user = context.current_user
|
||||||
|
unless current_user.role_admin?
|
||||||
|
workgroups = current_user.workgroups.map(&:id)
|
||||||
|
ret = ret.where(workgroup: [nil] + workgroups)
|
||||||
|
end
|
||||||
|
|
||||||
|
ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
3
plugins/links/lib/foodsoft_links/version.rb
Normal file
3
plugins/links/lib/foodsoft_links/version.rb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module FoodsoftLinks
|
||||||
|
VERSION = "0.0.1"
|
||||||
|
end
|
Loading…
Reference in a new issue