ig3tool 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/bin/ig3tool +17 -21
  2. data/lib/actions/bib.rb +295 -0
  3. data/lib/actions/bitching.rb +19 -0
  4. data/lib/actions/cultuur.rb +3 -0
  5. data/lib/actions/interne.rb +98 -0
  6. data/lib/actions/kaching.rb +90 -0
  7. data/lib/actions/people.rb +178 -0
  8. data/lib/actions/printing.rb +125 -0
  9. data/lib/actions/product.rb +154 -0
  10. data/lib/bib.rb +94 -0
  11. data/lib/billing.rb +112 -0
  12. data/lib/bitching.rb +49 -0
  13. data/lib/config.rb +19 -0
  14. data/lib/glade/cola_light_small.png +0 -0
  15. data/lib/glade/cola_light_xsmall.png +0 -0
  16. data/lib/glade/cola_small.png +0 -0
  17. data/lib/glade/cola_xsmall.png +0 -0
  18. data/lib/glade/doos_small.png +0 -0
  19. data/lib/glade/doos_xsmall.png +0 -0
  20. data/lib/glade/icons/cola_light_small.png +0 -0
  21. data/lib/glade/icons/cola_light_xsmall.png +0 -0
  22. data/lib/glade/icons/cola_small.png +0 -0
  23. data/lib/glade/icons/cola_xsmall.png +0 -0
  24. data/lib/glade/icons/doos_small.png +0 -0
  25. data/lib/glade/icons/doos_xsmall.png +0 -0
  26. data/lib/glade/icons/piggy_small.png +0 -0
  27. data/lib/glade/icons/piggy_xsmall.png +0 -0
  28. data/lib/glade/money_small.png +0 -0
  29. data/lib/glade/money_xsmall.png +0 -0
  30. data/lib/glade/newinterne.glade +504 -0
  31. data/lib/glade/piggy_small.png +0 -0
  32. data/lib/glade/piggy_xsmall.png +0 -0
  33. data/lib/glade/sales.glade +89 -87
  34. data/lib/horrible_hack.rb +15 -0
  35. data/lib/interne.rb +111 -0
  36. data/lib/ldap.rb +104 -0
  37. data/lib/log.rb +25 -0
  38. data/lib/membership.rb +32 -0
  39. data/lib/mymd5.rb +95 -0
  40. data/lib/people.rb +143 -0
  41. data/lib/printing.rb +238 -0
  42. data/lib/request.rb +14 -0
  43. data/lib/sales.rb +158 -0
  44. data/lib/ui/automaatwindow.rb +2 -2
  45. data/lib/ui/bibliotheekwindow.rb +16 -17
  46. data/lib/ui/bibwindow.rb +15 -15
  47. data/lib/ui/gladehelper.rb +20 -6
  48. data/lib/ui/internewindow.rb +12 -9
  49. data/lib/ui/loginwindow.rb +2 -4
  50. data/lib/ui/memberswindow.rb +9 -9
  51. data/lib/ui/newinterne.rb +258 -0
  52. data/lib/ui/peoplewindow.rb +14 -16
  53. data/lib/ui/printenwindow.rb +11 -11
  54. data/lib/ui/printingwindow.rb +19 -20
  55. data/lib/ui/productswindow.rb +27 -15
  56. data/lib/ui/saleswindow.rb +21 -8
  57. data/lib/ui/toolwindow.rb +5 -3
  58. data/lib/utils.rb +106 -0
  59. data/lib/web.rb +98 -0
  60. metadata +48 -3
data/lib/ldap.rb ADDED
@@ -0,0 +1,104 @@
1
+ =begin
2
+
3
+ beetje stuff om te authen naar ldap
4
+ bvb:
5
+ bitch?("joske", "dejoszijnpasswd")
6
+ => true/false
7
+
8
+ TODO: filteren op debugger!
9
+
10
+ =end
11
+
12
+ require 'mymd5'
13
+
14
+ begin
15
+
16
+ require "ldap"
17
+
18
+ class IGLDAP < LDAP::Conn
19
+ DN = "cn=Proxyuser,dc=infogroep,dc=be"
20
+ PASS = "pRoxyAuth"
21
+ BASE_DN = "dc=infogroep,dc=be"
22
+ PEOPLE_DN = "ou=People,dc=infogroep,dc=be"
23
+ LDAP_HOST = "infogroep.be"
24
+ LDAP_PORT = 389
25
+ PROTOCOL_VERSION = 3
26
+
27
+ def initialize (host = LDAP_HOST, version = PROTOCOL_VERSION)
28
+ super( host, LDAP_PORT )
29
+ set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, version )
30
+ return self
31
+ end
32
+
33
+ def bind(dn = DN, pass = PASS)
34
+ super( dn, pass )
35
+ end
36
+
37
+ def self.bitchke?(user, pass)
38
+ begin
39
+ conn = IGLDAP.new.bind
40
+ attrs = %w{uid userPassword}
41
+ filter = "uid=#{user}"
42
+ result = conn.search2(IGLDAP::PEOPLE_DN, LDAP::LDAP_SCOPE_SUBTREE,filter, attrs)
43
+
44
+ passr = result.first["userPassword"].first.gsub(/\{crypt\}/, "")
45
+
46
+
47
+ match = passr.match(/(\$.+\$.+\$)(.*)/)
48
+ #salt = match[1]
49
+ salt = match[1].gsub(/\$1\$/, "").delete("$")
50
+ passh = match[2]
51
+ #pass.crypt(salt) == passr
52
+ crypt(pass, :md5, salt) == passr
53
+ rescue Exception => e
54
+ false
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ rescue
61
+
62
+ require 'net/ldap'
63
+ include Net
64
+
65
+ class IGLDAP
66
+ DN = "cn=Proxyuser,dc=infogroep,dc=be"
67
+ PASS = "pRoxyAuth"
68
+ BASE_DN = "dc=infogroep,dc=be"
69
+ PEOPLE_DN = "ou=People,dc=infogroep,dc=be"
70
+ LDAP_HOST = "infogroep.be"
71
+ LDAP_PORT = 389
72
+ PROTOCOL_VERSION = 3
73
+
74
+ def initialize
75
+ @conn = Net::LDAP.new( {:host => LDAP_HOST, :port => LDAP_PORT, :auth => { :method => :simple, :username => DN, :password => PASS }} )
76
+ end
77
+
78
+ def bind
79
+ @conn.bind
80
+ @conn
81
+ end
82
+
83
+ def self.bitchke?(user, pass)
84
+ begin
85
+ conn = IGLDAP.new.bind
86
+ attrs = %w{uid userPassword}
87
+ filter = "uid=#{user}"
88
+ result = conn.search(:base => PEOPLE_DN, :filter => filter)
89
+
90
+ passr = result.first["userPassword"].first.gsub(/\{crypt\}/, "")
91
+
92
+ match = passr.match(/(\$.+\$.+\$)(.*)/)
93
+ salt = match[1].gsub(/\$1\$/, "").delete("$")
94
+ #salt = match[1]
95
+ passh = match[2]
96
+ crypt(pass, :md5, salt) == passr
97
+ #pass.crypt(salt) == passr
98
+ rescue Exception => e
99
+ false
100
+ end
101
+ end
102
+
103
+ end
104
+ end
data/lib/log.rb ADDED
@@ -0,0 +1,25 @@
1
+ module Ig3tool
2
+
3
+ class LogEntry < ActiveRecord::Base
4
+
5
+ set_table_name "log"
6
+
7
+ validates_presence_of :system,
8
+ :subsystem,
9
+ :timestamp,
10
+ :message
11
+
12
+ end
13
+
14
+ class Logger
15
+
16
+ def self.log(system, subsystem, message)
17
+ LogEntry.create(:system => system.to_s,
18
+ :timestamp => Time.now.to_i,
19
+ :subsystem => subsystem.to_s,
20
+ :message => message.to_s)
21
+ end
22
+
23
+ end
24
+
25
+ end
data/lib/membership.rb ADDED
@@ -0,0 +1,32 @@
1
+ module Ig3tool
2
+ class Membership < ActiveRecord::Base
3
+ set_table_name "Memberships"
4
+ set_nonauto_primary_key :barcode
5
+
6
+ validates_uniqueness_of :barcode
7
+
8
+ validates_presence_of :barcode,
9
+ :username,
10
+ :year,
11
+ :status
12
+
13
+ validates_inclusion_of :status,
14
+ :in => ["debugger",
15
+ "ex-debugger",
16
+ "member",
17
+ "honorary member"]
18
+
19
+ belongs_to :person,
20
+ :class_name => "Person",
21
+ :foreign_key => "username"
22
+
23
+ def self.member?(barcode)
24
+ begin
25
+ membership = find(barcode)
26
+ membership.year == Time.werkjaar
27
+ rescue ActiveRecord::RecordNotFound
28
+ false
29
+ end
30
+ end
31
+ end
32
+ end
data/lib/mymd5.rb ADDED
@@ -0,0 +1,95 @@
1
+ require 'English'
2
+ require 'base64'
3
+ require 'md5'
4
+ require 'sha1'
5
+
6
+ ITOA64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
7
+
8
+
9
+ def crypt(password, algo = :md5, salt = nil, magic='$1$')
10
+
11
+ salt ||= generate_salt(8)
12
+
13
+ case algo
14
+ when :md5, :sha1, :rmd160
15
+ require "digest/#{algo}"
16
+ when :sha256, :sha384, :sha512
17
+ require "digest/sha2"
18
+ else
19
+ raise(ArgumentError, "unknown algorithm")
20
+ end
21
+ digest_class = Digest.const_get(algo.to_s.upcase)
22
+
23
+ # The password first, since that is what is most unknown. Then our magic string. Then the raw salt.
24
+ m = digest_class.new
25
+ m.update(password + magic + salt)
26
+
27
+ # Then just as many characters of the MD5(pw,salt,pw)
28
+ mixin = digest_class.new.update(password + salt + password).digest
29
+ password.length.times do |i|
30
+ m.update(mixin[i % 16].chr)
31
+ end
32
+
33
+ # Then something really weird...
34
+ # Also really broken, as far as I can tell. -m
35
+ i = password.length
36
+ while i != 0
37
+ if (i & 1) != 0
38
+ m.update("\x00")
39
+ else
40
+ m.update(password[0].chr)
41
+ end
42
+ i >>= 1
43
+ end
44
+
45
+ final = m.digest
46
+
47
+ # and now, just to make sure things don't run too fast
48
+ 1000.times do |i|
49
+ m2 = digest_class.new
50
+
51
+ if (i & 1) != 0
52
+ m2.update(password)
53
+ else
54
+ m2.update(final)
55
+ end
56
+
57
+ if (i % 3) != 0
58
+ m2.update(salt)
59
+ end
60
+ if (i % 7) != 0
61
+ m2.update(password)
62
+ end
63
+
64
+ if (i & 1) != 0
65
+ m2.update(final)
66
+ else
67
+ m2.update(password)
68
+ end
69
+
70
+ final = m2.digest
71
+ end
72
+
73
+ # This is the bit that uses to64() in the original code.
74
+
75
+ rearranged = ""
76
+
77
+ [ [0, 6, 12], [1, 7, 13], [2, 8, 14], [3, 9, 15], [4, 10, 5] ].each do |a, b, c|
78
+
79
+ v = final[a] << 16 | final[b] << 8 | final[c]
80
+
81
+ 4.times do
82
+ rearranged += ITOA64[v & 0x3f].chr
83
+ v >>= 6
84
+ end
85
+ end
86
+
87
+ v = final[11]
88
+
89
+ 2.times do
90
+ rearranged += ITOA64[v & 0x3f].chr
91
+ v >>= 6
92
+ end
93
+
94
+ magic + salt + '$' + rearranged
95
+ end
data/lib/people.rb ADDED
@@ -0,0 +1,143 @@
1
+ require 'utils'
2
+
3
+ module Ig3tool
4
+
5
+ class Person < ActiveRecord::Base
6
+
7
+ set_table_name "people"
8
+ set_nonauto_primary_key :username
9
+
10
+ # XXX wat willen we dat aanwezig is?
11
+ validates_presence_of :username,
12
+ :email,
13
+ :first_name,
14
+ :last_name
15
+
16
+ validates_uniqueness_of :username,
17
+ :email
18
+
19
+ has_one :interne,
20
+ :class_name => "Interne",
21
+ :foreign_key => "username"
22
+
23
+ # breekt horribly met to_yaml, zucht
24
+ # has_one :membership,
25
+ # :conditions => ["year = ?", Time.werkjaar],
26
+ # :class_name => 'Membership',
27
+ # :foreign_key => "username"
28
+
29
+ has_many :memberships,
30
+ :class_name => "Membership",
31
+ :foreign_key => "username",
32
+ :order => "year desc"
33
+
34
+ has_one :print_user,
35
+ :class_name => "PrintUser",
36
+ :foreign_key => "username"
37
+ # :dependent => :destroy # destroyes printuser when person gets deleted
38
+ # XXX do we want that?
39
+
40
+ def membership
41
+ if !memberships.empty? and memberships[0].year == Time.werkjaar
42
+ memberships[0]
43
+ else
44
+ nil
45
+ end
46
+ end
47
+
48
+ def username=(newusername)
49
+ write_attribute(:username, newusername)
50
+ end
51
+
52
+ def member?
53
+ not membership.nil?
54
+ end
55
+
56
+ def honorarymember?
57
+ member? and membership.status == "honorary member"
58
+ end
59
+
60
+ def exhonorarymember?
61
+ not honorarymember? and not memberships.find(:all).find_all{|m| m.status == "honorary member"}.empty?
62
+ end
63
+
64
+ def debugger?
65
+ (not interne.nil?) and (interne.afgesloten != 1) and member? and (membership.status == "debugger")
66
+ end
67
+
68
+ def exdebugger?
69
+ (not debugger?) and (not memberships.find(:all).find_all{|m| m.status == "debugger" or m.status == "ex-debugger"}.empty?)
70
+ end
71
+
72
+ def self.everybody
73
+ find(:all)
74
+ end
75
+
76
+ def self.members
77
+ find(:all).find_all{|p| p.member?}
78
+ end
79
+
80
+ def self.nonmembers
81
+ find(:all).find_all{|p| p.membership.nil?}
82
+ end
83
+
84
+ def self.debuggers
85
+ find(:all).find_all{|p| p.debugger?}
86
+ end
87
+
88
+ def self.exdebuggers
89
+ find(:all).find_all{|p| p.exdebugger?}
90
+ end
91
+
92
+ def self.honorarymembers
93
+ find(:all).find_all{|p| p.honorarymember?}
94
+ end
95
+
96
+ def self.exhonorarymembers
97
+ find(:all).find_all{|p| p.exhonorarymember?}
98
+ end
99
+
100
+ def unbugger!
101
+ raise NotADebugger unless debugger?
102
+ raise SaldoNotZero if interne.saldo != 0
103
+
104
+ interne.afgesloten = true
105
+ membership.status = "member"
106
+
107
+ transaction do
108
+ print_user.remove_aliases
109
+
110
+ membership.save!
111
+ interne.save!
112
+ end
113
+ end
114
+
115
+ def bugger!
116
+ raise NotAMember unless member?
117
+ raise IG3Error, "already a debugger" if debugger?
118
+
119
+ membership.status = "debugger"
120
+
121
+ # interne
122
+ self.interne = i = Interne.new
123
+ i.username = username
124
+ i.saldo = 0
125
+ i.afgesloten = false
126
+
127
+ transaction do
128
+ # centjes overzetten
129
+ if print_user.saldo > 0
130
+ i.deposit("printaccount", print_user.saldo, "printkrediet")
131
+ # XXX print krediet?
132
+ # print_user.saldo = 0
133
+ end
134
+
135
+ membership.save!
136
+ i.save!
137
+ end
138
+ end
139
+
140
+ end
141
+
142
+
143
+ end
data/lib/printing.rb ADDED
@@ -0,0 +1,238 @@
1
+ module Ig3tool
2
+
3
+ # The printing section of ig3tool
4
+ #
5
+ # Classes & methods:
6
+ #
7
+ # PrintUser
8
+ # ---------
9
+ # lookup(username)
10
+ # looks for a printuser by username as well as alias
11
+ # use this method to look usernames up
12
+ #
13
+ # add_credit(amount)
14
+ # adds amount of credit to a user' saldo
15
+ #
16
+ # refund(amount, printid, msg)
17
+ # refunds a failed job
18
+ # should ONLY be called from PrintTransaction
19
+ #
20
+ # remove(username)
21
+ # removes a printuser along its aliasses
22
+ #
23
+ # print(job, pages, copies, host, amount, queue, message)
24
+ # handles the printing of a job
25
+ # should ONLY be used by the printscript
26
+ #
27
+ # err(queue, message)
28
+ # logs an error
29
+ # again printscript ONLY
30
+ #
31
+ #
32
+ #
33
+ # PrintAlias
34
+ # ----------
35
+ # no special functions
36
+ #
37
+ #
38
+ #
39
+ # PrintTransaction
40
+ # ----------------
41
+ # refund()
42
+ # refunds a specific job, calls aprintuser.refund()
43
+ #
44
+ #
45
+ #
46
+
47
+
48
+
49
+
50
+ # Implements a printuser.
51
+ class PrintUser < ActiveRecord::Base
52
+
53
+ set_table_name "print_users"
54
+ set_nonauto_primary_key :username
55
+ validates_uniqueness_of :username
56
+
57
+ # _username_ and _saldo_ must be provided
58
+ # a PrintUser must be linked with an existing _person_
59
+ validates_presence_of :username, :saldo, :person
60
+ belongs_to :person, :class_name => "Person", :foreign_key => "username"
61
+ has_many :print_transactions, :class_name => "PrintTransaction", :foreign_key => "username"
62
+ has_many :print_aliases, :class_name => "PrintAlias", :foreign_key => "username", :dependent => :destroy
63
+ attr_accessible :username
64
+ validates_associated :person
65
+
66
+ # override because of non-standard primary key
67
+ def username=(newusername)
68
+ write_attribute(:username, newusername)
69
+ save!
70
+ end
71
+
72
+ def self.lookup(username)
73
+ user = nil
74
+ begin
75
+ user = PrintUser.find(username) # Error if not found
76
+ rescue
77
+ begin
78
+ user = PrintAlias.find(username).print_user
79
+ rescue
80
+ raise NotFound, "the ig3tool imps found no such user..."
81
+ end
82
+ end
83
+ user
84
+ end
85
+
86
+ def self.errortest
87
+ raise NotFound
88
+ end
89
+
90
+ def remove_aliases
91
+ print_aliases.each {|pa| pa.destroy }
92
+ end
93
+
94
+ def self.remove(username)
95
+ user = PrintUser.lookup(username)
96
+ user.destroy
97
+ end
98
+
99
+ def email
100
+ self.person.email
101
+ end
102
+
103
+ def debugger?
104
+ self.person.debugger?
105
+ end
106
+
107
+ def add_credit (amount)
108
+ if self.debugger?
109
+ raise PermissionDenied, "debuggers cannot add credits to their account..."
110
+ else
111
+ PrintUser.transaction do
112
+ reload()
113
+ PrintTransaction.new do |pt|
114
+ pt.time = Time.now()
115
+ pt.username = username
116
+ pt.refunded = 0
117
+ pt.amount = amount.to_i
118
+ pt.queue = "ig3tool"
119
+ pt.message = "added #{amount} eurocents to #{username}'s account."
120
+ pt.category = "add"
121
+ pt.save!
122
+ end
123
+ self.saldo += amount.to_i
124
+ save!
125
+ end
126
+ end
127
+ end
128
+
129
+ def refund(amount, printid, undo, msg)
130
+ PrintUser.transaction do
131
+ reload()
132
+ pt = PrintTransaction.new
133
+ pt.time = Time.now()
134
+ pt.username = username
135
+ pt.refunded = 0
136
+ pt.queue = "ig3tool"
137
+ pt.amount = amount.to_i
138
+ pt.message = "#{"undo " if undo}refunded print #{printid} of #{amount} euro to #{username}."
139
+ pt.category = "refund"
140
+ pt.save!
141
+ if debugger?
142
+ person.interne.refundprint(amount, "#{"undo " if undo }refund print, id: #{printid}", undo)
143
+ else
144
+ if undo
145
+ self.saldo += amount
146
+ else
147
+ self.saldo -= amount
148
+ end
149
+ save!
150
+ end
151
+ end
152
+ end
153
+
154
+ def print(job, pages, copies, host, amount, queue, message)
155
+ PrintUser.transaction do
156
+ reload()
157
+ PrintTransaction.new do |pt|
158
+ pt.time = Time.now()
159
+ pt.username = username
160
+ pt.refunded = 0
161
+ pt.amount = amount.to_i
162
+ pt.pages = pages.to_i
163
+ pt.copies = copies.to_i
164
+ pt.host = host
165
+ pt.queue = queue
166
+ pt.job = job
167
+ pt.message = "Printed #{job} of #{pages} pages for #{amount} EUR - #{message}"
168
+ pt.category = "print"
169
+ pt.save!
170
+ end
171
+ if debugger?
172
+ person.interne.print(amount, "job: #{job}")
173
+ else
174
+ if self.saldo < amount.to_i
175
+ raise NotEnoughCredit, "you are broke!"
176
+ else
177
+ self.saldo -= amount.to_i
178
+ save!
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+
185
+ def err(message, queue)
186
+ PrintTransaction.new do |pt|
187
+ pt.time = Time.now()
188
+ pt.username = username
189
+ pt.queue = queue
190
+ pt.category = "error"
191
+ pt.save!
192
+ end
193
+ end
194
+
195
+ end
196
+
197
+
198
+ class PrintAlias < ActiveRecord::Base
199
+
200
+ set_table_name "print_aliases"
201
+ set_primary_key :alias
202
+ validates_uniqueness_of :alias
203
+ validates_presence_of :alias, :username, :print_user
204
+ belongs_to :print_user, :class_name => "PrintUser", :foreign_key => "username"
205
+ validates_associated :print_user
206
+
207
+ def alias=(newalias)
208
+ @attributes["alias"] = newalias
209
+ end
210
+
211
+ end
212
+
213
+
214
+ class PrintTransaction < ActiveRecord::Base
215
+
216
+ set_table_name "print_transactions"
217
+ validates_presence_of :time, :username, :category, :queue
218
+ validates_inclusion_of :category, :in => ["error", "add", "print", "refund", "debug"]
219
+ belongs_to :printuser, :class_name => "PrintUser", :foreign_key => "username"
220
+ attr_protected :refunded
221
+
222
+ def refund
223
+ PrintTransaction.transaction do
224
+ reload()
225
+ if category == "print" then
226
+ printuser.refund(amount, id, !refunded.to_b, message)
227
+ toggle!(:refunded)
228
+ else
229
+ raise WrongPrintlogType
230
+ end
231
+ end
232
+ end
233
+
234
+ end # class PrintTransaction
235
+
236
+
237
+
238
+ end # module Ig3tool