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)
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")
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)
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)
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
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
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
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)
def logout(): stop_session() utils.redirect("/", message="Logout successful!")
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