From 0242a9790ca73fc7f366349b433cb1e5065917ec Mon Sep 17 00:00:00 2001 From: Adrian Moennich Date: Tue, 7 Oct 2014 12:06:51 +0200 Subject: [PATCH] Properly handle JIDs --- chat/indico_chat/controllers.py | 2 ++ chat/indico_chat/forms.py | 16 ++++++++++++++-- .../201409291524_1bd6c5129d29_create_tables.py | 4 ++-- chat/indico_chat/models/chatrooms.py | 17 +++++++++++++---- chat/indico_chat/static/js/chat.js | 2 +- chat/indico_chat/templates/event_header.html | 2 +- chat/indico_chat/templates/event_page.html | 2 +- chat/indico_chat/templates/manage_event.html | 10 +++++++--- chat/indico_chat/xmpp.py | 18 ++++++++++++++++-- chat/indico_chat/zodbimport.py | 3 ++- 10 files changed, 59 insertions(+), 17 deletions(-) diff --git a/chat/indico_chat/controllers.py b/chat/indico_chat/controllers.py index 97ec914..221d535 100644 --- a/chat/indico_chat/controllers.py +++ b/chat/indico_chat/controllers.py @@ -115,7 +115,9 @@ class RHChatManageEventCreate(RHChatManageEventBase): event_chatroom = ChatroomEventAssociation(event_id=self.event_id, chatroom=chatroom) form.populate_obj(event_chatroom, fields=form.event_specific_fields) form.populate_obj(chatroom, skip=form.event_specific_fields) + chatroom.generate_jid() db.session.add_all((chatroom, event_chatroom)) + db.session.flush() create_room(chatroom) flash('Chatroom created', 'success') return redirect(url_for_plugin('.manage_rooms', self.event)) diff --git a/chat/indico_chat/forms.py b/chat/indico_chat/forms.py index 6430e6a..3766434 100644 --- a/chat/indico_chat/forms.py +++ b/chat/indico_chat/forms.py @@ -18,11 +18,14 @@ from __future__ import unicode_literals from wtforms.fields.core import BooleanField from wtforms.fields.simple import TextField, TextAreaField -from wtforms.validators import DataRequired +from wtforms.validators import DataRequired, ValidationError from indico.web.forms.base import IndicoForm from indico.util.string import strip_whitespace +from indico_chat.models.chatrooms import Chatroom +from indico_chat.xmpp import generate_jid + class EditChatroomForm(IndicoForm): event_specific_fields = {'hidden', 'show_password'} @@ -38,5 +41,14 @@ class EditChatroomForm(IndicoForm): class AddChatroomForm(EditChatroomForm): - custom_server = TextField('Server', filters=[strip_whitespace], + custom_server = TextField('Server', filters=[strip_whitespace, lambda x: x.lower() if x else x], description='External Jabber server. Should be left empty in most cases.') + + def validate_name(self, field): + jid = generate_jid(field.data) + if not jid: + # This error is not very helpful to a user, but it is extremely unlikely - only if he uses a name + # which does not contain a single char usable in a JID + raise ValidationError('Could not convert name to a jabber ID') + if Chatroom.find_first(jid_node=jid, custom_server=self.custom_server.data): + raise ValidationError('A room with this name already exists') diff --git a/chat/indico_chat/migrations/201409291524_1bd6c5129d29_create_tables.py b/chat/indico_chat/migrations/201409291524_1bd6c5129d29_create_tables.py index 90f976f..33d4059 100644 --- a/chat/indico_chat/migrations/201409291524_1bd6c5129d29_create_tables.py +++ b/chat/indico_chat/migrations/201409291524_1bd6c5129d29_create_tables.py @@ -21,6 +21,7 @@ def upgrade(): op.execute(CreateSchema('plugin_chat')) op.create_table('chatrooms', sa.Column('id', sa.Integer(), nullable=False), + sa.Column('jid_node', sa.String(), nullable=False), sa.Column('name', sa.String(), nullable=False), sa.Column('description', sa.Text(), nullable=False), sa.Column('password', sa.String(), nullable=False), @@ -29,8 +30,7 @@ def upgrade(): 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, + sa.UniqueConstraint('jid_node', 'custom_server'), schema='plugin_chat') op.create_table('chatroom_events', sa.Column('event_id', sa.Integer(), nullable=False, primary_key=True, index=True, diff --git a/chat/indico_chat/models/chatrooms.py b/chat/indico_chat/models/chatrooms.py index a2c9973..c25f9f4 100644 --- a/chat/indico_chat/models/chatrooms.py +++ b/chat/indico_chat/models/chatrooms.py @@ -16,7 +16,6 @@ from __future__ import unicode_literals -from sqlalchemy import func from sqlalchemy.ext.declarative import declared_attr from indico.core.db.sqlalchemy import db, UTCDateTime @@ -24,6 +23,7 @@ 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 +from indico_chat.xmpp import generate_jid class Chatroom(db.Model): @@ -31,7 +31,7 @@ class Chatroom(db.Model): @declared_attr def __table_args__(cls): - return (db.Index('ix_chatrooms_name_lower', func.lower(cls.name), unique=True), + return (db.UniqueConstraint(cls.jid_node, cls.custom_server), {'schema': 'plugin_chat'}) #: Chatroom ID @@ -39,7 +39,11 @@ class Chatroom(db.Model): db.Integer, primary_key=True ) - # TODO: jid column + #: Node of the chatroom's JID (the part before `@domain`) + jid_node = db.Column( + db.String, + nullable=False + ) #: Name of the chatroom name = db.Column( db.String, @@ -108,7 +112,12 @@ class Chatroom(db.Model): server = self.server if self.custom_server: server = '!' + server - return ''.format(self.id, self.name, server) + return ''.format(self.id, self.name, self.jid_node, server) + + def generate_jid(self): + """Generates the JID based on the room name""" + assert self.jid_node is None + self.jid_node = generate_jid(self.name) class ChatroomEventAssociation(db.Model): diff --git a/chat/indico_chat/static/js/chat.js b/chat/indico_chat/static/js/chat.js index bd28b2f..1372598 100644 --- a/chat/indico_chat/static/js/chat.js +++ b/chat/indico_chat/static/js/chat.js @@ -56,7 +56,7 @@ $('.js-chat-remove-room').on('click', function(e) { e.preventDefault(); var $this = $(this); - var msg = $T('Do you really want to delete this chatroom?'); + var msg = $T('Do you really want to remove this chatroom from the event?'); if ($this.data('numEvents') == 1) { msg += '
' + $T('Since it is only used in this event, it will be deleted from the Jabber server, too!'); } diff --git a/chat/indico_chat/templates/event_header.html b/chat/indico_chat/templates/event_header.html index 74d98b5..edf1f9a 100644 --- a/chat/indico_chat/templates/event_header.html +++ b/chat/indico_chat/templates/event_header.html @@ -11,7 +11,7 @@ {% trans %}More Info{% endtrans %} {% if chat_links %} - - {% trans %}Join now!{% endtrans %} + {% trans %}Join now!{% endtrans %} {% endif %}