Exemplo n.º 1
0
 def add_document(self, data, properties, request=None):
     """Add new document"""
     if request is None:
         request = check_request()
     registry = request.registry
     # check required properties
     properties = properties.copy()
     title = properties.get('title')
     application_name = properties.get('application_name')
     if (not title) or (not application_name) or (data is None):
         raise HTTPBadRequest("Missing arguments")
     owner = properties.get('owner')
     if owner and not request.has_permission(
             CREATE_DOCUMENT_WITH_OWNER_PERMISSION, context=self):
         raise HTTPForbidden()
     if not owner:
         properties['owner'] = request.principal.id
     properties['creator'] = request.principal.id
     # check storage folders
     folder = self._get_folder(datetime.utcnow())
     # create document and first version
     document, version = self._create_document(registry, folder)
     # update document data and properties
     version.update(data, properties)
     # store document
     document.get_oid()
     folder[document.oid] = document
     registry.notify(ObjectAddedEvent(version, folder, document.oid))
     # return
     return version
Exemplo n.º 2
0
 def resize(self, width, height, keep_ratio=True):
     """Resize image to given dimensions"""
     with self as blob:
         try:
             image = Image.open(blob)
             image_size = image.size
             if width >= image_size[0] and height >= image_size[1]:
                 return
             new_image = BytesIO()
             w_ratio = 1. * width / image_size[0]
             h_ratio = 1. * height / image_size[1]
             if keep_ratio:
                 ratio = min(w_ratio, h_ratio)
                 image.resize((round(ratio * image_size[0]), round(ratio * image_size[1])),
                              Image.ANTIALIAS) \
                      .save(new_image, image.format, quality=99)
             else:
                 image.resize((round(w_ratio * image_size[0]), round(h_ratio * image_size[1])),
                              Image.ANTIALIAS) \
                      .save(new_image, image.format, quality=99)
             self.data = new_image
             request = check_request()
             request.registry.notify(FileModifiedEvent(self))
         finally:
             blob.close()
Exemplo n.º 3
0
 def __init__(self, context):
     request = check_request()
     terms = []
     versions = IWorkflowVersions(context.__parent__, None)
     if versions is not None:
         # check for first version
         first_version_label = request.localizer.translate(
             VERSION_DISPLAY[DISPLAY_FIRST_VERSION])
         try:
             first_version = versions.get_version(1)  # pylint: disable=assignment-from-no-return
         except VersionError:
             pass
         else:
             info = IWorkflowPublicationInfo(first_version, None)
             if info is not None and info.publication_effective_date:
                 first_version_label = '{1} (= {0})'.format(
                     first_version_label.lower(),
                     format_date(info.publication_effective_date,
                                 format_string=SH_DATE_FORMAT))
         terms.append(
             SimpleTerm(DISPLAY_FIRST_VERSION, title=first_version_label))
     # check for current version
     current_version_label = request.localizer.translate(
         VERSION_DISPLAY[DISPLAY_CURRENT_VERSION])
     info = IWorkflowPublicationInfo(context, None)
     if info is not None and info.publication_effective_date:
         current_version_label = '{1} (= {0})'.format(
             current_version_label.lower(),
             format_date(info.publication_effective_date,
                         format_string=SH_DATE_FORMAT))
     terms.append(
         SimpleTerm(DISPLAY_CURRENT_VERSION, title=current_version_label))
     super().__init__(terms)
Exemplo n.º 4
0
def notify_user_activation(user, request=None):
    """Send mail for user activation"""
    security = query_utility(ISecurityManager)
    settings = INotificationSettings(security)
    if not settings.enable_notifications:  # pylint: disable=assignment-from-no-return
        LOGGER.info("Security notifications disabled, no message sent...")
        return
    mailer = settings.get_mailer()  # pylint: disable=assignment-from-no-return
    if mailer is None:
        LOGGER.warning("Can't find mailer utility, no notification message sent!")
        return
    if request is None:
        request = check_request()
    translate = request.localizer.translate
    i18n_settings = II18n(settings)
    message_text, template_name = None, None
    if user.self_registered:
        # pylint: disable=assignment-from-no-return
        message_text = i18n_settings.query_attribute('registration_template', request=request)
        if not message_text:
            template_name = 'templates/register-message.pt'
    elif user.wait_confirmation:
        # pylint: disable=assignment-from-no-return
        message_text = i18n_settings.query_attribute('confirmation_template', request=request)
        if not message_text:
            template_name = 'templates/register-info.pt'
    site = get_parent(request.context, ISite)
    if message_text is not None:
        message_text = message_text.format(**user.to_dict())
    elif template_name is not None:
        message_text = render(template_name, request=request, value={
            'user': user,
            'site': site,
            'settings': settings
        })
    html_body = render('templates/register-body.pt', request=request, value={
        'user': user,
        'site': site,
        'settings': settings,
        'message': message_text
    })
    message = Message(
        subject=translate(_("{prefix}Please confirm registration")).format(
            prefix="{prefix} ".format(prefix=settings.subject_prefix)
            if settings.subject_prefix else ''),
        sender='{name} <{email}>'.format(name=settings.sender_name,
                                         email=settings.sender_email),
        recipients=("{firstname} {lastname} <{email}>".format(firstname=user.firstname,
                                                              lastname=user.lastname,
                                                              email=user.email),),
        html=Attachment(data=html_body,
                        content_type='text/html; charset=utf-8',
                        disposition='inline',
                        transfer_encoding='quoted-printable'),
        body=Attachment(data=html_to_text(html_body),
                        content_type='text/plain; charset=utf-8',
                        disposition='inline',
                        transfer_encoding='quoted-printable'))
    mailer.send(message)
Exemplo n.º 5
0
 def permission(self):
     """Object permission getter"""
     request = getattr(self, 'request', None) or check_request()
     context = ISecurityContext(self, None)
     if context is None:
         context = getattr(self, 'context', request.context)
     view = getattr(self, 'view', None) or getattr(self, 'table', None)
     return get_edit_permission(request, context, view, self.action_type)
Exemplo n.º 6
0
def get_layer_skin(layer):
    """Get skin matching given layer"""
    request = check_request()
    registry = request.registry
    for name, util in registry.getUtilitiesFor(ISkin):  # pylint: disable=unused-variable
        if util.layer is layer:
            return util
    return None
Exemplo n.º 7
0
def public_profile_factory(context):  # pylint: disable=unused-argument
    """Generic public profile factory

    Applied on any context, this adapter returns public profile associated
    with the current request principal.
    """
    request = check_request()
    return IPublicProfile(request.principal)
Exemplo n.º 8
0
def get_age(value, request=None):
    """Get 'human' age of a given datetime (including timezone) compared to current datetime
    (in UTC)

    :param datetime value: input datetime to be compared with current datetime
    :return: str; the delta value, converted to months, weeks, days, hours or minutes

    >>> from datetime import datetime, timedelta
    >>> from pyams_utils.date import get_age
    >>> now = datetime.utcnow()
    >>> get_age(now)
    'less than 5 minutes ago'
    >>> get_age(now - timedelta(minutes=10))
    '10 minutes ago'
    >>> get_age(now - timedelta(hours=2))
    '2 hours ago'
    >>> get_age(now - timedelta(days=1))
    'yesterday'
    >>> get_age(now - timedelta(days=2))
    'the day before yesterday'
    >>> get_age(now - timedelta(days=4))
    '4 days ago'
    >>> get_age(now - timedelta(weeks=2))
    '2 weeks ago'
    >>> get_age(now - timedelta(days=80))
    '3 months ago'
    >>> get_age(None)
    '--'
    """
    if not value:
        return '--'
    if request is None:
        request = check_request()
    translate = request.localizer.translate
    now = gmtime(datetime.utcnow())
    delta = now - gmtime(value)
    if delta.days > 60:
        result = translate(_("%d months ago")) % int(
            round(delta.days * 1.0 / 30))
    elif delta.days > 10:
        result = translate(_("%d weeks ago")) % int(round(
            delta.days * 1.0 / 7))
    elif delta.days > 2:
        result = translate(_("%d days ago")) % delta.days
    elif delta.days == 2:
        result = translate(_("the day before yesterday"))
    elif delta.days == 1:
        result = translate(_("yesterday"))
    else:  # less than one day
        hours = int(round(delta.seconds * 1.0 / 3600))
        if hours > 1:
            result = translate(_("%d hours ago")) % hours
        elif delta.seconds > 300:
            result = translate(_("%d minutes ago")) % int(
                round(delta.seconds * 1.0 / 60))
        else:
            result = translate(_("less than 5 minutes ago"))
    return result
Exemplo n.º 9
0
 def update_document(self,
                     oid,
                     version=None,
                     data=None,
                     properties=None,
                     request=None,
                     check_permission=True):
     # pylint: disable=too-many-arguments
     """Update document data or properties"""
     if not oid:
         return None
     document = self.get_document(oid, version)
     if document is None:
         raise HTTPNotFound()
     if request is None:
         request = check_request()
     if check_permission and \
             not request.has_permission(MANAGE_DOCUMENT_PERMISSION, context=document):
         raise HTTPForbidden()
     if properties is None:
         properties = {}
     if data is not None:
         document_hash = get_hash(data)
         if document_hash == document.hash:
             # unmodified file content
             data = None
             _filename = properties.pop('filename', None)
         else:
             # modified file content, check state and create new version if required
             if request is None:
                 request = check_request()
             state = IWorkflowState(document)
             if state.state != DRAFT_STATE:
                 translate = request.localizer.translate
                 workflow_info = IWorkflowInfo(document)
                 document = workflow_info.fire_transition_toward(  # pylint: disable=assignment-from-no-return
                     DRAFT_STATE,
                     comment=translate(_("Document content update")),
                     request=request)
                 request.response.status = HTTPCreated.code
     state = document.update(data, properties)
     request.registry.notify(ObjectModifiedEvent(document))
     if state.state == DELETED_STATE:
         return None
     return document
Exemplo n.º 10
0
 def __init__(self, context=None, **kw):
     # pylint: disable=super-init-not-called,unused-argument
     request = check_request()
     registry = request.registry
     translate = request.localizer.translate
     utils = [(name, translate(util.label))
              for (name, util) in registry.getUtilitiesFor(self.interface)]
     self._terms = dict(
         (title, UtilityTerm(name, title)) for name, title in utils)
Exemplo n.º 11
0
 def fire_transition(self,
                     transition_id,
                     comment=None,
                     side_effect=None,
                     check_security=True,
                     principal=None,
                     request=None):
     # pylint: disable=too-many-arguments
     """Fire transition with given ID"""
     versions = IWorkflowVersions(self.parent)
     state = IWorkflowState(self.context)
     if request is None:
         request = check_request()
     # this raises InvalidTransitionError if id is invalid for current state
     transition = self.wf.get_transition(state.state, transition_id)
     # check whether we may execute this workflow transition
     if check_security and transition.permission:
         if not request.has_permission(transition.permission,
                                       context=self.context):
             raise HTTPUnauthorized()
     # now make sure transition can still work in this context
     if not transition.condition(self, self.context):
         raise ConditionFailedError()
     # perform action, return any result as new version
     if principal is None:
         principal = request.principal
     result = transition.action(self, self.context)
     if result is not None:
         # stamp it with version
         versions.add_version(result, transition.destination, principal)
         # execute any side effect:
         if side_effect is not None:
             side_effect(result)
         event = WorkflowVersionTransitionEvent(result, self.wf, principal,
                                                self.context,
                                                transition.source,
                                                transition.destination,
                                                transition, comment)
     else:
         versions.set_state(state.version_id, transition.destination,
                            principal)
         # execute any side effect
         if side_effect is not None:
             side_effect(self.context)
         event = WorkflowTransitionEvent(self.context, self.wf, principal,
                                         transition.source,
                                         transition.destination, transition,
                                         comment)
     # change state of context or new object
     registry = request.registry
     registry.notify(event)
     # send modified event for original or new object
     if result is None:
         registry.notify(ObjectModifiedEvent(self.context))
     else:
         registry.notify(ObjectModifiedEvent(result))
     return result
Exemplo n.º 12
0
 def __init__(self, context=None):  # pylint: disable=unused-argument
     request = check_request()
     translate = request.localizer.translate
     terms = sorted([
         SimpleTerm(v, title=translate(t))
         for v, t in ISO_LANGUAGES.items()
     ],
                    key=lambda x: x.title)
     super(ISOLanguagesVocabulary, self).__init__(terms)
Exemplo n.º 13
0
 def __init__(self, context=None):  # pylint: disable=unused-argument
     request = check_request()
     registry = request.registry
     translate = request.localizer.translate
     terms = []
     append = terms.append
     for name, adapter in registry.getAdapters(('', request), IHTMLRenderer):
         if hasattr(adapter, 'label'):
             append(SimpleTerm(name, title=translate(adapter.label)))
     super().__init__(terms)
Exemplo n.º 14
0
 def __init__(self, *args, **kwargs):  # pylint: disable=unused-argument
     request = check_request()
     registry = request.registry
     translate = request.localizer.translate
     terms = [
         SimpleTerm(p.id, title=translate(p.title))
         for n, p in registry.getUtilitiesFor(self.interface)
     ]
     terms.sort(key=lambda x: x.title)
     super().__init__(terms)
Exemplo n.º 15
0
 def publication(self):
     """Publication label used to display workflow publication state"""
     request = check_request()
     translate = request.localizer.translate
     sm = get_utility(ISecurityManager)  # pylint: disable=invalid-name
     return translate(_('{date} by {principal}')).format(
         date=format_datetime(tztime(
             IWorkflowPublicationInfo(self).publication_date),
                              request=request),
         principal=translate(sm.get_principal(self.publisher).title))
