diff --git a/migrations/versions/7c4fa4bd92bf_convert_account_session_relation_to_.py b/migrations/versions/7c4fa4bd92bf_convert_account_session_relation_to_.py new file mode 100644 index 0000000..638c034 --- /dev/null +++ b/migrations/versions/7c4fa4bd92bf_convert_account_session_relation_to_.py @@ -0,0 +1,67 @@ +"""convert account/session relation to many-many + +Revision ID: 7c4fa4bd92bf +Revises: 2bd33abe291c +Create Date: 2018-06-07 22:53:25.476476 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '7c4fa4bd92bf' +down_revision = '2bd33abe291c' +branch_labels = None +depends_on = None + +sessions = sa.table( + "sessions", + sa.Column('id', sa.String), + sa.Column('account_id', sa.String) +) + + +def upgrade(): + session_accounts = op.create_table( + "session_accounts", + sa.Column('session_id', sa.String), + sa.Column('account_id', sa.String), + sa.PrimaryKeyConstraint('session_id', 'account_id', name=op.f('pk_session_accounts')), + sa.ForeignKeyConstraint( + ['session_id'], ['sessions.id'], + name=op.f('fk_session_accounts_session_id_sessions'), + onupdate='CASCADE', ondelete='CASCADE' + ), + sa.ForeignKeyConstraint( + ['account_id'], ['accounts.id'], + name=op.f('fk_session_accounts_account_id_accounts'), + onupdate='CASCADE', ondelete='CASCADE' + ) + ) + op.execute( + session_accounts + .insert() + .from_select( + ['session_id', 'account_id'], + sa.select([sessions]) + ) + ) + op.drop_constraint('fk_sessions_account_id_accounts', 'sessions') + op.drop_index('ix_sessions_account_id') + op.alter_column('sessions', 'account_id', new_column_name='current_account_id', nullable=True) + op.create_foreign_key( + 'fk_sessions_current_account_id_accounts', 'sessions', 'accounts', + ['current_account_id'], ['id'], + onupdate='SET NULL', ondelete='SET NULL') + + +def downgrade(): + op.drop_table("session_accounts") + op.drop_constraint('fk_sessions_current_account_id_accounts') + op.alter_column('sessions', 'current_account_id', new_column_name='account_id', nullable=False) + op.create_foreign_key( + 'fk_sessions_account_id_accounts', 'sessions', 'accounts', + ['account_id'], ['id'], + onupdate='CASCADE', ondelete='CASCADE') + op.create_index('ix_sessions_account_id', 'sessions', ['account_id']) diff --git a/model.py b/model.py index 9134ed8..5180729 100644 --- a/model.py +++ b/model.py @@ -226,18 +226,33 @@ class OAuthToken(db.Model, TimestampMixin): # token is for until we call /account/verify_credentials with it +session_accounts = db.Table( + 'session_accounts', + db.Column( + 'session_id', + db.String, db.ForeignKey('sessions.id'), primary_key=True), + db.Column( + 'account_id', + db.String, db.ForeignKey('accounts.id'), primary_key=True) + ) + + class Session(db.Model, TimestampMixin): __tablename__ = 'sessions' id = db.Column(db.String, primary_key=True, default=secrets.token_urlsafe) - account_id = db.Column( + current_account_id = db.Column( db.String, - db.ForeignKey('accounts.id', - ondelete='CASCADE', onupdate='CASCADE'), - nullable=False, index=True) - account = db.relationship(Account, lazy='joined', backref='sessions') + db.ForeignKey( + 'accounts.id', ondelete='SET NULL', onupdate='SET NULL'), + nullable=True) + account = db.relationship(Account) + accounts = db.relationship( + Account, + secondary=session_accounts, + lazy='joined', backref=db.backref('sessions', lazy=True)) csrf_token = db.Column(db.String, default=secrets.token_urlsafe, diff --git a/routes/__init__.py b/routes/__init__.py index a3eecf7..cac9e29 100644 --- a/routes/__init__.py +++ b/routes/__init__.py @@ -65,11 +65,16 @@ def twitter_login_step1(): def login(account_id): - session = Session(account_id=account_id) - db.session.add(session) + session = get_viewer_session() + if not session: + session = Session() + db.session.add(session) + session.current_account_id = account_id db.session.commit() - session.account.dormant = False + session.current_account.dormant = False + if(session.account not in session.accounts): + session.accounts.append(session.account) db.session.commit() tasks.fetch_acc.s(account_id).apply_async(routing_key='high')