gdpr_rails 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +270 -13
  3. data/app/assets/javascripts/policy_manager/application.js +4 -0
  4. data/app/assets/javascripts/policy_manager/portability_requests.js +2 -0
  5. data/app/assets/javascripts/policy_manager/user_portability_requests.js +2 -0
  6. data/app/assets/stylesheets/policy_manager/portability_requests.css +4 -0
  7. data/app/assets/stylesheets/policy_manager/user_portability_requests.css +4 -0
  8. data/app/controllers/policy_manager/application_controller.rb +22 -0
  9. data/app/controllers/policy_manager/categories_controller.rb +5 -47
  10. data/app/controllers/policy_manager/portability_requests_controller.rb +34 -0
  11. data/app/controllers/policy_manager/terms_controller.rb +16 -13
  12. data/app/controllers/policy_manager/user_portability_requests_controller.rb +41 -0
  13. data/app/controllers/policy_manager/user_terms_controller.rb +68 -28
  14. data/app/helpers/policy_manager/application_helper.rb +28 -0
  15. data/app/helpers/policy_manager/portability_requests_helper.rb +4 -0
  16. data/app/helpers/policy_manager/scripts_helper.rb +11 -0
  17. data/app/helpers/policy_manager/terms_helper.rb +1 -1
  18. data/app/helpers/policy_manager/user_portability_requests_helper.rb +4 -0
  19. data/app/jobs/policy_manager/exporter_job.rb +10 -0
  20. data/app/mailers/policy_manager/application_mailer.rb +20 -2
  21. data/app/mailers/policy_manager/portability_mailer.rb +34 -0
  22. data/app/models/policy_manager/concerns/user_behavior.rb +80 -22
  23. data/app/models/policy_manager/portability_request.rb +65 -0
  24. data/app/models/policy_manager/term.rb +18 -0
  25. data/app/models/policy_manager/user_term.rb +14 -7
  26. data/app/views/layouts/policy_manager/application.html.erb +41 -39
  27. data/app/views/layouts/policy_manager/mailer.html.erb +13 -0
  28. data/app/views/layouts/policy_manager/mailer.text.erb +1 -0
  29. data/app/views/policy_manager/categories/index.html.erb +6 -12
  30. data/app/views/policy_manager/categories/show.html.erb +13 -20
  31. data/app/views/policy_manager/portability_mailer/completed_notification.erb +7 -0
  32. data/app/views/policy_manager/portability_mailer/progress_notification.erb +3 -0
  33. data/app/views/policy_manager/portability_requests/index.html.erb +42 -0
  34. data/app/views/policy_manager/portability_requests/index.json.jbuilder +5 -0
  35. data/app/views/policy_manager/terms/_form.html.erb +12 -11
  36. data/app/views/policy_manager/terms/edit.html.erb +6 -4
  37. data/app/views/policy_manager/terms/index.html.erb +12 -13
  38. data/app/views/policy_manager/terms/new.html.erb +5 -3
  39. data/app/views/policy_manager/terms/show.html.erb +12 -10
  40. data/app/views/policy_manager/user_portability_requests/index.html.erb +42 -0
  41. data/app/views/policy_manager/user_portability_requests/index.json.jbuilder +5 -0
  42. data/app/views/policy_manager/user_terms/pending.html.erb +10 -6
  43. data/app/views/policy_manager/user_terms/show.html.erb +7 -8
  44. data/app/views/policy_manager/user_terms/show.json.jbuilder +15 -8
  45. data/config/locales/en.yml +122 -0
  46. data/config/locales/es.yml +122 -0
  47. data/config/routes.rb +15 -6
  48. data/db/migrate/20180326193825_create_policy_manager_terms.rb +1 -0
  49. data/db/migrate/20180410171354_create_policy_manager_portability_requests.rb +18 -0
  50. data/lib/policy_manager/anonimizer.rb +18 -0
  51. data/lib/policy_manager/config.rb +35 -1
  52. data/lib/policy_manager/exporter/handler.rb +110 -0
  53. data/lib/policy_manager/exporter/paginator_renderer.rb +74 -0
  54. data/lib/policy_manager/exporter/view.rb +108 -0
  55. data/lib/policy_manager/exporter/zip_generator.rb +60 -0
  56. data/lib/policy_manager/exporter.rb +75 -0
  57. data/lib/policy_manager/portability_rule.rb +15 -0
  58. data/lib/policy_manager/rule.rb +21 -4
  59. data/lib/policy_manager/script.rb +56 -0
  60. data/lib/policy_manager/templates/index.html.erb +1 -0
  61. data/lib/policy_manager/version.rb +1 -1
  62. data/lib/policy_manager.rb +10 -0
  63. metadata +160 -19
  64. data/app/controllers/policy_manager/dashboard_controller.rb +0 -6
  65. data/app/helpers/policy_manager/categories_helper.rb +0 -4
  66. data/app/helpers/policy_manager/dashboard_helper.rb +0 -4
  67. data/app/helpers/policy_manager/terms_categories_helper.rb +0 -4
  68. data/app/views/policy_manager/categories/_form.html.erb +0 -22
  69. data/app/views/policy_manager/categories/edit.html.erb +0 -6
  70. data/app/views/policy_manager/categories/new.html.erb +0 -5
  71. data/app/views/policy_manager/dashboard/index.erb +0 -33
  72. data/app/views/policy_manager/terms_categories/_form.html.erb +0 -17
  73. data/app/views/policy_manager/terms_categories/edit.html.erb +0 -6
  74. data/app/views/policy_manager/terms_categories/index.html.erb +0 -24
  75. data/app/views/policy_manager/terms_categories/new.html.erb +0 -5
  76. data/app/views/policy_manager/terms_categories/show.html.erb +0 -4
  77. data/app/views/policy_manager/user_terms/_form.html.erb +0 -17
  78. data/app/views/policy_manager/user_terms/edit.html.erb +0 -6
  79. data/app/views/policy_manager/user_terms/index.html.erb +0 -24
  80. data/app/views/policy_manager/user_terms/new.html.erb +0 -5
@@ -1,27 +1,40 @@
1
- require_dependency "terms/application_controller"
2
-
3
- require "request_store"
1
+ require_dependency "policy_manager/application_controller"
4
2
 
5
3
  module PolicyManager
6
4
  class UserTermsController < ApplicationController
5
+
6
+ skip_before_action :user_authenticated?, only: [:show, :accept, :reject, :blocking_terms]
7
7
  before_action :set_user_term, only: [:accept, :reject, :show, :edit, :update, :destroy]
8
8
 
9
- if defined? Doorman
10
- include Doorman::Controller
9
+ # GET /user_terms/1
10
+ def show
11
+ @user_term = current_user.present? ? current_user.handle_policy_for(@term) : UserTerm.new(term: @term, user: nil, state: cookies["policy_rule_#{@term.rule.name}"])
11
12
  end
12
13
 
13
- # GET /user_terms
14
- def index
15
- @user_terms = UserTerm.all
14
+ # GET /pending
15
+ def pending
16
+ @pending_policies = current_user.pending_policies
17
+ respond_to do |format|
18
+ format.html{ }
19
+ format.json{ render json: @pending_policies }
20
+ end
16
21
  end
17
22
 
18
- # GET /user_terms/1
19
- def show
20
- @user_term = current_user.handle_policy_for(@term)
23
+ # GET /blocking_terms
24
+ def blocking_terms
25
+ respond_to do |format|
26
+ format.html{ }
27
+ format.json{ render json: PolicyManager::Config.rules.map{|p| p.name if p.blocking == true }.compact! }
28
+ end
21
29
  end
22
30
 
23
- def pending
31
+ def accept_multiples
32
+ rules = current_user.pending_policies.map{|o| "policy_rule_#{o.name}"}
33
+ resource_params = params.require(:user).permit(rules)
34
+ current_user.update_attributes(resource_params)
35
+
24
36
  @pending_policies = current_user.pending_policies
37
+
25
38
  respond_to do |format|
26
39
  format.html{ }
27
40
  format.json{ render json: @pending_policies }
@@ -29,8 +42,9 @@ module PolicyManager
29
42
  end
30
43
 
31
44
  def accept
32
- @user_term = current_user.handle_policy_for(@term)
33
- @user_term.accept!
45
+
46
+ handle_term_accept
47
+
34
48
  respond_to do |format|
