Merge branch 'master' into 'production'

Merge 'master' into production

See merge request sahkoinsinoorikilta/vtmk/web2.0-frontend!107
This commit is contained in:
Ilari Ojakorpi
2022-07-06 20:01:54 +00:00
10 changed files with 107 additions and 49 deletions
+15 -4
View File
@@ -1,8 +1,16 @@
import React, { useState, useEffect } from "react";
import React, {
useState,
useEffect,
} from "react";
import { NextPage } from "next";
import { useRouter } from "next/router";
import styled from "styled-components";
import { generateToken, setTokenCookie, isAuthenticated } from "@utils/auth";
import {
generateToken,
setAccessTokenCookie,
setRefreshTokenCookie,
isAuthenticated,
} from "@utils/auth";
import AdminPageWrapper from "@views/common/AdminPageWrapper";
const Main = styled.div`
@@ -30,8 +38,11 @@ const AdminLoginPage: NextPage = () => {
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
try {
const token = await generateToken(username, password);
setTokenCookie(token);
const { access, refresh } = await generateToken(username, password);
setAccessTokenCookie(access);
setRefreshTokenCookie(refresh);
router.push(next);
} catch (err) {
setError("Failed to log in!");
+2 -2
View File
@@ -1,12 +1,12 @@
import { NextPage } from "next";
import { useRouter } from "next/router";
import { deleteTokenCookie } from "@utils/auth";
import { deleteTokenCookies } from "@utils/auth";
const AdminLogoutPage: NextPage = () => {
const router = useRouter();
// client-side-only code
if (typeof window !== "undefined") {
deleteTokenCookie();
deleteTokenCookies();
router.push("/admin/login");
}
return null;
+52 -18
View File
@@ -1,46 +1,80 @@
import axios from "axios";
import Cookies from "js-cookie";
const tokenUrl = `${process.env.NEXT_PUBLIC_API_URL}/api-token-auth/`;
const checkUrl = `${process.env.NEXT_PUBLIC_API_URL}/api-token-verify/`;
const tokenUrl = `${process.env.NEXT_PUBLIC_API_URL}/token/`;
const checkUrl = `${process.env.NEXT_PUBLIC_API_URL}/token/verify/`;
const refreshUrl = `${process.env.NEXT_PUBLIC_API_URL}/token/refresh/`;
export async function generateToken(username: string, password: string): Promise<string> {
export async function generateToken(username: string, password: string): Promise<{"access":string, "refresh":string}> {
const resp = await axios.post(tokenUrl, {
username,
password,
});
return resp.data.token;
return {
"access": resp.data.access,
"refresh": resp.data.refresh,
};
}
export function setTokenCookie(token: string): void {
Cookies.set("jwt", token);
Cookies.set("jwt", token, { domain: ".sahkoinsinoorikilta.fi" });
export function setAccessTokenCookie(access_token: string): void {
Cookies.set("jwt_access", access_token);
Cookies.set("jwt_access", access_token, { domain: ".sahkoinsinoorikilta.fi" });
}
export function getTokenCookie(): string {
return Cookies.get("jwt");
export function setRefreshTokenCookie(refresh_token: string): void {
Cookies.set("jwt_refresh", refresh_token);
Cookies.set("jwt_refresh", refresh_token, { domain: ".sahkoinsinoorikilta.fi" });
}
export function deleteTokenCookie(): void {
Cookies.remove("jwt", { domain: ".sahkoinsinoorikilta.fi" });
Cookies.remove("jwt");
export function getAccessTokenCookie(): string {
return Cookies.get("jwt_access");
}
export function getRefreshTokenCookie(): string {
return Cookies.get("jwt_refresh");
}
export function deleteTokenCookies(): void {
Cookies.remove("jwt_access", { domain: ".sahkoinsinoorikilta.fi" });
Cookies.remove("jwt_access");
Cookies.remove("jwt_refresh", { domain: ".sahkoinsinoorikilta.fi" });
Cookies.remove("jwt_refresh");
}
export async function isAuthenticated(): Promise<boolean> {
try {
const token = getTokenCookie();
await axios.post(checkUrl, {
const token = getAccessTokenCookie();
await axios.post(checkUrl, {
token,
});
return true;
} catch (err) {
// remove the cookie since it's invalid
deleteTokenCookie();
return refreshToken();
}
}
export async function refreshToken(): Promise<boolean> {
try {
const refresh = getRefreshTokenCookie();
if (refresh) {
const resp = await axios.post(refreshUrl, {
refresh,
});
setAccessTokenCookie(resp.data.access);
return true;
}
return false;
} catch (err) {
deleteTokenCookies();
return false;
}
}
export function getAuthHeader(): string {
const jwt = getTokenCookie();
return `JWT ${jwt}`;
const jwt_access = getAccessTokenCookie();
return `Bearer ${jwt_access}`;
}
@@ -11,6 +11,12 @@ const FreshmenPageHero: React.FC = () => (
/>
<HeroAside bgColor="lightTurquoise">
<HeroAsideItem
header="Lue killan fuksiopas"
link="https://static.sahkoinsinoorikilta.fi/FTMK/Fuksiopas2022.pdf"
linkText="lue fuksiopas täältä!"
/>
<HeroAsideItem
header="Seuraa killan tiedotusta"
link="https://t.me/joinchat/rKg3rCtAVkkyNTdk"
+7 -1
View File
@@ -103,8 +103,14 @@ const FreshmenPageView: React.FC = () => (
<div>
<InfoBox>
<h6>Killan Fuksiopas</h6>
<Link to="https://static.sahkoinsinoorikilta.fi/FTMK/Fuksiopas2022.pdf" target="_blank">
<FopasImage
src="https://static.sahkoinsinoorikilta.fi/FTMK/Fuksiopas2022-kansi.jpg"
/>
</Link>
<p>
Ennen opintojen alkua on hyvä tutustua killan fuksioppaaseen. Tulette saamaan sen postitse ja se linkataan tähän heti kun se on julkaistu
Ennen opintojen alkua on hyvä tutustua killan fuksioppaaseen. Sitä pääset selailemaan <Link to="https://static.sahkoinsinoorikilta.fi/FTMK/Fuksiopas2022.pdf" target="_blank"> tästä.</Link>
</p>
<br />
<h6>Telegram?</h6>
+3 -3
View File
@@ -1,6 +1,6 @@
import { Selector } from "testcafe";
import {
getSiteRoot, getPageUrl, generateTestForm, deleteEvent, deleteForm, doLogin, generateToken, getPostRequestLogger,
getSiteRoot, getPageUrl, generateTestForm, deleteEvent, deleteForm, doLogin, generateAccessToken, getPostRequestLogger,
} from "../utils";
const LOGGER = getPostRequestLogger("events/");
@@ -8,12 +8,12 @@ const LOGGER = getPostRequestLogger("events/");
fixture`Admin events`.page(`${getSiteRoot()}/admin/events`)
.requestHooks(LOGGER)
.before(async (ctx) => {
const token = await generateToken();
const token = await generateAccessToken();
const form = await generateTestForm(token);
ctx.formId = form.id;
})
.after(async (ctx) => {
const token = await generateToken();
const token = await generateAccessToken();
await deleteEvent(ctx.eventId, token);
await deleteForm(ctx.formId, token);
});
+3 -2
View File
@@ -1,6 +1,6 @@
import { Selector } from "testcafe";
import {
getSiteRoot, getPageUrl, deleteForm, doLogin, generateToken, getPostRequestLogger,
getSiteRoot, getPageUrl, deleteForm, doLogin, generateAccessToken, getPostRequestLogger,
} from "../utils";
const LOGGER = getPostRequestLogger("signupForm/");
@@ -8,7 +8,8 @@ const LOGGER = getPostRequestLogger("signupForm/");
fixture`Admin signup form`.page(`${getSiteRoot()}/admin/signups`)
.requestHooks(LOGGER)
.after(async (ctx) => {
const token = await generateToken();
const token = await generateAccessToken();
await deleteForm(ctx.formId, token);
});
+1 -1
View File
@@ -39,7 +39,7 @@ test("User is redirected to login when JWT token is invalid", async (t) => {
* Test if the user is redirected to login when JWT token is invalid.
*/
const setCookie = ClientFunction(() => {
document.cookie = "jwt=FOOBAR";
document.cookie = "jwt_access=FOOBAR";
});
await setCookie();
await t.navigateTo("/admin/events");
+3 -3
View File
@@ -1,18 +1,18 @@
import { Selector } from "testcafe";
import {
getSiteRoot, getPageUrl, generateTestEvent, generateTestForm, deleteEvent, deleteForm, generateToken,
getSiteRoot, getPageUrl, generateTestEvent, generateTestForm, deleteEvent, deleteForm, generateAccessToken,
} from "./utils";
fixture`Event signup`.page(getSiteRoot())
.before(async (ctx) => {
const token = await generateToken();
const token = await generateAccessToken();
const form = await generateTestForm(token);
const event = await generateTestEvent([form.id], token);
ctx.eventId = event.id;
ctx.formId = form.id;
})
.after(async (ctx) => {
const token = await generateToken();
const token = await generateAccessToken();
await deleteEvent(ctx.eventId, token);
await deleteForm(ctx.formId, token);
});
+15 -15
View File
@@ -26,15 +26,15 @@ export const doLogin = async (t: TestController) => {
await t.click(Selector("#login-submit"));
};
export async function generateToken(): Promise<string> {
const tokenUrl = `${API_URL}/api-token-auth/`;
export async function generateAccessToken(): Promise<string> {
const tokenUrl = `${API_URL}/token/`;
try {
const resp = await axios.post(tokenUrl, {
username: USERNAME,
password: PASSWORD,
});
return resp.data.token;
return resp.data.access;
} catch (err) {
console.error(err);
throw err;
@@ -43,11 +43,11 @@ export async function generateToken(): Promise<string> {
const eventURL = `${API_URL}/events/`;
export async function createEvent(data, jwt: string) {
export async function createEvent(data, jwt_access: string) {
try {
const resp = await axios.post(eventURL, data, {
headers: {
Authorization: `JWT ${jwt}`,
Authorization: `Bearer ${jwt_access}`,
},
});
return resp.data;
@@ -57,11 +57,11 @@ export async function createEvent(data, jwt: string) {
}
}
export async function deleteEvent(id: string, jwt: string) {
export async function deleteEvent(id: string, jwt_access: string) {
try {
const resp = await axios.delete(`${eventURL}${id}/`, {
headers: {
Authorization: `JWT ${jwt}`,
Authorization: `Bearer ${jwt_access}`,
},
});
return resp.data;
@@ -73,11 +73,11 @@ export async function deleteEvent(id: string, jwt: string) {
const formURL = `${API_URL}/signupForm/`;
export async function createForm(data, jwt: string) {
export async function createForm(data, jwt_access: string) {
try {
const resp = await axios.post(formURL, data, {
headers: {
Authorization: `JWT ${jwt}`,
Authorization: `Bearer ${jwt_access}`,
},
});
return resp.data;
@@ -87,11 +87,11 @@ export async function createForm(data, jwt: string) {
}
}
export async function deleteForm(id: string, jwt: string) {
export async function deleteForm(id: string, jwt_access: string) {
try {
const resp = await axios.delete(`${formURL}${id}/`, {
headers: {
Authorization: `JWT ${jwt}`,
Authorization: `Bearer ${jwt_access}`,
},
});
return resp.data;
@@ -101,7 +101,7 @@ export async function deleteForm(id: string, jwt: string) {
}
}
export const generateTestForm = async (jwt: string) => (
export const generateTestForm = async (jwt_access: string) => (
createForm({
title_fi: "Testi Ilmo",
title_en: "Test Signup",
@@ -132,10 +132,10 @@ export const generateTestForm = async (jwt: string) => (
},
},
},
}, jwt)
}, jwt_access)
);
export const generateTestEvent = async (formIds = [], jwt: string) => (
export const generateTestEvent = async (formIds = [], jwt_access: string) => (
createEvent({
tags: [1],
visible: true,
@@ -153,7 +153,7 @@ export const generateTestEvent = async (formIds = [], jwt: string) => (
signupForm: formIds,
signup_id: formIds,
tag_id: [1],
}, jwt)
}, jwt_access)
);
export const sleep = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));