jgrouper 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY.md CHANGED
@@ -1,6 +1,18 @@
1
1
  JGrouper History
2
2
  ================
3
3
 
4
+ 2014-01-10 JGrouper v0.6.0
5
+ -------------------------
6
+ * Add `bin/jgrouper-diff`
7
+ * Add `bin/jgrouper-revoke`
8
+ * Add `JGrouper::ExportFileDiff`
9
+ * Add `JGrouper::ExportFileEntry`
10
+ * Add `JGrouper::ExportFileReader`
11
+ * Add `JGrouper::Group.revoke()`
12
+ * Add `JGrouper::Stem.revoke()`
13
+ * Update `JGrouper::Export` and `bin/jgrouper-export` to export to JSON
14
+
15
+
4
16
  2013-08-15 JGrouper v0.5.0
5
17
  --------------------------
6
18
  * Add `JGrouper.start_root_session()`
data/bin/jgrouper-diff ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env jruby
2
+
3
+ require 'jgrouper/export_file_entry'
4
+ require 'jgrouper/export_file_reader'
5
+
6
+ require 'optparse'
7
+
8
+ #
9
+ # TODO Optionally key on attribute other than UUID?
10
+ #
11
+
12
+
13
+ opts = OptionParser.new do |opts|
14
+ opts.banner = "USAGE: #{ File.basename(__FILE__) } [-h]"
15
+
16
+ opts.on_tail('-h', '--help', "Show this message") do
17
+ puts opts
18
+ exit
19
+ end
20
+ opts.on_tail( '-v', '--[no-]verbose', 'Enable verbose mode [DEFAULT: no]' ) do |value|
21
+ exporter.verbose = value
22
+ end
23
+ end.parse!
24
+
25
+
26
+ JGrouper::ExportFileReader.new(ARGV.shift) do |src|
27
+ JGrouper::ExportFileReader.new(ARGV.shift) do |dst|
28
+ loop do
29
+
30
+ src.next do |json|
31
+ entry = JGrouper::ExportFileEntry.new json
32
+ next if entry.metadata?
33
+
34
+ if dst.include?(entry)
35
+ diff = entry.diff dst[entry]
36
+ puts diff.to_json if diff.different? # Modified
37
+ dst.delete(entry)
38
+ else
39
+ src << entry
40
+ end
41
+ end unless src.done?
42
+
43
+
44
+ dst.next do |json|
45
+ entry = JGrouper::ExportFileEntry.new json
46
+ next if entry.metadata?
47
+
48
+ if src.include?( entry )
49
+ diff = src[entry].diff entry
50
+ puts diff.to_json if diff.different? # Modified
51
+ src.delete(entry)
52
+ else
53
+ dst << entry
54
+ end
55
+ end unless dst.done?
56
+
57
+ if dst.done? && src.done?
58
+ src.each { |_| puts _.diff( JGrouper::ExportFileEntry.new ).to_json } # Delete
59
+ dst.each { |_| puts JGrouper::ExportFileEntry.new.diff(_).to_json } # Add
60
+ break
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+
67
+ # vim: syntax=ruby
68
+
data/bin/jgrouper-export CHANGED
@@ -4,7 +4,6 @@ require 'jgrouper'
4
4
  require 'jgrouper/exporter'
5
5
  require 'optparse'
6
6
  require 'thread'
7
- require 'yaml'
8
7
 
9
8
 
10
9
  JGrouper::Exporter.new do |exporter|
@@ -44,14 +43,14 @@ JGrouper::Exporter.new do |exporter|
44
43
  JGrouper.start_root_session
45
44
 
46
45
  # TODO GzipWriter?
47
- fn = File.join directory, 'jgrouper-export.yaml'
46
+ fn = File.join directory, 'jgrouper-export.json'
48
47
  File.open( fn, 'w' ) do |fh|
49
48
  fh.flock File::LOCK_EX
50
49
 
51
50
  loop do
52
51
  while queue.size > 0
53
52
  value = queue.pop
54
- fh.puts value.to_yaml
53
+ fh.puts value
55
54
  end
56
55
  if done && queue.empty?
57
56
  break
data/bin/jgrouper-grant CHANGED
@@ -78,7 +78,7 @@ end
78
78
  MyApp.new do |app|
79
79
 
80
80
  opts = OptionParser.new do |opts|
81
- opts.banner = "USAGE: #{ File.basename(__FILE__) } [options] <stem-or-group> <privilege> <subject>"
81
+ opts.banner = "USAGE: #{ File.basename(__FILE__) } [options] <stem-or-group> <admin|create|optin|optout|read|stem|view> <subject>"
82
82
  opts.on('-R', '--[no-]recurse', 'Recursively grant privileges [DEFAULT: no]') do |recurse|
83
83
  app.recurse = recurse
84
84
  end
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env jruby
2
+
3
+ require 'jgrouper'
4
+ require 'optparse'
5
+
6
+
7
+ class MyApp
8
+
9
+ attr_accessor :recurse, :verbose
10
+
11
+ def initialize
12
+ @recurse = false
13
+ @verbose = false
14
+ yield self if block_given?
15
+ self
16
+ end
17
+
18
+ def revoke(stem_or_group, privilege, subject)
19
+ raise 'ERROR: stem-or-group is nil' if stem_or_group.nil?
20
+ raise 'ERROR: privilege is nil' if stem_or_group.nil?
21
+ raise 'ERROR: subject is nil' if stem_or_group.nil?
22
+
23
+ priv = JGrouper::Privilege.find privilege
24
+ raise "ERROR: could not find privilege: #{privilege}" if priv.nil?
25
+ puts "found privilege: #{priv.to_s}" if verbose?
26
+ subj = JGrouper::Subject.find(subject)
27
+ raise "ERROR: could not find subject: #{subject}" if subj.nil?
28
+ puts "found subject: #{subj.to_s}" if verbose?
29
+
30
+ stem = JGrouper::Stem.find(stem_or_group)
31
+ return revoke_stem(stem, priv, subj) unless stem.nil?
32
+
33
+ group = JGrouper::Group.find(stem_or_group)
34
+ return revoke_group(group, priv, subj) unless group.nil?
35
+
36
+ raise "ERROR: could not find stem-or-group: #{stem_or_group}"
37
+ end
38
+
39
+ def recurse? ; @recurse ; end
40
+ def verbose? ; @verbose ; end
41
+
42
+
43
+ private
44
+
45
+ def revoke_group(group, privilege, subject)
46
+ if privilege.naming?
47
+ warn 'WARNING: cannot revoke naming privilege on group'
48
+ return false
49
+ end
50
+
51
+ puts "revoking privilege #{privilege.name} from subject #{subject} on group #{group.name}" if verbose?
52
+ group.revoke(subject, privilege)
53
+ end
54
+
55
+ def revoke_stem(stem, privilege, subject)
56
+ if privilege.access?
57
+ unless recurse?
58
+ warn 'WARNING: cannot revoke access privilege on stem without specifying -R'
59
+ return false
60
+ end
61
+ stem.groups do |group|
62
+ puts "revoking privilege #{privilege.name} from subject #{subject} on group #{group.name}" if verbose?
63
+ group.revoke(subject, privilege)
64
+ end
65
+ stem.stems { |child| revoke_stem(child, privilege, subject) }
66
+ return
67
+ end
68
+
69
+ puts "revoking privilege #{privilege.name} from subject #{subject} on stem #{stem.name}" if verbose?
70
+ stem.revoke(subject, privilege)
71
+ stem.stems { |child| revoke_stem(child, privilege, subject) } if recurse?
72
+ true
73
+ end
74
+
75
+ end
76
+
77
+
78
+ MyApp.new do |app|
79
+
80
+ opts = OptionParser.new do |opts|
81
+ opts.banner = "USAGE: #{ File.basename(__FILE__) } [options] <stem-or-group> <admin|create|optin|optout|read|stem|view> <subject>"
82
+ opts.on('-R', '--[no-]recurse', 'Recursively revoke privileges [DEFAULT: no]') do |recurse|
83
+ app.recurse = recurse
84
+ end
85
+ opts.on_tail('-h', '--help', 'Show help') do
86
+ puts opts
87
+ exit
88
+ end
89
+ opts.on_tail('-v', '--[no-]verbose', 'Enable verbose mode [DEFAULT: no]') do |verbose|
90
+ app.verbose = verbose
91
+ end
92
+ end.parse!
93
+
94
+ # TODO DRY
95
+ if ENV['GROUPER_HOME']
96
+ JGrouper.home! ENV['GROUPER_HOME']
97
+ else
98
+ warn "ERROR: GROUPER_HOME not set"
99
+ exit 1
100
+ end
101
+
102
+ app.revoke( ARGV.shift, ARGV.shift, ARGV.shift ) or exit 1
103
+
104
+ end
105
+
106
+ # vim: syntax=ruby
107
+
data/jgrouper.gemspec CHANGED
@@ -18,7 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
+ spec.add_dependency 'hashdiff'
21
22
  spec.add_dependency 'jruby-jars', '>= 1.7.3'
23
+ spec.add_dependency 'json'
22
24
 
23
25
  spec.add_development_dependency 'bundler', '~> 1.3'
24
26
  spec.add_development_dependency 'rake'
@@ -0,0 +1,49 @@
1
+ require 'hashdiff'
2
+ require 'json'
3
+
4
+ module JGrouper # :nodoc:
5
+ #
6
+ # = JGrouper::ExportFileDiff - Difference between two JGrouper::ExportFileEntry objects
7
+ #
8
+ # == WARNING
9
+ #
10
+ # The output format is unstable and will change in a future release.
11
+ #
12
+ # == USAGE
13
+ #
14
+ # require 'jgrouper'
15
+ # require 'jgrouper/export_file_diff'
16
+ # require 'jgrouper/export_file_entry'
17
+ #
18
+ # diff = JGrouper::ExportFileDiff JGrouper::ExportFileEntry.new(json), JGrouper::ExportFileEntry.new(json)
19
+ #
20
+ class ExportFileDiff
21
+
22
+ def initialize(src, dst)
23
+ @dst = dst
24
+ @key = dst.key || src.key
25
+ @src = src
26
+ @diff = HashDiff.diff @src.json, @dst.json
27
+ end
28
+
29
+ def different?
30
+ !@diff.empty?
31
+ end
32
+
33
+ def to_s
34
+ { key: @key, diff: @diff }.inspect
35
+ end
36
+
37
+ def to_hash
38
+ return {} unless different?
39
+ return { entry: @key, changes: @diff }
40
+ end
41
+
42
+ def to_json
43
+ to_hash.to_json
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
@@ -0,0 +1,99 @@
1
+ require 'jgrouper/export_file_diff'
2
+ require 'json'
3
+
4
+ module JGrouper # :nodoc:
5
+ #
6
+ # = JGrouper::ExportFileEntry - Entry from JGrouper::Exporter file
7
+ #
8
+ # == USAGE
9
+ #
10
+ # require 'jgrouper'
11
+ # require 'jgrouper/export_file_entry'
12
+ # require 'jgrouper/export_file_reader'
13
+ #
14
+ # JGrouper::ExportFileReader.new(file_name) do |reader|
15
+ # reader.next { |json| entry = JGrouper::ExportFileEntry.new json }
16
+ # end
17
+ #
18
+ class ExportFileEntry
19
+
20
+ attr_reader :key, :kind, :json
21
+
22
+ def initialize( json = {} )
23
+ @json = json
24
+ @kind = @json['kind']
25
+
26
+ @key = nil
27
+ @name = nil
28
+ @stem = nil
29
+ @subject = nil
30
+ @uuid = nil # Or equivalent ...
31
+
32
+ case @kind
33
+ when 'admins', 'members', 'optins', 'optouts', 'readers', 'viewers', 'updaters'
34
+ @group = @json['group']
35
+ @subject = @json['subject']
36
+ @key = [ @kind, @group['uuid'], @subject ]
37
+ when 'composite'
38
+ @group = @json['group']
39
+ @key = [ @kind, @group['uuid'] ]
40
+ when 'creators', 'stemmers'
41
+ @stem = @json['stem']
42
+ @subject = @json['subject']
43
+ @key = [ @kind, @stem['uuid'], @subject ]
44
+ when 'field'
45
+ @name = @json['name']
46
+ @uuid = @json['uuid']
47
+ @key = [ @kind, @uuid ]
48
+ when 'group'
49
+ %w( create_subject create_time modify_subject modify_time ).each { |_| @json.delete _ }
50
+ @name = @json['name']
51
+ @uuid = @json['uuid']
52
+ @key = [ @kind, @uuid ]
53
+ when 'group_attributes'
54
+ @group = @json['group']
55
+ @name = @json['name']
56
+ @key = [ @kind, @group['uuid'], @name ]
57
+ when 'group_type'
58
+ @name = @json['name']
59
+ @uuid = @json['uuid']
60
+ @key = [ @kind, @uuid ]
61
+ when 'metadata'
62
+ @key = @kind
63
+ when 'source'
64
+ @name = @json['name']
65
+ @uuid = @json['id'] # Effectively ...
66
+ @key = [ @kind, @uuid ]
67
+ when 'stem'
68
+ %w( create_subject create_time modify_subject modify_time ).each { |_| @json.delete _ }
69
+ @name = @json['name']
70
+ @uuid = @json['uuid']
71
+ @key = [ @kind, @uuid ]
72
+ else
73
+ warn "invalid entry type: #{ @kind } - #{ @json.inspect }" unless @json.empty?
74
+ end
75
+ end
76
+
77
+ def ==(other)
78
+ self.class == other.class && self.kind == other.kind && self.key == other.key
79
+ end
80
+
81
+ alias eql? ==
82
+
83
+ def diff(other)
84
+ JGrouper::ExportFileDiff.new self, other
85
+ end
86
+
87
+ def hash
88
+ raise "nil @key - #{ @self.inspect }" if @key.nil?
89
+ @key.hash
90
+ end
91
+
92
+ def metadata?
93
+ 'metadata' == @kind
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+
@@ -0,0 +1,65 @@
1
+ require 'json'
2
+
3
+ module JGrouper # :nodoc:
4
+ #
5
+ # = JGrouper::ExportFileReader - Read output file from JGrouper::Exporter
6
+ #
7
+ # == USAGE
8
+ #
9
+ # require 'jgrouper'
10
+ # require 'jgrouper/export_file_reader'
11
+ #
12
+ # JGrouper::ExportFileReader.new(file_name) do |reader|
13
+ # reader.next { |json| ... }
14
+ # end
15
+ #
16
+ class ExportFileReader
17
+ include Enumerable
18
+
19
+ def initialize(fn)
20
+ @done = false
21
+ @entries = {}
22
+ @fn = fn
23
+
24
+ @fh = File.open @fn, 'r'
25
+ yield self
26
+ @fh.close
27
+ end
28
+
29
+ def <<(entry)
30
+ @entries[ entry ] = entry
31
+ end
32
+
33
+ def [](entry)
34
+ @entries[entry]
35
+ end
36
+
37
+ def delete(entry)
38
+ @entries.delete(entry)
39
+ end
40
+
41
+ def done?
42
+ @done
43
+ end
44
+
45
+ def each(&block)
46
+ @entries.values.each(&block)
47
+ end
48
+
49
+ def include?(entry)
50
+ @entries.include?(entry)
51
+ end
52
+
53
+ def next
54
+ return if done?
55
+ if @fh.eof?
56
+ @done = true
57
+ return
58
+ end
59
+ yield JSON.parse( @fh.gets )
60
+ end
61
+
62
+ end
63
+
64
+ end
65
+
@@ -1,3 +1,4 @@
1
+ require 'json'
1
2
 
2
3
  module JGrouper # :nodoc:
3
4
  #
@@ -8,12 +9,14 @@ module JGrouper # :nodoc:
8
9
  # require 'jgrouper'
9
10
  # require 'jgrouper/exporter'
10
11
  #
11
- # JGrouper::Exporter do |exporter|
12
+ # JGrouper::Exporter.new do |exporter|
12
13
  # exporter.export 'stem:to:export', lambda { |_| puts _.to_yaml }
13
14
  # end
14
15
  #
15
16
  class Exporter
16
17
 
18
+ EXPORT_VERSION = 1
19
+
17
20
  attr_writer :verbose
18
21
 
19
22
  def initialize
@@ -34,8 +37,10 @@ module JGrouper # :nodoc:
34
37
  # TODO Multiple readers?
35
38
  txt = stem.root? ? 'root stem' : "stem #{stem.name}"
36
39
  log "exporting #{txt} ..."
40
+ export_metadata params[:block]
37
41
  if stem.root? # TODO Configurable?
38
42
  export_group_types params[:block]
43
+ export_fields params[:block]
39
44
  export_sources params[:block]
40
45
  end
41
46
  export_stem stem, params[:block]
@@ -43,28 +48,120 @@ module JGrouper # :nodoc:
43
48
 
44
49
  end
45
50
 
51
+ # Export fields
52
+ def export_fields(p)
53
+ log 'exporting group fields ...'
54
+ JGrouper::Field.all.each { |_| p.call _.to_json }
55
+ log 'exporting group fields: done'
56
+ end
57
+
46
58
  # Export group types.
47
59
  def export_group_types(p)
48
60
  log 'exporting group types ...'
49
- p.call JGrouper::GroupType
61
+ JGrouper::GroupType.all.each { |_| p.call _.to_json }
62
+ log 'exporting group types: done'
63
+ end
64
+
65
+ # Export metadata
66
+ def export_metadata(p)
67
+ log 'exporting metadata ...'
68
+ p.call( { kind: 'metadata',
69
+ export_version: EXPORT_VERSION,
70
+ jgrouper_version: JGrouper::VERSION,
71
+ hostname: ENV['HOSTNAME'],
72
+ ruby_engine: RUBY_ENGINE,
73
+ ruby_platform: RUBY_PLATFORM,
74
+ ruby_version: RUBY_VERSION,
75
+ start_time: Time.now.to_datetime.rfc3339
76
+ }.to_json
77
+ )
78
+ log 'exporting metadata: done'
50
79
  end
51
80
 
52
81
  # Export subject sources.
53
82
  def export_sources(p)
54
83
  log 'exporting subject sources ...'
55
- p.call JGrouper::Source
84
+ JGrouper::Source.all.each { |source| p.call source.to_json }
85
+ log 'exporting subject sources: done'
56
86
  end
57
87
 
58
88
  # Export stem and childen.
59
- def export_stem( stem, p )
60
- log "exporting stem #{stem.name} ..."
61
- p.call stem
62
- stem.groups { |child| p.call child }
63
- stem.stems { |child| export_stem(child, p) }
89
+ def export_stem(stem, p)
90
+ log "exporting stem #{stem.name} ..." # TODO Debug ... unless root?!
91
+ p.call stem.to_json
92
+ export_stem_privileges(stem, p)
93
+ stem.groups { |child| export_group child, p }
94
+ stem.stems { |child| export_stem child, p }
95
+ log "exporting stem #{stem.name}: done" # TODO Debug ... unless root?!
64
96
  end
65
97
 
66
98
 
67
99
  private
100
+
101
+ def export_group(group, p)
102
+ p.call group.to_json
103
+ export_group_attributes group, p
104
+ export_group_privileges group, p
105
+ export_group_members group, p
106
+ end
107
+
108
+ def export_group_attributes(group, p)
109
+ group.get_attributes_map(false).each do |k, v|
110
+ p.call( { kind: 'group_attributes',
111
+ group: { name: group.name, uuid: group.uuid },
112
+ name: k,
113
+ value: v.get_value
114
+ }.to_json
115
+ )
116
+ end
117
+ end
118
+
119
+ def export_group_members(group, p)
120
+ c = group.get_composite false
121
+ if c
122
+ left = c.get_left_group
123
+ right = c.get_right_group
124
+ p.call( { kind: 'composite',
125
+ group: { name: group.name, uuid: group.uuid },
126
+ type: c.get_type.get_name,
127
+ left: { name: left.get_name, uuid: left.get_uuid },
128
+ right: { name: right.get_name, uuid: right.get_name }
129
+ }.to_json
130
+ )
131
+ else
132
+ group.get_immediate_members.each do |_|
133
+ p.call( { kind: 'members',
134
+ group: { name: group.name, uuid: group.uuid },
135
+ subject: JGrouper::Subject.new( _.get_subject ).to_hash
136
+ }.to_json
137
+ )
138
+ end
139
+ end
140
+ end
141
+
142
+ def export_group_privileges(group, p)
143
+ [ :admins, :optins, :optouts, :readers, :updaters, :viewers ].each do |privilege|
144
+ group.send(privilege).each do |_|
145
+ p.call( { kind: privilege,
146
+ group: { name: group.name, uuid: group.uuid },
147
+ subject: JGrouper::Subject.new(_).to_hash
148
+ }.to_json
149
+ )
150
+ end
151
+ end
152
+ end
153
+
154
+ def export_stem_privileges(stem, p)
155
+ [ :creators, :stemmers ].each do |privilege|
156
+ stem.send(privilege).each do |_|
157
+ p.call( { kind: privilege,
158
+ stem: { name: stem.name, uuid: stem.uuid },
159
+ subject: JGrouper::Subject.new(_).to_hash
160
+ }.to_json
161
+ )
162
+ end
163
+ end
164
+ end
68
165
 
69
166
  # TODO Use Logger...
70
167
  # TODO DRY
@@ -18,6 +18,13 @@ module JGrouper # :nodoc:
18
18
  self
19
19
  end
20
20
 
21
+ #
22
+ # Find all fields.
23
+ #
24
+ def self.all
25
+ JFieldFinder.find_all.collect { |_| self.new _ }
26
+ end
27
+
21
28
  #
22
29
  # For passing methods on to Grouper Field object.
23
30
  #
@@ -33,20 +40,19 @@ module JGrouper # :nodoc:
33
40
 
34
41
  def to_hash
35
42
  {
36
- 'kind' => 'field',
37
- 'name' => @obj.get_name,
38
- 'uuid' => @obj.get_uuid,
39
- 'nullable' => @obj.get_is_nullable,
40
- 'required' => @obj.get_required,
41
- 'privilege' => {
42
- 'read' => @obj.get_read_privilege,
43
- 'write' => @obj.get_write_privilege
44
- }
43
+ kind: 'field',
44
+ group_type: { name: @obj.get_group_type.get_name, uuid: @obj.get_group_type.get_uuid },
45
+ name: @obj.get_name,
46
+ uuid: @obj.get_uuid,
47
+ nullable: @obj.get_is_nullable,
48
+ required: @obj.get_required,
49
+ read_privilege: @obj.get_read_privilege,
50
+ write_privilege: @obj.get_write_privilege
45
51
  }
46
52
  end
47
53
 
48
- def to_yaml
49
- to_hash.to_yaml
54
+ def to_json
55
+ to_hash.to_json
50
56
  end
51
57
 
52
58
  end
@@ -50,74 +50,47 @@ module JGrouper # :nodoc:
50
50
  end
51
51
  end
52
52
 