Exemplo n.º 16
0
def get_label(item, request=None):
    """Get sort label of a given viewlet"""
    _, viewlet = item
    try:
        label = getattr(viewlet, 'label', None)
        if not label:
            return '--'
        if request is None:
            request = check_request()
        return request.localizer.translate(label)
    except AttributeError:
        return '--'
Exemplo n.º 17
0
 def __init__(self, context=None):  # pylint: disable=unused-argument
     terms = []
     negotiator = query_utility(INegotiator)
     if negotiator is not None:
         translate = check_request().localizer.translate
         for lang in negotiator.offered_languages:
             terms.append(
                 SimpleTerm(lang,
                            title=translate(
                                BASE_LANGUAGES.get(lang)
                                or _("<unknown>"))))
     super(I18nOfferedLanguages, self).__init__(terms)
Exemplo n.º 18
0
 def crop(self, x1, y1, x2, y2):  # pylint: disable=invalid-name
     """Crop image to given coordinates"""
     with self as blob:
         try:
             image = Image.open(blob)
             new_image = BytesIO()
             image.crop((x1, y1, x2, y2)) \
                  .save(new_image, image.format, quelity=99)
             self.data = new_image
             request = check_request()
             request.registry.notify(FileModifiedEvent(self))
         finally:
             blob.close()
Exemplo n.º 19
0
 def rotate(self, angle=-90):
     """Rotate image of given angle, in clockwise degrees"""
     with self as blob:
         try:
             image = Image.open(blob)
             new_image = BytesIO()
             image.rotate(angle, expand=True) \
                  .save(new_image, image.format, quality=99)
             self.data = new_image
             request = check_request()
             request.registry.notify(FileModifiedEvent(self))
         finally:
             blob.close()
Exemplo n.º 20
0
 def wrapper(obj, app, key, *args, **kwargs):
     request = check_request()
     if callable(key):
         key = key(obj, *args, **kwargs)
     if not key:
         key = '{1}::{0!r}'.format(obj, prefix or func.__name__)
     data = get_session_data(request, app, key, _MARKER)
     if data is _MARKER:
         data = func
         if callable(data):
             data = data(obj, *args, **kwargs)
         set_session_data(request, app, key, data)
     return data
Exemplo n.º 21
0
 def get_manual_transition_ids(self, check_security=True):
     """Getter for available transitions IDs"""
     if check_security:
         request = check_request()
         permission_checker = request.has_permission
     else:
         permission_checker = granted_permission
     return [
         transition.transition_id for transition in sorted(
             self._get_transitions(MANUAL_TRANSITION),
             key=lambda x: x.user_data.get('order', 999))
         if transition.condition(self, self.context)
         and permission_checker(transition.permission, context=self.context)
     ]
Exemplo n.º 22
0
 def delete_document(self, oid, request=None):
     """Delete document or version"""
     if not oid:
         return None
     document = self.get_document(oid)
     if document is None:
         raise HTTPNotFound()
     if request is None:
         request = check_request()
     if not request.has_permission(MANAGE_DOCUMENT_PERMISSION,
                                   context=document):
         raise HTTPForbidden()
     folder = get_parent(document, IDocumentFolder)
     del folder[document.oid]
     return document
Exemplo n.º 23
0
def publish_action(wf, context):  # pylint: disable=invalid-name,unused-argument
    """Publish version"""
    request = check_request()
    translate = request.localizer.translate
    publication_info = IWorkflowPublicationInfo(context)
    publication_info.publication_date = datetime.utcnow()
    publication_info.publisher = request.principal.id
    version_id = IWorkflowState(context).version_id
    for version in IWorkflowVersions(context).get_versions(
        (PUBLISHED_STATE, )):
        if version is not context:
            IWorkflowInfo(version).fire_transition_toward(
                ARCHIVED_STATE,
                comment=translate(
                    _("Published version {0}")).format(version_id))
Exemplo n.º 24
0
 def get_label(content, request=None, format=True):  # pylint: disable=redefined-builtin
     """Workflow state label getter"""
     if request is None:
         request = check_request()
     translate = request.localizer.translate
     state = IWorkflowState(content)
     header = STATES_HEADERS.get(state.state)
     if header is not None:
         state_label = translate(header)
         if format:
             state_label = translate(_('{state} {date}')).format(
                 state=state_label, date=format_datetime(state.state_date))
     else:
         state_label = translate(_("Unknown state"))
     return state_label
