Beispiel #1
0
    ("path", "expected"),
    [("/foo/bar/", True), ("/static/wat/", False),
     ("/_debug_toolbar/thing/", False)],
)
def test_activate_hook(path, expected):
    request = pretend.stub(path=path)
    assert config.activate_hook(request) == expected


@pytest.mark.parametrize(
    ("exc_info", "expected"),
    [
        (None, False),
        ((ValueError, ValueError(), None), True),
        ((HTTPForbidden, HTTPForbidden(), None), True),
        ((HTTPUnauthorized, HTTPUnauthorized(), None), True),
        ((BasicAuthBreachedPassword, BasicAuthBreachedPassword(), None),
         False),
        ((BasicAuthFailedPassword, BasicAuthFailedPassword(), None), False),
    ],
)
def test_commit_veto(exc_info, expected):
    request = pretend.stub(exc_info=exc_info)
    response = pretend.stub()

    assert bool(config.commit_veto(request, response)) == expected


@pytest.mark.parametrize("route_kw", [None, {}, {"foo": "bar"}])
def test_template_view(route_kw):
    configobj = pretend.stub(
Beispiel #2
0
def developer_application_edit(request):
    app_id = request.matchdict['app']

    try:
        uuid.UUID(app_id)
    except ValueError:
        return HTTPBadRequest()

    try:
        app = Session.query(Application).filter(Application.id == app_id).one()
    except NoResultFound:
        return HTTPNotFound()

    assert_authenticated_user_is_registered(request)

    if app.user != request.user:
        return HTTPUnauthorized()

    schema = FullApplicationSchema()
    button1 = Button('submit', _('Save application'))
    button1.css_class = 'btn-primary'
    button2 = Button('delete', _('Delete application'))
    button2.css_class = 'btn-danger'
    button3 = Button('cancel', _('Cancel'))
    button3.css_class = 'btn-default'
    form = Form(schema, buttons=(button1, button2, button3))

    if 'submit' in request.POST:
        controls = request.POST.items()
        try:
            appstruct = form.validate(controls)
        except ValidationFailure as e:
            return {'form': e.render(), 'app': app}

        # the data is fine, save into the db
        app.name = appstruct['name']
        app.main_url = appstruct['main_url']
        app.callback_url = appstruct['callback_url']
        app.authorized_origins = appstruct['authorized_origins']
        app.production_ready = appstruct['production_ready']
        app.image_url = appstruct['image_url']
        app.description = appstruct['description']

        Session.add(app)

        request.session.flash(_('The changes were saved successfully'),
                              'success')

        return HTTPFound(
            location=request.route_path('oauth2_developer_applications'))
    elif 'delete' in request.POST:
        return HTTPFound(location=request.route_path(
            'oauth2_developer_application_delete', app=app.id))
    elif 'cancel' in request.POST:
        return HTTPFound(
            location=request.route_path('oauth2_developer_applications'))

    # this is a GET
    return {
        'form':
        form.render({
            'name': app.name,
            'main_url': app.main_url,
            'callback_url': app.callback_url,
            'authorized_origins': app.authorized_origins,
            'production_ready': app.production_ready,
            'image_url': app.image_url,
            'description': app.description,
            'client_id': app.id,
            'client_secret': app.secret,
        }),
        'app':
        app,
    }
 def wrapper(request):
     if check_group_of_user(request, 'Users', plugin_name):
         return view_function(request)
     else:
         return HTTPUnauthorized()
Beispiel #4
0
def make_401_error(message, realm="AIRS Export"):
    error = HTTPUnauthorized(
        headers=make_headers({"WWW-Authenticate": 'Basic realm="%s"' % realm}))
    error.content_type = "text/plain"
    error.text = message
    return error
Beispiel #5
0
    def mutate(root, args, context, info):
        cls = models.Thematic
        discussion_id = context.matchdict['discussion_id']
        user_id = context.authenticated_userid or Everyone

        thematic_id = args.get('id')
        id_ = int(Node.from_global_id(thematic_id)[1])
        thematic = cls.get(id_)

        permissions = get_permissions(user_id, discussion_id)
        allowed = thematic.user_can(user_id, CrudPermissions.UPDATE,
                                    permissions)
        if not allowed or (allowed == IF_OWNED and user_id == Everyone):
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush:
            title_entries = args.get('title_entries')
            if len(title_entries) == 0:
                raise Exception(
                    'Thematic titleEntries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            update_langstring_from_input_entries(thematic, 'title',
                                                 title_entries)
            update_langstring_from_input_entries(
                thematic, 'description', args.get('description_entries'))
            kwargs = {}
            video = args.get('video')
            if video is not None:
                update_langstring_from_input_entries(thematic, 'video_title',
                                                     video['title_entries'])
                update_langstring_from_input_entries(
                    thematic, 'video_description',
                    video['description_entries'])
                kwargs['video_html_code'] = video['html_code']

            # take the first entry and set it for short_title
            kwargs['short_title'] = title_entries[0]['value']
            kwargs['identifier'] = args.get('identifier')
            for attr, value in kwargs.items():
                setattr(thematic, attr, value)
            db = thematic.db
            db.flush()

            questions_input = args.get('questions')
            existing_questions = {
                question.id: question
                for question in thematic.get_children()
            }
            updated_questions = set()
            if questions_input is not None:
                for question_input in questions_input:
                    if question_input.get('id', None) is not None:
                        id_ = int(Node.from_global_id(question_input['id'])[1])
                        updated_questions.add(id_)
                        question = models.Question.get(id_)
                        update_langstring_from_input_entries(
                            question, 'title', question_input['title_entries'])
                    else:
                        title_ls = langstring_from_input_entries(
                            question_input['title_entries'])
                        models.Question(title=title_ls,
                                        discussion_id=discussion_id)
                        thematic.children.append(
                            models.Question(title=title_ls,
                                            discussion_id=discussion_id))

            # remove question (tombstone it) that are not in questions_input
            for question_id in set(
                    existing_questions.keys()).difference(updated_questions):
                existing_questions[
                    question_id].tombstone_date = datetime.utcnow()

            db.flush()

        return UpdateThematic(thematic=thematic)
Beispiel #6
0
    def mutate(root, args, context, info):
        EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value
        discussion_id = context.matchdict['discussion_id']

        user_id = context.authenticated_userid or Everyone
        discussion = models.Discussion.get(discussion_id)

        idea_id = args.get('idea_id')
        idea_id = int(Node.from_global_id(idea_id)[1])
        in_reply_to_idea = models.Idea.get(idea_id)

        if isinstance(in_reply_to_idea, models.Question):
            cls = models.PropositionPost
        else:
            cls = models.AssemblPost

        extract_id = args.get('extract_id')
        if extract_id:
            extract_id_global = int(Node.from_global_id(extract_id)[1])
            extract = models.Extract.get(extract_id_global)
            cls = models.ExtractComment

        in_reply_to_post = None
        if (cls == models.AssemblPost) or (cls == models.ExtractComment):
            in_reply_to_post_id = args.get('parent_id')
            if in_reply_to_post_id:
                in_reply_to_post_id = int(
                    Node.from_global_id(in_reply_to_post_id)[1])
                if in_reply_to_post_id:
                    in_reply_to_post = models.Post.get(in_reply_to_post_id)

        permissions = get_permissions(user_id, discussion_id)
        allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE,
                                   permissions)
        if not allowed:
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush:
            subject = args.get('subject')
            body = args.get('body')
            classifier = args.get('message_classifier', None)
            body = sanitize_html(body)
            body_langstring = models.LangString.create(body)
            publication_state = models.PublicationStates.from_string(
                args.get('publication_state')) if args.get(
                    'publication_state') in models.PublicationStates.values(
                    ) else models.PublicationStates.PUBLISHED

            if subject:
                subject = sanitize_text(subject)
                subject_langstring = models.LangString.create(subject)
            elif issubclass(cls, models.PropositionPost):
                # Specific case first. Respect inheritance. Since we are using
                # a specific value, construct it with localization machinery.
                subject_langstring = models.LangString.create_localized_langstring(  # noqa: E501
                    _('Proposal'), discussion.discussion_locales,
                    {'fr': 'Proposition'})
            else:
                # We apply the same logic than in views/api/post.py::create_post  # noqa: E501
                locale = models.Locale.UNDEFINED
                if in_reply_to_post and in_reply_to_post.get_title():
                    original_subject = in_reply_to_post.get_title(
                    ).first_original()
                    locale = original_subject.locale_code
                    subject = original_subject.value
                elif in_reply_to_idea:
                    # TODO: some ideas have extra langstring titles
                    # we try to guess the locale of the body to use the same locale for post's subject
                    body_lang, data = discussion.translation_service(
                    ).identify(body_langstring.entries[0].value,
                               discussion.discussion_locales)

                    closest_subject = in_reply_to_idea.title.closest_entry(
                        body_lang)
                    if closest_subject:
                        subject = closest_subject.value
                        locale = closest_subject.locale.code
                    else:
                        # rather no subject than one in a random locale
                        subject = u''
                        locale = discussion.main_locale
                else:
                    subject = discussion.topic if discussion.topic else ''
                    locale = discussion.main_locale

                if subject is not None:
                    if in_reply_to_idea and in_reply_to_idea.message_view_override == u'messageColumns':
                        new_subject = subject
                    else:
                        new_subject = u'Re: ' + restrip_pat.sub(
                            '', subject).strip()  # noqa: E501

                    if (in_reply_to_post and new_subject == subject
                            and in_reply_to_post.get_title()):
                        # reuse subject and translations
                        subject_langstring = in_reply_to_post.get_title(
                        ).clone(discussion.db)
                    else:
                        subject_langstring = models.LangString.create(
                            new_subject, locale)

            if cls == models.ExtractComment:
                new_post = cls(discussion=discussion,
                               subject=subject_langstring,
                               body=body_langstring,
                               creator_id=user_id,
                               body_mime_type=u'text/html',
                               message_classifier=classifier,
                               creation_date=datetime.utcnow(),
                               publication_state=publication_state,
                               parent_extract_id=extract.id)
            else:
                new_post = cls(discussion=discussion,
                               subject=subject_langstring,
                               body=body_langstring,
                               creator_id=user_id,
                               body_mime_type=u'text/html',
                               message_classifier=classifier,
                               creation_date=datetime.utcnow(),
                               publication_state=publication_state)

            new_post.guess_languages()
            db = new_post.db
            db.add(new_post)
            db.flush()

            if in_reply_to_post:
                new_post.set_parent(in_reply_to_post)
            elif in_reply_to_idea and cls != models.ExtractComment:
                # don't create IdeaRelatedPostLink when we have both
                # in_reply_to_post and in_reply_to_idea or if it's a comment
                # for an extract
                idea_post_link = models.IdeaRelatedPostLink(
                    creator_id=user_id,
                    content=new_post,
                    idea=in_reply_to_idea)
                db.add(idea_post_link)
            db.flush()

            attachments = args.get('attachments', [])
            for document_id in attachments:
                document = models.Document.get(document_id)
                models.PostAttachment(document=document,
                                      discussion=discussion,
                                      creator_id=context.authenticated_userid,
                                      post=new_post,
                                      title=document.title,
                                      attachmentPurpose=EMBED_ATTACHMENT)

            db.flush()

        return CreatePost(post=new_post)
    def lux_report_create(self):
        token = self.config["authtkt_secret"]
        print_servers = DBSession.query(LuxPrintServers).all()
        if os.environ.get('FAKE_PRINT_URLS'):
            print_urls = os.environ.get('FAKE_PRINT_URLS').split(',')
        else:
            print_urls = [print_server.url for print_server in print_servers]
        urllib.request.getproxies = lambda: {}
        valid_print_urls = []
        if print_urls is not None and len(print_urls) > 0:
            for url in print_urls:
                try:
                    test_url = url.replace("/print/geoportailv3", "")
                    urllib.request.urlopen(test_url)
                    valid_print_urls.append(url)
                except Exception as e:
                    log.exception(e)
                    log.error("Print server not available : " + url)
            print_url = valid_print_urls[random.randint(
                0,
                len(valid_print_urls) - 1)]
        else:
            print_url = self.config["print_url"]

        spec = json.loads(
            self.request.body.decode("utf-8").replace(
                ".app.geoportail",
                ".geoportail").replace("vectortiles.geoportail.lu",
                                       "vectortiles-print.geoportail.lu"))

        for map_layer in spec["attributes"]["map"]["layers"]:
            if "baseURL" in map_layer and\
               "ogcproxywms" in map_layer["baseURL"]:
                if "customParams" in map_layer:
                    map_layer["customParams"]["GP_TOKEN"] = token
                else:
                    map_layer["customParams"] = {"GP_TOKEN": token}
                if self.request.user and\
                   self.request.user.ogc_role is not None and\
                   self.request.user.ogc_role != -1:
                    if "customParams" in map_layer:
                        map_layer["customParams"]["roleOGC"] =\
                            str(self.request.user.ogc_role)
                    else:
                        map_layer["customParams"] =\
                            {"roleOGC": str(self.request.user.ogc_role)}

                for layer in map_layer["layers"]:
                    internal_wms = DBSession.query(LuxLayerInternalWMS).filter(
                        LuxLayerInternalWMS.layer == layer).first()
                    if internal_wms is not None and\
                       not self._is_authorized(internal_wms):
                        return HTTPUnauthorized()
        if "longUrl" in spec["attributes"]:
            opener = urllib.request.build_opener(urllib.request.HTTPHandler())
            data = urllib.parse.urlencode(
                {"url": spec["attributes"]["longUrl"]})
            content = opener.open("https://map.geoportail.lu/short/create",
                                  data=data.encode('utf-8')).read()
            shortner = json.loads(content)
            spec["attributes"]["url"] = shortner["short_url"]
            spec["attributes"]["qrimage"] =\
                "https://map.geoportail.lu/main/wsgi/qr?url=" + \
                spec["attributes"]["url"]

        job = LuxPrintJob()
        job.spec = json.dumps(spec)
        if "longUrl" in spec["attributes"]:
            spec["attributes"].pop('longUrl', None)
        if "firstPagesUrls" in spec["attributes"]:
            spec["attributes"].pop('firstPagesUrls', None)
        self.request.body = str.encode(json.dumps(spec))

        resp, content = self._proxy(
            "%s/report.%s" % (print_url, self.request.matchdict.get("format")))
        job.id = json.loads(content)["ref"]
        job.print_url = print_url
        job.creation = datetime.now()
        DBSession.add(job)

        return self._build_response(resp, content, False, "print")
Beispiel #8
0
 def require_authentication(self):
   token = self.request.userdb.authenticate(self.get_username(),
                                            self.request.json_body['password'])
   if 'error' in token:
     raise HTTPUnauthorized(token)
Beispiel #9
0
    def login(self) -> pyramid.response.Response:
        self._referer_log()

        login = self.request.POST.get("login")
        password = self.request.POST.get("password")
        if login is None or password is None:
            raise HTTPBadRequest(
                "'login' and 'password' should be available in request params."
            )
        username = self.request.registry.validate_user(self.request, login,
                                                       password)
        if username is not None:
            user = models.DBSession.query(
                static.User).filter(static.User.username == username).one()
            if self.two_factor_auth:
                if "2fa_totp_secret" not in user.tech_data:
                    user.is_password_changed = False
                if not user.is_password_changed:
                    user.tech_data["2fa_totp_secret"] = pyotp.random_base32()
                    if self.request.GET.get("type") == "oauth2":
                        raise HTTPFound(
                            location=self.request.route_url("notlogin"))
                    return set_common_headers(
                        self.request,
                        "login",
                        Cache.PRIVATE_NO,
                        response=Response(
                            json.dumps({
                                "username":
                                user.username,
                                "is_password_changed":
                                False,
                                "two_factor_enable":
                                self.two_factor_auth,
                                "two_factor_totp_secret":
                                user.tech_data["2fa_totp_secret"],
                                "otp_uri":
                                pyotp.TOTP(user.tech_data["2fa_totp_secret"]).
                                provisioning_uri(
                                    user.email,
                                    issuer_name=self.two_factor_issuer_name),
                            }),
                            headers=(("Content-Type", "text/json"), ),
                        ),
                    )
                otp = self.request.POST.get("otp")
                if otp is None:
                    raise HTTPBadRequest("The second factor is missing.")
                if not self._validate_2fa_totp(user, otp):
                    LOG.info("The second factor is wrong for user '%s'.",
                             user.username)
                    raise HTTPUnauthorized("See server logs for details")
            user.update_last_login()
            user.tech_data["consecutive_failed"] = "0"

            if not user.is_password_changed:
                if self.request.GET.get("type") == "oauth2":
                    raise HTTPFound(
                        location=self.request.route_url("notlogin"))
                return set_common_headers(
                    self.request,
                    "login",
                    Cache.PRIVATE_NO,
                    response=Response(
                        json.dumps({
                            "username": user.username,
                            "is_password_changed": False,
                            "two_factor_enable": self.two_factor_auth,
                        }),
                        headers=(("Content-Type", "text/json"), ),
                    ),
                )

            LOG.info("User '%s' logged in.", username)
            if self.request.GET.get("type") == "oauth2":
                self._oauth2_login(user)

            headers = remember(self.request, username)
            came_from = self.request.params.get("came_from")
            if came_from:
                return HTTPFound(location=came_from, headers=headers)
            headers.append(("Content-Type", "text/json"))
            return set_common_headers(
                self.request,
                "login",
                Cache.PRIVATE_NO,
                response=Response(json.dumps(
                    self._user(self.request.get_user(username))),
                                  headers=headers),
            )
        user = models.DBSession.query(
            static.User).filter(static.User.username == login).one_or_none()
        if user and not user.deactivated:
            if "consecutive_failed" not in user.tech_data:
                user.tech_data["consecutive_failed"] = "0"
            user.tech_data["consecutive_failed"] = str(
                int(user.tech_data["consecutive_failed"]) + 1)
            if int(user.tech_data["consecutive_failed"]
                   ) >= self.request.registry.settings.get(
                       "authentication", {}).get("max_consecutive_failures",
                                                 sys.maxsize):
                user.deactivated = True
                user.tech_data["consecutive_failed"] = "0"

        if hasattr(self.request, "tm"):
            self.request.tm.commit()
        raise HTTPUnauthorized("See server logs for details")
