Compare commits
No commits in common. "main" and "trustchain" have entirely different histories.
main
...
trustchain
|
@ -0,0 +1,48 @@
|
|||
# Generated by Django 2.2.28 on 2023-07-22 08:01
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('orchestration', '__first__'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SystemUser',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('username', models.CharField(help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[orchestra.core.validators.validate_username], verbose_name='username')),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('home', models.CharField(blank=True, help_text='Starting location when login with this no-shell user.', max_length=256, verbose_name='home')),
|
||||
('directory', models.CharField(blank=True, help_text="Optional directory relative to user's home.", max_length=256, verbose_name='directory')),
|
||||
('shell', models.CharField(choices=[('/dev/null', 'No shell, FTP only'), ('/bin/rssh', 'No shell, SFTP/RSYNC only'), ('/usr/bin/git-shell', 'No shell, GIT only'), ('/bin/bash', '/bin/bash')], default='/dev/null', max_length=32, verbose_name='shell')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='systemusers', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('groups', models.ManyToManyField(blank=True, help_text='A new group will be created for the user. Which additional groups would you like them to be a member of?', to='systemusers.SystemUser')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WebappUsers',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('username', models.CharField(help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[orchestra.core.validators.validate_username], verbose_name='username')),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('home', models.CharField(blank=True, help_text='Starting location when login with this no-shell user.', max_length=256, verbose_name='home')),
|
||||
('shell', models.CharField(choices=[('/dev/null', 'No shell, FTP only'), ('/bin/rssh', 'No shell, SFTP/RSYNC only'), ('/usr/bin/git-shell', 'No shell, GIT only'), ('/bin/bash', '/bin/bash')], default='/dev/null', max_length=32, verbose_name='shell')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('target_server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='orchestration.Server', verbose_name='Server')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('username', 'target_server')},
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,43 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.forms import ReadOnlyPasswordHashField
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.html import format_html
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.core import validators
|
||||
from orchestra.contrib.systemusers.models import WebappUsers
|
||||
from .models import WebApp
|
||||
|
||||
|
||||
class WebappCreationForm(forms.ModelForm):
|
||||
username = forms.CharField(label=_("Username"), max_length=16,
|
||||
required=False, validators=[validators.validate_name],
|
||||
help_text=_("Required. 16 characters or fewer. Letters, digits and "
|
||||
"@/./+/-/_ only."),
|
||||
error_messages={
|
||||
'invalid': _("This value may contain 16 characters or fewer, only letters, numbers and "
|
||||
"@/./+/-/_ characters.")})
|
||||
user = forms.ModelChoiceField(required=False, queryset=WebappUsers.objects)
|
||||
password1 = forms.CharField(label=_("Password"), required=False,
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'off'}),
|
||||
validators=[validators.validate_password])
|
||||
password2 = forms.CharField(label=_("Password confirmation"), required=False,
|
||||
widget=forms.PasswordInput,
|
||||
help_text=_("Enter the same password as above, for verification."))
|
||||
|
||||
class Meta:
|
||||
model = WebApp
|
||||
fields = ('username', 'account', 'type')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(WebappCreationForm, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
def clean_password2(self):
|
||||
password1 = self.cleaned_data.get("password1")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
if password1 and password2 and password1 != password2:
|
||||
msg = _("The two password fields didn't match.")
|
||||
raise ValidationError(msg)
|
||||
return password2
|
|
@ -0,0 +1,64 @@
|
|||
# Generated by Django 2.2.28 on 2023-08-17 09:14
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('orchestration', '__first__'),
|
||||
('domains', '__first__'),
|
||||
('webapps', '0004_auto_20230817_1108'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Content',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('path', models.CharField(blank=True, max_length=256, validators=[orchestra.core.validators.validate_url_path], verbose_name='path')),
|
||||
('webapp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='webapps.WebApp', verbose_name='web application')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Website',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('protocol', models.CharField(choices=[('http', 'HTTP'), ('https', 'HTTPS'), ('http/https', 'HTTP and HTTPS'), ('https-only', 'HTTPS only')], default='http', help_text='Select the protocol(s) for this website<br><tt>HTTPS only</tt> performs a redirection from <tt>http</tt> to <tt>https</tt>.', max_length=16, verbose_name='protocol')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='active')),
|
||||
('comments', models.TextField(blank=True, default='')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('contents', models.ManyToManyField(through='websites.Content', to='webapps.WebApp')),
|
||||
('domains', models.ManyToManyField(blank=True, related_name='websites', to='domains.Domain', verbose_name='domains')),
|
||||
('target_server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', to='orchestration.Server', verbose_name='Target Server')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('name', 'account', 'target_server')},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WebsiteDirective',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(choices=[(None, '-------'), ('HTTPD', [('redirect', 'Redirection'), ('proxy', 'Proxy'), ('error-document', 'ErrorDocumentRoot')]), ('SSL', [('ssl-ca', 'SSL CA'), ('ssl-cert', 'SSL cert'), ('ssl-key', 'SSL key')]), ('ModSecurity', [('sec-rule-remove', 'SecRuleRemoveById'), ('sec-engine', 'SecRuleEngine Off')]), ('SaaS', [('wordpress-saas', 'WordPress SaaS'), ('dokuwiki-saas', 'DokuWiki SaaS'), ('drupal-saas', 'Drupdal SaaS'), ('moodle-saas', 'Moodle SaaS')])], db_index=True, max_length=128, verbose_name='name')),
|
||||
('value', models.CharField(blank=True, max_length=256, verbose_name='value')),
|
||||
('website', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='directives', to='websites.Website', verbose_name='web site')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='website',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websites.Website', verbose_name='web site'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='content',
|
||||
unique_together={('website', 'path')},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,64 @@
|
|||
# Generated by Django 2.2.28 on 2023-08-17 09:42
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('orchestration', '__first__'),
|
||||
('domains', '__first__'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('webapps', '0004_auto_20230817_1108'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Content',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('path', models.CharField(blank=True, max_length=256, validators=[orchestra.core.validators.validate_url_path], verbose_name='path')),
|
||||
('webapp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='webapps.WebApp', verbose_name='web application')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Website',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('protocol', models.CharField(choices=[('http', 'HTTP'), ('https', 'HTTPS'), ('http/https', 'HTTP and HTTPS'), ('https-only', 'HTTPS only')], default='http', help_text='Select the protocol(s) for this website<br><tt>HTTPS only</tt> performs a redirection from <tt>http</tt> to <tt>https</tt>.', max_length=16, verbose_name='protocol')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='active')),
|
||||
('comments', models.TextField(blank=True, default='')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('contents', models.ManyToManyField(through='websites.Content', to='webapps.WebApp')),
|
||||
('domains', models.ManyToManyField(blank=True, related_name='websites', to='domains.Domain', verbose_name='domains')),
|
||||
('target_server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', to='orchestration.Server', verbose_name='Target Server')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('name', 'account')},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WebsiteDirective',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(choices=[(None, '-------'), ('HTTPD', [('redirect', 'Redirection'), ('proxy', 'Proxy'), ('error-document', 'ErrorDocumentRoot')]), ('SSL', [('ssl-ca', 'SSL CA'), ('ssl-cert', 'SSL cert'), ('ssl-key', 'SSL key')]), ('ModSecurity', [('sec-rule-remove', 'SecRuleRemoveById'), ('sec-engine', 'SecRuleEngine Off')]), ('SaaS', [('wordpress-saas', 'WordPress SaaS'), ('dokuwiki-saas', 'DokuWiki SaaS'), ('drupal-saas', 'Drupdal SaaS'), ('moodle-saas', 'Moodle SaaS')])], db_index=True, max_length=128, verbose_name='name')),
|
||||
('value', models.CharField(blank=True, max_length=256, verbose_name='value')),
|
||||
('website', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='directives', to='websites.Website', verbose_name='web site')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='website',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websites.Website', verbose_name='web site'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='content',
|
||||
unique_together={('website', 'path')},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,64 @@
|
|||
# Generated by Django 2.2.28 on 2023-08-17 09:08
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('domains', '__first__'),
|
||||
('orchestration', '__first__'),
|
||||
('webapps', '0004_auto_20230817_1108'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Content',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('path', models.CharField(blank=True, max_length=256, validators=[orchestra.core.validators.validate_url_path], verbose_name='path')),
|
||||
('webapp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='webapps.WebApp', verbose_name='web application')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Website',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('protocol', models.CharField(choices=[('http', 'HTTP'), ('https', 'HTTPS'), ('http/https', 'HTTP and HTTPS'), ('https-only', 'HTTPS only')], default='http', help_text='Select the protocol(s) for this website<br><tt>HTTPS only</tt> performs a redirection from <tt>http</tt> to <tt>https</tt>.', max_length=16, verbose_name='protocol')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='active')),
|
||||
('comments', models.TextField(blank=True, default='')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('contents', models.ManyToManyField(through='websites.Content', to='webapps.WebApp')),
|
||||
('domains', models.ManyToManyField(blank=True, related_name='websites', to='domains.Domain', verbose_name='domains')),
|
||||
('target_server', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='websites', to='orchestration.Server', verbose_name='Target Server')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('name', 'account', 'target_server')},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='WebsiteDirective',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(choices=[(None, '-------'), ('HTTPD', [('redirect', 'Redirection'), ('proxy', 'Proxy'), ('error-document', 'ErrorDocumentRoot')]), ('SSL', [('ssl-ca', 'SSL CA'), ('ssl-cert', 'SSL cert'), ('ssl-key', 'SSL key')]), ('ModSecurity', [('sec-rule-remove', 'SecRuleRemoveById'), ('sec-engine', 'SecRuleEngine Off')]), ('SaaS', [('wordpress-saas', 'WordPress SaaS'), ('dokuwiki-saas', 'DokuWiki SaaS'), ('drupal-saas', 'Drupdal SaaS'), ('moodle-saas', 'Moodle SaaS')])], db_index=True, max_length=128, verbose_name='name')),
|
||||
('value', models.CharField(blank=True, max_length=256, verbose_name='value')),
|
||||
('website', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='directives', to='websites.Website', verbose_name='web site')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='content',
|
||||
name='website',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='websites.Website', verbose_name='web site'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='content',
|
||||
unique_together={('website', 'path')},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,3 @@
|
|||
[Trash Info]
|
||||
Path=orchestra/contrib/systemusers/migrations/0001_initial.py
|
||||
DeletionDate=2023-07-22T10:04:42
|
|
@ -0,0 +1,3 @@
|
|||
[Trash Info]
|
||||
Path=orchestra/contrib/webapps/forms.py
|
||||
DeletionDate=2023-07-24T18:44:25
|
|
@ -0,0 +1,3 @@
|
|||
[Trash Info]
|
||||
Path=orchestra/contrib/websites/migrations
|
||||
DeletionDate=2023-08-17T11:42:31
|
|
@ -0,0 +1,3 @@
|
|||
[Trash Info]
|
||||
Path=orchestra/contrib/websites/migrations
|
||||
DeletionDate=2023-08-17T11:45:11
|
|
@ -0,0 +1,3 @@
|
|||
[Trash Info]
|
||||
Path=orchestra/contrib/websites/migrations
|
||||
DeletionDate=2023-08-17T11:14:47
|
|
@ -7,9 +7,3 @@
|
|||
local_settings.py
|
||||
build
|
||||
*.egg-info
|
||||
/.Trash*
|
||||
/.git
|
||||
/.idea
|
||||
|
||||
.idea
|
||||
.Trash-1000/
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="24">
|
||||
<item index="0" class="java.lang.String" itemvalue="paramiko" />
|
||||
<item index="1" class="java.lang.String" itemvalue="fabric" />
|
||||
<item index="2" class="java.lang.String" itemvalue="django-admin-tools" />
|
||||
<item index="3" class="java.lang.String" itemvalue="django-fluent-dashboard" />
|
||||
<item index="4" class="java.lang.String" itemvalue="phonenumbers" />
|
||||
<item index="5" class="java.lang.String" itemvalue="jsonfield" />
|
||||
<item index="6" class="java.lang.String" itemvalue="amqp" />
|
||||
<item index="7" class="java.lang.String" itemvalue="python-dateutil" />
|
||||
<item index="8" class="java.lang.String" itemvalue="django-localflavor" />
|
||||
<item index="9" class="java.lang.String" itemvalue="ecdsa" />
|
||||
<item index="10" class="java.lang.String" itemvalue="kombu" />
|
||||
<item index="11" class="java.lang.String" itemvalue="django-extensions" />
|
||||
<item index="12" class="java.lang.String" itemvalue="celery" />
|
||||
<item index="13" class="java.lang.String" itemvalue="django-countries" />
|
||||
<item index="14" class="java.lang.String" itemvalue="Pygments" />
|
||||
<item index="15" class="java.lang.String" itemvalue="django-filter" />
|
||||
<item index="16" class="java.lang.String" itemvalue="Django" />
|
||||
<item index="17" class="java.lang.String" itemvalue="anyjson" />
|
||||
<item index="18" class="java.lang.String" itemvalue="django-celery" />
|
||||
<item index="19" class="java.lang.String" itemvalue="djangorestframework" />
|
||||
<item index="20" class="java.lang.String" itemvalue="Markdown" />
|
||||
<item index="21" class="java.lang.String" itemvalue="django-iban" />
|
||||
<item index="22" class="java.lang.String" itemvalue="billiard" />
|
||||
<item index="23" class="java.lang.String" itemvalue="passlib" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="JavaScriptSettings">
|
||||
<option name="languageLevel" value="ES6" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (zfs-blues)" project-jdk-type="Python SDK" />
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/orchestra.iml" filepath="$PROJECT_DIR$/.idea/orchestra.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="django" name="Django">
|
||||
<configuration>
|
||||
<option name="rootFolder" value="$MODULE_DIR$/orchestra/conf/project_template" />
|
||||
<option name="settingsModule" value="orchestra/settings.py" />
|
||||
<option name="manageScript" value="manage.py" />
|
||||
<option name="environment" value="<map/>" />
|
||||
<option name="doNotUseTestRunner" value="false" />
|
||||
<option name="trackFilePattern" value="migrations" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="TemplatesService">
|
||||
<option name="TEMPLATE_CONFIGURATION" value="Django" />
|
||||
<option name="TEMPLATE_FOLDERS">
|
||||
<list>
|
||||
<option value="$MODULE_DIR$/orchestra/contrib/bills/templates" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="TestRunnerService">
|
||||
<option name="projectConfiguration" value="pytest" />
|
||||
<option name="PROJECT_TEST_RUNNER" value="pytest" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,261 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="573278bf-2cdd-4afd-973a-1660f3364e9d" name="Default Changelist" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/api/actions.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/api/actions.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/api/serializers.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/api/serializers.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/accounts/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/accounts/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/accounts/serializers.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/accounts/serializers.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/admin.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/admin.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/locale/ca/LC_MESSAGES/django.mo" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/locale/ca/LC_MESSAGES/django.mo" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/locale/ca/LC_MESSAGES/django.po" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/locale/ca/LC_MESSAGES/django.po" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/locale/es/LC_MESSAGES/django.mo" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/locale/es/LC_MESSAGES/django.mo" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/locale/es/LC_MESSAGES/django.po" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/locale/es/LC_MESSAGES/django.po" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/settings.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/settings.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/templates/bills/microspective.css" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/templates/bills/microspective.css" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/bills/templates/bills/microspective.html" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/bills/templates/bills/microspective.html" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/databases/admin.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/databases/admin.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/databases/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/databases/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/domains/admin.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/domains/admin.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/domains/backends.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/domains/backends.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/domains/forms.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/domains/forms.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/domains/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/domains/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/domains/settings.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/domains/settings.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/domains/validators.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/domains/validators.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/lists/api.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/lists/api.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/lists/backends.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/lists/backends.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/lists/serializers.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/lists/serializers.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/mailboxes/backends.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/mailboxes/backends.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/orchestration/backends.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/orchestration/backends.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/payments/actions.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/payments/actions.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/payments/methods/sepadirectdebit.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/payments/methods/sepadirectdebit.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/saas/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/saas/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/saas/services/helpers.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/saas/services/helpers.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/systemusers/backends.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/systemusers/backends.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/systemusers/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/systemusers/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/webapps/backends/php.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/webapps/backends/php.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/webapps/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/webapps/models.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/webapps/options.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/webapps/options.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/webapps/serializers.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/webapps/serializers.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/webapps/signals.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/webapps/signals.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/websites/admin.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/websites/admin.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/websites/backends/apache.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/websites/backends/apache.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/orchestra/contrib/websites/models.py" beforeDir="false" afterPath="$PROJECT_DIR$/orchestra/contrib/websites/models.py" afterDir="false" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/orchestra/contrib/lists/backends.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="589">
|
||||
<caret line="124" column="4" lean-forward="true" selection-start-line="124" selection-start-column="4" selection-end-line="124" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/orchestra/contrib/orchestration/backends.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="4256">
|
||||
<caret line="224" column="8" selection-start-line="224" selection-start-column="8" selection-end-line="224" selection-end-column="8" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<findStrings>
|
||||
<find>check_origin</find>
|
||||
<find>updated_</find>
|
||||
<find>UPDATED_CHECK_ORIGIN</find>
|
||||
</findStrings>
|
||||
<dirStrings>
|
||||
<dir>$PROJECT_DIR$/orchestra/contrib/lists</dir>
|
||||
</dirStrings>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/orchestra/contrib/lists/backends.py" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectConfigurationFiles">
|
||||
<option name="files">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/.idea/orchestra.iml" />
|
||||
<option value="$PROJECT_DIR$/.idea/misc.xml" />
|
||||
<option value="$PROJECT_DIR$/.idea/modules.xml" />
|
||||
<option value="$PROJECT_DIR$/.idea/vcs.xml" />
|
||||
<option value="$PROJECT_DIR$/.idea/inspectionProfiles/Project_Default.xml" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<option name="x" value="959" />
|
||||
<option name="width" value="961" />
|
||||
<option name="height" value="1056" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator proportions="" version="1">
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="orchestra" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="orchestra" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="orchestra" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="orchestra" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="orchestra" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="orchestra" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="orchestra" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="orchestra" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="contrib" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="orchestra" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="orchestra" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="orchestra" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="contrib" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="lists" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="node.js.detected.package.eslint" value="true" />
|
||||
<property name="node.js.detected.package.tslint" value="true" />
|
||||
<property name="node.js.path.for.package.eslint" value="project" />
|
||||
<property name="node.js.path.for.package.tslint" value="project" />
|
||||
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
||||
<property name="node.js.selected.package.tslint" value="(autodetect)" />
|
||||
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
|
||||
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="orchestra" type="Python.DjangoServer" factoryName="Django server">
|
||||
<module name="orchestra" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="" />
|
||||
<option name="IS_MODULE_SDK" value="false" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="launchJavascriptDebuger" value="false" />
|
||||
<option name="port" value="8000" />
|
||||
<option name="host" value="" />
|
||||
<option name="additionalOptions" value="" />
|
||||
<option name="browserUrl" value="" />
|
||||
<option name="runTestServer" value="false" />
|
||||
<option name="runNoReload" value="false" />
|
||||
<option name="useCustomRunCommand" value="false" />
|
||||
<option name="customRunCommand" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SvnConfiguration">
|
||||
<configuration />
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="573278bf-2cdd-4afd-973a-1660f3364e9d" name="Default Changelist" comment="" />
|
||||
<created>1582799032840</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1582799032840</updated>
|
||||
<workItem from="1582799053215" duration="2986000" />
|
||||
<workItem from="1582882260836" duration="4157000" />
|
||||
<workItem from="1582890671958" duration="815000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TimeTrackingManager">
|
||||
<option name="totallyTimeSpent" value="7958000" />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="-1" y="0" width="1922" height="1057" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.124068156" />
|
||||
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
|
||||
<window_info id="Favorites" order="2" side_tool="true" />
|
||||
<window_info anchor="bottom" id="Message" order="0" />
|
||||
<window_info anchor="bottom" id="Find" order="1" />
|
||||
<window_info anchor="bottom" id="Run" order="2" />
|
||||
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
|
||||
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
|
||||
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
||||
<window_info anchor="bottom" id="TODO" order="6" />
|
||||
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
|
||||
<window_info anchor="bottom" id="Version Control" order="8" />
|
||||
<window_info anchor="bottom" id="Database Changes" order="9" />
|
||||
<window_info anchor="bottom" id="Event Log" order="10" side_tool="true" />
|
||||
<window_info anchor="bottom" id="Terminal" order="11" />
|
||||
<window_info anchor="bottom" id="Python Console" order="12" />
|
||||
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
|
||||
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
|
||||
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
|
||||
<window_info anchor="right" id="SciView" order="3" />
|
||||
<window_info anchor="right" id="Database" order="4" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/orchestra/contrib/lists/backends.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="589">
|
||||
<caret line="124" column="4" lean-forward="true" selection-start-line="124" selection-start-column="4" selection-end-line="124" selection-end-column="4" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/orchestra/contrib/orchestration/backends.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="4256">
|
||||
<caret line="224" column="8" selection-start-line="224" selection-start-column="8" selection-end-line="224" selection-end-column="8" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
|
@ -1,25 +0,0 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## master
|
||||
|
||||
## [0.2.0] 2022-03-11
|
||||
- [added] Language selector.
|
||||
- [added] Help link.
|
||||
- [changed] Order bills by creation date DESC.
|
||||
|
||||
## [0.2.0-beta1] 2022-02-05
|
||||
- [added] Write operations on mails section (addresses, mailboxes and forward).
|
||||
- [changed] Include @pangea.org mail addresses (#4).
|
||||
- [fixed] Error on login when user never has logged into the system (#6).
|
||||
- [fixed] Dashboard layout issues on tablet and mobile.
|
||||
|
||||
## [0.1] - 2020-01-29
|
||||
- Login & logout methods using backend as auth method
|
||||
- Base template with services sidebar menu
|
||||
- [added] Services views: mail, mailing list, SaaS, databases, domains and websites.
|
||||
- [added] Profile and billing views.
|
||||
- [added] Catalan and Spanish locales
|
|
@ -41,7 +41,7 @@ This deployment is **not suitable for production** but more than enough for chec
|
|||
```bash
|
||||
# Create and activate a Python virtualenv
|
||||
# Make sure python3.x-venv package is installed on your system
|
||||
python3 -m venv env-django-orchestra
|
||||
python3 -mvenv env-django-orchestra
|
||||
source env-django-orchestra/bin/activate
|
||||
|
||||
# Install Orchestra and its dependencies
|
||||
|
|
|
@ -55,7 +55,6 @@ INSTALLED_APPS = [
|
|||
'orchestra.contrib.vps',
|
||||
'orchestra.contrib.saas',
|
||||
'orchestra.contrib.miscellaneous',
|
||||
'orchestra.contrib.musician',
|
||||
|
||||
# Third-party apps
|
||||
'django_extensions',
|
||||
|
@ -71,7 +70,6 @@ INSTALLED_APPS = [
|
|||
'passlib.ext.django',
|
||||
'django_countries',
|
||||
# 'debug_toolbar',
|
||||
'bootstrap4',
|
||||
|
||||
# Django.contrib
|
||||
'django.contrib.auth',
|
||||
|
@ -221,24 +219,8 @@ EMAIL_BACKEND = 'orchestra.contrib.mailer.backends.EmailBackend'
|
|||
DATA_UPLOAD_MAX_NUMBER_FIELDS = None
|
||||
|
||||
|
||||
############################
|
||||
## MUSICIAN CONFIGURATION ##
|
||||
############################
|
||||
|
||||
# Direcction than go when you login
|
||||
LOGIN_REDIRECT_URL = 'musician:dashboard'
|
||||
|
||||
# Where requests are redirected for login
|
||||
LOGIN_URL = 'musician:login'
|
||||
|
||||
# The URL or named URL pattern where requests are redirected after logout
|
||||
LOGOUT_REDIRECT_URL = 'musician:login'
|
||||
|
||||
|
||||
USER_SUPPORT_EMAIL = "support@example.com"
|
||||
|
||||
#################################
|
||||
## 3RD PARTY APPS CONFIGURATION ##
|
||||
## 3RD PARTY APPS CONIGURATION ##
|
||||
#################################
|
||||
|
||||
# Admin Tools
|
||||
|
@ -251,7 +233,6 @@ FLUENT_DASHBOARD_ICON_THEME = '../orchestra/icons'
|
|||
|
||||
# Django-celery
|
||||
import djcelery
|
||||
|
||||
djcelery.setup_loader()
|
||||
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
|
||||
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2021-04-22 11:08
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.contrib.auth.models
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import orchestra.contrib.accounts.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('systemusers', '0001_initial'),
|
||||
('auth', '0006_require_contenttypes_0002'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Account',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
|
||||
('username', models.CharField(help_text='Required. 64 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid username.', 'invalid')], verbose_name='username')),
|
||||
('short_name', models.CharField(blank=True, max_length=64, verbose_name='short name')),
|
||||
('full_name', models.CharField(max_length=256, verbose_name='full name')),
|
||||
('email', models.EmailField(help_text='Used for password recovery', max_length=254, verbose_name='email address')),
|
||||
('type', models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('COMPANY', 'Company'), ('PUBLICBODY', 'Public body'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type')),
|
||||
('language', models.CharField(choices=[('EN', 'English')], default='EN', max_length=2, verbose_name='language')),
|
||||
('comments', models.TextField(blank=True, max_length=256, verbose_name='comments')),
|
||||
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
|
||||
('main_systemuser', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='accounts_main', to='systemusers.SystemUser')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
managers=[
|
||||
('objects', django.contrib.auth.models.UserManager()),
|
||||
],
|
||||
),
|
||||
migrations.AlterModelManagers(
|
||||
name='account',
|
||||
managers=[
|
||||
('objects', orchestra.contrib.accounts.models.AccountManager()),
|
||||
],
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='language',
|
||||
field=models.CharField(choices=[('CA', 'Catalan'), ('ES', 'Spanish'), ('EN', 'English')], default='CA', max_length=2, verbose_name='language'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='username',
|
||||
field=models.CharField(help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid username.', 'invalid')], verbose_name='username'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='language',
|
||||
field=models.CharField(choices=[('EN', 'English')], default='EN', max_length=2, verbose_name='language'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('COMPANY', 'Company'), ('PUBLICBODY', 'Public body'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='main_systemuser',
|
||||
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='accounts_main', to='systemusers.SystemUser'),
|
||||
),
|
||||
]
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 2.2.24 on 2024-07-11 12:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='language',
|
||||
field=models.CharField(choices=[('CA', 'Catalan'), ('ES', 'Spanish'), ('EN', 'English')], default='CA', max_length=2, verbose_name='language'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='account',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('INDIVIDUAL', 'Individual'), ('ASSOCIATION', 'Association'), ('CUSTOMER', 'Customer'), ('STAFF', 'Staff'), ('FRIEND', 'Friend')], default='INDIVIDUAL', max_length=32, verbose_name='type'),
|
||||
),
|
||||
]
|
|
@ -1,42 +0,0 @@
|
|||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||
BBBB BBBB BBBBBBBBBB BBBBBB BBBBBBBBBBBB
|
||||
|
||||
|
||||
BBBBB BBBBBBBBBBB
|
||||
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||
BB BBBBBBBBBBBB
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFFFFFFFFFFFXXXX
|
||||
BBBB
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
XXXXXXXX BB BBBBBBBBBBBBBBBBBBBBBXX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXXBBBBFFFFFFFFBBBBB
|
||||
BBBBB
|
||||
BB BBBBBBBBBBB
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXX gettext(u'Select %(name)s account') SSSSSS SSSSSSSS SSSSSSSXXXX
|
||||
BBBBB
|
||||
XXXXXXXX BB BBB gettext(u'Add') BBBBFFFFFFFFFFFFFFFFFFBBBBB
|
||||
XXXXXX
|
||||
BBBBBBBB
|
||||
|
||||
|
||||
BBBBB BBBBBBBBBBBBBBBBBB
|
||||
BB BBBBBBBB
|
||||
XXXXXXXXXXX XXXXXXXXXXXX XXXXXXXXXXXXXXXXXX X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XXXX X X XXXX
|
||||
XXXXXXX XXXXXXXX XXXXXXXXX gettext(u'Services') XXXXXXXXX
|
||||
BBB BBBBBBB BB BBBBBBBB
|
||||
XXXXXXX XXXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXFFFFFFFFXXXXXXXXX
|
||||
BBBBBB
|
||||
XXXXXXXXXXXXXX
|
||||
BBBBB
|
||||
BB BBBBBBBB
|
||||
XXXXXXXXXXX XXXXXXXXXXXX XXXXXXXXXXXXXXXXXX X XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XXXX XXX XXX XXXXXX
|
||||
XXXXXXX XXXXXXXX XXXXXXXXX gettext(u'Accounts') XXXXXXXXX
|
||||
BBB BBBBBBB BB BBBBBBBB
|
||||
XXXXXXX XXXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXFFFFFFFFXXXXXXXXX
|
||||
BBBBBB
|
||||
XXXXXXXXXXXXXX
|
||||
BBBBB
|
||||
|
||||
BBBBBBBB
|
|
@ -1,49 +0,0 @@
|
|||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB
|
||||
BBBB BBBB BBBBBBBBBB BBBBBBBBBB
|
||||
|
||||
|
||||
BBBBB BBBBBBBBBBB
|
||||
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||
BB BBBBBBB
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFFFFFFFFFFFXXXX
|
||||
BBBB
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
BBBBB
|
||||
XXXXXXXX FFFFFFFF
|
||||
XXXXXX
|
||||
BBBBBBBB
|
||||
|
||||
|
||||
BBBBB BBBBBBBBBBBBBBBBBB
|
||||
XXXX
|
||||
BBB BBBBBBBBBBBBBBBBBBBBBBBBBBB BB BBBBBBB
|
||||
XX XXXXXXBBBBBBBBBBBBBBBBBBBBB BBBBBBB BBBBBBBB BBBBBBBBX XXXXXXXXXXXXXXXX
|
||||
BB BBBBBBBBBBBB
|
||||
gettext(u'Add %(name)s') SSS SSSSSSSS
|
||||
BBBB
|
||||
gettext(u'Add %(account)s %(name)s') SSS SSSSSSSSSSS SSSSSSSS
|
||||
BBBBB
|
||||
XXXX
|
||||
XXXXX
|
||||
BBBBBBBB
|
||||
|
||||
|
||||
BBBBB BBBBBBB
|
||||
BB BBBBBBBBBBBBBB
|
||||
XXXX XXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXX gettext(u'Filter') XXXXX
|
||||
BB BBBBBBB
|
||||
XXXX gettext(u'By account') XXXXX
|
||||
XXXX
|
||||
XXX BB BBB BBBBBBBBBBBBXXXXXXXXXXXXXXXXBBBBBXXX XXXXXXXXXXXXXXXXXFFFFFFFFFFFFFFFFFFXXXXXXXXX
|
||||
XXX BB BBBBBBBBBBBBXXXXXXXXXXXXXXXXBBBBBXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXX
|
||||
BBBBB
|
||||
BBB BBBB BB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BB BBBBBBBBBB
|
||||
XXXXXX
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||
BBBB BBBB BBBB BBBBBBBBBB
|
||||
|
||||
BBBBB BBBBBBB
|
||||
BB BBBBBBBBBBBBB
|
||||
XXX gettext(u"Deleting the selected %(objects_name)s would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:") SSSSSSSS SSS SSSSSSSS SSSSSSSSSSSSSSSS SSSSS SSSSSS SS SSSSSSSS SSSSSSS SSSSSSSS SSS SSSS SSSSSSS SSSSSSS SSSS SSSSSSSSSS SS SSSSSS SSS SSSSSSSSS SSSSS SS SSSSSSSSXXXX
|
||||
XXXX
|
||||
BBB BBB BB BBBBBBBBBBBBB
|
||||
XXXXXXXXX
|
||||
BBBBBB
|
||||
XXXXX
|
||||
BBBB BBBBBBBBB
|
||||
XXX gettext(u'Deleting the selected %(objects_name)s would require deleting the following protected related objects:') SSSSSSSS SSS SSSSSSSS SSSSSSSSSSSSSSSS SSSSS SSSSSSS SSSSSSSS SSS SSSSSSSSS SSSSSSSSS SSSSSSS SSSSSSSSXXXX
|
||||
XXXX
|
||||
BBB BBB BB BBBBBBBBB
|
||||
XXXXXXXXX
|
||||
BBBBBB
|
||||
XXXXX
|
||||
BBBB
|
||||
XXX gettext(u'Are you sure you want to delete the selected %(objects_name)s? All of the following objects and their related items will be deleted:') SSS SSS SSSS SSS SSSS SS SSSSSS SSS SSSSSSSS SSSSSSSSSSSSSSSSS SSS SS SSS SSSSSSSSS SSSSSSS SSS SSSSS SSSSSSS SSSSS SSSS SS SSSSSSSSXXXX
|
||||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||
XXXX gettext(u'Objects') XXXXX
|
||||
BBB BBBBBBBBBBBBBBBB BB BBBBBBBBBBBBBBBBB
|
||||
XXXXFFFFFFFFFFFFFFXXXXX
|
||||
BBBBBB
|
||||
XXXXX XXXXXXXXX XXXXXXXXXXXXXXBBBBBBBBBB
|
||||
XXXXX
|
||||
BBB BBB BB BBBBBBBB
|
||||
XXXXXX XXXXXXXXXXXXX XXXXXXX XXXXXXXFFFFFFFFFFX XX
|
||||
BBBBBB
|
||||
XXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX
|
||||
XXXXXX XXXXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX XX
|
||||
XXXXXX XXXXXXXXXXXXX XXXXXXX gettext(u"Yes, I'm sure") X XX
|
||||
XX XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX gettext(u'No, take me back') XXXX
|
||||
XXXXXX
|
||||
XXXXXXX
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBB
|
||||
BBBB BBBB BBBB BBBBBBBBBB
|
||||
|
||||
BBBBB BBBBBBBBB XXXX XXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXBBBBBBBB
|
||||
|
||||
BBBBB BBBBBBBBBBB
|
||||
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||
XXXXXXXX BB BBBBBBB gettext(u'Disable %(objects_name)s') SSSSSSS SSSSSSSSSSSSSSSSBBBB gettext(u'Enable %(objects_name)s') SSSSSS SSSSSSSSSSSSSSSSBBBBB
|
||||
XXXXXX
|
||||
BBBBBBBB
|
||||
|
||||
BBBBB BBBBBBB
|
||||
BB BBBBBBBXXX gettext(u'Are you sure you want to disable selected %(objects_name)s?') SSS SSS SSSS SSS SSSS SS SSSSSSS SSSSSSSS SSSSSSSSSSSSSSSSSXXXX
|
||||
BBBBXXX gettext(u'Are you sure you want to enable selected %(objects_name)s?') SSS SSS SSSS SSS SSSS SS SSSSSS SSSSSSSS SSSSSSSSSSSSSSSSSXXXX
|
||||
BBBBB
|
||||
XXXX gettext(u'Objects') XXXXX
|
||||
BBB BBBBBBBBBBBBBBBB BB BBBBBBBBBBBBBBBBB
|
||||
XXXXFFFFFFFFFFFFFFXXXXX
|
||||
BBBBBB
|
||||
XXXXX XXXXXXXXX XXXXXXXXXXXXXXBBBBBBBBBB
|
||||
XXXXX
|
||||
BBB BBB BB BBBBBBBB
|
||||
XXXXXX XXXXXXXXXXXXX XXXXXXX XXXXXXXFFFFFFFFFFX XX
|
||||
BBBBBB
|
||||
XXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX XXXXXXXX XX
|
||||
XXXXXX XXXXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX XX
|
||||
XXXXXX XXXXXXXXXXXXX XXXXXXX gettext(u"Yes, I'm sure") X XX
|
||||
XX XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXXX XXXXXXXXXXXXX XXXXXXXXXXXXX gettext(u'No, take me back') XXXX
|
||||
XXXXXX
|
||||
XXXXXXX
|
||||
BBBBBBBB
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB
|
||||
BBBB BBBB BBBBBBBBBB
|
||||
|
||||
|
||||
BBBBB BBBBBBBBBBB
|
||||
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||
XXXXXXXX gettext(u'Select %(name)s account') SSSSSS SSSSSSSS SSSSSSS
|
||||
XXXXXX
|
||||
BBBBBBBB
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
BBBB BBBB BBBBBBBBBB BBBBB
|
||||
XXXXXX
|
||||
XXXXXX
|
||||
XXXXXXXBBBBB BBBBBXXXXXXX XXXXXXX XXXXXXBBBBBBBBXXXXXXXX
|
||||
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||
BBBBB BBBBBBBBBBBB
|
||||
XXXXXX XXXXXXXXXXXXXXXX
|
||||
XXXX X
|
||||
XXXXXXXXXX XXXXXX
|
||||
XXXXXXX XX XXXX XXXXXXXXXXX
|
||||
XXXXXX XXXX XXXXXXXXXXX
|
||||
XXXXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXXX XXXXXXX XXXXXX XXXXXXXXXXX
|
||||
XXXXXXXXXX XXXXX
|
||||
XXXXXX XXXXX
|
||||
X
|
||||
XXXXX X
|
||||
XXXXXX XXXXXX
|
||||
XXXXXX XXXXXXXX XXXX XXXXX
|
||||
X
|
||||
XXXXXXXXXXXXXXXX X
|
||||
XXXXXXX XXX XXX XXXX XXXXX
|
||||
X
|
||||
XXXXXXXXXXX X
|
||||
XXXXXXXXXXXXXXXX XXXXX
|
||||
XXXXXXXXXXXX XXXXX
|
||||
XXXXXX XXXXX
|
||||
X
|
||||
XXXXXXXXX X
|
||||
XXXXXXXX XXXX
|
||||
XXXXXXX XXX XXX XXXX XXXXX
|
||||
X
|
||||
XXXXXXXX X
|
||||
XXXXXXXXXXX XXXXX
|
||||
X
|
||||
XX X
|
||||
XXXXXXXXXXX XXXXX
|
||||
X
|
||||
X X
|
||||
XXXXXXXXXXXXXXXX XXXXX
|
||||
XXXXXX XXXXXXX XXXX XXXXX
|
||||
X
|
||||
XXXXXXXX
|
||||
XXXXXXX
|
||||
|
||||
XXXXXX
|
||||
XXXX XXXXXXXXXX gettext(u'Service report generated on') FFFFXXXXXX
|
||||
BBB BBBBBBBB BBBBB BB BBBBBBBB
|
||||
XXXX X XX XXXXXXFFFFFFFFFXXXXXXXXXXX
|
||||
XXXX
|
||||
XXXX XXXXXXXXXXXXXXXXXXXXXXXX
|
||||
gettext(u'account registered on') FFFFXXXX
|
||||
XXX XXXXXXXXXXXXXXXXX
|
||||
XXX XXXXXXXXXXXXXXXXXXX gettext(u'Resources') XXXXX
|
||||
BB BBBBBBBBBBBBBBBBB
|
||||
XXXX
|
||||
BBB BBBBBBBB BB BBBBBBBBBBBBBBBBB
|
||||
XXXXXX XXXXXXFFFFFFFFFXX BB BBBBBBBBBBBBB BB BBBBXXXXX XXXXXXX gettext(u'Used') XXXXXXXXXBBBBBBB BBBBBBBBBBBBBBBBBB BB BBBBBB BBBBBBBBBBBBB BB BBBB X BBBBBXXXXX XXXXXXX gettext(u'Allocated') XXXXXXXXXBBBBBXXXX XXXXX
|
||||
BBBBBB
|
||||
XXXXX
|
||||
BBBBB
|
||||
|
||||
BBB BBBBB BBBBBBB BB BBBBB
|
||||
XXX XXXXXXXXXXXXXXXXXXXXX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXXXXFFFFFFFFXXXXXXXXX
|
||||
XXXX
|
||||
BBB BBB BB BBBBBBB
|
||||
XXX XXXXXXXXXXXXXXXXXX XXXXXXFFFFFFFFFXXXXXX
|
||||
BB BBB BBBBBBBBBBBB X gettext(u'disabled') XBBBBB
|
||||
FFFFFFFF
|
||||
BB BBBBBBBBBBBBB
|
||||
XXXX
|
||||
BBB BBBBBBBB BB BBBBBBBBBBBBB
|
||||
XXXXXX XXXXXXFFFFFFFFFXX BB BBBBBBBBBBBBB BB BBBBXXXXX XXXXXXX gettext(u'Used') XXXXXXXXXBBBBBBB BBBBBBBBBBBBBBBBBB BB BBBBBB BBBBBBBBBBBBB BB BBBB X BBBBBXXXXX XXXXXXX gettext(u'Allocated') XXXXXXXXXBBBBBXXXX XXXXX
|
||||
BBBBBB
|
||||
XXXXX
|
||||
BBBBB
|
||||
XXXXX
|
||||
BBBBBB
|
||||
XXXXX
|
||||
BBBBBB
|
||||
XXXXX
|
||||
XXXXXX
|
||||
BBBBBB
|
||||
XXXXXXX
|
||||
XXXXXXX
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -29,9 +29,6 @@ class MySQLController(ServiceController):
|
|||
# Create database and re-set permissions
|
||||
mysql -e 'CREATE DATABASE `%(database)s`;' || true
|
||||
mysql mysql -e 'DELETE FROM db WHERE db = "%(database)s";'\
|
||||
|
||||
# wait to create user
|
||||
sleep 1.5
|
||||
""") % context
|
||||
)
|
||||
for user in database.users.all():
|
||||
|
@ -92,12 +89,20 @@ class MySQLUserController(ServiceController):
|
|||
if user.type != user.MYSQL:
|
||||
return
|
||||
context = self.get_context(user)
|
||||
if user.target_server.name != "mysql.pangea.lan":
|
||||
self.append(textwrap.dedent("""\
|
||||
# Create user %(username)s
|
||||
mysql -e 'CREATE USER IF NOT EXISTS "%(username)s"@"%(host)s";'
|
||||
mysql -e 'ALTER USER IF EXISTS "%(username)s"@"%(host)s" IDENTIFIED BY PASSWORD "%(password)s";'\
|
||||
""") % context
|
||||
)
|
||||
else:
|
||||
self.append(textwrap.dedent("""\
|
||||
# Create user %(username)s
|
||||
mysql -e 'CREATE USER "%(username)s"@"%(host)s";' || true # User already exists
|
||||
mysql -e 'UPDATE mysql.user SET Password="%(password)s" WHERE User="%(username)s";'\
|
||||
""") % context
|
||||
)
|
||||
|
||||
def delete(self, user):
|
||||
if user.type != user.MYSQL:
|
||||
|
@ -181,7 +186,7 @@ class MysqlDisk(ServiceMonitor):
|
|||
def get_context(self, db):
|
||||
context = {
|
||||
'db_name': db.name,
|
||||
'db_dirname': db.name.replace('-', '@002d').replace('.', '@002e'),
|
||||
'db_dirname': db.name.replace('-', '@002d'),
|
||||
'db_id': db.pk,
|
||||
'db_type': db.type,
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ from django.utils.translation import gettext_lazy as _
|
|||
from orchestra.core import validators
|
||||
|
||||
from .models import DatabaseUser, Database
|
||||
from .settings import DATABASES_SERVERS
|
||||
|
||||
|
||||
class DatabaseUserCreationForm(forms.ModelForm):
|
||||
|
@ -23,11 +22,6 @@ class DatabaseUserCreationForm(forms.ModelForm):
|
|||
model = DatabaseUser
|
||||
fields = ('username', 'account', 'type')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DatabaseUserCreationForm, self).__init__(*args, **kwargs)
|
||||
qsServer = self.fields['target_server'].queryset.filter(name__in=DATABASES_SERVERS)
|
||||
self.fields['target_server'].queryset = qsServer
|
||||
|
||||
def clean_password2(self):
|
||||
password1 = self.cleaned_data.get("password1")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
|
@ -64,12 +58,12 @@ class DatabaseForm(forms.ModelForm):
|
|||
|
||||
|
||||
class DatabaseCreationForm(DatabaseUserCreationForm):
|
||||
username = forms.CharField(label=_("Username"), max_length=32,
|
||||
username = forms.CharField(label=_("Username"), max_length=16,
|
||||
required=False, validators=[validators.validate_name],
|
||||
help_text=_("Required. 32 characters or fewer. Letters, digits and "
|
||||
help_text=_("Required. 16 characters or fewer. Letters, digits and "
|
||||
"@/./+/-/_ only."),
|
||||
error_messages={
|
||||
'invalid': _("This value may contain 32 characters or fewer, only letters, numbers and "
|
||||
'invalid': _("This value may contain 16 characters or fewer, only letters, numbers and "
|
||||
"@/./+/-/_ characters.")})
|
||||
user = forms.ModelChoiceField(required=False, queryset=DatabaseUser.objects)
|
||||
|
||||
|
@ -80,10 +74,6 @@ class DatabaseCreationForm(DatabaseUserCreationForm):
|
|||
def __init__(self, *args, **kwargs):
|
||||
super(DatabaseCreationForm, self).__init__(*args, **kwargs)
|
||||
account_id = self.initial.get('account', self.initial_account)
|
||||
|
||||
qsServer = self.fields['target_server'].queryset.filter(name__in=DATABASES_SERVERS)
|
||||
self.fields['target_server'].queryset = qsServer
|
||||
|
||||
if account_id:
|
||||
qs = self.fields['user'].queryset.filter(account=account_id).order_by('username')
|
||||
choices = [ (u.pk, "%s (%s) (%s)" % (u, u.get_type_display(), str(u.target_server.name) )) for u in qs ]
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2021-04-22 11:25
|
||||
from __future__ import unicode_literals
|
||||
# Generated by Django 2.2.28 on 2023-06-28 17:06
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
@ -10,69 +8,39 @@ import orchestra.core.validators
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Database',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('type', models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DatabaseUser',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('username', models.CharField(max_length=16, validators=[orchestra.core.validators.validate_name], verbose_name='username')),
|
||||
('password', models.CharField(max_length=256, verbose_name='password')),
|
||||
('type', models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type')),
|
||||
('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databaseusers', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'DB users',
|
||||
'unique_together': {('username', 'type')},
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='database',
|
||||
name='users',
|
||||
field=models.ManyToManyField(blank=True, related_name='databases', to='databases.DatabaseUser', verbose_name='users'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='databaseuser',
|
||||
unique_together=set([('username', 'type')]),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='database',
|
||||
unique_together=set([('name', 'type')]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='database',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='databaseuser',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='database',
|
||||
name='comments',
|
||||
field=models.TextField(blank=True, default=''),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='database',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='databaseuser',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('mysql', 'MySQL'), ('postgres', 'PostgreSQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||
migrations.CreateModel(
|
||||
name='Database',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type')),
|
||||
('comments', models.TextField(blank=True, default='')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='databases', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('users', models.ManyToManyField(blank=True, related_name='databases', to='databases.DatabaseUser', verbose_name='users')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('name', 'type')},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 2.2.24 on 2024-07-11 12:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('databases', '0006_auto_20230705_1237'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='database',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='databaseuser',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=32, verbose_name='type'),
|
||||
),
|
||||
]
|
|
@ -27,12 +27,3 @@ DATABASES_DEFAULT_HOST = Setting('DATABASES_DEFAULT_HOST',
|
|||
DATABASES_MYSQL_DB_DIR = Setting('DATABASES_MYSQL_DB_DIR',
|
||||
'/var/lib/mysql',
|
||||
)
|
||||
|
||||
|
||||
DATABASES_SERVERS = Setting('DATABASES_SERVERS', (
|
||||
'wpmu',
|
||||
'mysql.pangea.lan',
|
||||
'web-11.pangea.lan',
|
||||
'web-12.pangea.lan',
|
||||
)
|
||||
)
|
Binary file not shown.
|
@ -1,462 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-09-06 07:58+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: actions.py:25
|
||||
#, python-format
|
||||
msgid "%s zone content"
|
||||
msgstr "%s contingut zona"
|
||||
|
||||
#: actions.py:29 templates/admin/domains/domain/change_form.html:7
|
||||
#: templates/admin/domains/domain/view_zone.html:12
|
||||
msgid "View zone"
|
||||
msgstr "Veure zona"
|
||||
|
||||
#: actions.py:53
|
||||
msgid ""
|
||||
"This subdomain was not explicitly selected but has been automatically added "
|
||||
"to this list."
|
||||
msgstr ""
|
||||
"Aquest subdomini no va ser seleccionat explícitament, però s'ha afegit automàticament"
|
||||
"A aquesta llista."
|
||||
|
||||
|
||||
#: actions.py:88
|
||||
msgid "Records for one selected domain have been updated."
|
||||
msgstr "S'han actualitzat els registres d'un domini seleccionat."
|
||||
|
||||
#: actions.py:89
|
||||
#, python-format
|
||||
msgid "Records for %i selected domains have been updated."
|
||||
msgstr "S'han actualitzat els registres dels dominis seleccionars %i "
|
||||
|
||||
#: actions.py:96 actions.py:97
|
||||
msgid "Edit records"
|
||||
msgstr "Editar registres"
|
||||
|
||||
#: actions.py:112
|
||||
msgid "Set SOA on subdomains is not possible."
|
||||
msgstr "Configurar SOA en subdominis no és possible."
|
||||
|
||||
#: actions.py:120
|
||||
#, python-format
|
||||
msgid "SOA set %s"
|
||||
msgstr ""
|
||||
|
||||
#: actions.py:131
|
||||
msgid "SOA record for one domain has been updated."
|
||||
msgstr "El registre SOA per a un domini s'ha actualitzat."
|
||||
|
||||
#: actions.py:132
|
||||
#, python-format
|
||||
msgid "SOA record for %s domains has been updated."
|
||||
msgstr "S'ha actualitzat el rècord SOA per als dominis de %s"
|
||||
|
||||
#: actions.py:139 actions.py:152
|
||||
msgid "Set SOA for selected domains"
|
||||
msgstr "Configurar SOA pels dominis seleccionats"
|
||||
|
||||
#: actions.py:141
|
||||
msgid "Set SOA"
|
||||
msgstr "Afegir SOA"
|
||||
|
||||
#: admin.py:28
|
||||
msgid "Extra records"
|
||||
msgstr "Registres Extra"
|
||||
|
||||
#: admin.py:36
|
||||
msgid "Subdomains"
|
||||
msgstr "Subdominis"
|
||||
|
||||
#: admin.py:39
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: admin.py:44
|
||||
msgid "Declared records"
|
||||
msgstr "Registres declarats"
|
||||
|
||||
#: admin.py:78 models.py:27
|
||||
msgid "name"
|
||||
msgstr "nom"
|
||||
|
||||
#: admin.py:83
|
||||
msgid "Is top"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:96
|
||||
msgid "Edit website"
|
||||
msgstr "Editar website"
|
||||
|
||||
#: admin.py:105
|
||||
msgid "Add website"
|
||||
msgstr "Crear website"
|
||||
|
||||
#: admin.py:107
|
||||
#, python-format
|
||||
msgid "No website %s"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:110
|
||||
msgid "Websites"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:119
|
||||
msgid "Add address"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:127
|
||||
#, python-format
|
||||
msgid "No address %s"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:129
|
||||
msgid "Addresses"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:151 admin.py:158
|
||||
msgid "Implicit records"
|
||||
msgstr "Registres implicits"
|
||||
|
||||
#: admin.py:165
|
||||
msgid "SOA"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:168
|
||||
msgid ""
|
||||
"SOA (Start of Authority) records are used to determine how the zone "
|
||||
"propagates to the secondary nameservers."
|
||||
msgstr ""
|
||||
"Els registres SOA (Start of Authority) s'utilitzen per determinar com la zona"
|
||||
"Es propaga als servidors de noms secundaris."
|
||||
|
||||
#: backends.py:22
|
||||
msgid "Bind9 master domain"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:184
|
||||
msgid "Bind9 slave domain"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:7
|
||||
msgid "top domains"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:12
|
||||
msgid "Top domains"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:22
|
||||
msgid "has websites"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:27
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:28
|
||||
msgid "False"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:41
|
||||
msgid "has addresses"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:14
|
||||
msgid "Names"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:15
|
||||
msgid ""
|
||||
"Fully qualified domain name per line. All domains will have the provided "
|
||||
"account and records."
|
||||
msgstr ""
|
||||
"Nom de domini completament qualificat per línia. Tots els dominis tindran el subministrament"
|
||||
"Compte i registres."
|
||||
|
||||
#: forms.py:29
|
||||
#, python-format
|
||||
msgid "%s domain name provided multiple times."
|
||||
msgstr "El nom de domini %s es va proporcionar diverses vegades."
|
||||
|
||||
#: forms.py:65
|
||||
msgid "An account should be provided for top domain names."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:72
|
||||
msgid "Provided domain names belong to different accounts."
|
||||
msgstr "Els noms de domini pertanyen a diferents comptes"
|
||||
|
||||
#: forms.py:118
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s: Hosts can not have underscore character '_', consider providing a SRV, "
|
||||
"CNAME or TXT record."
|
||||
msgstr ""
|
||||
"%s: Els Hosts no poden tenir un caràcter '_', considereu proporcionar un SRV"
|
||||
"Registre CNAME o TXT."
|
||||
|
||||
#: forms.py:142
|
||||
msgid "Clear refresh"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:143
|
||||
msgid "Remove custom refresh value for all selected domains."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:145
|
||||
msgid "Clear retry"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:146
|
||||
msgid "Remove custom retry value for all selected domains."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:148
|
||||
msgid "Clear expire"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:149
|
||||
msgid "Remove custom expire value for all selected domains."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:151
|
||||
msgid "Clear min TTL"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:152
|
||||
msgid "Remove custom min TTL value for all selected domains."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:28
|
||||
msgid "Domain or subdomain name."
|
||||
msgstr "nom de Domini o Subdomini"
|
||||
|
||||
#: models.py:33
|
||||
msgid "Account"
|
||||
msgstr "Compte"
|
||||
|
||||
#: models.py:34
|
||||
msgid "Automatically selected for subdomains."
|
||||
msgstr "Seleccionat automàticament per a subdominis."
|
||||
|
||||
#: models.py:36
|
||||
msgid "top domain"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:37
|
||||
msgid "serial"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:38
|
||||
msgid "A revision number that changes whenever this domain is updated."
|
||||
msgstr "Un número de revisió que canvia sempre que aquest domini s'actualitzi."
|
||||
|
||||
#: models.py:39
|
||||
msgid "refresh"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:41
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The time a secondary DNS server waits before querying the primary DNS "
|
||||
"server's SOA record to check for changes. When the refresh time expires, the "
|
||||
"secondary DNS server requests a copy of the current SOA record from the "
|
||||
"primary. The primary DNS server complies with this request. The secondary "
|
||||
"DNS server compares the serial number of the primary DNS server's current "
|
||||
"SOA record and the serial number in it's own SOA record. If they are "
|
||||
"different, the secondary DNS server will request a zone transfer from the "
|
||||
"primary DNS server. The default value is <tt>%s</tt>."
|
||||
msgstr ""
|
||||
"El temps que un servidor DNS secundari espera abans de consultar el DNS primari"
|
||||
"Registre SOA del servidor per comprovar si hi ha canvis. Quan el temps d'actualització caduca,"
|
||||
"El servidor DNS secundari sol·licita una còpia del registre SOA actual del"
|
||||
"Primària. El servidor DNS primari compleix aquesta sol·licitud. La secundària"
|
||||
"El servidor DNS compara el número de sèrie del corrent principal del servidor DNS"
|
||||
"Registre SOA i el número de sèrie del seu propi registre SOA. Si ho són"
|
||||
"Diferent, el servidor DNS secundari sol·licitarà una transferència de zona des del"
|
||||
"Servidor DNS primari. El valor per defecte és <tt>%s</tt>."
|
||||
|
||||
#: models.py:50
|
||||
msgid "retry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The time a secondary server waits before retrying a failed zone transfer. "
|
||||
"Normally, the retry time is less than the refresh time. The default value is "
|
||||
"<tt>%s</tt>."
|
||||
msgstr ""
|
||||
"El temps que un servidor secundari espera abans de tornar a tornar a transferir una zona fallida."
|
||||
"Normalment, el temps de tornada és inferior al temps d'actualització. El valor predeterminat és"
|
||||
"<tt>%s</tt>."
|
||||
|
||||
#: models.py:55
|
||||
msgid "expire"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:57
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The time that a secondary server will keep trying to complete a zone "
|
||||
"transfer. If this time expires prior to a successful zone transfer, the "
|
||||
"secondary server will expire its zone file. This means the secondary will "
|
||||
"stop answering queries. The default value is <tt>%s</tt>."
|
||||
msgstr ""
|
||||
"El temps que un servidor secundari continuarà intentant completar una zona"
|
||||
"Transferència. Si aquesta vegada caduca abans d'una transferència de zona amb èxit,"
|
||||
"El servidor secundari caducarà el seu fitxer de zona. Això significa que la voluntat secundària"
|
||||
"Deixa de respondre a les consultes. El valor predeterminat és <tt>%s</tt>."
|
||||
|
||||
#: models.py:62
|
||||
msgid "min TTL"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:64
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The minimum time-to-live value applies to all resource records in the zone "
|
||||
"file. This value is supplied in query responses to inform other servers how "
|
||||
"long they should keep the data in cache. The default value is <tt>%s</tt>."
|
||||
msgstr ""
|
||||
"El valor mínim de temps en viu s'aplica a tots els registres de recursos de la zona"
|
||||
"Fitxer. Aquest valor es subministra a les respostes de consulta per informar a altres servidors com"
|
||||
"Long han de mantenir les dades en memòria cau. El valor predeterminat és <tt>%s</tt>"
|
||||
|
||||
#: models.py:118
|
||||
msgid "top domain with one subdomain"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:119
|
||||
#, python-format
|
||||
msgid "top domain with %d subdomains"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:121
|
||||
msgid "subdomain"
|
||||
msgstr "subdomini"
|
||||
|
||||
#: models.py:308
|
||||
msgid "A (IPv4 address)"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:309
|
||||
msgid "AAAA (IPv6 address)"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:329
|
||||
msgid "domain"
|
||||
msgstr "domini"
|
||||
|
||||
#: models.py:330
|
||||
msgid "TTL"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:331
|
||||
#, python-format
|
||||
msgid "Record TTL, defaults to %s"
|
||||
msgstr "Registre TTL, per defecte a %s"
|
||||
|
||||
#: models.py:333
|
||||
msgid "type"
|
||||
msgstr "tipus"
|
||||
|
||||
#: models.py:335
|
||||
msgid "value"
|
||||
msgstr "valor"
|
||||
|
||||
#: models.py:336
|
||||
msgid "MX, NS and CNAME records sould end with a dot."
|
||||
msgstr "Els registres de MX, NS i CNAME s'acaben amb un punt."
|
||||
|
||||
#: serializers.py:36
|
||||
msgid "Can not create subdomains of other users domains"
|
||||
msgstr "No es pot crear subdominis d'altres dominis d'usuaris"
|
||||
|
||||
#: templates/admin/domains/domain/change_form.html:11
|
||||
msgid "History"
|
||||
msgstr "Historial"
|
||||
|
||||
#: templates/admin/domains/domain/change_form.html:13
|
||||
msgid "View on site"
|
||||
msgstr "Veure al lloc"
|
||||
|
||||
#: templates/admin/domains/domain/view_zone.html:8
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
||||
#: validators.py:28
|
||||
msgid "This domain name is not allowed"
|
||||
msgstr "Aquest nom de domini no està permès"
|
||||
|
||||
#: validators.py:37
|
||||
msgid "Not a valid domain name."
|
||||
msgstr "No és un nom de domini vàlid."
|
||||
|
||||
#: validators.py:46
|
||||
#, python-format
|
||||
msgid "%s is not an appropiate zone interval value"
|
||||
msgstr "%s no és un valor d'interval de zona adequat"
|
||||
|
||||
#: validators.py:57
|
||||
msgid ""
|
||||
"Labels must start and end with a letter or digit, and have as interior "
|
||||
"characters only letters, digits, and hyphen."
|
||||
msgstr ""
|
||||
"Les etiquetes han de començar i acabar amb una lletra o dígit i tenir en l'interior"
|
||||
"Només caràcters lletres, dígits i guionet."
|
||||
|
||||
#: validators.py:61
|
||||
msgid "Use a fully expanded domain name ending with a dot."
|
||||
msgstr "Utilitzeu un nom de domini complet amb un punt final."
|
||||
|
||||
#: validators.py:64
|
||||
msgid "Labels must be 63 characters or less."
|
||||
msgstr "Les etiquetes han de tenir 63 caràcters o menys."
|
||||
|
||||
#: validators.py:68
|
||||
msgid ""
|
||||
"MX record format is 'priority domain.' tuple, with priority being a number."
|
||||
msgstr ""
|
||||
"El format de registre MX és 'domini prioritari'. Tuple, amb la prioritat que és un número "
|
||||
|
||||
#: validators.py:83 validators.py:95
|
||||
#, python-format
|
||||
msgid "%s is not an appropiate SRV record value"
|
||||
msgstr "%s no és un valor de registre SRV Apropiat"
|
||||
|
||||
#: validators.py:111
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s is not an appropiate CAA record value, sintax: 0-255 issue|issuewild|"
|
||||
"iodef \"domain|mailto:email\""
|
||||
msgstr ""
|
||||
"%s no és un valor de registre CAA adequat, sintaxi: 0-255 issue|issuewild|"
|
||||
"iodef \"domain|mailto:email\""
|
||||
|
||||
#: validators.py:134
|
||||
msgid ""
|
||||
"This record value contains spaces, you must enclose the string in double "
|
||||
"quotes; otherwise, individual words will be separately quoted and break up "
|
||||
"the record into multiple parts."
|
||||
msgstr ""
|
||||
"Aquest valor de registre conté espais, heu d'incloure la cadena ab cometes dobles"
|
||||
"en cas contrari, les paraules individuals es citaran per separat i es trencaran"
|
||||
"El registre en diverses parts"
|
Binary file not shown.
|
@ -1,461 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-09-05 10:11+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: actions.py:25
|
||||
#, python-format
|
||||
msgid "%s zone content"
|
||||
msgstr "%s contenido de zona"
|
||||
|
||||
#: actions.py:29 templates/admin/domains/domain/change_form.html:7
|
||||
#: templates/admin/domains/domain/view_zone.html:12
|
||||
msgid "View zone"
|
||||
msgstr "Ver zona"
|
||||
|
||||
#: actions.py:53
|
||||
msgid ""
|
||||
"This subdomain was not explicitly selected but has been automatically added "
|
||||
"to this list."
|
||||
msgstr ""
|
||||
"Este subdominio no fue seleccionado explícitamente, pero se ha agregado automáticamente"
|
||||
"A esta lista"
|
||||
|
||||
#: actions.py:88
|
||||
msgid "Records for one selected domain have been updated."
|
||||
msgstr "Se han actualizado los registros del dominio seleccionado"
|
||||
|
||||
#: actions.py:89
|
||||
#, python-format
|
||||
msgid "Records for %i selected domains have been updated."
|
||||
msgstr "Se han actualizado los registros para los %i dominios seleccionados"
|
||||
|
||||
#: actions.py:96 actions.py:97
|
||||
msgid "Edit records"
|
||||
msgstr "Editar Registros"
|
||||
|
||||
#: actions.py:112
|
||||
msgid "Set SOA on subdomains is not possible."
|
||||
msgstr "No es posible añadir el registro SOA en los subdominios"
|
||||
|
||||
#: actions.py:120
|
||||
#, python-format
|
||||
msgid "SOA set %s"
|
||||
msgstr "Añadir SOA %s"
|
||||
|
||||
#: actions.py:131
|
||||
msgid "SOA record for one domain has been updated."
|
||||
msgstr "Se ha actualizado el registro SOA del dominio"
|
||||
|
||||
#: actions.py:132
|
||||
#, python-format
|
||||
msgid "SOA record for %s domains has been updated."
|
||||
msgstr "Se actualizo el registro SOA para los dominios %s"
|
||||
|
||||
#: actions.py:139 actions.py:152
|
||||
msgid "Set SOA for selected domains"
|
||||
msgstr "Añadir SOA en los dominios seleccionados"
|
||||
|
||||
#: actions.py:141
|
||||
msgid "Set SOA"
|
||||
msgstr "Añadir SOA"
|
||||
|
||||
#: admin.py:28
|
||||
msgid "Extra records"
|
||||
msgstr "Registros extra"
|
||||
|
||||
#: admin.py:36
|
||||
msgid "Subdomains"
|
||||
msgstr "Subdominios"
|
||||
|
||||
#: admin.py:39
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: admin.py:44
|
||||
msgid "Declared records"
|
||||
msgstr "Registros declarados"
|
||||
|
||||
#: admin.py:78 models.py:27
|
||||
msgid "name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: admin.py:83
|
||||
msgid "Is top"
|
||||
msgstr "Es top level"
|
||||
|
||||
#: admin.py:96
|
||||
msgid "Edit website"
|
||||
msgstr "Editar WebSite"
|
||||
|
||||
#: admin.py:105
|
||||
msgid "Add website"
|
||||
msgstr "Añadir WebSite"
|
||||
|
||||
#: admin.py:107
|
||||
#, python-format
|
||||
msgid "No website %s"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:110
|
||||
msgid "Websites"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:119
|
||||
msgid "Add address"
|
||||
msgstr "Añadir dirección"
|
||||
|
||||
#: admin.py:127
|
||||
#, python-format
|
||||
msgid "No address %s"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:129
|
||||
msgid "Addresses"
|
||||
msgstr "Direcciones"
|
||||
|
||||
#: admin.py:151 admin.py:158
|
||||
msgid "Implicit records"
|
||||
msgstr "Registros implicitos"
|
||||
|
||||
#: admin.py:165
|
||||
msgid "SOA"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:168
|
||||
msgid ""
|
||||
"SOA (Start of Authority) records are used to determine how the zone "
|
||||
"propagates to the secondary nameservers."
|
||||
msgstr ""
|
||||
"Los registros SOA (inicio de la autoridad) se utilizan para determinar cómo la zona"
|
||||
"Se propaga a los servidores de nombres secundarios"
|
||||
|
||||
#: backends.py:22
|
||||
msgid "Bind9 master domain"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:184
|
||||
msgid "Bind9 slave domain"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:7
|
||||
msgid "top domains"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:12
|
||||
msgid "Top domains"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:22
|
||||
msgid "has websites"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:27
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:28
|
||||
msgid "False"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:41
|
||||
msgid "has addresses"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:14
|
||||
msgid "Names"
|
||||
msgstr "Nombres"
|
||||
|
||||
#: forms.py:15
|
||||
msgid ""
|
||||
"Fully qualified domain name per line. All domains will have the provided "
|
||||
"account and records."
|
||||
msgstr ""
|
||||
"Nombre de dominio totalmente calificado por línea. Todos los dominios tendrán los proporcionados"
|
||||
"Cuenta y registros"
|
||||
|
||||
#: forms.py:29
|
||||
#, python-format
|
||||
msgid "%s domain name provided multiple times."
|
||||
msgstr "%s Nombre de dominio proporcionado varias veces."
|
||||
|
||||
#: forms.py:65
|
||||
msgid "An account should be provided for top domain names."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:72
|
||||
msgid "Provided domain names belong to different accounts."
|
||||
msgstr "Los nombres de dominio proporcionados pertenecen a diferentes cuentas"
|
||||
|
||||
#: forms.py:118
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s: Hosts can not have underscore character '_', consider providing a SRV, "
|
||||
"CNAME or TXT record."
|
||||
msgstr ""
|
||||
"%s: los hosts no pueden tener un carácter subrayado '_', considere proporcionar un SRV, "
|
||||
"Registro CNAME o TXT."
|
||||
|
||||
#: forms.py:142
|
||||
msgid "Clear refresh"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:143
|
||||
msgid "Remove custom refresh value for all selected domains."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:145
|
||||
msgid "Clear retry"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:146
|
||||
msgid "Remove custom retry value for all selected domains."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:148
|
||||
msgid "Clear expire"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:149
|
||||
msgid "Remove custom expire value for all selected domains."
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:151
|
||||
msgid "Clear min TTL"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:152
|
||||
msgid "Remove custom min TTL value for all selected domains."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:28
|
||||
msgid "Domain or subdomain name."
|
||||
msgstr "Dominio o Subdominio"
|
||||
|
||||
#: models.py:33
|
||||
msgid "Account"
|
||||
msgstr "Cuenta"
|
||||
|
||||
#: models.py:34
|
||||
msgid "Automatically selected for subdomains."
|
||||
msgstr "Seleccionado automáticamente para subdominios"
|
||||
|
||||
#: models.py:36
|
||||
msgid "top domain"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:37
|
||||
msgid "serial"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:38
|
||||
msgid "A revision number that changes whenever this domain is updated."
|
||||
msgstr "Un número de revisión que cambia cada vez que se actualiza este dominio"
|
||||
|
||||
#: models.py:39
|
||||
msgid "refresh"
|
||||
msgstr "actualizar"
|
||||
|
||||
#: models.py:41
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The time a secondary DNS server waits before querying the primary DNS "
|
||||
"server's SOA record to check for changes. When the refresh time expires, the "
|
||||
"secondary DNS server requests a copy of the current SOA record from the "
|
||||
"primary. The primary DNS server complies with this request. The secondary "
|
||||
"DNS server compares the serial number of the primary DNS server's current "
|
||||
"SOA record and the serial number in it's own SOA record. If they are "
|
||||
"different, the secondary DNS server will request a zone transfer from the "
|
||||
"primary DNS server. The default value is <tt>%s</tt>."
|
||||
msgstr ""
|
||||
"La hora en que un servidor DNS secundario espera antes de consultar el DNS primario"
|
||||
"El registro SOA del servidor para verificar los cambios. Cuando la tiempo de actualización expira,"
|
||||
"El servidor DNS secundario solicita una copia del registro SOA actual del"
|
||||
"Primario. El servidor DNS principal cumple con esta solicitud. El secundario"
|
||||
"El servidor DNS compara el número de serie del servidor DNS principal actual"
|
||||
"SOA Record y el número de serie en su propio registro SOA. Si lo son"
|
||||
"Diferente, el servidor DNS secundario solicitará una transferencia de zona del"
|
||||
"Servidor DNS primario. El valor predeterminado es <tt>%s</tt>"
|
||||
|
||||
#: models.py:50
|
||||
msgid "retry"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:52
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The time a secondary server waits before retrying a failed zone transfer. "
|
||||
"Normally, the retry time is less than the refresh time. The default value is "
|
||||
"<tt>%s</tt>."
|
||||
msgstr ""
|
||||
"El tiempo en que un servidor secundario espera antes de volver a intentar una transferencia de zona fallida"
|
||||
"Normalmente, el tiempo de reintento es menor que el tiempo de actualización. El valor predeterminado es"
|
||||
"<Tt>%s</tt>"
|
||||
|
||||
#: models.py:55
|
||||
msgid "expire"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:57
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The time that a secondary server will keep trying to complete a zone "
|
||||
"transfer. If this time expires prior to a successful zone transfer, the "
|
||||
"secondary server will expire its zone file. This means the secondary will "
|
||||
"stop answering queries. The default value is <tt>%s</tt>."
|
||||
msgstr ""
|
||||
"El momento en que un servidor secundario seguirá intentando completar una zona"
|
||||
"Transferencia. Si este tiempo expira antes de una transferencia de zona exitosa,"
|
||||
"El servidor secundario caducará su archivo de zona. Esto significa que el secundario lo hará"
|
||||
"Deje de responder consultas. El valor predeterminado es <tt>%s</tt>"
|
||||
|
||||
#: models.py:62
|
||||
msgid "min TTL"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:64
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The minimum time-to-live value applies to all resource records in the zone "
|
||||
"file. This value is supplied in query responses to inform other servers how "
|
||||
"long they should keep the data in cache. The default value is <tt>%s</tt>."
|
||||
msgstr ""
|
||||
"El valor mínimo de tiempo de vida se aplica a todos los registros de recursos en la zona"
|
||||
"Archivo. Este valor se suministra en las respuestas de consulta para informar a otros servidores cómo"
|
||||
"Durante mucho tiempo deberían mantener los datos en caché. El valor predeterminado es <tt>%s </tt>"
|
||||
|
||||
#: models.py:118
|
||||
msgid "top domain with one subdomain"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:119
|
||||
#, python-format
|
||||
msgid "top domain with %d subdomains"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:121
|
||||
msgid "subdomain"
|
||||
msgstr "Subdominio"
|
||||
|
||||
#: models.py:308
|
||||
msgid "A (IPv4 address)"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:309
|
||||
msgid "AAAA (IPv6 address)"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:329
|
||||
msgid "domain"
|
||||
msgstr "dominio"
|
||||
|
||||
#: models.py:330
|
||||
msgid "TTL"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:331
|
||||
#, python-format
|
||||
msgid "Record TTL, defaults to %s"
|
||||
msgstr "Registro TTL, por defecto %s"
|
||||
|
||||
#: models.py:333
|
||||
msgid "type"
|
||||
msgstr "tipo"
|
||||
|
||||
#: models.py:335
|
||||
msgid "value"
|
||||
msgstr "valor"
|
||||
|
||||
#: models.py:336
|
||||
msgid "MX, NS and CNAME records sould end with a dot."
|
||||
msgstr "Los registros MX, NS and CNAME han de acabar con punto"
|
||||
|
||||
#: serializers.py:36
|
||||
msgid "Can not create subdomains of other users domains"
|
||||
msgstr "No puede crear subdominios de los dominios de otros usuarios"
|
||||
|
||||
#: templates/admin/domains/domain/change_form.html:11
|
||||
msgid "History"
|
||||
msgstr "Historial"
|
||||
|
||||
#: templates/admin/domains/domain/change_form.html:13
|
||||
msgid "View on site"
|
||||
msgstr "Ver en el sitio"
|
||||
|
||||
#: templates/admin/domains/domain/view_zone.html:8
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
||||
#: validators.py:28
|
||||
msgid "This domain name is not allowed"
|
||||
msgstr "Este nombre de dominio no esta permitido"
|
||||
|
||||
#: validators.py:37
|
||||
msgid "Not a valid domain name."
|
||||
msgstr "No es nombre de dominio valido"
|
||||
|
||||
#: validators.py:46
|
||||
#, python-format
|
||||
msgid "%s is not an appropiate zone interval value"
|
||||
msgstr "%s no es un valor de intervalo de zona apropiado"
|
||||
|
||||
#: validators.py:57
|
||||
msgid ""
|
||||
"Labels must start and end with a letter or digit, and have as interior "
|
||||
"characters only letters, digits, and hyphen."
|
||||
msgstr ""
|
||||
"Las etiquetas deben comenzar y terminar con una letra o dígito, y tener en su interior"
|
||||
"Caracteres solo letras, dígitos y guiones"
|
||||
|
||||
#: validators.py:61
|
||||
msgid "Use a fully expanded domain name ending with a dot."
|
||||
msgstr "Use un nombre de dominio completo que termine con un punto"
|
||||
|
||||
#: validators.py:64
|
||||
msgid "Labels must be 63 characters or less."
|
||||
msgstr "Las etiquetas deben ser de 63 caracteres o menos"
|
||||
|
||||
#: validators.py:68
|
||||
msgid ""
|
||||
"MX record format is 'priority domain.' tuple, with priority being a number."
|
||||
msgstr ""
|
||||
"El formato de registro MX es 'dominio prioritario'. Tuple, con la prioridad siendo un número "
|
||||
|
||||
#: validators.py:83 validators.py:95
|
||||
#, python-format
|
||||
msgid "%s is not an appropiate SRV record value"
|
||||
msgstr "%s no es un valor de SRV apropiado"
|
||||
|
||||
#: validators.py:111
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s is not an appropiate CAA record value, sintax: 0-255 issue|issuewild|"
|
||||
"iodef \"domain|mailto:email\""
|
||||
msgstr ""
|
||||
"%s no es un valor de registro de CAA apropiado, sintaxis: 0-255 issue|issuewild|"
|
||||
"iodef \"domain|mailto:email\""
|
||||
|
||||
#: validators.py:134
|
||||
msgid ""
|
||||
"This record value contains spaces, you must enclose the string in double "
|
||||
"quotes; otherwise, individual words will be separately quoted and break up "
|
||||
"the record into multiple parts."
|
||||
msgstr ""
|
||||
"Este valor de registro contiene espacios, debe encerrar la cadena en el doble"
|
||||
"Comillas; de lo contrario, las palabras individuales serán citadas por separado y se romperán"
|
||||
"El registro en múltiples partes"
|
|
@ -1,80 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.contrib.domains.utils
|
||||
import orchestra.contrib.domains.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Domain',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(help_text='Domain or subdomain name.', max_length=256, unique=True, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], verbose_name='name')),
|
||||
('serial', models.IntegerField(default=orchestra.contrib.domains.utils.generate_zone_serial, help_text='Serial number', verbose_name='serial')),
|
||||
('account', models.ForeignKey(blank=True, help_text='Automatically selected for subdomains.', on_delete=django.db.models.deletion.CASCADE, related_name='domains', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('top', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subdomain_set', to='domains.Domain')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Record',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('ttl', models.CharField(blank=True, help_text='Record TTL, defaults to 1h', max_length=8, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='TTL')),
|
||||
('type', models.CharField(choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SPF', 'SPF')], max_length=32, verbose_name='type')),
|
||||
('value', models.CharField(help_text='MX, NS and CNAME records sould end with a dot.', max_length=1024, verbose_name='value')),
|
||||
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='records', to='domains.Domain', verbose_name='domain')),
|
||||
],
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='domain',
|
||||
name='serial',
|
||||
field=models.IntegerField(default=orchestra.contrib.domains.utils.generate_zone_serial, editable=False, help_text='A revision number that changes whenever this domain is updated.', verbose_name='serial'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='domain',
|
||||
name='expire',
|
||||
field=models.CharField(blank=True, help_text='The time that a secondary server will keep trying to complete a zone transfer. If this time expires prior to a successful zone transfer, the secondary server will expire its zone file. This means the secondary will stop answering queries. The default value is <tt>4w</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='expire'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='domain',
|
||||
name='min_ttl',
|
||||
field=models.CharField(blank=True, help_text='The minimum time-to-live value applies to all resource records in the zone file. This value is supplied in query responses to inform other servers how long they should keep the data in cache. The default value is <tt>1h</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='min TTL'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='domain',
|
||||
name='refresh',
|
||||
field=models.CharField(blank=True, help_text="The time a secondary DNS server waits before querying the primary DNS server's SOA record to check for changes. When the refresh time expires, the secondary DNS server requests a copy of the current SOA record from the primary. The primary DNS server complies with this request. The secondary DNS server compares the serial number of the primary DNS server's current SOA record and the serial number in it's own SOA record. If they are different, the secondary DNS server will request a zone transfer from the primary DNS server. The default value is <tt>1d</tt>.", max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='refresh'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='domain',
|
||||
name='retry',
|
||||
field=models.CharField(blank=True, help_text='The time a secondary server waits before retrying a failed zone transfer. Normally, the retry time is less than the refresh time. The default value is <tt>2h</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='retry'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='domain',
|
||||
name='name',
|
||||
field=models.CharField(db_index=True, help_text='Domain or subdomain name.', max_length=256, unique=True, validators=[orchestra.contrib.domains.validators.validate_domain_name, orchestra.contrib.domains.validators.validate_allowed_domain], verbose_name='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='domain',
|
||||
name='top',
|
||||
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subdomain_set', to='domains.Domain', verbose_name='top domain'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='domain',
|
||||
name='dns2136_address_match_list',
|
||||
field=models.CharField(blank=True, default='key pangea.key;', help_text="A bind-9 'address_match_list' that will be granted permission to perform dns2136 updates. Chiefly used to enable Let's Encrypt self-service validation.", max_length=80),
|
||||
),
|
||||
]
|
|
@ -1,29 +0,0 @@
|
|||
# Generated by Django 2.2.24 on 2024-07-11 12:25
|
||||
|
||||
from django.db import migrations, models
|
||||
import orchestra.contrib.domains.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('domains', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='domain',
|
||||
name='min_ttl',
|
||||
field=models.CharField(blank=True, help_text='The minimum time-to-live value applies to all resource records in the zone file. This value is supplied in query responses to inform other servers how long they should keep the data in cache. The default value is <tt>30m</tt>.', max_length=16, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='min TTL'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='record',
|
||||
name='ttl',
|
||||
field=models.CharField(blank=True, help_text='Record TTL, defaults to 30m', max_length=8, validators=[orchestra.contrib.domains.validators.validate_zone_interval], verbose_name='TTL'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='record',
|
||||
name='type',
|
||||
field=models.CharField(choices=[('MX', 'MX'), ('NS', 'NS'), ('CNAME', 'CNAME'), ('A', 'A (IPv4 address)'), ('AAAA', 'AAAA (IPv6 address)'), ('SRV', 'SRV'), ('TXT', 'TXT'), ('SPF', 'SPF'), ('CAA', 'CAA')], max_length=32, verbose_name='type'),
|
||||
),
|
||||
]
|
|
@ -145,9 +145,8 @@ class Domain(models.Model):
|
|||
else:
|
||||
zone += subdomain.render_records()
|
||||
###darmengo 2021-03-25 add autoconfig
|
||||
# TODO: que se asigne esta ip automaticamente
|
||||
if self.has_default_mx():
|
||||
zone += 'autoconfig.{}. 30m IN A 45.150.186.197\n'.format(self.name)
|
||||
zone += 'autoconfig.{}. 30m IN A 109.69.8.133\n'.format(self.name)
|
||||
###END darmengo 2021-03-25 add autoconfig
|
||||
for subdomain in sorted(tail, key=lambda x: len(x.name), reverse=True):
|
||||
zone += subdomain.render_records()
|
||||
|
@ -299,7 +298,6 @@ class Record(models.Model):
|
|||
TXT = 'TXT'
|
||||
SPF = 'SPF'
|
||||
SOA = 'SOA'
|
||||
CAA = 'CAA'
|
||||
|
||||
TYPE_CHOICES = (
|
||||
(MX, "MX"),
|
||||
|
@ -310,7 +308,6 @@ class Record(models.Model):
|
|||
(SRV, "SRV"),
|
||||
(TXT, "TXT"),
|
||||
(SPF, "SPF"),
|
||||
(CAA, "CAA"),
|
||||
)
|
||||
|
||||
VALIDATORS = {
|
||||
|
@ -323,7 +320,6 @@ class Record(models.Model):
|
|||
SPF: (validate_ascii, validators.validate_quoted_record),
|
||||
SRV: (validators.validate_srv_record,),
|
||||
SOA: (validators.validate_soa_record,),
|
||||
CAA: (validators.validate_caa_record,),
|
||||
}
|
||||
|
||||
domain = models.ForeignKey(Domain, verbose_name=_("domain"), related_name='records', on_delete=models.CASCADE)
|
||||
|
|
|
@ -53,7 +53,7 @@ def validate_zone_label(value):
|
|||
Labels may not be all numbers, but may have a leading digit (e.g., 3com.com).
|
||||
Labels must end and begin only with a letter or digit. See [RFC 1035] and [RFC 1123].
|
||||
"""
|
||||
if not re.match(r'^[a-z0-9][\.\-0-9a-z_]*[\.0-9a-z]$', value):
|
||||
if not re.match(r'^[a-z0-9][\.\-0-9a-z]*[\.0-9a-z]$', value):
|
||||
msg = _("Labels must start and end with a letter or digit, "
|
||||
"and have as interior characters only letters, digits, and hyphen.")
|
||||
raise ValidationError(msg)
|
||||
|
@ -105,28 +105,6 @@ def validate_soa_record(value):
|
|||
raise ValidationError(msg)
|
||||
|
||||
|
||||
def validate_caa_record(value):
|
||||
# 0-255 issue|issuewild|iodef "domain|mailto:email"
|
||||
# 0 issue "letsewncript.org"
|
||||
msg = _("%s is not an appropiate CAA record value, sintax: 0-255 issue|issuewild|iodef \"domain|mailto:email\"") % value
|
||||
values = value.split()
|
||||
if len(values) != 3:
|
||||
raise ValidationError(msg)
|
||||
|
||||
patron_flag = r'^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
|
||||
patron_tag = r'^(issue|issuewild|iodef)$'
|
||||
patron_value_domain = r'^"[a-zA-Z0-9-.]+\.[a-zA-Z]+\.?"$'
|
||||
patron_value_mailto = r'^"mailto:[a-zA-Z0-9.]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"$'
|
||||
flag = re.match(patron_flag, values[0])
|
||||
tag = re.match(patron_tag, values[1])
|
||||
if values[1] == 'iodef':
|
||||
valor = re.match(patron_value_mailto, values[2])
|
||||
else:
|
||||
valor = re.match(patron_value_domain, values[2])
|
||||
if not (flag and tag and valor):
|
||||
raise ValidationError(msg)
|
||||
|
||||
|
||||
def validate_quoted_record(value):
|
||||
value = value.strip()
|
||||
if ' ' in value and (value[0] != '"' or value[-1] != '"'):
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB
|
||||
BBBB BBBB BBBBBBBBBB
|
||||
|
||||
BBBBB BBBBBBBBBBBBBBBBBB
|
||||
BBBBBBBB
|
||||
|
||||
|
||||
BBBBB BBBBBBBBBBB
|
||||
BB BBBBBBBB
|
||||
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFFFFFFFFFFFXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXX gettext(u'History') XXXX
|
||||
XXXXXXXX gettext(u'Edit')
|
||||
XXXXXX
|
||||
BBBB
|
||||
|
||||
BBBBB
|
||||
BBBBBBBB
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBB
|
||||
BBBB BBBB BBBBBBBBBB BBBBBB
|
||||
|
||||
BBBBB BBBBBBBBBBB
|
||||
XXXX XXXXXXXXXXXXXXXXXXXX
|
||||
XX XXXXXXBBB BBBBBBBBBBBBBXX gettext(u'Home') XXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXX
|
||||
XXXXXXXX XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBXXFFFFFFFFFFFFFFFFFFXXXX
|
||||
XXXXXXXX gettext(u'History')
|
||||
XXXXXX
|
||||
BBBBBBBB
|
||||
|
||||
BBBBB BBBBBBB
|
||||
XXXX XXXXXXXXXXXXXXXXXX
|
||||
XXXX XXXXXXXXXXXXXXX
|
||||
|
||||
BB BBBBBBBBBBB
|
||||
XXXXXX XXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXX
|
||||
XXXX
|
||||
XXX XXXXXXXXXXXX gettext(u'Date/time') XXXXX
|
||||
XXX XXXXXXXXXXXX gettext(u'User') XXXXX
|
||||
XXX XXXXXXXXXXXX gettext(u'Action') XXXXX
|
||||
XXXXX
|
||||
XXXXXXXX
|
||||
XXXXXXX
|
||||
BBB BBBBBB BB BBBBBBBBBBB
|
||||
XXXX
|
||||
XXX XXXXXXXXXXXXFFFFFFFFFFFFFFFFFFFFFFXXXXX
|
||||
XXXXBB BBBBBBBBBBBBBBBBBBBBBBBBB XXBBBBBXXXXX
|
||||
XXXXBB BBBBBBBBBBBBBBBBBB BBB BBB BBBBBBBBBBBBBBBBBBBBB gettext(u'Added') BBBBBBBBB XX XXXXXXBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXX XXXXXBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBXXXXXXXXXXXXXXXXX
|
||||
XXXXX
|
||||
BBBBBB
|
||||
XXXXXXXX
|
||||
XXXXXXXX
|
||||
BBBB
|
||||
XXX gettext(u"This object doesn't have a change history. It probably wasn't added via this admin site.") XXXX
|
||||
BBBBB
|
||||
XXXXXX
|
||||
XXXXXX
|
||||
BBBBBBBB
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import datetime
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.utils.timezone import utc
|
||||
import orchestra.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Message',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('author_name', models.CharField(blank=True, max_length=256, verbose_name='author name')),
|
||||
('content', models.TextField(verbose_name='content')),
|
||||
('created_on', models.DateTimeField(auto_now_add=True, verbose_name='created on')),
|
||||
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_messages', to=settings.AUTH_USER_MODEL, verbose_name='author')),
|
||||
],
|
||||
options={
|
||||
'get_latest_by': 'id',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Queue',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128, unique=True, verbose_name='name')),
|
||||
('verbose_name', models.CharField(blank=True, max_length=128, verbose_name='verbose_name')),
|
||||
('default', models.BooleanField(default=False, verbose_name='default')),
|
||||
('notify', orchestra.models.fields.MultiSelectField(blank=True, choices=[('SUPPORT', 'Support tickets'), ('ADMIN', 'Administrative'), ('BILLING', 'Billing'), ('TECH', 'Technical'), ('ADDS', 'Announcements'), ('EMERGENCY', 'Emergency contact')], default=('SUPPORT', 'ADMIN', 'BILLING', 'TECH', 'ADDS', 'EMERGENCY'), help_text='Contacts to notify by email', max_length=256, verbose_name='notify')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Ticket',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('creator_name', models.CharField(blank=True, max_length=256, verbose_name='creator name')),
|
||||
('subject', models.CharField(max_length=256, verbose_name='subject')),
|
||||
('description', models.TextField(verbose_name='description')),
|
||||
('priority', models.CharField(choices=[('HIGH', 'High'), ('MEDIUM', 'Medium'), ('LOW', 'Low')], default='MEDIUM', max_length=32, verbose_name='priority')),
|
||||
('state', models.CharField(choices=[('NEW', 'New'), ('IN_PROGRESS', 'In Progress'), ('RESOLVED', 'Resolved'), ('FEEDBACK', 'Feedback'), ('REJECTED', 'Rejected'), ('CLOSED', 'Closed')], default='NEW', max_length=32, verbose_name='state')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created')),
|
||||
('updated_at', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
||||
('cc', models.TextField(blank=True, help_text='emails to send a carbon copy to', verbose_name='CC')),
|
||||
('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
||||
('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets_owned', to=settings.AUTH_USER_MODEL, verbose_name='assigned to')),
|
||||
('queue', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to='issues.Queue')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['-updated_at'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TicketTracker',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trackers', to='issues.Ticket', verbose_name='ticket')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_trackers', to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='message',
|
||||
name='ticket',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='issues.Ticket', verbose_name='ticket'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='tickettracker',
|
||||
unique_together=set([('ticket', 'user')]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='created'),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='message',
|
||||
name='created_on',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='message',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 3, 20, 10, 27, 45, 766388, tzinfo=utc), verbose_name='created at'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='creator',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets_created', to=settings.AUTH_USER_MODEL, verbose_name='created by'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='owner',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets_owned', to=settings.AUTH_USER_MODEL, verbose_name='assigned to'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='queue',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='issues.Queue'),
|
||||
),
|
||||
]
|
|
@ -1,55 +0,0 @@
|
|||
XXXXXXXXX XXXX XXXXXX XXXXXXXXXXXX XXXXX XXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXX
|
||||
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XX
|
||||
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX XX
|
||||
XXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX
|
||||
XXXXXX XXXXXXXXXXXXXXXX
|
||||
XX X XXXXXXXXXXXX XXXXXXXX XXXXXXXXXXX XXXXXXXXXX XXXXX XXXXXXXXXXX XXXXXXX XXXXXX XXXXX X
|
||||
XXXX X XXXXXXXXXXXX XXXXXXXX XXXXXXXXXXX XXXXXXXXXX XXXXX XXXXXX XXXXX X
|
||||
XXXXX XX X XXXXXXXXXXXX XXXX X
|
||||
XXXXX XX X XXXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXXXXX XXXXXXXX XXXXXXX XXXX XXXXXXXXXXXXXXX XXXXXXXX
|
||||
XXXXX XX XXXX X XXXXXXXXXX XXXXXX X
|
||||
XXXXX XX XX X XXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXX X
|
||||
XXXXX XX XX X XXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXX X
|
||||
XXXXX XX XX X XXXXXXXXXX XXXXXX XXXXXXXXXXX XXXXX X
|
||||
XXXXX XX XXXX X XXXXXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXXX XXXX X
|
||||
|
||||
XXXXXXXX
|
||||
XXXXXXX
|
||||
XXXXXX
|
||||
|
||||
XXXXXXXXXXXX XXXXXX XXXXX XXXXXXXXXXXXXX
|
||||
|
||||
XXXXXX XXXXXXXXXXXXX
|
||||
XXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX X XX XXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
XXXXXXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXXX X XXXX XXXX X XX XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXX XXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXXXX XX XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX XXXXXXXXXX XXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX XXXX XXXXXXXX XXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
|
||||
XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXX XXXX XXXX XXX XXXX XXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXX XXXX XXXX XXXX XXXX XXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXX
|
||||
|
||||
XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXX XXXXX X XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXX XXXXX XXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
|
||||
|
||||
XXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX
|
||||
XXXXXXXX
|
||||
|
||||
XXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
XXXX XXXXXXXXX XX XXXXXXXX XXXXXXXXXXX
|
||||
XXXX
|
||||
|
||||
XXXXXXX
|
||||
XXXXXXX
|
|
@ -57,14 +57,6 @@ class MailmanVirtualDomainController(ServiceController):
|
|||
def commit(self):
|
||||
context = self.get_context_files()
|
||||
super(MailmanVirtualDomainController, self).commit()
|
||||
self.append(textwrap.dedent("""
|
||||
# Apply changes if needed
|
||||
if [[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]]; then
|
||||
postmap %(virtual_alias_domains)s
|
||||
systemctl reload postfix
|
||||
fi
|
||||
exit $exit_code""") % context
|
||||
)
|
||||
|
||||
def get_context_files(self):
|
||||
return {
|
||||
|
@ -109,7 +101,7 @@ class MailmanController(MailmanVirtualDomainController):
|
|||
for suffix in self.address_suffixes:
|
||||
context['suffix'] = suffix
|
||||
# Because mailman doesn't properly handle lists aliases we need virtual aliases
|
||||
if context['address_name'] != context['name'] or context['address_domain'] != settings.LISTS_DEFAULT_DOMAIN:
|
||||
if context['address_name'] != context['name']:
|
||||
aliases.append("%(address_name)s%(suffix)s@%(domain)s\t%(name)s%(suffix)s@grups.pangea.org" % context)
|
||||
return '\n'.join(aliases)
|
||||
|
||||
|
@ -173,18 +165,7 @@ class MailmanController(MailmanVirtualDomainController):
|
|||
|
||||
|
||||
def commit(self):
|
||||
context = self.get_context_files()
|
||||
self.append(textwrap.dedent("""
|
||||
# Apply changes if needed
|
||||
if [[ $UPDATED_VIRTUAL_ALIAS == 1 ]]; then
|
||||
postmap %(virtual_alias)s
|
||||
fi
|
||||
if [[ $UPDATED_VIRTUAL_ALIAS_DOMAINS == 1 ]]; then
|
||||
systemctl reload postfix
|
||||
fi
|
||||
exit $exit_code""") % context
|
||||
)
|
||||
|
||||
pass
|
||||
|
||||
def get_context_files(self):
|
||||
return {
|
||||
|
@ -218,7 +199,7 @@ class MailmanTraffic(ServiceMonitor):
|
|||
model = 'lists.List'
|
||||
resource = ServiceMonitor.TRAFFIC
|
||||
verbose_name = _("Mailman traffic")
|
||||
script_executable = '/usr/bin/python3'
|
||||
script_executable = '/usr/bin/python'
|
||||
monthly_sum_old_values = True
|
||||
doc_settings = (settings,
|
||||
('LISTS_MAILMAN_POST_LOG_PATH',)
|
||||
|
@ -229,10 +210,9 @@ class MailmanTraffic(ServiceMonitor):
|
|||
context = {
|
||||
'postlogs': str((postlog, postlog+'.1')),
|
||||
'current_date': self.current_date.strftime("%Y-%m-%d %H:%M:%S %Z"),
|
||||
'default_domain': settings.LISTS_DEFAULT_DOMAIN,
|
||||
}
|
||||
|
||||
self.append(textwrap.dedent("""\
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
@ -263,6 +243,7 @@ class MailmanTraffic(ServiceMonitor):
|
|||
'Nov': '11',
|
||||
'Dec': '12',
|
||||
}}
|
||||
mailman_addr = re.compile(r'.*-(admin|bounces|confirm|join|leave|owner|request|subscribe|unsubscribe)@.*|mailman@.*')
|
||||
|
||||
def prepare(object_id, list_name, ini_date):
|
||||
global lists
|
||||
|
@ -274,33 +255,39 @@ class MailmanTraffic(ServiceMonitor):
|
|||
for postlog in postlogs:
|
||||
try:
|
||||
with open(postlog, 'r') as postlog:
|
||||
recps_dict = {{}}
|
||||
for line in postlog.readlines():
|
||||
line = line.split()
|
||||
if 'recips,' in line:
|
||||
__, __, __, __, __, id, __, __, list_name, __, recps = line[:11]
|
||||
recps_dict[id] = recps
|
||||
if len(line) < 11:
|
||||
continue
|
||||
if not 'bytes' in line:
|
||||
continue
|
||||
month, day, time, year, __, __, __, __, list_name, __, addr, size = line[:12]
|
||||
month, day, time, year, __, __, __, list_name, __, addr, size = line[:11]
|
||||
try:
|
||||
list_name = list_name.split('@')[0]
|
||||
list = lists[list_name]
|
||||
except KeyError:
|
||||
continue
|
||||
else:
|
||||
# discard mailman messages because of inconsistent POST logging
|
||||
if mailman_addr.match(addr):
|
||||
continue
|
||||
date = year + months[month] + day + time.replace(':', '')
|
||||
if list[0] < int(date) < end_date:
|
||||
if id in recps_dict:
|
||||
list[2] += int(size) * int(recps_dict[id])
|
||||
|
||||
size = size[5:-1]
|
||||
try:
|
||||
list[2] += int(size)
|
||||
except ValueError:
|
||||
# anonymized post
|
||||
pass
|
||||
except IOError as e:
|
||||
sys.stderr.write(str(e)+'\\n')
|
||||
|
||||
for list_name, opts in lists.items():
|
||||
__, object_id, size = opts
|
||||
print(object_id, size)
|
||||
if size:
|
||||
cmd = ' '.join(('list_members', list_name, '| wc -l'))
|
||||
ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
subscribers = ps.communicate()[0].strip()
|
||||
size *= int(subscribers)
|
||||
sys.stderr.write("%s %s*%s traffic*subscribers\\n" % (object_id, size, subscribers))
|
||||
print object_id, size
|
||||
""").format(**context)
|
||||
)
|
||||
|
||||
|
|
Binary file not shown.
|
@ -1,117 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-09-06 10:23+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin.py:28 admin.py:42
|
||||
msgid "Address"
|
||||
msgstr "Direccio"
|
||||
|
||||
#: admin.py:32
|
||||
msgid "Admin"
|
||||
msgstr "Administrador"
|
||||
|
||||
#: admin.py:44
|
||||
#, python-format
|
||||
msgid "Additional address besides the default <name>@%s"
|
||||
msgstr "Adreça addicional a més del valor predeterminat <name>@%s"
|
||||
|
||||
#: backends.py:16
|
||||
msgid "Mailman virtdomain-only"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:201
|
||||
msgid "Mailman traffic"
|
||||
msgstr "Trànsit de Mailman"
|
||||
|
||||
#: backends.py:309
|
||||
msgid "Mailman subscribers"
|
||||
msgstr "Subscriptors Mailman"
|
||||
|
||||
#: filters.py:7
|
||||
msgid "has custom address"
|
||||
msgstr "té adreça personalitzada"
|
||||
|
||||
#: filters.py:12
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:13
|
||||
msgid "False"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:13
|
||||
msgid "name"
|
||||
msgstr "nom"
|
||||
|
||||
#: models.py:14
|
||||
#, python-format
|
||||
msgid "Default list address <name>@%s"
|
||||
msgstr "Adreça de llista predeterminada <name>@%s"
|
||||
|
||||
#: models.py:15
|
||||
msgid "address name"
|
||||
msgstr "Nom de l'adreça"
|
||||
|
||||
#: models.py:18
|
||||
msgid "address domain"
|
||||
msgstr "Domini adicional"
|
||||
|
||||
#: models.py:19
|
||||
msgid "admin email"
|
||||
msgstr "Correu electrònic d'administració"
|
||||
|
||||
#: models.py:20
|
||||
msgid "Administration email address"
|
||||
msgstr "Adreça de correu electrònic d'administració"
|
||||
|
||||
#: models.py:21
|
||||
msgid "Account"
|
||||
msgstr "Compte"
|
||||
|
||||
#: models.py:24
|
||||
msgid "active"
|
||||
msgstr "actiu"
|
||||
|
||||
#: models.py:25
|
||||
msgid ""
|
||||
"Designates whether this account should be treated as active. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
msgstr ""
|
||||
"Designa si aquest compte ha de ser tractat com a actiu. Deselecteu això "
|
||||
"En lloc de suprimir els comptes."
|
||||
|
||||
#: models.py:47
|
||||
msgid "Domain should be selected for provided address name."
|
||||
msgstr "El domini s'ha de seleccionar per al nom de l'adreça proporcionat."
|
||||
|
||||
#: serializers.py:20
|
||||
msgid "Password"
|
||||
msgstr "Contrasenya"
|
||||
|
||||
#: serializers.py:25
|
||||
msgid ""
|
||||
"Enter a valid password. This value may contain any ascii character except "
|
||||
"for '/\"/\\/ characters."
|
||||
msgstr ""
|
||||
"Introduïu una contrasenya vàlida. Aquest valor pot contenir qualsevol personatge ASCII excepte"
|
||||
"Per a '/\"/\\/caràcters. "
|
||||
|
||||
#: serializers.py:43
|
||||
msgid "address_domains should should be provided when providing an addres_name"
|
||||
msgstr "S'hauria de proporcionar address_domains en proporcionar un address_name"
|
Binary file not shown.
|
@ -1,117 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-09-06 10:03+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin.py:28 admin.py:42
|
||||
msgid "Address"
|
||||
msgstr "Dirección"
|
||||
|
||||
#: admin.py:32
|
||||
msgid "Admin"
|
||||
msgstr "Administrador"
|
||||
|
||||
#: admin.py:44
|
||||
#, python-format
|
||||
msgid "Additional address besides the default <name>@%s"
|
||||
msgstr "Dirección adicional además del valor predeterminado <name>@%s"
|
||||
|
||||
#: backends.py:16
|
||||
msgid "Mailman virtdomain-only"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:201
|
||||
msgid "Mailman traffic"
|
||||
msgstr "Tráfico Mailman"
|
||||
|
||||
#: backends.py:309
|
||||
msgid "Mailman subscribers"
|
||||
msgstr "Subscriptores Mailman"
|
||||
|
||||
#: filters.py:7
|
||||
msgid "has custom address"
|
||||
msgstr "tiene dirección personalizada"
|
||||
|
||||
#: filters.py:12
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:13
|
||||
msgid "False"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:13
|
||||
msgid "name"
|
||||
msgstr "nombre"
|
||||
|
||||
#: models.py:14
|
||||
#, python-format
|
||||
msgid "Default list address <name>@%s"
|
||||
msgstr "dirección de lista por defecto <name>@%s"
|
||||
|
||||
#: models.py:15
|
||||
msgid "address name"
|
||||
msgstr "nombre de dirección"
|
||||
|
||||
#: models.py:18
|
||||
msgid "address domain"
|
||||
msgstr "dominio adicional"
|
||||
|
||||
#: models.py:19
|
||||
msgid "admin email"
|
||||
msgstr "correo administrador"
|
||||
|
||||
#: models.py:20
|
||||
msgid "Administration email address"
|
||||
msgstr "dirección correo administrador"
|
||||
|
||||
#: models.py:21
|
||||
msgid "Account"
|
||||
msgstr "Cuenta"
|
||||
|
||||
#: models.py:24
|
||||
msgid "active"
|
||||
msgstr "activo"
|
||||
|
||||
#: models.py:25
|
||||
msgid ""
|
||||
"Designates whether this account should be treated as active. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
msgstr ""
|
||||
"Designa si esta cuenta debe tratarse como activa. Deseleccionar esto "
|
||||
"En lugar de eliminar cuentas."
|
||||
|
||||
#: models.py:47
|
||||
msgid "Domain should be selected for provided address name."
|
||||
msgstr "El dominio debe seleccionarse para el nombre de la dirección proporcionado."
|
||||
|
||||
#: serializers.py:20
|
||||
msgid "Password"
|
||||
msgstr "Contraseña"
|
||||
|
||||
#: serializers.py:25
|
||||
msgid ""
|
||||
"Enter a valid password. This value may contain any ascii character except "
|
||||
"for '/\"/\\/ characters."
|
||||
msgstr ""
|
||||
"Ingrese una contraseña válida. Este valor puede contener cualquier carácter ASCII excepto"
|
||||
"Para '/\"/\\/caracteres."
|
||||
|
||||
#: serializers.py:43
|
||||
msgid "address_domains should should be provided when providing an addres_name"
|
||||
msgstr "address_domains debe proporcionarse al proporcionar un addres_name"
|
|
@ -1,6 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
||||
from __future__ import unicode_literals
|
||||
# Generated by Django 2.2.28 on 2023-09-01 14:59
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
@ -10,8 +8,10 @@ import orchestra.core.validators
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('domains', '0001_initial'),
|
||||
('domains', '__first__'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
|
@ -20,46 +20,15 @@ class Migration(migrations.Migration):
|
|||
name='List',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(help_text='Default list address <name>@lists.orchestra.lan', max_length=128, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('address_name', models.CharField(blank=True, max_length=128, validators=[orchestra.core.validators.validate_name], verbose_name='address name')),
|
||||
('name', models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('address_name', models.CharField(blank=True, max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='address name')),
|
||||
('admin_email', models.EmailField(help_text='Administration email address', max_length=254, verbose_name='admin email')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this account should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lists', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('address_domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='domains.Domain', verbose_name='address domain')),
|
||||
('address_domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain')),
|
||||
],
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='list',
|
||||
unique_together=set([('address_name', 'address_domain')]),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='list',
|
||||
name='address_domain',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='domains.Domain', verbose_name='address domain'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='list',
|
||||
name='address_name',
|
||||
field=models.CharField(blank=True, max_length=52, validators=[orchestra.core.validators.validate_name], verbose_name='address name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='list',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=52, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='list',
|
||||
name='address_name',
|
||||
field=models.CharField(blank=True, max_length=64, validators=[orchestra.core.validators.validate_name], verbose_name='address name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='list',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='list',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Default list address <name>@lists.orchestra.lan', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
||||
options={
|
||||
'unique_together': {('address_name', 'address_domain')},
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
# Generated by Django 2.2.24 on 2024-07-11 12:25
|
||||
|
||||
from django.db import migrations, models
|
||||
import orchestra.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('lists', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='list',
|
||||
name='name',
|
||||
field=models.CharField(help_text='Default list address <name>@grups.pangea.org', max_length=64, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name'),
|
||||
),
|
||||
]
|
|
@ -47,7 +47,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
|||
)
|
||||
add_fieldsets = (
|
||||
(None, {
|
||||
'fields': ('account_link', 'name', 'password1', 'password2', 'filtering', 'ratelimit'),
|
||||
'fields': ('account_link', 'name', 'password1', 'password2', 'filtering'),
|
||||
}),
|
||||
(_("Custom filtering"), {
|
||||
'classes': ('collapse',),
|
||||
|
@ -61,7 +61,7 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
|||
)
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': ('name', 'password', 'is_active', 'account_link', 'filtering', 'ratelimit'),
|
||||
'fields': ('name', 'password', 'is_active', 'account_link', 'filtering'),
|
||||
}),
|
||||
(_("Custom filtering"), {
|
||||
'classes': ('collapse',),
|
||||
|
@ -213,8 +213,6 @@ class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedMo
|
|||
old = Mailbox.objects.get(pk=obj.pk)
|
||||
if old.custom_filtering != obj.custom_filtering:
|
||||
messages.warning(request, msg)
|
||||
# pass var to the backend so you don't change the password
|
||||
obj.changepass = None
|
||||
elif obj.custom_filtering:
|
||||
messages.warning(request, msg)
|
||||
super(MailboxAdmin, self).save_model(request, obj, form, change)
|
||||
|
|
|
@ -69,7 +69,6 @@ class UNIXUserMaildirController(SieveFilteringMixin, ServiceController):
|
|||
self.append(textwrap.dedent("""
|
||||
# Update/create %(user)s user state
|
||||
if id %(user)s ; then
|
||||
if [[ "%(changepass)s" == "True" ]]; then
|
||||
old_password=$(getent shadow %(user)s | cut -d':' -f2)
|
||||
usermod %(user)s \\
|
||||
--shell %(initial_shell)s \\
|
||||
|
@ -78,17 +77,11 @@ class UNIXUserMaildirController(SieveFilteringMixin, ServiceController):
|
|||
# Postfix SASL caches passwords
|
||||
RESTART_POSTFIX=1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
useradd %(user)s \\
|
||||
--home %(home)s \\
|
||||
--password '%(password)s'
|
||||
fi
|
||||
if [[ "%(is_active)s" == "True" ]]; then
|
||||
usermod --unlock %(user)s
|
||||
else
|
||||
usermod --lock %(user)s
|
||||
fi
|
||||
mkdir -p %(home)s
|
||||
chmod 751 %(home)s
|
||||
chown %(user)s:%(group)s %(home)s""") % context
|
||||
|
@ -142,22 +135,15 @@ class UNIXUserMaildirController(SieveFilteringMixin, ServiceController):
|
|||
super().commit()
|
||||
|
||||
def get_context(self, mailbox):
|
||||
# Check if you have to change password
|
||||
try:
|
||||
changepass = mailbox.changepass
|
||||
except:
|
||||
changepass = True
|
||||
context = {
|
||||
'user': mailbox.name,
|
||||
'group': mailbox.name,
|
||||
'name': mailbox.name,
|
||||
'password': mailbox.password,
|
||||
'password': mailbox.password if mailbox.active else '*%s' % mailbox.password,
|
||||
'home': mailbox.get_home(),
|
||||
'maildir': os.path.join(mailbox.get_home(), 'Maildir'),
|
||||
'initial_shell': self.SHELL,
|
||||
'banner': self.get_banner(),
|
||||
'changepass': changepass,
|
||||
'is_active': mailbox.active,
|
||||
}
|
||||
context['deleted_home'] = settings.MAILBOXES_MOVE_ON_DELETE_PATH % context
|
||||
return context
|
||||
|
@ -458,30 +444,12 @@ class DovecotMaildirDisk(ServiceMonitor):
|
|||
self.append(textwrap.dedent("""\
|
||||
function monitor () {
|
||||
SIZE=$(du -sb $1/Maildir/ 2> /dev/null || echo 0) && echo $SIZE | awk '{print $1}'
|
||||
list=()
|
||||
}"""))
|
||||
|
||||
def monitor(self, mailbox):
|
||||
context = self.get_context(mailbox)
|
||||
# self.append("echo %(object_id)s $(monitor %(maildir_path)s)" % context)
|
||||
# self.append("echo %(object_id)s $(monitor %(home)s)" % context)
|
||||
self.append("list[${#list[@]}]=\'echo %(object_id)s $(monitor %(home)s)\'" % context)
|
||||
|
||||
def commit(self):
|
||||
self.append(textwrap.dedent("""\
|
||||
proces=0
|
||||
for cmd in "${list[@]}"
|
||||
do
|
||||
eval $cmd &
|
||||
proces=$((proces+1))
|
||||
if [ $proces -ge 10 ];then
|
||||
wait
|
||||
proces=0
|
||||
fi
|
||||
done
|
||||
wait
|
||||
exit $exit_code
|
||||
"""))
|
||||
self.append("echo %(object_id)s $(monitor %(home)s)" % context)
|
||||
|
||||
def get_context(self, mailbox):
|
||||
context = {
|
||||
|
@ -500,7 +468,7 @@ class PostfixMailscannerTraffic(ServiceMonitor):
|
|||
model = 'mailboxes.Mailbox'
|
||||
resource = ServiceMonitor.TRAFFIC
|
||||
verbose_name = _("Postfix-Mailscanner traffic")
|
||||
script_executable = '/usr/bin/python3'
|
||||
script_executable = '/usr/bin/python'
|
||||
monthly_sum_old_values = True
|
||||
doc_settings = (settings,
|
||||
('MAILBOXES_MAIL_LOG_PATH',)
|
||||
|
@ -530,10 +498,6 @@ class PostfixMailscannerTraffic(ServiceMonitor):
|
|||
end_date = int(end_datetime.strftime('%Y%m%d%H%M%S'))
|
||||
months = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
|
||||
months = dict((m, '%02d' % n) for n, m in enumerate(months, 1))
|
||||
users = {{}}
|
||||
sends = {{}}
|
||||
register_imap_traffic = False
|
||||
register_pop_traffic = False
|
||||
|
||||
def inside_period(month, day, time, ini_date):
|
||||
global months
|
||||
|
@ -549,109 +513,91 @@ class PostfixMailscannerTraffic(ServiceMonitor):
|
|||
date += time.replace(':', '')
|
||||
return ini_date < int(date) < end_date
|
||||
|
||||
def search_username(pattern, users, line):
|
||||
match = pattern.search(line)
|
||||
if not match:
|
||||
return None
|
||||
username = match.groups(1)[0]
|
||||
if username not in users.keys():
|
||||
return None
|
||||
return username
|
||||
|
||||
def search_size(line, users, username, pattern):
|
||||
month, day, time, req_id = line.split()[:4]
|
||||
if inside_period(month, day, time, users[username][0]):
|
||||
group = req_id.split('<')[-1][:-2]
|
||||
matches = pattern.search(line)
|
||||
if not matches:
|
||||
return None, None
|
||||
return group, matches
|
||||
return None, None
|
||||
users = {{}}
|
||||
delivers = {{}}
|
||||
reverse = {{}}
|
||||
|
||||
def prepare(object_id, mailbox, ini_date):
|
||||
global users
|
||||
global sends
|
||||
global delivers
|
||||
global reverse
|
||||
ini_date = to_local_timezone(ini_date)
|
||||
ini_date = int(ini_date.strftime('%Y%m%d%H%M%S'))
|
||||
users[mailbox] = (ini_date, object_id)
|
||||
sends[mailbox] = {{}}
|
||||
|
||||
def monitor(users, sends, maillogs):
|
||||
grupos = []
|
||||
sasl_username_pattern = re.compile(r'sasl_username=([a-zA-Z0-9\.\-_]+)')
|
||||
size_pattern = re.compile(r'size=(\d+),')
|
||||
|
||||
pop_username_pattern = re.compile(r' pop3\(([^)].*)\)')
|
||||
pop_size_pattern = re.compile(r'size=(\d+)')
|
||||
|
||||
imap_username_pattern = re.compile(r' imap\(([^)].*)\)')
|
||||
imap_size_pattern = re.compile(r"in=(\d+) out=(\d+)")
|
||||
delivers[mailbox] = set()
|
||||
reverse[mailbox] = set()
|
||||
|
||||
def monitor(users, delivers, reverse, maillogs):
|
||||
targets = {{}}
|
||||
counter = {{}}
|
||||
user_regex = re.compile(r'\(Authenticated sender: ([^ ]+)\)')
|
||||
for maillog in maillogs:
|
||||
try:
|
||||
with open(maillog, 'r') as maillog:
|
||||
for line in maillog.readlines():
|
||||
# Only search for Authenticated sendings
|
||||
if 'sasl_username=' in line:
|
||||
# si el usuario es uno de los elegidos y el rango de tiempo es correcto
|
||||
# recoge el id de grupo
|
||||
username = search_username(sasl_username_pattern, users, line)
|
||||
if username is None:
|
||||
if '(Authenticated sender: ' in line:
|
||||
username = user_regex.search(line).groups()[0]
|
||||
try:
|
||||
sender = users[username]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
month, day, time, __, __, req_id = line.split()[:6]
|
||||
if inside_period(month, day, time, users[username][0]):
|
||||
group = req_id[:-1]
|
||||
sends[username][group] = 0
|
||||
grupos.append(group)
|
||||
else:
|
||||
# busca el size de envios donde se alla anadido el groupID anteriormente,
|
||||
# una vez encontrado borra el groupID
|
||||
for id in grupos:
|
||||
if id in line:
|
||||
match = size_pattern.search(line)
|
||||
if not match:
|
||||
month, day, time, __, proc, id = line.split()[:6]
|
||||
if inside_period(month, day, time, sender[0]):
|
||||
# Add new email
|
||||
delivers[id[:-1]] = username
|
||||
# Look for a MailScanner requeue ID
|
||||
elif ' Requeue: ' in line:
|
||||
id, __, req_id = line.split()[6:9]
|
||||
id = id.split('.')[0]
|
||||
try:
|
||||
username = delivers[id]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
targets[req_id] = (username, 0)
|
||||
reverse[username].add(req_id)
|
||||
# Look for the mail size and count the number of recipients of each email
|
||||
else:
|
||||
try:
|
||||
month, day, time, __, proc, req_id, __, msize = line.split()[:8]
|
||||
except ValueError:
|
||||
# not interested in this line
|
||||
continue
|
||||
for k, v in sends.items():
|
||||
if id in sends[k].keys():
|
||||
sends[k][id] += int(match.groups(1)[0])
|
||||
grupos.remove(id)
|
||||
|
||||
# pop trafic
|
||||
if register_pop_traffic:
|
||||
if 'pop3(' in line and 'size' in line:
|
||||
username = search_username(pop_username_pattern, users, line)
|
||||
if username is None:
|
||||
continue
|
||||
group, matches = search_size(line, users, username, pop_size_pattern)
|
||||
if group is not None and matches is not None :
|
||||
sends[username][group] = int(matches.groups(1)[0])
|
||||
|
||||
# imap trafic
|
||||
if register_imap_traffic:
|
||||
if 'imap(' in line and 'out=' in line:
|
||||
username = search_username(imap_username_pattern, users, line)
|
||||
if username is None:
|
||||
continue
|
||||
group, matches = search_size(line, users, username, imap_size_pattern)
|
||||
if group is not None and matches is not None :
|
||||
value = int(matches.group(1)) + int(matches.group(2))
|
||||
sends[username][group] = value
|
||||
|
||||
if proc.startswith('postfix/'):
|
||||
req_id = req_id[:-1]
|
||||
if msize.startswith('size='):
|
||||
try:
|
||||
target = targets[req_id]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
targets[req_id] = (target[0], int(msize[5:-1]))
|
||||
elif proc.startswith('postfix/smtp'):
|
||||
try:
|
||||
target = targets[req_id]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if inside_period(month, day, time, users[target[0]][0]):
|
||||
try:
|
||||
counter[req_id] += 1
|
||||
except KeyError:
|
||||
counter[req_id] = 1
|
||||
except IOError as e:
|
||||
sys.stderr.write(str(e)+'\\n')
|
||||
|
||||
# devolver la sumatoria de valores a orchestra (id_user, size)
|
||||
for username, opts in users.items():
|
||||
total_size = 0
|
||||
for size in sends[username].values():
|
||||
total_size += size
|
||||
print(f"{{opts[1]}} {{total_size}}")
|
||||
for username, opts in users.iteritems():
|
||||
size = 0
|
||||
for req_id in reverse[username]:
|
||||
size += targets[req_id][1] * counter.get(req_id, 0)
|
||||
print opts[1], size
|
||||
""").format(**context)
|
||||
)
|
||||
|
||||
def commit(self):
|
||||
self.append('monitor(users, sends, maillogs)')
|
||||
self.append('monitor(users, delivers, reverse, maillogs)')
|
||||
|
||||
def monitor(self, mailbox):
|
||||
context = self.get_context(mailbox)
|
||||
|
@ -672,57 +618,3 @@ class RoundcubeIdentityController(ServiceController):
|
|||
verbose_name = _("Roundcube Identity Controller")
|
||||
model = 'mailboxes.Mailbox'
|
||||
|
||||
|
||||
|
||||
class RSpamdRatelimitController(ServiceController):
|
||||
"""
|
||||
rspamd ratelimit to user
|
||||
"""
|
||||
|
||||
verbose_name = _("rspamd ratelimit user")
|
||||
model = 'mailboxes.Mailbox'
|
||||
|
||||
def save(self, mailbox):
|
||||
context = self.get_context(mailbox)
|
||||
self.append(textwrap.dedent("""
|
||||
sed -i '/^%(user)s$/d' %(maps)s
|
||||
echo '%(user)s' >> %(path_maps)s%(ratelimit)s.map
|
||||
systemctl reload rspamd.service
|
||||
""") % context
|
||||
)
|
||||
|
||||
def delete(self, mailbox):
|
||||
context = self.get_context(mailbox)
|
||||
self.append(textwrap.dedent("""
|
||||
sed -i '/^%(user)s$/d' %(maps)s
|
||||
systemctl reload rspamd.service
|
||||
""") % context
|
||||
)
|
||||
|
||||
# def commit(self):
|
||||
# self.append('[[ $RELOAD_RSPAMD -eq 1 ]] && systemctl reload rspamd.service')
|
||||
# super().commit()
|
||||
|
||||
def get_context(self, mailbox):
|
||||
maps = self.extract_group_maps()
|
||||
context = {
|
||||
'user': mailbox.name,
|
||||
'ratelimit': mailbox.ratelimit,
|
||||
'maps': maps,
|
||||
'path_maps': settings.MAILBOXES_RATELIMIT_PATH_MAPS,
|
||||
}
|
||||
return context
|
||||
|
||||
def extract_group_maps(self):
|
||||
"""
|
||||
debulve string de todos los ficheros de maps assignados en settings para ratelimit
|
||||
return string
|
||||
"""
|
||||
choice_groups = settings.MAILBOXES_RATELIMIT_GROUP
|
||||
path = settings.MAILBOXES_RATELIMIT_PATH_MAPS
|
||||
group_maps = ''
|
||||
if len(choice_groups) > 0:
|
||||
for choice in choice_groups:
|
||||
group_maps += f"{path}{choice[0]}.map "
|
||||
|
||||
return group_maps
|
|
@ -54,11 +54,6 @@ class MailboxForm(forms.ModelForm):
|
|||
raise ValidationError("Name length should be less than %i." % max_length)
|
||||
return name
|
||||
|
||||
def clean_ratelimit(self):
|
||||
ratelimit = self.cleaned_data['ratelimit']
|
||||
if ratelimit is None:
|
||||
ratelimit = settings.MAILBOXES_RATELIMIT_GROUP_DEFAULT
|
||||
return ratelimit
|
||||
|
||||
class MailboxChangeForm(UserChangeForm, MailboxForm):
|
||||
pass
|
||||
|
|
Binary file not shown.
|
@ -1,298 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-09-06 09:36+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin.py:31
|
||||
msgid "autoresponse"
|
||||
msgstr "autoresposta"
|
||||
|
||||
#: admin.py:52 admin.py:66 settings.py:177
|
||||
msgid "Custom filtering"
|
||||
msgstr "Filtre personalitzat"
|
||||
|
||||
#: admin.py:54
|
||||
msgid ""
|
||||
"Please remember to select <tt>custom filtering</tt> if you want this filter "
|
||||
"to be applied."
|
||||
msgstr ""
|
||||
"Recordeu que seleccioneu <tt> Filtratge personalitzat </tt> si voleu aquest filtre"
|
||||
"Per aplicar-se."
|
||||
|
||||
#: admin.py:58 admin.py:70 admin.py:114
|
||||
msgid "Addresses"
|
||||
msgstr "Adreces"
|
||||
|
||||
#: admin.py:122
|
||||
msgid "Forward from"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:127
|
||||
msgid "Filtering"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:181
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Mailbox '%s' local address matches '%s', please consider if selecting it "
|
||||
"makes sense."
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:199
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Address <a href='{url}'>{addr}</a> clashes with '{mailbox}' mailbox local "
|
||||
"address. Consider adding this mailbox to the address."
|
||||
msgstr ""
|
||||
"Adreça <a href='{url}'> {addr} </a> xoca amb '{mailbox}' bustia local"
|
||||
"Adreça. Penseu en afegir aquesta bústia a l'adreça."
|
||||
|
||||
#: admin.py:210
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You have provided a custom filtering but filtering selected option is %s"
|
||||
msgstr ""
|
||||
"Heu proporcionat un filtratge personalitzat, però l'opció seleccionada per filtrar és %s"
|
||||
|
||||
#: admin.py:246 admin.py:252
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:260
|
||||
msgid "Mailboxes"
|
||||
msgstr "Busties"
|
||||
|
||||
#: admin.py:269
|
||||
msgid "Mailboxes links"
|
||||
msgstr "Links de busties"
|
||||
|
||||
#: admin.py:282
|
||||
msgid "Forward"
|
||||
msgstr "Redireccio"
|
||||
|
||||
#: admin.py:321
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Address '%s' matches mailbox '%s' local address, please consider if makes "
|
||||
"sense adding the mailbox on the mailboxes or forward field."
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:64
|
||||
msgid "UNIX maildir user"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:263
|
||||
msgid "Postfix address virtdomain-only"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:347
|
||||
msgid "Postfix address"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:434
|
||||
msgid "Mail autoresponse"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:445
|
||||
msgid "Dovecot Maildir size"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:502
|
||||
msgid "Postfix-Mailscanner traffic"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:672
|
||||
msgid "Roundcube Identity Controller"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:682
|
||||
msgid "rspamd ratelimit user"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:9
|
||||
msgid "has mailbox"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:14
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:15
|
||||
msgid "False"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:28
|
||||
msgid "has forward"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:41
|
||||
msgid "has address"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:53
|
||||
msgid "has type server"
|
||||
msgstr "té un servidor de tipus"
|
||||
|
||||
#: forms.py:20 models.py:115
|
||||
msgid "addresses"
|
||||
msgstr "adreçes"
|
||||
|
||||
#: forms.py:84
|
||||
msgid "Mailboxes or forward address should be provided."
|
||||
msgstr "S'han de proporcionar bústies o adreça de reenviament."
|
||||
|
||||
#: models.py:17 models.py:101
|
||||
msgid "name"
|
||||
msgstr "nom"
|
||||
|
||||
#: models.py:19
|
||||
#, python-format
|
||||
msgid "Required. %s characters or fewer. Letters, digits and ./-/_ only."
|
||||
msgstr "Obligatori. %s caràcters o menys. Cartes, dígits i ./-/_ només."
|
||||
|
||||
#: models.py:22
|
||||
msgid "Enter a valid mailbox name."
|
||||
msgstr "Introduïu un nom de bústia vàlid."
|
||||
|
||||
#: models.py:24
|
||||
msgid "password"
|
||||
msgstr "contrasenya"
|
||||
|
||||
#: models.py:25
|
||||
msgid "account"
|
||||
msgstr "compte"
|
||||
|
||||
#: models.py:30
|
||||
msgid "filtering"
|
||||
msgstr "filtre"
|
||||
|
||||
#: models.py:32
|
||||
msgid ""
|
||||
"Arbitrary email filtering in <a href='https://tty1.net/blog/2011/sieve-"
|
||||
"tutorial_en.html'>sieve language</a>. This overrides any automatic junk "
|
||||
"email filtering"
|
||||
msgstr ""
|
||||
"Filtratge de correu electrònic arbitrari a <a href='https://tty1.net/blog/2011/sieve-"
|
||||
"Tutorial_en.html'> Idioma tamís </a>. Això substitueix qualsevol brossa automàtica"
|
||||
"Filtratge de correu electrònic"
|
||||
|
||||
#: models.py:35
|
||||
msgid "active"
|
||||
msgstr "actiu"
|
||||
|
||||
#: models.py:36
|
||||
msgid "ratelimit"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:43 models.py:106
|
||||
msgid "mailboxes"
|
||||
msgstr "busties"
|
||||
|
||||
#: models.py:76
|
||||
msgid "Custom filtering is selected but not provided."
|
||||
msgstr "El filtratge personalitzat està seleccionat però no es proporciona."
|
||||
|
||||
#: models.py:103
|
||||
msgid "Address name, left blank for a <i>catch-all</i> address"
|
||||
msgstr "Nom de l'adreça, deixa en blanc per a una adreça <i>aleatoria</i>"
|
||||
|
||||
#: models.py:105
|
||||
msgid "domain"
|
||||
msgstr "domini"
|
||||
|
||||
#: models.py:108
|
||||
msgid "forward"
|
||||
msgstr "redireccio"
|
||||
|
||||
#: models.py:110
|
||||
msgid "Space separated email addresses or mailboxes"
|
||||
msgstr "Adreces de correu electrònic o bústies de correu electrònic separades per l'espai"
|
||||
|
||||
#: models.py:111
|
||||
msgid "Account"
|
||||
msgstr "Compte"
|
||||
|
||||
#: models.py:147
|
||||
#, python-format
|
||||
msgid "Please use mailboxes field for '%s' mailbox."
|
||||
msgstr "Utilitzeu el camp de bústies de correu per la bústia '%s'."
|
||||
|
||||
#: models.py:153
|
||||
#, python-format
|
||||
msgid "'%s' forwards to itself."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:175
|
||||
msgid "address"
|
||||
msgstr "direccio"
|
||||
|
||||
#: models.py:178
|
||||
msgid "subject"
|
||||
msgstr "subjecte"
|
||||
|
||||
#: models.py:179
|
||||
msgid "message"
|
||||
msgstr "missatge"
|
||||
|
||||
#: models.py:180
|
||||
msgid "enabled"
|
||||
msgstr "habilitat"
|
||||
|
||||
#: settings.py:25
|
||||
msgid "Limit for system user based mailbox on Linux is 32."
|
||||
msgstr "El límit per a la bústia basada en l'usuari del sistema a Linux és 32."
|
||||
|
||||
#: settings.py:98
|
||||
msgid "Disable"
|
||||
msgstr "deshabilitat"
|
||||
|
||||
#: settings.py:99
|
||||
msgid "Reject spam (Score≥8)"
|
||||
msgstr ""
|
||||
|
||||
#: settings.py:118
|
||||
msgid "Reject spam (Score≥5)"
|
||||
msgstr ""
|
||||
|
||||
#: settings.py:137
|
||||
msgid "Archive spam (Score≥8)"
|
||||
msgstr ""
|
||||
|
||||
#: settings.py:157
|
||||
msgid "Archive spam (Score≥5)"
|
||||
msgstr ""
|
||||
|
||||
#: validators.py:15
|
||||
#, python-format
|
||||
msgid "'%s' is not a correct email name."
|
||||
msgstr "'%s' no és un nom de correu electrònic correcte."
|
||||
|
||||
#: validators.py:33
|
||||
#, python-format
|
||||
msgid "'%s' is already present."
|
||||
msgstr "'%s' ja està present."
|
||||
|
||||
#: validators.py:41
|
||||
#, python-format
|
||||
msgid "'%s' is not a valid email address."
|
||||
msgstr "'%s' no és una adreça de correu electrònic vàlida."
|
||||
|
||||
#: validators.py:45
|
||||
#, python-format
|
||||
msgid "'%s' is not an existent mailbox."
|
||||
msgstr "'%s' no és una bústia existent."
|
Binary file not shown.
|
@ -1,305 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-09-06 09:35+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: admin.py:31
|
||||
msgid "autoresponse"
|
||||
msgstr "autorespuesta"
|
||||
|
||||
#: admin.py:52 admin.py:66 settings.py:177
|
||||
msgid "Custom filtering"
|
||||
msgstr "Filtro personalizado"
|
||||
|
||||
#: admin.py:54
|
||||
msgid ""
|
||||
"Please remember to select <tt>custom filtering</tt> if you want this filter "
|
||||
"to be applied."
|
||||
msgstr ""
|
||||
"Recuerde seleccionar <TT> Filtrado personalizado </tt> Si desea este "
|
||||
"filtroAplicar"
|
||||
|
||||
#: admin.py:58 admin.py:70 admin.py:114
|
||||
msgid "Addresses"
|
||||
msgstr "Direcciones de coreo"
|
||||
|
||||
#: admin.py:122
|
||||
msgid "Forward from"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:127
|
||||
msgid "Filtering"
|
||||
msgstr "Filtración"
|
||||
|
||||
#: admin.py:181
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Mailbox '%s' local address matches '%s', please consider if selecting it "
|
||||
"makes sense."
|
||||
msgstr ""
|
||||
"Mailbox '%s' coincidencia de dirección local '%s', considere si "
|
||||
"seleccionarloTiene sentido"
|
||||
|
||||
#: admin.py:199
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Address <a href='{url}'>{addr}</a> clashes with '{mailbox}' mailbox local "
|
||||
"address. Consider adding this mailbox to the address."
|
||||
msgstr ""
|
||||
"Dirección <a href='{url}'>{addr}</a> se enfrenta con '{mailbox}' buzón "
|
||||
"localDirección. Considere agregar este buzón a la dirección."
|
||||
|
||||
#: admin.py:210
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You have provided a custom filtering but filtering selected option is %s"
|
||||
msgstr ""
|
||||
"Ha proporcionado un filtrado personalizado, pero la opción de filtrado "
|
||||
"seleccionada es %s"
|
||||
|
||||
#: admin.py:246 admin.py:252
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:260
|
||||
msgid "Mailboxes"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:269
|
||||
msgid "Mailboxes links"
|
||||
msgstr ""
|
||||
|
||||
#: admin.py:282
|
||||
msgid "Forward"
|
||||
msgstr "Redirección"
|
||||
|
||||
#: admin.py:321
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Address '%s' matches mailbox '%s' local address, please consider if makes "
|
||||
"sense adding the mailbox on the mailboxes or forward field."
|
||||
msgstr ""
|
||||
"Dirección '%s' coincide con buzón '%s', considere si lo hacetiene sentido "
|
||||
"agregar el buzón en los buzones o el campo Reenviar"
|
||||
|
||||
#: backends.py:64
|
||||
msgid "UNIX maildir user"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:263
|
||||
msgid "Postfix address virtdomain-only"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:347
|
||||
msgid "Postfix address"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:434
|
||||
msgid "Mail autoresponse"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:445
|
||||
msgid "Dovecot Maildir size"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:502
|
||||
msgid "Postfix-Mailscanner traffic"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:672
|
||||
msgid "Roundcube Identity Controller"
|
||||
msgstr ""
|
||||
|
||||
#: backends.py:682
|
||||
msgid "rspamd ratelimit user"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:9
|
||||
msgid "has mailbox"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:14
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:15
|
||||
msgid "False"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:28
|
||||
msgid "has forward"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:41
|
||||
msgid "has address"
|
||||
msgstr ""
|
||||
|
||||
#: filters.py:53
|
||||
msgid "has type server"
|
||||
msgstr ""
|
||||
|
||||
#: forms.py:20 models.py:115
|
||||
msgid "addresses"
|
||||
msgstr "direcciones de correo"
|
||||
|
||||
#: forms.py:84
|
||||
msgid "Mailboxes or forward address should be provided."
|
||||
msgstr "Se deben proporcionar buzones o dirección de reenvío"
|
||||
|
||||
#: models.py:17 models.py:101
|
||||
msgid "name"
|
||||
msgstr "nombre"
|
||||
|
||||
#: models.py:19
|
||||
#, python-format
|
||||
msgid "Required. %s characters or fewer. Letters, digits and ./-/_ only."
|
||||
msgstr "Requerido. %s caracteres o menos. Letras, dígitos y ./-/_ solamente"
|
||||
|
||||
#: models.py:22
|
||||
msgid "Enter a valid mailbox name."
|
||||
msgstr "Ingrese un nombre de buzón válido"
|
||||
|
||||
#: models.py:24
|
||||
msgid "password"
|
||||
msgstr "contraseña"
|
||||
|
||||
#: models.py:25
|
||||
msgid "account"
|
||||
msgstr "cuenta"
|
||||
|
||||
#: models.py:30
|
||||
msgid "filtering"
|
||||
msgstr "filtro"
|
||||
|
||||
#: models.py:32
|
||||
msgid ""
|
||||
"Arbitrary email filtering in <a href='https://tty1.net/blog/2011/sieve-"
|
||||
"tutorial_en.html'>sieve language</a>. This overrides any automatic junk "
|
||||
"email filtering"
|
||||
msgstr ""
|
||||
"Filtrado de correo electrónico arbitrario en <a href='https://tty1.net/"
|
||||
"blog/2011/sieve-tutorial_en.html'>lenguaje de tamiz</a>. Esto anula "
|
||||
"cualquier basura automáticaFiltrado por correo electrónico"
|
||||
|
||||
#: models.py:35
|
||||
msgid "active"
|
||||
msgstr "activo"
|
||||
|
||||
#: models.py:36
|
||||
msgid "ratelimit"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:43 models.py:106
|
||||
msgid "mailboxes"
|
||||
msgstr "buzones"
|
||||
|
||||
#: models.py:76
|
||||
msgid "Custom filtering is selected but not provided."
|
||||
msgstr "El filtrado personalizado se selecciona pero no se proporciona"
|
||||
|
||||
#: models.py:103
|
||||
msgid "Address name, left blank for a <i>catch-all</i> address"
|
||||
msgstr ""
|
||||
"Nombre de la dirección, dejado en blanco para dirección <i>aleatoria</i>"
|
||||
|
||||
#: models.py:105
|
||||
msgid "domain"
|
||||
msgstr "dominio"
|
||||
|
||||
#: models.py:108
|
||||
msgid "forward"
|
||||
msgstr "redirección"
|
||||
|
||||
#: models.py:110
|
||||
msgid "Space separated email addresses or mailboxes"
|
||||
msgstr "Direcciones de correo electrónico o buzones separados por un espacio"
|
||||
|
||||
#: models.py:111
|
||||
msgid "Account"
|
||||
msgstr "Cuenta"
|
||||
|
||||
#: models.py:147
|
||||
#, python-format
|
||||
msgid "Please use mailboxes field for '%s' mailbox."
|
||||
msgstr "Utilice el campo de mailboxes para el buzón '%s'"
|
||||
|
||||
#: models.py:153
|
||||
#, python-format
|
||||
msgid "'%s' forwards to itself."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:175
|
||||
msgid "address"
|
||||
msgstr "dirección"
|
||||
|
||||
#: models.py:178
|
||||
msgid "subject"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:179
|
||||
msgid "message"
|
||||
msgstr "mensage"
|
||||
|
||||
#: models.py:180
|
||||
msgid "enabled"
|
||||
msgstr "habilitado"
|
||||
|
||||
#: settings.py:25
|
||||
msgid "Limit for system user based mailbox on Linux is 32."
|
||||
msgstr ""
|
||||
"El límite para el buzón basado en el usuario del sistema en Linux es 32."
|
||||
|
||||
#: settings.py:98
|
||||
msgid "Disable"
|
||||
msgstr "Deshabilitado"
|
||||
|
||||
#: settings.py:99
|
||||
msgid "Reject spam (Score≥8)"
|
||||
msgstr ""
|
||||
|
||||
#: settings.py:118
|
||||
msgid "Reject spam (Score≥5)"
|
||||
msgstr ""
|
||||
|
||||
#: settings.py:137
|
||||
msgid "Archive spam (Score≥8)"
|
||||
msgstr ""
|
||||
|
||||
#: settings.py:157
|
||||
msgid "Archive spam (Score≥5)"
|
||||
msgstr ""
|
||||
|
||||
#: validators.py:15
|
||||
#, python-format
|
||||
msgid "'%s' is not a correct email name."
|
||||
msgstr "'%s' no es un nombre de email correcto."
|
||||
|
||||
#: validators.py:33
|
||||
#, python-format
|
||||
msgid "'%s' is already present."
|
||||
msgstr ""
|
||||
|
||||
#: validators.py:41
|
||||
#, python-format
|
||||
msgid "'%s' is not a valid email address."
|
||||
msgstr "'%s' no es una dirección valida."
|
||||
|
||||
#: validators.py:45
|
||||
#, python-format
|
||||
msgid "'%s' is not an existent mailbox."
|
||||
msgstr "'%s' no es un mailbox existente."
|
|
@ -1,67 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2021-04-22 11:27
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.contrib.mailboxes.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('domains', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Address',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(blank=True, help_text='Address name, left blank for a <i>catch-all</i> address', max_length=64, validators=[orchestra.contrib.mailboxes.validators.validate_emailname], verbose_name='name')),
|
||||
('forward', models.CharField(blank=True, help_text='Space separated email addresses or mailboxes', max_length=256, validators=[orchestra.contrib.mailboxes.validators.validate_forward], verbose_name='forward')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='addresses', to=settings.AUTH_USER_MODEL, verbose_name='Account')),
|
||||
('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='addresses', to='domains.Domain', verbose_name='domain')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'addresses',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Autoresponse',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('subject', models.CharField(max_length=256, verbose_name='subject')),
|
||||
('message', models.TextField(verbose_name='message')),
|
||||
('enabled', models.BooleanField(default=False, verbose_name='enabled')),
|
||||
('address', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='autoresponse', to='mailboxes.Address', verbose_name='address')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Mailbox',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(db_index=True, help_text='Required. 32 characters or fewer. Letters, digits and ./-/_ only.', max_length=32, unique=True, validators=[django.core.validators.RegexValidator('^[\\w.-]+$', 'Enter a valid mailbox name.')], verbose_name='name')),
|
||||
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||
('filtering', models.CharField(choices=[('CUSTOM', 'Custom filtering'), ('DISABLE', 'Disable'), ('REDIRECT', 'Archive spam (Score≥8)'), ('REDIRECT5', 'Archive spam (Score≥5)'), ('REJECT', 'Reject spam (Score≥8)'), ('REJECT5', 'Reject spam (Score≥5)')], default='REDIRECT', max_length=16)),
|
||||
('custom_filtering', models.TextField(blank=True, help_text="Arbitrary email filtering in <a href='https://tty1.net/blog/2011/sieve-tutorial_en.html'>sieve language</a>. This overrides any automatic junk email filtering", validators=[orchestra.contrib.mailboxes.validators.validate_sieve], verbose_name='filtering')),
|
||||
('is_active', models.BooleanField(default=True, verbose_name='active')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mailboxes', to=settings.AUTH_USER_MODEL, verbose_name='account')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'mailboxes',
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='address',
|
||||
name='mailboxes',
|
||||
field=models.ManyToManyField(blank=True, related_name='addresses', to='mailboxes.Mailbox', verbose_name='mailboxes'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='address',
|
||||
unique_together=set([('name', 'domain')]),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 2.2.24 on 2024-07-11 12:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mailboxes', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='mailbox',
|
||||
name='ratelimit',
|
||||
field=models.CharField(blank=True, choices=[('userbase', 'base'), ('user100', '100'), ('user200', '200'), ('user500', '500')], default='userbase', max_length=100, null=True, verbose_name='ratelimit'),
|
||||
),
|
||||
]
|
|
@ -33,11 +33,6 @@ class Mailbox(models.Model):
|
|||
"<a href='https://tty1.net/blog/2011/sieve-tutorial_en.html'>sieve language</a>. "
|
||||
"This overrides any automatic junk email filtering"))
|
||||
is_active = models.BooleanField(_("active"), default=True)
|
||||
ratelimit = models.CharField(_("ratelimit"),
|
||||
max_length=100, null=True, blank=True,
|
||||
choices=settings.MAILBOXES_RATELIMIT_GROUP,
|
||||
default=settings.MAILBOXES_RATELIMIT_GROUP_DEFAULT,)
|
||||
|
||||
|
||||
class Meta:
|
||||
verbose_name_plural = _("mailboxes")
|
||||
|
|
|
@ -203,21 +203,3 @@ MAILBOXES_MOVE_ON_DELETE_PATH = Setting('MAILBOXES_MOVE_ON_DELETE_PATH',
|
|||
help_text="Available fromat names: <tt>%s</tt>" % ', '.join(_backend_names),
|
||||
validators=[Setting.string_format_validator(_backend_names)],
|
||||
)
|
||||
|
||||
MAILBOXES_RATELIMIT_GROUP = Setting('MAILBOXES_RATELIMIT_GROUP', (
|
||||
('userbase', 'base'),
|
||||
('user100', '100'),
|
||||
('user200', '200'),
|
||||
('user500', '500'),
|
||||
),
|
||||
help_text="Available messages per second"
|
||||
)
|
||||
|
||||
MAILBOXES_RATELIMIT_GROUP_DEFAULT = Setting('MAILBOXES_RATELIMIT_GROUP_DEFAULT',
|
||||
'userbase',
|
||||
choices=MAILBOXES_RATELIMIT_GROUP
|
||||
)
|
||||
|
||||
MAILBOXES_RATELIMIT_PATH_MAPS = Setting('MAILBOXES_RATELIMIT_PATH_MAPS',
|
||||
'/etc/rspamd/local.d/maps/',
|
||||
)
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2021-04-22 11:28
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Message',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('state', models.CharField(choices=[('QUEUED', 'Queued'), ('SENT', 'Sent'), ('DEFERRED', 'Deferred'), ('FAILED', 'Failes')], default='QUEUED', max_length=16, verbose_name='State')),
|
||||
('priority', models.PositiveIntegerField(choices=[(0, 'Critical (not queued)'), (1, 'High'), (2, 'Normal'), (3, 'Low')], default=2, verbose_name='Priority')),
|
||||
('to_address', models.CharField(max_length=256)),
|
||||
('from_address', models.CharField(max_length=256)),
|
||||
('subject', models.CharField(max_length=256, verbose_name='subject')),
|
||||
('content', models.TextField(verbose_name='content')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created at')),
|
||||
('retries', models.PositiveIntegerField(default=0, verbose_name='retries')),
|
||||
('last_retry', models.DateTimeField(auto_now=True, verbose_name='last try')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SMTPLog',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('result', models.CharField(choices=[('SUCCESS', 'Success'), ('FAILURE', 'Failure')], default='SUCCESS', max_length=16)),
|
||||
('date', models.DateTimeField(auto_now_add=True)),
|
||||
('log_message', models.TextField()),
|
||||
('message', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='logs', to='mailer.Message')),
|
||||
],
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='message',
|
||||
old_name='last_retry',
|
||||
new_name='last_try',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='last_try',
|
||||
field=models.DateTimeField(verbose_name='last try'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='subject',
|
||||
field=models.TextField(verbose_name='subject'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='last_try',
|
||||
field=models.DateTimeField(null=True, verbose_name='last try'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='state',
|
||||
field=models.CharField(choices=[('QUEUED', 'Queued'), ('SENT', 'Sent'), ('DEFERRED', 'Deferred'), ('FAILED', 'Failed')], default='QUEUED', max_length=16, verbose_name='State'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='last_try',
|
||||
field=models.DateTimeField(db_index=True, null=True, verbose_name='last try'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='priority',
|
||||
field=models.PositiveIntegerField(choices=[(0, 'Critical (not queued)'), (1, 'High'), (2, 'Normal'), (3, 'Low')], db_index=True, default=2, verbose_name='Priority'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='retries',
|
||||
field=models.PositiveIntegerField(db_index=True, default=0, verbose_name='retries'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='message',
|
||||
name='state',
|
||||
field=models.CharField(choices=[('QUEUED', 'Queued'), ('SENT', 'Sent'), ('DEFERRED', 'Deferred'), ('FAILED', 'Failed')], db_index=True, default='QUEUED', max_length=16, verbose_name='State'),
|
||||
),
|
||||
]
|
|
@ -1,14 +0,0 @@
|
|||
BBBBBBB BBBBBBBBBBBBBBBBBBBBBBBB
|
||||
BBBB BBBB BBBBBBBBBB BBBBBB BBBBBBBBBB
|
||||
|
||||
|
||||
BBBBB BBBBBBBBBBBBBBBBBB
|
||||
XXXX
|
||||
BBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB BB BBBBBBBBBBBBBBBB
|
||||
XX XXXXXXBBBBBBBBBBBBBBBBBBBBB BBBBBBBBBBBBBBBB BBBBBBBB BBBBBBBBX XXXXXXXXXXXXXXXXXXXX
|
||||
gettext(u'Send pending') SSSS SSSSSSS
|
||||
XXXX
|
||||
XXXXX
|
||||
|
||||
BBBBBBBB
|
||||
|
|
@ -1 +0,0 @@
|
|||
default_app_config = 'orchestra.contrib.apps.MetricsConfig'
|
|
@ -1,3 +0,0 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
|
@ -1,7 +0,0 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MetricsConfig(AppConfig):
|
||||
name = 'orchestra.contrib.metrics'
|
||||
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
from prometheus_client import start_http_server, Gauge
|
||||
import random
|
||||
|
||||
from orchestra.contrib.accounts.models import Account
|
||||
from orchestra.contrib.websites.models import Website
|
||||
from orchestra.contrib.databases.models import Database
|
||||
from orchestra.contrib.resources.models import ResourceData
|
||||
from orchestra.contrib.mailboxes.models import Mailbox
|
||||
from orchestra.contrib.lists.models import List
|
||||
from orchestra.contrib.saas.models import SaaS
|
||||
|
||||
|
||||
# Crear métricas de tipo Gauge con etiquetas
|
||||
usuarios_metrica = Gauge('usuarios', 'Número total de usuarios', ['tipo', 'estado'])
|
||||
websites_metrica = Gauge('websites_server', 'Número total de websites en server', ['target_server', 'estado'])
|
||||
databases_metrica = Gauge('databases', 'Número total de websites en server', ['target_server'])
|
||||
mailboxes_metrica = Gauge('mailbox', 'Número total de mailbox', ['estado'])
|
||||
lists_metrica = Gauge('lists', 'Número total de listas')
|
||||
saas_metrica = Gauge('saas', 'Número total de saas', ['service', 'estado'])
|
||||
|
||||
usuarios_top_size_metrica = Gauge('usuarios_top_size', 'Top 10 cuentas ocupan espacio', ['object'])
|
||||
databases_top_size_metrica = Gauge('databases_top_size', 'Top 10 databases ocupan espacio', ['object'])
|
||||
mailboxes_top_size_metrica = Gauge('mailboxes_top_size', 'Top 10 mailboxes ocupan espacio', ['object'])
|
||||
saas_top_size_metrica = Gauge('saas_top_size', 'Top 10 saas ocupan espacio', ['object'])
|
||||
|
||||
|
||||
def get_size_resourcedata(id_resource, metrica):
|
||||
top_resources = ResourceData.objects.filter(resource_id=id_resource, used__isnull=False).order_by('-used')[:10]
|
||||
for resourcedata in top_resources:
|
||||
metrica.labels(object=resourcedata.content_object_repr).set(resourcedata.used)
|
||||
|
||||
def get_data_objects_with_active(model, field_type):
|
||||
objects = model.objects.all()
|
||||
|
||||
object_dict = {}
|
||||
for obj in objects:
|
||||
key = getattr(obj, field_type)
|
||||
if key not in object_dict:
|
||||
object_dict[key] = {'activo':0, 'inactivo':0}
|
||||
if getattr(obj, 'is_active'):
|
||||
object_dict[key]['activo'] += 1
|
||||
else:
|
||||
object_dict[key]['inactivo'] += 1
|
||||
|
||||
return object_dict
|
||||
|
||||
|
||||
def actualizar_metrica_usuarios():
|
||||
get_size_resourcedata(4, usuarios_top_size_metrica)
|
||||
user_dict = get_data_objects_with_active(Account, 'type')
|
||||
|
||||
# envia metrica por cada tipo de usuario num de activos y inactivos
|
||||
for type, value in user_dict.items():
|
||||
usuarios_metrica.labels(tipo=type, estado='activo').set(value['activo'])
|
||||
usuarios_metrica.labels(tipo=type, estado='no_activo').set(value['inactivo'])
|
||||
|
||||
|
||||
def actualizar_metrica_websites():
|
||||
website_dict = get_data_objects_with_active(Website, 'target_server')
|
||||
for server, value in website_dict.items():
|
||||
websites_metrica.labels(target_server=server, estado='activo').set(value['activo'])
|
||||
websites_metrica.labels(target_server=server, estado='no_activo').set(value['inactivo'])
|
||||
|
||||
|
||||
def actualizar_metrica_databases():
|
||||
get_size_resourcedata(5, databases_top_size_metrica)
|
||||
databases = Database.objects.all()
|
||||
|
||||
data = {}
|
||||
for database in databases:
|
||||
if database.target_server.name not in data.keys():
|
||||
data[database.target_server.name] = {'total':0}
|
||||
data[database.target_server.name]['total'] += 1
|
||||
|
||||
for server, value in data.items():
|
||||
databases_metrica.labels(target_server=server).set(value['total'])
|
||||
|
||||
|
||||
def actualizar_metrica_mailboxes():
|
||||
get_size_resourcedata(1, mailboxes_top_size_metrica)
|
||||
mailboxes = Mailbox.objects.all()
|
||||
|
||||
mailbox_activos = sum(1 for mailbox in mailboxes if mailbox.is_active)
|
||||
mailbox_inactivos = len(mailboxes) - mailbox_activos
|
||||
|
||||
mailboxes_metrica.labels(estado='activo').set(mailbox_activos)
|
||||
mailboxes_metrica.labels(estado='no_activo').set(mailbox_inactivos)
|
||||
|
||||
|
||||
def actualizar_metrica_lists():
|
||||
lists = List.objects.all()
|
||||
lists_metrica.set(len(lists))
|
||||
|
||||
def actualizar_metrica_saas():
|
||||
get_size_resourcedata(23, saas_top_size_metrica)
|
||||
saas_dict = get_data_objects_with_active(SaaS, 'service')
|
||||
for servicio, value in saas_dict.items():
|
||||
saas_metrica.labels(service=servicio, estado='activo').set(value['activo'])
|
||||
saas_metrica.labels(service=servicio, estado='no_activo').set(value['inactivo'])
|
|
@ -1,3 +0,0 @@
|
|||
from django.db import models
|
||||
|
||||
# Create your models here.
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,27 +0,0 @@
|
|||
from django.shortcuts import render
|
||||
from django.http import HttpResponse
|
||||
from django.views.decorators.http import require_GET
|
||||
from prometheus_client.exposition import generate_latest
|
||||
from prometheus_client import REGISTRY, CONTENT_TYPE_LATEST
|
||||
from .custom_metrics import (
|
||||
actualizar_metrica_usuarios,
|
||||
actualizar_metrica_websites,
|
||||
actualizar_metrica_databases,
|
||||
actualizar_metrica_mailboxes,
|
||||
actualizar_metrica_lists,
|
||||
actualizar_metrica_saas,
|
||||
)
|
||||
|
||||
@require_GET
|
||||
def metrics_view(request):
|
||||
# Actualizar métricas antes de generar el contenido
|
||||
actualizar_metrica_usuarios()
|
||||
actualizar_metrica_websites()
|
||||
actualizar_metrica_databases()
|
||||
actualizar_metrica_mailboxes()
|
||||
actualizar_metrica_lists()
|
||||
actualizar_metrica_saas()
|
||||
|
||||
# Devolver las métricas exportadas como respuesta HTTP
|
||||
output = generate_latest(REGISTRY)
|
||||
return HttpResponse(output, content_type=CONTENT_TYPE_LATEST)
|
|
@ -1,56 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2021-04-22 11:28
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import orchestra.core.validators
|
||||
import orchestra.models.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0001_initial'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Miscellaneous',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('identifier', orchestra.models.fields.NullableCharField(help_text='A unique identifier for this service.', max_length=256, null=True, unique=True, verbose_name='identifier')),
|
||||
('description', models.TextField(blank=True, verbose_name='description')),
|
||||
('amount', models.PositiveIntegerField(default=1, verbose_name='amount')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Designates whether this service should be treated as active. Unselect this instead of deleting services.', verbose_name='active')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='miscellaneous', to=settings.AUTH_USER_MODEL, verbose_name='account')),
|
||||
],
|
||||
options={
|
||||
'verbose_name_plural': 'miscellaneous',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MiscService',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(help_text='Raw name used for internal referenciation, i.e. service match definition', max_length=32, unique=True, validators=[orchestra.core.validators.validate_name], verbose_name='name')),
|
||||
('verbose_name', models.CharField(blank=True, help_text='Human readable name', max_length=256, verbose_name='verbose name')),
|
||||
('description', models.TextField(blank=True, help_text='Optional description', verbose_name='description')),
|
||||
('has_identifier', models.BooleanField(default=True, help_text='Designates if this service has a <b>unique text</b> field that identifies it or not.', verbose_name='has identifier')),
|
||||
('has_amount', models.BooleanField(default=False, help_text='Designates whether this service has <tt>amount</tt> property or not.', verbose_name='has amount')),
|
||||
('is_active', models.BooleanField(default=True, help_text='Whether new instances of this service can be created or not. Unselect this instead of deleting services.', verbose_name='active')),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='miscellaneous',
|
||||
name='service',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='instances', to='miscellaneous.MiscService', verbose_name='service'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='miscellaneous',
|
||||
name='identifier',
|
||||
field=orchestra.models.fields.NullableCharField(db_index=True, help_text='A unique identifier for this service.', max_length=256, null=True, unique=True, verbose_name='identifier'),
|
||||
),
|
||||
]
|
|
@ -1,260 +0,0 @@
|
|||
import urllib.parse
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import authenticate, login
|
||||
from django.http import Http404
|
||||
from django.urls.exceptions import NoReverseMatch
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.domains.models import Domain
|
||||
from orchestra.contrib.mailboxes.models import Mailbox
|
||||
from orchestra.contrib.websites.models import Website
|
||||
|
||||
from .models import Address, DatabaseService, SaasService, UserAccount
|
||||
|
||||
DOMAINS_PATH = 'domains/'
|
||||
TOKEN_PATH = '/api-token-auth/'
|
||||
|
||||
API_PATHS = {
|
||||
# auth
|
||||
'token-auth': '/api-token-auth/',
|
||||
'my-account': 'accounts/',
|
||||
|
||||
# services
|
||||
'database-list': 'databases/',
|
||||
'domain-list': 'domains/',
|
||||
'domain-detail': 'domains/{pk}/',
|
||||
'address-list': 'addresses/',
|
||||
'address-detail': 'addresses/{pk}/',
|
||||
'mailbox-list': 'mailboxes/',
|
||||
'mailbox-detail': 'mailboxes/{pk}/',
|
||||
'mailbox-password': 'mailboxes/{pk}/set_password/',
|
||||
'mailinglist-list': 'lists/',
|
||||
'saas-list': 'saas/',
|
||||
'website-list': 'websites/',
|
||||
|
||||
# other
|
||||
'bill-list': 'bills/',
|
||||
'bill-document': 'bills/{pk}/document/',
|
||||
'payment-source-list': 'payment-sources/',
|
||||
}
|
||||
|
||||
|
||||
class Orchestra(object):
|
||||
def __init__(self, request, username=None, password=None, **kwargs):
|
||||
self.request = request
|
||||
self.username = username
|
||||
self.user = self.authenticate(self.username, password)
|
||||
|
||||
def authenticate(self, username, password):
|
||||
user = authenticate(self.request, username=username, password=password)
|
||||
|
||||
if user is not None:
|
||||
login(self.request, user)
|
||||
return user
|
||||
|
||||
# Return an 'invalid login' error message.
|
||||
return None
|
||||
|
||||
|
||||
class OrchestraConnector:
|
||||
def __init__(self, request):
|
||||
self._request = request
|
||||
self.user = request.user
|
||||
assert not self.user.is_anonymous
|
||||
|
||||
def build_absolute_uri(self, path_name):
|
||||
path = API_PATHS.get(path_name, None)
|
||||
if path is None:
|
||||
raise NoReverseMatch(
|
||||
"Not found API path name '{}'".format(path_name))
|
||||
|
||||
return urllib.parse.urljoin(self.base_url, path)
|
||||
|
||||
def request(self, verb, resource=None, url=None, data=None, render_as="json", querystring=None, raise_exception=True):
|
||||
assert verb in ["HEAD", "GET", "POST", "PATCH", "PUT", "DELETE"]
|
||||
if resource is not None:
|
||||
url = self.build_absolute_uri(resource)
|
||||
elif url is None:
|
||||
raise AttributeError("Provide `resource` or `url` params")
|
||||
|
||||
if querystring is not None:
|
||||
url = "{}?{}".format(url, querystring)
|
||||
|
||||
verb = getattr(self.session, verb.lower())
|
||||
headers = {
|
||||
"Authorization": "Token {}".format(self.auth_token),
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
response = verb(url, json=data, headers=headers, allow_redirects=False)
|
||||
|
||||
if raise_exception:
|
||||
response.raise_for_status()
|
||||
|
||||
status = response.status_code
|
||||
if status < 500 and render_as == "json":
|
||||
output = response.json()
|
||||
else:
|
||||
output = response.content
|
||||
|
||||
return status, output
|
||||
|
||||
def retrieve_service_list(self, model_class, querystring=None):
|
||||
qs = model_class.objects.filter(account=self.user)
|
||||
|
||||
# TODO filter by querystring
|
||||
|
||||
return qs
|
||||
|
||||
# pattern_name = '{}-list'.format(service_name)
|
||||
# if pattern_name not in API_PATHS:
|
||||
# raise ValueError("Unknown service {}".format(service_name))
|
||||
# _, output = self.request("GET", pattern_name, querystring=querystring)
|
||||
# return output
|
||||
|
||||
def retrieve_profile(self):
|
||||
if self.user.is_anonymous:
|
||||
raise PermissionError("Cannot retrieve profile of an anonymous user.")
|
||||
|
||||
return self.user # return UserAccount.new_from_json(output[0])
|
||||
|
||||
def retrieve_bill_document(self, pk):
|
||||
path = API_PATHS.get('bill-document').format_map({'pk': pk})
|
||||
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
status, bill_pdf = self.request("GET", render_as="html", url=url, raise_exception=False)
|
||||
if status == 404:
|
||||
raise Http404(_("No domain found matching the query"))
|
||||
return bill_pdf
|
||||
|
||||
def create_mail_address(self, data):
|
||||
resource = '{}-list'.format(Address.api_name)
|
||||
return self.request("POST", resource=resource, data=data)
|
||||
|
||||
def retrieve_mail_address(self, pk):
|
||||
path = API_PATHS.get('address-detail').format_map({'pk': pk})
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
status, data = self.request("GET", url=url, raise_exception=False)
|
||||
if status == 404:
|
||||
raise Http404(_("No object found matching the query"))
|
||||
|
||||
return Address.new_from_json(data)
|
||||
|
||||
def update_mail_address(self, pk, data):
|
||||
path = API_PATHS.get('address-detail').format_map({'pk': pk})
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
return self.request("PUT", url=url, data=data)
|
||||
|
||||
def retrieve_mail_address_list(self, querystring=None):
|
||||
# retrieve mails applying filters (if any)
|
||||
raw_data = self.retrieve_service_list(
|
||||
Address.api_name,
|
||||
querystring=querystring,
|
||||
)
|
||||
|
||||
addresses = [Address.new_from_json(data) for data in raw_data]
|
||||
|
||||
# PATCH to include Pangea addresses not shown by orchestra
|
||||
# described on issue #4
|
||||
# TODO(@slamora) disabled hacky patch because breaks another funtionalities
|
||||
# XXX Fix it on orchestra instead of here???
|
||||
# raw_mailboxes = self.retrieve_mailbox_list()
|
||||
# for mailbox in raw_mailboxes:
|
||||
# if mailbox['addresses'] == []:
|
||||
# address_data = {
|
||||
# 'names': [mailbox['name']],
|
||||
# 'forward': '',
|
||||
# 'domain': {
|
||||
# 'name': 'pangea.org.',
|
||||
# },
|
||||
# 'mailboxes': [mailbox],
|
||||
# }
|
||||
# pangea_address = Address.new_from_json(address_data)
|
||||
# addresses.append(pangea_address)
|
||||
|
||||
return addresses
|
||||
|
||||
def delete_mail_address(self, pk):
|
||||
path = API_PATHS.get('address-detail').format_map({'pk': pk})
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
return self.request("DELETE", url=url, render_as=None)
|
||||
|
||||
def create_mailbox(self, data):
|
||||
resource = '{}-list'.format(Mailbox.api_name)
|
||||
return self.request("POST", resource=resource, data=data, raise_exception=False)
|
||||
|
||||
def retrieve_mailbox(self, pk):
|
||||
path = API_PATHS.get('mailbox-detail').format_map({'pk': pk})
|
||||
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
status, data_json = self.request("GET", url=url, raise_exception=False)
|
||||
if status == 404:
|
||||
raise Http404(_("No mailbox found matching the query"))
|
||||
return Mailbox.new_from_json(data_json)
|
||||
|
||||
def update_mailbox(self, pk, data):
|
||||
path = API_PATHS.get('mailbox-detail').format_map({'pk': pk})
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
status, response = self.request("PATCH", url=url, data=data, raise_exception=False)
|
||||
return status, response
|
||||
|
||||
def retrieve_mailbox_list(self):
|
||||
qs = self.retrieve_service_list(Mailbox)
|
||||
return qs
|
||||
|
||||
def delete_mailbox(self, pk):
|
||||
path = API_PATHS.get('mailbox-detail').format_map({'pk': pk})
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
# Mark as inactive instead of deleting
|
||||
# return self.request("DELETE", url=url, render_as=None)
|
||||
return self.request("PATCH", url=url, data={"is_active": False})
|
||||
|
||||
def set_password_mailbox(self, pk, data):
|
||||
path = API_PATHS.get('mailbox-password').format_map({'pk': pk})
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
status, response = self.request("POST", url=url, data=data, raise_exception=False)
|
||||
return status, response
|
||||
|
||||
|
||||
def retrieve_domain(self, pk):
|
||||
|
||||
path = API_PATHS.get('domain-detail').format_map({'pk': pk})
|
||||
|
||||
url = urllib.parse.urljoin(self.base_url, path)
|
||||
status, domain_json = self.request("GET", url=url, raise_exception=False)
|
||||
if status == 404:
|
||||
raise Http404(_("No domain found matching the query"))
|
||||
return Domain.new_from_json(domain_json)
|
||||
|
||||
def retrieve_domain_list(self):
|
||||
domains = self.retrieve_service_list(Domain)
|
||||
domains = domains.prefetch_related("addresses", "websites")
|
||||
|
||||
# TODO(@slamora): update when backend provides resource disk usage data
|
||||
# initialize domain usage for every domain
|
||||
# for domain in domains:
|
||||
# domain.usage = {
|
||||
# 'usage': 300,
|
||||
# 'total': 650,
|
||||
# 'unit': 'MB',
|
||||
# 'percent': 50,
|
||||
# }
|
||||
|
||||
return domains
|
||||
|
||||
def retrieve_website_list(self):
|
||||
qs = self.retrieve_service_list(Website)
|
||||
return qs
|
||||
|
||||
def verify_credentials(self):
|
||||
"""
|
||||
Returns:
|
||||
A user profile info if the
|
||||
credentials are valid, None otherwise.
|
||||
"""
|
||||
status, output = self.request("GET", 'my-account', raise_exception=False)
|
||||
|
||||
if status < 400:
|
||||
return output
|
||||
|
||||
return None
|
|
@ -1,5 +0,0 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MusicianConfig(AppConfig):
|
||||
name = 'orchestra.contrib.musician'
|
|
@ -1,38 +0,0 @@
|
|||
from django.middleware.csrf import rotate_token
|
||||
from django.utils.crypto import constant_time_compare
|
||||
|
||||
SESSION_KEY_TOKEN = '_auth_token'
|
||||
SESSION_KEY_USERNAME = '_auth_username'
|
||||
|
||||
|
||||
def login(request, username, token):
|
||||
"""
|
||||
Persist a user id and a backend in the request. This way a user doesn't
|
||||
have to reauthenticate on every request. Note that data set during
|
||||
the anonymous session is retained when the user logs in.
|
||||
"""
|
||||
if SESSION_KEY_TOKEN in request.session:
|
||||
if request.session[SESSION_KEY_USERNAME] != username:
|
||||
# To avoid reusing another user's session, create a new, empty
|
||||
# session if the existing session corresponds to a different
|
||||
# authenticated user.
|
||||
request.session.flush()
|
||||
else:
|
||||
request.session.cycle_key()
|
||||
|
||||
request.session[SESSION_KEY_TOKEN] = token
|
||||
request.session[SESSION_KEY_USERNAME] = username
|
||||
# if hasattr(request, 'user'):
|
||||
# request.user = user
|
||||
rotate_token(request)
|
||||
|
||||
|
||||
def logout(request):
|
||||
"""
|
||||
Remove the authenticated user's ID from the request and flush their session
|
||||
data.
|
||||
"""
|
||||
request.session.flush()
|
||||
# if hasattr(request, 'user'):
|
||||
# from django.contrib.auth.models import AnonymousUser
|
||||
# request.user = AnonymousUser()
|
|
@ -1,204 +0,0 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from django.contrib.auth.hashers import make_password
|
||||
|
||||
from orchestra.contrib.domains.models import Domain, Record
|
||||
from orchestra.contrib.mailboxes.models import Address, Mailbox
|
||||
from orchestra.contrib.systemusers.models import WebappUsers, SystemUser
|
||||
from orchestra.contrib.musician.validators import ValidateZoneMixin
|
||||
|
||||
from . import api
|
||||
|
||||
|
||||
class LoginForm(AuthenticationForm):
|
||||
|
||||
def clean(self):
|
||||
username = self.cleaned_data.get('username')
|
||||
password = self.cleaned_data.get('password')
|
||||
|
||||
if username is not None and password:
|
||||
orchestra = api.Orchestra(self.request, username=username, password=password)
|
||||
|
||||
if orchestra.user is None:
|
||||
raise self.get_invalid_login_error()
|
||||
else:
|
||||
self.username = username
|
||||
self.user = orchestra.user
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
class ChangePasswordForm(forms.ModelForm):
|
||||
error_messages = {
|
||||
'password_mismatch': _('The two password fields didn’t match.'),
|
||||
}
|
||||
password = forms.CharField(
|
||||
label=_("Password"),
|
||||
strip=False,
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
|
||||
)
|
||||
password2 = forms.CharField(
|
||||
label=_("Password confirmation"),
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
|
||||
strip=False,
|
||||
help_text=_("Enter the same password as before, for verification."),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
fields = ("password",)
|
||||
model = WebappUsers
|
||||
|
||||
def clean_password2(self):
|
||||
password = self.cleaned_data.get("password")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
if password and password2 and password != password2:
|
||||
raise ValidationError(
|
||||
self.error_messages['password_mismatch'],
|
||||
code='password_mismatch',
|
||||
)
|
||||
return password2
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
password = cleaned_data.get("password")
|
||||
cleaned_data['password'] = make_password(password)
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class MailForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Address
|
||||
fields = ("name", "domain", "mailboxes", "forward")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.user = kwargs.pop('user')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['domain'].queryset = Domain.objects.filter(account=self.user)
|
||||
self.fields['mailboxes'].queryset = Mailbox.objects.filter(account=self.user)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
if not cleaned_data.get('mailboxes') and not cleaned_data.get('forward'):
|
||||
raise ValidationError("A mailbox or forward address should be provided.")
|
||||
return cleaned_data
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super().save(commit=False)
|
||||
instance.account = self.user
|
||||
if commit:
|
||||
super().save(commit=True)
|
||||
return instance
|
||||
|
||||
|
||||
class MailboxChangePasswordForm(ChangePasswordForm):
|
||||
|
||||
class Meta:
|
||||
fields = ("password",)
|
||||
model = Mailbox
|
||||
|
||||
|
||||
class MailboxCreateForm(forms.ModelForm):
|
||||
error_messages = {
|
||||
'password_mismatch': _('The two password fields didn’t match.'),
|
||||
}
|
||||
name = forms.CharField()
|
||||
password = forms.CharField(
|
||||
label=_("Password"),
|
||||
strip=False,
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
|
||||
)
|
||||
password2 = forms.CharField(
|
||||
label=_("Password confirmation"),
|
||||
widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}),
|
||||
strip=False,
|
||||
help_text=_("Enter the same password as before, for verification."),
|
||||
)
|
||||
addresses = forms.ModelMultipleChoiceField(queryset=Address.objects.none(), required=False)
|
||||
|
||||
class Meta:
|
||||
fields = ("name", "password", "password2", "addresses")
|
||||
model = Mailbox
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
user = kwargs.pop('user')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['addresses'].queryset = Address.objects.filter(account=user)
|
||||
self.user = user
|
||||
|
||||
def clean_password2(self):
|
||||
password = self.cleaned_data.get("password")
|
||||
password2 = self.cleaned_data.get("password2")
|
||||
if password and password2 and password != password2:
|
||||
raise ValidationError(
|
||||
self.error_messages['password_mismatch'],
|
||||
code='password_mismatch',
|
||||
)
|
||||
return password
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
password = cleaned_data.get("password")
|
||||
cleaned_data['password'] = make_password(password)
|
||||
return cleaned_data
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super().save(commit=False)
|
||||
instance.account = self.user
|
||||
if commit:
|
||||
super().save(commit=True)
|
||||
return instance
|
||||
|
||||
|
||||
class MailboxUpdateForm(forms.ModelForm):
|
||||
addresses = forms.MultipleChoiceField(required=False)
|
||||
|
||||
class Meta:
|
||||
fields = ('addresses',)
|
||||
model = Mailbox
|
||||
|
||||
|
||||
class MailboxSearchForm(forms.Form):
|
||||
name = forms.CharField(required=False)
|
||||
address = forms.CharField(required=False)
|
||||
|
||||
class RecordCreateForm(ValidateZoneMixin, forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Record
|
||||
fields = ("ttl", "type", "value")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.domain = kwargs.pop('domain')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super().save(commit=False)
|
||||
instance.domain = self.domain
|
||||
if commit:
|
||||
super().save(commit=True)
|
||||
return instance
|
||||
|
||||
|
||||
class RecordUpdateForm(ValidateZoneMixin, forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Record
|
||||
fields = ("ttl", "type", "value")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.domain = self.instance.domain
|
||||
|
||||
|
||||
class WebappUsersChangePasswordForm(ChangePasswordForm):
|
||||
class Meta:
|
||||
fields = ("password",)
|
||||
model = WebappUsers
|
||||
|
||||
class SystemUsersChangePasswordForm(ChangePasswordForm):
|
||||
class Meta:
|
||||
fields = ("password",)
|
||||
model = SystemUser
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
from django import forms
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from orchestra.contrib.lists.models import List
|
||||
from orchestra.contrib.domains.models import Domain
|
||||
|
||||
class MailingUpdateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = List
|
||||
fields = ("is_active", "name", "address_name", "address_domain")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.user = kwargs.pop('user')
|
||||
super().__init__(*args, **kwargs)
|
||||
qs = Domain.objects.filter(account=self.user)
|
||||
self.fields['address_domain'].queryset = qs
|
||||
self.fields['address_name'].help_text = _("Additional address besides the default <name>@grups.pangea.org")
|
||||
self.fields['name'].widget.attrs['readonly'] = True
|
||||
|
||||
|
||||
class MailingCreateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = List
|
||||
fields = ("name", "address_name", "address_domain", "admin_email")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.user = kwargs.pop('user')
|
||||
super().__init__(*args, **kwargs)
|
||||
qs = Domain.objects.filter(account=self.user)
|
||||
self.fields['address_domain'].queryset = qs
|
||||
self.fields['address_name'].help_text = _("Additional address besides the default <name>@grups.pangea.org")
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super().save(commit=False)
|
||||
instance.account = self.user
|
||||
if commit:
|
||||
super().save(commit=True)
|
||||
return instance
|
|
@ -1,80 +0,0 @@
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
from django.views.generic.list import ListView
|
||||
from orchestra.contrib.musician.mixins import (CustomContextMixin, ExtendedPaginationMixin,
|
||||
UserTokenRequiredMixin)
|
||||
from django.views.generic.edit import (CreateView, DeleteView, FormView,
|
||||
UpdateView)
|
||||
|
||||
from orchestra.contrib.lists.models import List
|
||||
from orchestra.contrib.domains.models import Domain, Record
|
||||
from orchestra.contrib.lists.settings import LISTS_DEFAULT_DOMAIN
|
||||
|
||||
from .forms import MailingUpdateForm, MailingCreateForm
|
||||
|
||||
class MailingListsView(CustomContextMixin, UserTokenRequiredMixin, ListView):
|
||||
model = List
|
||||
template_name = "musician/mailinglist_list.html"
|
||||
extra_context = {
|
||||
# Translators: This message appears on the page title
|
||||
'title': _('Mailing lists'),
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
return self.model.objects.filter(account=self.request.user)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
domain_id = self.request.GET.get('domain')
|
||||
if domain_id:
|
||||
qs = Domain.objects.filter(account=self.request.user)
|
||||
context.update({
|
||||
'active_domain': get_object_or_404(qs, pk=domain_id),
|
||||
})
|
||||
context.update({'default_domain': LISTS_DEFAULT_DOMAIN})
|
||||
return context
|
||||
|
||||
def get_queryfilter(self):
|
||||
"""Retrieve query params (if any) to filter queryset"""
|
||||
domain_id = self.request.GET.get('domain')
|
||||
if domain_id:
|
||||
return {"address_domain_id": domain_id}
|
||||
return {}
|
||||
|
||||
class MailingUpdateView(CustomContextMixin, UserTokenRequiredMixin, UpdateView):
|
||||
model = List
|
||||
form_class = MailingUpdateForm
|
||||
template_name = "musician/mailinglist_form.html"
|
||||
|
||||
def get_queryset(self):
|
||||
qs = List.objects.filter(account=self.request.user)
|
||||
return qs
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy("musician:mailing-lists")
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs["user"] = self.request.user
|
||||
return kwargs
|
||||
|
||||
class MailingCreateView(CustomContextMixin, UserTokenRequiredMixin, CreateView):
|
||||
model = List
|
||||
form_class = MailingCreateForm
|
||||
template_name = "musician/mailinglist_form.html"
|
||||
success_url = reverse_lazy("musician:mailing-lists")
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['user'] = self.request.user
|
||||
return kwargs
|
||||
|
||||
class MailingDeleteView(CustomContextMixin, UserTokenRequiredMixin, DeleteView):
|
||||
template_name = "musician/mailing_check_delete.html"
|
||||
model = List
|
||||
success_url = reverse_lazy("musician:mailing-lists")
|
||||
|
||||
def get_queryset(self):
|
||||
return self.model.objects.filter(account=self.request.user)
|
Binary file not shown.
|
@ -1,978 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-06 09:39+0000\n"
|
||||
"PO-Revision-Date: 2021-11-25 12:53+0100\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: ca\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.0\n"
|
||||
|
||||
#: api.py:127 api.py:226
|
||||
msgid "No domain found matching the query"
|
||||
msgstr "No trobem cap domini que coincideixi amb la teva consulta"
|
||||
|
||||
#: api.py:139
|
||||
msgid "No object found matching the query"
|
||||
msgstr "No trobem cap objecte que coincideixi amb la teva consulta"
|
||||
|
||||
#: api.py:192
|
||||
msgid "No mailbox found matching the query"
|
||||
msgstr "No trobem cap bústia que coincideixi amb la teva consulta"
|
||||
|
||||
#: forms.py:35 forms.py:104
|
||||
msgid "The two password fields didn’t match."
|
||||
msgstr "Les contrasenyes introduïdes no coincideixen."
|
||||
|
||||
#: forms.py:38 forms.py:108
|
||||
msgid "Password"
|
||||
msgstr "Contrasenya"
|
||||
|
||||
#: forms.py:43 forms.py:113
|
||||
msgid "Password confirmation"
|
||||
msgstr "Confirma la contrasenya"
|
||||
|
||||
#: forms.py:46 forms.py:116
|
||||
msgid "Enter the same password as before, for verification."
|
||||
msgstr "Introdueix la mateixa contrasenya per verificar-la."
|
||||
|
||||
#: lists/forms.py:17 lists/forms.py:31
|
||||
msgid "Additional address besides the default <name>@grups.pangea.org"
|
||||
msgstr "Adreça addicional a més de la predeterminada <name>@grups.pangea.org"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: lists/views.py:22 mixins.py:20
|
||||
msgid "Mailing lists"
|
||||
msgstr "Llistes de correu"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:17 views.py:68
|
||||
msgid "Dashboard"
|
||||
msgstr "Panell de gestió"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:18 templates/musician/dashboard.html:89
|
||||
#: templates/musician/dashboard.html:90 views.py:202
|
||||
msgid "Domains"
|
||||
msgstr "Dominis"
|
||||
|
||||
#: mixins.py:19
|
||||
msgid "Mails"
|
||||
msgstr "Correus"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:21 models.py:146 views.py:542
|
||||
msgid "Databases"
|
||||
msgstr "Bases de dades"
|
||||
|
||||
msgid "Database"
|
||||
msgstr "Bases de dades"
|
||||
|
||||
#: mixins.py:22
|
||||
msgid "SaaS"
|
||||
msgstr "SaaS"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:23 websites/views.py:24
|
||||
msgid "Websites"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:24 webapps/views.py:25
|
||||
msgid "Webapps"
|
||||
msgstr ""
|
||||
|
||||
#: mixins.py:25
|
||||
msgid "Users"
|
||||
msgstr "Usuaris"
|
||||
|
||||
#: models.py:147
|
||||
msgid "Description details for databases page."
|
||||
msgstr "Consulta la configuració de les teves bases de dades."
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: models.py:234 views.py:342
|
||||
msgid "Mail addresses"
|
||||
msgstr "Adreces de correu"
|
||||
|
||||
#: models.py:235
|
||||
msgid "Description details for mail addresses page."
|
||||
msgstr "Consulta aquí totes les adreces de correu que tens actives."
|
||||
|
||||
#: models.py:310
|
||||
msgid "Mailbox"
|
||||
msgstr "Bústia de correu"
|
||||
|
||||
#: models.py:311
|
||||
msgid "Description details for mailbox page."
|
||||
msgstr "Aquí trobaràs el detall de les bústies de correu que tens actives."
|
||||
|
||||
#: models.py:336
|
||||
msgid "Mailing list"
|
||||
msgstr "Llista de correu"
|
||||
|
||||
#: models.py:337
|
||||
msgid "Description details for mailinglist page."
|
||||
msgstr "Consulta aquí els detalls de les teves llistes de correu."
|
||||
|
||||
#: models.py:363
|
||||
msgid "Software as a Service (SaaS)"
|
||||
msgstr "Software as a Service (SaaS)"
|
||||
|
||||
#: models.py:364
|
||||
msgid "Description details for SaaS page."
|
||||
msgstr ""
|
||||
"Si tens algun servei SaaS (Software as a Service) contractat, aquí trobaràs "
|
||||
"els seus detalls de configuració."
|
||||
|
||||
#: templates/auth/login.html:59
|
||||
msgid "Log in"
|
||||
msgstr "Accedeix"
|
||||
|
||||
#: templates/auth/login.html:67
|
||||
msgid "Forgot your password? Click here to recover"
|
||||
msgstr "Has oblidat la teva contrasenya? Fes click aquí per recuperar-la"
|
||||
|
||||
#: templates/auth/login.html:77
|
||||
msgid "Forgot your password?"
|
||||
msgstr "Has oblidat la teva contrasenya?"
|
||||
|
||||
#: templates/auth/login.html:83
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Send an email to <a href=\"mailto:%(support_email)s\">%(support_email)s</a> "
|
||||
"including your username and we will provide instructions."
|
||||
msgstr ""
|
||||
"Envia un correu a <a href=\"mailto:%(support_email)s\">%(support_email)s</a> "
|
||||
"indicant el teu nom d’usuari/a i t’explicarem què fer."
|
||||
|
||||
#: templates/musician/address_check_delete.html:7
|
||||
#, python-format
|
||||
msgid "Are you sure that you want remove the address: \"%(address_name)s\"?"
|
||||
msgstr ""
|
||||
"Estàs segur/a que vols esborrar l’adreça de correu: \"%(address_name)s\"?"
|
||||
|
||||
#: templates/musician/address_check_delete.html:8
|
||||
#: templates/musician/mailbox_check_delete.html:11
|
||||
#: templates/musician/mailing_check_delete.html:8
|
||||
#: templates/musician/record_check_delete.html:9
|
||||
#: templates/musician/webapps/webappoption_check_delete.html:9
|
||||
#: templates/musician/websites/websiteoption_check_delete.html:13
|
||||
msgid "WARNING: This action cannot be undone."
|
||||
msgstr "AVÍS: Aquesta acció es irreversible."
|
||||
|
||||
#: templates/musician/address_check_delete.html:9
|
||||
#: templates/musician/address_form.html:11
|
||||
#: templates/musician/mailbox_change_password.html:11
|
||||
#: templates/musician/mailbox_check_delete.html:13
|
||||
#: templates/musician/mailbox_form.html:20
|
||||
#: templates/musician/mailing_check_delete.html:9
|
||||
#: templates/musician/mailinglist_form.html:30
|
||||
#: templates/musician/record_check_delete.html:11
|
||||
#: templates/musician/record_form.html:16
|
||||
#: templates/musician/systemuser_change_password.html:11
|
||||
#: templates/musician/webapps/webapp_form.html:11
|
||||
#: templates/musician/webapps/webapp_option_form.html:18
|
||||
#: templates/musician/webapps/webappoption_check_delete.html:11
|
||||
#: templates/musician/webapps/webappuser_change_password.html:11
|
||||
#: templates/musician/websites/website_create_option_form.html:17
|
||||
#: templates/musician/websites/website_form.html:26
|
||||
#: templates/musician/websites/websiteoption_check_delete.html:15
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·lar"
|
||||
|
||||
#: templates/musician/address_check_delete.html:10
|
||||
#: templates/musician/address_form.html:15
|
||||
#: templates/musician/mailbox_check_delete.html:12
|
||||
#: templates/musician/mailbox_form.html:25
|
||||
#: templates/musician/mailing_check_delete.html:10
|
||||
#: templates/musician/mailinglist_form.html:34
|
||||
#: templates/musician/record_check_delete.html:10
|
||||
#: templates/musician/record_form.html:20
|
||||
#: templates/musician/webapps/webapp_form.html:15
|
||||
#: templates/musician/webapps/webappoption_check_delete.html:10
|
||||
#: templates/musician/websites/websiteoption_check_delete.html:14
|
||||
msgid "Delete"
|
||||
msgstr "Esborrar"
|
||||
|
||||
#: templates/musician/address_form.html:12
|
||||
#: templates/musician/mailbox_change_password.html:12
|
||||
#: templates/musician/mailbox_form.html:21
|
||||
#: templates/musician/mailinglist_form.html:31
|
||||
#: templates/musician/record_form.html:17
|
||||
#: templates/musician/systemuser_change_password.html:12
|
||||
#: templates/musician/webapps/webapp_form.html:12
|
||||
#: templates/musician/webapps/webapp_option_form.html:19
|
||||
#: templates/musician/webapps/webappuser_change_password.html:12
|
||||
#: templates/musician/websites/website_create_option_form.html:18
|
||||
#: templates/musician/websites/website_form.html:27
|
||||
msgid "Save"
|
||||
msgstr "Desar"
|
||||
|
||||
#: templates/musician/address_list.html:7
|
||||
#, fuzzy
|
||||
#| msgid "Filtering"
|
||||
msgid "Filter by domain"
|
||||
msgstr "Filtrat"
|
||||
|
||||
#: templates/musician/address_list.html:10
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: templates/musician/address_list.html:25
|
||||
msgid "Email"
|
||||
msgstr "Correu electrònic"
|
||||
|
||||
#: templates/musician/address_list.html:26
|
||||
msgid "Domain"
|
||||
msgstr "Domini"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: templates/musician/address_list.html:27 templates/musician/mail_base.html:22
|
||||
#: views.py:428
|
||||
msgid "Mailboxes"
|
||||
msgstr "Bústies de correu"
|
||||
|
||||
#: templates/musician/address_list.html:28
|
||||
msgid "Forward"
|
||||
msgstr "Redirecció"
|
||||
|
||||
#: templates/musician/address_list.html:49
|
||||
msgid "New mail address"
|
||||
msgstr "Nova adreça de correu"
|
||||
|
||||
#: templates/musician/base.html:67
|
||||
msgid "Settings"
|
||||
msgstr "Configuració"
|
||||
|
||||
#: templates/musician/base.html:70 templates/musician/profile.html:6
|
||||
msgid "Profile"
|
||||
msgstr "Perfil"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: templates/musician/base.html:71 templates/musician/billing.html:6
|
||||
#: views.py:300
|
||||
msgid "Billing"
|
||||
msgstr "Factures"
|
||||
|
||||
#: templates/musician/base.html:86
|
||||
msgid "Log out"
|
||||
msgstr "Surt"
|
||||
|
||||
#: templates/musician/base.html:97
|
||||
msgid "Language"
|
||||
msgstr "Idioma"
|
||||
|
||||
#: templates/musician/billing.html:7
|
||||
msgid "Billing page description."
|
||||
msgstr "Consulta i descarrega les teves factures."
|
||||
|
||||
#: templates/musician/billing.html:19
|
||||
msgid "Number"
|
||||
msgstr "Número"
|
||||
|
||||
#: templates/musician/billing.html:20
|
||||
msgid "Bill date"
|
||||
msgstr "Data de la factura"
|
||||
|
||||
#: templates/musician/billing.html:21 templates/musician/database_list.html:22
|
||||
#: templates/musician/domain_detail.html:38
|
||||
#: templates/musician/webapps/webapp_detail.html:94
|
||||
#: templates/musician/webapps/webapp_list.html:26
|
||||
msgid "Type"
|
||||
msgstr "Tipus"
|
||||
|
||||
#: templates/musician/billing.html:22
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
|
||||
#: templates/musician/billing.html:23
|
||||
msgid "Download PDF"
|
||||
msgstr "Descarrega el PDF"
|
||||
|
||||
#: templates/musician/dashboard.html:6
|
||||
msgid "Welcome back"
|
||||
msgstr "Hola de nou!"
|
||||
|
||||
#: templates/musician/dashboard.html:8
|
||||
#, python-format
|
||||
msgid "Last time you logged in was: %(last_login)s"
|
||||
msgstr "El darrer cop que vas accedir va ser el dia: %(last_login)s"
|
||||
|
||||
#: templates/musician/dashboard.html:10
|
||||
msgid "It's the first time you log into the system, welcome on board!"
|
||||
msgstr "És el primer cop que accedeixes, et donem la benvinguda!"
|
||||
|
||||
#: templates/musician/dashboard.html:14
|
||||
msgid " The disk space of resources is updated weekly "
|
||||
msgstr "L'espai en disc dels recursos es va actualitzant setmanalment."
|
||||
|
||||
#: templates/musician/dashboard.html:47
|
||||
msgid "Show history"
|
||||
msgstr "Mostrar historial"
|
||||
|
||||
#: templates/musician/database_list.html:21
|
||||
#: templates/musician/mailbox_list.html:30 templates/musician/saas_list.html:19
|
||||
#: templates/musician/webapps/webapp_list.html:25
|
||||
#: templates/musician/websites/website_detail.html:77
|
||||
#: templates/musician/websites/website_list.html:20
|
||||
#: templates/musician/mailinglist_list.html:24
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: templates/musician/database_list.html:23
|
||||
msgid "Database users"
|
||||
msgstr "Usuaris Base de dades"
|
||||
|
||||
#: templates/musician/database_list.html:24
|
||||
#: templates/musician/domain_list.html:59
|
||||
msgid "Disk usage"
|
||||
msgstr "Ús del disc"
|
||||
|
||||
#: templates/musician/database_list.html:33
|
||||
#: templates/musician/database_list.html:35
|
||||
msgid "Open database manager"
|
||||
msgstr "Obre el gestor de bases de dades"
|
||||
|
||||
#. Translators: database page when there isn't any database.
|
||||
#. Translators: saas page when there isn't any saas.
|
||||
#: templates/musician/database_list.html:58
|
||||
#: templates/musician/saas_list.html:53
|
||||
msgid "Ooops! Looks like there is nothing here!"
|
||||
msgstr "Mmmh, sembla que aquí no hi ha res!"
|
||||
|
||||
#: templates/musician/domain_detail.html:5
|
||||
#: templates/musician/mailinglist_form.html:16
|
||||
#: templates/musician/record_form.html:5
|
||||
#: templates/musician/webapps/webapp_detail.html:5
|
||||
#: templates/musician/webapps/webapp_option_form.html:7
|
||||
#: templates/musician/websites/website_create_option_form.html:7
|
||||
#: templates/musician/websites/website_detail.html:5
|
||||
#: templates/musician/websites/website_form.html:16
|
||||
msgid "Go back"
|
||||
msgstr "Tornar"
|
||||
|
||||
#: templates/musician/domain_detail.html:8
|
||||
msgid "DNS settings for"
|
||||
msgstr "Configuració DNS per a"
|
||||
|
||||
#: templates/musician/domain_detail.html:16
|
||||
msgid "Go to top level domain"
|
||||
msgstr "Anar al domini de nivell superior"
|
||||
|
||||
#: templates/musician/domain_detail.html:20
|
||||
msgid "DNS settings page description."
|
||||
msgstr "Consulta aquí la teva configuració DNS."
|
||||
|
||||
#: templates/musician/domain_detail.html:24
|
||||
msgid ""
|
||||
"\n"
|
||||
" <h5 class=\"alert-heading\">IMPORTANT NOTICE!!!</h5>\n"
|
||||
" DNS records control the functioning of your domain, and therefore your "
|
||||
"websites, email addresses, mailing lists, etc.<br>\n"
|
||||
" If you do not have the necessary knowledge about this topic, do not "
|
||||
"make changes in this section. It is dangerous!\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <h5 class=\"alert-heading\">AVÍS IMPORTANT!!!</h5>\n"
|
||||
"Els registres DNS controlen el funcionament del teu domini, i per tant dels "
|
||||
"llocs web, adreces de correu electrònic, llistes de correu, etc.<br>\n"
|
||||
"Si no tens els coneixements necessaris sobre aquest tema, no facis canvis en "
|
||||
"aquesta secció. És perillós!\n"
|
||||
" "
|
||||
|
||||
#: templates/musician/domain_detail.html:39
|
||||
#: templates/musician/webapps/webapp_detail.html:95
|
||||
#: templates/musician/websites/website_detail.html:78
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#: templates/musician/domain_detail.html:57
|
||||
msgid "Add new record"
|
||||
msgstr "Afegir registre DNS"
|
||||
|
||||
#: templates/musician/domain_detail.html:60
|
||||
msgid "Subdomains"
|
||||
msgstr "SubDominis"
|
||||
|
||||
#: templates/musician/domain_detail.html:65
|
||||
msgid "Any related subdomain."
|
||||
msgstr "Qualsevol subdomini relacionat."
|
||||
|
||||
#: templates/musician/domain_list.html:7
|
||||
msgid "Your domains"
|
||||
msgstr "Els teus dominis i llocs web"
|
||||
|
||||
#: templates/musician/domain_list.html:20
|
||||
#: templates/musician/domain_list.html:105
|
||||
msgid "View DNS records"
|
||||
msgstr "Veure registres DNS"
|
||||
|
||||
#: templates/musician/domain_list.html:24
|
||||
msgid "view configuration"
|
||||
msgstr "veure la configuració"
|
||||
|
||||
#: templates/musician/domain_list.html:31
|
||||
msgid "Expiration date"
|
||||
msgstr "Data de venciment"
|
||||
|
||||
#: templates/musician/domain_list.html:38
|
||||
msgid "Mail"
|
||||
msgstr "Correu"
|
||||
|
||||
#: templates/musician/domain_list.html:41
|
||||
msgid "mail addresses created"
|
||||
msgstr "adreces de correu creades"
|
||||
|
||||
#: templates/musician/domain_list.html:46
|
||||
msgid "Mail list"
|
||||
msgstr "Llista de correu"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: templates/musician/domain_list.html:51 views.py:565
|
||||
msgid "Software as a Service"
|
||||
msgstr "Software as a Service"
|
||||
|
||||
#: templates/musician/domain_list.html:53
|
||||
msgid "Nothing installed"
|
||||
msgstr "No tens res instal·lat"
|
||||
|
||||
#: templates/musician/domain_list.html:77
|
||||
msgid "Configuration details"
|
||||
msgstr "Detalls de configuració"
|
||||
|
||||
#: templates/musician/domain_list.html:84
|
||||
msgid "FTP access:"
|
||||
msgstr "Accés FTP:"
|
||||
|
||||
#: templates/musician/domain_list.html:87
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "Send an email to <a href=\"mailto:%(support_email)s\">%(support_email)s</"
|
||||
#| "a> including your username and we will provide instructions."
|
||||
msgid ""
|
||||
"E-mail us at %(support_email_anchor)s to get details concerning FTP access."
|
||||
msgstr ""
|
||||
"Envia un correu a <a href=\"mailto:%(support_email)s\">%(support_email)s</a> "
|
||||
"indicant el teu nom d’usuari/a i t’explicarem què fer."
|
||||
|
||||
#: templates/musician/domain_list.html:97
|
||||
msgid "No website configured."
|
||||
msgstr "No hi ha cap web configurada."
|
||||
|
||||
#: templates/musician/domain_list.html:99
|
||||
msgid "Root directory:"
|
||||
msgstr "Directori arrel:"
|
||||
|
||||
#: templates/musician/domain_list.html:100
|
||||
msgid "Type:"
|
||||
msgstr "Tipus:"
|
||||
|
||||
#: templates/musician/mail_base.html:6
|
||||
#: templates/musician/mailinglist_list.html:6
|
||||
#: templates/musician/users_base.html:6
|
||||
msgid "Go to global"
|
||||
msgstr "Totes les adreces"
|
||||
|
||||
#: templates/musician/mail_base.html:10
|
||||
#: templates/musician/mailinglist_list.html:9
|
||||
#: templates/musician/users_base.html:10
|
||||
msgid "for"
|
||||
msgstr "per a"
|
||||
|
||||
#: templates/musician/mail_base.html:18 templates/musician/mailbox_list.html:32
|
||||
msgid "Addresses"
|
||||
msgstr "Adreces de correu"
|
||||
|
||||
#: templates/musician/mailbox_change_password.html:5
|
||||
#: templates/musician/mailbox_form.html:24
|
||||
#: templates/musician/systemuser_change_password.html:5
|
||||
#: templates/musician/webapps/webappuser_change_password.html:5
|
||||
msgid "Change password"
|
||||
msgstr "Canvia la contrasenya"
|
||||
|
||||
#: templates/musician/mailbox_check_delete.html:7
|
||||
msgid "Are you sure that you want remove the mailbox:"
|
||||
msgstr "Estàs segur/a que vols esborrar la bústia de correu:"
|
||||
|
||||
#: templates/musician/mailbox_check_delete.html:9
|
||||
msgid ""
|
||||
"All mailbox's messages will be <strong>deleted and cannot be recovered</"
|
||||
"strong>."
|
||||
msgstr ""
|
||||
"Tots els missatges <strong>s'esborraran i no es podran recuperar</strong>."
|
||||
|
||||
#: templates/musician/mailbox_form.html:9
|
||||
msgid "Warning!"
|
||||
msgstr "Atenció!"
|
||||
|
||||
#: templates/musician/mailbox_form.html:9
|
||||
msgid ""
|
||||
"You have reached the limit of mailboxes of your subscription so "
|
||||
"<strong>extra fees</strong> may apply."
|
||||
msgstr ""
|
||||
"Has assolit el límit de bústies de correu de la teva subscripció, les noves "
|
||||
"bústies poden implicar <strong>costos addicionals</strong>."
|
||||
|
||||
#: templates/musician/mailbox_form.html:10
|
||||
msgid "Close"
|
||||
msgstr "Tancar"
|
||||
|
||||
#: templates/musician/mailbox_list.html:31
|
||||
msgid "Filtering"
|
||||
msgstr "Filtrat"
|
||||
|
||||
#: templates/musician/mailbox_list.html:43
|
||||
#: templates/musician/systemuser_list.html:32
|
||||
#: templates/musician/webapps/webapp_detail.html:33
|
||||
#: templates/musician/webapps/webapp_detail.html:41
|
||||
#: templates/musician/webapps/webappuser_list.html:30
|
||||
#: templates/musician/websites/website_list.html:86
|
||||
#: templates/musician/websites/website_list.html:93
|
||||
msgid "Update password"
|
||||
msgstr "Actualitza la contrasenya"
|
||||
|
||||
#: templates/musician/mailbox_list.html:60
|
||||
msgid "New mailbox"
|
||||
msgstr "Nova bústia de correu"
|
||||
|
||||
#: templates/musician/mailing_check_delete.html:7
|
||||
msgid "Are you sure that you want remove the list:"
|
||||
msgstr "Estàs segur/a que vols esborrar la següent llista:"
|
||||
|
||||
#: templates/musician/mailinglist_form.html:20
|
||||
msgid "Update list"
|
||||
msgstr "Actualitzar llista"
|
||||
|
||||
#: templates/musician/mailinglist_form.html:22
|
||||
msgid "Create list"
|
||||
msgstr "Crear llista"
|
||||
|
||||
#: templates/musician/websites/website_list.html:23
|
||||
#: templates/musician/saas_list.html:20
|
||||
#: templates/musician/mailinglist_list.html:25
|
||||
msgid "Status"
|
||||
msgstr "Estat"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:26
|
||||
msgid "Address"
|
||||
msgstr "Direcció de correu"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:27
|
||||
msgid "Admin email"
|
||||
msgstr "Administrador"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:28
|
||||
msgid "Configure"
|
||||
msgstr "Configura"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:37
|
||||
msgid "Active"
|
||||
msgstr "Actiu"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:39
|
||||
msgid "Inactive"
|
||||
msgstr "Inactiu"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:61
|
||||
msgid "New list"
|
||||
msgstr "Nova llista"
|
||||
|
||||
#: templates/musician/profile.html:7
|
||||
msgid "Little description on profile page."
|
||||
msgstr "Canvia les teves dades d’accés i opcions de perfil des d’aquí."
|
||||
|
||||
#: templates/musician/profile.html:11
|
||||
msgid "User information"
|
||||
msgstr "Informació d’usuari/a"
|
||||
|
||||
#: templates/musician/profile.html:21
|
||||
msgid "Preferred language:"
|
||||
msgstr "Llenguatge preferit:"
|
||||
|
||||
#: templates/musician/profile.html:35
|
||||
msgid "Billing information"
|
||||
msgstr "Informació de facturació"
|
||||
|
||||
#: templates/musician/profile.html:49
|
||||
msgid "payment method:"
|
||||
msgstr "mètode de pagament:"
|
||||
|
||||
#: templates/musician/profile.html:60
|
||||
msgid "Check your last bills"
|
||||
msgstr "Consulta les teves darreres factures"
|
||||
|
||||
#: templates/musician/record_check_delete.html:7
|
||||
msgid "Are you sure that you want remove the following record?"
|
||||
msgstr "Estàs segur/a que vols esborrar el següent registre?"
|
||||
|
||||
#: templates/musician/record_form.html:8
|
||||
msgid "Update record of"
|
||||
msgstr "Actualitza la contrasenya a"
|
||||
|
||||
#: templates/musician/record_form.html:8
|
||||
msgid "Add record to"
|
||||
msgstr "Afegir registre a"
|
||||
|
||||
#: templates/musician/saas_list.html:21
|
||||
msgid "Service"
|
||||
msgstr "Servei"
|
||||
|
||||
#: templates/musician/saas_list.html:22
|
||||
msgid "Service info"
|
||||
msgstr "Informació del servei"
|
||||
|
||||
#: templates/musician/saas_list.html:30
|
||||
msgid "Installed on"
|
||||
msgstr "Instal·lat a"
|
||||
|
||||
#: templates/musician/saas_list.html:37 templates/musician/saas_list.html:39
|
||||
msgid "Open service admin panel"
|
||||
msgstr "Obre el panell d’administració del servei"
|
||||
|
||||
#: templates/musician/systemuser_list.html:6
|
||||
msgid ""
|
||||
"The main user is your system's main user on each server. You'll be able to "
|
||||
"view the logs of your websites at (/home/account/logs) and all web content, "
|
||||
"but you'll never be able to edit content on a website."
|
||||
msgstr ""
|
||||
"L'usuari principal existeix en cada servidor web. Podrà veure els registres "
|
||||
"dels seus llocs web a (/home/account/logs) i tot el contingut web (/home/account/webapps/*), "
|
||||
"però mai podrà editar el contingut en un lloc web."
|
||||
|
||||
#: templates/musician/systemuser_list.html:7
|
||||
msgid "This user only has write permissions in their own directory."
|
||||
msgstr "Aquest usuari només té permisos d'escriptura en el seu propi directori."
|
||||
|
||||
#: templates/musician/systemuser_list.html:18
|
||||
#: templates/musician/webapps/webappuser_list.html:15
|
||||
msgid "Username"
|
||||
msgstr "Nom d’usuari/a"
|
||||
|
||||
#: templates/musician/systemuser_list.html:19
|
||||
#: templates/musician/webapps/webappuser_list.html:16
|
||||
#: templates/musician/websites/website_detail.html:49
|
||||
msgid "Path"
|
||||
msgstr "Ruta"
|
||||
|
||||
#: templates/musician/users_base.html:18
|
||||
msgid "Main User"
|
||||
msgstr "Usuari Principal"
|
||||
|
||||
#: templates/musician/users_base.html:22
|
||||
msgid "SFTP Users"
|
||||
msgstr "Usuaris SFTP"
|
||||
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:72
|
||||
msgid ""
|
||||
"\n"
|
||||
" Initial database and App admin password. <br>\n"
|
||||
" Subsequent changes to the admin password will not be reflected.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Contrasenya inicial de la base de dades i de l'administrador de l'aplicació. <br>"
|
||||
"Els canvis posteriors a la contrasenya de l'administrador no es reflectiran.\n"
|
||||
" "
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:7
|
||||
msgid "WebApp Options for"
|
||||
msgstr "Opcions WebApp per"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:58
|
||||
msgid "Database:"
|
||||
msgstr "Bases de dades"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:62
|
||||
msgid "User Database:"
|
||||
msgstr "Usuari DB"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:66
|
||||
msgid "Password:"
|
||||
msgstr "Contrasenya"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:80
|
||||
msgid "PHP settings"
|
||||
msgstr "Configuració PHP"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:85
|
||||
msgid "PHP settings page description."
|
||||
msgstr "Consulta aquí la teva configuració DNS."
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:117
|
||||
msgid "This WebApp has PHP options by default, create one if you need it."
|
||||
msgstr "Aquesta WebApp té les opcions PHP per defecte; crea'n una nova si la necessites."
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:119
|
||||
msgid "Add new option"
|
||||
msgstr "Afegir nova Opcio"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:27
|
||||
msgid "SFTP user"
|
||||
msgstr "Usuari SFTP"
|
||||
|
||||
#: templates/musician/webapps/webapp_list.html:27
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
|
||||
#: templates/musician/webapps/webapp_list.html:28
|
||||
msgid "SFTP User"
|
||||
msgstr "Usuari SFTP"
|
||||
|
||||
#: templates/musician/webapps/webapp_list.html:29
|
||||
#: templates/musician/webapps/webappuser_list.html:17
|
||||
#: templates/musician/websites/website_list.html:22
|
||||
msgid "Server"
|
||||
msgstr "Servidor"
|
||||
|
||||
#: templates/musician/webapps/webapp_option_form.html:10
|
||||
msgid "Update Option of"
|
||||
msgstr "Actualitza Opcions per"
|
||||
|
||||
#: templates/musician/webapps/webapp_option_form.html:10
|
||||
#: templates/musician/websites/website_create_option_form.html:10
|
||||
msgid "Add Option to"
|
||||
msgstr "Afegir Opcio a"
|
||||
|
||||
#: templates/musician/webapps/webappoption_check_delete.html:7
|
||||
#: templates/musician/websites/websiteoption_check_delete.html:7
|
||||
msgid "Are you sure that you want remove the following option?"
|
||||
msgstr "Estàs segur/a que vols esborrar la següent opció?"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:7
|
||||
msgid "WebSite Options for"
|
||||
msgstr "Opcions de WebSite per"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:37
|
||||
msgid "Edit options"
|
||||
msgstr "Editar opcions"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:40
|
||||
msgid "Contents"
|
||||
msgstr "Contingut"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:43
|
||||
msgid "Webapps assigned to this website"
|
||||
msgstr "WebApps assignades en aquest WebSite"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:47
|
||||
msgid "Webapp"
|
||||
msgstr ""
|
||||
|
||||
#: templates/musician/websites/website_detail.html:48
|
||||
msgid "Type "
|
||||
msgstr "Tipus"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:67
|
||||
msgid "Assigned new Webapp"
|
||||
msgstr "Afegir nova directiva WebApp"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:70
|
||||
#, fuzzy
|
||||
#| msgid "Active"
|
||||
msgid "Directives"
|
||||
msgstr "Actiu"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:73
|
||||
msgid "Options assigned to this Website"
|
||||
msgstr "Opcions assignades en aquest WebSite"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:95
|
||||
msgid "Add new directive"
|
||||
msgstr "Afegir nova directiva"
|
||||
|
||||
#: templates/musician/websites/website_form.html:19
|
||||
msgid "Update Option of Website"
|
||||
msgstr "Actualitzar Opció de WebSite"
|
||||
|
||||
#: templates/musician/websites/website_list.html:21
|
||||
msgid "Url"
|
||||
msgstr ""
|
||||
|
||||
#: validators.py:28
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s: Hosts can not have underscore character '_', consider providing a SRV, "
|
||||
"CNAME or TXT record."
|
||||
msgstr ""
|
||||
"%s: Els hosts no poden tenir el caràcter d'èmfasi '_'. Considera proporcionar un registre SRV, CNAME o TXT."
|
||||
|
||||
#: views.py:200 views.py:202 views.py:229
|
||||
msgid "available"
|
||||
msgstr "disponibles"
|
||||
|
||||
#: views.py:182
|
||||
msgid "Account"
|
||||
msgstr "Compte"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:227
|
||||
msgid "User profile"
|
||||
msgstr "El teu perfil"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:314
|
||||
msgid "Download bill"
|
||||
msgstr "Descarrega la factura"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:573
|
||||
msgid "Domain details"
|
||||
msgstr "Detalls del domini"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:629
|
||||
msgid "Login"
|
||||
msgstr "Accés"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:700
|
||||
msgid "Webapp users"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:718
|
||||
msgid "Main users"
|
||||
msgstr ""
|
||||
|
||||
#: webapps/forms.py:62
|
||||
msgid "This option already exist."
|
||||
msgstr "Aquesta opcio ja existeix"
|
||||
|
||||
#: webapps/views.py:34
|
||||
msgid ""
|
||||
"A web app is the directory where your website is stored. Through SFTP, you "
|
||||
"can access this directory and upload/edit/delete files."
|
||||
msgstr ""
|
||||
"Una WebApp és el directori on es desa el teu WebSite. "
|
||||
"A través de SFTP, pots accedir a aquest directori i pujar, editar o eliminar fitxers."
|
||||
|
||||
#: webapps/views.py:35
|
||||
msgid ""
|
||||
"Each Webapp has its own SFTP user, which is created automatically when the "
|
||||
"Webapp is created."
|
||||
msgstr ""
|
||||
"Cada WebApp té el seu propi usuari SFTP, que es crea automàticament quan es crea l'aplicació web."
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: webapps/views.py:44
|
||||
#, fuzzy
|
||||
#| msgid "Type details"
|
||||
msgid "webapp details"
|
||||
msgstr "Detalls de cada tipus"
|
||||
|
||||
#: websites/forms.py:21
|
||||
msgid ""
|
||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr ""
|
||||
"Mantén premuda la tecla 'Control' o 'Comando' en un Mac per seleccionar més d'un."
|
||||
|
||||
#: websites/forms.py:54
|
||||
msgid "This Path already exists on this Website."
|
||||
msgstr "Aquesta ruta ja existeix en aquest"
|
||||
|
||||
#: websites/views.py:33
|
||||
msgid ""
|
||||
"A website is the place where a domain is associated with the directory where "
|
||||
"the web files are located. (WebApp)"
|
||||
msgstr ""
|
||||
"Un WebSite és el lloc on es relaciona un domini amb el directori on es troben els fitxers web. (Aplicació web)"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: websites/views.py:42
|
||||
#, fuzzy
|
||||
#| msgid "Type details"
|
||||
msgid "website details"
|
||||
msgstr "Detalls de cada tipus"
|
||||
|
||||
#, fuzzy
|
||||
#~| msgid "Change password"
|
||||
#~ msgid "Change password for"
|
||||
#~ msgstr "Canvia la contrasenya"
|
||||
|
||||
#~ msgid "Domains & websites"
|
||||
#~ msgstr "Dominis i llocs web"
|
||||
|
||||
#~ msgid "Previous"
|
||||
#~ msgstr "Prèvia"
|
||||
|
||||
#~ msgid "Next"
|
||||
#~ msgstr "Següent"
|
||||
|
||||
#~ msgid "Notifications"
|
||||
#~ msgstr "Notificacions"
|
||||
|
||||
#~ msgid "There is no notifications at this time."
|
||||
#~ msgstr "No tens cap notificació."
|
||||
|
||||
#~ msgid "Dashboard page description."
|
||||
#~ msgstr ""
|
||||
#~ "Aquest és el teu panell de gestió, des d’on podràs consultar la "
|
||||
#~ "configuració dels serveis que Pangea t’ofereix."
|
||||
|
||||
#~ msgid "associated to"
|
||||
#~ msgstr "associada a"
|
||||
|
||||
#~ msgid "No users for this database."
|
||||
#~ msgstr "No hi ha persones usuàries d’aquesta base de dades."
|
||||
|
||||
#~ msgid "active"
|
||||
#~ msgstr "actiu"
|
||||
|
||||
#~ msgid "Traffic"
|
||||
#~ msgstr "Tràfic"
|
||||
|
||||
#~ msgid "Mailbox usage"
|
||||
#~ msgstr "Ús d’espai a la bústia de correu"
|
||||
|
||||
#~ msgid "Address deleted!"
|
||||
#~ msgstr "S’ha suprimit l’adreça de correu"
|
||||
|
||||
#~ msgid "Cannot process your request, please try again later."
|
||||
#~ msgstr ""
|
||||
#~ "Ara no podem processar la teva petició, torna a intentar-ho una mica més "
|
||||
#~ "tard sisplau"
|
||||
|
||||
#~ msgid "Mailbox deleted!"
|
||||
#~ msgstr "S’ha suprimit la bústia de correu"
|
||||
|
||||
#~ msgid "Contact with the support team to get details concerning FTP access."
|
||||
#~ msgstr ""
|
||||
#~ "Escriu-nos a <a href=“mailto:%(support_email)s”>%(support_email)s</a> per "
|
||||
#~ "saber com accedir al FTP."
|
||||
|
||||
#~ msgid "Password updated!"
|
||||
#~ msgstr "S’ha actualitzat la contrasenya"
|
||||
|
||||
#~ msgid "mail address left"
|
||||
#~ msgstr "adreces de correu per activar"
|
||||
|
||||
#~ msgid "Aliases"
|
||||
#~ msgstr "Àlies"
|
||||
|
||||
#~ msgid "databases created"
|
||||
#~ msgstr "bases de dades creades"
|
||||
|
||||
msgid "size"
|
||||
msgstr "tamany"
|
||||
|
||||
msgid "traffic"
|
||||
msgstr "tránsit"
|
||||
|
||||
msgid "Mailman list traffic"
|
||||
msgstr "Llistes de Mailman"
|
||||
|
||||
msgid "Mailman list Traffic"
|
||||
msgstr "Llistes de Mailman"
|
Binary file not shown.
|
@ -1,991 +0,0 @@
|
|||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-09-12 10:10+0000\n"
|
||||
"PO-Revision-Date: 2021-11-25 12:53+0100\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.0\n"
|
||||
|
||||
#: api.py:127 api.py:226
|
||||
msgid "No domain found matching the query"
|
||||
msgstr "No hay dominios que coincidan con tu búsqueda"
|
||||
|
||||
#: api.py:139
|
||||
msgid "No object found matching the query"
|
||||
msgstr "No hay objetos que coincidan con tu búsqueda"
|
||||
|
||||
#: api.py:192
|
||||
msgid "No mailbox found matching the query"
|
||||
msgstr "No hay buzones de correo que coincidan con tu búsqueda"
|
||||
|
||||
#: forms.py:35 forms.py:104
|
||||
msgid "The two password fields didn’t match."
|
||||
msgstr "Las contraseñas introducidas no coinciden."
|
||||
|
||||
#: forms.py:38 forms.py:108
|
||||
msgid "Password"
|
||||
msgstr "Contraseña"
|
||||
|
||||
#: forms.py:43 forms.py:113
|
||||
msgid "Password confirmation"
|
||||
msgstr "Confirma la contraseña"
|
||||
|
||||
#: forms.py:46 forms.py:116
|
||||
msgid "Enter the same password as before, for verification."
|
||||
msgstr "Introduce la misma contraseña para verificarla"
|
||||
|
||||
#: lists/forms.py:17 lists/forms.py:31
|
||||
msgid "Additional address besides the default <name>@grups.pangea.org"
|
||||
msgstr ""
|
||||
"Dirección adicional además de la predeterminada <name>@grups.pangea.org"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: lists/views.py:22 mixins.py:20
|
||||
msgid "Mailing lists"
|
||||
msgstr "Listas de correo"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:17 views.py:119
|
||||
msgid "Dashboard"
|
||||
msgstr "Panel de gestión"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:18 templates/musician/dashboard.html:101
|
||||
#: templates/musician/dashboard.html:102
|
||||
#: templates/musician/websites/website_detail.html:17 views.py:252
|
||||
msgid "Domains"
|
||||
msgstr "Dominios"
|
||||
|
||||
#: mixins.py:19
|
||||
msgid "Mails"
|
||||
msgstr "Correos"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:21 models.py:146 views.py:592
|
||||
msgid "Databases"
|
||||
msgstr "Bases de datos"
|
||||
|
||||
#: mixins.py:22
|
||||
msgid "SaaS"
|
||||
msgstr "SaaS"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:23 websites/views.py:24
|
||||
msgid "Websites"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: mixins.py:24 webapps/views.py:25
|
||||
msgid "Webapps"
|
||||
msgstr ""
|
||||
|
||||
#: mixins.py:25
|
||||
msgid "Users"
|
||||
msgstr "Usuarios"
|
||||
|
||||
#: models.py:147
|
||||
msgid "Description details for databases page."
|
||||
msgstr "Consulta la configuración de tus bases de datos."
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: models.py:234 views.py:392
|
||||
msgid "Mail addresses"
|
||||
msgstr "Direcciones de correo"
|
||||
|
||||
#: models.py:235
|
||||
msgid "Description details for mail addresses page."
|
||||
msgstr "Consulta aquí todas las direcciones de correo que tienes activas."
|
||||
|
||||
#: models.py:310
|
||||
msgid "Mailbox"
|
||||
msgstr "Buzón de correo"
|
||||
|
||||
#: models.py:311
|
||||
msgid "Description details for mailbox page."
|
||||
msgstr ""
|
||||
"Aquí encontrarás tus buzones de correo y sus detalles de configuración."
|
||||
|
||||
#: models.py:336
|
||||
msgid "Mailing list"
|
||||
msgstr "Lista de correo"
|
||||
|
||||
#: models.py:337
|
||||
msgid "Description details for mailinglist page."
|
||||
msgstr "Consulta aquí los detalles de tus listas de correo."
|
||||
|
||||
#: models.py:363
|
||||
msgid "Software as a Service (SaaS)"
|
||||
msgstr "Software as a Service (SaaS)"
|
||||
|
||||
#: models.py:364
|
||||
msgid "Description details for SaaS page."
|
||||
msgstr ""
|
||||
"Si tienes algún servicio SaaS (Software as a Service) contratado, aquí "
|
||||
"encontrarás sus detalles de configuración."
|
||||
|
||||
#: templates/auth/login.html:59
|
||||
msgid "Log in"
|
||||
msgstr "Accede"
|
||||
|
||||
#: templates/auth/login.html:67
|
||||
msgid "Forgot your password? Click here to recover"
|
||||
msgstr "¿Olvidaste tu contraseña? Haz clic aquí para recuperarla"
|
||||
|
||||
#: templates/auth/login.html:77
|
||||
msgid "Forgot your password?"
|
||||
msgstr "¿Olvidaste tu contraseña?"
|
||||
|
||||
#: templates/auth/login.html:83
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Send an email to <a href=\"mailto:%(support_email)s\">%(support_email)s</a> "
|
||||
"including your username and we will provide instructions."
|
||||
msgstr ""
|
||||
"Envía un correo a <a href=“mailto:%(support_email)s”>%(support_email)s</a> "
|
||||
"indicando tu nombre de usuaria/o y te explicaremos qué hacer."
|
||||
|
||||
#: templates/musician/address_check_delete.html:7
|
||||
#, python-format
|
||||
msgid "Are you sure that you want remove the address: \"%(address_name)s\"?"
|
||||
msgstr ""
|
||||
"¿Estás seguro/a de que quieres borrar la dirección de correo "
|
||||
"\"%(address_name)s\"?"
|
||||
|
||||
#: templates/musician/address_check_delete.html:8
|
||||
#: templates/musician/mailbox_check_delete.html:11
|
||||
#: templates/musician/mailing_check_delete.html:8
|
||||
#: templates/musician/record_check_delete.html:9
|
||||
#: templates/musician/webapps/webappoption_check_delete.html:9
|
||||
#: templates/musician/websites/websiteoption_check_delete.html:13
|
||||
msgid "WARNING: This action cannot be undone."
|
||||
msgstr "AVISO: Esta acción es irreversible."
|
||||
|
||||
#: templates/musician/address_check_delete.html:9
|
||||
#: templates/musician/address_form.html:11
|
||||
#: templates/musician/mailbox_change_password.html:11
|
||||
#: templates/musician/mailbox_check_delete.html:13
|
||||
#: templates/musician/mailbox_form.html:20
|
||||
#: templates/musician/mailing_check_delete.html:9
|
||||
#: templates/musician/mailinglist_form.html:30
|
||||
#: templates/musician/record_check_delete.html:11
|
||||
#: templates/musician/record_form.html:16
|
||||
#: templates/musician/systemuser_change_password.html:11
|
||||
#: templates/musician/webapps/webapp_form.html:11
|
||||
#: templates/musician/webapps/webapp_option_form.html:18
|
||||
#: templates/musician/webapps/webappoption_check_delete.html:11
|
||||
#: templates/musician/webapps/webappuser_change_password.html:11
|
||||
#: templates/musician/websites/website_create_option_form.html:17
|
||||
#: templates/musician/websites/website_form.html:26
|
||||
#: templates/musician/websites/websiteoption_check_delete.html:15
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#: templates/musician/address_check_delete.html:10
|
||||
#: templates/musician/address_form.html:15
|
||||
#: templates/musician/mailbox_check_delete.html:12
|
||||
#: templates/musician/mailbox_form.html:25
|
||||
#: templates/musician/mailing_check_delete.html:10
|
||||
#: templates/musician/mailinglist_form.html:34
|
||||
#: templates/musician/record_check_delete.html:10
|
||||
#: templates/musician/record_form.html:20
|
||||
#: templates/musician/webapps/webapp_form.html:15
|
||||
#: templates/musician/webapps/webappoption_check_delete.html:10
|
||||
#: templates/musician/websites/websiteoption_check_delete.html:14
|
||||
msgid "Delete"
|
||||
msgstr "Borrar"
|
||||
|
||||
#: templates/musician/address_form.html:12
|
||||
#: templates/musician/mailbox_change_password.html:12
|
||||
#: templates/musician/mailbox_form.html:21
|
||||
#: templates/musician/mailinglist_form.html:31
|
||||
#: templates/musician/record_form.html:17
|
||||
#: templates/musician/systemuser_change_password.html:12
|
||||
#: templates/musician/webapps/webapp_form.html:12
|
||||
#: templates/musician/webapps/webapp_option_form.html:19
|
||||
#: templates/musician/webapps/webappuser_change_password.html:12
|
||||
#: templates/musician/websites/website_create_option_form.html:18
|
||||
#: templates/musician/websites/website_form.html:27
|
||||
msgid "Save"
|
||||
msgstr "Guardar"
|
||||
|
||||
#: templates/musician/address_list.html:7
|
||||
#, fuzzy
|
||||
#| msgid "Filtering"
|
||||
msgid "Filter by domain"
|
||||
msgstr "Filtrado"
|
||||
|
||||
#: templates/musician/address_list.html:10
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: templates/musician/address_list.html:25
|
||||
msgid "Email"
|
||||
msgstr "Correo electrónico"
|
||||
|
||||
#: templates/musician/address_list.html:26
|
||||
msgid "Domain"
|
||||
msgstr "Dominio"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: templates/musician/address_list.html:27 templates/musician/mail_base.html:22
|
||||
#: views.py:478
|
||||
msgid "Mailboxes"
|
||||
msgstr "Buzones de correo"
|
||||
|
||||
#: templates/musician/address_list.html:28
|
||||
msgid "Forward"
|
||||
msgstr "Redirección"
|
||||
|
||||
#: templates/musician/address_list.html:49
|
||||
msgid "New mail address"
|
||||
msgstr "Nueva dirección de correo"
|
||||
|
||||
#: templates/musician/base.html:67
|
||||
msgid "Settings"
|
||||
msgstr "Configuración"
|
||||
|
||||
#: templates/musician/base.html:70 templates/musician/profile.html:6
|
||||
msgid "Profile"
|
||||
msgstr "Perfil"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: templates/musician/base.html:71 templates/musician/billing.html:6
|
||||
#: views.py:350
|
||||
msgid "Billing"
|
||||
msgstr "Facturas"
|
||||
|
||||
#: templates/musician/base.html:86
|
||||
msgid "Log out"
|
||||
msgstr "Desconéctate"
|
||||
|
||||
#: templates/musician/base.html:97
|
||||
msgid "Language"
|
||||
msgstr "Idioma"
|
||||
|
||||
#: templates/musician/billing.html:7
|
||||
msgid "Billing page description."
|
||||
msgstr "Consulta y descarga tus facturas."
|
||||
|
||||
#: templates/musician/billing.html:19
|
||||
msgid "Number"
|
||||
msgstr "Número"
|
||||
|
||||
#: templates/musician/billing.html:20
|
||||
msgid "Bill date"
|
||||
msgstr "Fecha de la factura"
|
||||
|
||||
#: templates/musician/billing.html:21 templates/musician/database_list.html:22
|
||||
#: templates/musician/domain_detail.html:38
|
||||
#: templates/musician/webapps/webapp_detail.html:17
|
||||
#: templates/musician/webapps/webapp_detail.html:96
|
||||
#: templates/musician/webapps/webapp_list.html:26
|
||||
msgid "Type"
|
||||
msgstr "Tipo"
|
||||
|
||||
#: templates/musician/billing.html:22
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
|
||||
#: templates/musician/billing.html:23
|
||||
msgid "Download PDF"
|
||||
msgstr "Descarga en PDF"
|
||||
|
||||
#: templates/musician/dashboard.html:6
|
||||
msgid "Welcome back"
|
||||
msgstr "¡Hola de nuevo!"
|
||||
|
||||
#: templates/musician/dashboard.html:8
|
||||
#, python-format
|
||||
msgid "Last time you logged in was: %(last_login)s"
|
||||
msgstr "La última vez que accediste fue el día: %(last_login)s"
|
||||
|
||||
#: templates/musician/dashboard.html:10
|
||||
msgid "It's the first time you log into the system, welcome on board!"
|
||||
msgstr "Es la primera vez que accedes: ¡te damos la bienvenida!"
|
||||
|
||||
#: templates/musician/dashboard.html:14
|
||||
msgid " The disk space of resources is updated weekly "
|
||||
msgstr "El espacio en disco de los recursos se actualiza semanalmente"
|
||||
|
||||
#: templates/musician/dashboard.html:47
|
||||
msgid "Show history"
|
||||
msgstr "Mostrar historial"
|
||||
|
||||
#: templates/musician/database_list.html:21
|
||||
#: templates/musician/mailbox_list.html:30
|
||||
#: templates/musician/mailinglist_list.html:24
|
||||
#: templates/musician/saas_list.html:19
|
||||
#: templates/musician/webapps/webapp_list.html:25
|
||||
#: templates/musician/websites/website_detail.html:77
|
||||
#: templates/musician/websites/website_list.html:20
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: templates/musician/database_list.html:23
|
||||
msgid "Database users"
|
||||
msgstr "Usuarios Base de datos"
|
||||
|
||||
#: templates/musician/database_list.html:24
|
||||
#: templates/musician/domain_list.html:59
|
||||
msgid "Disk usage"
|
||||
msgstr "Uso del disco"
|
||||
|
||||
#: templates/musician/database_list.html:33
|
||||
#: templates/musician/database_list.html:35
|
||||
msgid "Open database manager"
|
||||
msgstr "Abre el gestor de bases de datos"
|
||||
|
||||
#. Translators: database page when there isn't any database.
|
||||
#. Translators: saas page when there isn't any saas.
|
||||
#: templates/musician/database_list.html:58
|
||||
#: templates/musician/saas_list.html:53
|
||||
msgid "Ooops! Looks like there is nothing here!"
|
||||
msgstr "Mmmh… ¡parece que aquí no hay nada!"
|
||||
|
||||
#: templates/musician/domain_detail.html:5
|
||||
#: templates/musician/mailinglist_form.html:16
|
||||
#: templates/musician/record_form.html:5
|
||||
#: templates/musician/webapps/webapp_detail.html:5
|
||||
#: templates/musician/webapps/webapp_option_form.html:7
|
||||
#: templates/musician/websites/website_create_option_form.html:7
|
||||
#: templates/musician/websites/website_detail.html:5
|
||||
#: templates/musician/websites/website_form.html:16
|
||||
msgid "Go back"
|
||||
msgstr "Volver"
|
||||
|
||||
#: templates/musician/domain_detail.html:8
|
||||
msgid "DNS settings for"
|
||||
msgstr "Configuración DNS para"
|
||||
|
||||
#: templates/musician/domain_detail.html:16
|
||||
msgid "Go to top level domain"
|
||||
msgstr "Ir al dominio de nivel superior"
|
||||
|
||||
#: templates/musician/domain_detail.html:20
|
||||
msgid "DNS settings page description."
|
||||
msgstr "Consulta aquí tu configuración DNS."
|
||||
|
||||
#: templates/musician/domain_detail.html:24
|
||||
msgid ""
|
||||
"\n"
|
||||
" <h5 class=\"alert-heading\">IMPORTANT NOTICE!!!</h5>\n"
|
||||
" DNS records control the functioning of your domain, and therefore your "
|
||||
"websites, email addresses, mailing lists, etc.<br>\n"
|
||||
" If you do not have the necessary knowledge about this topic, do not "
|
||||
"make changes in this section. It is dangerous!\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <h5 class=\"alert-heading\">AVISO IMPORTANTE!!!</h5>\n"
|
||||
" Los registros DNS controlan el funcionamiento de su dominio, y por lo "
|
||||
"tanto, sus sitios web, direcciones de correo electrónico, listas de correo, "
|
||||
"etc.<br>\n"
|
||||
" Si no tiene el conocimiento necesario sobre este tema, no haga cambios "
|
||||
"en esta sección. ¡Es peligroso!\n"
|
||||
" "
|
||||
|
||||
#: templates/musician/domain_detail.html:39
|
||||
#: templates/musician/webapps/webapp_detail.html:97
|
||||
#: templates/musician/websites/website_detail.html:78
|
||||
msgid "Value"
|
||||
msgstr "Valor"
|
||||
|
||||
#: templates/musician/domain_detail.html:57
|
||||
msgid "Add new record"
|
||||
msgstr "Añadir registros DNS"
|
||||
|
||||
#: templates/musician/domain_detail.html:60
|
||||
msgid "Subdomains"
|
||||
msgstr "SubDominios"
|
||||
|
||||
#: templates/musician/domain_detail.html:65
|
||||
msgid "Any related subdomain."
|
||||
msgstr "Cualquier subdominio relacionado."
|
||||
|
||||
#: templates/musician/domain_list.html:7
|
||||
msgid "Your domains"
|
||||
msgstr "Tus dominios y sitios web"
|
||||
|
||||
#: templates/musician/domain_list.html:20
|
||||
#: templates/musician/domain_list.html:105
|
||||
msgid "View DNS records"
|
||||
msgstr "Ver registros DNS"
|
||||
|
||||
#: templates/musician/domain_list.html:24
|
||||
msgid "view configuration"
|
||||
msgstr "ver la configuración"
|
||||
|
||||
#: templates/musician/domain_list.html:31
|
||||
msgid "Expiration date"
|
||||
msgstr "Fecha de vencimiento"
|
||||
|
||||
#: templates/musician/domain_list.html:38
|
||||
msgid "Mail"
|
||||
msgstr "Correo"
|
||||
|
||||
#: templates/musician/domain_list.html:41
|
||||
msgid "mail addresses created"
|
||||
msgstr "direcciones de correo creadas"
|
||||
|
||||
#: templates/musician/domain_list.html:46
|
||||
msgid "Mail list"
|
||||
msgstr "Lista de correo"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: templates/musician/domain_list.html:51 views.py:615
|
||||
msgid "Software as a Service"
|
||||
msgstr "Software as a Service"
|
||||
|
||||
#: templates/musician/domain_list.html:53
|
||||
msgid "Nothing installed"
|
||||
msgstr "No tienes nada instalado"
|
||||
|
||||
#: templates/musician/domain_list.html:77
|
||||
msgid "Configuration details"
|
||||
msgstr "Detalles de configuración"
|
||||
|
||||
#: templates/musician/domain_list.html:84
|
||||
msgid "FTP access:"
|
||||
msgstr "Acceso FTP:"
|
||||
|
||||
#: templates/musician/domain_list.html:87
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "Send an email to <a href=\"mailto:%(support_email)s\">%(support_email)s</"
|
||||
#| "a> including your username and we will provide instructions."
|
||||
msgid ""
|
||||
"E-mail us at %(support_email_anchor)s to get details concerning FTP access."
|
||||
msgstr ""
|
||||
"Envía un correo a <a href=“mailto:%(support_email)s”>%(support_email)s</a> "
|
||||
"indicando tu nombre de usuaria/o y te explicaremos qué hacer."
|
||||
|
||||
#: templates/musician/domain_list.html:97
|
||||
msgid "No website configured."
|
||||
msgstr "No hay ninguna web configurada."
|
||||
|
||||
#: templates/musician/domain_list.html:99
|
||||
msgid "Root directory:"
|
||||
msgstr "Directorio raíz:"
|
||||
|
||||
#: templates/musician/domain_list.html:100
|
||||
msgid "Type:"
|
||||
msgstr "Tipo:"
|
||||
|
||||
#: templates/musician/mail_base.html:6
|
||||
#: templates/musician/mailinglist_list.html:6
|
||||
#: templates/musician/users_base.html:6
|
||||
msgid "Go to global"
|
||||
msgstr "Todas las direcciones"
|
||||
|
||||
#: templates/musician/mail_base.html:10
|
||||
#: templates/musician/mailinglist_list.html:9
|
||||
#: templates/musician/users_base.html:10
|
||||
msgid "for"
|
||||
msgstr "para"
|
||||
|
||||
#: templates/musician/mail_base.html:18 templates/musician/mailbox_list.html:32
|
||||
msgid "Addresses"
|
||||
msgstr "Direcciones de correo"
|
||||
|
||||
#: templates/musician/mailbox_change_password.html:5
|
||||
#: templates/musician/mailbox_form.html:24
|
||||
#: templates/musician/systemuser_change_password.html:5
|
||||
#: templates/musician/webapps/webappuser_change_password.html:5
|
||||
msgid "Change password"
|
||||
msgstr "Cambia la contraseña"
|
||||
|
||||
#: templates/musician/mailbox_check_delete.html:7
|
||||
msgid "Are you sure that you want remove the mailbox:"
|
||||
msgstr "¿Estás seguro/a de que quieres borrar el buzón de correo:"
|
||||
|
||||
#: templates/musician/mailbox_check_delete.html:9
|
||||
msgid ""
|
||||
"All mailbox's messages will be <strong>deleted and cannot be recovered</"
|
||||
"strong>."
|
||||
msgstr ""
|
||||
"Todos los mensajes <strong>se borrarán y no se podrán recuperar</strong>."
|
||||
|
||||
#: templates/musician/mailbox_form.html:9
|
||||
msgid "Warning!"
|
||||
msgstr "¡Aviso!"
|
||||
|
||||
#: templates/musician/mailbox_form.html:9
|
||||
msgid ""
|
||||
"You have reached the limit of mailboxes of your subscription so "
|
||||
"<strong>extra fees</strong> may apply."
|
||||
msgstr ""
|
||||
"Has alcanzado el límite de buzones de correo de tu suscripción, los nuevos "
|
||||
"buzones pueden suponer <strong>costes adicionales</strong>."
|
||||
|
||||
#: templates/musician/mailbox_form.html:10
|
||||
msgid "Close"
|
||||
msgstr "Cerrar"
|
||||
|
||||
#: templates/musician/mailbox_list.html:31
|
||||
msgid "Filtering"
|
||||
msgstr "Filtrado"
|
||||
|
||||
#: templates/musician/mailbox_list.html:43
|
||||
#: templates/musician/systemuser_list.html:32
|
||||
#: templates/musician/webapps/webapp_detail.html:33
|
||||
#: templates/musician/webapps/webapp_detail.html:41
|
||||
#: templates/musician/webapps/webappuser_list.html:30
|
||||
#: templates/musician/websites/website_list.html:86
|
||||
#: templates/musician/websites/website_list.html:93
|
||||
msgid "Update password"
|
||||
msgstr "Actualiza la contraseña"
|
||||
|
||||
#: templates/musician/mailbox_list.html:60
|
||||
msgid "New mailbox"
|
||||
msgstr "Nuevo buzón de correo"
|
||||
|
||||
#: templates/musician/mailing_check_delete.html:7
|
||||
msgid "Are you sure that you want remove the list:"
|
||||
msgstr "¿Estás seguro/a de que quieres borrar la siguiente lista:"
|
||||
|
||||
#: templates/musician/mailinglist_form.html:20
|
||||
msgid "Update list"
|
||||
msgstr "Actualizar lista"
|
||||
|
||||
#: templates/musician/mailinglist_form.html:22
|
||||
msgid "Create list"
|
||||
msgstr "Crear lista"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:25
|
||||
#: templates/musician/saas_list.html:20
|
||||
#: templates/musician/websites/website_list.html:23
|
||||
msgid "Status"
|
||||
msgstr "Estado"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:26
|
||||
msgid "Address"
|
||||
msgstr "Dirección de correo"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:27
|
||||
msgid "Admin email"
|
||||
msgstr "Administrador"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:28
|
||||
msgid "Configure"
|
||||
msgstr "Configura"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:37
|
||||
msgid "Active"
|
||||
msgstr "Activo"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:39
|
||||
msgid "Inactive"
|
||||
msgstr "Inactivo"
|
||||
|
||||
#: templates/musician/mailinglist_list.html:61
|
||||
msgid "New list"
|
||||
msgstr "Nueva Lista"
|
||||
|
||||
#: templates/musician/profile.html:7
|
||||
msgid "Little description on profile page."
|
||||
msgstr "Cambia tus datos de acceso y opciones de perfil desde aquí."
|
||||
|
||||
#: templates/musician/profile.html:11
|
||||
msgid "User information"
|
||||
msgstr "Información de usuario/a"
|
||||
|
||||
#: templates/musician/profile.html:21
|
||||
msgid "Preferred language:"
|
||||
msgstr "Idioma preferido:"
|
||||
|
||||
#: templates/musician/profile.html:35
|
||||
msgid "Billing information"
|
||||
msgstr "Datos de facturación"
|
||||
|
||||
#: templates/musician/profile.html:49
|
||||
msgid "payment method:"
|
||||
msgstr "método de pago:"
|
||||
|
||||
#: templates/musician/profile.html:60
|
||||
msgid "Check your last bills"
|
||||
msgstr "Consulta tus últimas facturas"
|
||||
|
||||
#: templates/musician/record_check_delete.html:7
|
||||
msgid "Are you sure that you want remove the following record?"
|
||||
msgstr "¿Estás seguro/a de que quieres borrar el siguiente registro ?"
|
||||
|
||||
#: templates/musician/record_form.html:8
|
||||
#, fuzzy
|
||||
#| msgid "Update password"
|
||||
msgid "Update record of"
|
||||
msgstr "Actualiza la contraseña"
|
||||
|
||||
#: templates/musician/record_form.html:8
|
||||
msgid "Add record to"
|
||||
msgstr "Agregar registro a"
|
||||
|
||||
#: templates/musician/saas_list.html:21
|
||||
msgid "Service"
|
||||
msgstr "Servicio"
|
||||
|
||||
#: templates/musician/saas_list.html:22
|
||||
msgid "Service info"
|
||||
msgstr "Información del servicio"
|
||||
|
||||
#: templates/musician/saas_list.html:30
|
||||
msgid "Installed on"
|
||||
msgstr "Instalado en"
|
||||
|
||||
#: templates/musician/saas_list.html:37 templates/musician/saas_list.html:39
|
||||
msgid "Open service admin panel"
|
||||
msgstr "Abre el panel de administración del servicio"
|
||||
|
||||
#: templates/musician/systemuser_list.html:6
|
||||
msgid ""
|
||||
"The main user is your system's main user on each server. You'll be able to "
|
||||
"view the logs of your websites at (/home/account/logs) and all web content, "
|
||||
"but you'll never be able to edit content on a website."
|
||||
msgstr ""
|
||||
"El usuario principal existe en cada servidor web.Podrá ver los registros de "
|
||||
"sus sitios web en (/home/account/logs) y todoel contenido web (/home/account/"
|
||||
"webapps/*), pero nunca podrá editar el contenido en un sitio web."
|
||||
|
||||
#: templates/musician/systemuser_list.html:7
|
||||
msgid "This user only has write permissions in their own directory."
|
||||
msgstr "Este usuario solo tiene permisos de escritura en su directorio."
|
||||
|
||||
#: templates/musician/systemuser_list.html:18
|
||||
#: templates/musician/webapps/webappuser_list.html:15
|
||||
msgid "Username"
|
||||
msgstr "Nombre de usuario/a"
|
||||
|
||||
#: templates/musician/systemuser_list.html:19
|
||||
#: templates/musician/webapps/webapp_detail.html:47
|
||||
#: templates/musician/webapps/webappuser_list.html:16
|
||||
#: templates/musician/websites/website_detail.html:49
|
||||
msgid "Path"
|
||||
msgstr "Ruta"
|
||||
|
||||
#: templates/musician/users_base.html:18
|
||||
msgid "Main User"
|
||||
msgstr "Usuario Principal"
|
||||
|
||||
#: templates/musician/users_base.html:22
|
||||
msgid "SFTP Users"
|
||||
msgstr "Usuarios SFTP"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:7
|
||||
msgid "WebApp Options for"
|
||||
msgstr "Opciones de WebApp para"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:13
|
||||
#: templates/musician/webapps/webapp_list.html:29
|
||||
#: templates/musician/webapps/webappuser_list.html:17
|
||||
#: templates/musician/websites/website_detail.html:13
|
||||
#: templates/musician/websites/website_list.html:22
|
||||
msgid "Server"
|
||||
msgstr "Servidor"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:27
|
||||
msgid "SFTP user"
|
||||
msgstr "Usuario SFTP"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:58
|
||||
#, fuzzy
|
||||
#| msgid "Databases"
|
||||
msgid "Database:"
|
||||
msgstr "Bases de datos"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:62
|
||||
msgid "User Database:"
|
||||
msgstr "Bases de datos"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:66
|
||||
msgid "Password:"
|
||||
msgstr "Contraseña"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:72
|
||||
msgid ""
|
||||
"\n"
|
||||
" Initial database and App admin password. <br>\n"
|
||||
" Subsequent changes to the admin password will not be reflected.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Contraseña inicial de la base de datos y del administrador de la aplicación. "
|
||||
"<br>Los cambios posteriores en la contraseña del administrador no se "
|
||||
"reflejarán.\n"
|
||||
" "
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:82
|
||||
msgid "PHP settings"
|
||||
msgstr "Configuración PHP"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:87
|
||||
msgid "PHP settings page description."
|
||||
msgstr "Consulta aquí tu configuración DNS."
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:119
|
||||
msgid "This WebApp has PHP options by default, create one if you need it."
|
||||
msgstr ""
|
||||
"Esta WebApp tiene las opciones por defecto, crea una nueva opción si la "
|
||||
"necesitas"
|
||||
|
||||
#: templates/musician/webapps/webapp_detail.html:121
|
||||
msgid "Add new option"
|
||||
msgstr "Añadir nueva opción"
|
||||
|
||||
#: templates/musician/webapps/webapp_list.html:27
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
|
||||
#: templates/musician/webapps/webapp_list.html:28
|
||||
msgid "SFTP User"
|
||||
msgstr "Usuario SFTP"
|
||||
|
||||
#: templates/musician/webapps/webapp_option_form.html:10
|
||||
msgid "Update Option of"
|
||||
msgstr "Actualizar opcion de"
|
||||
|
||||
#: templates/musician/webapps/webapp_option_form.html:10
|
||||
#: templates/musician/websites/website_create_option_form.html:10
|
||||
msgid "Add Option to"
|
||||
msgstr "Añadir Opción a"
|
||||
|
||||
#: templates/musician/webapps/webappoption_check_delete.html:7
|
||||
#: templates/musician/websites/websiteoption_check_delete.html:7
|
||||
msgid "Are you sure that you want remove the following option?"
|
||||
msgstr "¿Estás seguro/a de que quieres borrar la siguiente opción?"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:7
|
||||
msgid "WebSite Options for"
|
||||
msgstr "Opciones de Website para"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:25
|
||||
msgid "active"
|
||||
msgstr "activo"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:32
|
||||
msgid "Protocol"
|
||||
msgstr "Protocolo"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:37
|
||||
msgid "Edit options"
|
||||
msgstr "Editar opciones"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:40
|
||||
msgid "Contents"
|
||||
msgstr "Contenido"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:43
|
||||
msgid "Webapps assigned to this website"
|
||||
msgstr "WebApps asignadas a este WebSite"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:47
|
||||
msgid "Webapp"
|
||||
msgstr ""
|
||||
|
||||
#: templates/musician/websites/website_detail.html:48
|
||||
msgid "Type "
|
||||
msgstr "Tipo"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:67
|
||||
msgid "Assigned new Webapp"
|
||||
msgstr "Añadir nueva Webapp"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:70
|
||||
#, fuzzy
|
||||
#| msgid "Active"
|
||||
msgid "Directives"
|
||||
msgstr "Activo"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:73
|
||||
msgid "Options assigned to this Website"
|
||||
msgstr "Opciones asignadas en este Website"
|
||||
|
||||
#: templates/musician/websites/website_detail.html:95
|
||||
msgid "Add new directive"
|
||||
msgstr "Añadir nueva directiva"
|
||||
|
||||
#: templates/musician/websites/website_form.html:19
|
||||
msgid "Update Option of Website"
|
||||
msgstr "Actualizar Opción de WebSite"
|
||||
|
||||
#: templates/musician/websites/website_list.html:21
|
||||
msgid "Url"
|
||||
msgstr ""
|
||||
|
||||
#: validators.py:28
|
||||
#, python-format
|
||||
msgid ""
|
||||
"%s: Hosts can not have underscore character '_', consider providing a SRV, "
|
||||
"CNAME or TXT record."
|
||||
msgstr ""
|
||||
"%s: Los hosts no pueden tener el carácter de subrayado '_'. Considere "
|
||||
"proporcionar un registro SRV, CNAME o TXT."
|
||||
|
||||
#: views.py:200 views.py:202 views.py:229
|
||||
msgid "available"
|
||||
msgstr "disponibles"
|
||||
|
||||
#: views.py:232
|
||||
msgid "Account"
|
||||
msgstr "Cuenta"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:277
|
||||
msgid "User profile"
|
||||
msgstr "Tu perfil"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:364
|
||||
msgid "Download bill"
|
||||
msgstr "Descarga la factura"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:623
|
||||
msgid "Domain details"
|
||||
msgstr "Detalles del dominio"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:679
|
||||
msgid "Login"
|
||||
msgstr "Accede"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:750
|
||||
msgid "Webapp users"
|
||||
msgstr ""
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: views.py:768
|
||||
msgid "Main users"
|
||||
msgstr ""
|
||||
|
||||
#: webapps/forms.py:62
|
||||
msgid "This option already exist."
|
||||
msgstr "Esta opción ya existe."
|
||||
|
||||
#: webapps/views.py:34
|
||||
msgid ""
|
||||
"A web app is the directory where your website is stored. Through SFTP, you "
|
||||
"can access this directory and upload/edit/delete files."
|
||||
msgstr ""
|
||||
"Una aplicación web es el directorio donde se almacena su sitio web. A través "
|
||||
"de SFTP, puede acceder a este directorio y subir, editar o eliminar archivos."
|
||||
|
||||
#: webapps/views.py:35
|
||||
msgid ""
|
||||
"Each Webapp has its own SFTP user, which is created automatically when the "
|
||||
"Webapp is created."
|
||||
msgstr ""
|
||||
"Cada WebApp tiene su propio usuario SFTP, que se crea automáticamente cuando "
|
||||
"se crea la aplicación web."
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: webapps/views.py:44
|
||||
#, fuzzy
|
||||
#| msgid "Type details"
|
||||
msgid "webapp details"
|
||||
msgstr "Detalles de cada tipo"
|
||||
|
||||
#: websites/forms.py:21
|
||||
msgid ""
|
||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr ""
|
||||
"Mantén presionada la tecla \"Control\" o \"Comando\" en un Mac para "
|
||||
"seleccionar más de uno."
|
||||
|
||||
#: websites/forms.py:54
|
||||
msgid "This Path already exists on this Website."
|
||||
msgstr "Esta ruta ya existe en este WebSite"
|
||||
|
||||
#: websites/views.py:33
|
||||
msgid ""
|
||||
"A website is the place where a domain is associated with the directory where "
|
||||
"the web files are located. (WebApp)"
|
||||
msgstr ""
|
||||
"Un WebSite es el lugar donde se asocia un dominio con el directorio dondese "
|
||||
"encuentran los archivos web. (WebApp)"
|
||||
|
||||
#. Translators: This message appears on the page title
|
||||
#: websites/views.py:42
|
||||
msgid "website details"
|
||||
msgstr "Detalles de cada tipo"
|
||||
|
||||
msgid "Database"
|
||||
msgstr "Bases de datos"
|
||||
|
||||
msgid "Change password for"
|
||||
msgstr "Cambia la contraseña de"
|
||||
|
||||
#~ msgid "Domains & websites"
|
||||
#~ msgstr "Dominios y sitios web"
|
||||
|
||||
msgid "Previous"
|
||||
msgstr "Previa"
|
||||
|
||||
msgid "Next"
|
||||
msgstr "Siguiente"
|
||||
|
||||
msgid "Notifications"
|
||||
msgstr "Notificaciones"
|
||||
|
||||
msgid "There is no notifications at this time."
|
||||
msgstr "No tienes ninguna notificación."
|
||||
|
||||
msgid "Dashboard page description."
|
||||
msgstr ""
|
||||
"Este es tu panel de gestión, desde donde podrás consultar la "
|
||||
"configuración de los servicios que Pangea te ofrece."
|
||||
|
||||
msgid "associated to"
|
||||
msgstr "asociada a"
|
||||
|
||||
msgid "No users for this database."
|
||||
msgstr "No hay usuarias/os de esta base de datos."
|
||||
|
||||
msgid "Traffic"
|
||||
msgstr "Tráfico"
|
||||
|
||||
msgid "Mailbox usage"
|
||||
msgstr "Uso de espacio en tu buzón de correo"
|
||||
|
||||
msgid "Address deleted!"
|
||||
msgstr "Has eliminado la dirección de correo"
|
||||
|
||||
msgid "Cannot process your request, please try again later."
|
||||
msgstr ""
|
||||
"Ahora no podemos procesar tu petición, inténtalo de nuevo un poco más "
|
||||
"tarde por favor."
|
||||
|
||||
msgid "Mailbox deleted!"
|
||||
msgstr "Has eliminado el buzón de correo"
|
||||
|
||||
msgid "mail address left"
|
||||
msgstr "direcciones de correo por activar"
|
||||
|
||||
msgid "Aliases"
|
||||
msgstr "Alias"
|
||||
|
||||
msgid "databases created"
|
||||
msgstr "bases de datos creadas"
|
||||
|
||||
msgid "size"
|
||||
msgstr "tamaño"
|
||||
|
||||
msgid "traffic"
|
||||
msgstr "tráfico"
|
||||
|
||||
msgid "Mailman list traffic"
|
||||
msgstr "Listas de Mailman"
|
||||
|
||||
msgid "Mailman list Traffic"
|
||||
msgstr "Listas de Mailman"
|
|
@ -1,66 +0,0 @@
|
|||
from django.conf import settings
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.generic.base import ContextMixin
|
||||
|
||||
from orchestra import get_version
|
||||
|
||||
from . import api
|
||||
from .auth import SESSION_KEY_TOKEN
|
||||
|
||||
|
||||
class CustomContextMixin(ContextMixin):
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
# generate services menu items
|
||||
services_menu = [
|
||||
{'icon': 'home', 'pattern_name': 'musician:dashboard', 'title': _('Dashboard')},
|
||||
{'icon': 'globe-europe', 'pattern_name': 'musician:domain-list', 'title': _('Domains')},
|
||||
{'icon': 'envelope', 'pattern_name': 'musician:address-list', 'title': _('Mails')},
|
||||
{'icon': 'mail-bulk', 'pattern_name': 'musician:mailing-lists', 'title': _('Mailing lists')},
|
||||
{'icon': 'database', 'pattern_name': 'musician:database-list', 'title': _('Databases')},
|
||||
{'icon': 'fire', 'pattern_name': 'musician:saas-list', 'title': _('SaaS')},
|
||||
{'icon': 'globe', 'pattern_name': 'musician:website-list', 'title': _('Websites')},
|
||||
{'icon': 'folder', 'pattern_name': 'musician:webapp-list', 'title': _('Webapps'), 'indent': True},
|
||||
{'icon': 'user', 'pattern_name': 'musician:systemuser-list', 'title': _('Users'), 'indent': True},
|
||||
]
|
||||
context.update({
|
||||
'services_menu': services_menu,
|
||||
'version': get_version(),
|
||||
'languages': settings.LANGUAGES,
|
||||
})
|
||||
|
||||
return context
|
||||
|
||||
|
||||
class ExtendedPaginationMixin:
|
||||
paginate_by = 20
|
||||
paginate_by_kwarg = 'per_page'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'per_page_values': [5, 10, 20, 50],
|
||||
'per_page_param': self.paginate_by_kwarg,
|
||||
})
|
||||
return context
|
||||
|
||||
def get_paginate_by(self, queryset):
|
||||
per_page = self.request.GET.get(self.paginate_by_kwarg) or self.paginate_by
|
||||
try:
|
||||
paginate_by = int(per_page)
|
||||
except ValueError:
|
||||
paginate_by = self.paginate_by
|
||||
return paginate_by
|
||||
|
||||
|
||||
class UserTokenRequiredMixin(LoginRequiredMixin):
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
self.orchestra = api.OrchestraConnector(self.request)
|
||||
context.update({
|
||||
'profile': self.orchestra.retrieve_profile(),
|
||||
})
|
||||
return context
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue