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_documents', path: 'plugins/documents'
|
||||
gem 'foodsoft_discourse', path: 'plugins/discourse'
|
||||
gem 'foodsoft_links', path: 'plugins/links'
|
||||
gem 'foodsoft_polls', path: 'plugins/polls'
|
||||
|
||||
# plugins not enabled by default
|
||||
|
|
|
@ -26,6 +26,13 @@ PATH
|
|||
rails
|
||||
ruby-filemagic
|
||||
|
||||
PATH
|
||||
remote: plugins/links
|
||||
specs:
|
||||
foodsoft_links (0.0.1)
|
||||
deface (~> 1.0)
|
||||
rails
|
||||
|
||||
PATH
|
||||
remote: plugins/messages
|
||||
specs:
|
||||
|
@ -534,6 +541,7 @@ DEPENDENCIES
|
|||
faker
|
||||
foodsoft_discourse!
|
||||
foodsoft_documents!
|
||||
foodsoft_links!
|
||||
foodsoft_messages!
|
||||
foodsoft_polls!
|
||||
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
|
||||
|
||||
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|
|
||||
t.datetime "created_at"
|
||||
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