Exemplo n.º 25
0
def text_to_html(text, renderer='text', **kwargs):
    """Convert text to HTML using the given renderer

    Renderer name can be any registered HTML renderer adapter.

    You can provide several renderers by giving their names separated by semicolon; renderers
    will then act as in a pipe, each renderer transforming output of the previous one.
    """
    request = check_request()
    registry = request.registry
    for renderer_name in renderer.split(';'):
        renderer = registry.queryMultiAdapter((text, request), IHTMLRenderer, name=renderer_name)
        if renderer is not None:
            text = renderer.render(**kwargs) or text
    return text
Exemplo n.º 26
0
def handle_removed_task(event):
    """Handle removed task"""
    request = check_request()
    if request.registry is not None:
        handler = request.registry.settings.get(SCHEDULER_HANDLER_KEY, False)
        if handler:
            task = event.object
            scheduler_util = query_utility(IScheduler)
            zmq_settings = {
                'zodb_name': scheduler_util.zodb_name,
                'task_name': task.__name__,
                'job_id': task.internal_id
            }
            LOGGER.debug("Removing task {0.name} with {1!r}".format(task, zmq_settings))
            socket = zmq_socket(handler, auth=request.registry.settings.get(SCHEDULER_AUTH_KEY))
            socket.send_json(['remove_task', zmq_settings])
            zmq_response(socket)
Exemplo n.º 27
0
 def is_visible(self, request=None, check_parent=True):
     """Check if content is published and visible to given request"""
     if request is None:
         request = check_request()
     # associated workflow?
     content = IWorkflowManagedContent(self.__parent__, None)
     if content is not None:
         wf_name = content.workflow_name
         if not wf_name:
             return True
         # check workflow?
         if content.view_permission and \
            not request.has_permission(content.view_permission, context=self.__parent__):
             return False
     else:
         if not request.has_permission(VIEW_PERMISSION,
                                       context=self.__parent__):
             return False
     return self.is_published(check_parent)
Exemplo n.º 28
0
 def remove_version(self,
                    version_id,
                    state='deleted',
                    comment=None,
                    principal=None,
                    request=None):
     # pylint: disable=too-many-arguments
     """Remove version with given ID"""
     if str(version_id) not in self:
         return
     # update version state
     version = self[str(version_id)]
     wf_state = IWorkflowState(version)
     if comment:
         if request is None:
             request = check_request()
         translate = request.localizer.translate
         workflow = get_utility(
             IWorkflow,
             name=get_parent(self, IWorkflowManagedContent).workflow_name)
         item = WorkflowHistoryItem(
             date=datetime.utcnow(),
             source_version=wf_state.version_id,
             source_state=translate(
                 workflow.states.getTerm(wf_state.state).title),
             target_state=translate(workflow.states.getTerm(state).title),
             principal=request.principal.id,
             comment=comment)
         wf_state.history.append(item)  # pylint: disable=no-member
     wf_state.state = state
     if principal is not None:
         wf_state.state_principal = principal
     # remove given version
     state = self.state_by_version[version_id]
     versions = self.versions_by_state[state]
     versions.remove(version_id)
     if versions:
         self.versions_by_state[state] = versions
     else:
         del self.versions_by_state[state]
     del self.state_by_version[version_id]
     self.deleted[version_id] = self[str(version_id)]
     del self[str(version_id)]
Exemplo n.º 29
0
 def get_geometry(self, selection_name):
     """Get geometry matching given selection name"""
     geometries = get_annotation_adapter(self.image,
                                         THUMBNAIL_GEOMETRY_KEY,
                                         default={})
     # get default geometry for custom thumbnails
     if ':' in selection_name:
         selection_name, options = selection_name.split(':', 1)
     else:
         options = None
     if selection_name in geometries:
         return geometries[selection_name]
     registry = check_request().registry
     thumbnailer = registry.queryAdapter(self.image,
                                         IThumbnailer,
                                         name=selection_name)
     if thumbnailer is not None:
         return thumbnailer.get_default_geometry(options)
     return None
Exemplo n.º 30
0
 def update(self, data, properties, request=None):
     """Document data setter"""
     if properties:
         if request is None:
             request = check_request()
         self.updater = request.principal.id
     if data is not None:
         if 'filename' in properties:
             data = (properties.pop('filename'), data)
         self.data = data
     if (not self.title) or ('title' in properties):
         self.title = properties.pop('title', '<UNDEFINED>')
     if (not self.application_name) or ('application_name' in properties):
         self.application_name = properties.pop('application_name',
                                                '<UNDEFINED>')
     self.update_roles(properties, request)
     self.update_security_policy(properties, request)
     self.update_status(properties, request)
     self.update_properties(properties, request)
     return IWorkflowState(self)