diff --git a/admin/empty b/admin/empty deleted file mode 100644 index e69de29b..00000000 diff --git a/admin/freeposte/__init__.py b/admin/freeposte/__init__.py new file mode 100644 index 00000000..78dd88c1 --- /dev/null +++ b/admin/freeposte/__init__.py @@ -0,0 +1,16 @@ +from flask import Flask +from flask_sqlalchemy import SQLAlchemy + + + +# Create application +app = Flask(__name__) + +app.config.update({ + 'SQLALCHEMY_DATABASE_URI': 'sqlite:////tmp/freeposte.db' +}) + +# Create the database +db = SQLAlchemy(app) + +from freeposte import views diff --git a/admin/freeposte/__pycache__/__init__.cpython-35.pyc b/admin/freeposte/__pycache__/__init__.cpython-35.pyc new file mode 100644 index 00000000..3a4047b0 Binary files /dev/null and b/admin/freeposte/__pycache__/__init__.cpython-35.pyc differ diff --git a/admin/freeposte/__pycache__/models.cpython-35.pyc b/admin/freeposte/__pycache__/models.cpython-35.pyc new file mode 100644 index 00000000..2b21c3eb Binary files /dev/null and b/admin/freeposte/__pycache__/models.cpython-35.pyc differ diff --git a/admin/freeposte/__pycache__/views.cpython-35.pyc b/admin/freeposte/__pycache__/views.cpython-35.pyc new file mode 100644 index 00000000..3525948a Binary files /dev/null and b/admin/freeposte/__pycache__/views.cpython-35.pyc differ diff --git a/admin/freeposte/models.py b/admin/freeposte/models.py new file mode 100644 index 00000000..98bbddc4 --- /dev/null +++ b/admin/freeposte/models.py @@ -0,0 +1,34 @@ +from freeposte import db + + +class Domain(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80)) + max_users = db.Column(db.Integer) + max_aliases = db.Column(db.Integer) + + def __str__(self): + return self.name + + +class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(80)) + domain_id = db.Column(db.Integer, db.ForeignKey(Domain.id)) + domain = db.relationship(Domain, backref='users') + password = db.Column(db.String(255)) + quota_bytes = db.Column(db.Integer()) + + def __str__(self): + return '{0}@{1}'.format(self.username, self.domain.name) + + +class Alias(db.Model): + id = db.Column(db.Integer, primary_key=True) + localpart = db.Column(db.String(80)) + domain_id = db.Column(db.Integer, db.ForeignKey(Domain.id)) + domain = db.relationship(Domain, backref='aliases') + destination = db.Column(db.String()) + + def __str__(self): + return '{0}@{1}'.format(self.username, self.domain.name) diff --git a/admin/freeposte/views.py b/admin/freeposte/views.py new file mode 100644 index 00000000..2f9e53c0 --- /dev/null +++ b/admin/freeposte/views.py @@ -0,0 +1,26 @@ +import flask_admin as admin +from flask_admin.contrib import sqla + +from freeposte import app, db, models + + +# Flask admin +admin = admin.Admin(app, name='Freeposte.io', template_mode='bootstrap3') + + +class DomainModelView(sqla.ModelView): + pass + + +class UserModelView(sqla.ModelView): + pass + + +class AliasModelView(sqla.ModelView): + pass + + +# Add views +admin.add_view(DomainModelView(models.Domain, db.session)) +admin.add_view(UserModelView(models.User, db.session)) +admin.add_view(AliasModelView(models.Alias, db.session)) diff --git a/admin/requirements.txt b/admin/requirements.txt new file mode 100644 index 00000000..fb675a95 --- /dev/null +++ b/admin/requirements.txt @@ -0,0 +1,2 @@ +Flask +Flask-SQLAlchemy diff --git a/admin/run.py b/admin/run.py new file mode 100644 index 00000000..c9cfd78e --- /dev/null +++ b/admin/run.py @@ -0,0 +1,5 @@ +from freeposte import app + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/admin/testdb.py b/admin/testdb.py new file mode 100644 index 00000000..c7417c4c --- /dev/null +++ b/admin/testdb.py @@ -0,0 +1,7 @@ +from freeposte import db, models + + +if __name__ == "__main__": + db.drop_all() + db.create_all() + db.session.commit() diff --git a/config/dovecot/dovecot-sql.conf.ext b/config/dovecot/dovecot-sql.conf.ext index 97610abb..320da098 100644 --- a/config/dovecot/dovecot-sql.conf.ext +++ b/config/dovecot/dovecot-sql.conf.ext @@ -3,8 +3,14 @@ connect = /data/freeposte.db # Return the user hashed password password_query = \ - SELECT password FROM users, domains WHERE username = '%n' AND domain = '%d' + SELECT password \ + FROM users INNER JOIN domains ON users.domain_id = domains.id \ + WHERE domains.name = '%d' \ + AND users.username = '%n' # Mostly get the user quota user_query = \ - SELECT '*:bytes=' || quota_bytes AS quota_rule FROM users WHERE username = '%n' AND domain = '%d' + SELECT '*:bytes=' || users.quota_bytes AS quota_rule \ + FROM users INNER JOIN domains ON users.domain_id = domains.id \ + WHERE domains.name = '%d' \ + AND users.username = '%n' diff --git a/config/postfix/sqlite-virtual_alias_maps.cf b/config/postfix/sqlite-virtual_alias_maps.cf index 1d80e00c..009c6fe1 100644 --- a/config/postfix/sqlite-virtual_alias_maps.cf +++ b/config/postfix/sqlite-virtual_alias_maps.cf @@ -1,2 +1,6 @@ dbpath = /data/freeposte.db -query = SELECT destination FROM aliases WHERE localpart = '%u' AND domain = '%d' +query = \ + SELECT destination \ + FROM aliases INNER JOIN domains ON aliases.domain_id = domains.id \ + WHERE domains.name = '%d' \ + AND aliases.localpart = '%n' diff --git a/config/postfix/sqlite-virtual_mailbox_domains.cf b/config/postfix/sqlite-virtual_mailbox_domains.cf index 91002d8e..4134a848 100644 --- a/config/postfix/sqlite-virtual_mailbox_domains.cf +++ b/config/postfix/sqlite-virtual_mailbox_domains.cf @@ -1,2 +1,2 @@ dbpath = /data/freeposte.db -query = SELECT domain FROM domains WHERE domain='%s' +query = SELECT name FROM domains WHERE domain='%s'