repository-manager 0.0.13 → 0.0.22
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 +5 -13
- data/.rspec +1 -1
- data/README.md +424 -419
- data/app/models/repo_file.rb +29 -29
- data/app/models/repo_folder.rb +134 -114
- data/app/models/repo_item.rb +65 -64
- data/app/models/sharing.rb +58 -58
- data/app/models/sharings_member.rb +5 -5
- data/config/locales/en/repository_manager.en.yml +19 -0
- data/config/locales/fr/repository_manager.fr.yml +19 -0
- data/db/migrate/20131018214212_create_repository_manager.rb +32 -31
- data/lib/generators/repository_manager/install_generator.rb +32 -32
- data/lib/generators/repository_manager/templates/initializer.rb +11 -11
- data/lib/repository_manager/exceptions.rb +9 -9
- data/lib/repository_manager/has_repository.rb +506 -452
- data/lib/repository_manager/version.rb +1 -1
- data/repository-manager.gemspec +30 -30
- data/spec/dummy/db/migrate/20131016193722_create_users.rb +10 -10
- data/spec/dummy/db/migrate/20131016193834_create_groups.rb +9 -9
- data/spec/dummy/db/migrate/20131016194207_create_groups_users.rb +4 -4
- data/spec/dummy/db/migrate/20131018214212_create_repository_manager.rb +31 -31
- data/spec/dummy/db/schema.rb +66 -66
- data/spec/factories/group.rb +7 -7
- data/spec/factories/repo_file.rb +12 -12
- data/spec/factories/repo_folder.rb +7 -7
- data/spec/factories/user.rb +13 -13
- data/spec/has_repository_spec.rb +280 -281
- data/spec/models/associations_spec.rb +88 -88
- data/spec/models/repository_spec.rb +176 -144
- data/spec/models/share_spec.rb +67 -67
- metadata +34 -37
data/app/models/repo_file.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
|
-
class RepoFile < RepoItem
|
2
|
-
attr_accessible :file, :content_type, :file_size if RepositoryManager.protected_attributes?
|
3
|
-
|
4
|
-
validates :file, presence: true
|
5
|
-
mount_uploader :file, RepoFileUploader
|
6
|
-
before_save :update_asset_attributes
|
7
|
-
|
8
|
-
# Return the name of the file with his extension
|
9
|
-
def name
|
10
|
-
file.url.split('/').last
|
11
|
-
end
|
12
|
-
|
13
|
-
# Downloading this file
|
14
|
-
def download(options = {})
|
15
|
-
path = file.path
|
16
|
-
#render status: :bad_request and return unless File.exist?(path)
|
17
|
-
#send_file(path)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def update_asset_attributes
|
23
|
-
if file.present? && file_changed?
|
24
|
-
self.content_type = file.file.content_type
|
25
|
-
self.file_size = file.file.size
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
1
|
+
class RepoFile < RepoItem
|
2
|
+
attr_accessible :file, :content_type, :file_size if RepositoryManager.protected_attributes?
|
3
|
+
|
4
|
+
validates :file, presence: true
|
5
|
+
mount_uploader :file, RepoFileUploader
|
6
|
+
before_save :update_asset_attributes
|
7
|
+
|
8
|
+
# Return the name of the file with his extension
|
9
|
+
def name
|
10
|
+
file.url.split('/').last
|
11
|
+
end
|
12
|
+
|
13
|
+
# Downloading this file
|
14
|
+
def download(options = {})
|
15
|
+
path = file.path
|
16
|
+
#render status: :bad_request and return unless File.exist?(path)
|
17
|
+
#send_file(path)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def update_asset_attributes
|
23
|
+
if file.present? && file_changed?
|
24
|
+
self.content_type = file.file.content_type
|
25
|
+
self.file_size = file.file.size
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/app/models/repo_folder.rb
CHANGED
@@ -1,114 +1,134 @@
|
|
1
|
-
require 'zip'
|
2
|
-
|
3
|
-
class RepoFolder < RepoItem
|
4
|
-
attr_accessible :name if RepositoryManager.protected_attributes?
|
5
|
-
|
6
|
-
validates :name, presence: true
|
7
|
-
|
8
|
-
# Add a repo_item in the folder.
|
9
|
-
def add!(repo_item)
|
10
|
-
# We check if this name already exist
|
11
|
-
#if repo_item.children.exists?(:name => repo_item.name)
|
12
|
-
if RepoItem.where(name: repo_item.name).where(id: child_ids).first
|
13
|
-
raise RepositoryManager::RepositoryManagerException.new("add failed. The repo_item '#{repo_item.name}' already exist in the folder '#{name}'")
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
end
|
1
|
+
require 'zip'
|
2
|
+
|
3
|
+
class RepoFolder < RepoItem
|
4
|
+
attr_accessible :name if RepositoryManager.protected_attributes?
|
5
|
+
|
6
|
+
validates :name, presence: true
|
7
|
+
|
8
|
+
# Add a repo_item in the folder.
|
9
|
+
def add!(repo_item)
|
10
|
+
# We check if this name already exist
|
11
|
+
#if repo_item.children.exists?(:name => repo_item.name)
|
12
|
+
if RepoItem.where(name: repo_item.name).where(id: child_ids).first
|
13
|
+
raise RepositoryManager::RepositoryManagerException.new("add failed. The repo_item '#{repo_item.name}' already exist in the folder '#{name}'")
|
14
|
+
else
|
15
|
+
repo_item.update_attribute :parent, self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(repo_item)
|
20
|
+
begin
|
21
|
+
add!(repo_item)
|
22
|
+
rescue RepositoryManager::RepositoryManagerException
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Rename the item
|
28
|
+
def rename!(new_name)
|
29
|
+
# We take all siblings without itself
|
30
|
+
sibling_ids_without_itself = self.sibling_ids.delete(self.id)
|
31
|
+
# We check if another item has the same name
|
32
|
+
if RepoItem.where(name: self.name).where(id: sibling_ids_without_itself).first
|
33
|
+
raise RepositoryManager::RepositoryManagerException.new("rename failed. The repo_item '#{new_name}' already exist.'")
|
34
|
+
else
|
35
|
+
self.name = new_name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Rename the item
|
40
|
+
def rename(new_name)
|
41
|
+
begin
|
42
|
+
rename!(new_name)
|
43
|
+
rescue RepositoryManager::RepositoryManagerException
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Download this folder (zip it first)
|
49
|
+
# Return the path to the folder.zip
|
50
|
+
# options can have :
|
51
|
+
# :object => Object : is the object that request the download
|
52
|
+
# If object = nil, it download all the folder
|
53
|
+
# if object is set, it download only the folder that the object `can_read`.
|
54
|
+
# :path => 'path/to/zip/' is the path where the zip is generated
|
55
|
+
def download!(options = {})
|
56
|
+
# Get all the children
|
57
|
+
children = RepoItem.find(child_ids)
|
58
|
+
|
59
|
+
# If something is in the array to add, we zip it
|
60
|
+
if children.length > 0
|
61
|
+
|
62
|
+
# Default values
|
63
|
+
options[:object]? object = options[:object]: object = nil
|
64
|
+
|
65
|
+
RepositoryManager.default_zip_path == true ? path = get_default_download_path(object): path = RepositoryManager.default_zip_path
|
66
|
+
path = options[:path] if options[:path]
|
67
|
+
|
68
|
+
full_path = "#{path}#{name}.zip"
|
69
|
+
|
70
|
+
# Create the directory if not exist
|
71
|
+
dir = File.dirname(full_path)
|
72
|
+
unless File.directory?(dir)
|
73
|
+
FileUtils.mkdir_p(dir)
|
74
|
+
end
|
75
|
+
# Delete the zip if it already exist
|
76
|
+
File.delete(full_path) if File.exist?(full_path)
|
77
|
+
|
78
|
+
Zip::File.open(full_path, Zip::File::CREATE) { |zf|
|
79
|
+
add_repo_item_to_zip(children, zf, object)
|
80
|
+
}
|
81
|
+
return full_path
|
82
|
+
else
|
83
|
+
# Nothing to download here
|
84
|
+
raise RepositoryManager::RepositoryManagerException.new("download failed. Folder #{name} is empty")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def download(options = {})
|
89
|
+
begin
|
90
|
+
download!(options)
|
91
|
+
rescue RepositoryManager::RepositoryManagerException
|
92
|
+
false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# Delete the zip file
|
98
|
+
def delete_zip(options = {})
|
99
|
+
options[:object]? object = options[:object]: object = nil
|
100
|
+
RepositoryManager.default_zip_path == true ? path = get_default_download_path(object): path = RepositoryManager.default_zip_path
|
101
|
+
path = options[:path] if options[:path]
|
102
|
+
|
103
|
+
# Delete the path
|
104
|
+
FileUtils.rm_rf(path)
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
# Returns the default path of the zip file
|
110
|
+
# object is the object that want to download this file
|
111
|
+
def get_default_download_path(object = nil)
|
112
|
+
object ? add_to_path = object.get_default_download_path(''): add_to_path = ''
|
113
|
+
"download/#{add_to_path}#{self.class.to_s.underscore}/#{self.id}/"
|
114
|
+
end
|
115
|
+
|
116
|
+
def add_repo_item_to_zip(children, zf, object = nil, prefix = nil)
|
117
|
+
children.each do |child|
|
118
|
+
# If this is a file, we just add this file to the zip
|
119
|
+
if child.type == 'RepoFile'
|
120
|
+
# Add the file in the zip if the object is authorised to read it.
|
121
|
+
zf.add("#{prefix}#{child.name}", child.file.current_path) if object == nil || !RepositoryManager.accept_nested_sharing || object.can_read?(child)
|
122
|
+
elsif child.type == 'RepoFolder'
|
123
|
+
# If this folder has children, we do it again with it children
|
124
|
+
if child.has_children?
|
125
|
+
# We go in this new directory and add it repo_items
|
126
|
+
add_repo_item_to_zip(RepoItem.find(child.child_ids), zf, object, "#{prefix}#{child.name}/")
|
127
|
+
else
|
128
|
+
# We just create the folder if it is empty
|
129
|
+
zf.mkdir(child.name) if object == nil || !RepositoryManager.accept_nested_sharing || object.can_read?(child)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
data/app/models/repo_item.rb
CHANGED
@@ -1,64 +1,65 @@
|
|
1
|
-
class RepoItem < ActiveRecord::Base
|
2
|
-
attr_accessible :type if RepositoryManager.protected_attributes?
|
3
|
-
|
4
|
-
|
5
|
-
has_ancestry
|
6
|
-
|
7
|
-
# Associate with the User Class
|
8
|
-
belongs_to :owner, :polymorphic => true
|
9
|
-
has_many :sharings, :dependent => :destroy
|
10
|
-
#has_many :members, through: :sharings
|
11
|
-
|
12
|
-
if Rails::VERSION::MAJOR == 4
|
13
|
-
scope :files, -> { where type: 'RepoFile' }
|
14
|
-
scope :folders, -> { where type: 'RepoFolder' }
|
15
|
-
else
|
16
|
-
# Rails 3 does it this way
|
17
|
-
scope :files, where(type: 'RepoFile')
|
18
|
-
scope :folders, where(type: 'RepoFolder')
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
#new_file
|
24
|
-
#new_file.
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#FileUtils.
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
ancestor_and_descendant_ids
|
55
|
-
ancestor_and_descendant_ids << self.
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
1
|
+
class RepoItem < ActiveRecord::Base
|
2
|
+
attr_accessible :type if RepositoryManager.protected_attributes?
|
3
|
+
|
4
|
+
|
5
|
+
has_ancestry
|
6
|
+
|
7
|
+
# Associate with the User Class
|
8
|
+
belongs_to :owner, :polymorphic => true
|
9
|
+
has_many :sharings, :dependent => :destroy
|
10
|
+
#has_many :members, through: :sharings
|
11
|
+
|
12
|
+
if Rails::VERSION::MAJOR == 4
|
13
|
+
scope :files, -> { where type: 'RepoFile' }
|
14
|
+
scope :folders, -> { where type: 'RepoFolder' }
|
15
|
+
else
|
16
|
+
# Rails 3 does it this way
|
17
|
+
scope :files, where(type: 'RepoFile')
|
18
|
+
scope :folders, where(type: 'RepoFolder')
|
19
|
+
end
|
20
|
+
|
21
|
+
# Copy itself into the target_folder
|
22
|
+
def copy(target_folder)
|
23
|
+
#new_file = self.dup
|
24
|
+
#new_file.folder = target_folder
|
25
|
+
#new_file.save!
|
26
|
+
#
|
27
|
+
#path = "#{Rails.root}/uploads/#{Rails.env}/#{new_file.id}/original"
|
28
|
+
#FileUtils.mkdir_p path
|
29
|
+
#FileUtils.cp_r self.attachment.path, "#{path}/#{new_file.id}"
|
30
|
+
#
|
31
|
+
#new_file
|
32
|
+
end
|
33
|
+
|
34
|
+
# Move itself into the target_folder
|
35
|
+
def move!(target_folder)
|
36
|
+
if target_folder.type == 'RepoFolder'
|
37
|
+
self.update_attribute :parent, target_folder
|
38
|
+
else
|
39
|
+
raise RepositoryManager::RepositoryManagerException.new("move failed. target '#{name}' can't be a file")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def move(target_folder)
|
44
|
+
begin
|
45
|
+
move!(target_folder)
|
46
|
+
rescue RepositoryManager::RepositoryManagerException
|
47
|
+
false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns true if it exist a sharing in the ancestors of descendant_ids of the repo_item (without itself)
|
52
|
+
def has_nested_sharing?
|
53
|
+
# An array with the ids of all ancestors and descendants
|
54
|
+
ancestor_and_descendant_ids = []
|
55
|
+
ancestor_and_descendant_ids << self.descendant_ids if self.type == 'RepoFolder' && !self.descendant_ids.empty?
|
56
|
+
ancestor_and_descendant_ids << self.ancestor_ids if !self.ancestor_ids.empty?
|
57
|
+
|
58
|
+
# If it exist a sharing, it returns true
|
59
|
+
if Sharing.where(repo_item_id: ancestor_and_descendant_ids).count > 0
|
60
|
+
true
|
61
|
+
else
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/app/models/sharing.rb
CHANGED
@@ -1,58 +1,58 @@
|
|
1
|
-
class Sharing < ActiveRecord::Base
|
2
|
-
attr_accessible :can_read, :can_create, :can_update, :can_delete, :can_share if RepositoryManager.protected_attributes?
|
3
|
-
|
4
|
-
|
5
|
-
has_many :sharings_members, :dependent => :destroy
|
6
|
-
belongs_to :owner, :polymorphic => true
|
7
|
-
belongs_to :repo_item
|
8
|
-
|
9
|
-
#scope :recipient, lambda { |recipient|
|
10
|
-
# joins(:receipts).where('receipts.receiver_id' => recipient.id,'receipts.receiver_type' => recipient.class.base_class.to_s)
|
11
|
-
#}
|
12
|
-
scope :members, lambda { |member|
|
13
|
-
joins(:sharings_members).where('sharings_members.member_id' => member.id,'sharings_members.member_type' => member.class.base_class.to_s)
|
14
|
-
}
|
15
|
-
|
16
|
-
# Return the authorisations of the sharing for the member
|
17
|
-
def get_authorisations(member)
|
18
|
-
# If the member is the owner, he can do what he want !
|
19
|
-
if self.owner == member
|
20
|
-
return true
|
21
|
-
elsif i = self.sharings_members.where(member_id: member.id, member_type: member.class.base_class.to_s).first
|
22
|
-
return {can_add: i.can_add, can_remove: i.can_remove}
|
23
|
-
else
|
24
|
-
return false
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Add members to the sharing
|
29
|
-
def add_members(members, sharing_permissions = RepositoryManager.default_sharing_permissions)
|
30
|
-
if members.kind_of?(Array)
|
31
|
-
# Add each member to this sharing
|
32
|
-
members.each do |i|
|
33
|
-
sharing_member = SharingsMember.new(sharing_permissions)
|
34
|
-
sharing_member.member = i
|
35
|
-
# Add the sharings members in the sharing
|
36
|
-
self.sharings_members << sharing_member
|
37
|
-
end
|
38
|
-
else
|
39
|
-
sharing_member = SharingsMember.new(sharing_permissions)
|
40
|
-
sharing_member.member = members
|
41
|
-
# Add the sharings members in the sharing
|
42
|
-
self.sharings_members << sharing_member
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Remove members to the sharing
|
47
|
-
def remove_members(members)
|
48
|
-
if members.kind_of?(Array)
|
49
|
-
# Add each member to this sharing
|
50
|
-
members.each do |member|
|
51
|
-
self.sharings_members.where(:member_id => member.id, :member_type => member.class.base_class.to_s).first.destroy
|
52
|
-
end
|
53
|
-
else
|
54
|
-
self.sharings_members.where(:member_id => members.id, :member_type => members.class.base_class.to_s).first.destroy
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
1
|
+
class Sharing < ActiveRecord::Base
|
2
|
+
attr_accessible :can_read, :can_create, :can_update, :can_delete, :can_share if RepositoryManager.protected_attributes?
|
3
|
+
|
4
|
+
|
5
|
+
has_many :sharings_members, :dependent => :destroy
|
6
|
+
belongs_to :owner, :polymorphic => true
|
7
|
+
belongs_to :repo_item
|
8
|
+
|
9
|
+
#scope :recipient, lambda { |recipient|
|
10
|
+
# joins(:receipts).where('receipts.receiver_id' => recipient.id,'receipts.receiver_type' => recipient.class.base_class.to_s)
|
11
|
+
#}
|
12
|
+
scope :members, lambda { |member|
|
13
|
+
joins(:sharings_members).where('sharings_members.member_id' => member.id,'sharings_members.member_type' => member.class.base_class.to_s)
|
14
|
+
}
|
15
|
+
|
16
|
+
# Return the authorisations of the sharing for the member
|
17
|
+
def get_authorisations(member)
|
18
|
+
# If the member is the owner, he can do what he want !
|
19
|
+
if self.owner == member
|
20
|
+
return true
|
21
|
+
elsif i = self.sharings_members.where(member_id: member.id, member_type: member.class.base_class.to_s).first
|
22
|
+
return {can_add: i.can_add, can_remove: i.can_remove}
|
23
|
+
else
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Add members to the sharing
|
29
|
+
def add_members(members, sharing_permissions = RepositoryManager.default_sharing_permissions)
|
30
|
+
if members.kind_of?(Array)
|
31
|
+
# Add each member to this sharing
|
32
|
+
members.each do |i|
|
33
|
+
sharing_member = SharingsMember.new(sharing_permissions)
|
34
|
+
sharing_member.member = i
|
35
|
+
# Add the sharings members in the sharing
|
36
|
+
self.sharings_members << sharing_member
|
37
|
+
end
|
38
|
+
else
|
39
|
+
sharing_member = SharingsMember.new(sharing_permissions)
|
40
|
+
sharing_member.member = members
|
41
|
+
# Add the sharings members in the sharing
|
42
|
+
self.sharings_members << sharing_member
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Remove members to the sharing
|
47
|
+
def remove_members(members)
|
48
|
+
if members.kind_of?(Array)
|
49
|
+
# Add each member to this sharing
|
50
|
+
members.each do |member|
|
51
|
+
self.sharings_members.where(:member_id => member.id, :member_type => member.class.base_class.to_s).first.destroy
|
52
|
+
end
|
53
|
+
else
|
54
|
+
self.sharings_members.where(:member_id => members.id, :member_type => members.class.base_class.to_s).first.destroy
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|