sufia-models 0.0.1

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 (67) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.md +177 -0
  5. data/README.md +29 -0
  6. data/Rakefile +1 -0
  7. data/app/models/batch.rb +46 -0
  8. data/app/models/checksum_audit_log.rb +35 -0
  9. data/app/models/contact_form.rb +42 -0
  10. data/app/models/datastreams/batch_rdf_datastream.rb +23 -0
  11. data/app/models/datastreams/file_content_datastream.rb +18 -0
  12. data/app/models/datastreams/fits_datastream.rb +188 -0
  13. data/app/models/datastreams/generic_file_rdf_datastream.rb +75 -0
  14. data/app/models/datastreams/paranoid_rights_datastream.rb +37 -0
  15. data/app/models/datastreams/properties_datastream.rb +33 -0
  16. data/app/models/domain_term.rb +18 -0
  17. data/app/models/follow.rb +28 -0
  18. data/app/models/generic_file.rb +16 -0
  19. data/app/models/geo_names_resource.rb +34 -0
  20. data/app/models/group.rb +8 -0
  21. data/app/models/local_authority.rb +93 -0
  22. data/app/models/local_authority_entry.rb +18 -0
  23. data/app/models/single_use_link.rb +26 -0
  24. data/app/models/subject_local_authority_entry.rb +16 -0
  25. data/app/models/trophy.rb +12 -0
  26. data/app/models/version_committer.rb +17 -0
  27. data/lib/sufia/models.rb +11 -0
  28. data/lib/sufia/models/active_fedora/redis.rb +49 -0
  29. data/lib/sufia/models/active_record/redis.rb +56 -0
  30. data/lib/sufia/models/engine.rb +34 -0
  31. data/lib/sufia/models/file_content.rb +9 -0
  32. data/lib/sufia/models/file_content/extract_metadata.rb +60 -0
  33. data/lib/sufia/models/file_content/versions.rb +23 -0
  34. data/lib/sufia/models/generic_file.rb +183 -0
  35. data/lib/sufia/models/generic_file/actions.rb +39 -0
  36. data/lib/sufia/models/generic_file/audit.rb +119 -0
  37. data/lib/sufia/models/generic_file/characterization.rb +81 -0
  38. data/lib/sufia/models/generic_file/export.rb +339 -0
  39. data/lib/sufia/models/generic_file/permissions.rb +64 -0
  40. data/lib/sufia/models/generic_file/thumbnail.rb +91 -0
  41. data/lib/sufia/models/id_service.rb +57 -0
  42. data/lib/sufia/models/jobs/audit_job.rb +65 -0
  43. data/lib/sufia/models/jobs/batch_update_job.rb +86 -0
  44. data/lib/sufia/models/jobs/characterize_job.rb +43 -0
  45. data/lib/sufia/models/jobs/content_delete_event_job.rb +31 -0
  46. data/lib/sufia/models/jobs/content_deposit_event_job.rb +32 -0
  47. data/lib/sufia/models/jobs/content_new_version_event_job.rb +32 -0
  48. data/lib/sufia/models/jobs/content_restored_version_event_job.rb +40 -0
  49. data/lib/sufia/models/jobs/content_update_event_job.rb +32 -0
  50. data/lib/sufia/models/jobs/event_job.rb +33 -0
  51. data/lib/sufia/models/jobs/ffmpeg_transcode_job.rb +61 -0
  52. data/lib/sufia/models/jobs/resolrize_job.rb +23 -0
  53. data/lib/sufia/models/jobs/transcode_audio_job.rb +40 -0
  54. data/lib/sufia/models/jobs/transcode_video_job.rb +39 -0
  55. data/lib/sufia/models/jobs/unzip_job.rb +54 -0
  56. data/lib/sufia/models/jobs/user_edit_profile_event_job.rb +35 -0
  57. data/lib/sufia/models/jobs/user_follow_event_job.rb +37 -0
  58. data/lib/sufia/models/jobs/user_unfollow_event_job.rb +38 -0
  59. data/lib/sufia/models/model_methods.rb +39 -0
  60. data/lib/sufia/models/noid.rb +42 -0
  61. data/lib/sufia/models/solr_document_behavior.rb +125 -0
  62. data/lib/sufia/models/user.rb +126 -0
  63. data/lib/sufia/models/utils.rb +36 -0
  64. data/lib/sufia/models/version.rb +5 -0
  65. data/lib/tasks/sufia-models_tasks.rake +4 -0
  66. data/sufia-models.gemspec +28 -0
  67. metadata +151 -0
@@ -0,0 +1,32 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class ContentNewVersionEventJob < EventJob
16
+ def run
17
+ gf = GenericFile.find(generic_file_id)
18
+ action = "User #{link_to_profile depositor_id} has added a new version of #{link_to gf.title.first, Sufia::Engine.routes.url_helpers.generic_file_path(gf.noid)}"
19
+ timestamp = Time.now.to_i
20
+ depositor = User.find_by_user_key(depositor_id)
21
+ # Create the event
22
+ event = depositor.create_event(action, timestamp)
23
+ # Log the event to the depositor's profile stream
24
+ depositor.log_profile_event(event)
25
+ # Log the event to the GF's stream
26
+ gf.log_event(event)
27
+ # Fan out the event to all followers who have access
28
+ depositor.followers.select { |user| user.can? :read, gf }.each do |follower|
29
+ follower.log_event(event)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class ContentRestoredVersionEventJob < EventJob
16
+ attr_accessor :revision_id
17
+
18
+ def initialize(generic_file_id, depositor_id, revision_id)
19
+ self.generic_file_id = generic_file_id
20
+ self.depositor_id = depositor_id
21
+ self.revision_id = revision_id
22
+ end
23
+
24
+ def run
25
+ gf = GenericFile.find(generic_file_id)
26
+ action = "User #{link_to_profile depositor_id} has restored a version '#{revision_id}' of #{link_to gf.title.first, Sufia::Engine.routes.url_helpers.generic_file_path(gf.noid)}"
27
+ timestamp = Time.now.to_i
28
+ depositor = User.find_by_user_key(depositor_id)
29
+ # Create the event
30
+ event = depositor.create_event(action, timestamp)
31
+ # Log the event to the depositor's profile stream
32
+ depositor.log_profile_event(event)
33
+ # Log the event to the GF's stream
34
+ gf.log_event(event)
35
+ # Fan out the event to all followers who have access
36
+ depositor.followers.select { |user| user.can? :read, gf }.each do |follower|
37
+ follower.log_event(event)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,32 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class ContentUpdateEventJob < EventJob
16
+ def run
17
+ gf = GenericFile.find(generic_file_id)
18
+ action = "User #{link_to_profile depositor_id} has updated #{link_to gf.title.first, Sufia::Engine.routes.url_helpers.generic_file_path(gf.noid)}"
19
+ timestamp = Time.now.to_i
20
+ depositor = User.find_by_user_key(depositor_id)
21
+ # Create the event
22
+ event = depositor.create_event(action, timestamp)
23
+ # Log the event to the depositor's profile stream
24
+ depositor.log_profile_event(event)
25
+ # Log the event to the GF's stream
26
+ gf.log_event(event)
27
+ # Fan out the event to all followers who have access
28
+ depositor.followers.select { |user| user.can? :read, gf }.each do |follower|
29
+ follower.log_event(event)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class EventJob
16
+ include Rails.application.routes.url_helpers
17
+ include ActionView::Helpers
18
+ include ActionView::Helpers::DateHelper
19
+ include Hydra::AccessControlsEnforcement
20
+ include SufiaHelper
21
+
22
+ def queue_name
23
+ :event
24
+ end
25
+
26
+ attr_accessor :generic_file_id, :depositor_id
27
+
28
+ def initialize(generic_file_id, depositor_id)
29
+ self.generic_file_id = generic_file_id
30
+ self.depositor_id = depositor_id
31
+ end
32
+
33
+ end
@@ -0,0 +1,61 @@
1
+ # Created by: Justin Coyne
2
+ # 7 Feb 2013
3
+ # An abstract class for asyncronous jobs that transcode files using FFMpeg
4
+
5
+ require 'tmpdir'
6
+
7
+ class FfmpegTranscodeJob
8
+ extend Open3
9
+
10
+ attr_accessor :generic_file_id, :datastream_in, :datastream, :generic_file
11
+
12
+ def initialize(generic_file_id, datastream_in)
13
+ self.generic_file_id = generic_file_id
14
+ self.datastream_in = datastream_in
15
+ end
16
+
17
+ def process
18
+ raise "You attempted to call process() on an abstract class. Implement process() on the concrete class"
19
+ end
20
+
21
+ def run
22
+ return unless Sufia::Engine.config.enable_ffmpeg
23
+ self.generic_file = GenericFile.find(generic_file_id)
24
+ self.datastream = generic_file.datastreams[datastream_in]
25
+ if datastream
26
+ process
27
+ generic_file.save!
28
+ else
29
+ logger.warn "No datastream for transcoding!!!!! pid: #{generic_file_id} dsid: #{datastream_in}"
30
+ end
31
+ end
32
+
33
+ def encode_datastream(dest_dsid, mime_type, options)
34
+ file_suffix = dest_dsid
35
+ out_file = nil
36
+ output_file = Dir::Tmpname.create(['sufia', ".#{file_suffix}"], Sufia::Engine.config.temp_file_base){}
37
+ datastream.to_tempfile do |f|
38
+ self.class.encode(f.path, options, output_file)
39
+ end
40
+ out_file = File.open(output_file, "rb")
41
+ generic_file.add_file_datastream(out_file.read, :dsid=>dest_dsid, :mimeType=>mime_type)
42
+ File.unlink(output_file)
43
+ end
44
+
45
+ def self.encode(path, options, output_file)
46
+ command = "#{ffmpeg_path} -y -i \"#{path}\" #{options} #{output_file}"
47
+ stdin, stdout, stderr, wait_thr = popen3(command)
48
+ stdin.close
49
+ out = stdout.read
50
+ stdout.close
51
+ err = stderr.read
52
+ stderr.close
53
+ raise "Unable to execute command \"#{command}\"\n#{err}" unless wait_thr.value.success?
54
+ end
55
+
56
+ def self.ffmpeg_path
57
+ Sufia::Engine.config.ffmpeg_path
58
+ end
59
+ end
60
+
61
+
@@ -0,0 +1,23 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class ResolrizeJob
16
+ def queue_name
17
+ :resolrize
18
+ end
19
+
20
+ def run
21
+ ActiveFedora::Base.reindex_everything
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ # Created by: Justin Coyne
2
+ # 7 Feb 2013
3
+ # An asyncronous job for transcoding audio files using FFMpeg
4
+
5
+ class TranscodeAudioJob < FfmpegTranscodeJob
6
+ def queue_name
7
+ :audio
8
+ end
9
+
10
+ def process
11
+ encode_mp3()
12
+ encode_ogg()
13
+ end
14
+
15
+ private
16
+ def encode_ogg
17
+ opts = ""
18
+ if generic_file.mime_type == 'audio/ogg'
19
+ # Don't re-encode, just copy
20
+ generic_file.add_file_datastream(generic_file.content.read, :dsid=>'ogg', :mimeType=>'audio/ogg')
21
+ #generic_file.content.rewind
22
+ else
23
+ encode_datastream('ogg', 'audio/ogg', opts)
24
+ end
25
+ end
26
+
27
+ def encode_mp3
28
+ opts = ""
29
+ if generic_file.mime_type == 'audio/mpeg'
30
+ # Don't re-encode, just copy
31
+ generic_file.add_file_datastream(generic_file.content.read, :dsid=>'mp3', :mimeType=>'audio/mp3')
32
+ #generic_file.content.rewind
33
+ else
34
+ encode_datastream('mp3', 'audio/mp3', opts)
35
+ end
36
+ end
37
+
38
+
39
+ end
40
+
@@ -0,0 +1,39 @@
1
+ # Created by: Justin Coyne
2
+ # 13 Dec 2012
3
+ # An asyncronous job for transcoding video files using FFMpeg
4
+
5
+ class TranscodeVideoJob < FfmpegTranscodeJob
6
+ def queue_name
7
+ :video
8
+ end
9
+
10
+ def process
11
+ encode_mp4()
12
+ encode_webm()
13
+ end
14
+
15
+ private
16
+
17
+ def encode_webm
18
+ # -g 30 enforces keyframe generation every second (30fps)
19
+ # -b:v is the video bitrate
20
+ # -acodec is the audio codec
21
+ opts = "#{size_attributes} -g 30 -b:v 345k -acodec libvorbis #{audio_attributes}"
22
+ encode_datastream('webm', 'video/webm', opts)
23
+ end
24
+
25
+ def encode_mp4
26
+ opts = "#{size_attributes} -b:v 345k -vcodec libx264 -acodec libfaac #{audio_attributes} "
27
+ encode_datastream('mp4', 'video/mp4', opts)
28
+ end
29
+
30
+
31
+ def size_attributes
32
+ "-s 320x240"
33
+ end
34
+
35
+ def audio_attributes
36
+ "-ac 2 -ab 96k -ar 44100"
37
+ end
38
+ end
39
+
@@ -0,0 +1,54 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class UnzipJob
16
+ def queue_name
17
+ :unzip
18
+ end
19
+
20
+ attr_accessor :pid
21
+
22
+ def initialize(pid)
23
+ self.pid = pid
24
+ end
25
+
26
+ def run
27
+ Zip::Archive.open_buffer(zip_file.content.content) do |archive|
28
+ archive.each do |f|
29
+ create_file(f)
30
+ end
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ def create_file(f)
37
+ @generic_file = GenericFile.new
38
+ @generic_file.batch_id = zip_file.batch.pid
39
+ file_name = f.name
40
+ mime_types = MIME::Types.of(file_name)
41
+ mime_type = mime_types.empty? ? "application/octet-stream" : mime_types.first.content_type
42
+ options = {:label=>file_name, :dsid=>'content', :mimeType=>mime_type}
43
+ @generic_file.add_file_datastream(f.read, options)
44
+ @generic_file.set_title_and_label( file_name, :only_if_blank=>true )
45
+ @generic_file.apply_depositor_metadata(zip_file.edit_users.first)
46
+ @generic_file.date_uploaded = Time.now.ctime
47
+ @generic_file.date_modified = Time.now.ctime
48
+ @generic_file.save
49
+ end
50
+
51
+ def zip_file
52
+ @zip_file ||= GenericFile.find(pid)
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class UserEditProfileEventJob < EventJob
16
+ attr_accessor :editor_id
17
+
18
+ def initialize(editor_id)
19
+ self.editor_id = editor_id
20
+ end
21
+
22
+ def run
23
+ action = "User #{link_to_profile editor_id} has edited his or her profile"
24
+ timestamp = Time.now.to_i
25
+ editor = User.find_by_user_key(editor_id)
26
+ # Create the event
27
+ event = editor.create_event(action, timestamp)
28
+ # Log the event to the editor's stream
29
+ editor.log_event(event)
30
+ # Fan out the event to all followers
31
+ editor.followers.each do |user|
32
+ user.log_event(event)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class UserFollowEventJob < EventJob
16
+ attr_accessor :follower_id, :followee_id
17
+
18
+ def initialize(follower_id, followee_id)
19
+ self.follower_id = follower_id
20
+ self.followee_id = followee_id
21
+ end
22
+
23
+ def run
24
+ # Create the event
25
+ follower = User.find_by_user_key(follower_id)
26
+ event = follower.create_event("User #{link_to_profile follower_id} is now following #{link_to_profile followee_id}", Time.now.to_i)
27
+ # Log the event to the follower's stream
28
+ follower.log_event(event)
29
+ # Fan out the event to followee
30
+ followee = User.find_by_user_key(followee_id)
31
+ followee.log_event(event)
32
+ # Fan out the event to all followers
33
+ follower.followers.each do |user|
34
+ user.log_event(event)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright © 2012 The Pennsylvania State University
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ class UserUnfollowEventJob < EventJob
16
+ attr_accessor :unfollower_id, :unfollowee_id
17
+
18
+ def initialize(unfollower_id, unfollowee_id)
19
+ self.unfollower_id = unfollower_id
20
+ self.unfollowee_id = unfollowee_id
21
+ end
22
+ def run
23
+ action = "User #{link_to_profile unfollower_id} has unfollowed #{link_to_profile unfollowee_id}"
24
+ timestamp = Time.now.to_i
25
+ unfollower = User.find_by_user_key(unfollower_id)
26
+ # Create the event
27
+ event = unfollower.create_event(action, timestamp)
28
+ # Log the event to the unfollower's stream
29
+ unfollower.log_event(event)
30
+ # Fan out the event to unfollowee
31
+ unfollowee = User.find_by_user_key(unfollowee_id)
32
+ unfollowee.log_event(event)
33
+ # Fan out the event to all followers
34
+ unfollower.followers.each do |user|
35
+ user.log_event(event)
36
+ end
37
+ end
38
+ end