35
49
  format.html{
36
50
  if @user_term.errors.any?
@@ -40,13 +54,18 @@ module PolicyManager
40
54
  end
41
55
  }
42
56
  format.js
43
- format.json
57
+ format.json{
58
+ render json: {
59
+ status: @user_term ? @user_term.state : cookies["policy_rule_#{@term.rule.name}"]
60
+ }
61
+ }
44
62
  end
45
63
  end
46
64
 
47
65
  def reject
48
- @user_term = current_user.handle_policy_for(term: @term)
49
- @user_term.reject!
66
+
67
+ handle_term_reject
68
+
50
69
  respond_to do |format|
51
70
  format.html{
52
71
  if @user_term.errors.any?
@@ -57,13 +76,13 @@ module PolicyManager
57
76
  }
58
77
  format.js
59
78
  format.json{
60
-
61
- if @user_term.errors.any?
62
- render :json, url: root_url , notice: "hey there are some errors! #{@user_term.errors.full_messages.join()}"
79
+ if @user_term.present? && @user_term.errors.any?
80
+ render json: { url: root_url , notice: "hey there are some errors! #{@user_term.errors.full_messages.join()}" }
63
81
  else
64
- render :json, url: root_url
82
+ render json: {
83
+ state: @user_term ? @user_term.state : cookies["policy_rule_#{@term.rule.name}"]
84
+ }
65
85
  end
66
-
67
86
  }
68
87
  end
69
88
  end
@@ -73,10 +92,6 @@ module PolicyManager
73
92
  @user_term = UserTerm.new
74
93
  end
75
94
 
76
- # GET /user_terms/1/edit
77
- def edit
78
- end
79
-
80
95
  # POST /user_terms
81
96
  def create
82
97
  @user_term = UserTerm.new(user_term_params)
@@ -104,11 +119,36 @@ module PolicyManager
104
119
  end
105
120
 
106
121
  private
122
+
123
+ def handle_term_accept
124
+ if current_user
125
+ @user_term = current_user.handle_policy_for(@term)
126
+ if @user_term.accept!
127
+ @term.rule.on_accept.call(self) if @term.rule.on_accept.is_a?(Proc)
128
+ end
129
+ end
130
+
131
+ cookies["policy_rule_#{@term.rule.name}"] = {
132
+ :value => "accepted",
133
+ :expires => 1.year.from_now
134
+ }
135
+ end
136
+
137
+ def handle_term_reject
138
+ if current_user
139
+ @user_term = current_user.handle_policy_for(@term)
140
+ if @user_term.reject!
141
+ @term.rule.on_reject.call(self) if @term.rule.on_reject.is_a?(Proc)
142
+ end
143
+ end
144
+
145
+ cookies.delete("policy_rule_#{@term.rule.name}")
146
+ end
147
+
107
148
  # Use callbacks to share common setup or constraints between actions.
108
149
  def set_user_term
109
- @category = Category.find(params[:id])
150
+ @category = PolicyManager::Config.rules.find{|o| o.name == params[:id]}
110
151
  @term = @category.terms.last
111
- #@term = Term.find(params[:id])
112
152
  end
113
153
 
114
154
  # Only allow a trusted parameter "white list" through.
@@ -1,4 +1,32 @@
1
1
  module PolicyManager
2
2
  module ApplicationHelper
3
+
4
+ def bootstrap_class_for flash_type
5
+ { success: "alert-success", error: "alert-danger", alert: "alert-warning", notice: "alert-info" }[flash_type.to_sym] || flash_type.to_s
6
+ end
7
+
8
+ def flash_messages(opts = {})
9
+
10
+ flash.each do |msg_type, message|
11
+ flash.delete(msg_type)
12
+ concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)}") do
13
+ concat content_tag(:button, "<i class='fa fa-times-circle'></i>".html_safe, class: "close", data: { dismiss: 'alert' })
14
+ concat message
15
+ end)
16
+ end
17
+
18
+ session.delete(:flash)
19
+ nil
20
+ end
21
+
22
+
23
+ def chart(data)
24
+ begin
25
+ column_chart(data.call)
26
+ rescue Groupdate::Error
27
+ content_tag(:p, "chart not displayed, Be sure to install time zone support - https://github.com/ankane/groupdate#for-mysql", class: "alert alert-danger")
28
+ end
29
+ end
30
+
3
31
  end
4
32
  end
@@ -0,0 +1,4 @@
1
+ module PolicyManager
2
+ module PortabilityRequestsHelper
3
+ end
4
+ end
@@ -0,0 +1,11 @@
1
+ module PolicyManager
2
+ module ScriptsHelper
3
+
4
+ def render_scripts
5
+ PolicyManager::Script.scripts.map do |c|
6
+ render( partial: c.script) if c.can_render?
7
+ end.compact.join(" ").html_safe
8
+ end
9
+
10
+ end
11
+ end
@@ -1,4 +1,4 @@
1
1
  module PolicyManager
2
- module PolicyManagerHelper
2
+ module TermsHelper
3
3
  end
4
4
  end
@@ -0,0 +1,4 @@
1
+ module PolicyManager
2
+ module UserPortabilityRequestsHelper
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ module PolicyManager
2
+ class ExporterJob < ApplicationJob
3
+ queue_as :default
4
+
5
+ def perform(user_id)
6
+ user = User.find(user_id)
7
+ Config.exporter.perform(user)
8
+ end
9
+ end
10
+ end
@@ -1,6 +1,24 @@
1
1
  module PolicyManager
2
2
  class ApplicationMailer < ActionMailer::Base
3
- default from: 'from@example.com'
3
+ default from: Config.from_email
4
4
  layout 'mailer'
5
+
6
+ # configurable mailer helpers
7
+ Config.exporter.mail_helpers.each do |helpers|
8
+ add_template_helper(helpers)
9
+ end
10
+
11
+ def send!(opts = {})
12
+
13
+ I18n.locale = Config.user_language(@user)
14
+
15
+ default_opts = {
16
+ :to => @user.email,
17
+ :subject => @subject
18
+ }.merge(opts)
19
+
20
+ mail(default_opts)
21
+ end
22
+
5
23
  end
6
- end
24
+ end
@@ -0,0 +1,34 @@
1
+ module PolicyManager
2
+ class PortabilityMailer < ApplicationMailer
3
+
4
+ def progress_notification(portability_request_id)
5
+ @portability_request = PortabilityRequest.find(portability_request_id)
6
+ @user = User.find(@portability_request.user_id)
7
+ @subject = I18n.t("terms_app.mails.progress.subject")
8
+
9
+ opts = {}
10
+ opts.merge!({
11
+ template_path: PolicyManager::Config.exporter.mailer_templates[:path].to_s,
12
+ template_name: PolicyManager::Config.exporter.mailer_templates[:progress]
13
+ }) if PolicyManager::Config.exporter.mailer_templates.present?
14
+
15
+ send!(opts)
16
+ end
17
+
18
+ def completed_notification(portability_request_id)
19
+ @portability_request = PortabilityRequest.find(portability_request_id)
20
+ @user = User.find(@portability_request.user_id)
21
+ @subject = I18n.t("terms_app.mails.completed.subject")
22
+ @link = @portability_request.download_link
23
+
24
+ opts = {}
25
+ opts.merge!({
26
+ template_path: PolicyManager::Config.exporter.mailer_templates[:path].to_s,
27
+ template_name: PolicyManager::Config.exporter.mailer_templates[:complete]
28
+ }) if PolicyManager::Config.exporter.mailer_templates.present?
29
+
30
+ send!(opts)
31
+ end
32
+
33
+ end
34
+ end
@@ -3,8 +3,73 @@ module PolicyManager::Concerns::UserBehavior
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- has_many :user_terms, class_name: "PolicyManager::UserTerm"
6
+ has_many :user_terms, class_name: "PolicyManager::UserTerm", autosave: true
7
7
  has_many :terms, through: :user_terms
