ucb_confluence 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.svnignore ADDED
@@ -0,0 +1,6 @@
1
+ Manifest
2
+ log
3
+ pkg
4
+ .idea
5
+ .rvmrc
6
+ Ucb_confluence.iml
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem "bundler", "1.0.18"
data/Gemfile.lock ADDED
@@ -0,0 +1,37 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ucb_confluence (0.0.1)
5
+ rake (>= 0.8.7)
6
+ ucb_ldap (>= 1.4.2)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ columnize (0.3.4)
12
+ diff-lcs (1.1.2)
13
+ linecache (0.46)
14
+ rbx-require-relative (> 0.0.4)
15
+ rake (0.8.7)
16
+ rbx-require-relative (0.0.5)
17
+ rcov (0.9.9)
18
+ rspec (1.3.0)
19
+ ruby-debug (0.10.4)
20
+ columnize (>= 0.1)
21
+ ruby-debug-base (~> 0.10.4.0)
22
+ ruby-debug-base (0.10.4)
23
+ linecache (>= 0.3)
24
+ ruby-net-ldap (0.0.4)
25
+ ucb_ldap (1.4.2)
26
+ ruby-net-ldap (>= 0.0.4)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ bundler (= 1.0.18)
33
+ diff-lcs (>= 1.1.2)
34
+ rcov (>= 0.9.9)
35
+ rspec (>= 1.3.0)
36
+ ruby-debug (>= 0.10.4)
37
+ ucb_confluence!
data/INTERNALS.md ADDED
@@ -0,0 +1,12 @@
1
+
2
+ Resources
3
+ ---------
4
+
5
+ http://confluence.atlassian.com/display/CONFDEV/Remote+API+Specification
6
+
7
+
8
+ Tests
9
+ -----
10
+
11
+ To run the test suite, its recommended that you setup a local version of
12
+ confluence.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ UCB Confluence
2
+ ============
3
+
4
+ UCB Confluence is a gem to assist with User and Group administration via
5
+ the Confluence xmlrpc API.
6
+
7
+
8
+ Overview
9
+ --------
10
+
11
+ Installation
12
+ ------------
13
+
14
+ gem install ucb_confluence
15
+
16
+
17
+ Assumptions
18
+ -----------
19
+
20
+ General Configuration
21
+ ---------------------
22
+ - Create the directory: $HOME/.ucb_confluence
23
+ - Create the file: $HOME/.ucb_confluence/config.yml
24
+ - Configure your config.yml file w/appropriate values, see sample config.yml below
25
+
26
+ server_url: https://<your-confluence-hostname>
27
+ ldap_url: ldap.berkeley.edu
28
+ username: <confluence-username>
29
+ password: <your-password>
30
+ user_default_password: <default-password-for-new-users>
31
+
32
+
33
+ Confluence Configuration
34
+ ------------------------
35
+
36
+ Usage
37
+ -----
38
+
39
+ See all available commands with:
40
+
41
+ ucb_confluence -T
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ require 'spec/rake/spectask'
3
+ require 'spec/rake/verify_rcov'
4
+
5
+ Bundler::GemHelper.install_tasks()
6
+
7
+ Spec::Rake::SpecTask.new("spec:rcov") do |t|
8
+ t.spec_opts ||= []
9
+ t.spec_opts << "--options" << "spec/spec.opts"
10
+ t.rcov = true
11
+ end
12
+
13
+ Spec::Rake::SpecTask.new("spec") do |t|
14
+ t.spec_opts ||= []
15
+ t.spec_opts << "--options" << "spec/spec.opts"
16
+ end
17
+
18
+ RCov::VerifyTask.new(:rcov => "spec:rcov") do |t|
19
+ t.threshold = 100
20
+ end
21
+
data/TODO.md ADDED
@@ -0,0 +1,8 @@
1
+
2
+ * Make thread safe: put Conn and Config objects in an instance of Confluence class
3
+ instead of the class itself so if we use this class in a JRuby rails app where multiple
4
+ threads are used we will be happy.
5
+
6
+ - Add module for Spaces
7
+
8
+ - Add module for Permissions
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pp'
4
+ require 'rubygems'
5
+ require 'rake'
6
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
7
+ require 'confluence'
8
+
9
+
10
+ Rake.application.init("ucb_confluence")
11
+
12
+ namespace(:jobs) do
13
+ desc "Sync Confluence IST group with LDAP IST group."
14
+ task(:ist_ldap_sync) do
15
+ Confluence::Jobs::IstLdapSync.new.execute()
16
+ end
17
+
18
+ desc "Disable expired Confluence users."
19
+ task(:disable_expired_users) do
20
+ Confluence::Jobs::DisableExpiredUsers.new.execute()
21
+ end
22
+ end
23
+
24
+ namespace(:user) do
25
+ desc "List of all users in Confluence."
26
+ task(:all) do
27
+ $stdout.puts(Confluence::User.all)
28
+ end
29
+
30
+ desc "List of all disabled confluence users."
31
+ task(:expired) do
32
+ $stdout.puts(Confluence::User.expired())
33
+ end
34
+
35
+ desc "List of all active confluence users."
36
+ task(:active) do
37
+ $stdout.puts(Confluence::User.active())
38
+ end
39
+
40
+ desc "Number of total users (both expired and active) in Confluence."
41
+ task(:total_count) do
42
+ $stdout.puts(Confluence::User.all.length)
43
+ end
44
+
45
+ desc "Number of expired users in Confluence."
46
+ task(:expired_count) do
47
+ $stdout.puts(Confluence::User.expired.length)
48
+ end
49
+
50
+ desc "Number of active users in Confluence."
51
+ task(:active_count) do
52
+ $stdout.puts(Confluence::User.active.length)
53
+ end
54
+
55
+ desc "List of groups for a given user in Confluence."
56
+ task(:groups) do
57
+ user = Confluence::User.find_by_name(ENV["NAME"])
58
+ if user
59
+ $stdout.puts(user.groups)
60
+ else
61
+ $stdout.puts("[]")
62
+ end
63
+ end
64
+
65
+ desc "Display info for a given user"
66
+ task(:find) do
67
+ $stdout.puts(Confluence::User.find_by_name(ENV["NAME"]))
68
+ end
69
+ end
70
+
71
+ namespace(:group) do
72
+ desc "List of all groups in Confluence."
73
+ task(:all) do
74
+ $stdout.puts(Confluence::Group.all())
75
+ end
76
+
77
+ desc "Number of groups in Confluence."
78
+ task(:count) do
79
+ $stdout.puts(Confluence::Group.all.length)
80
+ end
81
+ end
82
+
83
+
84
+ Rake.application.top_level
data/config/.svnignore ADDED
@@ -0,0 +1 @@
1
+ config.yml
@@ -0,0 +1,21 @@
1
+ dev:
2
+ server_url: https://wikihub-dev.berkeley.edu
3
+ ldap_host: ldap-test.berkeley.edu
4
+ username: <username>
5
+ password: <password>
6
+ user_default_password: <user_default_password>
7
+
8
+ qa:
9
+ server_url: https://wikihub-qa.berkeley.edu
10
+ ldap_host: ldap.berkeley.edu
11
+ username: <username>
12
+ password: <password>
13
+ user_default_password: <user_default_password>
14
+
15
+ prod:
16
+ server_url: https://wikihub.berkeley.edu
17
+ ldap_host: ldap.berkeley.edu
18
+ username: <username>
19
+ password: <password>
20
+ user_default_password: <user_default_password>
21
+
data/lib/confluence.rb ADDED
@@ -0,0 +1,57 @@
1
+ require 'pp'
2
+ require 'logger'
3
+ require 'ucb_ldap'
4
+ require 'xmlrpc/client'
5
+ require 'fileutils'
6
+
7
+ require 'confluence/conn'
8
+ require 'confluence/user'
9
+ require 'confluence/group'
10
+ require 'confluence/config'
11
+
12
+ require 'confluence/jobs/ist_ldap_sync'
13
+ require 'confluence/jobs/disable_expired_users'
14
+
15
+
16
+ module Confluence
17
+ ROOT = File.expand_path(File.dirname(__FILE__) + '/../')
18
+
19
+ class << self
20
+
21
+ def conn()
22
+ unless @conn
23
+ @conn = Confluence::Conn.new(config())
24
+ end
25
+ @conn
26
+ end
27
+
28
+ def config()
29
+ unless @config
30
+ @config = Confluence::Config.new()
31
+ Confluence.logger.debug(@config.inspect())
32
+ end
33
+ @config
34
+ end
35
+
36
+ def config=(config)
37
+ @config = config
38
+ end
39
+
40
+ def logger()
41
+ unless @logger
42
+ @logger = Logger.new("#{config.home()}/log/ucb_confluence.log")
43
+ @logger.level = Logger::DEBUG
44
+ end
45
+ @logger
46
+ end
47
+
48
+ def logger=(logger)
49
+ @logger = logger
50
+ end
51
+
52
+ def root()
53
+ ROOT
54
+ end
55
+ end
56
+ end
57
+
@@ -0,0 +1,31 @@
1
+ module Confluence
2
+ class Config
3
+
4
+ def initialize(config_file = "#{home()}/config.yml")
5
+ init_home_dir()
6
+ config = YAML.load_file(config_file)
7
+
8
+ @config = {}
9
+ @config[:server_url] = config['server_url']
10
+ @config[:server_url].concat("/rpc/xmlrpc") unless @config[:server_url][-11..-1] == "/rpc/xmlrpc"
11
+ @config[:ldap_url] = config['ldap_url']
12
+ @config[:username] = config['username'].to_s
13
+ @config[:password] = config['password'].to_s
14
+ @config[:user_default_password] = config['user_default_password'].to_s
15
+ end
16
+
17
+ def [](key)
18
+ @config[key.to_sym]
19
+ end
20
+
21
+ def home()
22
+ "#{ENV['HOME']}/.ucb_confluence"
23
+ end
24
+
25
+ def init_home_dir()
26
+ FileUtils.mkdir(home()) unless File.exists?(home())
27
+ FileUtils.mkdir("#{home()}/log") unless File.exists?("#{home()}/log")
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ module Confluence
2
+ class Conn
3
+
4
+ def initialize(config)
5
+ @config = config
6
+ server = XMLRPC::Client.new2(@config[:server_url])
7
+ @conn = server.proxy("confluence1")
8
+ @token = "12345"
9
+ do_connect()
10
+ end
11
+
12
+ def method_missing(method_name, *args)
13
+ begin
14
+ @conn.send(method_name, *([@token] + args))
15
+ rescue XMLRPC::FaultException => e
16
+ if (e.faultString.include?("InvalidSessionException"))
17
+ do_connect
18
+ retry
19
+ else
20
+ raise(e.faultString)
21
+ end
22
+ end
23
+ end
24
+
25
+ def do_connect()
26
+ @token = @conn.login(@config[:username], @config[:password])
27
+ rescue XMLRPC::FaultException => e
28
+ raise(e.faultString)
29
+ rescue => e
30
+ Confluence.logger.debug("#{e.class}: #{e.message}")
31
+ raise(e)
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,56 @@
1
+ module Confluence
2
+ class Group
3
+ class << self
4
+ ##
5
+ # Retrieve a list of all groups in Confluence.
6
+ #
7
+ # @return [Array<String>] names of all groups in our Confluence instance.
8
+ #
9
+ def all()
10
+ Confluence.conn.getGroups()
11
+ end
12
+
13
+ ##
14
+ # Creates a new group in Confluence.
15
+ #
16
+ # @param [String] name of group to create.
17
+ # @return [true, false] result of whether group was successfully created.
18
+ #
19
+ def create(name)
20
+ if all.include?(name)
21
+ return false
22
+ else
23
+ result = Confluence.conn.addGroup(name)
24
+ Confluence.logger.debug("Created group: #{name}")
25
+ end
26
+ result
27
+ end
28
+
29
+ ##
30
+ # Delete a group from Confluence.
31
+ #
32
+ # @param [String] name of group to delete.
33
+ # @return [true, false] result of whether group was successfully deleted.
34
+ #
35
+ def delete(name)
36
+ if all.include?(name)
37
+ result = Confluence.conn.removeGroup(name, Confluence::User::DEFAULT_GROUP)
38
+ Confluence.logger.debug("Deleted group: #{name}")
39
+ return result
40
+ else
41
+ return false
42
+ end
43
+ end
44
+
45
+ ##
46
+ # Predicate that indicates whether a given group exists in Confluence
47
+ #
48
+ # @param [String] the group name.
49
+ # @return [true,false]
50
+ #
51
+ def exists?(grp_name)
52
+ all.include?(grp_name)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,87 @@
1
+
2
+ ##
3
+ # Disables a user's Confluence account if they are considered expired.
4
+ #
5
+ module Confluence
6
+ module Jobs
7
+ class DisableExpiredUsers
8
+
9
+ def initialize()
10
+ @disabled_users = []
11
+ end
12
+
13
+ ##
14
+ # Run the job
15
+ #
16
+ def execute()
17
+ @disabled_users.clear()
18
+ disable_expired_users()
19
+ log_job()
20
+ end
21
+
22
+ ##
23
+ # Disables any users that are expired in LDAP or are no longer in LDAP.
24
+ #
25
+ def disable_expired_users()
26
+ confluence_user_names.each do |name|
27
+ next if name == "conflusa"
28
+ ldap_person = find_in_ldap(name)
29
+
30
+ if ldap_person.nil? || !eligible_for_confluence?(ldap_person)
31
+ user = find_in_confluence(name)
32
+ user.disable()
33
+ @disabled_users << user
34
+ end
35
+ end
36
+ end
37
+
38
+ def log_job()
39
+ msg = "#{self.class.name}\n\n"
40
+ msg.concat("Disabled the following Users:\n\n")
41
+ @disabled_users.each { |u| msg.concat(u) }
42
+ logger.info(msg)
43
+ end
44
+
45
+ def logger()
46
+ Confluence.logger
47
+ end
48
+
49
+ ##
50
+ # @return [Array<String>] confluence user names.
51
+ #
52
+ def confluence_user_names()
53
+ Confluence::User.active.map(&:name)
54
+ end
55
+
56
+ ##
57
+ # @param [String] user's confluence account name.
58
+ # @return [Confluence::User, nil]
59
+ #
60
+ def find_in_confluence(name)
61
+ Confluence::User.find_by_name(name)
62
+ end
63
+
64
+ ##
65
+ # @param [String] user's ldap uid
66
+ # @return [UCB::LDAP::Person, nil]
67
+ #
68
+ def find_in_ldap(ldap_uid)
69
+ UCB::LDAP::Person.find_by_uid(ldap_uid)
70
+ end
71
+
72
+ def eligible_for_confluence?(person)
73
+ valid_affiliations = person.affiliations.inject([]) do |accum, aff|
74
+ if aff =~ /AFFILIATE-TYPE.*(ALUMNUS|RETIREE|EXPIRED)/
75
+ accum
76
+ elsif aff =~ /AFFILIATE-TYPE.*/
77
+ accum << aff
78
+ end
79
+ accum
80
+ end
81
+
82
+ person.employee? || !valid_affiliations.empty?
83
+ end
84
+ end
85
+ end
86
+ end
87
+