couldn't stay away, implemented all the basics for domains, mailboxes and aliases
This commit is contained in:
parent
1d01e66a4d
commit
66eb84bb8e
15 changed files with 328 additions and 87 deletions
|
@ -17,6 +17,6 @@ from django.contrib import admin
|
|||
from django.urls import include, path
|
||||
|
||||
urlpatterns = [
|
||||
path('multimail/', include('multimail.urls')),
|
||||
path('', include('multimail.urls')),
|
||||
path('admin/', admin.site.urls),
|
||||
]
|
||||
|
|
|
@ -1,29 +1,32 @@
|
|||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.views import generic
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth import logout as auth_logout
|
||||
|
||||
from .models import Choice, Question, Domain
|
||||
from .models import Domain, Mailbox, Alias
|
||||
|
||||
@login_required(login_url='/login/')
|
||||
def delete_domain(request, domain_id):
|
||||
domain = get_object_or_404(Domain, pk=domain_id)
|
||||
domain.delete()
|
||||
return HttpResponseRedirect(reverse('multimail:domains'))
|
||||
|
||||
|
||||
@login_required(login_url='/login/')
|
||||
def vote(request, question_id):
|
||||
question = get_object_or_404(Question, pk=question_id)
|
||||
try:
|
||||
selected_choice = question.choice_set.get(pk=request.POST['choice'])
|
||||
except (KeyError, Choice.DoesNotExist):
|
||||
# Redisplay the question voting form.
|
||||
return render(request, 'multimail/detail.html', {
|
||||
'question': question,
|
||||
'error_message': "You didn't select a choice.",
|
||||
})
|
||||
else:
|
||||
selected_choice.votes += 1
|
||||
selected_choice.save()
|
||||
# Always return an HttpResponseRedirect after successfully dealing
|
||||
# with POST data. This prevents data from being posted twice if a
|
||||
# user hits the Back button.
|
||||
return HttpResponseRedirect(reverse('multimail:results', args=(question.id,)))
|
||||
def delete_mailbox(request, mailbox_id):
|
||||
mailbox = get_object_or_404(Mailbox, pk=mailbox_id)
|
||||
mailbox.delete()
|
||||
return HttpResponseRedirect(reverse('multimail:mailboxes'))
|
||||
|
||||
|
||||
@login_required(login_url='/login/')
|
||||
def delete_alias(request, alias_id):
|
||||
alias = get_object_or_404(Alias, pk=alias_id)
|
||||
alias.delete()
|
||||
return HttpResponseRedirect(reverse('multimail:aliases'))
|
||||
|
||||
|
||||
def logout(request):
|
||||
auth_logout(request)
|
||||
return HttpResponseRedirect(reverse('multimail:login'))
|
||||
|
|
64
backend/multimail/forms.py
Normal file
64
backend/multimail/forms.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
from django.contrib.auth.decorators import login_required
|
||||
from django.forms import ModelForm
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
|
||||
from multimail.models import Domain, Mailbox, Alias
|
||||
|
||||
|
||||
class DomainForm(ModelForm):
|
||||
class Meta:
|
||||
model = Domain
|
||||
fields = ['domain']
|
||||
|
||||
class MailboxForm(ModelForm):
|
||||
class Meta:
|
||||
model = Mailbox
|
||||
fields = '__all__'
|
||||
|
||||
class AliasForm(ModelForm):
|
||||
class Meta:
|
||||
model = Alias
|
||||
fields = '__all__'
|
||||
|
||||
@login_required(login_url='/login/')
|
||||
def edit_domain(request, domain_id):
|
||||
domain = Domain.objects.get(id=domain_id)
|
||||
if request.method == 'POST':
|
||||
form = DomainForm(request.POST, instance=domain)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return HttpResponseRedirect('/domains/')
|
||||
|
||||
else:
|
||||
form = DomainForm(instance=domain)
|
||||
|
||||
return render(request, 'multimail/edit_domain.html', {'form': form})
|
||||
|
||||
@login_required(login_url='/login/')
|
||||
def edit_mailbox(request, mailbox_id):
|
||||
mailbox = Mailbox.objects.get(id=mailbox_id)
|
||||
if request.method == 'POST':
|
||||
form = MailboxForm(request.POST, instance=mailbox)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return HttpResponseRedirect('/mailboxes/')
|
||||
|
||||
else:
|
||||
form = MailboxForm(instance=mailbox)
|
||||
|
||||
return render(request, 'multimail/edit_mailbox.html', {'form': form})
|
||||
|
||||
@login_required(login_url='/login/')
|
||||
def edit_alias(request, alias_id):
|
||||
alias = Alias.objects.get(id=alias_id)
|
||||
if request.method == 'POST':
|
||||
form = AliasForm(request.POST, instance=alias)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return HttpResponseRedirect('/aliases/')
|
||||
|
||||
else:
|
||||
form = AliasForm(instance=alias)
|
||||
|
||||
return render(request, 'multimail/edit_alias.html', {'form': form})
|
31
backend/multimail/templates/multimail/aliases.html
Normal file
31
backend/multimail/templates/multimail/aliases.html
Normal file
|
@ -0,0 +1,31 @@
|
|||
{% extends 'multimail/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="mt-4">Aliases</h1>
|
||||
|
||||
{% if alias_list %}
|
||||
<table class="table table-striped table-responsive-md btn-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Source</th>
|
||||
<th scope="col">Destination</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for alias in alias_list %}
|
||||
<tr>
|
||||
<th scope="row"><a href="{% url 'multimail:edit_alias' alias.id %}">{{ alias.source_username }}@{{ alias.source_domain }}</a></th>
|
||||
<th scope="row">{{ alias.destination_username }}@{{ alias.destination_domain }}</th>
|
||||
<td><a href="{% url 'multimail:delete_alias' alias.id %}" class="btn btn-danger btn-sm m-0">Delete</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p>You haven't set up any aliases yet.</p>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="{% static 'multimail/css/simple-sidebar.css' %}" rel="stylesheet">
|
||||
<link href="{% static "fontawesome/css/all.min.css" %}" rel="stylesheet" type="text/css"/>
|
||||
|
||||
</head>
|
||||
|
||||
|
@ -29,7 +30,7 @@
|
|||
<div class="list-group list-group-flush">
|
||||
<a href="{% url 'multimail:domains' %}" class="list-group-item list-group-item-action bg-light">Domains</a>
|
||||
<a href="{% url 'multimail:mailboxes' %}" class="list-group-item list-group-item-action bg-light">Mailboxes</a>
|
||||
<a href="#" class="list-group-item list-group-item-action bg-light">Aliases</a>
|
||||
<a href="{% url 'multimail:aliases' %}" class="list-group-item list-group-item-action bg-light">Aliases</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /#sidebar-wrapper -->
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
<h1>{{ question.question_text }}</h1>
|
||||
|
||||
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
|
||||
|
||||
<form action="{% url 'multimail:vote' question.id %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% for choice in question.choice_set.all %}
|
||||
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
|
||||
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
|
||||
{% endfor %}
|
||||
<input type="submit" value="Vote">
|
||||
</form>
|
|
@ -4,13 +4,26 @@
|
|||
<h1 class="mt-4">Domains</h1>
|
||||
|
||||
{% if domain_list %}
|
||||
<ul>
|
||||
{% for question in domain_list %}
|
||||
<li><a href="{% url 'multimail:detail' question.id %}">{{ question.domain }}</a></li>
|
||||
<table class="table table-striped table-responsive-md btn-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Domain</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for domain in domain_list %}
|
||||
<tr>
|
||||
<th scope="row"><a href="{% url 'multimail:edit_domain' domain.id %}">{{ domain.domain }}</a></th>
|
||||
<td><a href="{% url 'multimail:delete_domain' domain.id %}" class="btn btn-danger btn-sm m-0">Delete</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p>No multimail are available.</p>
|
||||
<p>You haven't set up any domains yet.</p>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
18
backend/multimail/templates/multimail/edit_alias.html
Normal file
18
backend/multimail/templates/multimail/edit_alias.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends 'multimail/base.html' %}
|
||||
{% load bootstrap4 %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="mt-4">{{ form.source_username.value }}@{{ form.source_domain.value }}</h1>
|
||||
|
||||
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
|
||||
|
||||
|
||||
<form action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
17
backend/multimail/templates/multimail/edit_domain.html
Normal file
17
backend/multimail/templates/multimail/edit_domain.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
{% extends 'multimail/base.html' %}
|
||||
{% load bootstrap4 %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="mt-4">{{ form.domain.value }}</h1>
|
||||
|
||||
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
|
||||
|
||||
<form action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
17
backend/multimail/templates/multimail/edit_mailbox.html
Normal file
17
backend/multimail/templates/multimail/edit_mailbox.html
Normal file
|
@ -0,0 +1,17 @@
|
|||
{% extends 'multimail/base.html' %}
|
||||
{% load bootstrap4 %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="mt-4">{{ form.username.value }}@{{ form.domain.value }}</h1>
|
||||
|
||||
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
|
||||
|
||||
<form action="" method="post" class="form">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
83
backend/multimail/templates/multimail/login.html
Normal file
83
backend/multimail/templates/multimail/login.html
Normal file
|
@ -0,0 +1,83 @@
|
|||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>Multimail</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="{% static 'vendor/bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="{% static 'multimail/css/simple-sidebar.css' %}" rel="stylesheet">
|
||||
<link href="{% static "fontawesome/css/all.min.css" %}" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="container" style="height:100vh;">
|
||||
<div class="row h-100 justify-content-center align-items-center">
|
||||
<div class="card col-6">
|
||||
<article class="card-body">
|
||||
<h4 class="card-title text-center mb-4 mt-1">Sign in</h4>
|
||||
<hr>
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<ul>
|
||||
{% for error in form.non_field_errors %}
|
||||
<li>{{ error|escape }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="POST">{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"> <i class="fa fa-user"></i> </span>
|
||||
</div>
|
||||
<input id="{{ form.username.id_for_label }}" name="{{ form.username.html_name }}"
|
||||
class="form-control" placeholder="Email or login" type="text" requird>
|
||||
</div> <!-- input-group.//-->
|
||||
{% if form.username.errors %}
|
||||
<p class="text-danger text-center">
|
||||
{% for error in form.username.errors %}
|
||||
{{ error|escape }}<br>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div> <!-- form-group// -->
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"> <i class="fa fa-lock"></i> </span>
|
||||
</div>
|
||||
<input id="{{ form.password.id_for_label }}" name="{{ form.password.html_name }}"
|
||||
class="form-control" placeholder="******" type="password" required>
|
||||
</div> <!-- input-group.// -->
|
||||
{% if form.password.errors %}
|
||||
<p class="text-danger text-center">
|
||||
{% for error in form.password.errors %}
|
||||
{{ error|escape }}<br>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div> <!-- form-group// -->
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-primary btn-block"> Login</button>
|
||||
</div> <!-- form-group// -->
|
||||
<!--p class="text-center"><a href="#" class="btn">Forgot password?</a></p-->
|
||||
</form>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -4,13 +4,26 @@
|
|||
<h1 class="mt-4">Mailboxes</h1>
|
||||
|
||||
{% if mailbox_list %}
|
||||
<ul>
|
||||
{% for question in mailbox_list %}
|
||||
<li><a href="{% url 'multimail:detail' question.id %}">{{ question.domain }}</a></li>
|
||||
<table class="table table-striped table-responsive-md btn-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Mailbox</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for mailbox in mailbox_list %}
|
||||
<tr>
|
||||
<th scope="row"><a href="{% url 'multimail:edit_mailbox' mailbox.id %}">{{ mailbox.username }}@{{ mailbox.domain }}</a></th>
|
||||
<td><a href="{% url 'multimail:delete_mailbox' mailbox.id %}" class="btn btn-danger btn-sm m-0">Delete</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p>No multimail are available.</p>
|
||||
<p>You haven't set up any mailboxes yet.</p>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
|
@ -1,9 +0,0 @@
|
|||
<h1>{{ question.question_text }}</h1>
|
||||
|
||||
<ul>
|
||||
{% for choice in question.choice_set.all %}
|
||||
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<a href="{% url 'multimail:detail' question.id %}">Vote again?</a>
|
|
@ -1,17 +1,25 @@
|
|||
from django.urls import path
|
||||
from django.contrib.auth import views as auth_views
|
||||
|
||||
from . import views
|
||||
from . import views, forms
|
||||
from . import actions
|
||||
|
||||
app_name = 'multimail'
|
||||
urlpatterns = [
|
||||
path('', views.DomainListView.as_view(), name='index'),
|
||||
|
||||
path('domains/', views.DomainListView.as_view(), name='domains'),
|
||||
path('domain/<int:domain_id>/', forms.edit_domain, name='edit_domain'),
|
||||
path('domain/<int:domain_id>/delete', actions.delete_domain, name='delete_domain'),
|
||||
|
||||
path('mailboxes/', views.MailboxListView.as_view(), name='mailboxes'),
|
||||
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
|
||||
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
|
||||
path('<int:question_id>/vote/', actions.vote, name='vote'),
|
||||
path('login/', auth_views.LoginView.as_view(), name='login'),
|
||||
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
|
||||
path('mailbox/<int:mailbox_id>/', forms.edit_mailbox, name='edit_mailbox'),
|
||||
path('mailbox/<int:mailbox_id>/delete', actions.delete_mailbox, name='delete_mailbox'),
|
||||
|
||||
path('aliases/', views.AliasListView.as_view(), name='aliases'),
|
||||
path('alias/<int:alias_id>/', forms.edit_alias, name='edit_alias'),
|
||||
path('alias/<int:alias_id>/delete', actions.delete_alias, name='delete_alias'),
|
||||
|
||||
path('login/', views.UserLoginView.as_view(), name='login'),
|
||||
path('logout/', actions.logout, name='logout'),
|
||||
]
|
|
@ -1,17 +1,16 @@
|
|||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse
|
||||
from django.views import generic
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.views import LoginView
|
||||
|
||||
from .models import Choice, Question, Domain, Mailbox
|
||||
from .models import Domain, Mailbox, Alias
|
||||
|
||||
|
||||
class UserLoginView(LoginView):
|
||||
template_name = 'multimail/login.html'
|
||||
|
||||
|
||||
class DomainListView(LoginRequiredMixin, generic.ListView):
|
||||
login_url = 'login/'
|
||||
# redirect_field_name = 'redirect_to'
|
||||
template_name = 'multimail/domains.html'
|
||||
context_object_name = 'domain_list'
|
||||
|
||||
|
@ -23,9 +22,9 @@ class DomainListView(LoginRequiredMixin, generic.ListView):
|
|||
# ).order_by('-pub_date')[:5]
|
||||
return Domain.objects.all()
|
||||
|
||||
|
||||
class MailboxListView(LoginRequiredMixin, generic.ListView):
|
||||
login_url = 'login/'
|
||||
# redirect_field_name = 'redirect_to'
|
||||
template_name = 'multimail/mailboxes.html'
|
||||
context_object_name = 'mailbox_list'
|
||||
|
||||
|
@ -38,20 +37,15 @@ class MailboxListView(LoginRequiredMixin, generic.ListView):
|
|||
return Mailbox.objects.all()
|
||||
|
||||
|
||||
class DetailView(LoginRequiredMixin, generic.DetailView):
|
||||
class AliasListView(LoginRequiredMixin, generic.ListView):
|
||||
login_url = 'login/'
|
||||
model = Question
|
||||
template_name = 'multimail/detail.html'
|
||||
template_name = 'multimail/aliases.html'
|
||||
context_object_name = 'alias_list'
|
||||
|
||||
def get_queryset(self):
|
||||
"""
|
||||
Excludes any questions that aren't published yet.
|
||||
"""
|
||||
return Question.objects.filter(pub_date__lte=timezone.now())
|
||||
|
||||
|
||||
class ResultsView(LoginRequiredMixin, generic.DetailView):
|
||||
login_url = 'login/'
|
||||
model = Question
|
||||
template_name = 'multimail/results.html'
|
||||
|
||||
print(self.request.user)
|
||||
"""Return the last five published questions."""
|
||||
# return Domain.objects.filter(
|
||||
# pub_date__lte=timezone.now()
|
||||
# ).order_by('-pub_date')[:5]
|
||||
return Alias.objects.all()
|
||||
|
|
Loading…
Reference in a new issue