From 1272ef25887aabcf281efbdff404cdae835a58bd Mon Sep 17 00:00:00 2001 From: Adnan Maolood Date: Thu, 18 Aug 2022 22:27:45 -0400 Subject: [PATCH] gitsrht: Use canonical user IDs Update user IDs across git.sr.ht to match those of meta.sr.ht. --- api/go.mod | 2 +- api/go.sum | 4 +- .../08e3d103b672_add_user_remote_id.py | 54 ++++++++++ .../5f3e7771c065_use_canonical_user_id.py | 101 ++++++++++++++++++ 4 files changed, 158 insertions(+), 3 deletions(-) create mode 100644 gitsrht/alembic/versions/08e3d103b672_add_user_remote_id.py create mode 100644 gitsrht/alembic/versions/5f3e7771c065_use_canonical_user_id.py diff --git a/api/go.mod b/api/go.mod index 0fdd2bc..d41ebca 100644 --- a/api/go.mod +++ b/api/go.mod @@ -3,7 +3,7 @@ module git.sr.ht/~sircmpwn/git.sr.ht/api go 1.14 require ( - git.sr.ht/~sircmpwn/core-go v0.0.0-20220530120843-d0bf1153ada4 + git.sr.ht/~sircmpwn/core-go v0.0.0-20221025082458-3e69641ef307 git.sr.ht/~sircmpwn/dowork v0.0.0-20210820133136-d3970e97def3 github.com/99designs/gqlgen v0.17.20 github.com/Masterminds/squirrel v1.4.0 diff --git a/api/go.sum b/api/go.sum index 386bed7..c7a1717 100644 --- a/api/go.sum +++ b/api/go.sum @@ -31,8 +31,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -git.sr.ht/~sircmpwn/core-go v0.0.0-20220530120843-d0bf1153ada4 h1:pyGHngvO7qIANeI5pmqzfVc+nLKSTTuwq2OA66nxEGw= -git.sr.ht/~sircmpwn/core-go v0.0.0-20220530120843-d0bf1153ada4/go.mod h1:uUqzeO5OLl/nRZfPk0igIAweRZiVwUmu/OGYfjS9fWc= +git.sr.ht/~sircmpwn/core-go v0.0.0-20221025082458-3e69641ef307 h1:KYkDsSLoJZ+LshT7ab/8PMhWyq8X+43+FkT1hR3ee1c= +git.sr.ht/~sircmpwn/core-go v0.0.0-20221025082458-3e69641ef307/go.mod h1:uUqzeO5OLl/nRZfPk0igIAweRZiVwUmu/OGYfjS9fWc= git.sr.ht/~sircmpwn/dowork v0.0.0-20210820133136-d3970e97def3 h1:9WCv5cK67s2SiY/R4DWT/OchEsFnfYDz3lbevKxZ4QI= git.sr.ht/~sircmpwn/dowork v0.0.0-20210820133136-d3970e97def3/go.mod h1:8neHEO3503w/rNtttnR0JFpQgM/GFhaafVwvkPsFIDw= git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3 h1:4wDp4BKF7NQqoh73VXpZsB/t1OEhDpz/zEpmdQfbjDk= diff --git a/gitsrht/alembic/versions/08e3d103b672_add_user_remote_id.py b/gitsrht/alembic/versions/08e3d103b672_add_user_remote_id.py new file mode 100644 index 0000000..2579d3a --- /dev/null +++ b/gitsrht/alembic/versions/08e3d103b672_add_user_remote_id.py @@ -0,0 +1,54 @@ +"""Add user.remote_id + +Revision ID: 08e3d103b672 +Revises: 64fcd80183c8 +Create Date: 2022-07-14 12:21:50.325962 + +""" + +# revision identifiers, used by Alembic. +revision = '08e3d103b672' +down_revision = '64fcd80183c8' + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import scoped_session, sessionmaker +from srht.crypto import internal_anon +from srht.database import db +from srht.graphql import exec_gql + +Base = declarative_base() + +class User(Base): + __tablename__ = "user" + id = sa.Column(sa.Integer, primary_key=True) + username = sa.Column(sa.Unicode(256), index=True, unique=True) + remote_id = sa.Column(sa.Integer, unique=True) + +def upgrade(): + engine = op.get_bind() + session = scoped_session(sessionmaker( + autocommit=False, + autoflush=False, + bind=engine)) + Base.query = session.query_property() + + op.execute("""ALTER TABLE "user" ADD COLUMN remote_id integer UNIQUE""") + + for user in User.query: + user.remote_id = fetch_user_id(user.username) + print(f"~{user.username} id: {user.id} -> {user.remote_id}") + session.commit() + + op.execute("""ALTER TABLE "user" ALTER COLUMN remote_id SET NOT NULL""") + +def downgrade(): + op.drop_column("user", "remote_id") + +def fetch_user_id(username): + resp = exec_gql("meta.sr.ht", + "query($username: String!) { user(username: $username) { id } }", + user=internal_anon, + username=username) + return resp["user"]["id"] diff --git a/gitsrht/alembic/versions/5f3e7771c065_use_canonical_user_id.py b/gitsrht/alembic/versions/5f3e7771c065_use_canonical_user_id.py new file mode 100644 index 0000000..d69bc66 --- /dev/null +++ b/gitsrht/alembic/versions/5f3e7771c065_use_canonical_user_id.py @@ -0,0 +1,101 @@ +"""Use canonical user ID + +Revision ID: 5f3e7771c065 +Revises: 08e3d103b672 +Create Date: 2022-07-14 12:24:54.356882 + +""" + +# revision identifiers, used by Alembic. +revision = '5f3e7771c065' +down_revision = '08e3d103b672' + +from alembic import op +import sqlalchemy as sa + + +# These tables all have a column referencing "user"(id) +tables = [ + ("access", "user_id"), + ("artifacts", "user_id"), + ("gql_user_wh_sub", "user_id"), + ("oauthtoken", "user_id"), + ("redirect", "owner_id"), + ("repo_webhook_subscription", "user_id"), + ("repository", "owner_id"), + ("sshkey", "user_id"), + ("user_webhook_subscription", "user_id"), +] + +def upgrade(): + # Drop unique constraints + op.execute(""" + ALTER TABLE access DROP CONSTRAINT uq_access_user_id_repo_id; + ALTER TABLE repository DROP CONSTRAINT uq_repo_owner_id_name; + """) + + # Drop foreign key constraints and update user IDs + for (table, col) in tables: + op.execute(f""" + ALTER TABLE {table} DROP CONSTRAINT {table}_{col}_fkey; + UPDATE {table} t SET {col} = u.remote_id FROM "user" u WHERE u.id = t.{col}; + """) + + # Update primary key + op.execute(""" + ALTER TABLE "user" DROP CONSTRAINT user_pkey; + ALTER TABLE "user" DROP CONSTRAINT user_remote_id_key; + ALTER TABLE "user" RENAME COLUMN id TO old_id; + ALTER TABLE "user" RENAME COLUMN remote_id TO id; + ALTER TABLE "user" ADD PRIMARY KEY (id); + ALTER TABLE "user" ADD UNIQUE (old_id); + """) + + # Add foreign key constraints + for (table, col) in tables: + op.execute(f""" + ALTER TABLE {table} ADD CONSTRAINT {table}_{col}_fkey FOREIGN KEY ({col}) REFERENCES "user"(id) ON DELETE CASCADE; + """) + + # Add unique constraints + op.execute(""" + ALTER TABLE access ADD CONSTRAINT uq_access_user_id_repo_id UNIQUE (user_id, repo_id); + ALTER TABLE repository ADD CONSTRAINT uq_repo_owner_id_name UNIQUE (owner_id, name); + """) + + +def downgrade(): + # Drop unique constraints + op.execute(""" + ALTER TABLE access DROP CONSTRAINT uq_access_user_id_repo_id; + ALTER TABLE repository DROP CONSTRAINT uq_repo_owner_id_name; + """) + + # Drop foreign key constraints and update user IDs + for (table, col) in tables: + op.execute(f""" + ALTER TABLE {table} DROP CONSTRAINT {table}_{col}_fkey; + UPDATE {table} t SET {col} = u.old_id FROM "user" u WHERE u.id = t.{col}; + """) + + # Update primary key + op.execute(""" + ALTER TABLE "user" DROP CONSTRAINT user_pkey; + ALTER TABLE "user" DROP CONSTRAINT user_old_id_key; + ALTER TABLE "user" RENAME COLUMN id TO remote_id; + ALTER TABLE "user" RENAME COLUMN old_id TO id; + ALTER TABLE "user" ADD PRIMARY KEY (id); + ALTER TABLE "user" ADD UNIQUE (remote_id); + """) + + # Add foreign key constraints + for (table, col) in tables: + op.execute(f""" + ALTER TABLE {table} ADD CONSTRAINT {table}_{col}_fkey FOREIGN KEY ({col}) REFERENCES "user"(id) ON DELETE CASCADE; + """) + + # Add unique constraints + op.execute(""" + ALTER TABLE access ADD CONSTRAINT uq_access_user_id_repo_id UNIQUE (user_id, repo_id); + ALTER TABLE repository ADD CONSTRAINT uq_repo_owner_id_name UNIQUE (owner_id, name); + """) -- 2.38.4