M api/go.mod => api/go.mod +1 -1
@@ 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
M api/go.sum => api/go.sum +2 -2
@@ 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=
A gitsrht/alembic/versions/08e3d103b672_add_user_remote_id.py => gitsrht/alembic/versions/08e3d103b672_add_user_remote_id.py +54 -0
@@ 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"]
A gitsrht/alembic/versions/5f3e7771c065_use_canonical_user_id.py => gitsrht/alembic/versions/5f3e7771c065_use_canonical_user_id.py +101 -0
@@ 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);
+ """)