8
+ has_many :portability_requests, class_name: "PolicyManager::PortabilityRequest"
9
+
10
+ # adds policies
11
+ PolicyManager::Config.rules.each do |rule|
12
+ # next if rule. !internal?
13
+ rule_name = "policy_rule_#{rule.name}".to_sym
14
+ attr_accessor rule_name
15
+
16
+ if rule.validates_on
17
+
18
+ validate :"check_#{rule_name}", :on => rule.validates_on, :if => ->(o){
19
+ return true if rule.if.nil?
20
+ rule.if.call(o) rescue true
21
+ }
22
+
23
+ define_method :"check_#{rule_name}" do
24
+ if self.send(rule_name).blank? && needs_policy_confirmation_for?(rule.name)
25
+ errors.add(rule_name, "needs confirmation")
26
+ end
27
+ end
28
+ end
29
+
30
+ define_method :"has_consented_#{rule.name}?" do
31
+ !needs_policy_confirmation_for?(rule.name)
32
+ end
33
+
34
+ define_method :"#{rule_name}=" do |val=true|
35
+ self.instance_variable_set("@#{rule_name}", val)
36
+ ut = user_terms.new
37
+ ut.term = policy_term_on(rule.name)
38
+ val ? ut.accept : ut.reject
39
+ end
40
+ end
41
+
42
+ # adds portability rules
43
+ PolicyManager::Config.portability_rules.each do |rule|
44
+ if rule.collection
45
+ define_method :"portability_collection_#{rule.name}" do |page=1|
46
+ portability_collection_for(rule, page)
47
+ end
48
+ end
49
+
50
+ if rule.member
51
+ define_method :"portability_member_#{rule.name}" do
52
+ portability_member_for(rule)
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ def
59
+
60
+ def portability_schema
61
+ PolicyManager::Config.portability_rules.map(&:name)
62
+ end
63
+
64
+ def portability_member_for(rule)
65
+ self.send(rule.member)
66
+ end
67
+
68
+ def portability_collection_for(rule, page)
69
+ # if kaminari
70
+ # self.send(rule.collection).page(1)
71
+ # if will paginate
72
+ self.send(rule.collection).paginate(page: page, per_page: rule.per)
8
73
  end
9
74
 
10
75
  def pending_policies
@@ -15,6 +80,12 @@ module PolicyManager::Concerns::UserBehavior
15
80
  end
16
81
  end
17
82
 
83
+ def pending_blocking_policies
84
+ PolicyManager::Config.rules.select do |c|
85
+ c.blocking && self.needs_policy_confirmation_for?(c.name)
86
+ end
87
+ end
88
+
18
89
  def confirm_all_policies!
19
90
  peding_policies.each do |c|
20
91
  term = c.terms.last
@@ -31,27 +102,20 @@ module PolicyManager::Concerns::UserBehavior
31
102
 
32
103
  def needs_policy_confirmation_for?(rule)
33
104
  term = policy_term_on(rule)
34
- user_term = policy_user_term_on(rule)
35
- return false if term.blank?
105
+ user_term = policy_user_term_on(term)
36
106
  return true if user_term.blank?
107
+ return true if user_term.rejected?
37
108
  term.created_at > user_term.created_at
38
109
  end
39
110
 
40
- def is_confirmed?
41
- end
42
-
43
- def block_feature?
44
- end
45
-
46
111
  def policy_term_on(rule)
47
112
  category = PolicyManager::Config.rules.find{|o| o.name == rule}
48
- term = category.terms.last
49
- return if term.blank?
113
+ term = category.terms.where(state: "published").last
114
+ raise "no term for #{rule} policy" if term.blank?
50
115
  term
51
116
  end
52
117
 
53
- def policy_user_term_on(rule)
54
- term = policy_term_on(rule)
118
+ def policy_user_term_on(term)
55
119
  return if term.blank?
56
120
  self.user_terms.where(term_id: term.id).first
57
121
  end
@@ -62,14 +126,8 @@ module PolicyManager::Concerns::UserBehavior
62
126
  end
63
127
  end
64
128
 
65
-
66
- #######
67
- ## DATA PORTABILITY
68
- #######
69
-
70
-
71
- #######
72
- ## DATA FOGOTTABILITY
73
- #######
129
+ def can_request_portability?
130
+ self.portability_requests.select{|p| p.pending? || p.progress?}.blank?
131
+ end
74
132
 
75
133
  end
