Example #1
0
def create_project(userauth, prjtypename, prjname):
    acceptance = utils.verify_name(prjname, "Project identifier", True)
    if acceptance is not None:
        redirect("/newproject", message=acceptance)
        return

    if prjname in config.cache.projects:
        redirect("/newproject", message='Project "{}" already exists'.format(prjname))
        return

    human_name = request.forms.humanname.strip()
    acceptance = utils.verify_name(human_name, "Full project name", False)
    if acceptance is not None:
        redirect("/newproject", message=acceptance)
        return

    url = request.forms.url
    acceptance = utils.verify_url(url)
    if acceptance is not None:
        redirect("/newproject", message=acceptance)
        return

    projtype = project_type.project_types.get(prjtypename)
    if projtype is None or projtype.name not in config.cfg.project_types:
        abort(404, "Unknown project type.")
        return

    error = config.cache.create_project(prjname, human_name, projtype, url)
    if error is not None:
        abort(404, error)
        return

    message = "Successfully created project '" + prjname + "' " + utils.get_datetime_now_formatted()
    redirect("/project/<prjname>", prjname=prjname.lower(), message=message)
Example #2
0
def oauth(userauth):
    if not users.oauth_callback:
        abort(500, "No authentication method")
        return

    req_redirect = users.oauth_callback(userauth, request.url)
    if userauth.is_auth:
        login_success(req_redirect)
    else:
        utils.redirect("/", message="Try harder!", message_class="error")
Example #3
0
def project_post(userauth, prjname):
    pmd = config.cache.get_pmd(prjname)
    if pmd is None:
        abort(404, "Project does not exist")
        return

    pdata = pmd.pdata

    # Get and check the new project name.
    human_name = request.forms.name.strip()
    acceptance = utils.verify_name(human_name, "Full project name", False)
    if acceptance is not None:
        redirect("/projsettings/<prjname>",
                 prjname=prjname,
                 message=acceptance)
        return

    # Get and check the new url.
    url = request.forms.url
    acceptance = utils.verify_url(url)
    if acceptance is not None:
        abort(404, acceptance)

    message_parts = []
    if pdata.human_name != human_name:
        pdata.human_name = human_name
        pmd.human_name = human_name  # Also assign the new name to the meta-data storage.
        message_parts.append("name")
    if pdata.url != url:
        pdata.url = url
        message_parts.append("URL")

    if len(message_parts) == 0:
        message = "Project settings are not modified"
    else:
        parts = " and ".join(message_parts)
        if len(message_parts) < 2:
            has = "has"
        else:
            has = "have"

        message = "Project {} {} been changed {}"
        message = message.format(parts, has,
                                 utils.get_datetime_now_formatted())

        config.cache.save_pmd(pmd)

    redirect("/project/<prjname>", prjname=prjname.lower(), message=message)
Example #4
0
def page_post(userauth):
    prjname = request.forms.name.lower().strip()
    acceptance = utils.verify_name(prjname, "Project identifier", True)
    if acceptance is not None:
        redirect('/newproject', message=acceptance)
        return

    if prjname in config.cache.projects:
        redirect('/newproject',
                 message="Project \"{}\" already exists".format(prjname))
        return

    ptype_name = request.forms.projtype_select
    projtype = None
    for prjtp in project_type.project_types.values():
        if prjtp.human_name == ptype_name and prjtp.name in config.cfg.project_types:
            projtype = prjtp
            break
    if projtype is None:
        redirect('/newproject', message='No known project type provided')
        return
    return template('createproject_form',
                    userauth=userauth,
                    projtype_name=projtype.name,
                    prjname=prjname)
Example #5
0
        def wrapper(*a, **ka):
            pname = [ka.get(p, p)
                     for p in page_name] + [METHODS.get(request.method, "-")]
            prjname = ka.get("prjname")
            lngname = ka.get("lngname")
            userauth = get_session()

            # We must read all uploaded content before returning a response.
            # Otherwise the connection may be closed by the server and the client aborts.
            for f in request.files:
                pass

            if userauth is None:
                # No authentication backend.
                abort(403, "Access denied")
            elif userauth.may_access(pname, prjname, lngname):
                # Access granted.
                return func(userauth, *a, **ka)
            elif not userauth.is_auth:
                # Not logged in.
                redirect("/login", redirect=request.path)
            elif prjname is not None and prjname in config.cache.projects:
                # Valid user, but insufficient permissions: Go to project page.
                redirect("/project/<prjname>",
                         prjname=prjname.lower(),
                         message="Access denied")
            else:
                # Valid user, no project context: Go to project list.
                redirect("/projects", message="Access denied")
            return
Example #6
0
def delete_submit(userauth, prjname, lngname):
    pmd = config.cache.get_pmd(prjname)
    if pmd is None:
        abort(404, "Project does not exist")
        return

    if pmd.storage_type == config.STORAGE_SEPARATE_LANGUAGES:
        abort(
            404,
            "Cannot delete a language, ask the system administrator to remove the language file"
        )
        return

    pdata = pmd.pdata
    lng = pdata.languages.get(lngname)
    if lng is None:
        abort(404, "Language does not exist in the project")
        return

    if pdata.base_language == lngname:
        abort(404, "Cannot delete base language!")
        return

    del pdata.languages[lngname]
    pdata.set_modified()
    if lngname in pdata.statistics:
        del pdata.statistics[lngname]
    if lngname in pmd.overview:
        del pmd.overview[lngname]

    config.process_project_changes(pdata)  # Update changes of the project.
    config.cache.save_pmd(pmd)

    msg = "Language " + lngname + " is deleted"
    redirect("/project/<prjname>", prjname=prjname, message=msg)
    return
Example #7
0
def fix_string_page(pmd, prjname, lngname, message):
    """
    Jump to a string edit page to fix a string.

    @param pmd: Meta data of the project.
    @type  pmd: L{ProjectMetaData}

    @param prjname: Internal project identifier.
    @type  prjname: C{str}

    @param lngname: Language to select from.
    @type  lngname: C{str}

    @param message: Message to display, if any.
    @type  message: C{str} or C{None}
    """
    sname = find_string(pmd, lngname)
    if sname is None:
        if message is None:
            message = "All strings are up-to-date, perhaps some translations need rewording?"
        redirect("/translation/<prjname>/<lngname>",
                 prjname=prjname,
                 lngname=lngname,
                 message=message)
        return

    if message is None:
        redirect("/string/<prjname>/<lngname>/<sname>",
                 prjname=prjname,
                 lngname=lngname,
                 sname=sname)
    else:
        redirect("/string/<prjname>/<lngname>/<sname>",
                 prjname=prjname,
                 lngname=lngname,
                 sname=sname,
                 message=message)
    return