Beispiel #10
0
    def submit(self):
        request = self.request
        context = self.context
        if context.username == "root" and context.index == "pypi":
            abort_submit(request, 404, "cannot submit to pypi mirror")
        stage = self.context.stage
        if not request.has_permission("pypi_submit"):
            # if there is no authenticated user, then issue a basic auth challenge
            if not request.authenticated_userid:
                response = HTTPUnauthorized()
                response.headers.update(forget(request))
                return response
            abort_submit(request, 403, "no permission to submit")
        try:
            action = request.POST[":action"]
        except KeyError:
            abort_submit(request, 400, ":action field not found")
        if action == "submit":
            self._set_versiondata_form(stage, request.POST)
            return Response("")
        elif action in ("doc_upload", "file_upload"):
            try:
                content = request.POST["content"]
            except KeyError:
                abort_submit(request, 400, "content file field not found")
            name = ensure_unicode(request.POST.get("name"))
            # version may be empty on plain doczip uploads
            version = ensure_unicode(request.POST.get("version") or "")
            project = normalize_name(name)

            if action == "file_upload":
                if not stage.has_project(name):
                    abort_submit(
                        request, 400,
                        "no project named %r was ever registered" % (name))

                self.log.debug("metadata in form: %s",
                               list(request.POST.items()))

                # we only check for release files if version is
                # contained in the filename because for doczip files
                # we construct the filename ourselves anyway.
                if version and version not in content.filename:
                    abort_submit(
                        request, 400,
                        "filename %r does not contain version %r" % (
                            content.filename, version))

                abort_if_invalid_filename(request, name, content.filename)
                metadata = stage.get_versiondata_perstage(project, version)
                if not metadata:
                    self._set_versiondata_form(stage, request.POST)
                    metadata = stage.get_versiondata(project, version)
                    if not metadata:
                        abort_submit(
                            request, 400, "could not process form metadata")
                file_content = content.file.read()
                try:
                    link = stage.store_releasefile(
                        project, version,
                        content.filename, file_content)
                except stage.NonVolatile as e:
                    if e.link.matches_checksum(file_content):
                        abort_submit(
                            request, 200,
                            "Upload of identical file to non volatile index.",
                            level="info")
                    abort_submit(
                        request, 409,
                        "%s already exists in non-volatile index" % (
                            content.filename,))
                link.add_log(
                    'upload', request.authenticated_userid, dst=stage.name)
                try:
                    self.xom.config.hook.devpiserver_on_upload_sync(
                        log=request.log, application_url=request.application_url,
                        stage=stage, project=project, version=version)
                except Exception as e:
                    abort_submit(
                        request, 200,
                        "OK, but a trigger plugin failed: %s" % e, level="warn")
            else:
                doczip = content.file.read()
                try:
                    link = stage.store_doczip(project, version, doczip)
                except stage.MissesVersion as e:
                    abort_submit(
                        request, 400,
                        "%s" % e)
                except stage.MissesRegistration:
                    abort_submit(
                        request, 400,
                        "%s-%s is not registered" % (name, version))
                except stage.NonVolatile as e:
                    if e.link.matches_checksum(doczip):
                        abort_submit(
                            request, 200,
                            "Upload of identical file to non volatile index.",
                            level="info")
                    abort_submit(
                        request, 409,
                        "%s already exists in non-volatile index" % (
                            content.filename,))
                link.add_log(
                    'upload', request.authenticated_userid, dst=stage.name)
        else:
            abort_submit(request, 400, "action %r not supported" % action)
        return Response("")
Beispiel #11
0
def settings(request):
    if request.user.keyname == 'guest':
        return HTTPUnauthorized()

    return dict(title=_("User settings"))
Beispiel #12
0
def create_post(request):
    """
    Create a new post in this discussion.

    We use post, not put, because we don't know the id of the post
    """
    localizer = request.localizer
    request_body = json.loads(request.body)
    user_id = request.authenticated_userid
    if not user_id:
        raise HTTPUnauthorized()

    user = Post.default_db.query(User).filter_by(id=user_id).one()

    body = request_body.get('body', None)
    html = request_body.get('html',
                            None)  # BG: Is this used now? I cannot see it.
    reply_id = request_body.get('reply_id', None)
    idea_id = request_body.get('idea_id', None)
    subject = request_body.get('subject', None)
    publishes_synthesis_id = request_body.get('publishes_synthesis_id', None)
    message_classifier = request_body.get('message_classifier', None)

    if not body and not publishes_synthesis_id:
        # Should we allow empty messages otherwise?
        raise HTTPBadRequest(localizer.translate(_("Your message is empty")))

    if reply_id:
        in_reply_to_post = Post.get_instance(reply_id)
    else:
        in_reply_to_post = None

    if idea_id:
        in_reply_to_idea = Idea.get_instance(idea_id)
    else:
        in_reply_to_idea = None

    discussion_id = int(request.matchdict['discussion_id'])
    discussion = Discussion.get_instance(discussion_id)

    if not discussion:
        raise HTTPNotFound(
            localizer.translate(_("No discussion found with id=%s")) %
            (discussion_id, ))

    ctx = DummyContext({Discussion: discussion})
    if html:
        log.warning("Still using html")
        # how to guess locale in this case?
        body = LangString.create(sanitize_html(html))
        # TODO: AssemblPosts are pure text right now.
        # Allowing HTML requires changes to the model.
    elif body:
        # TODO: Accept HTML body.
        for e in body['entries']:
            e['value'] = sanitize_text(e['value'])
        body = LangString.create_from_json(body, context=ctx, user_id=user_id)
    else:
        body = LangString.EMPTY(discussion.db)

    if subject:
        for e in subject['entries']:
            e['value'] = sanitize_text(e['value'])
        subject = LangString.create_from_json(subject,
                                              context=ctx,
                                              user_id=user_id)
    else:
        from assembl.models import Locale
        locale = Locale.UNDEFINED
        # print(in_reply_to_post.subject, discussion.topic)
        if in_reply_to_post and in_reply_to_post.get_title():
            original_subject = in_reply_to_post.get_title().first_original()
            if original_subject:
                locale = original_subject.locale_code
                subject = (original_subject.value or ''
                           if in_reply_to_post.get_title() else '')
        elif in_reply_to_idea:
            # TODO:  THis should use a cascade like the frontend
            # also, some ideas have extra langstring titles
            subject = (in_reply_to_idea.short_title
                       if in_reply_to_idea.short_title else '')
            locale = discussion.main_locale
        else:
            subject = discussion.topic if discussion.topic else ''
            locale = discussion.main_locale
        # print subject
        if subject is not None and len(subject):
            new_subject = "Re: " + restrip_pat.sub('', subject).strip()
            if (in_reply_to_post and new_subject == subject
                    and in_reply_to_post.get_title()):
                # reuse subject and translations
                subject = in_reply_to_post.get_title().clone(discussion.db)
            else:
                # how to guess locale in this case?
                subject = LangString.create(new_subject, locale)
        else:
            capture_message(
                "A message is about to be written to the database with an "
                "empty subject.  This is not supposed to happen.")
            subject = LangString.EMPTY(discussion.db)

    post_constructor_args = {
        'discussion': discussion,
        'creator_id': user_id,
        'message_classifier': message_classifier,
        'subject': subject,
        'body': body
    }

    if publishes_synthesis_id:
        published_synthesis = Synthesis.get_instance(publishes_synthesis_id)
        post_constructor_args['publishes_synthesis'] = published_synthesis
        new_post = SynthesisPost(**post_constructor_args)
        new_post.finalize_publish()
    else:
        new_post = AssemblPost(**post_constructor_args)
    new_post.guess_languages()

    discussion.db.add(new_post)
    discussion.db.flush()

    if in_reply_to_post:
        new_post.set_parent(in_reply_to_post)
    if in_reply_to_idea:
        idea_post_link = IdeaRelatedPostLink(creator_id=user_id,
                                             content=new_post,
                                             idea=in_reply_to_idea)
        discussion.db.add(idea_post_link)
        idea = in_reply_to_idea
        while idea:
            idea.send_to_changes()
            parents = idea.get_parents()
            idea = next(iter(parents)) if parents else None
    else:
        discussion.root_idea.send_to_changes()
    for source in discussion.sources:
        if 'send_post' in dir(source):
            source.send_post(new_post)
    permissions = get_permissions(user_id, discussion_id)

    return new_post.generic_json('default', user_id, permissions)
Beispiel #13
0
def search_endpoint(context, request):
    if not indexing_active():
        return HTTPServiceUnavailable("Indexing inactive")

    query = request.json_body
    # u'query': {u'bool': {u'filter': [{u'term': {u'discussion_id': u'23'}}]}}
    filters = [fil for fil in query['query']['bool']['filter']]
    discussion_id = [f.values()[0].values()[0]
                     for f in filters if 'discussion_id' in f.values()[0].keys()][0]
    discussion = models.Discussion.get_instance(discussion_id)
    if discussion is None:
        raise HTTPUnauthorized()

    user_id = request.authenticated_userid or Everyone
    permissions = get_permissions(user_id, discussion_id)
    if not discussion.user_can(user_id, CrudPermissions.READ, permissions):
        raise HTTPUnauthorized()

    es = connect()
    index_name = get_index_settings(config)['index_name']
#    print get_curl_query(query)
    result = es.search(index=index_name, body=query)

    # add creator_name in each hit
    creator_ids = set([hit['_source']['creator_id']
                       for hit in result['hits']['hits']
                       if hit['_source'].get('creator_id', None) is not None])
    session = get_session_maker()
    creators = session.query(models.AgentProfile.id, models.AgentProfile.name
        ).filter(models.AgentProfile.id.in_(creator_ids)).all()
    creators_by_id = dict(creators)
    for hit in result['hits']['hits']:
        source = hit['_source']
        creator_id = source.get('creator_id', None)
        # Remove inner_hits key to not leak posts from private discussion.
        # You can easily craft a query to get the participants of a public
        # discussion and do a has_child filter with inner_hits on a private discussion.
        if 'inner_hits' in hit:
            del hit['inner_hits']

        if creator_id is not None:
            source['creator_name'] = creators_by_id.get(creator_id)

        if hit['_type'] == 'idea':
            idea = models.Idea.get_instance(source['id'])
            # The check is not really necessary because it's the same
            # 'read' permission as the discussion, but it doesn't cost anything
            # to check it and the READ permission may change in the future.
            if not idea.user_can(user_id, CrudPermissions.READ, permissions):
                raise HTTPUnauthorized

            source['num_posts'] = idea.num_posts
            source['num_contributors'] = idea.num_contributors
        elif hit['_type'] == 'user':
            agent_profile = models.AgentProfile.get_instance(source['id'])
            if not agent_profile.user_can(user_id, CrudPermissions.READ, permissions):
                raise HTTPUnauthorized

            source['num_posts'] = agent_profile.count_posts_in_discussion(discussion_id)
        # Don't do an extra request to verify the CrudPermissions.READ permission
        # for post or synthesis.
        # It's currently the same 'read' permission as the discussion.
        # elif hit['_type'] in ('synthesis', 'post'):
        #     post = models.Post.get_instance(source['id'])
        #     if not post.user_can(user_id, CrudPermissions.READ, permissions):
        #         raise HTTPUnauthorized

    return result
Beispiel #14
0
def get_token(request):
    if 'access_code' in request.session:
        return {'access_code': request.session['access_code']}
    else:
        return HTTPUnauthorized()
Beispiel #15
0
def assembl_profile(request):
    session = AgentProfile.default_db
    localizer = request.localizer
    profile = get_profile(request)
    id_type = request.matchdict.get('type').strip()
    logged_in = request.authenticated_userid
    save = request.method == 'POST'
    # if some other user
    if not profile or not logged_in or logged_in != profile.id:
        if save:
            raise HTTPUnauthorized()
        # Add permissions to view a profile?
        return render_to_response(
            'assembl:templates/view_profile.jinja2',
            dict(get_default_context(request),
                 profile=profile,
                 user=logged_in and session.query(User).get(logged_in)))

    confirm_email = request.params.get('confirm_email', None)
    if confirm_email:
        return HTTPTemporaryRedirect(location=request.route_url(
            'confirm_emailid_sent', email_account_id=int(confirm_email)))
    errors = []
    if save:
        user_id = profile.id
        redirect = False
        username = request.params.get('username', '').strip()
        if username and (profile.username is None
                         or username != profile.username.username):
            # check if exists
            if session.query(Username).filter_by(username=username).count():
                errors.append(
                    localizer.translate(_('The username %s is already used')) %
                    (username, ))
            else:
                old_username = profile.username
                if old_username is not None:
                    # free existing username
                    session.delete(old_username)
                    session.flush()
                # add new username
                session.add(Username(username=username, user=profile))

                if id_type == 'u':
                    redirect = True
        name = request.params.get('name', '').strip()
        if name:
            profile.name = name
        p1, p2 = (request.params.get('password1', '').strip(),
                  request.params.get('password2', '').strip())
        if p1 != p2:
            errors.append(
                localizer.translate(_('The passwords are not identical')))
        elif p1:
            profile.password_p = p1
        add_email = request.params.get('add_email', '').strip()
        if add_email:
            if not is_email(add_email):
                return dict(get_default_context(request),
                            error=localizer.translate(
                                _("This is not a valid email")))
            # No need to check presence since not validated yet
            email = EmailAccount(email=add_email, profile=profile)
            session.add(email)
        if redirect:
            return HTTPFound(location=request.route_url(
                'profile_user', type='u', identifier=username))
        profile = session.query(User).get(user_id)
    unverified_emails = [
        (ea,
         session.query(AbstractAgentAccount).filter_by(email_ci=ea.email_ci,
                                                       verified=True).first())
        for ea in profile.email_accounts if not ea.verified
    ]
    get_route = create_get_route(request)
    providers = get_provider_data(get_route)
    return render_to_response(
        'assembl:templates/profile.jinja2',
        dict(get_default_context(request),
             error='<br />'.join(errors),
             unverified_emails=unverified_emails,
             providers=providers,
             providers_json=json.dumps(providers),
             google_consumer_key=request.registry.settings.get(
                 'google.consumer_key', ''),
             the_user=profile,
             user=session.query(User).get(logged_in)))
Beispiel #16
0
    def challenge(self, request, content="Unauthorized"):
        if self.authenticated_userid(request):
            return HTTPUnauthorized(content, headers=self.forget(request))

        return HTTPForbidden(content, headers=self.forget(request))
Beispiel #17
0
    def authenticated_userid(self, request):
        # Override current user in tests via ngw_auth_administrator fixture
        if self.test_user is not None:
            return User.by_keyname(self.test_user).id

        session = request.session

        # Session based authentication

        current = session.get('auth.policy.current')
        if current is not None:
            atype, user_id, exp = current[0:3]
            exp = timestamp_to_datetime(int(exp))

            now = datetime.utcnow()
            expired = exp <= now

            if atype == 'OAUTH':
                if len(current) != 3:
                    raise ValueError("Invalid OAuth session data")

                if expired:
                    try:
                        tresp = self.oauth.grant_type_refresh_token(
                            refresh_token=session['auth.policy.refresh_token'],
                            access_token=session['auth.policy.access_token'])
                        self.remember(request, (user_id, tresp))
                    except OAuthTokenRefreshException:
                        self.forget(request)
                        return None

                return user_id

            elif atype == 'LOCAL':
                if expired:
                    return None

                refresh, = current[3:]
                if timestamp_to_datetime(refresh) <= now:
                    session['auth.policy.current'] = current[0:2] + (
                        int(
                            datetime_to_timestamp(
                                now + self.options['local.lifetime'])),
                        int(
                            datetime_to_timestamp(
                                now + self.options['local.refresh'])),
                    )

                return user_id

            else:
                raise ValueError("Invalid authentication type: " + atype)

        # HTTP based authentication

        ahead = request.headers.get('Authorization')
        if ahead is not None:
            ahead = six.ensure_text(ahead)
            amode, value = ahead.split(' ')
            amode = amode.upper()

            if amode == 'BASIC':
                username, password = six.ensure_text(
                    b64decode(value)).split(':')

                # Allow token authorization via basic when
                # username is empty (for legacy clients).

                if username == '':
                    amode = 'BEARER'
                    value = password

                else:
                    user, _ = self.authenticate_with_password(username,
                                                              password,
                                                              oauth=False)
                    return user.id

            if amode == 'BEARER' and self.oauth is not None:
                user = self.oauth.access_token_to_user(value)
                if user is not None:
                    return user.id

            raise HTTPUnauthorized()

        return None
Beispiel #18
0
 def safe_del(self, key, permissions=(P_READ, )):
     if not self.can_edit(key, permissions):
         raise HTTPUnauthorized("Cannot delete " + key)
     del self[key]
Beispiel #19
0
    def mutate(root, args, context, info):
        EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value
        discussion_id = context.matchdict['discussion_id']

        user_id = context.authenticated_userid or Everyone
        discussion = models.Discussion.get(discussion_id)

        post_id = args.get('post_id')
        post_id = int(Node.from_global_id(post_id)[1])
        post = models.Post.get(post_id)
        cls = models.Post

        permissions = get_permissions(user_id, discussion_id)
        allowed = post.user_can(user_id, CrudPermissions.UPDATE, permissions)
        if not allowed:
            raise HTTPUnauthorized()

        changed = False
        subject = args.get('subject')
        if subject:
            subject = sanitize_text(subject)
        body = args.get('body')
        if body:
            body = sanitize_html(body)
        # TODO: Here, an assumption that the modification uses the same
        # language as the original. May need revisiting.
        original_subject_entry = post.subject.first_original()
        # subject is not required, be careful to not remove it if not specified
        if subject and subject != original_subject_entry.value:
            changed = True
            post.subject.add_value(subject, original_subject_entry.locale_code)
            # Edit subject for all descendants
            children = post.children[:]
            new_subject = u'Re: ' + restrip_pat.sub('', subject).strip()
            while children:
                child = children.pop()
                children.extend(child.children)
                child.subject.add_value(
                    new_subject,
                    child.subject.first_original().locale_code)

        original_body_entry = post.body.first_original()
        if body != original_body_entry.value:
            post.body.add_value(body, original_body_entry.locale_code)
            changed = True

            original_attachments = post.attachments
            original_attachments_doc_ids = []
            if original_attachments:
                original_attachments_doc_ids = [
                    str(a.document_id) for a in original_attachments
                ]

            attachments = args.get('attachments', [])
            for document_id in attachments:
                if document_id not in original_attachments_doc_ids:
                    document = models.Document.get(document_id)
                    models.PostAttachment(
                        document=document,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        post=post,
                        title=document.title,
                        attachmentPurpose=EMBED_ATTACHMENT)

            # delete attachments that has been removed
            documents_to_delete = set(original_attachments_doc_ids) - set(
                attachments)  # noqa: E501
            for document_id in documents_to_delete:
                with cls.default_db.no_autoflush:
                    document = models.Document.get(document_id)
                    post_attachment = post.db.query(
                        models.PostAttachment).filter_by(
                            discussion_id=discussion_id,
                            post_id=post_id,
                            document_id=document_id).first()
                    document.delete_file()
                    post.db.delete(document)
                    post.attachments.remove(post_attachment)
                    post.db.flush()

        publication_state = models.PublicationStates.from_string(
            args.get('publication_state')) if args.get(
                'publication_state') in models.PublicationStates.values(
                ) else None
        if publication_state and publication_state != post.publication_state:
            post.publication_state = publication_state
            changed = True
            # Update the creation date when switching from draft to published
            if post.publication_state == models.PublicationStates.DRAFT and publication_state == models.PublicationStates.PUBLISHED:
                post.creation_date = datetime.utcnow()

        if changed:
            post.modification_date = datetime.utcnow()
            post.body_mime_type = u'text/html'
            post.db.flush()
            post.db.expire(post.subject, ["entries"])
            post.db.expire(post.body, ["entries"])

        return UpdatePost(post=post)
