Akoda35 commited on
Commit
b4d357b
·
verified ·
1 Parent(s): 8f26696

Upload 7 files

Browse files
templates/auth/change_password.html ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}{% if has_password %}Change{% else %}Set{% endif %} Password - PyRunner{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="min-h-[calc(100vh-12rem)] flex items-center justify-center px-4 py-12">
7
+ <div class="w-full max-w-md">
8
+ <div class="text-center mb-10">
9
+ <div class="w-16 h-16 bg-code-accent/20 rounded-2xl flex items-center justify-center mx-auto mb-6">
10
+ <svg class="w-8 h-8 text-code-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
11
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
12
+ </svg>
13
+ </div>
14
+ <h1 class="text-2xl font-bold text-code-text mb-2">
15
+ {% if has_password %}Change Password{% else %}Set Password{% endif %}
16
+ </h1>
17
+ <p class="text-code-muted">
18
+ {% if has_password %}
19
+ Update your account password
20
+ {% else %}
21
+ Create a password for your account
22
+ {% endif %}
23
+ </p>
24
+ </div>
25
+
26
+ <div class="bg-code-surface border border-code-border rounded-xl p-8">
27
+ {% if form.errors %}
28
+ <div class="mb-6 p-4 bg-code-red/10 border border-code-red/30 rounded-lg">
29
+ {% for error in form.non_field_errors %}
30
+ <p class="text-sm text-code-red">{{ error }}</p>
31
+ {% endfor %}
32
+ </div>
33
+ {% endif %}
34
+
35
+ <form method="post" class="space-y-5">
36
+ {% csrf_token %}
37
+
38
+ <div>
39
+ <label for="id_password" class="block text-sm font-medium text-code-muted mb-2">
40
+ New Password
41
+ </label>
42
+ {{ form.password }}
43
+ {% if form.password.help_text %}
44
+ <p class="mt-1 text-xs text-code-muted">{{ form.password.help_text }}</p>
45
+ {% endif %}
46
+ {% if form.password.errors %}
47
+ <p class="mt-1 text-xs text-code-red">{{ form.password.errors.0 }}</p>
48
+ {% endif %}
49
+ </div>
50
+
51
+ <div>
52
+ <label for="id_password_confirm" class="block text-sm font-medium text-code-muted mb-2">
53
+ Confirm Password
54
+ </label>
55
+ {{ form.password_confirm }}
56
+ {% if form.password_confirm.errors %}
57
+ <p class="mt-1 text-xs text-code-red">{{ form.password_confirm.errors.0 }}</p>
58
+ {% endif %}
59
+ </div>
60
+
61
+ <div class="flex space-x-4 pt-2">
62
+ <a href="{% url 'cpanel:settings' %}" class="flex-1 py-3 px-4 bg-code-bg hover:bg-code-bg/80 text-code-text border border-code-border font-medium rounded-lg transition-colors text-center">
63
+ Cancel
64
+ </a>
65
+ <button type="submit" class="flex-1 py-3 px-4 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors">
66
+ {% if has_password %}Change Password{% else %}Set Password{% endif %}
67
+ </button>
68
+ </div>
69
+ </form>
70
+ </div>
71
+ </div>
72
+ </div>
73
+ {% endblock %}
templates/auth/forgot_password.html ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Forgot Password - PyRunner{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="min-h-[calc(100vh-12rem)] flex items-center justify-center px-4 py-12">
7
+ <div class="w-full max-w-md">
8
+ <div class="text-center mb-10">
9
+ <div class="w-16 h-16 bg-code-accent/20 rounded-2xl flex items-center justify-center mx-auto mb-6">
10
+ <svg class="w-8 h-8 text-code-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
11
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
12
+ </svg>
13
+ </div>
14
+ <h1 class="text-2xl font-bold text-code-text mb-2">Forgot Password</h1>
15
+ <p class="text-code-muted">Enter your email to receive a password reset link</p>
16
+ </div>
17
+
18
+ <div class="bg-code-surface border border-code-border rounded-xl p-8">
19
+ <form method="post" class="space-y-5">
20
+ {% csrf_token %}
21
+
22
+ <div>
23
+ <label for="email" class="block text-sm font-medium text-code-muted mb-2">
24
+ Email address
25
+ </label>
26
+ <input
27
+ type="email"
28
+ id="email"
29
+ name="email"
30
+ required
31
+ autocomplete="email"
32
+ autofocus
33
+ placeholder="you@example.com"
34
+ class="w-full px-4 py-3 bg-code-bg border border-code-border rounded-lg text-code-text placeholder-code-muted/50 focus:outline-none focus:ring-2 focus:ring-code-accent/50 focus:border-code-accent transition-all"
35
+ >
36
+ </div>
37
+
38
+ <button
39
+ type="submit"
40
+ class="w-full py-3 px-4 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors"
41
+ >
42
+ Send Reset Link
43
+ </button>
44
+ </form>
45
+
46
+ <div class="mt-6 text-center">
47
+ <a href="{% url 'auth:login' %}" class="text-sm text-code-muted hover:text-code-accent transition-colors">
48
+ Back to sign in
49
+ </a>
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ {% endblock %}
templates/auth/invite_invalid.html ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Invalid Invite - PyRunner{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="min-h-[calc(100vh-12rem)] flex items-center justify-center px-4 py-12">
7
+ <div class="w-full max-w-md text-center">
8
+ <div class="w-20 h-20 bg-code-red/20 rounded-full flex items-center justify-center mx-auto mb-6">
9
+ <svg class="w-10 h-10 text-code-red" fill="none" stroke="currentColor" viewBox="0 0 24 24">
10
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
11
+ </svg>
12
+ </div>
13
+
14
+ <h1 class="text-2xl font-bold text-code-text mb-4">{{ error }}</h1>
15
+
16
+ <p class="text-code-muted mb-8">
17
+ {{ message }}
18
+ </p>
19
+
20
+ <div class="bg-code-surface border border-code-border rounded-xl p-6 mb-8">
21
+ <h3 class="text-sm font-medium text-code-text mb-3">What can you do?</h3>
22
+ <ul class="text-sm text-code-muted space-y-2 text-left">
23
+ <li class="flex items-start">
24
+ <svg class="w-4 h-4 text-code-accent mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
25
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
26
+ </svg>
27
+ Ask an administrator for a new invite
28
+ </li>
29
+ <li class="flex items-start">
30
+ <svg class="w-4 h-4 text-code-accent mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
31
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
32
+ </svg>
33
+ Check if you have the correct link
34
+ </li>
35
+ <li class="flex items-start">
36
+ <svg class="w-4 h-4 text-code-accent mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
37
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
38
+ </svg>
39
+ If you already have an account, try signing in
40
+ </li>
41
+ </ul>
42
+ </div>
43
+
44
+ <a
45
+ href="{% url 'auth:login' %}"
46
+ class="inline-flex items-center text-code-accent hover:text-code-accent/80 transition-colors"
47
+ >
48
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
49
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
50
+ </svg>
51
+ Back to sign in
52
+ </a>
53
+ </div>
54
+ </div>
55
+ {% endblock %}
templates/auth/login.html ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Sign In - PyRunner{% endblock %}
4
+
5
+ {% block header %}{% endblock %}
6
+ {% block footer %}{% endblock %}
7
+
8
+ {% block content %}
9
+ <div class="min-h-screen flex items-center justify-center px-4 py-12">
10
+ <div class="w-full max-w-md">
11
+ <div class="text-center mb-10">
12
+ <div class="w-16 h-16 bg-code-accent/20 rounded-2xl flex items-center justify-center mx-auto mb-6 glow-accent">
13
+ <svg class="w-8 h-8 text-code-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
14
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
15
+ </svg>
16
+ </div>
17
+ <h1 class="text-3xl font-bold gradient-text mb-6">PyRunner</h1>
18
+ </div>
19
+
20
+ <div class="bg-code-surface border border-code-border rounded-xl p-8">
21
+ <h2 class="text-xl font-semibold text-code-text mb-6 text-center">Sign In</h2>
22
+
23
+ {% if error_message %}
24
+ <div class="mb-6 p-4 bg-code-red/10 border border-code-red/30 rounded-lg">
25
+ <p class="text-sm text-code-red">{{ error_message }}</p>
26
+ </div>
27
+ {% endif %}
28
+
29
+ <!-- Password Login Form -->
30
+ <form method="post" class="space-y-5" id="password-form">
31
+ {% csrf_token %}
32
+ <input type="hidden" name="action" value="password">
33
+
34
+ <div>
35
+ <label for="id_email" class="block text-sm font-medium text-code-muted mb-2">
36
+ Email address
37
+ </label>
38
+ {{ password_form.email }}
39
+ </div>
40
+
41
+ <div>
42
+ <label for="id_password" class="block text-sm font-medium text-code-muted mb-2">
43
+ Password
44
+ </label>
45
+ {{ password_form.password }}
46
+ </div>
47
+
48
+ <button
49
+ type="submit"
50
+ class="w-full py-3 px-4 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-code-accent/50 focus:ring-offset-2 focus:ring-offset-code-surface"
51
+ >
52
+ Sign In
53
+ </button>
54
+ </form>
55
+
56
+ {% if email_enabled %}
57
+ <!-- Forgot Password Link -->
58
+ <div class="mt-4 text-center">
59
+ <a href="{% url 'auth:forgot_password' %}" class="text-sm text-code-muted hover:text-code-accent transition-colors">
60
+ Forgot your password?
61
+ </a>
62
+ </div>
63
+
64
+ <!-- Divider -->
65
+ <div class="relative my-6">
66
+ <div class="absolute inset-0 flex items-center">
67
+ <div class="w-full border-t border-code-border"></div>
68
+ </div>
69
+ <div class="relative flex justify-center text-sm">
70
+ <span class="px-4 bg-code-surface text-code-muted">or</span>
71
+ </div>
72
+ </div>
73
+
74
+ <!-- Magic Link Section -->
75
+ <div id="magic-link-section">
76
+ <button
77
+ type="button"
78
+ onclick="toggleMagicLink()"
79
+ id="magic-link-toggle"
80
+ class="w-full py-3 px-4 bg-code-bg hover:bg-code-bg/80 text-code-text border border-code-border font-medium rounded-lg transition-colors flex items-center justify-center space-x-2"
81
+ >
82
+ <svg class="w-5 h-5 text-code-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
83
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
84
+ </svg>
85
+ <span>Use Magic Link Instead</span>
86
+ </button>
87
+
88
+ <form method="post" class="hidden mt-4 space-y-4" id="magic-link-form">
89
+ {% csrf_token %}
90
+ <input type="hidden" name="action" value="magic_link">
91
+
92
+ <div>
93
+ <label for="magic_email" class="block text-sm font-medium text-code-muted mb-2">
94
+ Email address
95
+ </label>
96
+ <input
97
+ type="email"
98
+ id="magic_email"
99
+ name="magic_email"
100
+ required
101
+ autocomplete="email"
102
+ placeholder="you@example.com"
103
+ class="w-full px-4 py-3 bg-code-bg border border-code-border rounded-lg text-code-text placeholder-code-muted/50 focus:outline-none focus:ring-2 focus:ring-code-accent/50 focus:border-code-accent transition-all"
104
+ >
105
+ </div>
106
+
107
+ <button
108
+ type="submit"
109
+ class="w-full py-3 px-4 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors"
110
+ >
111
+ Send Magic Link
112
+ </button>
113
+
114
+ <button
115
+ type="button"
116
+ onclick="toggleMagicLink()"
117
+ class="w-full py-2 text-sm text-code-muted hover:text-code-text transition-colors"
118
+ >
119
+ Back to password login
120
+ </button>
121
+ </form>
122
+ </div>
123
+ {% endif %}
124
+ </div>
125
+ </div>
126
+ </div>
127
+
128
+ <script>
129
+ function toggleMagicLink() {
130
+ const toggle = document.getElementById('magic-link-toggle');
131
+ const form = document.getElementById('magic-link-form');
132
+ const passwordForm = document.getElementById('password-form');
133
+
134
+ if (form.classList.contains('hidden')) {
135
+ form.classList.remove('hidden');
136
+ toggle.classList.add('hidden');
137
+ passwordForm.classList.add('hidden');
138
+ } else {
139
+ form.classList.add('hidden');
140
+ toggle.classList.remove('hidden');
141
+ passwordForm.classList.remove('hidden');
142
+ }
143
+ }
144
+ </script>
145
+ {% endblock %}
templates/auth/magic_link_sent.html ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}{% if show_magic_link %}Sign In{% else %}Check Your Email{% endif %} - PyRunner{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="min-h-[calc(100vh-12rem)] flex items-center justify-center px-4 py-12">
7
+ <div class="w-full max-w-md text-center">
8
+ {% if show_magic_link %}
9
+ <!-- Email not configured - show magic link with security warning -->
10
+ <div class="w-20 h-20 bg-red-500/20 rounded-full flex items-center justify-center mx-auto mb-6">
11
+ <svg class="w-10 h-10 text-red-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
12
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
13
+ </svg>
14
+ </div>
15
+
16
+ <h1 class="text-2xl font-bold text-code-text mb-4">Your Sign-In Link</h1>
17
+
18
+ <!-- Security Warning -->
19
+ <div class="bg-red-500/10 border border-red-500/30 rounded-xl p-5 mb-6 text-left">
20
+ <div class="flex items-start gap-3 mb-3">
21
+ <svg class="w-5 h-5 text-red-400 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
22
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
23
+ </svg>
24
+ <div>
25
+ <h3 class="text-red-400 font-semibold text-sm">Security Warning: Email Not Configured</h3>
26
+ <p class="text-xs text-code-muted mt-1">
27
+ Sign-in links are displayed on-screen because email is disabled.
28
+ <strong class="text-red-300">Anyone who sees this screen can sign in.</strong>
29
+ </p>
30
+ </div>
31
+ </div>
32
+ <p class="text-xs text-red-300/80 ml-8">
33
+ Configure SMTP in Settings → Email Notifications to send links securely.
34
+ </p>
35
+ </div>
36
+
37
+ <!-- Sign In Button and Link -->
38
+ <div class="bg-code-surface border border-code-border rounded-xl p-6 mb-6">
39
+ <a href="{{ magic_link_url }}"
40
+ class="block w-full py-3 px-4 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors text-center mb-4">
41
+ Sign In Now
42
+ </a>
43
+
44
+ <div class="relative">
45
+ <input type="text"
46
+ value="{{ magic_link_url }}"
47
+ readonly
48
+ id="magic-link-input"
49
+ class="w-full px-4 py-3 pr-20 bg-code-bg border border-code-border rounded-lg text-code-text font-mono text-xs">
50
+ <button onclick="copyMagicLink()"
51
+ id="copy-btn"
52
+ class="absolute right-2 top-1/2 -translate-y-1/2 px-3 py-1.5 bg-code-surface border border-code-border rounded text-code-muted text-sm hover:text-code-text hover:bg-code-border transition-colors">
53
+ Copy
54
+ </button>
55
+ </div>
56
+
57
+ <p class="text-xs text-code-muted mt-3 text-center">
58
+ Expires in 15 minutes. One-time use only.
59
+ </p>
60
+ </div>
61
+
62
+ <script>
63
+ function copyMagicLink() {
64
+ const input = document.getElementById('magic-link-input');
65
+ const btn = document.getElementById('copy-btn');
66
+ navigator.clipboard.writeText(input.value).then(() => {
67
+ btn.textContent = 'Copied!';
68
+ btn.classList.add('text-code-green');
69
+ setTimeout(() => {
70
+ btn.textContent = 'Copy';
71
+ btn.classList.remove('text-code-green');
72
+ }, 2000);
73
+ });
74
+ }
75
+ </script>
76
+
77
+ {% else %}
78
+ <!-- Email configured - show check email message -->
79
+ <div class="w-20 h-20 bg-code-green/20 rounded-full flex items-center justify-center mx-auto mb-6">
80
+ <svg class="w-10 h-10 text-code-green" fill="none" stroke="currentColor" viewBox="0 0 24 24">
81
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
82
+ </svg>
83
+ </div>
84
+
85
+ <h1 class="text-2xl font-bold text-code-text mb-4">Check your email</h1>
86
+
87
+ <p class="text-code-muted mb-8">
88
+ We've sent you a magic link to sign in. Click the link in your email to continue.
89
+ </p>
90
+
91
+ <div class="bg-code-surface border border-code-border rounded-xl p-6 mb-8">
92
+ <h3 class="text-sm font-medium text-code-text mb-3">Didn't receive the email?</h3>
93
+ <ul class="text-sm text-code-muted space-y-2 text-left">
94
+ <li class="flex items-start">
95
+ <svg class="w-4 h-4 text-code-accent mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
96
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
97
+ </svg>
98
+ Check your spam or junk folder
99
+ </li>
100
+ <li class="flex items-start">
101
+ <svg class="w-4 h-4 text-code-accent mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
102
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
103
+ </svg>
104
+ Make sure you entered the correct email
105
+ </li>
106
+ <li class="flex items-start">
107
+ <svg class="w-4 h-4 text-code-accent mr-2 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
108
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
109
+ </svg>
110
+ The link expires in 15 minutes
111
+ </li>
112
+ </ul>
113
+ </div>
114
+ {% endif %}
115
+
116
+ <a
117
+ href="{% url 'auth:login' %}"
118
+ class="inline-flex items-center text-code-accent hover:text-code-accent/80 transition-colors"
119
+ >
120
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
121
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
122
+ </svg>
123
+ Back to sign in
124
+ </a>
125
+ </div>
126
+ </div>
127
+ {% endblock %}
templates/auth/reset_password.html ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Reset Password - PyRunner{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="min-h-[calc(100vh-12rem)] flex items-center justify-center px-4 py-12">
7
+ <div class="w-full max-w-md">
8
+ <div class="text-center mb-10">
9
+ <div class="w-16 h-16 bg-code-accent/20 rounded-2xl flex items-center justify-center mx-auto mb-6">
10
+ <svg class="w-8 h-8 text-code-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
11
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
12
+ </svg>
13
+ </div>
14
+ <h1 class="text-2xl font-bold text-code-text mb-2">Reset Password</h1>
15
+ <p class="text-code-muted">Enter your new password</p>
16
+ </div>
17
+
18
+ <div class="bg-code-surface border border-code-border rounded-xl p-8">
19
+ {% if error %}
20
+ <!-- Error State -->
21
+ <div class="text-center">
22
+ <div class="w-16 h-16 bg-code-red/20 rounded-full flex items-center justify-center mx-auto mb-6">
23
+ <svg class="w-8 h-8 text-code-red" fill="none" stroke="currentColor" viewBox="0 0 24 24">
24
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
25
+ </svg>
26
+ </div>
27
+ <h2 class="text-xl font-semibold text-code-text mb-2">{{ error }}</h2>
28
+ <p class="text-code-muted mb-6">{{ message }}</p>
29
+ <a href="{% url 'auth:forgot_password' %}" class="inline-block py-3 px-6 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors">
30
+ Request New Link
31
+ </a>
32
+ </div>
33
+ {% else %}
34
+ <!-- Reset Form -->
35
+ {% if form.errors %}
36
+ <div class="mb-6 p-4 bg-code-red/10 border border-code-red/30 rounded-lg">
37
+ {% for error in form.non_field_errors %}
38
+ <p class="text-sm text-code-red">{{ error }}</p>
39
+ {% endfor %}
40
+ </div>
41
+ {% endif %}
42
+
43
+ <form method="post" class="space-y-5">
44
+ {% csrf_token %}
45
+
46
+ <div>
47
+ <label for="id_password" class="block text-sm font-medium text-code-muted mb-2">
48
+ New Password
49
+ </label>
50
+ {{ form.password }}
51
+ {% if form.password.help_text %}
52
+ <p class="mt-1 text-xs text-code-muted">{{ form.password.help_text }}</p>
53
+ {% endif %}
54
+ {% if form.password.errors %}
55
+ <p class="mt-1 text-xs text-code-red">{{ form.password.errors.0 }}</p>
56
+ {% endif %}
57
+ </div>
58
+
59
+ <div>
60
+ <label for="id_password_confirm" class="block text-sm font-medium text-code-muted mb-2">
61
+ Confirm Password
62
+ </label>
63
+ {{ form.password_confirm }}
64
+ {% if form.password_confirm.errors %}
65
+ <p class="mt-1 text-xs text-code-red">{{ form.password_confirm.errors.0 }}</p>
66
+ {% endif %}
67
+ </div>
68
+
69
+ <button
70
+ type="submit"
71
+ class="w-full py-3 px-4 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors"
72
+ >
73
+ Reset Password
74
+ </button>
75
+ </form>
76
+ {% endif %}
77
+ </div>
78
+ </div>
79
+ </div>
80
+ {% endblock %}
templates/auth/verify.html ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}{{ error }} - PyRunner{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="min-h-[calc(100vh-12rem)] flex items-center justify-center px-4 py-12">
7
+ <div class="w-full max-w-md text-center">
8
+ <div class="w-20 h-20 bg-code-red/20 rounded-full flex items-center justify-center mx-auto mb-6">
9
+ <svg class="w-10 h-10 text-code-red" fill="none" stroke="currentColor" viewBox="0 0 24 24">
10
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
11
+ </svg>
12
+ </div>
13
+
14
+ <h1 class="text-2xl font-bold text-code-text mb-4">{{ error }}</h1>
15
+
16
+ <p class="text-code-muted mb-8">{{ message }}</p>
17
+
18
+ <a
19
+ href="{% url 'auth:login' %}"
20
+ class="inline-flex items-center justify-center w-full py-3 px-4 bg-code-accent hover:bg-code-accent/90 text-white font-semibold rounded-lg transition-colors"
21
+ >
22
+ Request a new link
23
+ </a>
24
+ </div>
25
+ </div>
26
+ {% endblock %}