53
- def to_hash
54
- begin
55
- mod_subj = JGrouper::Subject.new( @obj.get_modify_subject )
56
- rescue edu.internet2.middleware.subject.SubjectNotFoundException
57
- mod_subj = nil
58
- end
53
+ def revoke(subject, privilege)
54
+ @obj.revokePriv subject.to_grouper, privilege.to_grouper, false
55
+ end
59
56
 
60
- hash = {
61
- 'kind' => 'group',
62
- 'uuid' => @obj.get_uuid,
63
- 'name' => @obj.get_name,
64
- 'display_name' => @obj.get_display_name,
65
- 'extension' => @obj.get_extension,
66
- 'display_extension' => @obj.get_display_extension,
67
- 'description' => @obj.get_description,
68
- 'parent' => {
69
- 'name' => @obj.get_parent_stem_name,
70
- 'uuid' => @obj.get_parent_uuid,
71
- },
72
- 'create' => {
73
- 'subject' => JGrouper::Subject.new( @obj.get_create_subject ).to_hash,
74
- 'time' => Time.at( @obj.get_create_time_long / 1000 ).to_datetime.rfc3339
75
- }
57
+ def to_hash
58
+ h = {
59
+ kind: 'group',
60
+ uuid: @obj.get_uuid,
61
+ name: @obj.get_name,
62
+ display_name: @obj.get_display_name,
63
+ extension: @obj.get_extension,
64
+ display_extension: @obj.get_display_extension,
65
+ create_subject: JGrouper::Subject.new( @obj.get_create_subject ).to_hash,
66
+ create_time: Time.at( @obj.get_create_time_long / 1000 ).to_datetime.rfc3339,
67
+ parent: { name: @obj.get_parent_stem.get_name, uuid: @obj.get_parent_stem.get_uuid }
76
68
  }
77
69
 
78
- begin
79
- mod_subj = JGrouper::Subject.new( @obj.get_modify_subject )
80
- hash['modify'] = {
81
- 'subject' => mod_subj ? mod_subj.to_hash : nil,
82
- 'time' => Time.at( @obj.get_modify_time_long / 1000 ).to_datetime.rfc3339
83
- }
84
- rescue
70
+ unless @obj.get_alternate_names.empty?
71
+ h[:alternate_names] = @obj.get_alternate_names.collect(&:to_s)
85
72
  end
86
-
87
- # TODO Ugly
88
- unless @obj.get_admins.empty? &&
89
- @obj.get_optins.empty? &&
90
- @obj.get_optouts.empty? &&
91
- @obj.get_readers.empty? &&
92
- @obj.get_updaters.empty &&
93
- @obj.get_viewers.empty?
94
- hash['privileges'] = {}
95
- hash['privileges']['admin'] = @obj.get_admins.collect { |_| JGrouper::Subject.new(_).to_hash } unless @obj.get_admins.empty?
96
- hash['privileges']['optin'] = @obj.get_optins.collect { |_| JGrouper::Subject.new(_).to_hash } unless @obj.get_optins.empty?
97
- hash['privileges']['optout'] = @obj.get_optouts.collect { |_| JGrouper::Subject.new(_).to_hash } unless @obj.get_optouts.empty?
98
- hash['privileges']['read'] = @obj.get_readers.collect { |_| JGrouper::Subject.new(_).to_hash } unless @obj.get_readers.empty?
99
- hash['privileges']['update'] = @obj.get_updaters.collect { |_| JGrouper::Subject.new(_).to_hash } unless @obj.get_updaters.empty?
100
- hash['privileges']['view'] = @obj.get_viewers.collect { |_| JGrouper::Subject.new(_).to_hash } unless @obj.get_viewers.empty?
73
+ unless @obj.get_description.empty?
74
+ h[:description] = @obj.get_description
75
+ end
76
+ unless @obj.get_removable_types.empty?
77
+ h[:group_types] = @obj.get_removable_types.collect { |_| { name: _.get_name, uuid: _.get_uuid } }
78
+ end
79
+ if 'role' == @obj.get_type_of_group.to_s
80
+ h[:role] = true
101
81
  end
102
82
 
103
- hash['types'] = @obj.get_removable_types.collect { |_| { 'name' => _.get_name, 'uuid' => _.get_uuid } } unless @obj.get_removable_types.empty?
104
- hash['attributes'] = @obj.get_attributes_map(false).inject({}) { |h, (k,v)| h[k] = v.get_value ; h } unless @obj.get_attributes_map(false).empty?
105
- hash['alternate_names'] = @obj.get_alternate_names.collect { |_| _ } unless @obj.get_alternate_names.empty?
106
-
107
- hash['role'] = 'role' if 'role' == @obj.get_type_of_group.to_string
108
-
109
- composite = @obj.get_composite(false)
110
- if composite
111
- hash['composite'] = {
112
- 'type' => composite.get_type.get_name,
113
- 'left' => { 'name' => composite.get_left_group.get_name, 'uuid' => composite.get_left_group.get_uuid },
114
- 'right' => { 'name' => composite.get_right_group.get_name, 'uuid' => composite.get_right_group.get_uuid }
115
- }
116
- else
117
- hash['members'] = @obj.get_immediate_members.collect { |_| JGrouper::Subject.new( _.get_subject ).to_hash } unless @obj.get_immediate_members.empty?
83
+ begin
84
+ h[:modify_subject] = JGrouper::Subject.new( @obj.get_modify_subject ).to_hash
85
+ h[:modify_time] = Time.at( @obj.get_modify_time_long / 1000 ).to_datetime.rfc3339
86
+ rescue
118
87
  end
119
88
 
120
- hash
89
+ h
90
+ end
91
+
92
+ def to_json
93
+ to_hash.to_json
121
94
  end
122
95
 
123
96
  def to_s
@@ -125,10 +98,6 @@ module JGrouper # :nodoc:
125
98
  %w( name display_name uuid ).collect { |k| "#{k}=#{ self.send(k) }" }.to_csv.chomp
126
99
  end
127
100
 
128
- def to_yaml
129
- to_hash.to_yaml
130
- end
131
-
132
101
  end
133
102
  end
134
103
 
@@ -54,32 +54,20 @@ module JGrouper # :nodoc:
54
54
  end
55
55
 
56
56
  def to_hash
57
- hash = {
58
- 'kind' => 'group_type',
59
- 'name' => @obj.get_name,
60
- 'uuid' => @obj.get_uuid,
61
- 'assignable' => @obj.get_is_assignable,
62
- 'internal' => @obj.get_is_internal,
63
- 'create' => {
64
- 'uuid' => @obj.get_creator_uuid,
65
- 'time' => Time.at( @obj.get_create_time / 1000 ).to_datetime.rfc3339
66
- }
67
- }
68
- unless @obj.get_fields.empty?
69
- hash['fields'] = @obj.get_fields.collect { |_| JGrouper::Field.new(_).to_hash }
70
- end
71
- hash
72
- end
73
-
74
- def self.to_yaml
75
57
  {
76
- 'kind' => 'group_types',
77
- 'group_types' => all.collect { |_| self.new(_).to_hash }
78
- }.to_yaml
58
+ kind: 'group_type',
59
+ name: @obj.get_name,
60
+ uuid: @obj.get_uuid,
61
+ assignable: @obj.get_is_assignable,
62
+ internal: @obj.get_is_internal,
63
+ create_time: Time.at( @obj.get_create_time / 1000 ).to_datetime.rfc3339,
64
+ create_uuid: @obj.get_creator_uuid,
65
+ fields: @obj.get_fields.collect { |f| { name: f.get_name, uuid: f.get_uuid } }
66
+ }
79
67
  end
