Skip to content

Commit ab99854

Browse files
authored
Fixed auth status (#48)
* Fixed auth status * Added unused functions * Fixed linting error * Re-apply code changes
1 parent 7e050ea commit ab99854

File tree

9 files changed

+67
-79
lines changed

9 files changed

+67
-79
lines changed

backend/accounts/serializers.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from rest_framework import serializers
44
from rest_framework.validators import UniqueValidator
55

6+
from orders.serializers import DonationOrderSerializer
7+
68

79
class UserSerializer(serializers.ModelSerializer):
810
email = serializers.EmailField(
@@ -23,6 +25,8 @@ class UserSerializer(serializers.ModelSerializer):
2325
total_donations = serializers.FloatField(read_only=True)
2426
total_dividends = serializers.FloatField(read_only=True)
2527

28+
donations = DonationOrderSerializer(read_only=True, many=True)
29+
2630
class Meta:
2731
model = get_user_model()
2832
fields = [
@@ -36,6 +40,7 @@ class Meta:
3640
"password2",
3741
"total_donations",
3842
"total_dividends",
43+
"donations",
3944
]
4045

4146
def validate(self, attrs):
@@ -51,7 +56,7 @@ def validate(self, attrs):
5156
# Update sanitized phone number in attrs
5257
attrs["phone_number"] = phone_number
5358

54-
if(
59+
if (
5560
not attrs.get("phone_number").isdigit()
5661
or len(attrs.get("phone_number")) < 10
5762
):

backend/orders/admin.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from django.contrib import admin
2+
from .models import DonationOrder
3+
4+
5+
@admin.register(DonationOrder)
6+
class DonationOrderAdmin(admin.ModelAdmin):
7+
pass

backend/orders/serializers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
from rest_framework import serializers
22
from .models import DonationOrder
33

4+
45
class DonationOrderSerializer(serializers.HyperlinkedModelSerializer):
6+
stripe_transaction_id = serializers.CharField(write_only=True)
7+
58
class Meta:
69
model = DonationOrder
7-
fields = ("donation_total", "account", "time", "status", "stripe_transaction_id")
10+
fields = ("amount", "date", "status", "stripe_transaction_id")

backend/orders/urls.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,10 @@
2222

2323

2424
router = DefaultRouter()
25-
router.register(r'order', DonationViewSet, basename='donation')
25+
router.register(r"order", DonationViewSet, basename="donation")
2626

2727
urlpatterns = [
28-
path('', include(router.urls)),
29-
path(
30-
"user-donations/",
31-
DonationViewSet.as_view({"get": "get_account_donations"}),
32-
name="user-donations",
33-
),
28+
path("", include(router.urls)),
3429
path(
3530
"total-donations/",
3631
DonationViewSet.as_view({"get": "get_total_donations"}),

backend/orders/views.py

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -38,32 +38,17 @@ def get_queryset(self):
3838
else:
3939
return user.donations.all()
4040

41-
@action(detail=False, methods=["get"], url_path="total", permission_classes=[AllowAny])
41+
@action(
42+
detail=False, methods=["get"], url_path="total", permission_classes=[AllowAny]
43+
)
4244
def get_total_donations(self, request) -> float:
4345
"""This method will return the total value of all donations
4446
4547
Example call: http://127.0.0.1:8000/order/total-donations/"""
46-
total_donations = self.filter_queryset(DonationOrder.objects.all()).aggregate(
47-
total=Sum("amount")
48-
)["total"] or 0
48+
total_donations = (
49+
self.filter_queryset(DonationOrder.objects.all()).aggregate(
50+
total=Sum("amount")
51+
)["total"]
52+
or 0
53+
)
4954
return Response({"donation_total": total_donations}, status=200)
50-
51-
52-
def get_account_donations(self, request):
53-
"""This method will return a 2-dimensional list of all the donations
54-
made by a user. The first row will be the donation amount and the second
55-
row will be the date of the donation"""
56-
57-
donation_amounts = []
58-
donation_dates = []
59-
60-
donations = self.filter_queryset(self.get_queryset().filter(account=request.user))
61-
62-
for donation in donations:
63-
donation_amounts.append(donation.amount)
64-
donation_dates.append(donation.date)
65-
donation_list = [donation_amounts, donation_dates]
66-
# donation_list = [
67-
# [donation.amount, donation.date] for donation in donations
68-
# ]
69-
return Response({"donations_list": donation_list}, status=200)

webapp/src/components/navbar.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import { isLoggedIn } from '@/util/request';
66

77
const NavBar: React.FC = () => {
88
const [menuOpen, setMenuOpen] = useState(false);
9-
const [cookie,,removeCookie] = useCookies(["token"]);
9+
const [cookie, , removeCookie] = useCookies(["token", "refresh"]);
1010
const [loggedIn, setIsLoggedIn] = useState<boolean>(false);
11-
useMemo(()=>{
12-
isLoggedIn().then(()=>setIsLoggedIn(true)).catch(()=>setIsLoggedIn(false));
13-
},[cookie]);
11+
useMemo(() => {
12+
isLoggedIn().then(() => setIsLoggedIn(true)).catch(() => setIsLoggedIn(false));
13+
}, [cookie]);
1414

1515
return (
1616
<header className="flex shadow-lg py-4 px-4 sm:px-10 bg-white font-[sans-serif] min-h-[70px] tracking-wide relative z-50">
@@ -63,15 +63,15 @@ const NavBar: React.FC = () => {
6363
{/* Right Side Buttons */}
6464
<div className="flex items-center ml-auto space-x-6">
6565
{loggedIn ?
66-
<button className="text-[#007bff] hover:underline" onClick={()=>removeCookie("token")}>Logout</button>:
67-
<>
68-
<button className='.btn-primary'>
69-
<Link href="/login" className="text-[#007bff] hover:underline">Login</Link>
70-
</button>
71-
<button className="px-4 py-2 btn-login">
72-
<Link href="/register">Sign up</Link>
73-
</button>
74-
</>
66+
<button className="text-[#007bff] hover:underline" onClick={() => { removeCookie("token"); removeCookie("refresh"); }}>Logout</button> :
67+
<>
68+
<button className='.btn-primary'>
69+
<Link href="/login" className="text-[#007bff] hover:underline">Login</Link>
70+
</button>
71+
<button className="px-4 py-2 btn-login">
72+
<Link href="/register">Sign up</Link>
73+
</button>
74+
</>
7575
}
7676

7777
{/* Mobile Menu Toggle Button */}

webapp/src/pages/account.tsx

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
import { JSX, useEffect, useState } from "react";
22
import PieChart from "@/components/pie-chart";
3-
import { AccountType, getAccountInfo, DonationsListType, getUserDonations } from "@/util/request";
3+
import { AccountType, getAccountInfo, isLoggedIn } from "@/util/request";
44
import { useRouter } from "next/navigation";
5+
import { useCookies } from "react-cookie";
56

67

78
const Account = (): JSX.Element => {
89
const router = useRouter();
910
const [accountInfo, setAccountInfo] = useState<AccountType>();
11+
const [cookie] = useCookies(["token"])
1012
useEffect(() => {
11-
getAccountInfo().then((response) => setAccountInfo(response.data)).catch(() =>
12-
router.push("login"))
13-
}, []);
14-
15-
16-
17-
const [donations, setDonations] = useState<DonationsListType>();
18-
useEffect(() => {
19-
getUserDonations().then((response) => setDonations(response.data));
20-
}, []);
13+
isLoggedIn().then(() =>
14+
getAccountInfo().then((response) => setAccountInfo(response.data)).catch(() => router.push("login"))
15+
).catch(
16+
() => router.push("login")
17+
);
18+
}, [cookie]);
2119

2220
// Variables are hard coded for now to demo until backend is implemented.
2321
// const stocks_owned = ["Stock 1", "Stock 2", "Stock 3", "Stock 4", "Stock 5", "Stock 6", "Stock 7"];
@@ -54,15 +52,15 @@ const Account = (): JSX.Element => {
5452
{/* Stocks owned */}
5553
<div className="bg-gray-300 p-2 rounded-md">
5654
<h3 className="text-lg font-bold">Donations:</h3>
57-
<p>Total Donations: {accountInfo?.total_donations?.toLocaleString('en-US', { style: 'currency', currency: 'CAD' })}</p>
55+
<p>Total Donations: {accountInfo?.total_donations?.toLocaleString('en-US', { style: 'currency', currency: 'CAD' })}</p>
5856
<br></br>
59-
{donations?.donations_list?.[0]?.map((donation, index) => (
57+
{accountInfo?.donations.map((donation, index) => (
6058
<p key={index}>
61-
{donation.toLocaleString('en-US', { style: 'currency', currency: 'CAD' })} on {new Date(donations?.donations_list?.[1]?.[index]).toLocaleDateString('en-US')}
59+
{donation.amount.toLocaleString('en-US', { style: 'currency', currency: 'CAD' })} on {new Date(donation.date).toLocaleDateString('en-US')}
6260
</p>
6361
))}
6462

65-
63+
6664

6765
</div>
6866

webapp/src/pages/login.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ const LoginPage: () => JSX.Element = () => {
2323
setMessage("");
2424
sendLogin({ email, password })
2525
.then((response) => {
26-
console.log(response);
2726
setCookie("token", response.data.access, { maxAge: 86400, path: "/" });
2827
setCookie("refresh", response.data.refresh, { path: "/" });
2928
router.push("account");
@@ -72,7 +71,7 @@ const LoginPage: () => JSX.Element = () => {
7271
<Link href="/register" className="text-[#007bff] hover:underline">Register</Link>
7372
<div className="field mt-5">
7473
<div className="btn-primary h-10 flex items-center justify-center">
75-
<input className="button" type="submit" value="Login" disabled={disabled}/>
74+
<input className="button" type="submit" value="Login" disabled={disabled} />
7675
</div>
7776
</div>
7877
</form>

webapp/src/util/request.tsx

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,25 @@ backendConfig.interceptors.request.use((config) => {
2121
const refreshToken: () => Promise<void> = () => {
2222
const refresh_cookie = Cookie.get("refresh");
2323
if (refresh_cookie) {
24-
return backendConfig.post("login/refresh/", { "refresh": refresh_cookie }).then((refresh_response) => {
24+
return backendConfig.post("login/refresh/", { "refresh": refresh_cookie }).then(refresh_response => {
2525
Cookie.set("token", refresh_response.data.access);
2626
return Promise.resolve();
2727
}).catch((refresh_error) => {
28-
console.log(refresh_error);
29-
Cookie.remove("token")
30-
return Promise.reject();
28+
Cookie.remove("token");
29+
Cookie.remove("refresh");
30+
return Promise.reject(refresh_error);
3131
});
3232
}
3333
return Promise.reject();
3434
}
3535

3636
/* Auto refresh token */
37-
backendConfig.interceptors.response.use(response => response, async (error) => {
38-
if (error.response.status == 401 && !error.config?._refresh_retry) {
37+
backendConfig.interceptors.response.use(response => response, error => {
38+
if (error.response.status === 401 && !error.config?._refresh_retry && error.config.url !== "login/refresh/") {
3939
error.config._refresh_retry = true;
40-
console.log("Try refresh")
4140
return refreshToken().then(() => backendConfig(error.config)).catch(() => error);
4241
}
43-
return error
42+
return Promise.reject(error);
4443
})
4544

4645
export const isLoggedIn: () => Promise<void> = async () => {
@@ -93,12 +92,11 @@ export type AccountType = {
9392
is_active: boolean;
9493
total_dividends: number;
9594
total_donations: number;
96-
};
97-
98-
export type DonationsListType = {
99-
// amount: Array<number>;
100-
// date: Array<Date>;
101-
donations_list: Array<[number, Date]>;
95+
donations: {
96+
amount: number;
97+
date: string;
98+
status: string;
99+
}[];
102100
};
103101

104102
export type CharityType = {
@@ -140,8 +138,6 @@ export const sendCharity: (data: CharityFormData) =>
140138

141139
export const getAccountInfo: () => Promise<AxiosResponse<AccountType>> = () => backendConfig.get("account/");
142140

143-
export const getUserDonations: () => Promise<AxiosResponse<DonationsListType>> = () => backendConfig.get("user-donations/");
144-
145141
export const getCharities: () => Promise<AxiosResponse<CharityType[]>> = () => backendConfig.get("charity/");
146142

147143
export const setCharityApproved: (id: number, approved: boolean) => Promise<AxiosResponse<CharityType>> = (id: number, approved: boolean) => backendConfig.patch(`charity/${id}/`, { "is_approved": approved })

0 commit comments

Comments
 (0)