sakai-info 0.1.0 → 0.2.0

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.
@@ -2,7 +2,7 @@
2
2
  # SakaiInfo::User library
3
3
  #
4
4
  # Created 2012-02-17 daveadams@gmail.com
5
- # Last updated 2012-02-17 daveadams@gmail.com
5
+ # Last updated 2012-02-24 daveadams@gmail.com
6
6
  #
7
7
  # https://github.com/daveadams/sakai-info
8
8
  #
@@ -17,31 +17,50 @@ module SakaiInfo
17
17
  @@cache = {}
18
18
  def self.find(id)
19
19
  if @@cache[id].nil?
20
- user_id = eid = nil
21
- DB.connect.exec("select user_id, eid from sakai_user_id_map " +
22
- "where user_id=:user_id or eid=:eid", id, id) do |row|
23
- user_id = row[0]
24
- eid = row[1]
25
- end
26
- if user_id.nil? or eid.nil?
20
+ eid = User.get_eid(id)
21
+ user_id = User.get_user_id(id)
22
+ if eid.nil? or user_id.nil?
27
23
  raise ObjectNotFoundException.new(User, id)
28
24
  end
29
25
 
30
- DB.connect.exec("select first_name, last_name, type, " +
31
- "to_char(createdon,'YYYY-MM-DD HH24:MI:SS'), " +
32
- "to_char(modifiedon,'YYYY-MM-DD HH24:MI:SS') " +
33
- "from sakai_user where user_id=:userid", user_id) do |row|
34
- first_name, last_name, type, created_at, modified_at = *row
35
- first_name ||= ""
36
- last_name ||= ""
37
- @@cache[eid] =
38
- @@cache[user_id] =
39
- User.new(user_id, eid, (first_name+' '+last_name), type, created_at, modified_at)
26
+ row = DB.connect.fetch("select first_name, last_name, type, " +
27
+ "to_char(createdon,'YYYY-MM-DD HH24:MI:SS') as created_at, " +
28
+ "to_char(modifiedon,'YYYY-MM-DD HH24:MI:SS') as modified_at " +
29
+ "from sakai_user where user_id=?", user_id).first
30
+ if row.nil?
31
+ raise ObjectNotFoundException.new(User, id)
40
32
  end
33
+ @@cache[eid] =
34
+ @@cache[user_id] =
35
+ User.new(user_id, eid,
36
+ ((row[:first_name] || "") + " " + (row[:last_name] || "")).strip,
37
+ row[:type], row[:created_at], row[:modified_at])
41
38
  end
42
39
  @@cache[id]
43
40
  end
44
41
 
42
+ @@id_cache = {}
43
+ def self.get_ids(id)
44
+ @@id_cache[id] ||=
45
+ DB.connect[:sakai_user_id_map].where({:user_id => id, :eid => id}.sql_or).first
46
+ end
47
+
48
+ def self.get_eid(id)
49
+ if ids = User.get_ids(id)
50
+ ids[:eid]
51
+ else
52
+ nil
53
+ end
54
+ end
55
+
56
+ def self.get_user_id(id)
57
+ if ids = User.get_ids(id)
58
+ ids[:user_id]
59
+ else
60
+ nil
61
+ end
62
+ end
63
+
45
64
  def initialize(id, eid, name, type, created_at, modified_at)
46
65
  @id = id
47
66
  @eid = eid
@@ -102,56 +121,46 @@ module SakaiInfo
102
121
 
103
122
  def preferences_xml
104
123
  if @preferences_xml.nil?
105
- db = DB.connect
106
124
  @preferences_xml = ""
107
- db.exec("select xml from sakai_preferences " +
108
- "where preferences_id=:userid", @user_id) do |row|
109
- REXML::Document.new(row[0].read).write(@preferences_xml, 2)
125
+ row = DB.connect[:sakai_preferences].filter(:preferences_id => @user_id).first
126
+ if not row.nil?
127
+ REXML::Document.new(row[:xml].read).write(@preferences_xml, 2)
110
128
  end
111
129
  end
112
130
  @preferences_xml
113
131
  end
114
132
 
115
133
  # finders/counters
116
- @@total_user_count = nil
117
134
  def self.count
118
- if @@total_user_count.nil?
119
- @@total_user_count = 0
120
- DB.connect.exec("select count(*) from sakai_user") do |row|
121
- @@total_user_count = row[0].to_i
122
- end
123
- end
124
- @@total_user_count
135
+ DB.connect[:sakai_user].count
125
136
  end
126
137
 
127
138
  def self.count_by_realm_id_and_role_id(realm_id, role_id)
128
- count = 0
129
- DB.connect.exec("select count(*) from sakai_realm_rl_gr " +
130
- "where realm_key = :realm_id " +
131
- "and role_key = :role_id", realm_id, role_id) do |row|
132
- count = row[0].to_i
133
- end
134
- count
139
+ DB.connect[:sakai_realm_rl_gr].
140
+ filter(:realm_key => realm_id, :role_key => role_id).count
135
141
  end
136
142
 
137
143
  def self.find_by_realm_id_and_role_id(realm_id, role_id)
138
- users = []
139
- DB.connect.exec("select first_name, last_name, type, " +
140
- "to_char(createdon,'YYYY-MM-DD HH24:MI:SS'), " +
141
- "to_char(modifiedon,'YYYY-MM-DD HH24:MI:SS') " +
142
- "from sakai_user where user_id in " +
143
- "(select user_id from sakai_realm_rl_gr " +
144
- "where realm_key = :realm_id " +
145
- "and role_key = :role_id)", realm_id, role_id) do |row|
146
- first_name, last_name, type, created_at, modified_at = *row
147
- first_name ||= ""
148
- last_name ||= ""
149
- @@cache[eid] =
150
- @@cache[user_id] =
151
- User.new(user_id, eid, (first_name+' '+last_name), type, created_at, modified_at)
152
- users << @@cache[eid]
153
- end
154
- users
144
+ # TODO: implement this correctly
145
+ # (code below isn't going to work)
146
+ # users = []
147
+ # DB.connect.fetch("select first_name, last_name, type, " +
148
+ # "to_char(createdon,'YYYY-MM-DD HH24:MI:SS') as created_at, " +
149
+ # "to_char(modifiedon,'YYYY-MM-DD HH24:MI:SS') as modified_at " +
150
+ # "from sakai_user where user_id in " +
151
+ # "(select user_id from sakai_realm_rl_gr " +
152
+ # "where realm_key = ? " +
153
+ # "and role_key = ?)", realm_id, role_id) do |row|
154
+ # first_name, last_name, type, created_at, modified_at = *row
155
+ # first_name ||= ""
156
+ # last_name ||= ""
157
+ # @@cache[eid] =
158
+ # @@cache[user_id] =
159
+ # User.new(user_id, eid, (first_name+' '+last_name), type, created_at, modified_at)
160
+ # users << @@cache[eid]
161
+ # end
162
+ # users
163
+ nil
155
164
  end
156
165
 
157
166
  # yaml/json serialization
@@ -177,13 +186,13 @@ module SakaiInfo
177
186
  }
178
187
  end
179
188
 
180
- def membership_serialization
189
+ def sites_serialization
181
190
  {
182
191
  "sites" => self.membership.collect { |sm| sm.serialize(:user_summary) }
183
192
  }
184
193
  end
185
194
 
186
- def question_pools_serialization
195
+ def pools_serialization
187
196
  if self.question_pool_count > 0
188
197
  {
189
198
  "question_pools" => self.question_pools.collect { |qp| qp.serialize(:user_summary) }
@@ -192,27 +201,27 @@ module SakaiInfo
192
201
  {}
193
202
  end
194
203
  end
204
+
205
+ def self.all_serializations
206
+ [:default, :sites, :pools]
207
+ end
195
208
  end
196
209
 
197
210
  class UserProperty
198
211
  def self.get(user_id, property_name)
199
- db = DB.connect
200
- value = nil
201
- db.exec("select value from sakai_user_property " +
202
- "where user_id=:user_id and name=:name", user_id, property_name) do |row|
203
- value = row[0].read
212
+ row = DB.connect[:sakai_user_property].
213
+ filter(:user_id => user_id, :name => property_name).first
214
+ if row.nil?
215
+ nil
216
+ else
217
+ row[:value].read
204
218
  end
205
- return value
206
219
  end
207
220
 
208
221
  def self.find_by_user_id(user_id)
209
- db = DB.connect
210
222
  properties = {}
211
- db.exec("select name, value from sakai_user_property " +
212
- "where user_id=:user_id", user_id) do |row|
213
- name = row[0]
214
- value = row[1].read
215
- properties[name] = value
223
+ DB.connect[:sakai_user_property].where(:user_id => user_id).all.each do |row|
224
+ properties[row[:name]] = row[:value].read
216
225
  end
217
226
  return properties
218
227
  end
@@ -1,3 +1,3 @@
1
1
  module SakaiInfo
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sakai-info
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - David Adams
@@ -15,10 +15,37 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-02-19 00:00:00 -06:00
18
+ date: 2012-02-24 00:00:00 -06:00
19
19
  default_executable:
20
- dependencies: []
21
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: sequel
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: sqlite3
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
22
49
  description: A command line tool and a suite of libraries for representing the objects and relationships defined by a Sakai CLE database.
23
50
  email: daveadams@gmail.com
24
51
  executables:
@@ -40,12 +67,10 @@ files:
40
67
  - lib/sakai-info/user.rb
41
68
  - lib/sakai-info/version.rb
42
69
  - lib/sakai-info/announcement.rb
70
+ - lib/sakai-info/database.rb
43
71
  - lib/sakai-info/cli.rb
44
- - lib/sakai-info/instance.rb
45
- - lib/sakai-info/configuration.rb
46
72
  - lib/sakai-info/message.rb
47
73
  - lib/sakai-info/content.rb
48
- - lib/sakai-info/db.rb
49
74
  - lib/sakai-info/sakai_xml_entity.rb
50
75
  - bin/sakai-info
51
76
  - README.md
@@ -54,8 +79,8 @@ files:
54
79
  - ROADMAP.md
55
80
  has_rdoc: true
56
81
  homepage: https://github.com/daveadams/sakai-info
57
- licenses: []
58
-
82
+ licenses:
83
+ - Public Domain
59
84
  post_install_message:
60
85
  rdoc_options: []
61
86
 
@@ -1,288 +0,0 @@
1
- # sakai-info/configuration.rb
2
- # SakaiInfo::Configuration library
3
- #
4
- # Created 2012-02-15 daveadams@gmail.com
5
- # Last updated 2012-02-19 daveadams@gmail.com
6
- #
7
- # https://github.com/daveadams/sakai-info
8
- #
9
- # This software is public domain.
10
- #
11
-
12
- module SakaiInfo
13
- class NoConfigFoundException < SakaiException; end
14
- class AlreadyConfiguredException < SakaiException; end
15
- class InvalidInstanceNameException < SakaiException; end
16
- class InvalidConfigException < SakaiException; end
17
- class UnsupportedConfigException < InvalidConfigException; end
18
- class MultipleConfigException < InvalidConfigException
19
- def initialize
20
- @exceptions = []
21
- end
22
-
23
- def add(instance_name, exception)
24
- @exceptions << [instance_name, exception]
25
- end
26
-
27
- def count
28
- @exceptions.length
29
- end
30
-
31
- def message
32
- "Multiple config exceptions were found:\n " +
33
- @exceptions.collect{ |e| "#{e[0]}: #{e[1].message}" }.join("\n ")
34
- end
35
- end
36
-
37
- # config format assumptions:
38
- # a YAML string containing one of the following options:
39
- # - a single database connection spec
40
- # - eg:
41
- # ---
42
- # dbtype: oracle
43
- # dbsid: PROD
44
- # username: sakai
45
- # password: Sekrit1
46
- # OR:
47
- # - an "instances" key containing a hash of named connection specs
48
- # - with a "default" key naming the spec to use if none is specified
49
- # - eg:
50
- # ---
51
- # default: production
52
- # instances:
53
- # production:
54
- # dbtype: oracle
55
- # service: PROD
56
- # username: sakai
57
- # password: prodpass
58
- # test:
59
- # dbtype: oracle
60
- # service: TEST
61
- # host: testdb.host
62
- # port: 1521
63
- # username: sakai
64
- # password: testpass
65
- # dev:
66
- # dbtype: mysql
67
- # host: dbserver.hostname.int
68
- # port: 3306
69
- # username: sakai
70
- # password: ironchef
71
- # dbname: sakaidev
72
- # localdev:
73
- # dbtype: mysql
74
- # host: localhost
75
- # port: 3306
76
- # username: sakai
77
- # password: ironchef
78
- # dbname: sakailocal
79
- #
80
- #
81
- # NOTES:
82
- # - Oracle connections should use either an alias defined in the
83
- # driver's tnsnames.ora file, or specify the host and port as the
84
- # test instance example above does
85
- #
86
- class Configuration
87
- @@config = nil
88
-
89
- # validate just a single database connection configuration hash
90
- def self.validate_single_connection_config(config)
91
- if config.nil?
92
- raise InvalidConfigException.new("The config provided was nil")
93
- end
94
-
95
- if not config.is_a? Hash
96
- raise InvalidConfigException.new("The config provided must be a Hash")
97
- end
98
-
99
- # we have to have a dbtype value or we can't validate
100
- if config["dbtype"].nil?
101
- raise InvalidConfigException.new("The config does not specify 'dbtype'")
102
- end
103
-
104
- # force lowercase to simplify comparisons
105
- dbtype = config["dbtype"].downcase
106
-
107
- if not %w(oracle mysql).include? dbtype
108
- raise UnsupportedConfigException.new("Database type '#{dbtype}' is not supported.")
109
- end
110
-
111
- # now check per-dbtype requirements
112
- if dbtype == "oracle"
113
- %w(service username password).each do |required_key|
114
- if config[required_key].nil? or config[required_key] == ""
115
- raise InvalidConfigException.new("Oracle config requires values for 'service', 'username', and 'password'.")
116
- end
117
- end
118
- elsif dbtype == "mysql"
119
- %w(host username password dbname).each do |required_key|
120
- if config[required_key].nil? or config[required_key] == ""
121
- raise InvalidConfigException.new("MySQL config requires values for 'host', 'username', 'password', and 'dbname'.")
122
- end
123
- end
124
- else
125
- # we should never have made it here
126
- raise UnsupportedConfigException.new("Database type '#{dbtype}' is not supported.")
127
- end
128
-
129
- # for both types, 'port' is optional but if it exists it must be a valid TCP port
130
- if not config["port"].nil?
131
- begin
132
- port = config["port"].to_i
133
- if port < 1 or port > 65535
134
- raise
135
- end
136
- rescue
137
- raise InvalidConfigException.new("Config value 'port' must be a valid TCP port number.")
138
- end
139
- end
140
-
141
- # if we made it here the config is complete and well-formed
142
- return true
143
- end
144
-
145
- # validate that configuration is complete and well-formed
146
- def self.validate_config(config)
147
- if config.nil?
148
- raise InvalidConfigException.new("The config provided was nil")
149
- end
150
-
151
- if not config.is_a? Hash
152
- raise InvalidConfigException.new("The config provided must be a Hash")
153
- end
154
-
155
- # if 'dbtype' exists, it will be a single database configuration
156
- if config["dbtype"]
157
- self.validate_single_connection_config(config)
158
- else
159
- # otherwise both 'default' and 'instances' keys are required
160
- if config.keys.sort != ["default","instances"]
161
- raise InvalidConfigException.new("The config must specify either 'dbtype' or both 'default' and 'instances'.")
162
- end
163
-
164
- # enforce types on the values of 'default' and 'instances'
165
- if not config["default"].is_a? String
166
- raise InvalidConfigException.new("The value of 'default' must be a String.")
167
- end
168
- if not config["instances"].is_a? Hash
169
- raise InvalidConfigException.new("The value of 'instances' must be a Hash.")
170
- end
171
-
172
- # 'default' must be a string pointing to one of the 'instances' keys
173
- if not config["instances"].keys.include? config["default"]
174
- raise InvalidConfigException.new("The default instance '#{config["default"]}' was not among the instance names given: #{config["instances"].keys.inspect}")
175
- end
176
-
177
- # check the validity of each instance, collecting exceptions as we go
178
- multi_exceptions = nil
179
- config["instances"].keys.each do |instance_name|
180
- begin
181
- self.validate_single_connection_config(config["instances"][instance_name])
182
- rescue InvalidConfigException => e
183
- # create the object if it doesn't already exist
184
- multi_exceptions ||= MultipleConfigException.new
185
-
186
- # add this exception to the list
187
- multi_exceptions.add(instance_name, e)
188
- end
189
- # continue the loop no matter what
190
- end
191
-
192
- # if this object was created, the exception needs to be raised
193
- if not multi_exceptions.nil?
194
- raise multi_exceptions
195
- end
196
- end
197
-
198
- # if we've made it this far, the configuration must be fine
199
- return true
200
- end
201
-
202
- def initialize(config)
203
- begin
204
- if config.is_a? Hash
205
- @config = config
206
- elsif config.is_a? String and File.exist?(config)
207
- # try to parse as a filename first
208
- if File.exist?(config)
209
- @config = YAML::load_file(config)
210
- end
211
- else
212
- # otherwise try to parse it generically
213
- @config = YAML::load(config)
214
- end
215
- rescue Exception => e
216
- raise InvalidConfigException.new("Unable to parse configuration: #{e}")
217
- end
218
-
219
- # check that the configuration specified is well formed
220
- if not Configuration.validate_config(@config)
221
- raise InvalidConfigException.new("Config provided is either incomplete or poorly formed.")
222
- end
223
-
224
- # create instance objects
225
- @instances = {}
226
- if not @config["instances"].nil?
227
- @config["instances"].keys.each do |instance_name|
228
- @instances[instance_name] = Instance.create(@config["instances"][instance_name])
229
- if instance_name == @config["default"]
230
- @instances[:default] = @instances[instance_name]
231
- end
232
- end
233
- else
234
- @instances[:default] = Instance.create(@config)
235
- end
236
- end
237
-
238
- # instance accessibility
239
- def get_instance(instance_name)
240
- @instances[instance_name] or raise InvalidInstanceNameException
241
- end
242
-
243
- def default_instance
244
- @instances[:default]
245
- end
246
-
247
- DEFAULT_CONFIG_FILE = File.expand_path("~/.sakai-info")
248
- # check to see if configuration file exists
249
- # by default ~/.sakai-info
250
- def self.config_file_path
251
- if File.readable? DEFAULT_CONFIG_FILE
252
- DEFAULT_CONFIG_FILE
253
- else
254
- nil
255
- end
256
- end
257
-
258
- # are we already configured?
259
- def self.configured?
260
- not @@config.nil?
261
- end
262
-
263
- # load configuration as a class variable (and return it as well)
264
- def self.load_config(alternate_config_file = nil)
265
- if Configuration.configured?
266
- raise AlreadyConfiguredException
267
- end
268
-
269
- unless(config_file = alternate_config_file || Configuration.config_file_path)
270
- raise NoConfigFoundException
271
- end
272
-
273
- @@config = Configuration.new(config_file)
274
- end
275
-
276
- # return specified database connection configuration
277
- def self.get_instance(instance_name = nil)
278
- Configuration.load_config unless Configuration.configured?
279
-
280
- if instance_name.nil?
281
- @@config.default_instance
282
- else
283
- @@config.get_instance(instance_name)
284
- end
285
- end
286
- end
287
- end
288
-