@@ -0,0 +1,65 @@
1
+ require "paperclip"
2
+ require "aasm"
3
+
4
+ module PolicyManager
5
+ class PortabilityRequest < ApplicationRecord
6
+ include Paperclip::Glue
7
+
8
+ belongs_to :user
9
+
10
+ has_attached_file :attachment,
11
+ path: Config.exporter.try(:attachment_path) || Rails.root.join("tmp/portability/:id/build.zip").to_s,
12
+ storage: Config.exporter.try(:attachment_storage) || :filesystem,
13
+ s3_permissions: :private
14
+
15
+ do_not_validate_attachment_file_type :attachment
16
+
17
+ include AASM
18
+
19
+ aasm column: :state do
20
+ state :pending, :initial => true
21
+ state :progress, :after_enter => :handle_progress
22
+ state :completed, :after_enter => :notify_completeness
23
+
24
+ event :confirm do
25
+ transitions from: :pending, to: :progress
26
+ end
27
+
28
+ event :complete do
29
+ transitions from: :progress, to: :completed
30
+ end
31
+ end
32
+
33
+ def user_email
34
+ self.user.email
35
+ end
36
+
37
+ def file_remote_url=(url_value)
38
+ self.attachment = File.open(url_value) unless url_value.blank?
39
+ self.save
40
+ self.complete!
41
+ end
42
+
43
+ def download_link
44
+ self.attachment.expiring_url(PolicyManager::Config.exporter.expiration_link)
45
+ end
46
+
47
+ def handle_progress
48
+ notify_progress
49
+ perform_job
50
+ end
51
+
52
+ def perform_job
53
+ ExporterJob.set(queue: :default).perform_later(self.user.id)
54
+ end
55
+
56
+ def notify_progress
57
+ PortabilityMailer.progress_notification(self.id).deliver_now
58
+ end
59
+
60
+ def notify_completeness
61
+ PortabilityMailer.completed_notification(self.id).deliver_now
62
+ end
63
+
64
+ end
65
+ end
@@ -1,9 +1,27 @@
1
1
  require "redcarpet"
2
+ require "aasm"
2
3
 
3
4
  module PolicyManager
4
5
  class Term < ApplicationRecord
6
+ include AASM
5
7
 
6
8
  validates_presence_of :rule
9
+ validates_presence_of :description
10
+ validates_presence_of :state
11
+
12
+ aasm :column => :state do
13
+ state :draft, :initial => true # db column's default
14
+ state :published
15
+
16
+ event :publish do
17
+ transitions from: :draft, to: :published
18
+ end
19
+
20
+ event :unpublish do
21
+ transitions from: :published, to: :draft
22
+ end
23
+
24
+ end
7
25
 
8
26
  def self.renderer
9
27
  @markdown = markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, autolink: true, tables: true)
@@ -1,18 +1,25 @@
1
+ require "aasm"
2
+
1
3
  module PolicyManager
2
4
  class UserTerm < ApplicationRecord
5
+ include AASM
6
+
3
7
  belongs_to :user
4
8
  belongs_to :term
5
9
 
6
10
  validates_uniqueness_of :term_id, :scope => :user_id
7
11
 
8
- def accept!
9
- self.state = "accepted"
10
- self.save
11
- end
12
+ aasm :column => :state do
13
+ state :rejected, :initial => true
14
+ state :accepted
15
+
16
+ event :accept do
17
+ transitions from: :rejected, to: :accepted
18
+ end
12
19
 
13
- def reject!
14
- self.state = "rejected"
15
- self.save
20
+ event :reject do
21
+ transitions from: :accepted, to: :rejected
22
+ end
16
23
  end
17
24
 
18
25
  end
@@ -1,7 +1,7 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
3
  <head>
4
- <title>Terms</title>
4
+ <title><%= I18n.t("terms_app.title") %></title>
5
5
 
6
6
  <%= csrf_meta_tags %>
7
7
 
@@ -15,77 +15,79 @@
15
15
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
16
16
  <script src="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.js"></script>
17
17
 
18
- <%= stylesheet_link_tag "terms/application", media: "all" %>
19
- <%= javascript_include_tag "terms/application" %>
18
+ <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.10/css/all.css" integrity="sha384-+d0P83n9kaQMCwj8F4RJB66tzIwOKmrdb46+porD/OvrJ+37WqIM7UoBtwHO6Nlg" crossorigin="anonymous">
19
+
20
+ <%= javascript_include_tag "https://www.gstatic.com/charts/loader.js" %>
21
+ <%= stylesheet_link_tag "policy_manager/application", media: "all" %>
22
+ <%= javascript_include_tag "policy_manager/application", debug: false %>
20
23
 
21
24
  </head>
22
25
  <body>
23
26
 
24
27
  <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
25
- <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="#">PREYPROJECT</a>
26
- <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
28
+ <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="/">
29
+ <%= I18n.t("terms_app.sub_title") %></a>
27
30
  <ul class="navbar-nav px-3">
28
31
  <li class="nav-item text-nowrap">
29
- <a class="nav-link" href="#">Sign out</a>
32
+ <% if PolicyManager::Config.logout_url.present? %>
33
+ <a class="nav-link" href="<%= PolicyManager::Config.logout_url %>"><%= I18n.t("terms_app.sign_out") %></a>
34
+ <% end %>
30
35
  </li>
31
36
  </ul>
32
37
  </nav>
33
38
 
34
39
  <div class="container-fluid">
35
-
36
-
37
40
  <div class="row">
38
41
  <nav class="col-md-2 d-none d-md-block bg-light sidebar">
39
42
  <div class="sidebar-sticky">
40
43
  <ul class="nav flex-column">
44
+ <% if PolicyManager::Config.is_admin?(current_user) %>
45
+ <li class="nav-item">
46
+ <a class="nav-link" href="<%= categories_path %>">
47
+ <i class="fas fa-balance-scale"></i>
48
+ <%= I18n.t("terms_app.menu.policies") %>
49
+ </a>
50
+ </li>
51
+ <% end %>
52
+
53
+
54
+ <% if PolicyManager::Config.is_admin?(current_user) %>
55
+ <li class="nav-item">
56
+ <a class="nav-link" href="<%= portability_requests_path %>">
57
+ <i class="fas fa-suitcase"></i>
58
+ <%= I18n.t("terms_app.menu.portability_requests") %>
59
+ </a>
60
+ </li>
61
+ <% end %>
62
+
63
+ <li class="separator"></li>
64
+
41
65
  <li class="nav-item">
42
- <a class="nav-link active" href="<%= root_url %>">
43
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-home"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
44
- Dashboard <span class="sr-only">(current)</span>
66
+ <a class="nav-link" href="<%= pending_user_terms_path %>">
67
+ <i class="fas fa-user-secret"></i>
68
+ <%= I18n.t("terms_app.menu.user_pending_policies") %>
45
69
  </a>
46
70
  </li>
71
+
47
72
  <li class="nav-item">
48
- <a class="nav-link" href="<%= categories_path %>">
49
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
50
- Categories
51
- </a>
52
- </li>
53
-
54
-
55
- <li class="nav-item">
56
- <a class="nav-link" href="<%= pending_user_terms_path %>">
57
- <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>
58
- user's pending policies
73
+ <a class="nav-link" href="<%= user_portability_requests_path %>">
74
+ <i class="fas fa-suitcase"></i>
75
+ <%= I18n.t("terms_app.menu.user_portability_requests") %>
59
76
  </a>
60
77
  </li>
78
+
61
79
  </ul>
62
80
 
63
81
  </div>
64
82
  </nav>
65
83
 
66
84
  <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
67
-
68
- <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
69
- <h1 class="h2">Policies</h1>
70
- <div class="btn-toolbar mb-2 mb-md-0">
71
- <div class="btn-group mr-2">
72
- <button class="btn btn-sm btn-outline-secondary">Share</button>
73
- <button class="btn btn-sm btn-outline-secondary">Export</button>
74
- </div>
75
- </div>
76
- </div>
77
-
78
85
  <p id="notice">
79
- <%= notice %>
86
+ <%= flash_messages %>
80
87
  </p>
81
-
82
88
  <%= yield %>
83
89
  </main>
84
90
  </div>
85
-
86
-
87
-
88
-
89
91
  </div>
90
92
 
91
93
  </body>