diff --git a/pykolab/auth/plesk/__init__.py b/pykolab/auth/plesk/__init__.py new file mode 100644 index 0000000..bf29c28 --- /dev/null +++ b/pykolab/auth/plesk/__init__.py @@ -0,0 +1,229 @@ +# Copyright 2010-2017 Kolab Systems AG (http://www.kolabsys.com) +# +# Jeroen van Meeuwen (Kolab Systems) +# +# This program 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. + +# This program 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 this program. If not, see . +# + +import datetime + +import sqlalchemy + +from sqlalchemy import Column +from sqlalchemy import ForeignKey +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import Text + +from sqlalchemy import MetaData +from sqlalchemy import Table + +from sqlalchemy import desc +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import mapper + +try: + from sqlalchemy.orm import relationship +except: + from sqlalchemy.orm import relation as relationship + +try: + from sqlalchemy.orm import sessionmaker +except: + from sqlalchemy.orm import create_session + +import pykolab + +from pykolab import utils +from pykolab.translate import _ + +conf = pykolab.getConf() +log = pykolab.getLogger('pykolab.auth.plesk') + +metadata = MetaData() + +## +## Classes +## + +DeclarativeBase = declarative_base() + +class Object(DeclarativeBase): + __tablename__ = 'objects' + + id = Column(Integer, primary_key=True) + object_type = Column(String(256), index=True, nullable=False) + object_name = Column(String(256), index=True, nullable=False) + + params = relationship('ObjectParam') + +class ObjectParam(DeclarativeBase): + __tablename__ = 'object_params' + + id = Column(Integer, primary_key=True) + object_id = Column(Integer, ForeignKey('objects.id', ondelete="CASCADE"), nullable=False) + key = Column(String(256), index=True, nullable=False) + value = Column(Text, nullable=False) + +class Plesk(pykolab.base.Base): + db = None + + def __init__(self, domain=None): + self.domain = domain + + def connect(self): + self.__init_db() + + def extract_recipient_addresses(self, entry): + _object = self.db.query(Object).get(entry['id']) + + if _object is None: + return [] + + addresses = [] + + addresses.append(_object.object_name) + + for param in _object.params: + if param.key == 'alias': + addresses.append(param.value) + + return addresses + + def find_resource(self, recipient_address): + _objects = self.db.query(Object).filter_by(object_name=recipient_address).all() + + return [] + + def get_entry_attributes(self, entry, attributes): + _object = self.db.query(Object).get((int)(entry)) + + if _object is None: + return None + + attrs = {'id': entry} + + attrs['mail'] = _object.object_name + + for param in _object.params: + if param.key not in attrs: + attrs[param.key] = [] + + attrs[param.key].append(param.value) + + return attrs + + def list_delegators(self, user): + return [] + + def _disconnect(self): + self.db.close() + + def _find_user_dn(self, recipient_address, kolabuser=False): + _object = self.db.query(Object).filter_by(object_name=recipient_address).first() + + if _object is None: + return None + + return (str)(_object.id) + + def __init_db(self): + if not self.db is None: + return + + db_uri = conf.get('plesk', 'sql_uri') + + echo = conf.debuglevel > 8 + engine = create_engine(db_uri, echo=echo) + Session = sessionmaker(bind=engine) + self.db = Session() + + import dbhash + + virtual_domains = dbhash.open("/var/spool/postfix/plesk/virtual_domains.db") + + plesk_domains = [] + + for k, v in virtual_domains.iteritems(): + k = k.strip().replace('\x00', '') + if k not in plesk_domains: + plesk_domains.append(k) + + current_domains = self.db.query(Object).filter_by(object_type='domain').all() + + current_domains = [x.object_name for x in current_domains] + + added_domains = list(set(plesk_domains) - set(current_domains)) + removed_domains = list(set(current_domains) - set(plesk_domains)) + + changed = False + + for domain in added_domains: + self.db.add(Object(object_type='domain', object_name=domain)) + changed = True + + for domain in removed_domains: + _domain = self.db.query(Object).filter_by(object_type='domain', object_name=domain).first() + self.db.remove(_domain) + changed = True + + virtual_recipients = dbhash.open("/var/spool/postfix/plesk/virtual.db") + + plesk_recipients = {} + + for k, v in virtual_recipients.iteritems(): + k = k.strip().replace('\x00', '') + v = v.strip().replace('\x00', '') + + if not '@' in k and not '@' in v: + continue + + if v.endswith('@localhost.localdomain'): + continue + + if not v in plesk_recipients: + plesk_recipients[v] = [] + + if not k == v: + plesk_recipients[v].append(k) + + _current_recipients = self.db.query(Object).filter_by(object_type='mail_user').all() + + current_recipients = {} + + for current_recipient in _current_recipients: + if not current_recipient.object_name in current_recipients: + current_recipients[current_recipient.object_name] = [] + + added_objects = list(set(plesk_recipients.keys()) - set(current_recipients.keys())) + removed_objects = list(set(current_recipients.keys()) - set(plesk_recipients.keys())) + + for added in added_objects: + _object = Object(object_type='mail_user', object_name=added) + self.db.add(_object) + changed = True + + if len(plesk_recipients[added]) > 0: + for alias in plesk_recipients[added]: + _object.params.append(ObjectParam(key='alias', value=alias)) + + for removed in removed_objects: + _object = self.db.query(Object).filter_by(object_type='mail_user', object_name=removed).first() + self.db.remove(_object) + changed = True + + if changed: + self.db.commit() +