rbac_rls 0.1.0 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bc52fa4bdbbc44cf0d4b6ede8d4d142458a169baed9767a30c1f6549a827520
4
- data.tar.gz: d289b6293db261f8643b702a70c0f8d9affd094385a898e299f1e7b7d6966c25
3
+ metadata.gz: 7ec44866c989046890add9f57eafc781f16a3774e54858a5f4996498fa2e96cb
4
+ data.tar.gz: 1f349e1e5e4011768758345c95349984b0910d33f1652245225217fd7133a83f
5
5
  SHA512:
6
- metadata.gz: 6a7d8a952d7bbb5af6eedee3338ffd0ff76e71384eb82a2c7e0010f58855519cccb653e6b28e5ec29358b0c4a5f700d9663dfe0a372097d1fb2040ea60a5ff9c
7
- data.tar.gz: ae99e701a1bce22e40993385b0f0644a6c49f2aa8e496cf7ed57cd4808133eb8d3ffeb15f70768389728321ddcd741184716a992f35e45dd0cad3aad9fa8528f
6
+ metadata.gz: 86ab0f00de6b4291edbdc4bfb3a8b18a9430af2bd9b3043de979731c9209314be6ba05ac5f8d58f10242957c67947203addc5c8c96d428c9960618af105e8043
7
+ data.tar.gz: 43438f64d3cc5ba86face84828579bc9556e5e81cf0731f0c2aba6edc04abf0cb7f877340934c1e4c86cf5c50055a184e1c6e2b4736801ec1148df60f7b2d1f6
data/README.md CHANGED
@@ -30,6 +30,19 @@ And then add in your application_record.rb and application_controller.rb:
30
30
  include ConnectionRls
31
31
  include ConnectionRlsUser
32
32
  ```
33
+ ```bash
34
+ crie um novo everioniment para rodar as migrations
35
+ por exemplo: duplique um arquivo de app/config/environments configure o deu database.yml com o env
36
+
37
+ exemplo:
38
+ -----------
39
+ migrations:
40
+ <<: *default
41
+ database: main_app_development
42
+ username: username
43
+ password: password
44
+ -----------
45
+ ```
33
46
 
34
47
  And then run this command:
35
48
  ```bash
@@ -0,0 +1,26 @@
1
+ module HelperMethodsPermission
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+
6
+ def has_permission?(type = nil)
7
+ if type == :read
8
+ # and type == :owner_read and type == :owner_change and type == :owner_remove
9
+ end
10
+
11
+ if type == :write
12
+ end
13
+
14
+ if type == :change
15
+ end
16
+
17
+ if type == :remove
18
+ end
19
+
20
+ end
21
+ end
22
+
23
+ class_methods do
24
+ end
25
+
26
+ end
@@ -0,0 +1,33 @@
1
+ module ManageRlsMigrationConcern
2
+ extend ActiveSupport::Concern
3
+
4
+ class_methods {}
5
+
6
+ included { after_destroy :delete_nested_policy }
7
+
8
+ def delete_nested_policy
9
+ down_migrate()
10
+ delete_file(get_migration_file_path)
11
+ end
12
+
13
+ def down_migrate(file_version = migration_version)
14
+ return true if system(Settings.down_migrate_command(file_version))
15
+ false
16
+ end
17
+
18
+ def get_migration_file_path(file_name = migration_version)
19
+ path = Rails.root.join('db', 'migrate', "#{file_name}*").to_s
20
+ file_path = Dir[path]&.first
21
+ file_path.to_s
22
+ end
23
+
24
+ def delete_file(path)
25
+ deleted = false
26
+ if File.exist?(path)
27
+ File.delete(path)
28
+ deleted = !File.exist?(path)
29
+ end
30
+ deleted
31
+ end
32
+
33
+ end
@@ -1,20 +1,40 @@
1
1
  module RbacRls
2
2
  class GroupPermission < ApplicationRecord
3
+ include ManageRlsMigrationConcern
4
+
3
5
  self.table_name = :group_permissions
