• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gcivil-nyu-org / fall24-monday-team3 / 271

13 Dec 2024 12:03AM UTC coverage: 74.578% (-0.3%) from 74.837%
271

push

travis-pro

ivarfan
Deleted unused imported packages

1370 of 1837 relevant lines covered (74.58%)

0.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.34
/users/views.py
1
from django.shortcuts import render, redirect, get_object_or_404
1✔
2
from django.contrib.auth import login, authenticate, get_user_model
1✔
3
from .forms import SignUpForm
1✔
4
from django.contrib.auth.forms import AuthenticationForm
1✔
5
from django.contrib import messages
1✔
6
from django.contrib.auth.decorators import login_required
1✔
7
from rentals.models import Favorite as RentalFavorite
1✔
8
from roommates.models import Favorite as RoommateFavorite
1✔
9
from django.http import JsonResponse
1✔
10
from django.views.decorators.http import require_POST
1✔
11
import json
1✔
12
from django.views.decorators.cache import never_cache
1✔
13
from django.views.decorators.http import require_http_methods
1✔
14
from django.views.decorators.cache import cache_control
1✔
15
from rentals.models import ApartmentPost
1✔
16
from roommates.models import RoommatePost
1✔
17
from discussions.models import Discussion
1✔
18
from django.urls import reverse
1✔
19
from django.core.mail import send_mail
1✔
20
from django.conf import settings
1✔
21
from .models import EmailVerificationToken, PendingEmailChange
1✔
22

23
User = get_user_model()
1✔
24

25

26
@never_cache
1✔
27
def signup(request):
1✔
28
    if request.method == "POST":
1✔
29
        form = SignUpForm(request.POST)
1✔
30
        if form.is_valid():
1✔
31
            # Check if email already exists
32
            email = form.cleaned_data.get("email")
1✔
33
            if User.objects.filter(email=email).exists():
1✔
34
                form.add_error("email", "This email address is already in use.")
×
35
                return render(request, "users/signup.html", {"form": form})
×
36

37
            user = form.save(commit=False)
1✔
38
            user.is_active = False
1✔
39
            user.save()
1✔
40

41
            # Create verification token
42
            token = EmailVerificationToken.objects.create(user=user)
1✔
43

44
            # Build verification URL
45
            verify_url = request.build_absolute_uri(
1✔
46
                reverse("verify_email", args=[str(token.token)])
47
            )
48

49
            # Send verification email
50
            send_mail(
1✔
51
                "Verify your RentSense account",
52
                f"Click the following link to verify your email: {verify_url}",
53
                settings.DEFAULT_FROM_EMAIL,
54
                [user.email],
55
                fail_silently=False,
56
                html_message=f"""
57
                    <h2>Welcome to RentSense!</h2>
58
                    <p>Please click the button below to verify your email address:</p>
59
                    <a href="{verify_url}" style="display: inline-block; padding: 10px 20px; background-color: #3498db; color: white; text-decoration: none; border-radius: 5px;">Verify Email</a>
60
                    <p>If the button doesn't work, copy and paste this link into your browser:</p>
61
                    <p>{verify_url}</p>
62
                """,
63
            )
64

65
            return render(
1✔
66
                request, "users/verification_pending.html", {"email": user.email}
67
            )
68
    else:
69
        form = SignUpForm()
1✔
70
    return render(request, "users/signup.html", {"form": form})
1✔
71

72

73
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
1✔
74
@never_cache
1✔
75
def login_view(request):
1✔
76
    if request.method == "POST":
1✔
77
        form = AuthenticationForm(request, data=request.POST)
1✔
78
        if form.is_valid():
1✔
79
            username = form.cleaned_data.get("username")
1✔
80
            password = form.cleaned_data.get("password")
1✔
81
            user = authenticate(username=username, password=password)
1✔
82
            if user is not None:
1✔
83
                login(request, user)
1✔
84
                return redirect("home")
1✔
85
        form.add_error(None, "Invalid username or password")
1✔
86
    else:
87
        form = AuthenticationForm()
1✔
88

89
    return render(request, "users/login.html", {"form": form})
1✔
90

91

92
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
1✔
93
def register_view(request):
1✔
94
    return render(request, "users/register.html")
×
95

96

97
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
1✔
98
def home_view(request):
1✔
99
    return render(request, "users/home.html")
1✔
100

101

102
@login_required
1✔
103
@cache_control(no_cache=True, must_revalidate=True, no_store=True)
1✔
104
def profile_view(request):
1✔
105
    rental_favorites = RentalFavorite.objects.filter(user=request.user).select_related(
1✔
106
        "post"
107
    )
108
    roommate_favorites = RoommateFavorite.objects.filter(
1✔
109
        user=request.user
110
    ).select_related("post")
111
    user_rental_posts = ApartmentPost.objects.filter(user=request.user).order_by("-id")
1✔
112
    user_roommate_posts = RoommatePost.objects.filter(user=request.user).order_by("-id")
1✔
113
    user_discussion_posts = Discussion.objects.filter(author=request.user).order_by(
1✔
114
        "-created_at"
115
    )
116

117
    context = {
1✔
118
        "rental_favorites": rental_favorites,
119
        "roommate_favorites": roommate_favorites,
120
        "user_rental_posts": user_rental_posts,
121
        "user_roommate_posts": user_roommate_posts,
122
        "user_discussion_posts": user_discussion_posts,
123
    }
124
    return render(request, "users/profile.html", context)
1✔
125

126

127
@login_required
1✔
128
@require_http_methods(["POST"])
1✔
129
def edit_profile(request):
1✔
130
    if request.method == "POST":
1✔
131
        try:
1✔
132
            data = json.loads(request.body)
1✔
133
            user = request.user
1✔
134
            email_changed = data.get("email_changed", False)
1✔
135
            new_email = data.get("email")
1✔
136

137
            # Check for duplicate email
138
            if email_changed and new_email:
1✔
139
                if User.objects.filter(email=new_email).exclude(id=user.id).exists():
1✔
140
                    return JsonResponse(
×
141
                        {"success": False, "error": "This email is already in use."}
142
                    )
143

144
            # Update user fields
145
            user.first_name = data.get("first_name", user.first_name)
1✔
146
            user.last_name = data.get("last_name", user.last_name)
1✔
147
            user.bio = data.get("bio", user.bio)
1✔
148

149
            if email_changed and new_email:
1✔
150
                # Create pending email change
151
                PendingEmailChange.objects.filter(user=user).delete()
1✔
152
                pending_change = PendingEmailChange.objects.create(
1✔
153
                    user=user, new_email=new_email
154
                )
155

156
                # Send verification email
157
                verification_url = request.build_absolute_uri(
1✔
158
                    reverse(
159
                        "verify_email_change", kwargs={"token": pending_change.token}
160
                    )
161
                )
162
                send_mail(
1✔
163
                    "Verify your new email address",
164
                    f"Please click the following link to verify your new email address: {verification_url}",
165
                    settings.DEFAULT_FROM_EMAIL,
166
                    [new_email],
167
                    fail_silently=False,
168
                )
169
                return JsonResponse(
1✔
170
                    {
171
                        "success": True,
172
                        "email_verification_required": True,
173
                        "message": "A verification email has been sent. The email change will be applied once verified.",
174
                    }
175
                )
176
            else:
177
                user.email = data.get("email", user.email)
1✔
178

179
            user.save()
1✔
180
            return JsonResponse({"success": True})
1✔
181

182
        except json.JSONDecodeError:
1✔
183
            return JsonResponse({"success": False, "error": "Invalid JSON data"})
1✔
184

185
    return render(request, "users/edit_profile.html")
×
186

187

188
@login_required
1✔
189
@require_POST
1✔
190
@never_cache
1✔
191
def delete_favorite(request, type, favorite_id):
1✔
192
    try:
×
193
        if type == "rental":
×
194
            favorite = RentalFavorite.objects.get(id=favorite_id, user=request.user)
×
195
        else:
196
            favorite = RoommateFavorite.objects.get(id=favorite_id, user=request.user)
×
197

198
        favorite.delete()
×
199
        return JsonResponse({"success": True})
×
200
    except (RentalFavorite.DoesNotExist, RoommateFavorite.DoesNotExist):
×
201
        return JsonResponse({"success": False}, status=404)
×
202

203

204
@login_required(login_url="/users/login/")
1✔
205
def public_profile(request, username):
1✔
206
    profile_user = get_object_or_404(get_user_model(), username=username)
1✔
207

208
    context = {
1✔
209
        "profile_user": profile_user,
210
        "user_rental_posts": ApartmentPost.objects.filter(user=profile_user).order_by(
211
            "-id"
212
        ),
213
        "user_roommate_posts": RoommatePost.objects.filter(user=profile_user).order_by(
214
            "-id"
215
        ),
216
        "user_discussion_posts": Discussion.objects.filter(
217
            author=profile_user
218
        ).order_by("-created_at"),
219
    }
220

221
    return render(request, "users/public_profile.html", context)
1✔
222

223

224
@login_required(login_url="/users/login/")
1✔
225
def discussion_create(request):
1✔
226
    if request.method == "POST":
×
227
        form = Discussion(request.POST)
×
228
        if form.is_valid():
×
229
            discussion = form.save(commit=False)
×
230
            discussion.author = request.user
×
231
            discussion.save()
×
232
            return redirect(
×
233
                reverse("discussions:discussion_detail", args=[discussion.pk])
234
            )
235
    else:
236
        form = Discussion()
×
237
    return render(request, "discussions/discussion_form.html", {"form": form})
×
238

239

240
@login_required
1✔
241
@require_http_methods(["POST"])
1✔
242
def send_user_email(request, username):
1✔
243
    if not request.content_type == "application/json":
1✔
244
        return JsonResponse(
×
245
            {"success": False, "error": "Content-Type must be application/json"},
246
            status=400,
247
        )
248

249
    try:
1✔
250
        data = json.loads(request.body)
1✔
251
    except json.JSONDecodeError:
1✔
252
        return JsonResponse({"success": False, "error": "Invalid JSON"}, status=400)
1✔
253

254
    try:
1✔
255
        recipient = User.objects.get(username=username)
1✔
256
    except User.DoesNotExist:
1✔
257
        return JsonResponse(
1✔
258
            {"success": False, "error": "User not found"},
259
            status=404,
260
            content_type="application/json",
261
        )
262

263
    subject = data.get("subject")
1✔
264
    message = data.get("message")
1✔
265

266
    if not subject or not message:
1✔
267
        return JsonResponse(
×
268
            {"success": False, "error": "Missing subject or message"},
269
            status=400,
270
            content_type="application/json",
271
        )
272

273
    try:
1✔
274
        send_mail(
1✔
275
            subject,
276
            message,
277
            settings.DEFAULT_FROM_EMAIL,
278
            [recipient.email],
279
            fail_silently=False,
280
        )
281
        return JsonResponse({"success": True}, content_type="application/json")
1✔
282
    except Exception as e:
×
283
        return JsonResponse(
×
284
            {"success": False, "error": str(e)},
285
            status=500,
286
            content_type="application/json",
287
        )
288

289

290
def verify_email(request, token):
1✔
291
    verification = get_object_or_404(
1✔
292
        EmailVerificationToken, token=token, is_verified=False
293
    )
294

295
    user = verification.user
1✔
296
    user.is_active = True
1✔
297
    user.save()
1✔
298

299
    verification.is_verified = True
1✔
300
    verification.save()
1✔
301

302
    messages.success(
1✔
303
        request,
304
        "Your email has been verified! You can now log in.",
305
        extra_tags="verification",
306
    )
307
    return redirect("login")
1✔
308

309

310
@login_required
1✔
311
def verify_email_change(request, token):
1✔
312
    pending_change = get_object_or_404(PendingEmailChange, token=token)
1✔
313

314
    # Update user's email
315
    user = pending_change.user
1✔
316
    user.email = pending_change.new_email
1✔
317
    user.save()
1✔
318

319
    # Delete the pending change
320
    pending_change.delete()
1✔
321

322
    messages.success(
1✔
323
        request, "Your email has been successfully updated!", extra_tags="email_change"
324
    )
325
    return redirect("profile")  # This now matches the URL name
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc