예제 #1
0
def sync_trigger_partial_sync_callback(req, service):
    svc = Service.FromID(service)
    if req.method == "POST":
        # if whe're using decathlon services, force resync
        # Get users ids list, depending of services
        response = svc.ExternalIDsForPartialSyncTrigger(req)

        _sync = Sync()
        # Get users _id list from external ID
        users_to_sync = _sync.getUsersIDFromExternalId(response, service)

        if not users_to_sync:
            return HttpResponse(status=401)
        else:
            for user in users_to_sync:

                # For each users, if we can sync now
                if "LastSynchronization" in user and user["LastSynchronization"] is not None and datetime.utcnow() - \
                        user["LastSynchronization"] < _sync.MinimumSyncInterval:
                    return HttpResponse(status=403)
                exhaustive = None
                if "LastSynchronization" in user and user["LastSynchronization"] is not None and datetime.utcnow() - \
                        user["LastSynchronization"] > _sync.MaximumIntervalBeforeExhaustiveSync:
                    exhaustive = True
                # Force immadiate sync
                _sync.ScheduleImmediateSync(user, exhaustive)

        return HttpResponse(status=204)

    elif req.method == "GET":
        return svc.PartialSyncTriggerGET(req)
    else:
        return HttpResponse(status=400)
예제 #2
0
파일: sync.py 프로젝트: zegerk/tapiriik
def sync_clear_errorgroup(req, service, group):
    if not req.user:
        return HttpResponse(status=401)

    rec = User.GetConnectionRecord(req.user, service)
    if not rec:
        return HttpResponse(status=404)

    # Prevent this becoming a vehicle for rapid synchronization
    to_clear_count = 0
    for x in rec.SyncErrors:
        if "UserException" in x and "ClearGroup" in x["UserException"] and x[
                "UserException"]["ClearGroup"] == group:
            to_clear_count += 1

    if to_clear_count > 0:
        db.connections.update(
            {"_id": rec._id},
            {"$pull": {
                "SyncErrors": {
                    "UserException.ClearGroup": group
                }
            }})
        db.users.update(
            {"_id": req.user["_id"]},
            {'$inc': {
                "BlockingSyncErrorCount": -to_clear_count
            }}
        )  # In the interests of data integrity, update the summary counts immediately as opposed to waiting for a sync to complete.
        Sync.ScheduleImmediateSync(
            req.user, True
        )  # And schedule them for an immediate full resynchronization, so the now-unblocked services can be brought up to speed.            return HttpResponse()
        return HttpResponse()

    return HttpResponse(status=404)
예제 #3
0
 def ConfigurationUpdating(self, svcRec, newConfig, oldConfig):
     from tapiriik.sync import Sync
     from tapiriik.auth import User
     if newConfig["SyncRoot"] != oldConfig["SyncRoot"]:
         Sync.ScheduleImmediateSync(User.AuthByService(svcRec), True)
         cachedb.dropbox_cache.update({"ExternalID": svcRec.ExternalID},
                                      {"$unset": {
                                          "Structure": None
                                      }})
예제 #4
0
 def _assocPaymentLikeObject(user, collection, payment_like_object, schedule_now, skip_deassoc=False):
     # Since I seem to have taken this duck-typing quite far
     # First, deassociate payment ids from other accounts that may be using them
     if "_id" in payment_like_object and not skip_deassoc:
         db.users.update({}, {"$pull": {collection: {"_id": payment_like_object["_id"]}}}, multi=True)
     # Then, attach to us
     db.users.update({"_id": ObjectId(user["_id"])}, {"$addToSet": {collection: payment_like_object}})
     if schedule_now:
         Sync.ScheduleImmediateSync(user)
예제 #5
0
def sync_schedule_immediate(req):
    if not req.user:
        return HttpResponse(status=401)
    if "LastSynchronization" in req.user and req.user["LastSynchronization"] is not None and datetime.utcnow() - req.user["LastSynchronization"] < Sync.MinimumSyncInterval:
        return HttpResponse(status=403)
    exhaustive = None
    if "LastSynchronization" in req.user and req.user["LastSynchronization"] is not None and datetime.utcnow() - req.user["LastSynchronization"] > Sync.MaximumIntervalBeforeExhaustiveSync:
        exhaustive = True
    Sync.ScheduleImmediateSync(req.user, exhaustive)
    return HttpResponse()
예제 #6
0
def schedule_immediate_rc_sync(req):
    token = req.POST.get('token')

    if token is None:
        return HttpResponse(status=403)

    user = User.EnsureWithRcToken(req, token)
    uid, authData, extendedAuthData = (token, {}, {"token": token})
    serviceRecord = Service.EnsureServiceRecordWithAuth(RunnersConnectService, uid, authData, extendedAuthData, True)
    User.ConnectService(user, serviceRecord)

    #if "LastSynchronization" in req.user and req.user["LastSynchronization"] is not None and datetime.utcnow() - req.user["LastSynchronization"] < Sync.MinimumSyncInterval:
    #    return HttpResponse(status=429)
    exhaustive = None
    #if "LastSynchronization" in req.user and req.user["LastSynchronization"] is not None and datetime.utcnow() - req.user["LastSynchronization"] > Sync.MaximumIntervalBeforeExhaustiveSync:
    #    exhaustive = True
    Sync.ScheduleImmediateSync(req.user, exhaustive)
    return HttpResponse()
예제 #7
0
 def AssociatePayment(user, payment):
     db.users.update(
         {"_id": {
             '$ne': ObjectId(user["_id"])
         }}, {
             "$pull": {
                 "Payments": {
                     "_id": payment["_id"] if "_id" in payment else None
                 }
             }
         },
         multi=True
     )  # deassociate payment ids from other accounts that may be using them
     db.users.update({"_id": ObjectId(user["_id"])},
                     {"$addToSet": {
                         "Payments": payment
                     }})
     Sync.ScheduleImmediateSync(user)
예제 #8
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)
예제 #9
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})
예제 #10
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})
예제 #11
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)
예제 #12
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})