ucb_confluence 0.0.2

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