예제 #1
0
def check_user(site: str, user: str, sig: str = "") -> UserCheck:
    validate_username(user)
    errors: Set[Result] = set()
    failure = None
    html_sig = ""
    if site not in datasources.get_sitematrix():
        flask.abort(404)

    sitedata = datasources.get_site_data(site)
    dbname = sitedata.dbname
    user = (user[0].upper() + user[1:]).replace("_", " ")

    if not sig:
        # signature not supplied, get data from database
        user_props = datasources.get_user_properties(user, dbname)
        logger.debug(user_props)

        if not user_props.nickname:
            # user does not exist or uses default sig
            if not datasources.check_user_exists(user, sitedata):
                # user does not exist
                errors.add(WebAppMessage.USER_DOES_NOT_EXIST)
                failure = True
            else:
                # user exists but uses default signature
                errors.add(WebAppMessage.DEFAULT_SIG)
                sig = get_default_sig(site, user, user)
                failure = False
        elif not user_props.fancysig:
            # user exists but uses non-fancy sig with nickname
            errors.add(WebAppMessage.SIG_NOT_FANCY)
            sig = get_default_sig(site, user, user_props.nickname)
            failure = False
        else:
            # user exists and has custom fancy sig, check it
            sig = user_props.nickname

    if failure is None:
        # OK so far, actually check the signature
        errors = cast(Set[Result], sigprobs.check_sig(user, sig, sitedata,
                                                      site))
        html_sig = get_rendered_sig(site,
                                    sigprobs.evaluate_subst(sig, sitedata))
        logger.debug(errors)

    if not errors:
        # check returned no errors
        errors.add(WebAppMessage.NO_ERRORS)
        failure = False

    data = UserCheck(
        site=site,
        username=user,
        errors=list(errors),
        signature=sig,
        failure=failure,
        html_sig=html_sig,
    )
    return data
예제 #2
0
def sitedata(site):
    data = datasources.get_site_data(site["domain"])
    return data
예제 #3
0
def main(
    hostname: str,
    lastedit: Optional[str] = None,
    days: int = 30,
    checks: datatypes.Checks = datatypes.Checks.DEFAULT,
    data: Optional[Union[Dict[str, str], List[str]]] = None,
) -> Optional[Dict]:
    """Site-level report mode: Iterate over signatures and check for errors"""
    logger.info(f"Processing signatures for {hostname}")
    total = 0

    sitedata = datasources.get_site_data(hostname)
    dbname = sitedata.dbname

    if data is None:
        sigsource = datasources.iter_active_user_sigs(dbname, lastedit, days)
    elif isinstance(data, list):
        sigsource = datasources.iter_listed_user_sigs(data, dbname)
    elif isinstance(data, dict):
        sigsource = data.items()  # type: ignore
    else:
        raise TypeError(
            "Data is of type %s when None, list, or dict expected" % (type(data))
        )

    resultdata: Dict[str, Dict[str, Union[str, List[SigError]]]] = {}
    accumulate = {}
    for user, sig in sigsource:
        total += 1
        if not sig:
            continue
        try:
            errors = check_sig(
                user, sig, sitedata, hostname, checks=checks ^ Checks.LINT
            )
            if SigError.PLAIN_FANCY_SIG not in errors:
                accumulate[user] = sig
        except Exception:
            logger.error(f"Processing User:{user}: {sig}")
            raise
        if errors:
            resultdata[user] = {"signature": sig, "errors": list(errors)}
        # Batch requests to lint, since network requests are slow
        # There is probably a better way to do this with async, but
        # that's more work.
        if len(accumulate) >= 5:
            accumulate, resultdata = batch_check_lint(
                accumulate, resultdata, hostname, checks
            )

    # Catch any sigs that didn't get linted
    if accumulate:
        accumulate, resultdata = batch_check_lint(
            accumulate, resultdata, hostname, checks
        )

    # Collect stats, and generate json file
    stats = {}
    stats["total"] = len(resultdata)
    for user, line in resultdata.items():
        line["errors"] = [error.value for error in cast(List[SigError], line["errors"])]
        for error in line.get("errors", []):
            stats[error] = stats.setdefault(error, 0) + 1

    meta = {"last_update": datetime.datetime.utcnow().isoformat(), "site": hostname}
    if lastedit:
        meta["active_since"] = datetime.datetime.strptime(
            lastedit, "%Y%m%d%H%M%S"
        ).isoformat()
    else:
        meta["active_since"] = (
            datetime.datetime.utcnow() - datetime.timedelta(days=days)
        ).isoformat()

    outdata = {
        "errors": stats,
        "meta": meta,
        "sigs": {key: resultdata[key] for key in sorted(resultdata)},
    }

    return outdata