mirror of
https://github.com/postgres/pgweb.git
synced 2025-08-03 15:38:59 +00:00

This adds the concept of an apiurl to each site that uses community authentication, that the main website server can make calls to and send updates. This URL will receive POSTs from the main website when a user account that has been used on this site gets updated, and can then optionally update it's local entries with it (the django plugin sample is updated to handle this fully). Updates are only sent for users that have a history of having logged into the specific site -- this way we avoid braodcasting user information to sites requiring specific constent that the user hasn't given, and also decreases the amount of updates that have to be sent. Updates are queued by the system in a table and using listen/notify a daemon that's running picks up what needs to be updated and posts it to the endpoints. If this daemon is not running, obviously nothing gets sent. Updates are tracked using triggers in the database which push information into this queue.
125 lines
5.4 KiB
Python
125 lines
5.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Generated by Django 1.11.27 on 2020-08-06 13:36
|
|
from __future__ import unicode_literals
|
|
|
|
from django.db import migrations, models
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
dependencies = [
|
|
('account', '0005_secondaryemail'),
|
|
('core', '0001_initial'),
|
|
]
|
|
|
|
operations = [
|
|
migrations.AddField(
|
|
model_name='communityauthsite',
|
|
name='apiurl',
|
|
field=models.URLField(max_length=200, null=False, blank=True),
|
|
),
|
|
migrations.AddField(
|
|
model_name='communityauthsite',
|
|
name='push_changes',
|
|
field=models.BooleanField(default=False, help_text='Supports receiving http POSTs with changes to accounts'),
|
|
),
|
|
migrations.AddField(
|
|
model_name='communityauthsite',
|
|
name='push_ssh',
|
|
field=models.BooleanField(default=False, help_text='Wants to receive SSH keys in push changes'),
|
|
),
|
|
migrations.RunSQL(
|
|
"""CREATE TABLE account_communityauthchangelog (
|
|
user_id int NOT NULL REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED,
|
|
site_id int NOT NULL REFERENCES account_communityauthsite (id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
|
|
changedat timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT account_communityauthchangelog_pkey PRIMARY KEY (user_id, site_id)
|
|
)""",
|
|
"""DROP TABLE account_communityauthchangelog""",
|
|
),
|
|
|
|
# When a user entry is changed, propagate it to any community auth site that has push enabled, and that
|
|
# the user has at some point logged in to. We do this through a trigger on auth_user, to make sure we
|
|
# definitely catch all changes.
|
|
migrations.RunSQL(
|
|
"""CREATE FUNCTION account_cauth_changetrack () RETURNS trigger AS $$
|
|
BEGIN
|
|
IF NEW.username != OLD.username THEN
|
|
RAISE EXCEPTION 'Usernames cannot be changed';
|
|
END IF;
|
|
|
|
IF NEW.first_name != OLD.first_name OR NEW.last_name != OLD.last_name OR NEW.email != OLD.email THEN
|
|
INSERT INTO account_communityauthchangelog (user_id, site_id, changedat)
|
|
SELECT NEW.id, s.id, CURRENT_TIMESTAMP
|
|
FROM account_communityauthsite s
|
|
INNER JOIN account_communityauthlastlogin ll ON ll.site_id=s.id
|
|
WHERE s.push_changes AND ll.user_id=NEW.id
|
|
ON CONFLICT (user_id, site_id) DO UPDATE SET changedat=greatest(account_communityauthchangelog.changedat, CURRENT_TIMESTAMP);
|
|
NOTIFY communityauth_changetrack;
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql'""",
|
|
"""DROP FUNCTION account_cauth_changetrack""",
|
|
),
|
|
|
|
# We specifically don't use "UPDATE OF" to find columns because then we create a dependency on columns in
|
|
# auth_user, which is owned by django, and may block migrations in that app. So we make the check at runtime.
|
|
migrations.RunSQL(
|
|
"""CREATE TRIGGER account_cauth_changetrack_trg
|
|
AFTER UPDATE ON auth_user
|
|
FOR EACH ROW EXECUTE FUNCTION account_cauth_changetrack()""",
|
|
"""DROP TRIGGER account_cauth_changetrack_trg ON auth_user""",
|
|
),
|
|
|
|
# We also need to track when secondary email addresses are added/removed (if they are confirmed)
|
|
# We don't have to track INSERTs as they are always unconfirmed, but we do need to track deletes here.
|
|
migrations.RunSQL(
|
|
"""CREATE FUNCTION account_secondaryemail_changetrack () RETURNS trigger AS $$
|
|
BEGIN
|
|
INSERT INTO account_communityauthchangelog (user_id, site_id, changedat)
|
|
SELECT NEW.user_id, s.id, CURRENT_TIMESTAMP
|
|
FROM account_communityauthsite s
|
|
INNER JOIN account_communityauthlastlogin ll ON ll.site_id=s.id
|
|
WHERE s.push_changes AND ll.user_id=NEW.user_id
|
|
ON CONFLICT (user_id, site_id) DO UPDATE SET changedat=greatest(account_communityauthchangelog.changedat, CURRENT_TIMESTAMP);
|
|
NOTIFY communityauth_changetrack;
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql'""",
|
|
"""DROP FUNCTION account_secondaryemail_changetrack""",
|
|
),
|
|
|
|
migrations.RunSQL(
|
|
"""CREATE TRIGGER account_secondaryemail_changetrack_trg
|
|
AFTER DELETE OR UPDATE ON account_secondaryemail
|
|
FOR EACH ROW EXECUTE FUNCTION account_secondaryemail_changetrack()""",
|
|
"""DROP TRIGGER account_Secondaryemail_changetrack_trg""",
|
|
),
|
|
|
|
migrations.RunSQL(
|
|
"""CREATE FUNCTION account_profile_changetrack () RETURNS trigger AS $$
|
|
BEGIN
|
|
IF NEW.sshkey != OLD.sshkey THEN
|
|
INSERT INTO account_communityauthchangelog (user_id, site_id, changedat)
|
|
SELECT NEW.user_id, s.id, CURRENT_TIMESTAMP
|
|
FROM account_communityauthsite s
|
|
INNER JOIN account_communityauthlastlogin ll ON ll.site_id=s.id
|
|
WHERE s.push_changes AND s.push_ssh AND ll.user_id=NEW.user_id
|
|
ON CONFLICT (user_id, site_id) DO UPDATE SET changedat=greatest(account_communityauthchangelog.changedat, CURRENT_TIMESTAMP);
|
|
NOTIFY communityauth_changetrack;
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql'""",
|
|
"""DROP FUNCTION account_secondaryemail_changetrack""",
|
|
),
|
|
|
|
migrations.RunSQL(
|
|
"""CREATE TRIGGER account_profile_changetrack_trg
|
|
AFTER DELETE OR UPDATE ON core_userprofile
|
|
FOR EACH ROW EXECUTE FUNCTION account_profile_changetrack()""",
|
|
"""DROP TRIGGER account_profile_changetrack_trg""",
|
|
),
|
|
]
|