mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
feat: use subdomains for organizations
This commit is contained in:
parent
600bb96603
commit
fac6b57ab3
16 changed files with 57 additions and 60 deletions
3
app.py
3
app.py
|
|
@ -1,5 +1,6 @@
|
||||||
import logging
|
import logging
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
|
import re
|
||||||
from src.core.config.config import Settings, get_settings
|
from src.core.config.config import Settings, get_settings
|
||||||
from src.core.events.events import shutdown_app, startup_app
|
from src.core.events.events import shutdown_app, startup_app
|
||||||
from src.main import global_router
|
from src.main import global_router
|
||||||
|
|
@ -23,9 +24,11 @@ app = FastAPI(
|
||||||
root_path="/"
|
root_path="/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
origin_regex = re.compile(r"^http://[\w.-]+\.localhost:3000$")
|
||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
CORSMiddleware,
|
CORSMiddleware,
|
||||||
|
allow_origin_regex=str(origin_regex.pattern),
|
||||||
allow_origins=["http://localhost:3000", "http://localhost:3001"],
|
allow_origins=["http://localhost:3000", "http://localhost:3001"],
|
||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_credentials=True,
|
allow_credentials=True,
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,6 @@ services:
|
||||||
- "1338:80"
|
- "1338:80"
|
||||||
volumes:
|
volumes:
|
||||||
- .:/usr/learnhouse
|
- .:/usr/learnhouse
|
||||||
frontend:
|
|
||||||
build: ./front
|
|
||||||
ports:
|
|
||||||
- "3001:3000"
|
|
||||||
volumes:
|
|
||||||
- ./front:/usr/learnhouse/front
|
|
||||||
mongo:
|
mongo:
|
||||||
image: mongo:5.0
|
image: mongo:5.0
|
||||||
restart: always
|
restart: always
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ import { default as React, useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { getLecture } from "../../../../../../../../services/courses/lectures";
|
import { getLecture } from "@services/courses/lectures";
|
||||||
import AuthProvider from "../../../../../../../../components/Security/AuthProvider";
|
import AuthProvider from "@components/Security/AuthProvider";
|
||||||
import EditorWrapper from "../../../../../../../../components/Editor/EditorWrapper";
|
import EditorWrapper from "@components/Editor/EditorWrapper";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl } from "@services/config";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
1
front/app/_editor/main.ts
Normal file
1
front/app/_editor/main.ts
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export const EDITOR = "main";
|
||||||
|
|
@ -4,7 +4,7 @@ import Link from "next/link";
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import Layout from "@components/UI/Layout";
|
import Layout from "@components/UI/Layout";
|
||||||
import { getLecture } from "@services/courses/lectures";
|
import { getLecture } from "@services/courses/lectures";
|
||||||
import { getAPIUrl, getBackendUrl } from "@services/config";
|
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config";
|
||||||
import Canva from "@components/LectureViews/DynamicCanva/DynamicCanva";
|
import Canva from "@components/LectureViews/DynamicCanva/DynamicCanva";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getCourse } from "@services/courses/courses";
|
import { getCourse } from "@services/courses/courses";
|
||||||
|
|
@ -39,7 +39,7 @@ function LecturePage(params: any) {
|
||||||
<LectureLayout>
|
<LectureLayout>
|
||||||
<LectureTopWrapper>
|
<LectureTopWrapper>
|
||||||
<LectureThumbnail>
|
<LectureThumbnail>
|
||||||
<Link href={`/org/${orgslug}/course/${courseid}`}>
|
<Link href={getUriWithOrg(orgslug,"") +`/course/${courseid}`}>
|
||||||
<img src={`${getBackendUrl()}content/uploads/img/${course.course.thumbnail}`} alt="" />
|
<img src={`${getBackendUrl()}content/uploads/img/${course.course.thumbnail}`} alt="" />
|
||||||
</Link>
|
</Link>
|
||||||
</LectureThumbnail>
|
</LectureThumbnail>
|
||||||
|
|
@ -56,7 +56,7 @@ function LecturePage(params: any) {
|
||||||
{chapter.lectures.map((lecture: any) => {
|
{chapter.lectures.map((lecture: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`}>
|
<Link href={getUriWithOrg(orgslug,"") +`/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`}>
|
||||||
<ChapterIndicator key={lecture.id} />
|
<ChapterIndicator key={lecture.id} />
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { closeActivity, createActivity } from "@services/courses/activity";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { getAPIUrl, getBackendUrl } from "@services/config";
|
import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ const CourseIdPage = (params: any) => {
|
||||||
<p>Course</p>
|
<p>Course</p>
|
||||||
<h1>
|
<h1>
|
||||||
{course.course.name}{" "}
|
{course.course.name}{" "}
|
||||||
<Link href={`/org/${orgslug}/course/${courseid}/edit`} rel="noopener noreferrer">
|
<Link href={getUriWithOrg(orgslug,"") +`/course/${courseid}/edit`} rel="noopener noreferrer">
|
||||||
<Pencil2Icon />
|
<Pencil2Icon />
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
@ -56,7 +56,7 @@ const CourseIdPage = (params: any) => {
|
||||||
{chapter.lectures.map((lecture: any) => {
|
{chapter.lectures.map((lecture: any) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`}>
|
<Link href={getUriWithOrg(orgslug,"") +`/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`}>
|
||||||
<ChapterIndicator />
|
<ChapterIndicator />
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
</>
|
</>
|
||||||
|
|
@ -97,7 +97,7 @@ const CourseIdPage = (params: any) => {
|
||||||
<>
|
<>
|
||||||
<p>
|
<p>
|
||||||
Lecture {lecture.name}
|
Lecture {lecture.name}
|
||||||
<Link href={`/org/${orgslug}/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`} rel="noopener noreferrer">
|
<Link href={getUriWithOrg(orgslug,"") +`/course/${courseid}/lecture/${lecture.id.replace("lecture_", "")}`} rel="noopener noreferrer">
|
||||||
<EyeOpenIcon />
|
<EyeOpenIcon />
|
||||||
</Link>{" "}
|
</Link>{" "}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ const CoursesIndexPage = (params: any) => {
|
||||||
<button style={{ backgroundColor: "red", border: "none" }} onClick={() => deleteCourses(course.course_id)}>
|
<button style={{ backgroundColor: "red", border: "none" }} onClick={() => deleteCourses(course.course_id)}>
|
||||||
Delete <Trash size={10}></Trash>
|
Delete <Trash size={10}></Trash>
|
||||||
</button>
|
</button>
|
||||||
<Link href={"/org/" + orgslug + "/course/" + removeCoursePrefix(course.course_id)}>
|
<Link href={getUriWithOrg(orgslug,"") + "/course/" + removeCoursePrefix(course.course_id)}>
|
||||||
<Link href={"/org/" + orgslug + "/course/" + removeCoursePrefix(course.course_id) + "/edit"}>
|
<Link href={getUriWithOrg(orgslug,"") + "/course/" + removeCoursePrefix(course.course_id) + "/edit"}>
|
||||||
<button>
|
<button>
|
||||||
Edit <Edit2 size={10}></Edit2>
|
Edit <Edit2 size={10}></Edit2>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ import "@styles/globals.css";
|
||||||
import { Menu } from "@components/UI/Elements/Menu";
|
import { Menu } from "@components/UI/Elements/Menu";
|
||||||
import AuthProvider from "@components/Security/AuthProvider";
|
import AuthProvider from "@components/Security/AuthProvider";
|
||||||
|
|
||||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
export default function RootLayout({ children, params }: { children: React.ReactNode , params:any}) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AuthProvider>
|
<AuthProvider>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
import { Title } from "@components/UI/Elements/Styles/Title";
|
import { Title } from "@components/UI/Elements/Styles/Title";
|
||||||
|
import { getUriWithOrg } from "@services/config";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
|
|
||||||
|
|
@ -10,7 +11,7 @@ const OrgHomePage = (params: any) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Title>Welcome {orgslug} 👋🏻</Title>
|
<Title>Welcome {orgslug} 👋🏻</Title>
|
||||||
<Link href={pathname + "/courses"}>
|
<Link href={getUriWithOrg(orgslug,"/courses")}>
|
||||||
<button>See Courses </button>
|
<button>See Courses </button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import { Title } from "../../components/UI/Elements/Styles/Title";
|
||||||
import { loginAndGetToken } from "../../services/auth/auth";
|
import { loginAndGetToken } from "../../services/auth/auth";
|
||||||
|
|
||||||
const Login = () => {
|
const Login = () => {
|
||||||
const [email, setEmail] = React.useState("");
|
const [email, setEmail] = React.useState("admin@admin.admin");
|
||||||
const [password, setPassword] = React.useState("");
|
const [password, setPassword] = React.useState("admin");
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const handleSubmit = (e: any) => {
|
const handleSubmit = (e: any) => {
|
||||||
|
|
@ -39,7 +39,7 @@ const Login = () => {
|
||||||
<Title>Login</Title>
|
<Title>Login</Title>
|
||||||
|
|
||||||
<form>
|
<form>
|
||||||
<input onChange={handleEmailChange} type="text" placeholder="email" />
|
<input onChange={handleEmailChange} type="text" placeholder="email" />
|
||||||
<input onChange={handlePasswordChange} type="password" placeholder="password" />
|
<input onChange={handlePasswordChange} type="password" placeholder="password" />
|
||||||
<button onClick={handleSubmit} type="submit">
|
<button onClick={handleSubmit} type="submit">
|
||||||
Login
|
Login
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { Title } from "../../components/UI/Elements/Styles/Title";
|
||||||
import { deleteOrganizationFromBackend } from "@services/orgs";
|
import { deleteOrganizationFromBackend } from "@services/orgs";
|
||||||
import useSWR, { mutate } from "swr";
|
import useSWR, { mutate } from "swr";
|
||||||
import { swrFetcher } from "@services/utils/requests";
|
import { swrFetcher } from "@services/utils/requests";
|
||||||
import { getAPIUrl } from "@services/config";
|
import { getAPIUrl, getUriWithOrg } from "@services/config";
|
||||||
|
|
||||||
const Organizations = () => {
|
const Organizations = () => {
|
||||||
const { data : organizations , error } = useSWR(`${getAPIUrl()}orgs/user/page/1/limit/10`, swrFetcher)
|
const { data : organizations , error } = useSWR(`${getAPIUrl()}orgs/user/page/1/limit/10`, swrFetcher)
|
||||||
|
|
@ -32,7 +32,7 @@ const Organizations = () => {
|
||||||
<div>
|
<div>
|
||||||
{organizations.map((org: any) => (
|
{organizations.map((org: any) => (
|
||||||
<div key={org.org_id}>
|
<div key={org.org_id}>
|
||||||
<Link href={`/org/${org.slug}`}>
|
<Link href={getUriWithOrg(org.slug,"/")}>
|
||||||
<h3>{org.name}</h3>
|
<h3>{org.name}</h3>
|
||||||
</Link>
|
</Link>
|
||||||
<button onClick={() => deleteOrganization(org.org_id)}>Delete</button>
|
<button onClick={() => deleteOrganization(org.org_id)}>Delete</button>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import React from "react";
|
||||||
import { Draggable } from "react-beautiful-dnd";
|
import { Draggable } from "react-beautiful-dnd";
|
||||||
import { EyeOpenIcon, Pencil2Icon } from '@radix-ui/react-icons'
|
import { EyeOpenIcon, Pencil2Icon } from '@radix-ui/react-icons'
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import { getUriWithOrg } from "@services/config";
|
||||||
|
|
||||||
function Lecture(props: any) {
|
function Lecture(props: any) {
|
||||||
|
|
||||||
|
|
@ -12,13 +13,13 @@ function Lecture(props: any) {
|
||||||
<LectureWrapper key={props.lecture.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
<LectureWrapper key={props.lecture.id} {...provided.draggableProps} {...provided.dragHandleProps} ref={provided.innerRef}>
|
||||||
<p>{props.lecture.name} </p>
|
<p>{props.lecture.name} </p>
|
||||||
<Link
|
<Link
|
||||||
href={`/org/${props.orgslug}/course/${props.courseid}/lecture/${props.lecture.id.replace("lecture_", "")}`}
|
href={getUriWithOrg(props.orgslug,"")+`/course/${props.courseid}/lecture/${props.lecture.id.replace("lecture_", "")}`}
|
||||||
|
|
||||||
rel="noopener noreferrer">
|
rel="noopener noreferrer">
|
||||||
<EyeOpenIcon/>
|
<EyeOpenIcon/>
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
href={`/org/${props.orgslug}/course/${props.courseid}/lecture/${props.lecture.id.replace("lecture_", "")}/edit`}
|
href={getUriWithOrg(props.orgslug,"") +`/course/${props.courseid}/lecture/${props.lecture.id.replace("lecture_", "")}/edit`}
|
||||||
rel="noopener noreferrer">
|
rel="noopener noreferrer">
|
||||||
<Pencil2Icon/>
|
<Pencil2Icon/>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,6 @@ export default function middleware(req: NextRequest) {
|
||||||
// Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
|
// Get hostname of request (e.g. demo.vercel.pub, demo.localhost:3000)
|
||||||
const hostname = req.headers.get("host") || "learnhouse.app";
|
const hostname = req.headers.get("host") || "learnhouse.app";
|
||||||
|
|
||||||
// Only for demo purposes - remove this if you want to use your root domain as the landing page
|
|
||||||
if (hostname === "vercel.pub" || hostname === "platforms.vercel.app") {
|
|
||||||
return NextResponse.redirect("https://demo.vercel.pub");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* You have to replace ".vercel.pub" with your own domain if you deploy this example under your domain.
|
/* You have to replace ".vercel.pub" with your own domain if you deploy this example under your domain.
|
||||||
You can also use wildcard subdomains on .vercel.app links that are associated with your Vercel team slug
|
You can also use wildcard subdomains on .vercel.app links that are associated with your Vercel team slug
|
||||||
in this case, our team slug is "platformize", thus *.platformize.vercel.app works. Do note that you'll
|
in this case, our team slug is "platformize", thus *.platformize.vercel.app works. Do note that you'll
|
||||||
|
|
@ -34,30 +29,28 @@ export default function middleware(req: NextRequest) {
|
||||||
? hostname.replace(`.vercel.pub`, "").replace(`.platformize.vercel.app`, "")
|
? hostname.replace(`.vercel.pub`, "").replace(`.platformize.vercel.app`, "")
|
||||||
: hostname.replace(`.localhost:3000`, "");
|
: hostname.replace(`.localhost:3000`, "");
|
||||||
|
|
||||||
// if url starts with "/organizations" rewrite to path
|
/* Editor route */
|
||||||
|
if (url.pathname.match(/^\/course\/[^/]+\/lecture\/[^/]+\/edit$/)) {
|
||||||
|
url.pathname = `/_editor${url.pathname}`;
|
||||||
|
console.log("editor route", url.pathname);
|
||||||
|
|
||||||
|
return NextResponse.rewrite(url, { headers: { orgslug: currentHost } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Organizations route */
|
||||||
if (url.pathname.startsWith("/organizations")) {
|
if (url.pathname.startsWith("/organizations")) {
|
||||||
url.pathname = url.pathname.replace("/organizations", `/organizations${currentHost}`);
|
url.pathname = url.pathname.replace("/organizations", `/organizations${currentHost}`);
|
||||||
// remove localhost:3000 from url
|
// remove localhost:3000 from url
|
||||||
url.pathname = url.pathname.replace(`localhost:3000`, "");
|
url.pathname = url.pathname.replace(`localhost:3000`, "");
|
||||||
console.log(url);
|
|
||||||
|
|
||||||
return NextResponse.rewrite(url);
|
return NextResponse.rewrite(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (url.pathname.startsWith("/org")) {
|
console.log("currentHost", url);
|
||||||
url.pathname = url.pathname.replace("/organizations", `/_orgs/${currentHost}`);
|
|
||||||
// remove localhost:3000 from url
|
|
||||||
|
|
||||||
url.pathname = `/_orgs/${currentHost}${url.pathname}`;
|
|
||||||
url.pathname = url.pathname.replace(`localhost:3000/org/`, "");
|
|
||||||
console.log(url);
|
|
||||||
|
|
||||||
return NextResponse.rewrite(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
// rewrite everything else to `/_sites/[site] dynamic route
|
// rewrite everything else to `/_sites/[site] dynamic route
|
||||||
url.pathname = `/_orgs/${currentHost}${url.pathname}`;
|
url.pathname = `/_orgs/${currentHost}${url.pathname}`;
|
||||||
console.log(url);
|
|
||||||
|
|
||||||
return NextResponse.rewrite(url, { headers: { "olgslug": currentHost } });
|
return NextResponse.rewrite(url, { headers: { olgslug: currentHost } });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,10 @@ interface LoginAndGetTokenResponse {
|
||||||
|
|
||||||
export async function loginAndGetToken(username: string, password: string): Promise<LoginAndGetTokenResponse> {
|
export async function loginAndGetToken(username: string, password: string): Promise<LoginAndGetTokenResponse> {
|
||||||
// Request Config
|
// Request Config
|
||||||
const HeadersConfig = new Headers({ "Content-Type": "application/x-www-form-urlencoded" , Origin: "http://localhost:3000" });
|
|
||||||
|
// get origin
|
||||||
|
const origin = window.location.origin;
|
||||||
|
const HeadersConfig = new Headers({ "Content-Type": "application/x-www-form-urlencoded" , Origin: origin });
|
||||||
const urlencoded = new URLSearchParams({ username: username, password: password });
|
const urlencoded = new URLSearchParams({ username: username, password: password });
|
||||||
|
|
||||||
const requestOptions: any = {
|
const requestOptions: any = {
|
||||||
|
|
@ -28,7 +31,8 @@ export async function loginAndGetToken(username: string, password: string): Prom
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUserInfo(token: string): Promise<any> {
|
export async function getUserInfo(token: string): Promise<any> {
|
||||||
const HeadersConfig = new Headers({ Authorization: `Bearer ${token}`, Origin: "http://localhost:3000" });
|
const origin = window.location.origin;
|
||||||
|
const HeadersConfig = new Headers({ Authorization: `Bearer ${token}`, Origin:origin });
|
||||||
|
|
||||||
const requestOptions: any = {
|
const requestOptions: any = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,13 @@ export const getAPIUrl = () => LEARNHOUSE_API_URL;
|
||||||
export const getBackendUrl = () => LEARNHOUSE_BACKEND_URL;
|
export const getBackendUrl = () => LEARNHOUSE_BACKEND_URL;
|
||||||
|
|
||||||
export const getUriWithOrg = (orgslug: string, path: string) => {
|
export const getUriWithOrg = (orgslug: string, path: string) => {
|
||||||
return `http://localhost:3000/org/${orgslug}${path}`;
|
return `http://${orgslug}.localhost:3000${path}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getOrgFromUri = (uri: any) => {
|
export const getOrgFromUri = () => {
|
||||||
// if url contains /org
|
const hostname = window.location.hostname;
|
||||||
if (uri.includes("/org/")) {
|
// get the orgslug from the hostname
|
||||||
let org = uri.match(/\/org\/([\w]+)/)[1];
|
const orgslug = hostname.split(".")[0];
|
||||||
return org;
|
return orgslug;
|
||||||
}
|
|
||||||
else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ class Settings(BaseModel):
|
||||||
authjwt_token_location = {"cookies"}
|
authjwt_token_location = {"cookies"}
|
||||||
authjwt_cookie_csrf_protect = False
|
authjwt_cookie_csrf_protect = False
|
||||||
authjwt_access_token_expires = False # (pre-alpha only) # TODO: set to 1 hour
|
authjwt_access_token_expires = False # (pre-alpha only) # TODO: set to 1 hour
|
||||||
|
authjwt_cookie_samesite = "none"
|
||||||
|
authjwt_cookie_secure = True
|
||||||
|
|
||||||
|
|
||||||
@AuthJWT.load_config # type: ignore
|
@AuthJWT.load_config # type: ignore
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue