예제 #1
0
def fetchtl():
    """ Return the requested timeline and note the fetch. """
    try:
        tlid = dbacc.reqarg("tlid", "dbid")
        if tlid:
            tl = dbacc.cfbk("Timeline", "dsId", str(tlid), required=True)
        else:
            slug = dbacc.reqarg("slug", "string")
            if not slug:
                slug = "default"
            slug = slug.lower()  # in case someone camelcased the url.
            tl = dbacc.cfbk("Timeline", "slug", slug, required=True)
        tls = contained_timelines(tl)
        # Note the timeline was fetched for daily stats tracking
        det = {
            "referer": flask.request.headers.get("Referer", ""),
            "useragent": flask.request.headers.get("User-Agent", ""),
            "tlid": tl["dsId"],
            "tlname": tl["name"],
            "uid": dbacc.reqarg("uid", "dbid")
        }
        dcd = {
            "dsType": "DayCount",
            "tstamp": dbacc.timestamp(),
            "rtype": "tlfetch",
            "detail": json.dumps(det)
        }
        dbacc.write_entity(dcd)
    except ValueError as e:
        return util.serve_value_error(e)
    return util.respJSON(tls)
예제 #2
0
def authenticate():
    emaddr = dbacc.reqarg("an", "AppUser.email")
    if not emaddr:
        emaddr = dbacc.reqarg("email", "AppUser.email")
    if not emaddr:
        raise ValueError("'an' or 'email' parameter required")
    emaddr = normalize_email(emaddr)
    appuser = dbacc.cfbk("AppUser", "email", emaddr)
    if not appuser:
        raise ValueError(emaddr + " not found")
    dbacc.entcache.cache_put(appuser)  # will likely reference again soon
    reqtok = dbacc.reqarg("at", "string")
    if not reqtok:
        password = dbacc.reqarg("password", "string")
        if not password:
            raise ValueError("Access token or password required")
        phash = make_password_hash(emaddr, password, appuser["created"])
        if phash == appuser["phash"]:  # authenticated, rebuild token
            reqtok = token_for_user(appuser)
        else:  # failing now due to lack of token, log for analysis if needed
            logging.info(appuser["email"] + " password hash did not match")
            logging.info("  AppUser[\"phash\"]: " + appuser["phash"])
            logging.info("      Server phash: " + phash)
    srvtok = token_for_user(appuser)
    if reqtok != srvtok:
        logging.info(appuser["email"] + " authenticated token did not match")
        logging.info("  reqtok: " + reqtok)
        logging.info("  srvtok: " + srvtok)
        raise ValueError("Wrong password")
    return appuser, srvtok
예제 #3
0
def upldpic():
    """ Form submit and monitoring for uploading a point pic. """
    # flask.request.method always returns "GET", so check for file input.
    picfile = flask.request.files.get("picfilein")
    if not picfile:
        logging.info("upldpic ready for upload")
        return util.respond("Ready", mimetype="text/plain")
    try:
        appuser, _ = util.authenticate()
        ptid = dbacc.reqarg("ptid", "dbid", required=True)
        pt = dbacc.cfbk("Point", "dsId", ptid, required=True)
        logging.info(appuser["email"] + " upldpic Point " + str(ptid))
        if not appuser["dsId"] in util.csv_to_list(pt["editors"]):
            raise ValueError("Not authorized to edit this point")
        img = Image.open(picfile)
        img = ImageOps.exif_transpose(img)  # correct vertical orientation
        sizemaxdims = 400, 400  # max allowed width/height for thumbnail resize
        img.thumbnail(sizemaxdims)  # modify, preserving aspect ratio
        bbuf = io.BytesIO()  # file-like object for save
        img.save(bbuf, format="PNG")
        pt["pic"] = base64.b64encode(bbuf.getvalue())
        pt = dbacc.write_entity(pt, pt["modified"])
    except ValueError as e:
        logging.info("upldpic Point " + str(ptid) + ": " + str(e))
        return util.serve_value_error(e)
    return util.respond("Done: " + pt["modified"], mimetype="text/plain")
예제 #4
0
def update_prebuilt(tldat, tldb):
    lpx = "update_prebuilt Timeline " + str(tldat.get("dsId", "new") + " ")
    # make a reference dict out of whatever existing preb is available
    preb = tldat.get("preb")
    if not preb and tldb:
        preb = tldb.get("preb")
    preb = preb or "[]"
    preb = util.load_json_or_default(preb, [])
    ptd = {k["dsId"]: k for k in preb}
    # update any ptd entries that were modified since last timeline save
    if tldb and tldat.get("cids"):
        logging.info(lpx + "fetching points updated since last timeline save")
        where = ("WHERE modified > \"" + tldb["modified"] + "\"" +
                 "AND dsId IN (" + tldat["cids"] + ")")
        points = dbacc.query_entity("Point", where)
        for point in points:
            ptd[point["dsId"]] = point_preb_summary(point)
    # rebuild preb, fetching points for any missing ptd entries
    logging.info(lpx + "rebuilding preb")
    preb = []
    for pid in util.csv_to_list(tldat.get("cids", "")):
        summary = ptd.get(pid)  # dict or None
        if not summary:
            point = dbacc.cfbk("Point", "dsId", pid)
            if point:
                summary = point_preb_summary(point)
        if not summary:
            logging.info(lpx + "No point info for pid " + pid)
        else:  # have summary info
            preb.append(summary)
    tldat["preb"] = json.dumps(preb)
예제 #5
0
def verify_new_email_valid(emaddr):
    # something @ something . something
    if not re.match(r"[^@]+@[^@]+\.[^@]+", emaddr):
        raise ValueError("Invalid email address: " + emaddr)
    existing = dbacc.cfbk("AppUser", "email", emaddr)
    if existing:
        raise ValueError("Email address already used")
    return emaddr
예제 #6
0
파일: import.py 프로젝트: theriex/rh
def set_point_srctls(tlid, ptidcsv):
    if ptidcsv:
        ptids = ptidcsv.split(",")
        for ptid in ptids:
            point = dbacc.cfbk("Point", "dsId", ptid)
            if point:
                point["srctl"] = tlid
                dbacc.write_entity(point, point["modified"])
예제 #7
0
파일: import.py 프로젝트: theriex/rh
def verify_db_instance(fbase, fields, fob):
    dbob = dbacc.cfbk(fob["dsType"], "importid", fob["importid"])
    if not dbob:
        for fieldname, fattrs in fields.items():
            if fattrs["pt"] == "image" and fob[fieldname]:
                imgfilename = fbase + "images/" + fob["importid"] + ".png"
                with open(imgfilename, 'rb') as imagefile:
                    bdat = imagefile.read()
                    fob[fieldname] = base64.b64encode(bdat)
        logging.info("Writing " + fob["dsType"] + fob["importid"])
        dbacc.write_entity(fob)
예제 #8
0
def supphelp():
    accurl = "Nope."
    try:
        administrator_auth()
        emaddr = dbacc.reqarg("email", "AppUser.email", required=True)
        appuser = dbacc.cfbk("AppUser", "email", emaddr)
        accurl = (site_home() + "/timeline/default?an=" +
                  urllib.parse.quote(appuser["email"]) + "&at=" +
                  token_for_user(appuser))
    except ValueError as e:
        return serve_value_error(e)
    return accurl
예제 #9
0
파일: import.py 프로젝트: theriex/rh
def convert_dbid(entity, importid):
    if not importid:
        return ""
    enti2d = imp2ds.get(entity)
    if not enti2d:
        imp2ds[entity] = {}
        enti2d = imp2ds[entity]
    dsId = enti2d.get(importid)
    if not dsId:
        refobj = dbacc.cfbk(entity, "importid", importid, required=True)
        enti2d[importid] = refobj["dsId"]
        dsId = refobj["dsId"]
    return dsId
예제 #10
0
def verify_active_user(uid, user=None):
    if not uid:
        raise ValueError("Valid uid required, received: '" + str(uid) + "'")
    users = rst["dets"]["users"]
    if not users.get(uid):
        if not user:
            user = dbacc.cfbk("AppUser", "dsId", uid, required=True)
        users[uid] = {
            "name": user["name"],
            "created": user["created"],
            "modified": user["modified"],
            "ptedits": {}
        }
