Example #1
0
def account_setconfig(req):
    if not req.user:
        return HttpResponse(status=403)
    data = json.loads(req.body.decode("utf-8"))
    if data["sync_skip_before"] and len(data["sync_skip_before"]):
        data["sync_skip_before"] = dateutil.parser.parse(
            data["sync_skip_before"])
    User.SetConfiguration(req.user, data)
    Sync.SetNextSyncIsExhaustive(req.user, True)
    return HttpResponse()
Example #2
0
def config_save(req, service):
    if not req.user:
        return HttpResponse(status=403)

    conn = User.GetConnectionRecord(req.user, service)
    if not conn:
        return HttpResponse(status=404)
    conn.SetConfiguration(json.loads(req.POST["config"]))
    Sync.SetNextSyncIsExhaustive(req.user, True) # e.g. if they opted to sync private activities.
    return HttpResponse()
Example #3
0
def config_flow_save(req, service):
    if not req.user:
        return HttpResponse(status=403)
    conns = User.GetConnectionRecordsByUser(req.user)
    if service not in [x.Service.ID for x in conns]:
        return HttpResponse(status=404)
    sourceSvc = [x for x in conns if x.Service.ID == service][0]
    #  the JS doesn't resolve the flow exceptions, it just passes in the expanded config flags for the edited service (which will override other flowexceptions)
    flowFlags = json.loads(req.POST["flowFlags"])
    for destSvc in [x for x in conns if x.Service.ID != service]:
        User.SetFlowException(req.user, sourceSvc, destSvc, destSvc.Service.ID in flowFlags["forward"], None)
    Sync.SetNextSyncIsExhaustive(req.user, True)  # to pick up any activities left behind
    return HttpResponse()
Example #4
0
    def ConnectService(user, serviceRecord):
        from tapiriik.services import Service, UserExceptionType
        existingUser = db.users.find_one({
            "_id": {
                '$ne': ObjectId(user["_id"])
            },
            "ConnectedServices.ID":
            ObjectId(serviceRecord._id)
        })
        if "ConnectedServices" not in user:
            user["ConnectedServices"] = []
        delta = False
        if existingUser is not None:
            # merge merge merge

            # Don't let the user end up with two services of the same type, ever
            # It's not fully supported, plus it's caused all sorts of trauma in the past.
            # Note that this will discard the new serviceRecord connection if an existing one exists on the other account
            # ...which isn't the end of the world, compared to screwing around asking the user which they wanted to keep.
            for to_merge_service in existingUser["ConnectedServices"]:
                if len([
                        x for x in user["ConnectedServices"]
                        if x["Service"] == to_merge_service["Service"]
                ]) == 0:
                    user["ConnectedServices"].append(to_merge_service)

            # There's got to be some 1-liner to do this merge
            if "Payments" in existingUser:
                if "Payments" not in user:
                    user["Payments"] = []
                user["Payments"] += existingUser["Payments"]
            if "Promos" in existingUser:
                if "Promos" not in user:
                    user["Promos"] = []
                user["Promos"] += existingUser["Promos"]
            if "ExternalPayments" in existingUser:
                if "ExternalPayments" not in user:
                    user["ExternalPayments"] = []
                user["ExternalPayments"] += existingUser["ExternalPayments"]
            if "FlowExceptions" in existingUser:
                if "FlowExceptions" not in user:
                    user["FlowExceptions"] = []
                user["FlowExceptions"] += existingUser["FlowExceptions"]
            user["Email"] = user["Email"] if "Email" in user and user[
                "Email"] is not None else (
                    existingUser["Email"] if "Email" in existingUser else None)
            user["NonblockingSyncErrorCount"] = (
                user["NonblockingSyncErrorCount"]
                if "NonblockingSyncErrorCount" in user
                and user["NonblockingSyncErrorCount"] is not None else 0
            ) + (existingUser["NonblockingSyncErrorCount"]
                 if "NonblockingSyncErrorCount" in existingUser and
                 existingUser["NonblockingSyncErrorCount"] is not None else 0)
            user["BlockingSyncErrorCount"] = (
                user["BlockingSyncErrorCount"] if "BlockingSyncErrorCount"
                in user and user["BlockingSyncErrorCount"] is not None else 0
            ) + (existingUser["BlockingSyncErrorCount"]
                 if "BlockingSyncErrorCount" in existingUser
                 and existingUser["BlockingSyncErrorCount"] is not None else 0)
            user["SyncExclusionCount"] = (
                user["SyncExclusionCount"] if "SyncExclusionCount" in user
                and user["SyncExclusionCount"] is not None else 0) + (
                    existingUser["SyncExclusionCount"]
                    if "SyncExclusionCount" in existingUser
                    and existingUser["SyncExclusionCount"] is not None else 0)
            user[
                "Created"] = user["Created"] if user["Created"] < existingUser[
                    "Created"] else existingUser["Created"]
            if "AncestorAccounts" not in user:
                user["AncestorAccounts"] = []
            user["AncestorAccounts"] += existingUser["AncestorAccounts"] if "AncestorAccounts" in existingUser else []
            user["AncestorAccounts"] += [existingUser["_id"]]
            user["Timezone"] = user["Timezone"] if "Timezone" in user and user[
                "Timezone"] else (existingUser["Timezone"]
                                  if "Timezone" in existingUser else None)
            user["CreationIP"] = user[
                "CreationIP"] if "CreationIP" in user and user[
                    "CreationIP"] else (existingUser["CreationIP"] if
                                        "CreationIP" in existingUser else None)
            existing_config = existingUser[
                "Config"] if "Config" in existingUser else {}
            existing_config.update(user["Config"] if "Config" in user else {})
            user["Config"] = existing_config
            delta = True
            db.users.remove({"_id": existingUser["_id"]})
        else:
            if serviceRecord._id not in [
                    x["ID"] for x in user["ConnectedServices"]
            ]:
                # we might be connecting a second account for the same service
                for duplicateConn in [
                        x for x in user["ConnectedServices"]
                        if x["Service"] == serviceRecord.Service.ID
                ]:
                    dupeRecord = User.GetConnectionRecord(
                        user, serviceRecord.Service.ID
                    )  # this'll just pick the first connection of type, but we repeat the right # of times anyways
                    Service.DeleteServiceRecord(dupeRecord)
                    # We used to call DisconnectService() here, but the results of that call were getting overwritten, which was unfortunate.
                    user["ConnectedServices"] = [
                        x for x in user["ConnectedServices"]
                        if x["Service"] != serviceRecord.Service.ID
                    ]

                user["ConnectedServices"].append({
                    "Service":
                    serviceRecord.Service.ID,
                    "ID":
                    serviceRecord._id
                })
                delta = True

        db.users.update({"_id": user["_id"]}, user)
        if delta or (
                hasattr(serviceRecord, "SyncErrors")
                and len(serviceRecord.SyncErrors) > 0
        ):  # also schedule an immediate sync if there is an outstanding error (i.e. user reconnected)
            db.connections.update(
                {"_id": serviceRecord._id}, {
                    "$pull": {
                        "SyncErrors": {
                            "UserException.Type":
                            UserExceptionType.Authorization
                        }
                    }
                }
            )  # Pull all auth-related errors from the service so they don't continue to see them while the sync completes.
            db.connections.update(
                {"_id": serviceRecord._id}, {
                    "$pull": {
                        "SyncErrors": {
                            "UserException.Type":
                            UserExceptionType.RenewPassword
                        }
                    }
                }
            )  # Pull all auth-related errors from the service so they don't continue to see them while the sync completes.
            Sync.SetNextSyncIsExhaustive(
                user, True
            )  # exhaustive, so it'll pick up activities from newly added services / ones lost during an error
            if hasattr(serviceRecord,
                       "SyncErrors") and len(serviceRecord.SyncErrors) > 0:
                Sync.ScheduleImmediateSync(user)