4
6
  belongs_to :permission
5
7
  belongs_to :group
6
- after_save :create_group_rls_policy
8
+ after_validation :create_group_rls_policy
7
9
 
8
10
  #rails generate rbac_rls:group_permission table_name description:table_key 'produto':table_value
9
11
  def create_group_rls_policy
10
- cmd = ""
11
- if self.permission.table_name.present? and self.table_key.present? and self.table_value.present?
12
- cmd = "rails generate rbac_rls:group_permission #{self.permission.table_name} '#{self.table_key}':table_key '#{self.table_value}':table_value"
12
+ if permission.table_name.present? and table_key.present? and table_value.present?
13
+ cmd = -> { "rails generate rbac_rls:group_permission #{permission.table_name} '#{table_key}':table_key '#{table_value}':table_value" }
14
+ migraion_generated = false
15
+ migraion_generated = system(cmd.===) if new_record?
16
+ migraion_generated = system(cmd.===) if persisted? and database_changed? and drop_policy()
17
+ if migraion_generated
18
+ system(Settings.run_migrate_command)
19
+ self.migration_version = ActiveRecord::Migrator.current_version
20
+ end
13
21
  end
14
- if cmd.present?
15
- system(cmd)
16
- system('rake db:migrate RAILS_ENV=migrations')
22
+ end
23
+
24
+ def drop_policy()
25
+ r_value = false
26
+ r_value = true if migration_version.nil?
27
+ if persisted? && delete_nested_policy()
28
+ self.migration_version = nil
29
+ r_value = true
17
30
  end
31
+ r_value
18
32
  end
33
+
34
+ def database_changed?
35
+ attrs_in_database = self.class.find(id).attributes
36
+ attributes != attrs_in_database
37
+ end
38
+
19
39
  end
20
- end
40
+ end
@@ -1,5 +1,5 @@
1
1
  class RbacRls::Permission < ApplicationRecord
2
-
2
+ include ManageRlsMigrationConcern
3
3
  self.table_name = :permissions
4
4
  belongs_to :permission, :class_name => 'RbacRls::Permission', optional: true
5
5
  has_many :role_permissions, :class_name => 'RbacRls::RolePermission'
@@ -10,10 +10,10 @@ class RbacRls::Permission < ApplicationRecord
10
10
  validates_uniqueness_of :name, message: "This permission already exists"
11
11
  validates_presence_of :table_name
12
12
  before_validation :set_permission_name
13
- after_commit :create_rls_policy
13
+ after_validation :create_rls_policy
14
14
 
15
- def self.all_tables(schema = :public)
16
15
 
16
+ def self.all_tables(schema = :public)
17
17
  sql = "SELECT table_name FROM information_schema.tables #{where_schema(schema)} "
18
18
  result = ActiveRecord::Base.connection.select_all(sql)
19
19
  tables = result.map { |k| k['table_name'] }
@@ -40,18 +40,13 @@ class RbacRls::Permission < ApplicationRecord
40
40
  cmd += " delete:role " if remove.present?
41
41
  cmd
42
42
  end
43
- type_options = -> () do
44
- cmd = ""
45
- cmd += " --permission_identifier #{self.id} " if self.id.present?
46
- cmd
47
- end
48
-
49
- if (type_policies.===).present? and (type_options.===).present? &&
50
- RbacRls::Permission.all.map(&:table_name).exclude?(table_name)
43
+ type_options = -> () { " --permission_identifier #{self.id} " if self.id.present? }
51
44
 
45
+ if RbacRls::Permission.all.map(&:table_name).exclude?(table_name) && migration_version.nil?
52
46
  cmd = "rails generate rbac_rls:custom_migration #{table_name} #{type_policies.===} #{type_options.===}"
53
- system(cmd)
54
- system('rake db:migrate RAILS_ENV=migrations')
47
+ if system(cmd) && system(Settings.run_migrate_command)
48
+ self.migration_version = ActiveRecord::Migrator.current_version
49
+ end
55
50
  end
56
51
  end
57
52
 
@@ -65,4 +60,5 @@ class RbacRls::Permission < ApplicationRecord
65
60
 
66
61
  def has_role_permission?() end
67
62
 
63
+
68
64
  end
@@ -0,0 +1,3 @@
1
+ module Settings
2
+
3
+ end
@@ -1,7 +1,7 @@
1
1
  <div role="main">
2
2
  <div class="jumbotron">
3
3
  <div class="container">
4
- <h1 class="display-3">RBAC RLS GEM <i class="fas fa-gem"></i></h1>
4
+ <h1 class="display-3">GRANAR <i class="fas fa-gem"></i></h1>
5
5
  <p>This is a GEM based on RBAC and RLS, to control users' access to information</p>
6
6
  </div>
7
7
  <hr>
@@ -10,6 +10,7 @@ class CreateRbacRlsPermissions < ActiveRecord::Migration[7.0]
10
10
  t.boolean :owner_read, default: false
11
11
  t.boolean :owner_change, default: false
12
12
  t.boolean :owner_remove, default: false
13
+ t.string :migration_version, default: nil
13
14
  t.references :permission, null: true, index: true
14
15
 
15
16
  t.timestamps
@@ -5,6 +5,7 @@ class CreateRbacRlsGroupPermissions < ActiveRecord::Migration[7.0]
5
5
  t.references :group, null: false, foreign_key: true
6
6
  t.string :table_key, null: false, limit: 60
7
7
  t.string :table_value, null: false, limit: 60
8
+ t.string :migration_version, default: nil
8
9
 
9
10
  t.timestamps
10
11
  end
@@ -1,7 +1,7 @@
1
1
  class CreateBasicPermissionsForApplicationAcess < ActiveRecord::Migration[7.0]
2
2
  def change
3
3
  schema = 'public'
4
- user = 'app_user'
4
+ user = RbacRls::Settings.application_db_user
5
5
  where_schema = ->(schema_name = nil) do
6
6
  schema_name.present? ? "WHERE table_schema = '#{schema_name}'" : ''
7
7
  end
@@ -13,6 +13,6 @@ class CreateBasicPermissionsForApplicationAcess < ActiveRecord::Migration[7.0]
13
13
  execute "GRANT ALL PRIVILEGES on #{schema}.#{table} TO #{user}"
14
14
  end
15
15
 
16
- execute 'GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO app_user'
16
+ execute "GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO #{RbacRls::Settings.application_db_user}"
17
17
  end
18
18
  end
@@ -21,7 +21,7 @@ class Create<%= "#{"#{name}#{options[:identifier]}".camelize}" %>Gpolicy < Activ
21
21
  def change
22
22
  <%
23
23
  policy_name = ->(table_name,method) { "p#{time_now}#{table_name}#{method}"[0,limit_policy_name] }
24
- db_role = "app_user"
24
+ db_role = "#{RbacRls::Settings.application_db_user}"
25
25
  permission_id = options[:permission_identifier]
26
26
  owner_rls_policy = ->(type){
27
27
  if type.to_sym != :insert
@@ -53,17 +53,18 @@ def change
53
53
  WHERE (p.\"#{type_polices[type.to_sym]}\")
54
54
  AND p.table_name = '#{gen_table_name}'
55
55
  )
56
- ) #{owner_rls_policy[type]} ) and #{table_key.to_s} LIKE '%#{table_value}%'
56
+ ) #{owner_rls_policy[type]} ) and CAST( #{table_key.to_s} AS TEXT) LIKE '%#{table_value}%'
57
57
 
58
58
  "
59
59
  }
60
60
  %>
61
61
 
62
62
  <% %i(insert select update delete).each do |attr| %>
63
- execute '<%="GRANT #{attr} ON #{name} TO #{db_role}"%>'
64
- execute '<%= "ALTER TABLE #{name} ENABLE ROW LEVEL SECURITY" %>'
63
+
65
64
  reversible do |dir|
66
65
  dir.up do
66
+ execute '<%="GRANT #{attr} ON #{name} TO #{db_role}"%>'
67
+ execute '<%= "ALTER TABLE #{name} ENABLE ROW LEVEL SECURITY" %>'
67
68
  <%if attr.to_sym ==:insert %>
68
69
  execute <<-SQL
69
70
  <%= "CREATE POLICY #{policy_name.(name, attr.to_sym)} ON #{name} for #{attr.to_s} TO #{db_role} with check (#{constraint_for_rls[attr.to_s]})" %>
@@ -74,6 +75,11 @@ def change
74
75
  SQL
75
76
  <%end%>
76
77
  end
78
+ dir.down do
79
+ execute <<-SQL
80
+ <%= "DROP POLICY #{policy_name.(name, attr.to_sym)} ON #{name}" %>
81
+ SQL
82
+ end
77
83
  end
78
84
  <% end %>
79
85
 
@@ -18,7 +18,7 @@ class Create<%= "#{name.underscore.camelize}#{options[:permission_identifier]}"
18
18
  def change
19
19
  <%
20
20
  policy_name = ->(table_name,method) { "p#{time_now}#{table_name}#{method}"[0,limit_policy_name] }
21
- db_role = "app_user"
21
+ db_role = RbacRls::Settings.application_db_user
22
22
  permission_id = options[:permission_identifier]
