diff --git a/chat/indico_chat/migrations/201409291524_1bd6c5129d29_create_tables.py b/chat/indico_chat/migrations/201409291524_1bd6c5129d29_create_tables.py new file mode 100644 index 0000000..eb221c5 --- /dev/null +++ b/chat/indico_chat/migrations/201409291524_1bd6c5129d29_create_tables.py @@ -0,0 +1,57 @@ +"""Create tables + +Revision ID: 1bd6c5129d29 +Revises: None +Create Date: 2014-09-29 15:24:03.369025 +""" + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.sql.ddl import CreateSchema, DropSchema + +from indico.core.db.sqlalchemy import UTCDateTime + + +# revision identifiers, used by Alembic. +revision = '1bd6c5129d29' +down_revision = None + + +def upgrade(): + op.execute(CreateSchema('plugin_chat')) + op.create_table('chatrooms', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(), nullable=False), + sa.Column('description', sa.Text(), nullable=False), + sa.Column('password', sa.String(), nullable=False), + sa.Column('custom_server', sa.String(), nullable=True), + sa.Column('created_by_id', sa.Integer(), nullable=False), + sa.Column('created_dt', UTCDateTime(), nullable=False), + sa.Column('modified_dt', UTCDateTime(), nullable=True), + sa.PrimaryKeyConstraint('id'), + schema='plugin_chat' + ) + op.create_index('ix_chatrooms_name_lower', 'chatrooms', [sa.text('lower(plugin_chat.chatrooms.name)')], unique=True, + schema='plugin_chat') + op.create_table('chatroom_events', + sa.Column('event_id', sa.Integer(), nullable=False), + sa.Column('chatroom_id', sa.Integer(), nullable=False), + sa.Column('hidden', sa.Boolean(), nullable=False), + sa.Column('show_password', sa.Boolean(), nullable=False), + sa.ForeignKeyConstraint(['chatroom_id'], ['plugin_chat.chatrooms.id']), + sa.PrimaryKeyConstraint('event_id', 'chatroom_id'), + schema='plugin_chat') + op.create_index(op.f('ix_plugin_chat_chatroom_events_chatroom_id'), 'chatroom_events', ['chatroom_id'], + unique=False, schema='plugin_chat') + op.create_index(op.f('ix_plugin_chat_chatroom_events_event_id'), 'chatroom_events', ['event_id'], unique=False, + schema='plugin_chat') + + +def downgrade(): + op.drop_index(op.f('ix_plugin_chat_chatroom_events_event_id'), table_name='chatroom_events', schema='plugin_chat') + op.drop_index(op.f('ix_plugin_chat_chatroom_events_chatroom_id'), table_name='chatroom_events', + schema='plugin_chat') + op.drop_table('chatroom_events', schema='plugin_chat') + op.drop_index('ix_chatrooms_name_lower', table_name='chatrooms', schema='plugin_chat') + op.drop_table('chatrooms', schema='plugin_chat') + op.execute(DropSchema('plugin_chat')) diff --git a/chat/indico_chat/models/__init__.py b/chat/indico_chat/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/chat/indico_chat/models/chatrooms.py b/chat/indico_chat/models/chatrooms.py new file mode 100644 index 0000000..2e49f58 --- /dev/null +++ b/chat/indico_chat/models/chatrooms.py @@ -0,0 +1,148 @@ +# This file is part of Indico. +# Copyright (C) 2002 - 2014 European Organization for Nuclear Research (CERN). +# +# Indico is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3 of the +# License, or (at your option) any later version. +# +# Indico is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Indico; if not, see . + +from __future__ import unicode_literals + +from flask_pluginengine import current_plugin +from sqlalchemy import func +from sqlalchemy.ext.declarative import declared_attr + +from indico.core.db.sqlalchemy import db, UTCDateTime +from indico.util.date_time import now_utc +from indico.util.string import return_ascii +from MaKaC.user import AvatarHolder +from MaKaC.conference import ConferenceHolder + + +class Chatroom(db.Model): + __tablename__ = 'chatrooms' + + @declared_attr + def __table_args__(cls): + return (db.Index('ix_chatrooms_name_lower', func.lower(cls.name), unique=True), + {'schema': 'plugin_chat'}) + + #: Chatroom ID + id = db.Column( + db.Integer, + primary_key=True + ) + #: Name of the chatroom + name = db.Column( + db.String, + nullable=False + ) + #: Description of the chatroom + description = db.Column( + db.Text, + nullable=False, + default='' + ) + #: Password to join the room + password = db.Column( + db.String, + nullable=False, + default='' + ) + #: Custom Jabber MUC server hostname + custom_server = db.Column( + db.String + ) + #: ID of the creator + created_by_id = db.Column( + db.Integer, + nullable=False + ) + #: Creation timestamp of the chatroom + created_dt = db.Column( + UTCDateTime, + nullable=False, + default=now_utc + ) + #: Modification timestamp of the chatroom + modified_dt = db.Column( + UTCDateTime + ) + + @property + def created_by_user(self): + """The Avatar who created the chatroom.""" + return AvatarHolder().getById(str(self.created_by_id)) + + @created_by_user.setter + def created_by_user(self, user): + self.created_by_id = int(user.getId()) + + @property + def server(self): + """The server name of the chatroom. + + Usually the default one unless a custom one is set. + """ + return self.custom_server or current_plugin.settings.get('muc_server') + + @return_ascii + def __repr__(self): + return ''.format(self.id, self.name, self.server) + + +class ChatroomEventAssociation(db.Model): + __tablename__ = 'chatroom_events' + __table_args__ = {'schema': 'plugin_chat'} + + #: ID of the event + event_id = db.Column( + db.Integer, + primary_key=True, + index=True + ) + #: ID of the chatroom + chatroom_id = db.Column( + db.Integer, + db.ForeignKey('plugin_chat.chatrooms.id'), + primary_key=True, + index=True + ) + #: If the chatroom should be hidden on the event page + hidden = db.Column( + db.Boolean, + nullable=False, + default=False + ) + #: If the password should be visible on the event page + show_password = db.Column( + db.Boolean, + nullable=False, + default=False + ) + #: The associated :class:Chatroom + chatroom = db.relationship( + 'Chatroom', + lazy=False, + backref='events' + ) + + @property + def event(self): + return ConferenceHolder().getById(str(self.event_id)) + + @event.setter + def event(self, event): + self.event_id = int(event.getId()) + + @return_ascii + def __repr__(self): + return ''.format(self.event_id, self.chatroom) diff --git a/chat/indico_chat/plugin.py b/chat/indico_chat/plugin.py index 313be3c..b08961a 100644 --- a/chat/indico_chat/plugin.py +++ b/chat/indico_chat/plugin.py @@ -14,7 +14,16 @@ # You should have received a copy of the GNU General Public License # along with Indico; if not, see . +from __future__ import unicode_literals + from indico.core.plugins import IndicoPlugin +from indico.web.forms.base import IndicoForm +from wtforms.fields.simple import TextField + + +class SettingsForm(IndicoForm): + server = TextField('XMPP server') + muc_server = TextField('XMPP MUC server (conference.*)') class ChatPlugin(IndicoPlugin): @@ -22,3 +31,5 @@ class ChatPlugin(IndicoPlugin): Provides an XMPP based chat for events. """ + + settings_form = SettingsForm