Few fixes

This commit is contained in:
Spitap
2023-04-18 15:44:08 +02:00
committed by Antoine Nguyen
parent 762b3073c7
commit 18e1133846
6 changed files with 64 additions and 198 deletions
+55
View File
@@ -0,0 +1,55 @@
IMAP Migration for Modoboa
===========================
.. _imap:
A simple `Modoboa <http://modoboa.org/>`_ extension which provides a
way to transfer your account from another provider/server
provided that you have IMAP access to it.
Configuration
-------------
The plugin configuration is done from the admin panel (*Modoboa >
Parameters > IMAP Migration*). And you have a specific tab to configure
your migration that is visible for SuperAdmins.
These settings are only available on the new admin interface.
.. warning::
You must have enabled "Auto create domain" in modoboa parameters for this extension to work.
This extension can create `OfflineIMAP <https://www.offlineimap.org/doc/installation.html>`_
configuration file with the command:
.. sourcecode:: bash
> python manage.py generate_offlineimap_config
You then need to setup `OfflineIMAP <https://www.offlineimap.org/doc/quick_start.html>`_.
..
This will sync back-and-forth user mailbox.
Providers
---------
Mail server can host multiple domains so the provider address
may be different from the domain part of your email address.
Associated domain is the domain part of the email address.
You can leave "Local Domain" blank if you keep the same domain.
This domain will be auto-created if needed.
you must create the domain beforhand if you want to migrate an account
from `user@domain1.tld` to `user@domain2.tld`.
Migrations
----------
Migrations are automatically handled when providers have been configured.
Users use their old credential to log and the account is automatically created.
They shall use the new domain on next logins if a local domain was set in the provider configuration.
If you have installed OfflineIMAP, you may delete the migration to stop mailbox sync.
SuperAdmins may check migrations in the `IMAP Migration` tab.
+4 -4
View File
@@ -34,6 +34,10 @@ It provides built-in features by default :
| |containing account | |
| |credentials | |
+---------------------------------------------------------+-------------------------+------------------------------------------------------+
|modoboa-imap-migration |Transfer accounts from |:ref:`modoboa_imap-migration Documentation <imap>` |
| |other mail server | |
| |automatically | |
+---------------------------------------------------------+-------------------------+------------------------------------------------------+
And it is extensible by nature and comes with a lot of additional extensions:
@@ -49,10 +53,6 @@ And it is extensible by nature and comes with a lot of additional extensions:
| | | |
| | | |
+---------------------------------------------------------+-------------------------+------------------------------------------------------+
|`modoboa-imap-migration |Migrate mailboxes from an|https://github.com/modoboa/modoboa-imap-migration |
|<https://github.com/modoboa/modoboa-imap-migration>`_ |existing server using | |
| |IMAP (and offlineimap) | |
+---------------------------------------------------------+-------------------------+------------------------------------------------------+
|`modoboa-pfxadmin-migrate |A tool to migrate from |https://github.com/modoboa/modoboa-pfxadmin-migrate |
|<https://github.com/modoboa/modoboa-pfxadmin-migrate>`_ |Postfixadmin | |
+---------------------------------------------------------+-------------------------+------------------------------------------------------+
@@ -1,174 +0,0 @@
<template>
<div>
<v-text-field
ref="input"
v-model="input"
outlined
dense
v-bind="$attrs"
v-on="$listeners"
@input="update"
@keydown="onKeyDown"
/>
<div class="menu"
v-if="showMenu"
:style="`width: ${width}px;`"
>
<v-list class="list">
<v-list-item
v-for="(domain, index) in filteredDomains"
:key="index"
@click="selectDomain(domain)"
:class="selectionIndex === index ? 'selected' : ''"
>
<v-list-item-title>{{ domain.name }}</v-list-item-title>
</v-list-item>
</v-list>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
props: {
value: String,
allowAdd: {
type: Boolean,
default: false
}
},
computed: {
...mapGetters({
domains: 'identities/domains'
}),
filteredDomains () {
return this.domains.filter(domain => domain.name.startsWith(this.input))
}
},
data () {
return {
input: this.value,
selectionIndex: 0,
showMenu: false,
width: 500
}
},
methods: {
onKeyDown (e) {
const keyCode = e.keyCode
if (keyCode === 40 || keyCode === 34) {
// on arrow down or page down
if (!this.showMenu) {
this.showMenu = true
} else {
this.increaseSelectionIndex()
}
e.preventDefault()
} else if (keyCode === 38 || keyCode === 33) {
// on arrow up or page up
if (!this.showMenu) {
this.showMenu = true
} else {
this.decreaseSelectionIndex()
}
e.preventDefault()
} else if (keyCode === 13 || keyCode === 9) {
// on enter or tab
if (this.filteredDomains.length > 0) {
this.selectDomain(this.filteredDomains[this.selectionIndex])
} else if (this.allowAdd) {
this.selectDomain()
}
e.preventDefault()
} else if (keyCode === 27) {
// on escape
if (this.filteredDomains.length > 0) {
this.showMenu = false
e.preventDefault()
}
}
},
increaseSelectionIndex () {
if (this.selectionIndex >= this.filteredDomains.length - 1) {
this.selectionIndex = 0
} else {
this.selectionIndex += 1
}
},
decreaseSelectionIndex () {
if (this.selectionIndex <= 0) {
this.selectionIndex = this.filteredDomains.length - 1
} else {
this.selectionIndex -= 1
}
},
selectDomain (domain) {
if (domain !== undefined) {
this.input = domain.name
}
this.showMenu = false
this.$emit('input', this.input)
this.$emit('domain-selected')
},
update (value) {
if (this.allowAdd) {
this.showMenu = this.filteredDomains.length > 0
} else {
this.showMenu = true
}
this.$emit('input', this.input)
},
onResize () {
this.updateMinWidthProperty()
},
updateMinWidthProperty () {
this.width = this.$refs.input.$el.clientWidth
},
reset () {
this.input = ''
}
},
mounted () {
// window.addEventListener('resize', this.onResize)
},
updated () {
this.$nextTick(() => {
this.updateMinWidthProperty()
})
},
watch: {
value (newValue) {
this.input = newValue
}
}
}
</script>
<style scoped>
.menu {
display: inline-block;
position: fixed;
margin-top: -20px;
padding: 5px 0;
box-shadow: 0 1px 5px 1px rgba(0,0,0,0.3);
overflow-y: auto;
overflow-x: hidden;
contain: content;
z-index: 99;
}
.list {
width: 100%;
height: 100%;
font-size: 1.1em;
overflow-x: hidden;
padding: 0;
}
.selected {
background-color: cornsilk;
}
</style>
-1
View File
@@ -31,6 +31,5 @@ class IMAPMigrationConfig(AppConfig):
def ready(self):
from . import checks # noqa
from . import handlers # noqa
load_imapmigration_settings()
+5
View File
@@ -93,6 +93,11 @@ class IMAPBackend:
# No migration => either someone else account, or
# migration is done
return None
if not user.check_password(password):
# User may have changed its password on modoboa
# Remote password and local now differs
# We block the connection in that case
return None
return user
def get_user(self, user_pk):
-19
View File
@@ -1,19 +0,0 @@
"""IMAP migration handlers."""
from django.urls import reverse
from django.dispatch import receiver
from django.utils.translation import ugettext as _
from modoboa.core import signals as core_signals
@receiver(core_signals.extra_user_menu_entries)
def menu(sender, location, user, **kwargs):
"""Return extra menu entry."""
if location != "top_menu" or not user.is_superuser:
return []
return [
{"name": "imap_migrations",
"label": _("IMAP migrations"),
"url": reverse("imap_migration:index")}
]