Example #5
0
def diag_user(req, user):
    try:
        userRec = db.users.find_one({"_id": ObjectId(user)})
    except:
        userRec = None
    if not userRec:
        searchOpts = [{"Payments.Txn": user}, {"Payments.Email": user}]
        try:
            searchOpts.append({"AncestorAccounts": ObjectId(user)})
            searchOpts.append({"ConnectedServices.ID": ObjectId(user)})
        except:
            pass  # Invalid format for ObjectId
        userRec = db.users.find_one({"$or": searchOpts})
        if not userRec:
            searchOpts = [{"ExternalID": user}]
            try:
                searchOpts.append({"ExternalID": int(user)})
            except:
                pass  # Not an int
            svcRec = db.connections.find_one({"$or": searchOpts})
            if svcRec:
                userRec = db.users.find_one(
                    {"ConnectedServices.ID": svcRec["_id"]})
        if userRec:
            return redirect("diagnostics_user", user=userRec["_id"])
    if not userRec:
        return render(req, "diag/error_user_not_found.html")
    delta = True  # Easier to set this to false in the one no-change case.
    if "sync" in req.POST:
        Sync.ScheduleImmediateSync(userRec, req.POST["sync"] == "Full")
    elif "unlock" in req.POST:
        db.users.update({"_id": ObjectId(user)},
                        {"$unset": {
                            "SynchronizationWorker": None
                        }})
    elif "lock" in req.POST:
        db.users.update({"_id": ObjectId(user)},
                        {"$set": {
                            "SynchronizationWorker": 1
                        }})
    elif "hostrestrict" in req.POST:
        host = req.POST["host"]
        if host:
            db.users.update({"_id": ObjectId(user)},
                            {"$set": {
                                "SynchronizationHostRestriction": host
                            }})
        else:
            db.users.update(
                {"_id": ObjectId(user)},
                {"$unset": {
                    "SynchronizationHostRestriction": None
                }})
    elif "substitute" in req.POST:
        req.session["substituteUserid"] = user
        return redirect("dashboard")
    elif "svc_setauth" in req.POST and len(req.POST["authdetails"]):
        db.connections.update(
            {"_id": ObjectId(req.POST["id"])},
            {"$set": {
                "Authorization": json.loads(req.POST["authdetails"])
            }})
    elif "svc_unlink" in req.POST:
        from tapiriik.services import Service
        from tapiriik.auth import User
        svcRec = Service.GetServiceRecordByID(req.POST["id"])
        try:
            Service.DeleteServiceRecord(svcRec)
        except:
            pass
        try:
            User.DisconnectService(svcRec)
        except:
            pass
    elif "svc_marksync" in req.POST:
        db.connections.update(
            {"_id": ObjectId(req.POST["id"])},
            {"$addToSet": {
                "SynchronizedActivities": req.POST["uid"]
            }},
            multi=False)
    elif "svc_clearexc" in req.POST:
        db.connections.update({"_id": ObjectId(req.POST["id"])},
                              {"$unset": {
                                  "ExcludedActivities": 1
                              }})
    elif "svc_clearacts" in req.POST:
        db.connections.update({"_id": ObjectId(req.POST["id"])},
                              {"$unset": {
                                  "SynchronizedActivities": 1
                              }})
        Sync.SetNextSyncIsExhaustive(userRec, True)
    else:
        delta = False

    if delta:
        return redirect("diagnostics_user", user=user)
    return render(req, "diag/user.html", {"user": userRec})
Example #6
0
def diag_user(req, user):
    try:
        userRec = db.users.find_one({"_id": ObjectId(user)})
    except:
        userRec = None
    if not userRec:
        searchOpts = [{"Payments.Txn": user}, {"Payments.Email": user}]
        try:
            searchOpts.append({"AncestorAccounts": ObjectId(user)})
            searchOpts.append({"ConnectedServices.ID": ObjectId(user)})
        except:
            pass  # Invalid format for ObjectId
        userRec = db.users.find_one({"$or": searchOpts})
        if not userRec:
            searchOpts = [{"ExternalID": user}]
            try:
                searchOpts.append({"ExternalID": int(user)})
            except:
                pass  # Not an int
            svcRec = db.connections.find_one({"$or": searchOpts})
            if svcRec:
                userRec = db.users.find_one(
                    {"ConnectedServices.ID": svcRec["_id"]})
        if userRec:
            return redirect("diagnostics_user", user=userRec["_id"])
    if not userRec:
        return render(req, "diag/error_user_not_found.html")
    delta = True  # Easier to set this to false in the one no-change case.
    if "sync" in req.POST:
        Sync.ScheduleImmediateSync(userRec, req.POST["sync"] == "Full")
    elif "unlock" in req.POST:
        db.users.update({"_id": ObjectId(user)},
                        {"$unset": {
                            "SynchronizationWorker": None
                        }})
    elif "lock" in req.POST:
        db.users.update({"_id": ObjectId(user)},
                        {"$set": {
                            "SynchronizationWorker": 1
                        }})
    elif "requeue" in req.POST:
        db.users.update({"_id": ObjectId(user)},
                        {"$unset": {
                            "QueuedAt": None
                        }})
    elif "hostrestrict" in req.POST:
        host = req.POST["host"]
        if host:
            db.users.update({"_id": ObjectId(user)},
                            {"$set": {
                                "SynchronizationHostRestriction": host
                            }})
        else:
            db.users.update(
                {"_id": ObjectId(user)},
                {"$unset": {
                    "SynchronizationHostRestriction": None
                }})
    elif "substitute" in req.POST:
        req.session["substituteUserid"] = user
        return redirect("dashboard")
    elif "svc_setauth" in req.POST and len(req.POST["authdetails"]):
        db.connections.update(
            {"_id": ObjectId(req.POST["id"])},
            {"$set": {
                "Authorization": json.loads(req.POST["authdetails"])
            }})
    elif "svc_setconfig" in req.POST and len(req.POST["config"]):
        db.connections.update(
            {"_id": ObjectId(req.POST["id"])},
            {"$set": {
                "Config": json.loads(req.POST["config"])
            }})
    elif "svc_unlink" in req.POST:
        from tapiriik.services import Service
        from tapiriik.auth import User
        svcRec = Service.GetServiceRecordByID(req.POST["id"])
        try:
            Service.DeleteServiceRecord(svcRec)
        except:
            pass
        try:
            User.DisconnectService(svcRec)
        except:
            pass
    elif "svc_marksync" in req.POST:
        db.connections.update(
            {"_id": ObjectId(req.POST["id"])},
            {"$addToSet": {
                "SynchronizedActivities": req.POST["uid"]
            }},
            multi=False)
    elif "svc_clearexc" in req.POST:
        db.connections.update({"_id": ObjectId(req.POST["id"])},
                              {"$unset": {
                                  "ExcludedActivities": 1
                              }})
    elif "svc_clearacts" in req.POST:
        db.connections.update({"_id": ObjectId(req.POST["id"])},
                              {"$unset": {
                                  "SynchronizedActivities": 1
                              }})
        Sync.SetNextSyncIsExhaustive(userRec, True)
    elif "svc_toggle_poll_sub" in req.POST:
        from tapiriik.services import Service
        svcRec = Service.GetServiceRecordByID(req.POST["id"])
        svcRec.SetPartialSyncTriggerSubscriptionState(
            not svcRec.PartialSyncTriggerSubscribed)
    elif "svc_toggle_poll_trigger" in req.POST:
        from tapiriik.services import Service
        svcRec = Service.GetServiceRecordByID(req.POST["id"])
        db.connections.update({"_id": ObjectId(req.POST["id"])}, {
            "$set": {
                "TriggerPartialSync":
                not getattr(svcRec, "TriggerPartialSync", False)
            }
        })
    elif "svc_tryagain" in req.POST:
        from tapiriik.services import Service
        svcRec = Service.GetServiceRecordByID(req.POST["id"])
        db.connections.update({"_id": ObjectId(req.POST["id"])},
                              {"$pull": {
                                  "SyncErrors": {
                                      "Scope": "activity"
                                  }
                              }})
        act_recs = db.activity_records.find_one({"UserID": ObjectId(user)})
        for act in act_recs["Activities"]:
            if "FailureCounts" in act and svcRec.Service.ID in act[
                    "FailureCounts"]:
                del act["FailureCounts"][svcRec.Service.ID]
        db.activity_records.save(act_recs)
    else:
        delta = False

    if delta:
        return redirect("diagnostics_user", user=user)
    return render(req, "diag/user.html", {"diag_user": userRec})
Example #7
0
    def ConnectService(user, serviceRecord):
        from tapiriik.services import Service, UserExceptionType
        existingUser = db.users.find_one({
            "_id": {
                '$ne': ObjectId(user["_id"])
            },
            "ConnectedServices.ID":
            ObjectId(serviceRecord._id)
        })
        if "ConnectedServices" not in user:
            user["ConnectedServices"] = []
        delta = False
        if existingUser is not None:
            # merge merge merge
            user["ConnectedServices"] += existingUser["ConnectedServices"]
            if "Payments" in existingUser:
                if "Payments" not in user:
                    user["Payments"] = []
                user["Payments"] += existingUser["Payments"]
            if "FlowExceptions" in existingUser:
                if "FlowExceptions" not in user:
                    user["FlowExceptions"] = []
                user["FlowExceptions"] += existingUser["FlowExceptions"]
            user["Email"] = user["Email"] if "Email" in user and user[
                "Email"] is not None else (
                    existingUser["Email"] if "Email" in existingUser else None)
            user["NonblockingSyncErrorCount"] = (
                user["NonblockingSyncErrorCount"]
                if "NonblockingSyncErrorCount" in user
                and user["NonblockingSyncErrorCount"] is not None else 0
            ) + (existingUser["NonblockingSyncErrorCount"]
                 if "NonblockingSyncErrorCount" in existingUser and
                 existingUser["NonblockingSyncErrorCount"] is not None else 0)
            user["BlockingSyncErrorCount"] = (
                user["BlockingSyncErrorCount"] if "BlockingSyncErrorCount"
                in user and user["BlockingSyncErrorCount"] is not None else 0
            ) + (existingUser["BlockingSyncErrorCount"]
                 if "BlockingSyncErrorCount" in existingUser
                 and existingUser["BlockingSyncErrorCount"] is not None else 0)
            user["SyncExclusionCount"] = (
                user["SyncExclusionCount"] if "SyncExclusionCount" in user
                and user["SyncExclusionCount"] is not None else 0) + (
                    existingUser["SyncExclusionCount"]
                    if "SyncExclusionCount" in existingUser
                    and existingUser["SyncExclusionCount"] is not None else 0)
            user[
                "Created"] = user["Created"] if user["Created"] < existingUser[
                    "Created"] else existingUser["Created"]
            if "AncestorAccounts" not in user:
                user["AncestorAccounts"] = []
            user["AncestorAccounts"] += existingUser["AncestorAccounts"] if "AncestorAccounts" in existingUser else []
            user["AncestorAccounts"] += [existingUser["_id"]]
            user["Timezone"] = user["Timezone"] if user[
                "Timezone"] else existingUser["Timezone"]
            delta = True
            db.users.remove({"_id": existingUser["_id"]})
        else:
            if serviceRecord._id not in [
                    x["ID"] for x in user["ConnectedServices"]
            ]:
                # we might be connecting a second account for the same service
                for duplicateConn in [
                        x for x in user["ConnectedServices"]
                        if x["Service"] == serviceRecord.Service.ID
                ]:
                    dupeRecord = User.GetConnectionRecord(
                        user, serviceRecord.Service.ID
                    )  # this'll just pick the first connection of type, but we repeat the right # of times anyways
                    Service.DeleteServiceRecord(dupeRecord)
                    # We used to call DisconnectService() here, but the results of that call were getting overwritten, which was unfortunate.
                    user["ConnectedServices"] = [
                        x for x in user["ConnectedServices"]
                        if x["Service"] != serviceRecord.Service.ID
                    ]

                user["ConnectedServices"].append({
                    "Service":
                    serviceRecord.Service.ID,
                    "ID":
                    serviceRecord._id
                })
                delta = True

        db.users.update({"_id": user["_id"]}, user)
        if delta or (
                hasattr(serviceRecord, "SyncErrors")
                and len(serviceRecord.SyncErrors) > 0
        ):  # also schedule an immediate sync if there is an outstanding error (i.e. user reconnected)
            db.connections.update(
                {"_id": serviceRecord._id}, {
                    "$pull": {
                        "SyncErrors": {
                            "UserException.Type":
                            UserExceptionType.Authorization
                        }
                    }
                }
            )  # Pull all auth-related errors from the service so they don't continue to see them while the sync completes.
            Sync.SetNextSyncIsExhaustive(
                user, True
            )  # exhaustive, so it'll pick up activities from newly added services / ones lost during an error
            if hasattr(serviceRecord,
                       "SyncErrors") and len(serviceRecord.SyncErrors) > 0:
                Sync.ScheduleImmediateSync(user)
Example #8
0
def diag_user(req, user):
    userRec = db.users.find_one({"_id": ObjectId(user)})
    if not userRec:
        userRec = db.users.find_one({"AncestorAccounts": ObjectId(user)})
        if userRec:
            return redirect("diagnostics_user", user=userRec["_id"])
    if not userRec:
        return render(req, "diag/error_user_not_found.html")
    delta = False
    if "sync" in req.POST:
        Sync.ScheduleImmediateSync(userRec, req.POST["sync"] == "Full")
        delta = True
    elif "unlock" in req.POST:
        db.users.update({"_id": ObjectId(user)},
                        {"$unset": {
                            "SynchronizationWorker": None
                        }})
        delta = True
    elif "lock" in req.POST:
        db.users.update({"_id": ObjectId(user)},
                        {"$set": {
                            "SynchronizationWorker": 1
                        }})
        delta = True
    elif "substitute" in req.POST:
        req.session["substituteUserid"] = user
        return redirect("dashboard")
    elif "svc_setauth" in req.POST and len(req.POST["authdetails"]):
        db.connections.update(
            {"_id": ObjectId(req.POST["id"])},
            {"$set": {
                "Authorization": json.loads(req.POST["authdetails"])
            }})
        delta = True
    elif "svc_unlink" in req.POST:
        from tapiriik.services import Service
        from tapiriik.auth import User
        svcRec = Service.GetServiceRecordByID(req.POST["id"])
        try:
            Service.DeleteServiceRecord(svcRec)
        except:
            pass
        try:
            User.DisconnectService(svcRec)
        except:
            pass
        delta = True
    elif "svc_marksync" in req.POST:
        from tapiriik.services import Service
        from tapiriik.auth import User
        db.connections.update(
            {"_id": ObjectId(req.POST["id"])},
            {"$addToSet": {
                "SynchronizedActivities": req.POST["uid"]
            }},
            multi=False)
        delta = True
    elif "svc_clearexc" in req.POST:
        from tapiriik.services import Service
        from tapiriik.auth import User
        db.connections.update({"_id": ObjectId(req.POST["id"])},
                              {"$unset": {
                                  "ExcludedActivities": 1
                              }})
        delta = True
    elif "svc_clearacts" in req.POST:
        from tapiriik.services import Service
        from tapiriik.auth import User
        db.connections.update({"_id": ObjectId(req.POST["id"])},
                              {"$unset": {
                                  "SynchronizedActivities": 1
                              }})
        Sync.SetNextSyncIsExhaustive(userRec, True)
        delta = True

    if delta:
        return redirect("diagnostics_user", user=user)
    return render(req, "diag/user.html", {"user": userRec})