23
23
  owner_rls_policy = ->(type){
24
24
  if type.to_sym != :insert
@@ -58,10 +58,11 @@ def change
58
58
 
59
59
 
60
60
  <% %i(insert select update delete).each do |attr| %>
61
- execute '<%="GRANT #{attr} ON #{name} TO #{db_role}"%>'
62
- execute '<%= "ALTER TABLE #{name} ENABLE ROW LEVEL SECURITY" %>'
61
+
63
62
  reversible do |dir|
64
63
  dir.up do
64
+ execute '<%="GRANT #{attr} ON #{name} TO #{db_role}"%>'
65
+ execute '<%= "ALTER TABLE #{name} ENABLE ROW LEVEL SECURITY" %>'
65
66
  <%if attr.to_sym ==:insert %>
66
67
  execute <<-SQL
67
68
  <%= "CREATE POLICY #{policy_name.(name, attr.to_sym)} ON #{name} for #{attr.to_s} TO #{db_role} with check (#{constraint_for_rls[attr.to_s]})" %>
@@ -72,6 +73,11 @@ def change
72
73
  SQL
73
74
  <%end%>
74
75
  end
76
+ dir.down do
77
+ execute <<-SQL
78
+ <%= "DROP POLICY #{policy_name.(name, attr.to_sym)} ON #{name}" %>
79
+ SQL
80
+ end
75
81
  end
76
82
  <% end %>
77
83
 
@@ -8,12 +8,14 @@ type_polices_owner = {insert: :owner_write,select: :owner_read,update: :owner_ch
8
8
 
9
9
  %>
10
10
 
11
- class Create<%= "#{name.underscore.camelize}" %>Policy<%="#{}" %> < ActiveRecord::Migration[7.0]
11
+ class Create <%= "#{name.underscore.camelize}" %>
12
+ Policy <%="#{}" %> < ActiveRecord::Migration[7.0]
12
13
 
13
14
  def change
14
15
  <%
15
16
  policy_name = ->(table_name,method) { "p#{time_now}#{table_name}#{method}"[0,limit_policy_name] }
16
- db_role = "app_user"
17
+ db_role = RbacRls::Settings.application_db_user
18
+
17
19
  permission_id = options[:permission_identifier]
18
20
 
19
21
  constraint_for_rls = ->(type) {"
@@ -44,8 +46,8 @@ class Create<%= "#{name.underscore.camelize}" %>Policy<%="#{}" %> < ActiveRecord
44
46
  }
45
47
  %>
46
48
  <% %i(insert select update delete).each do |attr| %>
47
- execute '<%="GRANT #{attr} ON #{name} TO #{db_role}"%>'
48
- execute '<%= "ALTER TABLE #{name} ENABLE ROW LEVEL SECURITY" %>'
49
+ execute ' <%="GRANT #{attr} ON #{name} TO #{db_role}"%> '
50
+ execute ' <%= "ALTER TABLE #{name} ENABLE ROW LEVEL SECURITY" %> '
49
51
  reversible do |dir|
50
52
  dir.up do
51
53
  <%if attr.to_sym ==:insert %>
@@ -58,6 +60,11 @@ class Create<%= "#{name.underscore.camelize}" %>Policy<%="#{}" %> < ActiveRecord
58
60
  SQL
59
61
  <%end%>
60
62
  end
63
+ dir.down do
64
+ execute <<-SQL
65
+ <%= "DROP POLICY #{policy_name.(name, attr.to_sym)} ON #{name}" %>
66
+ SQL
67
+ end
61
68
  end
62
69
  <% end %>
63
70
  end
@@ -17,7 +17,8 @@ class Create<%= "#{name.underscore.camelize}#{options[:permission_identifier]}"
17
17
  def change
18
18
  <%
19
19
  policy_name = ->(table_name,method) { "p#{time_now}#{table_name}#{method}"[0,limit_policy_name] }
20
- db_role = "app_user"
20
+ db_role = RbacRls::Settings.application_db_user
21
+
21
22
  permission_id = options[:permission_identifier]
22
23
  owner_rls_policy = ->(type){
23
24
  if type.to_sym != :insert
@@ -10,6 +10,7 @@ require 'vanilla_nested/view_helpers'
10
10
 
11
11
  module RbacRls
12
12
  class Engine < ::Rails::Engine
13
+
13
14
  isolate_namespace RbacRls
14
15
 
15
16
  # initializer "rbac_rls.precompile" do |app|
@@ -1,3 +1,3 @@
1
1
  module RbacRls
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.2"
3
3
  end
data/lib/rbac_rls.rb CHANGED
@@ -2,5 +2,17 @@ require "rbac_rls/version"
2
2
  require "rbac_rls/engine"
3
3
 
4
4
  module RbacRls
5
- # Your code goes here...
5
+ module Settings
6
+ def self.run_migrate_command
7
+ "rake db:migrate RAILS_ENV=migrations"
8
+ end
9
+
10
+ def self.down_migrate_command(version = nil)
11
+ "rake db:migrate:down VERSION=#{version} RAILS_ENV=migrations"
12
+ end
13
+
14
+ def self.application_db_user
15
+ "app_user"
16
+ end
17
+ end
6
18
  end
@@ -1,4 +1,55 @@
1
- # desc "Explaining what the task does"
2
- # task :rbac_rls do
3
- # # Task goes here
4
- # end
1
+ desc "Explaining what the task does"
2
+ task :rbac_rls do
3
+ #frozen_string_literal: true
4
+
5
+ desc 'Uninstall gem'
6
+
7
+ task :uninstall_gem => :environment do
8
+ cmds = ['ALTER TABLE products DISABLE ROW LEVEL SECURITY']
9
+ permissions = RbacRls::Permission.all.map(&:migration_version)
10
+ basic_permissions = ["20220411125339",
11
+ "20220912104712",
12
+ "20220411125613",
13
+ "20220912104929",
14
+ "20220411133054",
15
+ "20220914004802",
16
+ "20220425212731",
17
+ "20220914004803",]
18
+
19
+
20
+ create_rbac_rls_roles.rbac_rls.rb from rbac_rls
21
+ create_rbac_rls_user_roles.rbac_rls.rb from rbac_rls
22
+ create_rbac_rls_permissions.rbac_rls.rb from rbac_rls
23
+ create_role_permissions.rbac_rls.rb from rbac_rls
24
+ create_rbac_rls_groups.rbac_rls.rb from rbac_rls
25
+ create_rbac_rls_group_permissions.rbac_rls.rb from rbac_rls
26
+ create_rbac_rls_group_users.rbac_rls.rb from rbac_rls
27
+ create_basic_permissions_for_application_acess.rbac_rls.rb
28
+ versions = permissions + basic_permissions
29
+ for migration in versions
30
+ system(RbacRls::Settings.down_migrate_command(migration))
31
+ delete_file(get_migration_file_path(migration))
32
+ end
33
+
34
+ for cmd in cmds
35
+ ActiveRecord::Base.connection.execute(cmd)
36
+ end
37
+
38
+ end
39
+
40
+ def get_migration_file_path(file_name = migration_version)
41
+ path = Rails.root.join('db', 'migrate', "#{file_name}*").to_s
42
+ file_path = Dir[path]&.first
43
+ file_path.to_s
44
+ end
45
+
46
+ def delete_file(path)
47
+ deleted = false
48
+ if File.exist?(path)
49
+ File.delete(path)
50
+ deleted = !File.exist?(path)
51
+ end
52
+ deleted
53
+ end
54
+
55
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbac_rls
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - FilipeBeserraMaia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-09-29 00:00:00.000000000 Z
11
+ date: 2022-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: byebug
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
69
  description: Description of RbacRls.
84
70
  email:
85
71
  - filipeifgcc@gmail.com
@@ -94,6 +80,7 @@ files:
94
80
  - app/assets/javascripts/rbac_rls/application.js
95
81
  - app/assets/stylesheets/rbac_rls/application.css.scss
96
82
  - app/controllers/concerns/connection_rls_user_concern.rb
83
+ - app/controllers/concerns/helper_methods_permission.rb
97
84
  - app/controllers/rbac_rls/application_controller.rb
98
85
  - app/controllers/rbac_rls/groups_controller.rb
99
86
  - app/controllers/rbac_rls/home_controller.rb
@@ -106,6 +93,7 @@ files:
106
93
  - app/jobs/rbac_rls/application_job.rb
107
94
  - app/mailers/rbac_rls/application_mailer.rb
108
95
  - app/models/concerns/connection_rls_concern.rb
96
+ - app/models/concerns/manage_rls_migration_concern.rb
109
97
  - app/models/rbac_rls/application_record.rb
110
98
  - app/models/rbac_rls/group.rb
111
99
  - app/models/rbac_rls/group_permission.rb
@@ -113,6 +101,7 @@ files:
113
101
  - app/models/rbac_rls/permission.rb
114
102
  - app/models/rbac_rls/role.rb
115
103
  - app/models/rbac_rls/role_permission.rb
104
+ - app/models/rbac_rls/settings.rb
116
105
  - app/models/rbac_rls/user_role.rb
117
106
  - app/views/layouts/rbac_rls/application.html.erb
118
107
  - app/views/rbac_rls/groups/_form.html.erb
@@ -142,7 +131,6 @@ files:
142
131
  - config/assets.rb
143
132
  - config/importmap.rb
144
133
  - config/routes.rb
145
- - config/setup.rb
146
134
  - db/migrate/20220411125339_create_rbac_rls_roles.rb
147
135
  - db/migrate/20220411125613_create_rbac_rls_user_roles.rb
148
136
  - db/migrate/20220411133054_create_rbac_rls_permissions.rb
@@ -162,12 +150,12 @@ files:
162
150
  - lib/rbac_rls/engine.rb
163
151
  - lib/rbac_rls/version.rb
164
152
  - lib/tasks/rbac_rls_tasks.rake
165
- homepage: https://rubygems.org/rbac_rls
153
+ homepage: https://rubygems.org/granar
166
154
  licenses:
167
155
  - MIT
168
156
  metadata:
169
157
  allowed_push_host: https://rubygems.org/
170
- homepage_uri: https://rubygems.org/rbac_rls
158
+ homepage_uri: https://rubygems.org/granar
171
159
  source_code_uri: https://gitlab.com/FilipeBeserraMaia/rbac_rls
172
160
  changelog_uri: https://gitlab.com/FilipeBeserraMaia/rbac_rls
173
161
  post_install_message:
data/config/setup.rb DELETED
File without changes