merge_email_verifier #3

Merged
tracer merged 23 commits from merge_email_verifier into master 2022-11-04 10:35:23 +01:00
25 changed files with 135 additions and 438 deletions

View File

@ -1,4 +1,3 @@
TODO: A CMS based on symfony
Make user work WIP
make quotes work

5
TODO
View File

@ -1,10 +1,9 @@
accent color #d43934 accent color #d43934
merge RequestController/SecurityController add dates and author to pages
don't use html in easyadmin / quotes
use turbo use turbo
make unit tests make unit tests
- harden Api-Platform

View File

@ -6,7 +6,26 @@
*/ */
// any CSS you import will output into a single css file (app.css in this case) // any CSS you import will output into a single css file (app.css in this case)
import './styles/app.css'; import 'fork-awesome/scss/fork-awesome.scss'
import './styles/app.scss'
import $ from 'jquery'
import 'bootstrap'
//import './js/index'
// needed for legacy code
//global.$ = $
if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
console.log('🎉 Dark mode is supported')
}
$(document).ready(() => {
console.log('ready')
$('#toggleSidebar').on('click', () => {
const toggleIcon = $('#toggleIcon')
toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-left')
toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-right')
$('#sidebar').toggleClass('active')
})
})
// start the Stimulus application // start the Stimulus application
import './bootstrap'; //import './bootstrap'

4
assets/bootstrap.js vendored
View File

@ -1,11 +1,11 @@
import { startStimulusApp } from '@symfony/stimulus-bridge'; import {startStimulusApp} from '@symfony/stimulus-bridge'
// Registers Stimulus controllers from controllers.json and in the controllers/ directory // Registers Stimulus controllers from controllers.json and in the controllers/ directory
export const app = startStimulusApp(require.context( export const app = startStimulusApp(require.context(
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers', '@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
true, true,
/\.[jt]sx?$/ /\.[jt]sx?$/
)); ))
// register any custom, 3rd party controllers here // register any custom, 3rd party controllers here
// app.register('some_controller_name', SomeImportedController); // app.register('some_controller_name', SomeImportedController);

View File

@ -1,17 +1,2 @@
// assets/js/index.js // assets/js/index.js
import '../styles/app.scss'
import 'fork-awesome/scss/fork-awesome.scss'
require('bootstrap')
import 'bootswatch/dist/slate/bootstrap.min.css'
$(document).ready(function () {
console.log('ready')
$('#toggleSidebar').on('click', function () {
let toggleIcon = $('#toggleIcon')
toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-left')
toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-right')
$('#sidebar').toggleClass('active')
})
})

View File

@ -14,6 +14,15 @@
//border: 1px solid gray; //border: 1px solid gray;
} }
// customize some Bootstrap variables
$primary: #FF8040;
$jet-black: #0e0e10;
//$body-bg: red;
$body-color: #8f8f8f;
@import 'bootstrap-dark-5/dist/css/bootstrap-night.min.css';
html, body { html, body {
margin: 0; margin: 0;
@ -23,10 +32,6 @@ html, body {
} }
// customize some Bootstrap variables
$primary: #FF8040;
$jet-black: #0e0e10;
//@import "bootstrap/scss/bootstrap";
/// ///
@ -40,6 +45,7 @@ $jet-black: #0e0e10;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
float: left; float: left;
background-color: $jet-black;
transition: min-width 0.5s, max-width 0.5s; transition: min-width 0.5s, max-width 0.5s;
} }
@ -57,7 +63,7 @@ $jet-black: #0e0e10;
#main_content { #main_content {
overflow-y: auto; overflow-y: auto;
height: calc(100vh - 160px) height: calc(100vh - 180px); // 74px header, 64px header
} }
.form-signin { .form-signin {
@ -96,3 +102,13 @@ $jet-black: #0e0e10;
margin-bottom: 10px; margin-bottom: 10px;
border-radius: 0 0 0.375rem 0.375rem; border-radius: 0 0 0.375rem 0.375rem;
} }
.quote-box {
border-left: 1px solid #ff8844;
color: #ff8844;
}
.project-image {
width: 200px;
margin: 15px;
}

View File

@ -31,6 +31,7 @@
"@typescript-eslint/eslint-plugin-tslint": "^5.26.0", "@typescript-eslint/eslint-plugin-tslint": "^5.26.0",
"axios": "^0.27.1", "axios": "^0.27.1",
"bootstrap": "^5.2.2", "bootstrap": "^5.2.2",
"bootstrap-dark-5": "^1.1.3",
"bootswatch": "^5.2.2", "bootswatch": "^5.2.2",
"eslint": "^8.15.0", "eslint": "^8.15.0",
"eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-base": "^15.0.0",

View File

@ -52,7 +52,7 @@ class DashboardController extends AbstractDashboardController
} }
return parent::configureUserMenu(user: $user) return parent::configureUserMenu(user: $user)
->setAvatarUrl(url: 'build/images/'.$user->getAvatar()); ->setAvatarUrl(url: 'uploads/avatars/' . $user->getAvatar());
} }
public function configureActions(): Actions public function configureActions(): Actions

View File