80
68
 
81
- def to_yaml
82
- to_hash.to_yaml
69
+ def to_json
70
+ to_hash.to_json
83
71
  end
84
72
 
85
73
  end
@@ -23,7 +23,7 @@ module JGrouper # :nodoc:
23
23
  #
24
24
  def self.find(uuid)
25
25
  begin
26
- m = MemberFinder.find_by_uuid JGrouper.start_root_session, uuid, false
26
+ m = JMemberFinder.find_by_uuid JGrouper.start_root_session, uuid, false
27
27
  rescue => e
28
28
  warn "JGrouper::Member.find(#{uuid}) => #{e}"
29
29
  end
@@ -40,22 +40,15 @@ module JGrouper # :nodoc:
40
40
 
41
41
  def to_hash
42
42
  {
43
- 'kind' => 'source',
44
- 'id' => @obj.get_id,
45
- 'name' => @obj.get_name,
46
- 'init_params' => @obj.get_init_params.inject({}) { |h, (k,v)| h[k] = v ; h }
43
+ kind: 'source',
44
+ id: @obj.get_id,
45
+ name: @obj.get_name,
46
+ init_params: @obj.get_init_params.each { |k,v| { name: k, value: v }.collect }
47
47
  }
48
48
  end
49
49
 
50
- def self.to_yaml
51
- {
52
- 'kind' => 'sources',
53
- 'sources' => all.collect { |_| self.new(_).to_hash }
54
- }.to_yaml
55
- end
56
-
57
- def to_yaml
58
- to_hash.to_yaml
50
+ def to_json
51
+ to_hash.to_json
59
52
  end
60
53
 
61
54
  end
data/lib/jgrouper/stem.rb CHANGED
@@ -24,7 +24,7 @@ module JGrouper # :nodoc:
24
24
  #
25
25
  def self.find(name)
26
26
  begin
27
- obj = StemFinder.find_by_name JGrouper.start_root_session, name, false
27
+ obj = JStemFinder.find_by_name JGrouper.start_root_session, name, false
28
28
  rescue => e
29
29
  warn "JGrouper::Group.find(#{name}) => #{e}"
30
30
  end
@@ -62,11 +62,15 @@ module JGrouper # :nodoc:
62
62
  end
63
63
  end
64
64
 
65
+ def revoke(subject, privilege)
66
+ @obj.revokePriv subject.to_grouper, privilege.to_grouper, false
67
+ end
68
+
65
69
  #
66
70
  # Find Grouper root stem. Returns +JGrouper::Stem+ or +nil+.
67
71
  #
68
72
  def self.root
69
- obj = StemFinder.find_root_stem JGrouper.start_root_session
73
+ obj = JStemFinder.find_root_stem JGrouper.start_root_session
70
74
  return nil if obj.nil?
71
75
  stem = self.new obj
72
76
  yield stem if block_given?
@@ -92,43 +96,34 @@ module JGrouper # :nodoc:
92
96
  end
93
97
 
94
98
  def to_hash
95
- hash = {
96
- 'kind' => 'stem',
97
- 'uuid' => @obj.get_uuid,
98
- 'name' => @obj.get_name,
99
- 'display_name' => @obj.get_display_name,
100
- 'extension' => @obj.get_extension,
101
- 'display_extension' => @obj.get_display_extension
99
+ h = {
100
+ kind: 'stem',
101
+ uuid: @obj.get_uuid,
102
+ name: @obj.get_name,
103
+ display_name: @obj.get_display_name,
104
+ extension: @obj.get_extension,
105
+ display_extension: @obj.get_display_extension,
106
+ create_subject: JGrouper::Subject.new( @obj.get_create_subject ).to_hash,
107
+ create_time: Time.at( @obj.get_create_time_long / 1000 ).to_datetime.rfc3339
102
108
  }
103
109
 
104
- hash['description'] = @obj.get_description unless @obj.get_description.empty?
105
-
106
- hash['create'] = {
107
- 'subject' => JGrouper::Subject.new( @obj.get_create_subject ).to_hash,
108
- 'time' => Time.at( @obj.get_create_time_long / 1000 ).to_datetime.rfc3339
109
- }
110
+ h[:description] = @obj.get_description unless @obj.get_description.empty?
111
+ unless root?
112
+ parent = @obj.get_parent_stem
113
+ h[:parent] = { name: parent.get_name, uuid: parent.get_uuid }
114
+ end
110
115
 
111
116
  begin
112
- mod_subj = JGrouper::Subject.new( @obj.get_modify_subject )
113
- hash['modify'] = {
114
- 'subject' => mod_subj ? mod_subj.to_hash : nil,
115
- 'time' => Time.at( @obj.get_modify_time_long / 1000 ).to_datetime.rfc3339
116
- }
117
+ h[:modify_subject] = JGrouper::Subject.new( @obj.get_modify_subject ).to_hash
118
+ h[:modify_time] = Time.at( @obj.get_modify_time_long / 1000 ).to_datetime.rfc3339
117
119
  rescue
118
120
  end
119
121
 
120
- unless @obj.get_creators.empty? && @obj.get_stemmers.empty?
121
- hash['privileges'] = {}
122
- hash['privileges']['create'] = @obj.get_creators.collect { |_| JGrouper::Subject.new(_).to_hash } unless @obj.get_creators.empty?
123
- hash['privileges']['stem'] = @obj.get_stemmers.collect { |_| JGrouper::Subject.new(_).to_hash } unless @obj.get_stemmers.empty?
124
- end
125
-
126
- hash['stems'] = @obj.child_stems.collect { |_| { 'name' => _.get_name, 'uuid' => _.get_uuid } } unless @obj.child_stems.empty?
127
- hash['groups'] = @obj.child_groups.collect { |_| { 'name' => _.get_name, 'uuid' => _.get_uuid } } unless @obj.child_groups.empty?
128
-
129
- hash['parent'] = { 'name' => @obj.get_parent_stem.get_name, 'uuid' => @obj.get_parent_uuid } unless root?
122
+ h
123
+ end
130
124
 
131
- hash
125
+ def to_json
126
+ to_hash.to_json
132
127
  end
133
128
 
134
129
  def to_s
@@ -136,10 +131,6 @@ module JGrouper # :nodoc:
136
131
  %w( name display_name uuid ).collect { |k| "#{k}=#{ self.send(k) }" }.to_csv.chomp
137
132
  end
138
133
 
139
- def to_yaml
140
- to_hash.to_yaml
141
- end
142
-
143
134
  end
144
135
  end
145
136
 
@@ -23,7 +23,7 @@ module JGrouper # :nodoc:
23
23
  #
24
24
  def self.find(id_or_identifier)
25
25
  begin
26
- subj = SubjectFinder.find_by_id_or_identifier id_or_identifier, false
26
+ subj = JSubjectFinder.find_by_id_or_identifier id_or_identifier, false
27
27
  rescue => e
28
28
  warn "JGrouper::Subject.find(#{id_or_identifier}) => #{e}"
29
29
  end
@@ -50,22 +50,22 @@ module JGrouper # :nodoc:
50
50
 
51
51
  def to_hash
52
52
  {
53
- 'kind' => 'subject',
54
- 'id' => @obj.get_id,
55
- 'source' => @obj.get_source_id,
56
- 'type' => @obj.get_type_name
53
+ kind: 'subject',
54
+ id: @obj.get_id,
55
+ source: @obj.get_source_id,
56
+ type: @obj.get_type_name
57
57
  }
58
58
  end
59
59
 
60
+ def to_json
61
+ to_hash.to_json
62
+ end
63
+
60
64
  def to_s
61
65
  return nil if @obj.nil?
62
66
  %w( id type_name source_id name ).collect { |k| "#{k}=#{ self.send(k) }" }.to_csv.chomp
63
67
  end
64
68
 
65
- def to_yaml
66
- to_hash.to_yaml
67
- end
68
-
69
69
  end
70
70
  end
71
71
 
@@ -1,4 +1,4 @@
1
1
  module JGrouper
2
- VERSION = '0.5.0'
2
+ VERSION = '0.6.0'
3
3
  end
4
4
 
data/lib/jgrouper.rb CHANGED
@@ -10,6 +10,7 @@ require 'jgrouper/stem'
10
10
  require 'jgrouper/subject'
11
11
  require 'jgrouper/version'
12
12
 
13
+
13
14
  #
14
15
  # = JGrouper - JRuby wrapper around the Internet2 Grouper API
15
16
  #
@@ -161,20 +162,18 @@ module JGrouper
161
162
  $CLASSPATH << File.join( path, 'conf' )
162
163
  $CLASSPATH << File.join( path, 'dist', 'lib', 'grouper.jar' )
163
164
 
164
- %w( edu.internet2.middleware.subject.SubjectNotFoundException
165
- edu.internet2.middleware.grouper.GrouperSession
166
- edu.internet2.middleware.grouper.MemberFinder
167
- edu.internet2.middleware.grouper.StemFinder
168
- edu.internet2.middleware.grouper.SubjectFinder
169
- ).each { |klass| java_import klass }
170
-
171
- # TODO Do this for everything?
172
165
  %w(
173
166
  edu.internet2.middleware.grouper.Field
167
+ edu.internet2.middleware.grouper.FieldFinder
174
168
  edu.internet2.middleware.grouper.GroupFinder
169
+ edu.internet2.middleware.grouper.GrouperSession
175
170
  edu.internet2.middleware.grouper.GroupTypeFinder
171
+ edu.internet2.middleware.grouper.MemberFinder
176
172
  edu.internet2.middleware.grouper.privs.Privilege
177
173
  edu.internet2.middleware.subject.provider.SourceManager
174
+ edu.internet2.middleware.grouper.StemFinder
175
+ edu.internet2.middleware.grouper.SubjectFinder
176
+ edu.internet2.middleware.subject.SubjectNotFoundException
178
177
  ).each do |klass|
179
178
  java_import klass do |pkg, cls| "J#{cls}"; end
180
179
  end
@@ -183,7 +182,7 @@ module JGrouper
183
182
  # TODO Block method?
184
183
  def self.start_root_session
185
184
  # TODO Block method?
186
- GrouperSession.start_root_session
185
+ JGrouperSession.start_root_session
187
186
  end
188
187
 
189
188
  end
metadata CHANGED
@@ -1,87 +1,121 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jgrouper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
5
- prerelease:
4
+ version: 0.6.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - blair christensen
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-15 00:00:00.000000000 Z
12
+ date: 2014-01-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: jruby-jars
16
- requirement: !ruby/object:Gem::Requirement
15
+ name: hashdiff
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
17
21
  none: false
22
+ requirement: !ruby/object:Gem::Requirement
18
23
  requirements:
19
- - - ! '>='
24
+ - - '>='
20
25
  - !ruby/object:Gem::Version
21
- version: 1.7.3
22
- type: :runtime
26
+ version: '0'
27
+ none: false
23
28
  prerelease: false
29
+ type: :runtime
30
+ - !ruby/object:Gem::Dependency
31
+ name: jruby-jars
24
32
  version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - '>='
35
+ - !ruby/object:Gem::Version
36
+ version: 1.7.3
25
37
  none: false
38
+ requirement: !ruby/object:Gem::Requirement
26
39
  requirements:
27
- - - ! '>='
40
+ - - '>='
28
41
  - !ruby/object:Gem::Version
29
42
  version: 1.7.3
43
+ none: false
44
+ prerelease: false
45
+ type: :runtime
30
46
  - !ruby/object:Gem::Dependency
31
- name: bundler
47
+ name: json
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ none: false
32
54
  requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
33
59
  none: false
60
+ prerelease: false
61
+ type: :runtime
62
+ - !ruby/object:Gem::Dependency
63
+ name: bundler
64
+ version_requirements: !ruby/object:Gem::Requirement
34
65
  requirements:
35
66
  - - ~>
36
67
  - !ruby/object:Gem::Version
37
68
  version: '1.3'
38
- type: :development
39
- prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
69
  none: false
70
+ requirement: !ruby/object:Gem::Requirement
42
71
  requirements:
43
72
  - - ~>
44
73
  - !ruby/object:Gem::Version
45
74
  version: '1.3'
75
+ none: false
76
+ prerelease: false
77
+ type: :development
46
78
  - !ruby/object:Gem::Dependency
47
79
  name: rake
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
80
+ version_requirements: !ruby/object:Gem::Requirement
50
81
  requirements:
51
- - - ! '>='
82
+ - - '>='
52
83
  - !ruby/object:Gem::Version
53
84
  version: '0'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
85
  none: false
86
+ requirement: !ruby/object:Gem::Requirement
58
87
  requirements:
59
- - - ! '>='
88
+ - - '>='
60
89
  - !ruby/object:Gem::Version
61
90
  version: '0'
91
+ none: false
92
+ prerelease: false
93
+ type: :development
62
94
  - !ruby/object:Gem::Dependency
63
95
  name: rdoc-readme
64
- requirement: !ruby/object:Gem::Requirement
65
- none: false
96
+ version_requirements: !ruby/object:Gem::Requirement
66
97
  requirements:
67
98
  - - ~>
68
99
  - !ruby/object:Gem::Version
69
100
  version: 0.1.2
70
- type: :development
71
- prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
73
101
  none: false
102
+ requirement: !ruby/object:Gem::Requirement
74
103
  requirements:
75
104
  - - ~>
76
105
  - !ruby/object:Gem::Version
77
106
  version: 0.1.2
107
+ none: false
108
+ prerelease: false
109
+ type: :development
78
110
  description: JRuby wrapper around the Internet2 Grouper API
79
111
  email:
80
112
  - blair.christensen@gmail.com
81
113
  executables:
82
114
  - jgrouper-audit-archiver
115
+ - jgrouper-diff
83
116
  - jgrouper-export
84
117
  - jgrouper-grant
118
+ - jgrouper-revoke
85
119
  extensions: []
86
120
  extra_rdoc_files: []
87
121
  files:
@@ -94,11 +128,16 @@ files:
94
128
  - Rakefile
95
129
  - TODO.md
96
130
  - bin/jgrouper-audit-archiver
131
+ - bin/jgrouper-diff
97
132
  - bin/jgrouper-export
98
133
  - bin/jgrouper-grant
134
+ - bin/jgrouper-revoke
99
135
  - jgrouper.gemspec
100
136
  - lib/jgrouper.rb
101
137
  - lib/jgrouper/audit_archiver.rb
138
+ - lib/jgrouper/export_file_diff.rb
139
+ - lib/jgrouper/export_file_entry.rb
140
+ - lib/jgrouper/export_file_reader.rb
102
141
  - lib/jgrouper/exporter.rb
103
142
  - lib/jgrouper/field.rb
104
143
  - lib/jgrouper/group.rb
@@ -112,26 +151,26 @@ files:
112
151
  homepage: https://github.com/blairc/jgrouper/
113
152
  licenses:
114
153
  - MIT
115
- post_install_message:
154
+ post_install_message:
116
155
  rdoc_options: []
117
156
  require_paths:
118
157
  - lib
119
158
  required_ruby_version: !ruby/object:Gem::Requirement
120
- none: false
121
159
  requirements:
122
- - - ! '>='
160
+ - - '>='
123
161
  - !ruby/object:Gem::Version
124
162
  version: '0'
125
- required_rubygems_version: !ruby/object:Gem::Requirement
126
163
  none: false
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
165
  requirements:
128
- - - ! '>='
166
+ - - '>='
129
167
  - !ruby/object:Gem::Version
130
168
  version: '0'
169
+ none: false
131
170
  requirements: []
132
- rubyforge_project:
133
- rubygems_version: 1.8.23
134
- signing_key:
171
+ rubyforge_project:
172
+ rubygems_version: 1.8.24
173
+ signing_key:
135
174
  specification_version: 3
136
175
  summary: JRuby wrapper around the Internet2 Grouper API
137
176
  test_files: []