sufia-models 0.0.1

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