UMGUM.COM (лучше) 

Jabberd 2 + Public Roster update ( Применение на работающую базу пользователей XMPP сервер Jabberd 2 шаблона списка публичных аккаунтов. )

9 февраля 2011  (обновлено 31 января 2015)

Эта публикация отнесена в архив. Она неактуальна.

Debian GNU/Linux Lenny.

Ранее, когда отрабатывался механизм автоматического применения шаблона для публикации списка доступных пользователей при создании нового аккаунта, я упоминал о том, что было бы очень хорошо иметь возможность воздействовать на уже имеющиеся аккаунты, я не только те, что вновь создаются. В Jabberd2 нет такой встроенной возможности. Создадим её сторонними средствами.

Мне показалось интересным сделать это на встроенном в "Bash" языке программирования, обращаясь к СУБД MySQL с помощью оригинального клиента.


И так, с чем мы работаем? С тремя таблицами.

Таблица зарегистрированных аккаунтов:

Tablename: authreg:

username: TEXT;
realm: TINYTEXT;
password: TINYTEXT.

Таблица "ростеров":

Tablename: roster-items:

collection-owner: TEXT, not NULL;
object-sequence: BIGINT(20), primary key, auto-increment, not NULL;
jid: TEXT;
name: TEXT;
to: TINYINT(4);
from: TINYINT(4);
ask: INTEGER.

Таблица группировки фигурантов "ростеров":

Tablename: roster-groups:

collection-owner: TEXT, not NULL;
object-sequence: BIGINT(20), primary key, auto-increment, not NULL;
jid: TEXT;
group: TEXT.

Формат файла шаблона должен быть определённого вида, чтобы наш примитивный скрипт разбора переменных не сбоил. Создаём (или изменяем существующий) файл шаблона по адресу "/etc/jabberd/templates/roster.xml" и приводим его к следующему виду:

# cat /etc/jabberd/templates/roster.xml

<query xmlns='jabber:iq:roster'>
  <item name='Helpdesk One' jid='one.support@domain.com' subscription='none'><group>Support</group></item>
  <item name='Helpdesk Two' jid='two.support@domain.com' subscription='none'><group>Support</group></item>
  ....
  <item name='Helpdesk X' jid='x.support@domain.com' subscription='none'><group>Support</group></item>
  <item name='Head of Department One' jid='one.head@domain.com' subscription='none'><group>Management</group></item>
  <item name='Head of Department Two' jid='two.head@domain.com' subscription='none'><group>Management</group></item>
  ....
  <item name='Head of Department X' jid='x.head@domain.com' subscription='none'><group>Management</group></item>
  <item name='Service personnel One' jid='one.service@domain.com' subscription='none'><group>Service</group></item>
  <item name='Service personnel Two' jid='two.service@domain.com' subscription='none'><group>Service</group></item>
  ....
  <item name='Service personnel X' jid='x.service@domain.com' subscription='none'><group>Service</group></item>
</query>

Для того, чтобы не указывать параметры подключения к СУБД в скриптах, воспользуемся способность клиента брать эти данные из конфигурационных файлов:

# touch /etc/jabberd2/my.cnf
# chown jabberd2:jabberd2 /etc/jabberd2/my.cnf
# chmod go-rwx /etc/jabberd2/my.cnf

# cat /etc/jabberd2/my.cnf

[client]
user = jabberd2
password = strongPassword
host = localhost
[mysql]
database = jabberd2

Разработчики Jabberd2 люди с размахом, видимо, не желающие размениваться на такие мелочи, как использование "безопасных" имён в СУБД; потому, часть таковых придётся экранировать. Заковырка в том, что символы экранирования в MySQL конфликтуют с аналогичными символами в языке программирования в "Bash" и нам придётся не особо изящно изворачиваться.

Приступаем:

# touch /etc/jabberd2/templates/public.sh
# chown jabberd2:jabberd2 /etc/jabberd2/templates/public.sh
# chmod u+x /etc/jabberd2/templates/public.sh
# chmod go-rwx /etc/jabberd2/templates/public.sh

# cat /etc/jabberd2/templates/public.sh

#!/bin/bash

export PATH=/sbin:/bin:/usr/sbin:/usr/bin

# Указываем доменное имя нашего сервера Jabber (XMPP)
REALM="@domain.name"
# Загоняем в переменные требующие экранирования имена и названия
TITEMS="\`roster-items\`"
TGROUPS="\`roster-groups\`"
CCOLLECTIONOWNER="\`collection-owner\`"
CTO="\`to\`"
CFROM="\`from\`"
CGROUP="\`group\`"

# Формируем строку запуска клиента MySQL с соответствующими опциями
MYSQL="mysql --defaults-extra-file=/etc/jabberd2/my.cnf --skip-column-names jabberd2"

# Делаем выборку всех пользователей сервера
RESULT=`$MYSQL -e "SELECT DISTINCT username FROM authreg"`

# Перебираем в цикле пользователей
for I in $RESULT
do
  # Запускаем перебор строк файла шаблона, отвечающих условию
  cat /etc/jabberd/templates/roster.xml | grep --invert-match '<!--' | grep --ignore-case 'jid=' | while read LINE
  do
    # Выделяем имя, логин и группу аккаунта, вносимого в "ростер"
    NAME=`echo $LINE | awk 'match($0,/ name=\047[A-Za-z0-9!@-\., ]+\047 /) {print substr($0, RSTART, RLENGTH)}' |  cut -c 8- | rev | cut -c 3- | rev`
    JID=`echo $LINE | awk 'match($0,/ jid=\047[A-Za-z0-9!@-\.]+\047 /) {print substr($0, RSTART, RLENGTH)}' | cut -c 7- | rev | cut -c 3- | rev`
    GROUP=`echo $LINE | awk 'match($0,/\074group\076.+\074\/group\076/) {print substr($0, RSTART, RLENGTH)}' | cut -c 8- | rev | cut -c 9- | rev`

    if [ "${I}${REALM}" != "$JID" ]
    then
      # Если вносимый аккаунт не есть он самый, то продолжаем
      echo "Success done..."
      # Проверяем, нет ли уже в "ростере" вносимого в него аккаунта
      CHECK_TITEMS=`$MYSQL -e "SELECT jid FROM $TITEMS WHERE $CCOLLECTIONOWNER='${I}${REALM}' AND jid='$JID'"`
      if [ "$CHECK_TITEMS" == "" ]
      then
        # Вносим в "ростер" новый аккаунт, если его там ещё нет
        INSERT_TITEMS=`$MYSQL -e "INSERT INTO $TITEMS ($CCOLLECTIONOWNER, jid, name, $CTO, $CFROM, ask) VALUES ('${I}${REALM}', '$JID', '$NAME', 0, 1, 0)"`
        echo "Insert..."
      else
        # Обновляем парметры аккаунта, если он уже присутствует в "ростере"
        UPDATE_TITEMS=`$MYSQL -e "UPDATE $TITEMS SET name='$NAME', $CFROM=1 WHERE $CCOLLECTIONOWNER='${I}${REALM}' AND jid='$JID'"`
        echo "Update..."
      fi

      # Проверяем, нет ли уже в таблице группировки вносимого в него аккаунта
      CHECK_TGROUPS=`$MYSQL -e "SELECT jid FROM $TGROUPS WHERE $CCOLLECTIONOWNER='${I}${REALM}' AND jid='$JID' LIMIT 1"`
      if [ "$CHECK_TGROUPS" == "" ]
      then
        # Вносим в таблицу аккаунт, если его там ещё нет
        INSERT_TGROUPS=`$MYSQL -e "INSERT INTO $TGROUPS ($CCOLLECTIONOWNER, jid, $CGROUP) VALUES ('${I}${REALM}', '$JID', '$GROUP')"`
        echo "Add Group..."
      else
        # Обновляем параметры аккаунта, если он уже присутствует в таблице группировок
        UPDATE_TGROUPS=`$MYSQL -e "UPDATE $TGROUPS SET $CGROUP='$GROUP' WHERE $CCOLLECTIONOWNER='${I}${REALM}' AND jid='$JID'"`
        echo "Update Groupe..."
      fi

    fi
  done
done

exit 0

С помощью такого примитивного скрипта мы отобразим шаблон списка публичных аккаунтов на всю базу пользователей сервера Jabberd2 (XMPP). В случае необходимости частого применения этого способа придётся озаботится методикой проверки и перепроверки корректности вносимых данных, результатов работы, автоматизацией и тому подобными вещами. Для разовых случаев применения вполне подойдёт внимательность и резервное копирование перед операцией в качестве средства обеспечения целостности.


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )