gdpr_rails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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>