-Django==3.1.7
+Django==3.2.6
django-gravatar2==1.4.4
django-oidc-provider2==0.8.3
--e git+https://github.com/fnp/django-cas-provider.git@53585f7615b3a647d1badda1a2ebd7f5ec81f607#egg=django-cas-provider
+-e git+https://github.com/fnp/django-cas-provider.git@122f2f5678cfe723a44c140206da2cb9117b46ee#egg=django-cas-provider
alt="Gravatar"
title="{% trans 'Change at Gravatar.com' %}">
{% block menu %}
+ <p><a {% if menu == 'services' %}class="active"{% endif %} href="{% url 'services' %}">{% trans "Services" %}</a></p>
<p><a {% if menu == 'profile' %}class="active"{% endif %} href="{% url 'accounts_profile' %}">{% trans "Your profile" %}</a></p>
<p><a {% if menu == 'password' %}class="active"{% endif %} href="{% url 'password_change' %}">{% trans "Password change" %}</a></p>
{% use_email as use_email %}
<div id="details">
{% if messages %}
- <section id="messages">
- {% for message in messages %}<p>{{ message }}</p>{% endfor %}
- </section>
+ {% for message in messages %}
+ <div class="alert alert-primary">
+ {{ message }}
+ </div>
+ {% endfor %}
{% endif %}
-
+
{% block accounts-content %}
{% endblock %}
</div>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
- <p><button type="submit">{% trans "Change profile" %}</button></p>
+ <p><button type="submit" class="btn btn-primary">{% trans "Change profile" %}</button></p>
</form>
{% endblock %}
{{ form.as_p }}
<p>
- <input type="submit" value="{% trans 'Change my password' %}">
+ <input type="submit" value="{% trans 'Change my password' %}" class="btn btn-primary">
</p>
</form>
}
}
+DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
+
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
.menu img {
box-shadow: 0 0 .2em black;
+ margin-bottom: 1em;
}
code.key {
display: block;
color: #666;
}
+
+
+.service-list {
+ display: flex;
+ gap: 10px;
+ flex-wrap: wrap;
+}
+a.service {
+ width: 130px;
+ height: 80px;
+ background: white;
+ box-shadow: 3px 3px 5px #aaa;
+ padding: 10px;
+ position: relative;
+ display: flex;
+ color: black;
+ align-items: center;
+ justify-content: center;
+}
+a.service:hover {
+ text-decoration: none;
+ background: orange;
+}
+.service-icon {
+ max-width: 100%;
+ max-height: 100%;
+}
<head>
<meta charset="utf-8" />
<title>{% block title %}Logowanie{% endblock %} | Fundacja Nowoczesna Polska</title>
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<link rel="stylesheet" href="{% static 'css/main.css' %}"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
{% block extrahead %}
if settings.DEBUG:
- from django.views.static import serve
- urlpatterns += [
- path('media/<path>', serve, {
- 'document_root': settings.MEDIA_ROOT,
- }),
- ]
+ from django.conf.urls.static import static
+ urlpatterns += static(
+ settings.MEDIA_URL,
+ document_root=settings.MEDIA_ROOT
+ )
--- /dev/null
+# Generated by Django 3.2.6 on 2021-08-20 10:35
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('services', '0002_auto_20190330_2220'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='service',
+ name='description',
+ field=models.TextField(blank=True, verbose_name='description'),
+ ),
+ migrations.AddField(
+ model_name='service',
+ name='for_all',
+ field=models.BooleanField(default=False, verbose_name='for all'),
+ ),
+ migrations.AddField(
+ model_name='service',
+ name='icon',
+ field=models.FileField(blank=True, upload_to='service/icon', verbose_name='icon'),
+ ),
+ ]
from django.conf import settings
from django.contrib.auth.models import User
from django.db import models
+from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
url = models.URLField(_('URL'), blank=True)
key = models.CharField(_('key'), max_length=255, blank=True)
uses_ssh = models.BooleanField(_('uses SSH'), default=False)
+
+ for_all = models.BooleanField(_('for all'), default=False)
+ description = models.TextField(_('description'), blank=True)
+ icon = models.FileField(_('icon'), blank=True, upload_to='service/icon')
+
groups = models.ManyToManyField('auth.Group', verbose_name=_('groups'), blank=True)
users = models.ManyToManyField(settings.AUTH_USER_MODEL, verbose_name=_('users'), blank=True)
def __str__(self):
return self.name
+ def get_absolute_url(self):
+ return reverse('service_detail', args=[self.pk])
+
def save(self, *args, **kwargs):
if not self.key:
self.key = secrets.token_urlsafe()
@classmethod
def for_user(cls, user):
- return cls.objects.filter(models.Q(users=user) | models.Q(groups__user=user))
+ return cls.objects.filter(
+ models.Q(for_all=True) | models.Q(users=user) | models.Q(groups__user=user)
+ )
class Hook(models.Model):
--- /dev/null
+{% extends "account/base.html" %}
+
+{% block menu %}
+ {% with menu="services" %}
+ {{ block.super }}
+ {% endwith %}
+{% endblock %}
--- /dev/null
+{% extends "services/base.html" %}
+{% load i18n %}
+
+
+{% block accounts-content %}
+ <h1>{% translate "Serwis" %}: {{ service.name }}</h1>
+
+ {% if service.url %}
+ {{ service.url }}
+ {% endif %}
+
+ {% if service.uses_ssh %}
+ {% url 'ssh_keys' as url_ssh_keys %}
+ {% if request.user.sshkey_set.exists %}
+ {% blocktrans %}
+ This service will use your <a href="{{ url_ssh_keys}}">SSH keys.</a>
+ {% endblocktrans %}
+ {% else %}
+ <div class="alert alert-warning">
+ {% blocktrans %}
+ This service uses SSH keys.
+ You can add one in the <a href="{{ url_ssh_keys}}">SSH keys</a> section.
+ {% endblocktrans %}
+ </div>
+ {% endif %}
+ {% endif %}
+
+ {{ service.description|linebreaks }}
+{% endblock %}
--- /dev/null
+{% extends 'services/base.html' %}
+{% load i18n %}
+
+{% block accounts-content %}
+ <h1>{% translate "Services" %}</h1>
+
+ <div class="service-list">
+ {% for service in object_list %}
+ <a class="service" href="{% if service.url %}{{ service.url }}{% else %}{% url 'service_detail' service.pk %}{% endif %}" title="{{ service.name }}">
+ {% if service.icon %}
+ <img class="service-icon" alt="{{ service.name }}" src="{{ service.icon.url }}">
+ {% else %}
+ <span class="service-name">
+ {{ service.name }}
+ </span>
+ {% endif %}
+ </a>
+ {% endfor %}
+ </div>
+
+{% endblock %}
urlpatterns = [
+ path('', views.ServicesView.as_view(), name='services'),
+ path('<int:pk>/', views.ServiceDetail.as_view(), name='service_detail'),
path('<int:pk>/ssh/authorized_keys', views.SshAuthorizedKeysView.as_view()),
]
-from django.views.generic import DetailView
+from django.views.generic import DetailView, ListView
from .models import Service
obj = None
return obj
+
+class ServicesView(ListView):
+ def get_queryset(self):
+ return Service.for_user(self.request.user)
+
+
+class ServiceDetail(DetailView):
+ def get_queryset(self):
+ return Service.for_user(self.request.user)
<form method='post'>
{% csrf_token %}
{{ form.as_p }}
- <button type='submit'>
+ <button type='submit' class="btn btn-primary">
{% trans "Add" %}
</button>
</form>
{% block accounts-content %}
+ <a href="{% url 'ssh_keys_add' %}" class="btn btn-primary float-end" >
+ {% trans "Add" %}
+ </a>
+
<h1>{% trans "SSH keys" %}</h1>
{% for key in object_list %}
- <p>
- {{ key.comment }} ({{ key.algorithm}} {{ key.bit_length }})<br>
- {{ key.md5_hash }}
- <code class="key">{{ key.key }}</code><br>
- {% trans "Added" %}: {{ key.created_at }}<br>
- {% trans "Last seen" %}: {{ key.last_seen_at|default:"–" }}<br>
-
- <a href="{% url 'ssh_keys_delete' key.id %}">
- {% trans "Delete" %}
- </a>
- </p>
- <hr>
+ <div class="card mb-2">
+ <div class="card-header">
+ {{ key.comment }} ({{ key.algorithm}} {{ key.bit_length }})<br>
+ </div>
+ <div class="card-body">
+ {% trans "Added" %}: {{ key.created_at }}<br>
+ {% trans "Last seen" %}: {{ key.last_seen_at|default:"–" }}<br>
+
+ <br>
+ {{ key.md5_hash }}
+ <code class="key">{{ key.key }}</code><br>
+ <a href="{% url 'ssh_keys_delete' key.id %}" class="btn btn-danger">
+ {% trans "Delete" %}
+ </a>
+ </div>
+ </div>
+ {% empty %}
+ <div class="alert alert-warning">
+ {% translate "You don't have any SSH keys." %}
+ </div>
{% endfor %}
- <a href="{% url 'ssh_keys_add' %}">
- {% trans "Add" %}
- </a>
{% endblock %}