Beispiel #20
0
 def safe_set(self, key, value, permissions=(P_READ, )):
     if not self.can_edit(key, permissions):
         raise HTTPUnauthorized("Cannot edit " + key)
     self[key] = value
    def lux_get_thumbnail(self):
        layer_id = self.request.params.get('layerid', 359)
        internal_wms = DBSession.query(LuxLayerInternalWMS).filter(
            LuxLayerInternalWMS.id == layer_id).first()
        x = float(self.request.params.get('x', '684675.0594454071'))
        y = float(self.request.params.get('y', '6379501.028468124'))
        scale = float(self.request.params.get('scale', '77166.59993240683'))
        center = [x, y]

        spec = None
        if internal_wms is not None:
            if 'PROXYWMSURL' in os.environ:
                base_url = os.environ.get('PROXYWMSURL')
            else:
                base_url = "https://wmsproxy.geoportail.lu/ogcproxywms"
            spec = {
                "attributes": {
                    "map": {
                        "dpi":
                        127,
                        "rotation":
                        0,
                        "center":
                        center,
                        "projection":
                        "EPSG:3857",
                        "scale":
                        scale,
                        "layers": [{
                            "baseURL": base_url,
                            "imageFormat": "image/png",
                            "layers": [internal_wms.layer],
                            "customParams": {
                                "TRANSPARENT": True,
                                "MAP_RESOLUTION": 127
                            },
                            "type": "wms",
                            "opacity": 1,
                            "useNativeAngle": True
                        }]
                    }
                },
                "format": "png",
                "layout": "thumbnail"
            }
        else:
            external_wms = DBSession.query(LuxLayerExternalWMS).filter(
                LuxLayerExternalWMS.id == layer_id).first()
            if external_wms is not None:
                base_url = "https://ws.geoportail.lu/mymaps"
                category_id = external_wms.category_id
                spec = {
                    "attributes": {
                        "map": {
                            "dpi":
                            127,
                            "rotation":
                            0,
                            "center":
                            center,
                            "projection":
                            "EPSG:3857",
                            "scale":
                            scale,
                            "layers": [{
                                "baseURL": base_url,
                                "imageFormat": "image/png",
                                "layers": ["category"],
                                "customParams": {
                                    "TRANSPARENT": True,
                                    "category_id": category_id,
                                    "MAP_RESOLUTION": 127
                                },
                                "type": "wms",
                                "opacity": 1,
                                "useNativeAngle": True
                            }]
                        }
                    },
                    "format": "png",
                    "layout": "thumbnail"
                }
            else:
                layer_wmts = DBSession.query(LayerWMTS).filter(
                    LayerWMTS.id == layer_id).first()
                if layer_wmts is not None:
                    image_type = layer_wmts.image_type
                    image_ext = layer_wmts.image_type.split("/")[1]
                    spec = {
                        "attributes": {
                            "map": {
                                "dpi":
                                127,
                                "rotation":
                                0,
                                "center":
                                center,
                                "projection":
                                "EPSG:3857",
                                "scale":
                                scale,
                                "layers": [{
                                    "baseURL":
                                    "https://wmts3.geoportail.lu/mapproxy_4_v3/wmts/{Layer}/{TileMatrixSet}/{TileMatrix}/{TileCol}/{TileRow}."
                                    + image_ext,
                                    "dimensions": [],
                                    "dimensionParams": {},
                                    "imageFormat":
                                    image_type,
                                    "layer":
                                    layer_wmts.layer,
                                    "matrices": [{
                                        "identifier":
                                        "00",
                                        "matrixSize": [1, 1],
                                        "scaleDenominator":
                                        559082264.029,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "01",
                                        "matrixSize": [2, 2],
                                        "scaleDenominator":
                                        279541132.014,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "02",
                                        "matrixSize": [4, 4],
                                        "scaleDenominator":
                                        139770566.007,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "03",
                                        "matrixSize": [8, 8],
                                        "scaleDenominator":
                                        69885283.0036,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "04",
                                        "matrixSize": [16, 16],
                                        "scaleDenominator":
                                        34942641.5018,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "05",
                                        "matrixSize": [32, 32],
                                        "scaleDenominator":
                                        17471320.7509,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "06",
                                        "matrixSize": [64, 64],
                                        "scaleDenominator":
                                        8735660.37545,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "07",
                                        "matrixSize": [128, 128],
                                        "scaleDenominator":
                                        4367830.18772,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "08",
                                        "matrixSize": [256, 256],
                                        "scaleDenominator":
                                        2183915.09386,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "09",
                                        "matrixSize": [512, 512],
                                        "scaleDenominator":
                                        1091957.54693,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "10",
                                        "matrixSize": [1024, 1024],
                                        "scaleDenominator":
                                        545978.773466,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "11",
                                        "matrixSize": [2048, 2048],
                                        "scaleDenominator":
                                        272989.386733,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "12",
                                        "matrixSize": [4096, 4096],
                                        "scaleDenominator":
                                        136494.693366,
                                        "tileSize": [256, 256],
                                        "topLeftCorner":
                                        [-20037508.3428, 20037508.3428]
                                    }, {
                                        "identifier":
                                        "13",
                                        "scaleDenominator":
                                        68247.34668321429,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [8191, 8191]
                                    }, {
                                        "identifier":
                                        "14",
                                        "scaleDenominator":
                                        34123.673341607144,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [16383, 16383]
                                    }, {
                                        "identifier":
                                        "15",
                                        "scaleDenominator":
                                        17061.836670785713,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [32767, 32767]
                                    }, {
                                        "identifier":
                                        "16",
                                        "scaleDenominator":
                                        8530.918335392857,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [65535, 65535]
                                    }, {
                                        "identifier":
                                        "17",
                                        "scaleDenominator":
                                        4265.459167714285,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [131071, 131071]
                                    }, {
                                        "identifier":
                                        "18",
                                        "scaleDenominator":
                                        2132.7295838500004,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [262143, 262143]
                                    }, {
                                        "identifier":
                                        "19",
                                        "scaleDenominator":
                                        1066.3647919250002,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [524287, 524287]
                                    }, {
                                        "identifier":
                                        "20",
                                        "scaleDenominator":
                                        533.1823959625001,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [1048575, 1048575]
                                    }, {
                                        "identifier":
                                        "21",
                                        "scaleDenominator":
                                        266.59119798125005,
                                        "tileSize": [256, 256],
                                        "topLeftCorner": [
                                            -20037508.342789244,
                                            20037508.342789244
                                        ],
                                        "matrixSize": [2097151, 2097151]
                                    }],
                                    "matrixSet":
                                    "GLOBAL_WEBMERCATOR_4_V3",
                                    "opacity":
                                    1,
                                    "requestEncoding":
                                    "REST",
                                    "style":
                                    "default",
                                    "type":
                                    "WMTS",
                                    "version":
                                    "1.0.0"
                                }]
                            }
                        },
                        "format": "png",
                        "layout": "thumbnail"
                    }
        if spec is None:
            return HTTPNotFound()

        for map_layer in spec["attributes"]["map"]["layers"]:
            if "baseURL" in map_layer and\
               "ogcproxywms" in map_layer["baseURL"]:
                token = self.config["authtkt_secret"]
                if "customParams" in map_layer:
                    map_layer["customParams"]["GP_TOKEN"] = token
                else:
                    map_layer["customParams"] = {"GP_TOKEN": token}
                if self.request.user and\
                   self.request.user.ogc_role is not None and\
                   self.request.user.ogc_role != -1:
                    if "customParams" in map_layer:
                        map_layer["customParams"]["roleOGC"] =\
                            str(self.request.user.ogc_role)
                    else:
                        map_layer["customParams"] =\
                            {"roleOGC": str(self.request.user.ogc_role)}

                for layer in map_layer["layers"]:
                    internal_wms = DBSession.query(LuxLayerInternalWMS).filter(
                        LuxLayerInternalWMS.layer == layer).first()
                    if internal_wms is not None and\
                       not self._is_authorized(internal_wms):
                        return HTTPUnauthorized()

        print_servers = DBSession.query(LuxPrintServers).all()
        print_urls = [print_server.url for print_server in print_servers]
        urllib.request.getproxies = lambda: {}
        valid_print_urls = []
        if print_urls is not None and len(print_urls) > 0:
            for url in print_urls:
                try:
                    test_url = url.replace("/print/geoportailv3", "")
                    urllib.request.urlopen(test_url)
                    valid_print_urls.append(url)
                except Exception as e:
                    log.exception(e)
                    log.error("Print server not available : " + url)
            print_url = valid_print_urls[random.randint(
                0,
                len(valid_print_urls) - 1)]
        else:
            print_url = self.config["print_url"]
        resp, content = self._proxy(
            "%s/buildreport.png" % (print_url),
            params="",
            method="POST",
            body=str.encode(dumps(spec)),
            headers={"Referer": "http://print.geoportail.lu/"})
        resp["content-disposition"] = "filename=%s.png" % (str(layer_id))

        return self._build_response(resp, content, NO_CACHE, "print")
Beispiel #22
0
    def mutate(root, args, context, info):
        cls = models.Discussion
        discussion_id = context.matchdict['discussion_id']
        discussion = cls.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        permissions = get_permissions(user_id, discussion_id)
        allowed = discussion.user_can(
            user_id, CrudPermissions.UPDATE, permissions)
        if not allowed:
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush as db:
            title_entries = args.get('title_entries')
            if title_entries is not None and len(title_entries) == 0:
                raise Exception(
                    'Title entries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            update_langstring_from_input_entries(
                discussion, 'title', title_entries)

            subtitle_entries = args.get('subtitle_entries')
            update_langstring_from_input_entries(
                discussion, 'subtitle', subtitle_entries)

            button_label_entries = args.get('button_label_entries')
            update_langstring_from_input_entries(
                discussion, 'button_label', button_label_entries)

            # add uploaded header image as an attachment to the discussion
            LANDING_PAGE_HEADER_IMAGE = models.AttachmentPurpose.LANDING_PAGE_HEADER_IMAGE.value
            image = args.get('header_image')
            if image is not None:
                header_images = [
                    att for att in discussion.attachments
                    if att.attachmentPurpose == LANDING_PAGE_HEADER_IMAGE
                ]

                if image == 'TO_DELETE' and header_images:
                    header_image = header_images[0]
                    header_image.document.delete_file()
                    db.delete(header_image.document)
                    discussion.attachments.remove(header_image)
                else:
                    filename = os.path.basename(context.POST[image].filename)
                    mime_type = context.POST[image].type
                    document = models.File(
                        discussion=discussion,
                        mime_type=mime_type,
                        title=filename)
                    document.add_file_data(context.POST[image].file)

                    # if there is already an IMAGE, remove it with the
                    # associated document
                    if header_images:
                        header_image = header_images[0]
                        header_image.document.delete_file()
                        db.delete(header_image.document)
                        discussion.attachments.remove(header_image)

                    db.add(models.DiscussionAttachment(
                        document=document,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        title=filename,
                        attachmentPurpose=LANDING_PAGE_HEADER_IMAGE
                    ))

            # add uploaded logo image as an attachment to the discussion
            LANDING_PAGE_LOGO_IMAGE = models.AttachmentPurpose.LANDING_PAGE_LOGO_IMAGE.value
            image = args.get('logo_image')
            if image is not None:
                logo_images = [
                    att for att in discussion.attachments
                    if att.attachmentPurpose == LANDING_PAGE_LOGO_IMAGE
                ]

                if image == 'TO_DELETE' and logo_images:
                    logo_image = logo_images[0]
                    logo_image.document.delete_file()
                    db.delete(logo_image.document)
                    discussion.attachments.remove(logo_image)
                else:
                    filename = os.path.basename(context.POST[image].filename)
                    mime_type = context.POST[image].type
                    document = models.File(
                        discussion=discussion,
                        mime_type=mime_type,
                        title=filename)
                    document.add_file_data(context.POST[image].file)

                    # if there is already an IMAGE, remove it with the
                    # associated document
                    if logo_images:
                        logo_image = logo_images[0]
                        logo_image.document.delete_file()
                        db.delete(logo_image.document)
                        discussion.attachments.remove(logo_image)

                    db.add(models.DiscussionAttachment(
                        document=document,
                        discussion=discussion,
                        creator_id=context.authenticated_userid,
                        title=filename,
                        attachmentPurpose=LANDING_PAGE_LOGO_IMAGE
                    ))

        db.flush()
        discussion = cls.get(discussion_id)
        return UpdateDiscussion(discussion=discussion)
Beispiel #23
0
    def mutate(root, args, context, info):
        cls = models.Thematic
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        permissions = get_permissions(user_id, discussion_id)
        allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE,
                                   permissions)
        if not allowed or (allowed == IF_OWNED and user_id == Everyone):
            raise HTTPUnauthorized()

        identifier = args.get('identifier')
        with cls.default_db.no_autoflush:
            title_entries = args.get('title_entries')
            if len(title_entries) == 0:
                raise Exception(
                    'Thematic titleEntries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            title_langstring = langstring_from_input_entries(title_entries)
            description_langstring = langstring_from_input_entries(
                args.get('description_entries'))
            kwargs = {}
            if description_langstring is not None:
                kwargs['description'] = description_langstring

            video = args.get('video')
            if video is not None:
                video_title = langstring_from_input_entries(
                    video['title_entries'])
                if video_title is not None:
                    kwargs['video_title'] = video_title

                video_description = langstring_from_input_entries(
                    video['description_entries'])
                if video_description is not None:
                    kwargs['video_description'] = video_description

                kwargs['video_html_code'] = video['html_code']

            # Our thematic, because it inherits from Idea, needs to be
            # associated to the root idea of the discussion.
            # We create a hidden root thematic, corresponding to the
            # `identifier` phase, child of the root idea,
            # and add our thematic as a child of this root thematic.
            root_thematic = [
                idea for idea in discussion.root_idea.get_children()
                if getattr(idea, 'identifier', '') == identifier
            ]
            if not root_thematic:
                short_title = u'Phase {}'.format(identifier)
                root_thematic = cls(discussion_id=discussion_id,
                                    short_title=short_title,
                                    title=langstring_from_input_entries([{
                                        'locale_code':
                                        'en',
                                        'value':
                                        short_title
                                    }]),
                                    identifier=identifier,
                                    hidden=True)
                discussion.root_idea.children.append(root_thematic)
            else:
                root_thematic = root_thematic[0]

            # take the first entry and set it for short_title
            short_title = title_entries[0]['value']
            saobj = cls(discussion_id=discussion_id,
                        title=title_langstring,
                        short_title=short_title,
                        identifier=identifier,
                        **kwargs)
            root_thematic.children.append(saobj)
            db = saobj.db
            db.add(saobj)
            db.flush()

            questions_input = args.get('questions')
            if questions_input is not None:
                for question_input in questions_input:
                    title_ls = langstring_from_input_entries(
                        question_input['title_entries'])
                    saobj.children.append(
                        models.Question(title=title_ls,
                                        discussion_id=discussion_id))
                db.flush()

        return CreateThematic(thematic=saobj)
Beispiel #24
0
    def mutate(root, args, context, info):
        cls = models.Discussion
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        permissions = get_permissions(user_id, discussion_id)
        allowed = discussion.user_can(
            user_id, CrudPermissions.UPDATE, permissions)
        if not allowed:
            raise HTTPUnauthorized()

        with cls.default_db.no_autoflush as db:
            legal_notice_entries = args.get('legal_notice_entries')
            if legal_notice_entries is not None and len(legal_notice_entries) == 0:
                raise Exception(
                    'Legal notice entries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            update_langstring_from_input_entries(
                discussion, 'legal_notice', legal_notice_entries)

            terms_and_conditions_entries = args.get(
                'terms_and_conditions_entries')
            if terms_and_conditions_entries is not None and len(terms_and_conditions_entries) == 0:
                raise Exception(
                    'Terms and conditions entries needs at least one entry')
                # Better to have this message than
                # 'NoneType' object has no attribute 'owner_object'
                # when creating the saobj below if title=None

            update_langstring_from_input_entries(
                discussion, 'terms_and_conditions', terms_and_conditions_entries)

            cookies_policy_entries = args.get('cookies_policy_entries')
            if cookies_policy_entries is not None and len(cookies_policy_entries) == 0:
                raise Exception(
                    'Cookies policy entries needs at least one entry')

            update_langstring_from_input_entries(
                discussion, 'cookies_policy', cookies_policy_entries)

            privacy_policy_entries = args.get('privacy_policy_entries')
            if privacy_policy_entries is not None and len(privacy_policy_entries) == 0:
                raise Exception(
                    'Privacy policy entries need to be at least one entry'
                )

            update_langstring_from_input_entries(
                discussion, 'privacy_policy', privacy_policy_entries)

            user_guidelines_entries = args.get('user_guidelines_entries')
            if user_guidelines_entries is not None and len(user_guidelines_entries) == 0:
                raise Exception(
                    'User guidelines entries need to be at least one entry'
                )

            update_langstring_from_input_entries(
                discussion, 'user_guidelines', user_guidelines_entries
            )

        db.flush()
        legal_contents = LegalContents()
        return UpdateLegalContents(legal_contents=legal_contents)
Beispiel #25
0
 def get(self):
     user_id = self.request.matchdict.get('user_id')
     if user_id != self.request.authenticated_userid.user_id:
         raise HTTPUnauthorized()
     user = User.get(user_id)
     return ReturnUser.build(user).serialize()
Beispiel #26
0
def twitter_callback(request):
    settings = request.registry.settings

    try:
        oauth_token = request.params['oauth_token']
    except KeyError:
        return HTTPBadRequest('Missing required oauth_token')

    try:
        oauth_verifier = request.params['oauth_verifier']
    except KeyError:
        return HTTPBadRequest('Missing required oauth_verifier')

    try:
        saved_oauth_token = request.session['oauth_token']
    except KeyError:
        return HTTPBadRequest('No oauth_token was found in the session')

    if saved_oauth_token != oauth_token:
        return HTTPUnauthorized("OAuth tokens don't match")
    else:
        del request.session['oauth_token']

    access_token_url = settings['twitter_access_token_url']

    params = (
        ('oauth_token', oauth_token),
        ('oauth_verifier', oauth_verifier),
    )

    auth = auth_header('POST', access_token_url, params, settings, oauth_token)

    response = requests.post(access_token_url,
                             headers={'Authorization': auth})

    if response.status_code != 200:
        return HTTPUnauthorized(response.text)

    response_args = dict(urlparse.parse_qsl(response.text))
    # moauth_token_secret = response_args['oauth_token_secret']
    oauth_token = response_args['oauth_token']
    user_id = response_args['user_id']
    screen_name = response_args['screen_name']

    existing_user = user_from_provider_id('twitter', user_id)
    if existing_user is None:
        # fetch Twitter info only if this is the first time for
        # the user sice Twitter has very strong limits for using
        # its APIs
        twitter_info = get_user_info(settings, user_id)
        first_name, last_name = split_name(twitter_info['name'])
        info = {
            'screen_name': screen_name,
            'first_name': first_name,
            'last_name': last_name,
        }
    else:
        info = {}

    return register_or_update(request, 'twitter', user_id, info,
                              request.route_path('home'))
Beispiel #27
0
 def forbidden_view(request):
     resp = HTTPUnauthorized()
     resp.www_authenticate = 'Basic realm="Thinkhazard"'
     return resp
Beispiel #28
0
def unauthorized(request):
    if request.is_xhr:
        return HTTPUnauthorized()
    return HTTPFound(
        request.route_path('login', _query=[('came_from', request.url)]))
Beispiel #29
0
def forbidden_view(request):
    response = HTTPUnauthorized()
    response.headers.update(forget(request))
    return response
Beispiel #30
0
    def mutate(root, args, context, info):
        PROFILE_PICTURE = models.AttachmentPurpose.PROFILE_PICTURE.value
        cls = models.User
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        user_id = context.authenticated_userid or Everyone

        global_id = args.get('id')
        id_ = int(Node.from_global_id(global_id)[1])
        user = cls.get(id_)

        permissions = get_permissions(user_id, discussion_id)
        allowed = user.user_can(
            user_id, CrudPermissions.UPDATE, permissions)
        if not allowed:
            raise HTTPUnauthorized("The authenticated user can't update this user")

        with cls.default_db.no_autoflush as db:
            username = args.get('username')
            if username and username != user.username_p:
                if db.query(models.Username).filter_by(
                    username=username
                ).count():
                    raise Exception(u"001: We already have a user with this username.")

            user.username_p = username
            name = args.get('name')
            # only modify the name if it was given in parameter
            if name is not None:
                user.real_name_p = name

            old_password = args.get('old_password')
            new_password = args.get('new_password')
            new_password2 = args.get('new_password2')
            # only modify the password if it was given in parameter
            if old_password is not None and new_password is not None and new_password2 is not None:
                if not user.check_password(old_password):
                    raise Exception(u"002: The entered password doesn't match your current password.")

                if new_password != new_password2:
                    raise Exception(u"003: You entered two different passwords.")

                if old_password == new_password:
                    raise Exception(u"004: The new password has to be different than the current password.")

                from ..auth.password import verify_password
                for p in user.old_passwords:
                    if verify_password(new_password, p.password):
                        raise Exception(u"005: The new password has to be different than the last 5 passwords you set.")

                user.password_p = new_password

            # add uploaded image as an attachment to the user
            image = args.get('image')
            if image is not None:
                filename = os.path.basename(context.POST[image].filename)
                mime_type = context.POST[image].type
                document = models.File(
                    discussion=discussion,
                    mime_type=mime_type,
                    title=filename)
                document.add_file_data(context.POST[image].file)
                # if there is already an PROFILE_PICTURE, remove it with the
                # associated document
                images = [
                    att for att in user.profile_attachments
                    if att.attachmentPurpose == PROFILE_PICTURE]
                if images:
                    image = images[0]
                    allowed = image.user_can(
                        user_id, CrudPermissions.DELETE, permissions)
                    if not allowed:
                        raise HTTPUnauthorized("The authenticated user can't delete the existing AgentProfileAttachment")

                    image.document.delete_file()
                    db.delete(image.document)
                    user.profile_attachments.remove(image)

                allowed = models.AgentProfileAttachment.user_can_cls(
                    user_id, CrudPermissions.CREATE, permissions)
                if not allowed:
                    raise HTTPUnauthorized("The authenticated user can't create an AgentProfileAttachment")

                discussion.db.add(models.AgentProfileAttachment(
                    document=document,
                    discussion=discussion,
                    user=user,
                    creator_id=context.authenticated_userid,
                    title=filename,
                    attachmentPurpose=PROFILE_PICTURE
                ))

            db.flush()

        return UpdateUser(user=user)