basic auth

This commit is contained in:
Flatlogic Bot 2025-12-17 19:03:11 +00:00
parent 321df5d009
commit 26e9533758
21 changed files with 313 additions and 6 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -180,3 +180,8 @@ if EMAIL_USE_SSL:
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGIN_URL = 'login'
LOGIN_REDIRECT_URL = 'index'
LOGOUT_REDIRECT_URL = 'index'

View File

@ -36,6 +36,15 @@
<li><a href="#"><i data-feather="users"></i> Clients</a></li> <li><a href="#"><i data-feather="users"></i> Clients</a></li>
<li><a href="#"><i data-feather="settings"></i> Settings</a></li> <li><a href="#"><i data-feather="settings"></i> Settings</a></li>
</ul> </ul>
<ul class="auth-nav">
{% if user.is_authenticated %}
<li><a href="{% url 'logout' %}"><i data-feather="log-out"></i> Logout</a></li>
{% else %}
<li><a href="{% url 'login' %}"><i data-feather="log-in"></i> Login</a></li>
<li><a href="{% url 'register' %}"><i data-feather="user-plus"></i> Register</a></li>
{% endif %}
</ul>
</ul>
</nav> </nav>
</div> </div>
<div class="main-content"> <div class="main-content">

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}webFirma{% endblock %}</title>
{% if project_description %}
<meta name="description" content="{{ project_description }}">
<meta property="og:description" content="{{ project_description }}">
<meta property="twitter:description" content="{{ project_description }}">
{% endif %}
{% if project_image_url %}
<meta property="og:image" content="{{ project_image_url }}">
<meta property="twitter:image" content="{{ project_image_url }}">
{% endif %}
{% load static %}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
<script src="https://unpkg.com/feather-icons"></script>
{% block head %}{% endblock %}
</head>
<body>
<div class="public-layout">
<header class="public-header">
<div class="logo">
<h2>webFirma</h2>
</div>
<div class="public-actions">
<a href="{% url 'login' %}" class="btn">Login</a>
<a href="{% url 'register' %}" class="btn btn-primary">Register</a>
</div>
</header>
<main class="public-content">
{% block content %}{% endblock %}
</main>
</div>
<script>
feather.replace()
</script>
</body>
</html>

View File

@ -0,0 +1,22 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Edytuj Projekt - webFirma{% endblock %}
{% block content %}
<div class="main-header">
<h1>Edytuj Projekt</h1>
</div>
<div class="content-grid">
<div class="project-card">
<div class="card-body">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Zapisz zmiany</button>
</form>
</div>
</div>
</div>
{% endblock %}

View File

@ -11,7 +11,9 @@
<i data-feather="search"></i> <i data-feather="search"></i>
<input type="text" placeholder="Search projects..."> <input type="text" placeholder="Search projects...">
</div> </div>
{% if user.is_authenticated %}
<a href="{% url 'add_project' %}" class="btn btn-primary"><i data-feather="plus"></i> Dodaj projekt</a> <a href="{% url 'add_project' %}" class="btn btn-primary"><i data-feather="plus"></i> Dodaj projekt</a>
{% endif %}
</div> </div>
</div> </div>
@ -37,7 +39,10 @@
<img src="https://i.pravatar.cc/32?u=c" alt="Avatar"> <img src="https://i.pravatar.cc/32?u=c" alt="Avatar">
</div> </div>
</div> </div>
<a href="#" class="btn-view">Zobacz projekt</a> {% if user.is_authenticated %}
<a href="{% url 'edit_project' project.id %}" class="btn-view">Edit</a>
<a href="{% url 'delete_project' project.id %}" class="btn-view">Delete</a>
{% endif %}
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

View File

@ -0,0 +1,14 @@
{% extends 'base_public.html' %}
{% load static %}
{% block title %}Welcome to webFirma{% endblock %}
{% block content %}
<div class="landing-page">
<div class="hero">
<h1>Zarządzaj swoimi projektami</h1>
<p>webFirma to proste i intuicyjne narzędzie do zarządzania projektami, fakturami i klientami.</p>
<a href="{% url 'register' %}" class="btn btn-primary btn-lg">Zacznij za darmo</a>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,14 @@
{% extends 'base_public.html' %}
{% block title %}Login - webFirma{% endblock %}
{% block content %}
<div class="container">
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
{% endblock %}

View File

@ -0,0 +1,14 @@
{% extends 'base_public.html' %}
{% block title %}Register - webFirma{% endblock %}
{% block content %}
<div class="container">
<h2>Register</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
{% endblock %}

View File

@ -1,7 +1,13 @@
from django.urls import path from django.urls import path
from .views import index, add_project from .views import index, add_project, register, edit_project, delete_project
from django.contrib.auth.views import LoginView, LogoutView
urlpatterns = [ urlpatterns = [
path('', index, name='index'), path('', index, name='index'),
path('add-project/', add_project, name='add_project'), path('add-project/', add_project, name='add_project'),
path('register/', register, name='register'),
path('login/', LoginView.as_view(template_name='core/login.html'), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),
path('edit-project/<int:project_id>/', edit_project, name='edit_project'),
path('delete-project/<int:project_id>/', delete_project, name='delete_project'),
] ]

View File

@ -1,11 +1,19 @@
from django.shortcuts import render, redirect from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.views import LoginView, LogoutView
from .models import Project from .models import Project
from .forms import ProjectForm from .forms import ProjectForm
def index(request): def index(request):
projects = Project.objects.all().order_by('-start_date') if request.user.is_authenticated:
return render(request, 'core/index.html', {'projects': projects}) projects = Project.objects.all().order_by('-start_date')
return render(request, 'core/index.html', {'projects': projects})
else:
return render(request, 'core/landing.html')
@login_required
def add_project(request): def add_project(request):
if request.method == 'POST': if request.method == 'POST':
form = ProjectForm(request.POST) form = ProjectForm(request.POST)
@ -14,4 +22,33 @@ def add_project(request):
return redirect('index') return redirect('index')
else: else:
form = ProjectForm() form = ProjectForm()
return render(request, 'core/add_project.html', {'form': form}) return render(request, 'core/add_project.html', {'form': form})
@login_required
def edit_project(request, project_id):
project = get_object_or_404(Project, pk=project_id)
if request.method == 'POST':
form = ProjectForm(request.POST, instance=project)
if form.is_valid():
form.save()
return redirect('index')
else:
form = ProjectForm(instance=project)
return render(request, 'core/edit_project.html', {'form': form, 'project': project})
@login_required
def delete_project(request, project_id):
project = get_object_or_404(Project, pk=project_id)
project.delete()
return redirect('index')
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect('index')
else:
form = UserCreationForm()
return render(request, 'core/register.html', {'form': form})

View File

@ -33,6 +33,16 @@ body {
flex-direction: column; flex-direction: column;
} }
.sidebar-nav {
flex-grow: 1;
}
.auth-nav {
list-style: none;
padding: 0;
margin: 0;
}
.sidebar-header h2 { .sidebar-header h2 {
font-weight: 700; font-weight: 700;
color: var(--primary-dark); color: var(--primary-dark);
@ -251,4 +261,62 @@ body {
.empty-state p { .empty-state p {
color: var(--dark-grey); color: var(--dark-grey);
margin-bottom: 24px; margin-bottom: 24px;
}
/* Public Layout */
.public-layout {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.public-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24px 48px;
border-bottom: 1px solid var(--medium-grey);
}
.public-header .logo h2 {
font-weight: 700;
color: var(--primary-dark);
margin: 0;
font-size: 24px;
}
.public-actions .btn {
text-decoration: none;
font-weight: 600;
margin-left: 16px;
}
.public-content {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
}
/* Landing Page */
.landing-page .hero {
text-align: center;
}
.landing-page .hero h1 {
font-size: 48px;
font-weight: 700;
color: var(--primary-dark);
margin-bottom: 16px;
}
.landing-page .hero p {
font-size: 18px;
color: var(--dark-grey);
margin-bottom: 32px;
}
.btn-lg {
padding: 14px 28px;
font-size: 16px;
} }

View File

@ -33,6 +33,16 @@ body {
flex-direction: column; flex-direction: column;
} }
.sidebar-nav {
flex-grow: 1;
}
.auth-nav {
list-style: none;
padding: 0;
margin: 0;
}
.sidebar-header h2 { .sidebar-header h2 {
font-weight: 700; font-weight: 700;
color: var(--primary-dark); color: var(--primary-dark);
@ -251,4 +261,62 @@ body {
.empty-state p { .empty-state p {
color: var(--dark-grey); color: var(--dark-grey);
margin-bottom: 24px; margin-bottom: 24px;
}
/* Public Layout */
.public-layout {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.public-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24px 48px;
border-bottom: 1px solid var(--medium-grey);
}
.public-header .logo h2 {
font-weight: 700;
color: var(--primary-dark);
margin: 0;
font-size: 24px;
}
.public-actions .btn {
text-decoration: none;
font-weight: 600;
margin-left: 16px;
}
.public-content {
flex-grow: 1;
display: flex;
justify-content: center;
align-items: center;
}
/* Landing Page */
.landing-page .hero {
text-align: center;
}
.landing-page .hero h1 {
font-size: 48px;
font-weight: 700;
color: var(--primary-dark);
margin-bottom: 16px;
}
.landing-page .hero p {
font-size: 18px;
color: var(--dark-grey);
margin-bottom: 32px;
}
.btn-lg {
padding: 14px 28px;
font-size: 16px;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB