Skip to content

Commit

Permalink
feat: allow for login user
Browse files Browse the repository at this point in the history
  • Loading branch information
JimmyLv committed Mar 6, 2023
1 parent 25b1b43 commit e9aea82
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 13 deletions.
2 changes: 2 additions & 0 deletions components/sign-in-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Modal from "~/components/shared/modal";
import Image from "next/image";
import { BASE_DOMAIN, LOGIN_LIMIT_COUNT } from "~/utils/constants";
import Link from "next/link";
import { isDev } from "~/utils/env";

const SignInModal = ({
showSignInModal,
Expand Down Expand Up @@ -42,6 +43,7 @@ const SignInModal = ({
<div className="flex flex-col space-y-4 bg-gray-50 px-4 py-8 md:px-16">
<Auth
supabaseClient={supabaseClient}
// redirectTo={isDev ? window?.location?.origin : BASE_DOMAIN}
localization={{
variables: {
sign_up: {
Expand Down
2 changes: 1 addition & 1 deletion hooks/use-toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function dispatch(action: Action) {
interface Toast extends Omit<ToasterToast, "id"> {}

function toast({ ...props }: Toast) {
console.log('========toast props========', props)
// console.log('========toast props========', props)
const id = genId()

const update = (props: ToasterToast) =>
Expand Down
15 changes: 14 additions & 1 deletion hooks/useSummarize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,21 @@ export function useSummarize() {
title: `网站访问量过大`,
description: `每日限额使用 ${RATE_LIMIT_COUNT} 次哦!`,
});
} else if (response.status === 401) {
toast({
variant: "destructive",
title: `${response.statusText} 请登录哦!`,
// ReadableStream can't get error message
// description: response.body
description: "每天的免费次数已经用完啦,🆓",
});
} else {
toast({ variant: "destructive", title: response.statusText });
toast({
variant: "destructive",
title: response.statusText,
// ReadableStream can't get error message
// description: response.body
});
}
setLoading(false);
return;
Expand Down
8 changes: 7 additions & 1 deletion lib/openai/OpenAIResult.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { createParser, ParsedEvent, ReconnectInterval } from "eventsource-parser";
import {
createParser,
ParsedEvent,
ReconnectInterval,
} from "eventsource-parser";
import { formatResult } from "~/lib/openai/formatResult";
import { isDev } from "~/utils/env";

// TODO: maybe chat with video?
export type ChatGPTAgent = "user" | "system" | "assistant";
Expand Down Expand Up @@ -28,6 +33,7 @@ export async function OpenAIResult(
const encoder = new TextEncoder();
const decoder = new TextDecoder();

isDev && console.log({ apiKey });
const res = await fetch("https://api.openai.com/v1/chat/completions", {
headers: {
"Content-Type": "application/json",
Expand Down
54 changes: 47 additions & 7 deletions middleware.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createMiddlewareSupabaseClient } from "@supabase/auth-helpers-nextjs";
import { Redis } from "@upstash/redis";
import type { NextFetchEvent, NextRequest } from "next/server";
import { NextResponse } from "next/server";
Expand All @@ -11,6 +12,16 @@ const redis = Redis.fromEnv();
export async function middleware(req: NextRequest, context: NextFetchEvent) {
const { apiKey, bvId } = await req.json();

function redirectAuth() {
// return NextResponse.redirect(new URL("/shop", req.url));
// Respond with JSON indicating an error message
console.error("Authentication Failed");
return new NextResponse(
JSON.stringify({ success: false, message: "Authentication Failed" }),
{ status: 401, headers: { "content-type": "application/json" } }
);
}

// licenseKeys
if (apiKey) {
if (checkOpenaiApiKeys(apiKey)) {
Expand All @@ -19,15 +30,44 @@ export async function middleware(req: NextRequest, context: NextFetchEvent) {

// 3. something-invalid-sdalkjfasncs-key
if (!(await validateLicenseKey(apiKey, bvId))) {
return NextResponse.redirect(new URL("/shop", req.url));
return redirectAuth();
}
}
// TODO: unique to a user (userid, email etc) instead of IP
const identifier = req.ip ?? "127.0.0.7";
const { success, remaining } = await ratelimit.limit(identifier);
console.log(`======== ip ${identifier}, remaining: ${remaining} ========`);
if (!apiKey && !success) {
return NextResponse.redirect(new URL("/shop", req.url));

if (!apiKey) {
const identifier = req.ip ?? "127.0.0.7";
const { success, remaining } = await ratelimit.limit(identifier);
console.log(`======== ip ${identifier}, remaining: ${remaining} ========`);
if (!success) {
// We need to create a response and hand it to the supabase client to be able to modify the response headers.
const res = NextResponse.next();
// TODO: unique to a user (userid, email etc) instead of IP
// Create authenticated Supabase Client.
const supabase = createMiddlewareSupabaseClient({ req, res });
// Check if we have a session
const {
data: { session },
} = await supabase.auth.getSession();
// Check auth condition
const userEmail = session?.user.email;
if (userEmail) {
// Authentication successful, forward request to protected route.
const { success, remaining } = await ratelimit.limit(userEmail + "2");
console.log(
`======== user ${userEmail}, remaining: ${remaining} ========`
);
if (!success) {
return redirectAuth();
}

return res;
}

// todo: throw error to trigger a modal, rather than redirect a page
return redirectAuth();
}

return redirectAuth();
}

const result = await redis.get<string>(bvId);
Expand Down
12 changes: 10 additions & 2 deletions pages/[...slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export const Home: NextPage = () => {
const licenseKey = searchParams.get("license_key");
const [curVideo, setCurVideo] = useState<string>("");
const [currentBvId, setCurrentBvId] = useState<string>("");
const [userKey, setUserKey] = useLocalStorage<string>("user-openai-apikey");
const [userKey, setUserKey, remove] =
useLocalStorage<string>("user-openai-apikey");
const { loading, summary, resetSummary, summarize } = useSummarize();
const { toast } = useToast();

Expand Down Expand Up @@ -120,6 +121,13 @@ export const Home: NextPage = () => {
toast({ description: "复制成功 ✂️" });
};

const handleApiKeyChange = (e: any) => {
if (!e.target.value) {
remove();
}
setUserKey(e.target.value);
};

return (
<div className="mt-10 w-full sm:mt-40">
<a
Expand Down Expand Up @@ -221,7 +229,7 @@ export const Home: NextPage = () => {
<div className="text-lg text-slate-700 dark:text-slate-400">
<input
value={userKey}
onChange={(e) => setUserKey(e.target.value)}
onChange={handleApiKeyChange}
className="mx-auto my-4 w-full appearance-none rounded-lg rounded-md border bg-transparent py-2 pl-2 text-sm leading-6 text-slate-900 shadow-sm ring-1 ring-slate-200 placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder={
"填你的 OpenAI API Key: sk-xxxxxx 或者购买的 License Key: xxx-CCDE-xxx"
Expand Down
2 changes: 1 addition & 1 deletion utils/extractTimestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ export function extractTimestamp(matchResult: RegExpMatchArray) {
}catch(e){
console.log('handle text after time error', e);
}
console.log("========matchResult========", {matchResult, timestamp, formattedContent});
// console.log("========matchResult========", {matchResult, timestamp, formattedContent});
return { timestamp, formattedContent };
}

1 comment on commit e9aea82

@vercel
Copy link

@vercel vercel bot commented on e9aea82 Mar 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.