Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add ability to ignore versions with sync_google
Browse files Browse the repository at this point in the history
dcramer committed Apr 7, 2021
1 parent 1f53281 commit 90eb69f
Showing 6 changed files with 51 additions and 12 deletions.
6 changes: 5 additions & 1 deletion backend/atlas/management/commands/sync_google.py
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument("--domain", type=str, default=settings.GOOGLE_DOMAIN)
parser.add_argument("--push", action="store_true", default=False)
parser.add_argument("--ignore-versions", action="store_true", default=False)
parser.add_argument("users", nargs="*", metavar="EMAIL")

def handle(self, *args, **options):
@@ -30,7 +31,10 @@ def handle(self, *args, **options):
)
else:
result = google.sync_domain(
identity=identity, domain=domain, users=options["users"]
identity=identity,
domain=domain,
users=options["users"],
ignore_versions=options["ignore_versions"],
)
self.stdout.write(self.style.MIGRATE_HEADING("Done!"))

4 changes: 2 additions & 2 deletions backend/atlas/middleware/auth.py
Original file line number Diff line number Diff line change
@@ -20,11 +20,11 @@ def get_user(header):
try:
user = User.objects.get(id=payload["uid"])
except (TypeError, KeyError, User.DoesNotExist):
logging.error("auth.invalid-uid")
logging.error("auth.invalid-uid", exc_info=True)
return AnonymousUser()

if security_hash(user) != payload["sh"]:
logging.error("auth.invalid-security-hash")
logging.error("auth.invalid-security-hash uid={}".format(payload["uid"]))
return AnonymousUser()

return user
2 changes: 2 additions & 0 deletions backend/atlas/mutations/test_login.py
Original file line number Diff line number Diff line change
@@ -109,6 +109,8 @@ def test_login_new_user_google_auth(gql_client, responses):
user = User.objects.get(id=resp["user"]["id"])
assert user.name == "Jane Smith"
assert user.email == "jsmith@example.com"
profile = user.profile
assert profile.title == "CTO"

assert isinstance(resp["token"], str)

6 changes: 3 additions & 3 deletions backend/atlas/utils/auth.py
Original file line number Diff line number Diff line change
@@ -22,13 +22,13 @@ def parse_token(token: str) -> Optional[str]:
try:
payload = s.loads(token)
except BadSignature:
logger.warning("auth: bad signature")
logger.warning("auth.bad-signature")
return None
if "uid" not in payload:
logger.warning("auth: missing uid")
logger.warning("auth.missing-uid")
return None
if "sh" not in payload:
logger.warning("auth: missing security hash")
logger.warning("auth.missing-security-hash")
return None
return payload

28 changes: 22 additions & 6 deletions backend/atlas/utils/google.py
Original file line number Diff line number Diff line change
@@ -328,7 +328,11 @@ def update_profile(


def sync_user( # NOQA
data: dict, user: User = None, user_identity: Identity = None, cache: Cache = None
data: dict,
user: User = None,
user_identity: Identity = None,
cache: Cache = None,
ignore_versions: bool = False,
) -> UserSyncResult:
if cache is None:
cache = Cache()
@@ -365,7 +369,7 @@ def sync_user( # NOQA
# we dont allow updates if the version of data received is _older_ than the current version
# _but_ we do allow udpates if they match (which means the version was not incremented, but something changed on Google's side)
# TODO(dcramer): we should bump the version when a remote update happens
if local_version > remote_version:
if local_version > remote_version and not ignore_versions:
logger.warning(
"user.sync-refused id={} reason=version-mismatch local_version={} remote_version={}".format(
str(user.id), local_version, remote_version
@@ -637,13 +641,19 @@ def sync_building( # NOQA


def sync_domain(
identity: Identity, domain: str, users: List[str] = None, offices: List[str] = None
identity: Identity,
domain: str,
users: List[str] = None,
offices: List[str] = None,
ignore_versions: bool = False,
) -> DomainSyncResult:
cache = Cache()

building_result = sync_buildings(identity, domain, offices=offices, cache=cache)

user_result = sync_users(identity, domain, users=users, cache=cache)
user_result = sync_users(
identity, domain, users=users, cache=cache, ignore_versions=ignore_versions
)

return DomainSyncResult(
total_users=user_result.total,
@@ -704,7 +714,11 @@ def sync_buildings(


def sync_users(
identity: Identity, domain: str, users: List[str] = None, cache: Cache = None
identity: Identity,
domain: str,
users: List[str] = None,
cache: Cache = None,
ignore_versions: bool = False,
) -> BatchSyncResult:
total, created, updated = 0, 0, 0
known = set()
@@ -732,7 +746,9 @@ def sync_users(
with sentry_sdk.Hub.current.start_span(
op="google.sync-user", description=str(row["id"])
), transaction.atomic():
user, is_created, is_updated = sync_user(row, cache=cache)
user, is_created, is_updated = sync_user(
row, cache=cache, ignore_versions=ignore_versions
)
with sentry_sdk.Hub.current.start_span(
op="google.sync-user-photo", description=str(row["id"])
):
17 changes: 17 additions & 0 deletions backend/atlas/utils/test_google.py
Original file line number Diff line number Diff line change
@@ -538,6 +538,23 @@ def test_sync_user_refuses_old_version_update(responses, default_user, user_payl
assert user.name != "Joe Doe"


def test_sync_user_updates_old_version_update_with_ignore_versions(
responses, default_user, user_payload
):
last_change = Change.record(default_user, {})

user_payload["customSchemas"]["System"]["Version"] = last_change.version - 1

user_payload["name"] = {"fullName": "Joe Doe"}
result = sync_user(data=user_payload, ignore_versions=True)
assert not result.created
assert result.updated

user = result.user
assert user.id == default_user.id
assert user.name == "Joe Doe"


def test_sync_user_accepts_same_version_update(responses, default_user, user_payload):
last_change = Change.record(default_user, {})

0 comments on commit 90eb69f

Please sign in to comment.