Example #8
0
def handle_upload(userauth, pmd, projname, langfile, override, is_base,
                  lng_data):
    """
    Process the upload.

    @param userauth: User authentication.
    @type  userauth: L{UserAuthentication}

    @param pmd: Project meta data.
    @type  pmd: L{ProjectMetaData}

    @param projname: Project name.
    @type  projname: C{str}

    @param langfile: Language file to load if available.
    @type  langfile: C{file} or C{None}

    @param override: Override existing text.
    @type  override: C{bool}

    @param lng_data: Used language, if provided.
    @type  lng_data: L{LanguageData} or C{None}
    """
    pdata = pmd.pdata

    # Missing language file in the upload.
    if not langfile or not langfile.file:
        abort(404, "Missing language file")
        return

    base_language = pdata.get_base_language()

    # Cannot download a translation without base language.
    if not is_base and base_language is None:
        abort(404, "Project has no base language")
        return

    # Parse language file, and report any errors.
    ng_data = language_file.load_language_file(pdata.projtype, langfile.file,
                                               config.cfg.language_file_size,
                                               lng_data)
    if len(ng_data.errors) > 0:
        return template('upload_errors',
                        userauth=userauth,
                        pmd=pmd,
                        errors=ng_data.errors)

    # Is the language allowed?
    if not pdata.projtype.allow_language(ng_data.language_data):
        abort(
            404, "Language \"{}\" may not be uploaded".format(
                ng_data.language_data.isocode))
        return

    stamp = data.make_stamp()

    lng = pdata.languages.get(ng_data.language_data.isocode)
    if lng is None:  # New language being added.
        result = add_new_language(ng_data, pdata, is_base)
        if not result[0]:
            abort(404, result[0])
            return
        lng = result[1]
        if is_base and base_language is None: base_language = lng

    if is_base:
        if base_language is not None and base_language != lng:
            abort(404, "Cannot change a translation to a base language")
            return

        # Add strings as changes.
        for sv in ng_data.strings:
            sv.text = language_file.sanitize_text(sv.text)
            chgs = base_language.changes.get(sv.name)
            chg = get_blng_change(sv, base_language)
            if chg is None:  # New change.
                base_text = data.Text(sv.text, sv.case, stamp)
                chg = data.Change(sv.name, sv.case, base_text, None, stamp,
                                  userauth.name, True)
                if chgs is None:
                    chgs = [chg]
                    base_language.changes[sv.name] = chgs
                else:
                    chgs.append(chg)
            else:
                # Only way to update a base language is by upload, no need for override check.
                chg.stamp = stamp
                chg.user = userauth.name

            for c in chgs:
                c.last_upload = (c == chg)

        # Update language properties as well.
        copy_lng_properties(pdata.projtype, ng_data, base_language)

        pdata.skeleton = ng_data.skeleton  # Use the new skeleton file.
        pdata.flush_related_cache()  # Drop the related strings cache.
        pdata.set_modified()

        # Push the new set of string-names to all languages (this includes the base language).
        str_names = set(sv.name for sv in ng_data.strings)
        for lang in pdata.languages.values():
            lng_modified = False
            not_seen = str_names.copy()
            for sn in list(lang.changes.keys()):
                not_seen.discard(sn)
                if sn in str_names: continue  # Name is kept.
                del lang.changes[sn]  # Old string, delete
                lng_modified = True
            for sn in not_seen:
                # Missing translation are not saved, so no set_modified here.
                lang.changes[sn] = []

            if lng_modified:
                lang.set_modified()

    else:
        # Not a base language -> it is a translation.
        if base_language is not None and base_language == lng:
            abort(404, "Cannot change a base language to a translation")
            return

        for sv in ng_data.strings:
            sv.text = language_file.sanitize_text(sv.text)

            # Find base language string for 'sv'.
            bchgs = base_language.changes.get(sv.name)
            if bchgs is None:
                continue  # Translation has a string not in the base language
            bchg = data.get_newest_change(bchgs, '')
            if bchg is None: continue  # Nothing to base against.
            base_text = bchg.base_text

            chgs = lng.changes.get(sv.name)
            chg = get_lng_change(sv, lng, base_text)
            if chg is None:  # It's a new text or new case.
                lng_text = data.Text(sv.text, sv.case, stamp)
                chg = data.Change(sv.name, sv.case, base_text, lng_text, stamp,
                                  userauth.name, True)
                if chgs is None:
                    lng.changes[sv.name] = [chg]
                else:
                    for c in chgs:
                        c.last_upload = False
                    chgs.append(chg)
            elif override:  # Override existing entry.
                chg.stamp = stamp
                chg.user = userauth.name
                for c in chgs:
                    c.last_upload = (c == chg)

        # Update language properties as well.
        copy_lng_properties(pdata.projtype, ng_data, lng)
        lng.set_modified()

    config.cache.save_pmd(pmd)

    if is_base:
        pmd.create_statistics(None)  # Update all languages.
    else:
        pmd.create_statistics(lng)

    message = "Successfully uploaded language '" + lng.name + "' " + utils.get_datetime_now_formatted(
    )
    redirect("/project/<prjname>", prjname=projname, message=message)
Example #9
0
def logout():
    stop_session()
    utils.redirect("/", message="Logout successful!")
Example #10
0
def make_language_post(userauth, prjname, lngname):
    """
    Create the requested language.

    @param prjname: Name of the project.
    @type  prjname: C{str}

    @param lngname: Name of the language to create in the project.
    @type  lngname: C{str}
    """
    pmd = config.cache.get_pmd(prjname)
    if pmd is None:
        abort(404, "Project does not exist")
        return

    lng_def = get_language(lngname)
    if lng_def is None:
        msg = "No language found that can be created"
        abort(404, msg)
        return

    pdata = pmd.pdata
    if lng_def.isocode in pdata.languages:
        abort(404, 'Language "{}" already exists'.format(lng_def.isocode))
        return

    projtype = pdata.projtype
    if not projtype.allow_language(lng_def):
        msg = 'Language "{}" may not be created in this project'.format(
            lng_def.isocode)
        abort(404, msg)
        return

    # Create the language.
    lng = data.Language(lng_def.isocode)
    lng.grflangid = lng_def.grflangid
    lng.plural = lng_def.plural

    if projtype.allow_gender:
        lng.gender = lng_def.gender
    else:
        lng.gender = []

    if projtype.allow_case:
        lng.case = lng_def.case
    else:
        lng.case = [""]

    pdata.languages[lng.name] = lng
    pdata.set_modified()
    lng.set_modified()

    config.cache.save_pmd(pmd)
    pmd.create_statistics(lng)

    msg = "Successfully created language '" + lng.name + "' " + utils.get_datetime_now_formatted(
    )
    redirect("/translation/<prjname>/<lngname>",
             prjname=prjname,
             lngname=lng.name,
             message=msg)
    return