hubsrht: Use canonical user IDs

Update user IDs across all of hub.sr.ht to match those of meta.sr.ht.
This commit is contained in:
Adnan Maolood 2022-07-18 11:33:50 -04:00 committed by Drew DeVault
parent 638a05c8df
commit 0f2393ea80
3 changed files with 218 additions and 0 deletions

View File

@ -0,0 +1,54 @@
"""Add user.remote_id
Revision ID: 1cdfad7c20b8
Revises: de4adc3cc306
Create Date: 2022-06-16 15:06:53.119381
"""
# revision identifiers, used by Alembic.
revision = '1cdfad7c20b8'
down_revision = 'de4adc3cc306'
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"]

View File

@ -0,0 +1,73 @@
"""Use canonical user ID
Revision ID: 9a939f5d527e
Revises: 1cdfad7c20b8
Create Date: 2022-06-16 15:14:10.901524
"""
# revision identifiers, used by Alembic.
revision = '9a939f5d527e'
down_revision = '1cdfad7c20b8'
from alembic import op
import sqlalchemy as sa
# These tables all have a column referencing "user"(id)
tables = [
("event", "user_id"),
("mailing_list", "owner_id"),
("project", "owner_id"),
("source_repo", "owner_id"),
("tracker", "owner_id"),
]
def upgrade():
# 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;
""")
def downgrade():
# 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;
""")

View File

@ -0,0 +1,91 @@
"""Reconfigure user webhooks
Revision ID: e748f55a827c
Revises: 9a939f5d527e
Create Date: 2022-07-18 10:49:42.704659
"""
# revision identifiers, used by Alembic.
revision = 'e748f55a827c'
down_revision = '9a939f5d527e'
from alembic import op
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker
from flask import url_for
from srht.api import ensure_webhooks
from srht.config import get_origin
from srht.crypto import internal_anon
from srht.database import db
from srht.graphql import exec_gql
from hubsrht.app import app
Base = declarative_base()
app.config['SERVER_NAME'] = ''
_gitsrht = get_origin("git.sr.ht", external=True, default=None)
_hgsrht = get_origin("hg.sr.ht", external=True, default=None)
_todosrht = get_origin("todo.sr.ht", external=True, default=None)
origin = get_origin("hub.sr.ht")
class User(Base):
__tablename__ = "user"
id = sa.Column(sa.Integer, primary_key=True)
old_id = sa.Column(sa.Integer, unique=True)
username = sa.Column(sa.Unicode(256), index=True, unique=True)
def reconfigure_webhooks(user, old_id, id):
# git user webhooks
if _gitsrht:
ensure_webhooks(user, f"{_gitsrht}/api/user/webhooks", {
origin + url_for("webhooks.git_user", user_id=old_id, _external=False): None,
origin + url_for("webhooks.git_user", user_id=id, _external=False):
["repo:update", "repo:delete"],
})
# hg user webhooks
if _hgsrht:
ensure_webhooks(user, f"{_hgsrht}/api/user/webhooks", {
origin + url_for("webhooks.hg_user", user_id=old_id, _external=False): None,
origin + url_for("webhooks.hg_user", user_id=id, _external=False):
["repo:update", "repo:delete"],
})
# todo user webhooks
if _todosrht:
ensure_webhooks(user, f"{_todosrht}/api/user/webhooks", {
origin + url_for("webhooks.todo_user", user_id=old_id, _external=False): None,
origin + url_for("webhooks.todo_user", user_id=id, _external=False):
["tracker:update", "tracker:delete"],
})
print(f"Reconfigured ~{user.username} webhooks: {old_id} -> {id}")
def upgrade():
engine = op.get_bind()
session = scoped_session(sessionmaker(
autocommit=False,
autoflush=False,
bind=engine))
Base.query = session.query_property()
with app.app_context():
for user in User.query:
reconfigure_webhooks(user, user.old_id, user.id)
session.commit()
def downgrade():
engine = op.get_bind()
session = scoped_session(sessionmaker(
autocommit=False,
autoflush=False,
bind=engine))
Base.query = session.query_property()
with app.app_context():
for user in User.query:
reconfigure_webhooks(user, user.id, user.old_id)
session.commit()