@ -8,6 +8,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\CodeEditorField; use EasyCorp\Bundle\EasyAdminBundle\Field\CodeEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class PagesCrudController extends AbstractCrudController class PagesCrudController extends AbstractCrudController
@ -24,7 +25,7 @@ class PagesCrudController extends AbstractCrudController
yield TextField::new(propertyName: 'name'); yield TextField::new(propertyName: 'name');
yield AssociationField::new(propertyName: 'owner'); yield AssociationField::new(propertyName: 'owner');
// yield CodeEditorField::new(propertyName: 'content') // yield CodeEditorField::new(propertyName: 'content')
yield TextareaField::new(propertyName: 'content') yield TextEditorField::new(propertyName: 'content')
->onlyOnForms(); ->onlyOnForms();
} }
} }

View File

@ -5,7 +5,7 @@ namespace App\Controller\Admin;
use App\Entity\Quotes; use App\Entity\Quotes;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController; use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField; use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class QuotesCrudController extends AbstractCrudController class QuotesCrudController extends AbstractCrudController
@ -21,7 +21,7 @@ class QuotesCrudController extends AbstractCrudController
->onlyOnIndex(); ->onlyOnIndex();
yield TextField::new(propertyName: 'quote') yield TextField::new(propertyName: 'quote')
->onlyOnIndex(); ->onlyOnIndex();
yield TextEditorField::new(propertyName: 'quote') yield TextAreaField::new(propertyName: 'quote')
->onlyOnForms(); ->onlyOnForms();
} }
} }

View File

@ -27,7 +27,7 @@ class UserCrudController extends AbstractCrudController
yield ImageField::new(propertyName: 'avatar') yield ImageField::new(propertyName: 'avatar')
->setBasePath(path: 'uploads/avatars') ->setBasePath(path: 'uploads/avatars')
->setUploadDir(uploadDirPath: 'public/uploads/avatars') ->setUploadDir(uploadDirPath: 'public/uploads/avatars')
->setUploadedFileNamePattern(patternOrCallable: '[timestamp]-[slug].[extension]'); ->setUploadedFileNamePattern(patternOrCallable: '[slug]-[timestamp].[extension]');
$roles = ['ROLE_FOUNDER', 'ROLE_ADMIN', 'ROLE_MODERATOR', 'ROLE_USER']; $roles = ['ROLE_FOUNDER', 'ROLE_ADMIN', 'ROLE_MODERATOR', 'ROLE_USER'];
yield ChoiceField::new(propertyName: 'roles') yield ChoiceField::new(propertyName: 'roles')
->setChoices(choiceGenerator: array_combine(keys: $roles, values: $roles)) ->setChoices(choiceGenerator: array_combine(keys: $roles, values: $roles))

View File

@ -23,7 +23,7 @@ class FrontendController extends AbstractController
return $this->render(view: '@default/base.html.twig', parameters: [ return $this->render(view: '@default/base.html.twig', parameters: [
'user' => $user, 'user' => $user,
'quote' => json_encode(value: $quote->getQuote()) 'quote' => $quote->getQuote()
]); ]);
} }
} }

View File

@ -4,39 +4,37 @@ namespace App\Controller;
use App\Entity\Pages; use App\Entity\Pages;
use App\Repository\PagesRepository; use App\Repository\PagesRepository;
use App\Repository\UserRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
class PagesController extends AbstractController class PagesController extends AbstractController
{ {
#[Route(path: '/pages/{name}', name: 'pages_display')] #[Route(path: '/pages/{slug}', name: 'pages_display')]
public function display(PagesRepository $pagesRepository, string $name): Response public function display(PagesRepository $pagesRepository, UserRepository $userRepository, string $slug): Response
{ {
$page = $pagesRepository->findOneBy([ $page = $pagesRepository->findOneBy([
'slug' => $name, 'slug' => $slug,
]); ]);
if (!$page) { if (!$page) {
$page = new Pages(); $page = new Pages();
$page->setName(name: 'Not Found'); $page->setName(name: 'Not Found');
$page->setContent(content: 'The requested page was not found.'); $page->setContent(content: '404 - The requested page was not found.');
} }
return $this->render(view: '@default/pages/display.html.twig', parameters: [ dump($page);
'page' => $page, dump($page->getOwner());
$user = $userRepository->findOneBy(['id' => $page->getOwner()->getId()]);
dd($user);
return $this->render(view: '@default/pages/index.html.twig', parameters: [
'page_name' => $page->getName(),
'page_content' => $page->getContent(),
'created_at' => $page->getCreatedAt(),
'modified_at' => $page->getModifiedAt(),
'owner' => $page->getOwner()
]); ]);
} }
#[Route(path: '/imprint', name: 'app_imprint')]
public function imprint(): Response
{
return $this->render(view: '@default/pages/imprint.html.twig');
}
#[Route(path: '/privacy', name: 'app_privacy')]
public function privacy(): Response
{
return $this->render(view: '@default/pages/privacy.html.twig');
}
} }

View File

@ -2,56 +2,38 @@
namespace App\Entity; namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use App\Repository\PagesRepository; use App\Repository\PagesRepository;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Sunrise\Slugger\Slugger; use Sunrise\Slugger\Slugger;
#[ORM\Entity(repositoryClass: PagesRepository::class), ORM\HasLifecycleCallbacks] #[ORM\Entity(repositoryClass: PagesRepository::class), ORM\HasLifecycleCallbacks]
#[ApiResource]
#[ApiFilter(filterClass: SearchFilter::class, properties: ['slug' => 'exact'])]
class Pages class Pages
{ {
#[ORM\Id] #[ORM\Id]
#[ORM\GeneratedValue] #[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')] #[ORM\Column(type: 'integer')]
private $id; private ?int $id;
#[ORM\Column(type: 'string', length: 255)] #[ORM\Column(type: 'string', length: 255)]
private $name; private string $name;
#[ORM\Column(type: 'text')] #[ORM\Column(type: 'text')]
private $content; private string $content;
#[ORM\Column(type: 'datetime_immutable')] #[ORM\Column(type: 'datetime_immutable')]
private $createdAt; private ?DateTimeImmutable $createdAt;
#[ORM\Column(type: 'datetime_immutable', nullable: true)] #[ORM\Column(type: 'datetime_immutable', nullable: true)]
private $modifiedAt; private ?DateTimeImmutable $modifiedAt;
#[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'pages')] #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'pages')]
#[ORM\JoinColumn(nullable: false)] #[ORM\JoinColumn(nullable: false)]
private $owner; private User $owner;
#[ORM\Column(type: 'string', length: 255)] #[ORM\Column(type: 'string', length: 255)]
private $slug; private string $slug;
/**
* @param $id
*/
/* public function __construct(String $name = '', String $content = '')
{
$this->name = $name;
$this->content = $content;
$owner = $userRepository->findOneBy(['username' => 'tracer']);
$this->owner = $owner;
}
*/
public function getId(): ?int public function getId(): ?int
{ {

View File

@ -2,21 +2,19 @@
namespace App\Entity; namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Repository\QuotesRepository; use App\Repository\QuotesRepository;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: QuotesRepository::class)] #[ORM\Entity(repositoryClass: QuotesRepository::class)]
#[ApiResource]
class Quotes class Quotes
{ {
#[ORM\Id] #[ORM\Id]
#[ORM\GeneratedValue] #[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')] #[ORM\Column(type: 'integer')]
private $id; private int $id;
#[ORM\Column(type: 'text')] #[ORM\Column(type: 'text')]
private $quote; private string $quote;
public function getId(): ?int public function getId(): ?int
{ {

View File

@ -3,11 +3,11 @@
namespace App\Entity; namespace App\Entity;
use App\Repository\UserRepository; use App\Repository\UserRepository;
use DateTime;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Stringable;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserInterface;
@ -15,7 +15,6 @@ use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: UserRepository::class), ORM\HasLifecycleCallbacks] #[ORM\Entity(repositoryClass: UserRepository::class), ORM\HasLifecycleCallbacks]
#[UniqueEntity(fields: ['username', 'email'], message: 'There is already an account with this username or email.')] #[UniqueEntity(fields: ['username', 'email'], message: 'There is already an account with this username or email.')]
class User implements UserInterface, PasswordAuthenticatedUserInterface class User implements UserInterface, PasswordAuthenticatedUserInterface
{ {
#[ORM\Id] #[ORM\Id]
@ -45,22 +44,22 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
private ?string $lastName = ''; private ?string $lastName = '';
#[ORM\ManyToMany(targetEntity: Projects::class, mappedBy: 'developer')] #[ORM\ManyToMany(targetEntity: Projects::class, mappedBy: 'developer')]
private $projects; private Collection $projects;
#[ORM\Column(type: 'string', length: 255, nullable: true)] #[ORM\Column(type: 'string', length: 255, nullable: true)]
private string $avatar; private ?string $avatar;
#[ORM\OneToMany(mappedBy: 'owner', targetEntity: Pages::class)] #[ORM\OneToMany(mappedBy: 'owner', targetEntity: Pages::class)]
private $pages; private Collection $pages;
#[ORM\Column(type: 'datetime_immutable')] #[ORM\Column(type: 'datetime_immutable')]
private $createdAt; private DateTimeImmutable $createdAt;
#[ORM\Column(type: 'datetime_immutable', nullable: true)] #[ORM\Column(type: 'datetime_immutable', nullable: true)]
private $modifiedAt; private DateTimeImmutable $modifiedAt;
#[ORM\Column(type: 'boolean')] #[ORM\Column(type: 'boolean')]
private $isVerified = false; private bool $isVerified = false;
#[ORM\Column] #[ORM\Column]
private ?DateTimeImmutable $agreedTermsAt = null; private ?DateTimeImmutable $agreedTermsAt = null;
@ -137,13 +136,6 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this; return $this;
} }
/**
* @see UserInterface
*/
public function eraseCredentials()
{
$this->plainPassword = '';
}
public function getEmail(): ?string public function getEmail(): ?string
{ {
@ -157,10 +149,6 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this; return $this;
} }
public function setPlainPassword(string $plainPassword): void
{
$this->plainPassword = $plainPassword;
}
public function getFirstName(): ?string public function getFirstName(): ?string
{ {
@ -282,7 +270,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
/** /**
* @return string * @return string
*/ */
public function getAvatarUri() public function getAvatarUri(): string
{ {
return 'avatar'; return 'avatar';
} }
@ -322,4 +310,9 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
return $this; return $this;
} }
public function eraseCredentials()
{
// TODO: Implement eraseCredentials() method.
}
} }

View File

@ -23,7 +23,7 @@ class PagesRepository extends ServiceEntityRepository
public function add(Pages $entity, bool $flush = true): void public function add(Pages $entity, bool $flush = true): void
{ {
$this->_em->persist($entity); $this->_em->persist(entity: $entity);
if ($flush) { if ($flush) {
$this->_em->flush(); $this->_em->flush();
} }
@ -31,7 +31,7 @@ class PagesRepository extends ServiceEntityRepository
public function remove(Pages $entity, bool $flush = true): void public function remove(Pages $entity, bool $flush = true): void
{ {
$this->_em->remove($entity); $this->_em->remove(entity: $entity);
if ($flush) { if ($flush) {
$this->_em->flush(); $this->_em->flush();
} }

View File

@ -1,12 +1,14 @@
<footer class="footer"> <footer class="footer">
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-bottom navbar-bottom"> <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-bottom navbar-bottom">
<div class="d-flex justify-content-xl-around"> <div class="d-flex justify-content-xl-around">
<div>powered by <div class="ms-5">powered by
<a href="#"><img src="{{ asset('build/images/Spookie/spookie_64x64.png') }}" alt="Spookie"></a> <a href="#">
<img class="mx-1" src="{{ asset('build/images/Spookie/spookie_64x64.png') }}" alt="Spookie">
</a>
</div> </div>
<div id="legal"> <div id="legal">
<a href="{{ path('app_imprint') }}">Imprint</a> <a href="{{ path('pages_display', { 'slug': 'imprint' }) }}">Imprint</a>
<a href="{{ path('app_privacy') }}">Privacy Policy</a> <a href="{{ path('pages_display', { 'slug': 'privacy' }) }}">Privacy Policy</a>
</div> </div>
</div> </div>
</nav> </nav>

View File

@ -82,14 +82,14 @@
</div> </div>
{% endfor %} {% endfor %}
<div class="col m-3" id="main_content"> <div class="col m-3" id="main_content">
{% block body %} {% block body %}
<h1 class="q-title-show">Quote of the Moment</h1>
<div class="q-display p-3"> <h1 class="title-show">Quote of the Moment</h1>
{# <i class="fa fa-quote-left"></i> #} <div class="quote-box p-3">
<p class="d-inline"> <i class="fa fa-quote-left"></i><br>
{{ quote | raw }} {{ quote | raw | nl2br }}
</p>
</div> </div>
{% endblock %} {% endblock %}
</div> </div>

View File

@ -1,23 +0,0 @@
{% extends '@default/base.html.twig' %}
{% block title %}Imprint{% endblock %}
{% block body %}
<div class="imprint-wrapper">
<h2>This page is only available in German, as the server is located in Germany.</h2>
<p>Inhaltlich Verantwortlicher gemäß § 55 Abs. 2RStV:<br><br>
Michael Espey<br>
Große Kirchreihe 27<br>
25377 Kollmar</p>
<p>eMail: webmaster (AT) 24unix.net</p>
<p>Für den Inhalt des Internetauftritts ist allein der Inhaber zuständig. Der Inhaber bemüht sich, sein Internetangebot aktuell, korrekt und vollständig zu halten. Dessen ungeachtet kann eine Garantie für die Vollständigkeit, Richtigkeit und letzte Aktualität der Angaben nicht übernommen werden. Daher kann der Inhaber keinerlei Verantwortung oder Haftung weder auf den redaktionellen Inhalt noch für die angebotenen Leistungen auf dieser Website übernehmen. Bei den bereitgestellten Informationen handelt es sich um solche allgemeiner Art, die nicht auf die Bedürfnisse bestimmter Personen oder Unternehmen zugeschnitten sind. Insbesondere soll durch sie keine rechtliche Beratung erfolgen. Trotz sorgfältiger inhaltlicher Kontrolle übernehme ich keine Haftung für die Inhalte externer Links. Für den Inhalt der verlinkten Seiten sind ausschließlich deren Betreiber verantwortlich.</p>
<p>Umsatzsteuer-Identifikationsnummer gemäß § 27a Umsatzsteuergesetz: DE245057708</p>
</div>
{% endblock %}

View File

@ -0,0 +1,9 @@
{% extends '@default/base.html.twig' %}
{% block title %}page_name{% endblock %}
{% block body %}
{{ page_content | raw }}
<br>
Page created by: {{ owner }} at {{ created_at }}
{% endblock %}

View File

@ -1,289 +0,0 @@
{% extends '@default/base.html.twig' %}
{% block title %}Privacy{% endblock %}
{% block body %}
<p class="privacy-wrapper">
<h2>This page is only available in German, as the server is located in Germany.</h2>
<p style="text-align:left;">Der Betreiber der Internetseite 24unix.net nimmt den Schutz Deiner persönlichen Daten
sehr ernst.
Er behandelt Deine Daten vertraulich und entsprechend der gesetzlichen Datenschutzvorschriften sowie dieser
Datenschutzerklärung.
Die Kontaktdaten des Ansprechpartners kannst Du dem Impressum entnehmen.
Zusätzlich stehen Dir die Administratoren gerne unter webmaster@24unix.net zur Verfügung.<p>
<b>Behandlung personenbezogener Daten</b>
<p style="text-align:left;">Die Nutzung von 24unix.net zum Lesen und Suchen ist ohne Angabe von personenbezogenen
Daten möglich.
Die Nutzung der Angebote zur Diskussion (z.B. Schreiben von Beiträgen, private Nachrichten empfangen und
verfassen) benötigt eine vorherige Registrierung.
Die im Zuge dieser Registrierung eingegebenen Daten, die aus der Eingabemaske des Registrierungsformulars
ersichtlich sind, umfassen u.a. E-Mailadresse, Benutzername (Nutzung eines Pseudonyms möglich) und Passwort.
Diese Daten werden ausschließlich für die Verwendung des Angebots seitens 24unix.net erhoben und gespeichert.
Mit der Registrierung werden zudem das Datum sowie die Uhrzeit der Registrierung gespeichert.
Dies dient dem Fall, dass ein Dritter deine Daten missbraucht und sich mit diesen Daten ohne dein Wissen auf
24unix.net registriert sowie zur Absicherung des Betreibers.
Zugriff auf deine Registrierungsdaten haben ausschließlich der Betreiber (siehe Impressum) sowie die berufenen
Forenadministratoren (siehe Admin-Team).
Alle diese Parteien sind dieser Datenschutzrichtlinie verpflichtet. Eine Weitergabe deiner Daten an Dritte
erfolgt nicht.
Ein Abgleich der so erhobenen Daten mit Daten, die möglicherweise durch andere Komponenten (z.B. in
Server-Log-Dateien) erhoben werden, erfolgt ebenfalls nicht.
24unix.net anonymisiert sämtliche IP-Adressen seiner Nutzer automatisch nach drei Wochen.
Der Betreiber weist darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail)
Sicherheitslücken aufweist.
Einen lückenlosen Schutz deiner Daten vor dem Zugriff durch Dritte kann der Betreiber daher nicht
gewährleisten.</p>
<b>Speicherung des Passworts</b>
<p style="text-align:left">Dein Passwort wird mit einer Einwegeverschlüsselung (Hash) gespeichert, sodass der
originale Inhalt nicht rekonstruiert werden kann.
Jedoch ist zu empfehlen, dieses Passwort nicht auf einer Vielzahl von Webseiten zu verwenden.
Insbesondere wird dich kein Vertreter seitens 24unix.net (Betreiber oder Administratoren) nach deinem Passwort
fragen.
Solltest du dein Passwort vergessen haben, so nutze die Funktion „Ich habe mein Passwort vergessen“.
Die Forensoftware fragt dich daraufhin nach deinem Benutzernamen sowie eMailadresse und sendet anschließend ein
neu generiertes Passwort an deine hinterlegte Adresse.</p>
<b>Hinweis zur TLS-Verschlüsselung</b>
<p style="text-align:left">24unix.net wird über das Secure-http-Protokoll ausgeliefert. Diese TLS (früher:
SSL)-Verschlüsselung stellt nach derzeitigem technischen Stand sicher,
dass kein Dritter übertragene Daten mitlesen bzw. verändern kann. Dies gilt sowohl für die Inhalte der Seite als
auch für Daten,
die Ihr durch die Nutzung von Formularen an uns sendet.</p>
<b>Kommentarmöglichkeit</b>
<p style="text-align:left">24unix.net bietet Dir die Möglichkeit, Kommentare zu den einzelnen Beiträgen zu
hinterlassen.
Hierbei wird die IP-Adresse des Verfassers/Anschlussinhabers für drei Wochen gespeichert, um sie ggf. an
Strafermittlungsbehörden weiterleiten zu können wenn wir dazu verpflichtet werden sollten.
Eine Weitergabe von Daten an Dritte erfolgt nicht. Ein Abgleich der so erhobenen Daten mit Daten, die
möglicherweise durch andere Komponenten seitens 24unix.net erhoben werden,
erfolgt ebenfalls nicht.</p>
<b>Nutzung von Cookies</b>
<p style="text-align:left">24unix.net verwendet sogenannte Cookies. Dies sind kleine Textdateien, die auf Deinem
Rechner lokal abgelegt werden und die Dein Browser speichert.
Cookies dienen dazu, das Forum nutzerfreundlicher, effektiver und sicherer zu machen.
<!-- Alle Cookies werden standardmäßig für ein Jahr angelegt, können jedoch jederzeit über einen am Ende der Seite
[url="https://rc-heli-fan.org/ucp.php?mode=delete_cookies"]auffindbaren Link[/url] gelöscht werden.-->
Cookies werden im 24unix.net für folgende Funktionen genutzt:</p>
<ul style="text-align:left">
<li>Speichern der persönlichen Einstellung der User, über ein- oder ausgeklappte Kategorien
<li>Den automatischen Login-Dienst zu nutzen
<li>Die Sitzungs-ID. Mit diesem Cookie wird in Verbindung mit der Benutzer-ID der Nutzer identifiziert.
<li>Die User ID des Benutzers
<li>Speichern, ob der User den Hinweis des Forums, dass Cookies genutzt werden, bestätigt hat.
<li>Markieren von gelesenen/ungelesenen Beiträgen für Gäste
</ul>
<p style="text-align:left">Du kannst den Umgang mit Cookies in Deinem Browser konfigurieren, z.B. das du über das
Speichern neuer Cookies
informiert wirst.
Bei der Deaktivierung von Cookies im Browser kann die Funktionalität des 24unix.nets eingeschränkt sein.</p>
<b>Zugriffsdaten in Server-Log-Dateien</b>
<p style="text-align:left">24unix.net erhebt und speichert Informationen in sogenannten Server-Log-Dateien, die Dein
Browser automatisch übermittelt.
Diese Daten werden bis zu zehn Wochen gespeichert. Sie umfassen:</p>
<ul style="text-align:left">
<li>Browsertyp und -version</li>
<li>verwendetes Betriebssystem</li>
<li>Webseite, von der aus du uns besuchst (Referrer URL)</li>
<li>die aufgerufene Seite</li>
<li>Datum und Uhrzeit des Zugriffs</li>
<li>die Internet Protokoll (IP)-Adresse</li>
</ul>
<p style="text-align:left">Die Verarbeitung erfolgt gemäß Art. 6 Abs. 1 lit. f DSGVO auf Basis unseres berechtigten Interesses an
der Verbesserung der Stabilität
und Funktionalität unserer Website. Eine Weitergabe oder anderweitige Verwendung der Daten findet nicht statt.
Wir behalten uns allerdings vor, die Server-Logfiles nachträglich zu überprüfen, sollten konkrete Anhaltspunkte
auf eine rechtswidrige Nutzung hinweisen.</p>
<b>Gestattung der Kontaktaufnahme</b>
<p style="text-align:left">Du gestattest dem Betreiber und den Administratoren, dich unter den von dir angegebenen
Kontaktdaten zu kontaktieren,
sofern dies zur Übermittlung zentraler Informationen über das Forum erforderlich ist. Darüber hinaus dürfen der
Betreiber,
Administratoren und andere registrierte Benutzer des Forums dich kontaktieren, sofern du dies an entsprechender
Stelle erlaubt hast.
Im Rahmen der Kontaktaufnahme mit uns (z.B. per eMail) werden personenbezogene Daten (IP Adressen) erhoben.
Diese Daten werden ausschließlich zum Zweck der Beantwortung deines Anliegens bzw. für die Kontaktaufnahme und
die damit verbundene technische Administration gespeichert und verwendet. Rechtsgrundlage für die Verarbeitung
der Daten ist unser berechtigtes Interesse an der Beantwortung deines Anliegens gemäß Art. 6 Abs. 1 lit. f
DSGVO.
Zielt Deine Kontaktierung auf den Abschluss eines Vertrages ab, so ist zusätzliche Rechtsgrundlage für die
Verarbeitung Art. 6 Abs. 1 lit. b DSGVO.
Deine Daten werden nach abschließender Bearbeitung der Anfrage gelöscht, dies ist der Fall, wenn sich aus den
Umständen entnehmen lässt,
dass der betroffene Sachverhalt abschließend geklärt ist und sofern keine gesetzlichen Aufbewahrungspflichten
entgegenstehen.</p>
<b>Rechte des Betroffenen</b>
<p style="text-align:left">Das geltende Datenschutzrecht gewährt dir gegenüber dem Verantwortlichen hinsichtlich der
Verarbeitung deiner personenbezogenen Daten
umfassende Betroffenenrechte (Auskunfts- und Interventionsrechte), über die wir dich nachstehend
informieren:</p>
<ul style="text-align:left">
<li>Auskunftsrecht gemäß Art. 15 DSGVO: Du hast insbesondere ein Recht auf Auskunft über Deine von uns
verarbeiteten personenbezogenen Daten,
die Verarbeitungszwecke, die Kategorien der verarbeiteten personenbezogenen Daten, die Empfänger oder
Kategorien
von Empfängern,
gegenüber denen Deine Daten offengelegt wurden oder werden, die geplante Speicherdauer bzw. die Kriterien
für
die Festlegung der Speicherdauer,
das Bestehen eines Rechts auf Berichtigung, Löschung, Einschränkung der Verarbeitung, Widerspruch gegen die
Verarbeitung,
Beschwerde bei einer Aufsichtsbehörde, die Herkunft Deiner Daten, wenn diese nicht durch uns bei dir erhoben
wurden,
das Bestehen einer automatisierten Entscheidungsfindung einschließlich Profiling und ggf. aussagekräftige
Informationen
über die involvierte Logik und die Dich betreffende Tragweite und die angestrebten Auswirkungen einer
solchen
Verarbeitung,
sowie dein Recht auf Unterrichtung, welche Garantien gemäß Art. 46 DSGVO bei Weiterleitung deiner Daten in
Drittländer bestehen.
</li>
<li>Recht auf Berichtigung gemäß Art. 16 DSGVO: Du hast ein Recht auf unverzügliche Berichtigung dich
betreffender unrichtiger Daten
und/oder Vervollständigung deiner bei uns gespeicherten unvollständigen Daten.
</li>
<li>Recht auf Löschung gemäß Art. 17 DSGVO: Du hast das Recht, die Löschung Deiner personenbezogenen Daten bei
Vorliegen
der Voraussetzungen des Art. 17 Abs. 1 DSGVO zu verlangen. Dieses Recht besteht jedoch insbesondere dann
nicht,
wenn die Verarbeitung zur Ausübung des Rechts auf freie Meinungsäußerung und Information, zur Erfüllung
einer
rechtlichen
Verpflichtung, aus Gründen des öffentlichen Interesses oder zur Geltendmachung, Ausübung oder Verteidigung
von
Rechtsansprüchen erforderlich ist.
</li>
<li>Recht auf Einschränkung der Verarbeitung gemäß Art. 18 DSGVO: Du hast das Recht, die Einschränkung der
Verarbeitung Deiner personenbezogenen
Daten zu verlangen, solange die von dir bestrittene Richtigkeit Deiner Daten überprüft wird, wenn du eine
Löschung Deiner Daten wegen unzulässiger
Datenverarbeitung ablehnst und stattdessen die Einschränkung der Verarbeitung Deiner Daten verlangen, wenn
du
Deine Daten zur Geltendmachung,
Ausübung oder Verteidigung von Rechtsansprüchen benötigst, nachdem wir diese Daten nach Zweckerreichung
nicht
mehr benötigen oder wenn du Widerspruch
aus Gründen deiner besonderen Situation eingelegt hast, solange noch nicht feststeht, ob unsere berechtigten
Gründe überwiegen.
</li>
<li>Recht auf Unterrichtung gemäß Art. 19 DSGVO: Hast Du das Recht auf Berichtigung, Löschung oder Einschränkung
der Verarbeitung gegenüber
dem Verantwortlichen geltend gemacht, ist dieser verpflichtet, allen Empfängern, denen die dich betreffenden
personenbezogenen Daten
offengelegt wurden, diese Berichtigung oder Löschung der Daten oder Einschränkung der Verarbeitung
mitzuteilen,
es sei denn, dies erweist
sich als unmöglich oder ist mit einem unverhältnismäßigen Aufwand verbunden. Dir steht das Recht zu, über
diese
Empfänger unterrichtet zu werden.
</li>
<li>Recht auf Datenübertragbarkeit gemäß Art. 20 DSGVO: Du hast das Recht, Deine personenbezogenen Daten, die du
uns bereitgestellt hast,
in einem strukturierten, gängigen und maschinenlesebaren Format zu erhalten oder die Übermittlung an einen
anderen Verantwortlichen
zu verlangen, soweit dies technisch machbar ist.
</li>
<li>Recht auf Widerruf erteilter Einwilligungen gemäß Art. 7 Abs. 3 DSGVO: Du hast das Recht, eine einmal
erteilte Einwilligung
in die Verarbeitung von Daten jederzeit mit Wirkung für die Zukunft zu widerrufen. Im Falle des Widerrufs
werden
wir die betroffenen
Daten unverzüglich löschen, sofern eine weitere Verarbeitung nicht auf eine Rechtsgrundlage zur
einwilligungslosen Verarbeitung gestützt
werden kann. Durch den Widerruf der Einwilligung wird die Rechtmäßigkeit der aufgrund der Einwilligung bis
zum
Widerruf erfolgten Verarbeitung nicht berührt.
</li>
<li>Recht auf Beschwerde gemäß Art. 77 DSGVO: Wenn du der Ansicht bist, dass die Verarbeitung der Dich
betreffenden personenbezogenen Daten gegen die DSGVO
verstößt, hast du - unbeschadet eines anderweitigen verwaltungsrechtlichen oder gerichtlichen Rechtsbehelfs
-
das Recht auf Beschwerde
bei einer Aufsichtsbehörde, insbesondere in dem Mitgliedstaat deines Aufenthaltsortes, deines Arbeitsplatzes
oder des Ortes des mutmaßlichen Verstoßes.
</li>
</ul>
<b>Widerspruchsrecht</b>
<p style="text-align:left">Du hast das Recht, aus Gründen, die sich aus Deiner besonderen Situation ergibt,
jederzeit gegen die Verarbeitung der Dich betreffenden
personenbezogenen Daten, die aufgrund von Art. 6 Abs. 1 lit. e oder f DSGVO erfolgt, Widerspruch einzulegen;
dies gilt auch für ein auf diese Bestimmungen gestütztes Profiling.
Der Verantwortliche verarbeitet die Dich betreffenden personenbezogenen Daten nicht mehr, es sei denn, er kann
zwingende schutzwürdige Gründe
für die Verarbeitung nachweisen, die deine Interessen, Rechte und Freiheiten überwiegen, oder die Verarbeitung
dient der Geltendmachung,
Ausübung oder Verteidigung von Rechtsansprüchen.
Werden die Dich betreffenden personenbezogenen Daten verarbeitet, um Direktwerbung zu betreiben, hast du das
Recht,
jederzeit Widerspruch gegen die Verarbeitung der Dich betreffenden personenbezogenen Daten zum Zwecke derartiger
Werbung einzulegen;
dies gilt auch für das Profiling, soweit es mit solcher Direktwerbung in Verbindung steht.
Widersprichst du der Verarbeitung für Zwecke der Direktwerbung, so werden die dich betreffenden
personenbezogenen Daten nicht mehr für diese Zwecke verarbeitet.
Du hast die Möglichkeit, im Zusammenhang mit der Nutzung von Diensten der Informationsgesellschaft ungeachtet
der Richtlinie 2002/58/EG Dein
Widerspruchsrecht mittels automatisierter Verfahren auszuüben, bei denen technische Spezifikationen verwendet
werden.
Du hast auch das Recht, aus Gründen, die sich aus Deiner besonderen Situation ergeben, bei der Verarbeitung Dich
betreffender personenbezogener Daten,
die zu wissenschaftlichen oder historischen Forschungszwecken oder zu statistischen Zwecken gem. Art. 89 Abs. 1
DSGVO erfolgt, dieser zu widersprechen.
Dein Widerspruchsrecht kann insoweit beschränkt werden, als es voraussichtlich die Verwirklichung der
Forschungs- oder Statistikzwecke unmöglich
macht oder ernsthaft beeinträchtigt und die Beschränkung für die Erfüllung der Forschungs- oder Statistikzwecke
notwendig ist.</p>
<b>Geltungsbereich dieser Richtlinie</b>
<p>Diese Richtlinie umfasst alle Seiten, die unter 24unix.net gespeichert sind.
Ergeben sich Änderungen an dieser Richtlinie, werden die Benutzer des Forums hierüber informiert und es besteht
ein Widerspruchsrecht.
Explizit keinen Einfluss hat der Betreiber auf externe, verlinkte Webseiten, auf denen diese Richtlinie nicht
gilt.</p>
Quellen:
<ul style="text-align:left;padding-bottom: 200px">
<li><a href="https://www.ratgeberrecht.eu">Muster-Datenschutzerklärung der Anwaltskanzlei Weiß & Partner</a>
</li>
<li><a href="https://www.e-recht24.de">e-recht24.de</a></li>
<li><a href="https://dsaforum.de/app.php/datenschutz">Datenschutzerklärung des DSA-Forums</a></li>
<li>eigene Ergänzungen</li>
</ul>
{% endblock %}

View File

@ -17,12 +17,12 @@
<a href="{{ path('app_projects', { name: project.name }) }}"> <a href="{{ path('app_projects', { name: project.name }) }}">
{% if project.teaserImage %} {% if project.teaserImage %}
<img <img
class="blog-img" class="project-image"
src="/uploads/projects/{{ project.teaserImage }}" src="/uploads/projects/{{ project.teaserImage }}"
alt="Teaser"> alt="Teaser">
{% else %} {% else %}
<img <img
class="blog-img" class="project-image"
src="{{ asset('build/images/24unix/24_logo_bg_96x96.png') }}" src="{{ asset('build/images/24unix/24_logo_bg_96x96.png') }}"
alt="Teaser"> alt="Teaser">
{% endif %} {% endif %}

View File

@ -13,7 +13,7 @@ Encore
from: './assets/images', from: './assets/images',
to: 'images/[path][name].[ext]' to: 'images/[path][name].[ext]'
}) })
.addEntry('app', './assets/js/index.js') .addEntry('app', './assets/app.js')
.splitEntryChunks() .splitEntryChunks()
// will require an extra script tag for runtime.js // will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app // but, you probably want this, unless you're building a single-page app

View File

@ -1717,7 +1717,14 @@ boolbase@^1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
bootstrap@^5.2.2: bootstrap-dark-5@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/bootstrap-dark-5/-/bootstrap-dark-5-1.1.3.tgz#a40c42083f2ee1f05ca0423f334d5edf52c35f9e"
integrity sha512-3Paopsp8wyOM1oeaLWLFuUZThhRc3tBYKUnoF+uwrU/xN4G47MCLZlALBJNqYqAecg7dSln9vgaYK1CwPnTeBw==
dependencies:
bootstrap "^5.1.3"
bootstrap@^5.1.3, bootstrap@^5.2.2:
version "5.2.2" version "5.2.2"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.2.tgz#834e053eed584a65e244d8aa112a6959f56e27a0" resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.2.tgz#834e053eed584a65e244d8aa112a6959f56e27a0"
integrity sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ== integrity sha512-dEtzMTV71n6Fhmbg4fYJzQsw1N29hJKO1js5ackCgIpDcGid2ETMGC6zwSYw09v05Y+oRdQ9loC54zB1La3hHQ==