예제 #11
0
def obimg():
    """ Return the associated image for the give object, or a blank 4x4. """
    # The client might make a call to get a pic for an object which might
    # not have one.  Better to return a blank than an error in that case.
    imgdat = B64ENCTRANSPARENT4X4PNG
    try:
        dsType = dbacc.reqarg("dt", "string", required=True)
        dsId = dbacc.reqarg("di", "string", required=True)
        inst = dbacc.cfbk(dsType, "dsId", dsId)
        if inst:
            picfldmap = {"Point": "pic"}
            imgdat = inst[picfldmap[dsType]]
            imgdat = base64.b64decode(imgdat)
    except ValueError as e:
        return util.serve_value_error(e)
    return util.respond(imgdat, mimetype="image/png")
예제 #12
0
def fetchobj():
    """ General purpose object retrieval, public info only. """
    oj = ""
    try:
        dsType = dbacc.reqarg("dt", "string", required=True)
        keyfld = dbacc.reqarg("ak", "string")  # alternate key
        if keyfld:
            fldval = dbacc.reqarg("kv", "string", required=True)
        else:
            keyfld = "dsId"
            fldval = dbacc.reqarg("di", "string", required=True)
        inst = dbacc.cfbk(dsType, keyfld, fldval)
        if not inst:
            raise ValueError(dsType + " " + keyfld + ": " + fldval +
                             " not found")
        oj = util.safe_JSON(inst)
    except ValueError as e:
        return util.serve_value_error(e)
    return util.respJSON("[" + oj + "]")
예제 #13
0
def verify_edit_authorization(appuser, obj):
    if not obj.get("dsType") in ["Point", "Timeline"]:
        raise ValueError("Unknown object type for edit authorization")
    if not obj.get("dsId"):
        obj["editors"] = appuser["dsId"]
        return None  # Done. Anyone may create a new Point or Timeline
    dbo = dbacc.cfbk(obj["dsType"], "dsId", obj["dsId"], required=True)
    if not util.val_in_csv(appuser["dsId"], dbo["editors"]):
        raise ValueError("Not an editor for " + obj["dsType"] + obj["dsId"])
    updeds = obj.get("editors")
    if not updeds:  # didn't pass editors info, use existing values
        obj["editors"] = dbo["editors"]
    else:  # verify editors value is ok
        if updeds != dbo["editors"]:
            owner = util.csv_to_list(dbo["editors"])[0]
            if owner != appuser["dsId"]:
                if updeds == "deleted":
                    raise ValueError("Only the owner can delete")
                raise ValueError("Only the owner may change editors")
    return dbo
예제 #14
0
def mailpwr():
    try:
        subj = "PastKey.org account password reset link"
        emaddr = dbacc.reqarg("email", "AppUser.email", required=True)
        returl = url_for_mail_message()
        body = "You asked to reset your PastKey account password.\n\n"
        user = dbacc.cfbk("AppUser", "email", emaddr)
        if user:
            logging.info("mailpwr sending access link to " + emaddr)
            body += "Use this link to access the settings for your account: "
            body += (returl + "?an=" + urllib.parse.quote(user["email"]) +
                     "&at=" + token_for_user(user) + "\n\n")
        else:
            logging.info("mailpwr no account found for " + emaddr)
            body += "You do not have an account for " + emaddr + ". "
            body += "Either you have not signed up yet, or you used "
            body += "a different email address.  To create an account "
            body += "visit " + returl + "\n\n"
        send_mail(emaddr, subj, body)
    except ValueError as e:
        return serve_value_error(e)
    return respJSON("[]")
예제 #15
0
def get_connection_service(svcname):
    cs = dbacc.cfbk("AppService", "name", svcname)
    if not cs:
        # create needed placeholder for administrators to update
        cs = dbacc.write_entity({"dsType": "AppService", "name": svcname})
    return cs
예제 #16
0
def contained_timelines(tl):
    allts = [tl]
    if tl["ctype"].startswith("Timelines"):
        for cid in tl["cids"].split(","):
            allts.append(dbacc.cfbk("Timeline", "dsId", cid, required=True))
    return allts