class IssueKeyForm(BaseForm): label = _(u'Issue Service Key') description = _(u'Issue a key to be used for authentication ' u'by a service application') fields = Fields(IKeyMetadataSchema).select('title', 'ip_range') download_key_template = ViewPageTemplateFile('download_key.pt') @button.buttonAndHandler(_(u'Issue key'), name='save') def handleApply(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return user_id = api.user.get_current().id private_key, service_key = self.get_plugin().issue_keypair( user_id, data['title'], data['ip_range']) self._key_issued = True self._generated_private_key = private_key self._generated_service_key = service_key msg = _('Key created: ${key_id}', mapping={'key_id': service_key['key_id']}) api.portal.show_message(msg, getRequest()) @button.buttonAndHandler(_(u'Cancel'), name='cancel') def handleCancel(self, action): api.portal.show_message(_(u'Key creation cancelled.'), getRequest()) return self.request.RESPONSE.redirect(self.main_url) def render(self): if getattr(self, '_key_issued', False) is True: # We carry over the newly issued key in these attributes on the # view to offer the private key for download exactly once. private_key = self._generated_private_key service_key = self._generated_service_key del self._generated_private_key json_keyfile = create_json_keyfile(private_key, service_key) template_vars = { 'key_id': service_key['key_id'], 'title': service_key['title'], 'json_keyfile': json_keyfile, } return self.download_key_template(**template_vars) return super(IssueKeyForm, self).render()
def revoke_selected_keys(self): user_id = api.user.get_current().id selected_keys = self.request.form.get('selected_keys', []) storage = CredentialStorage(self.plugin) for key_id in selected_keys: storage.revoke_service_key(user_id, key_id) api.portal.show_message(_('Keys revoked.'), getRequest()) return self.request.RESPONSE.redirect(self.main_url)
def valid_ip_range(value): """Form validator that checks for a valid IP range specification. """ try: parse_ip_range(value) except InvalidIPRangeSpecification as exc: raise Invalid( _('Invalid IP range: ${ip_range_error}', mapping={'ip_range_error': str(exc)})) return True
class IKeyMetadataSchema(model.Schema): """ """ title = schema.TextLine(title=_(u'label_title', default=u'Title'), ) key_id = schema.TextLine( title=_(u'label_key_id', default=u'Key ID'), readonly=True, ) user_id = schema.TextLine( title=_(u'label_user_id', default=u'User ID'), readonly=True, ) issued = schema.Datetime( title=_(u'label_issued', default=u'Issued'), readonly=True, ) ip_range = schema.TextLine( title=_(u'label_ip_range', default=u'IP Range'), required=False, constraint=valid_ip_range, description= _(u'Allowed IP range specification in ' u'<strong><a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_notation">' # noqa u'CIDR notation</a></strong>. ' u'Multiple comma-separated addresses / networks may be supplied.'), )
def handleApply(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return user_id = api.user.get_current().id private_key, service_key = self.get_plugin().issue_keypair( user_id, data['title'], data['ip_range']) self._key_issued = True self._generated_private_key = private_key self._generated_service_key = service_key msg = _('Key created: ${key_id}', mapping={'key_id': service_key['key_id']}) api.portal.show_message(msg, getRequest())
def handleCancel(self, action): api.portal.show_message(_('Edit cancelled'), getRequest()) return self.request.RESPONSE.redirect(self.main_url)
class EditKeyForm(BaseForm): label = _(u'Edit Service Key') successMessage = Z3CFormMF('Data successfully updated.') noChangesMessage = Z3CFormMF('No changes were applied.') fields = Fields(IKeyMetadataSchema) def updateWidgets(self, *args, **kwargs): super(EditKeyForm, self).updateWidgets(*args, **kwargs) saving = 'form.buttons.save' in self.request # Prefill form widgets with persisted values from DB key = self.get_key() for widget in self.widgets.values(): # Always prefill readonly widgets. # # Prefill other widgets only upon initial rendering of the form, # not when trying to save - this is so we don't override # actual user provided inputs with persisted values from the # DB when rendering the form in the case of validation errors. if widget.field.readonly or not saving: name = widget.field.getName() value = key[name] converter = IDataConverter(widget) widget.value = converter.toWidgetValue(value) def get_key(self): key_id = self.request.form['key_id'] storage = CredentialStorage(self.get_plugin()) key = storage.get_service_key(key_id) return key def action(self): """Redefine <form action=''> attribute. """ return self.request.getURL() + '?key_id=%s' % self.request['key_id'] def field_value_has_changed(self, field, new_value, key): name = field.getName() old_value = key[name] return old_value != new_value def applyChanges(self, data): # Based on z3c.form.form.applyChanges, but without firing events key = self.get_key() changes = {} for name, field in self.fields.items(): # If the field is not in the data, then go on to the next one try: new_value = data[name] except KeyError: continue # If the value is NOT_CHANGED, ignore it, since the # widget/converter sent a strong message not to do so. if new_value is NOT_CHANGED: continue if self.field_value_has_changed(field.field, new_value, key): # Only update the data if it changed # TODO: Should we possibly be using toFieldValue here? key[name] = new_value # Record the change using information required later changes.setdefault(field.interface, []).append(name) return changes @button.buttonAndHandler(_(u'Save'), name='save') def handleApply(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return changes = self.applyChanges(data) if changes: api.portal.show_message(self.successMessage, getRequest()) else: api.portal.show_message(self.noChangesMessage, getRequest()) return self.request.RESPONSE.redirect(self.main_url) @button.buttonAndHandler(_(u'Cancel'), name='cancel') def handleCancel(self, action): api.portal.show_message(_('Edit cancelled'), getRequest()) return self.request.RESPONSE.redirect(self.main_url)