1 from zope.interface import implements
2 from twisted.internet import reactor
3 from twisted.internet import defer
4 from webut.skin import iskin
5 from ldaptor.protocols import pureldap
6 from ldaptor.protocols.ldap import ldapsyntax, distinguishedname
7 from ldaptor import generate_password, interfaces
8 from ldaptor.apps.webui.uriquote import uriUnquote
9 from ldaptor import weave
10 from ldaptor.apps.webui.i18n import _
11 from ldaptor.apps.webui import i18n
12
13 import os
14 from nevow import rend, inevow, loaders, url, tags
15 from formless import annotate, webform, iformless, configurable
16
17 -def getEntry(ctx, dn):
18 user = ctx.locate(inevow.ISession).getLoggedInRoot().loggedIn
19 e=ldapsyntax.LDAPEntry(client=user.client, dn=dn)
20 return e
21
22 -def getEntryWithAttributes(ctx, dn, *attributes):
23 e = getEntry(ctx, dn)
24 d = e.fetch(*attributes)
25 return d
26
28 d = getEntryWithAttributes(ctx, dn, 'cn')
29 def _cb(e):
30 for cn in e.get('cn', []):
31 return cn
32 raise RuntimeError, \
33 _("Service password entry has no attribute cn: %r") % e
34 d.addCallback(_cb)
35 return d
36
37
39 if newPassword != again:
40 raise annotate.ValidateError(
41 {},
42 formErrorMessage=_('Passwords do not match.'))
43
48
51
53 return annotate.MethodBinding(
54 'remove',
55 annotate.Method(arguments=[
56 annotate.Argument('ctx', annotate.Context()),
57 ],
58 label=_('Remove')),
59 action=_('Remove'))
60
69 d.addCallback(_delete, e)
70
71 def _report(name):
72 return _('Removed service %r') % name
73 d.addCallback(_report)
74
75 return d
76
81
83 return ['setServicePassword']
84
86 return annotate.MethodBinding(
87 'setServicePassword',
88 annotate.Method(arguments=[
89 annotate.Argument('ctx', annotate.Context()),
90 annotate.Argument('newPassword', annotate.PasswordEntry(required=True,
91 label=_('New password'))),
92 annotate.Argument('again', annotate.PasswordEntry(required=True,
93 label=_('Again'))),
94 ],
95 label=_('Set password')),
96 action=_('Set password'))
97
100
102 d = defer.maybeDeferred(self._isPasswordAcceptable, ctx, newPassword, again)
103 def _setPassword(ctx, dn, newPassword):
104 e = getEntry(ctx, dn)
105 d=defer.maybeDeferred(e.setPassword, newPasswd=newPassword)
106 return d
107 d.addCallback(lambda _: _setPassword(ctx, self.dn, newPassword))
108
109 def _getName(_, ctx):
110 d = getServiceName(ctx, self.dn)
111 return d
112 d.addCallback(_getName, ctx)
113
114 def _report(name):
115 return _('Set password for service %r') % name
116 d.addCallback(_report)
117
118 return d
119
124
126 return ['generateRandom']
127
129 return annotate.MethodBinding(
130 'generateRandom',
131 annotate.Method(arguments=[
132 annotate.Argument('ctx', annotate.Context()),
133 ],
134 label=_('Generate random')),
135 action=_('Generate random'))
136
142 d.addCallback(_first)
143
144 def _setPass(newPassword, ctx):
145 e = getEntry(ctx, self.dn)
146 d = e.setPassword(newPassword)
147
148 def _getName(_, ctx):
149 d = getServiceName(ctx, self.dn)
150 return d
151 d.addCallback(_getName, ctx)
152
153 def _report(name, newPassword):
154 return _('Service %r password set to %s') % (name, newPassword)
155 d.addCallback(_report, newPassword)
156
157 return d
158
159 d.addCallback(_setPass, ctx)
160 return d
161
166
169
171 return annotate.MethodBinding(
172 'add',
173 annotate.Method(arguments=[
174 annotate.Argument('ctx', annotate.Context()),
175 annotate.Argument('serviceName', annotate.String(required=True,
176 label=_('Service name'))),
177 annotate.Argument('newPassword', annotate.PasswordEntry(required=False,
178 label=_('New password'),
179 description=_("Leave empty to generate random password."))),
180 annotate.Argument('again', annotate.PasswordEntry(required=False,
181 label=_('Again'))),
182 ],
183 label=_('Add')),
184 action=_('Add'))
185
186 - def add(self, ctx, serviceName, newPassword, again):
187 if newPassword or again:
188 checkPasswordTypos(newPassword, again)
189
190 if not newPassword:
191 return self._generate(ctx, serviceName)
192 else:
193 return self._add(ctx, newPassword, serviceName)
194 return d
195
197 e = getEntry(ctx, self.dn)
198 rdn = distinguishedname.RelativeDistinguishedName(
199 attributeTypesAndValues=[
200 distinguishedname.LDAPAttributeTypeAndValue(
201 attributeType='cn', value=serviceName),
202 distinguishedname.LDAPAttributeTypeAndValue(
203 attributeType='owner', value=str(self.dn))
204 ])
205 d = e.addChild(rdn, {
206 'objectClass': ['serviceSecurityObject'],
207 'cn': [serviceName],
208 'owner': [str(self.dn)],
209 'userPassword': ['{crypt}!'],
210 })
211 def _setPass(e, newPassword):
212 d = e.setPassword(newPassword)
213 return d
214 d.addCallback(_setPass, newPassword)
215 return d
216
222 d.addCallback(_first)
223
224 def _cb(newPassword, serviceName):
225 d = self._cbSetPassword(ctx, newPassword, serviceName)
226 d.addCallback(lambda dummy: _('Added service %r with password %s') % (serviceName, newPassword))
227 return d
228 d.addCallback(_cb, serviceName)
229
230 return d
231
232 - def _add(self, ctx, newPassword, serviceName):
233 d = self._cbSetPassword(ctx, newPassword, serviceName)
234 def _report(dummy, name):
235 return _('Added service %r') % name
236 d.addCallback(_report, serviceName)
237
238 return d
239
240
245
247 l = [(int(pri), name)
248 for x, pri, name in [name.split('_', 2) for name in dir(self)
249 if name.startswith('servicePasswordAction_')]]
250 l.sort()
251 for pri, name in l:
252 yield name
253
255 for attrName in dir(self):
256 if not attrName.startswith('servicePasswordAction_'):
257 continue
258
259 x, pri, actionName = attrName.split('_', 2)
260
261 if actionName == name:
262 return getattr(self, attrName)
263 return None
264
266 docFactory = loaders.xmlfile(
267 'change_service_passwords.xhtml',
268 templateDir=os.path.split(os.path.abspath(__file__))[0])
269 r = inevow.IQ(docFactory).onePattern('main')
270 return r
271
273 if data:
274 return ctx.tag
275 else:
276 return tags.invisible()
277
292
299
318
319
320 render_zebra = weave.zebra()
321
322 render_i18n = i18n.render()
323
324
326 implements(iskin.ISkinnable)
327
328 title = _('Ldaptor Password Change Page')
329
330 addSlash = True
331
332 docFactory = loaders.xmlfile(
333 'change_password.xhtml',
334 templateDir=os.path.split(os.path.abspath(__file__))[0])
335
337 return ['setPassword', 'generateRandom']
338
340 return annotate.MethodBinding(
341 'setPassword',
342 annotate.Method(arguments=[
343 annotate.Argument('ctx', annotate.Context()),
344 annotate.Argument('newPassword', annotate.PasswordEntry(required=True,
345 label=_('New password'))),
346 annotate.Argument('again', annotate.PasswordEntry(required=True,
347 label=_('Again'))),
348 ],
349 label=_('Set password')),
350 action=_('Set password'))
351
353 return annotate.MethodBinding(
354 'generateRandom',
355 annotate.Method(arguments=[
356 annotate.Argument('ctx', annotate.Context()),
357 ],
358 label=_('Generate random')),
359 action=_('Generate random'))
360
361 servicePasswordAction_10_remove = RemoveServicePassword
362 servicePasswordAction_20_set = SetServicePassword
363 servicePasswordAction_30_random = SetRandomServicePassword
364
369
371 d = defer.maybeDeferred(checkPasswordTypos, newPassword, again)
372 d.addCallback(lambda dummy: self._setPassword(ctx, newPassword))
373 d.addCallback(lambda dummy: _('Password set.'))
374 def eb(fail):
375 return _("Failed: %s") % fail.getErrorMessage()
376 d.addErrback(eb)
377 return d
378
384 d.addCallback(_first)
385
386 def _status(newPassword, ctx):
387 d = self._setPassword(ctx, newPassword)
388 d.addCallback(lambda dummy: _('Password set to %s') % newPassword)
389 return d
390 d.addCallback(_status, ctx)
391 def eb(fail):
392 return _("Failed: %s") % fail.getErrorMessage()
393 d.addErrback(eb)
394 return d
395
397 try:
398 return ctx.locate(inevow.IStatusMessage)
399 except KeyError:
400 return ''
401
404
407
410
412 u=url.URL.fromContext(ctx)
413 u=u.parentdir().parentdir().clear()
414 l=[]
415 l.append(tags.a(href=u.sibling("search"))[_("Search")])
416 l.append(tags.a(href=u.sibling("add"))[_("add new entry")])
417 l.append(tags.a(href=u.sibling("edit").child(str(self.dn)))[_("edit")])
418 l.append(tags.a(href=u.sibling("delete").child(str(self.dn)))[_("delete")])
419 return l
420
422 return webform.renderForms('add')
423
426
427 render_i18n = i18n.render()
428
431
433 addSlash = True
434
436 entry = inevow.ISession(ctx).getLoggedInRoot().loggedIn
437 u = inevow.IRequest(ctx).URLPath()
438 return u.child(str(entry.dn))
439
449
452