mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-08 13:05:08 +09:00
add styles
This commit is contained in:
1 parent
8f4a8ef23b
commit
3ad34f2a59
18 files changed
+288
-36
No files matched your search
@@ -3,6 +3,8 @@ const config = {
|
||||
canvasPath: "/canvas",
|
||||
designerPath: "/designer",
|
||||
dashboardPath: "/dashboard",
|
||||
loginPath: "/login",
|
||||
logoutPath: "/logout",
|
||||
};
|
||||
export default config;
|
||||
export type Config = typeof config;
|
||||
@@ -10,6 +10,7 @@ const getCssTextFunctions = {
|
||||
[config.canvasPath]: getCanvasCssText,
|
||||
[config.designerPath]: getDesignerCssText,
|
||||
[config.dashboardPath]: getDesignerCssText,
|
||||
[config.loginPath]: getDesignerCssText,
|
||||
};
|
||||
|
||||
const getCssTextFunction = (url: string) => {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { ActionFunction, LoaderFunction, redirect } from "@remix-run/node";
|
||||
import { ActionFunction } from "@remix-run/node";
|
||||
import config from "~/config";
|
||||
import { authenticator } from "~/services/auth.server";
|
||||
|
||||
export const loader: LoaderFunction = () => redirect("/login");
|
||||
|
||||
export const action: ActionFunction = ({ request }) => {
|
||||
return authenticator.authenticate("github", request);
|
||||
return authenticator.authenticate("github", request, {
|
||||
successRedirect: config.dashboardPath,
|
||||
failureRedirect: config.loginPath,
|
||||
});
|
||||
};
|
||||
@@ -1,9 +1,10 @@
|
||||
import { LoaderFunction } from "@remix-run/node";
|
||||
import config from "~/config";
|
||||
import { authenticator } from "~/services/auth.server";
|
||||
|
||||
export const loader: LoaderFunction = ({ request }) => {
|
||||
return authenticator.authenticate("github", request, {
|
||||
successRedirect: "/dashboard",
|
||||
failureRedirect: "/login",
|
||||
successRedirect: config.dashboardPath,
|
||||
failureRedirect: config.loginPath,
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ActionFunction, LoaderFunction, redirect } from "@remix-run/node";
|
||||
import { authenticator } from "~/services/auth.server";
|
||||
|
||||
export const loader: LoaderFunction = () => redirect("/login");
|
||||
|
||||
export const action: ActionFunction = ({ request }) => {
|
||||
return authenticator.authenticate("google", request);
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
import { LoaderFunction } from "@remix-run/node";
|
||||
import config from "~/config";
|
||||
import { authenticator } from "~/services/auth.server";
|
||||
|
||||
export const loader: LoaderFunction = ({ request }) => {
|
||||
return authenticator.authenticate("google", request, {
|
||||
successRedirect: config.dashboardPath,
|
||||
failureRedirect: config.loginPath,
|
||||
});
|
||||
};
|
||||
@@ -31,9 +31,9 @@ export const action: ActionFunction = async ({ request }) => {
|
||||
|
||||
export const loader: LoaderFunction = async ({ request }) => {
|
||||
const user = await authenticator.isAuthenticated(request);
|
||||
console.log(user);
|
||||
console.log(user)
|
||||
if (!user) {
|
||||
return redirect("/login");
|
||||
return redirect(config.loginPath);
|
||||
}
|
||||
const { userId, headers } = await ensureUserCookie(request);
|
||||
const projects = await db.project.loadManyByUserId(userId);
|
||||
|
||||
+88
-5
@@ -1,9 +1,92 @@
|
||||
import { Links, LiveReload, Meta, Scripts } from "@remix-run/react";
|
||||
import {
|
||||
LinksFunction,
|
||||
LoaderFunction,
|
||||
MetaFunction,
|
||||
redirect,
|
||||
} from "@remix-run/node";
|
||||
import { CriticalCss } from "@webstudio-is/sdk";
|
||||
import { darkTheme } from "~/shared/design-system";
|
||||
import { Form } from "@remix-run/react";
|
||||
import { Button, Card, Flex, Heading } from "~/shared/design-system";
|
||||
import interStyles from "~/shared/font-faces/inter.css";
|
||||
|
||||
export default function Login() {
|
||||
import { GoogleIcon, GithubIcon } from "~/shared/icons";
|
||||
import { authenticator } from "~/services/auth.server";
|
||||
import config from "~/config";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [
|
||||
{
|
||||
rel: "stylesheet",
|
||||
href: interStyles,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return { title: "Webstudio Login" };
|
||||
};
|
||||
|
||||
const RootDesignerRoute = () => {
|
||||
return (
|
||||
<Form action="/auth/github" method="post">
|
||||
<button>Login with GitHub</button>
|
||||
</Form>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<Meta />
|
||||
<Links />
|
||||
<CriticalCss />
|
||||
</head>
|
||||
<body className={darkTheme}>
|
||||
<Flex
|
||||
css={{ height: "100vh" }}
|
||||
direction="column"
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<Card
|
||||
css={{ width: "$10", padding: "$5", zoom: 1.4 }}
|
||||
variant="active"
|
||||
>
|
||||
<Flex direction="column" gap="2" align="center">
|
||||
<Heading>Login</Heading>
|
||||
|
||||
<Flex gap="2" direction="column" align="center">
|
||||
<Form action="/auth/github" method="post">
|
||||
<Button type="submit">
|
||||
<Flex gap="1">
|
||||
<GithubIcon width="16" />
|
||||
Login with GitHub
|
||||
</Flex>
|
||||
</Button>
|
||||
</Form>
|
||||
<Form action="/auth/google" method="post">
|
||||
<Button type="submit">
|
||||
<Flex gap="1">
|
||||
<GoogleIcon width="16" color="white" />
|
||||
Login with Google
|
||||
</Flex>
|
||||
</Button>
|
||||
</Form>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
</Flex>
|
||||
<Scripts />
|
||||
{process.env.NODE_ENV === "development" && <LiveReload />}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const loader: LoaderFunction = async ({ request }) => {
|
||||
const user = await authenticator.isAuthenticated(request);
|
||||
if (user) {
|
||||
return redirect(config.dashboardPath);
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
export default RootDesignerRoute;
|
||||
+39
-18
@@ -1,28 +1,49 @@
|
||||
import { User } from "@prisma/client";
|
||||
import { Authenticator } from "remix-auth";
|
||||
import { GitHubStrategy } from "remix-auth-github";
|
||||
import { GoogleStrategy } from "remix-auth-google";
|
||||
import { sessionStorage } from "~/services/session.server";
|
||||
import { createOrLoginWithGithub } from "~/shared/db/user.server";
|
||||
import {
|
||||
createOrLoginWithGithub,
|
||||
createOrLoginWithGoogle,
|
||||
} from "~/shared/db/user.server";
|
||||
|
||||
const url = `${
|
||||
process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}`
|
||||
: "http://localhost:3000"
|
||||
}/auth`;
|
||||
|
||||
const github = new GitHubStrategy(
|
||||
{
|
||||
clientID: process.env.GH_CLIENT_ID as string,
|
||||
clientSecret: process.env.GH_CLIENT_SECRET as string,
|
||||
callbackURL: `${url}/github/callback`,
|
||||
},
|
||||
async ({ profile }) => {
|
||||
const user = createOrLoginWithGithub(profile);
|
||||
|
||||
return user;
|
||||
}
|
||||
);
|
||||
|
||||
const google = new GoogleStrategy(
|
||||
{
|
||||
clientID: "YOUR_CLIENT_ID",
|
||||
clientSecret: "YOUR_CLIENT_SECRET",
|
||||
callbackURL: `${url}/google/callback`,
|
||||
},
|
||||
async ({ profile }) => {
|
||||
const user = createOrLoginWithGoogle(profile);
|
||||
|
||||
return user;
|
||||
}
|
||||
);
|
||||
|
||||
// Create an instance of the authenticator, pass a generic with what
|
||||
// strategies will return and will store in the session
|
||||
export const authenticator = new Authenticator<User>(sessionStorage);
|
||||
if (process.env.GH_CLIENT_ID && process.env.GH_CLIENT_SECRET) {
|
||||
authenticator.use(
|
||||
new GitHubStrategy(
|
||||
{
|
||||
clientID: process.env.GH_CLIENT_ID as string,
|
||||
clientSecret: process.env.GH_CLIENT_SECRET as string,
|
||||
callbackURL: `https://${
|
||||
process.env.VERCEL_URL || "192.168.1.91:3000"
|
||||
}/auth/github/callback`,
|
||||
},
|
||||
async ({ profile }) => {
|
||||
const user = createOrLoginWithGithub(profile);
|
||||
|
||||
return user;
|
||||
}
|
||||
),
|
||||
"github"
|
||||
);
|
||||
authenticator.use(github, "github");
|
||||
authenticator.use(google, "google");
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { User } from "@prisma/client";
|
||||
import { GitHubProfile } from "remix-auth-github";
|
||||
import { GoogleProfile } from "remix-auth-google";
|
||||
import { ensureUserCookie } from "../session";
|
||||
import { prisma } from "./prisma.server";
|
||||
|
||||
export const createOrLoginWithGithub = async (
|
||||
@@ -24,3 +26,26 @@ export const createOrLoginWithGithub = async (
|
||||
|
||||
return newUser;
|
||||
};
|
||||
|
||||
export const createOrLoginWithGoogle = async (
|
||||
profile: GoogleProfile
|
||||
): Promise<User> => {
|
||||
const user = await prisma.user.findUnique({
|
||||
where: { email: profile._json.email },
|
||||
});
|
||||
|
||||
if (user) {
|
||||
return user;
|
||||
}
|
||||
|
||||
const newUser = prisma.user.create({
|
||||
data: {
|
||||
email: profile._json.email,
|
||||
username: profile.displayName,
|
||||
image: profile._json.avatar_url,
|
||||
provider: profile.provider,
|
||||
},
|
||||
});
|
||||
|
||||
return newUser;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as React from "react";
|
||||
import { IconProps } from "./types";
|
||||
|
||||
export const GithubIcon = React.forwardRef<SVGSVGElement, IconProps>(
|
||||
({ color = "currentColor", ...props }, forwardedRef) => {
|
||||
return (
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
ref={forwardedRef}
|
||||
>
|
||||
<title>GitHub</title>
|
||||
<path
|
||||
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
|
||||
fill={color}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
GithubIcon.displayName = "GithubIcon";
|
||||
@@ -0,0 +1,24 @@
|
||||
import * as React from "react";
|
||||
import { IconProps } from "./types";
|
||||
|
||||
export const GoogleIcon = React.forwardRef<SVGSVGElement, IconProps>(
|
||||
({ color = "currentColor", ...props }, forwardedRef) => {
|
||||
return (
|
||||
<svg
|
||||
role="img"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
ref={forwardedRef}
|
||||
>
|
||||
<title>Google</title>
|
||||
<path
|
||||
d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z"
|
||||
fill={color}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
GoogleIcon.displayName = "GoogleIcon";
|
||||
@@ -4,6 +4,8 @@ export * from "./brush";
|
||||
export * from "./form";
|
||||
export * from "./undo";
|
||||
export * from "./redo";
|
||||
export * from "./google";
|
||||
export * from "./github";
|
||||
export * from "./devices";
|
||||
export * from "./tablet";
|
||||
export * from "./types";
|
||||
@@ -72,6 +72,7 @@
|
||||
"react-use": "^17.3.2",
|
||||
"remix-auth": "^3.2.2",
|
||||
"remix-auth-github": "^1.1.1",
|
||||
"remix-auth-google": "^1.1.0",
|
||||
"slugify": "^1.6.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `createdAt` on the `User` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `email` on the `User` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `image` on the `User` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `provider` on the `User` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `username` on the `User` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- DropIndex
|
||||
DROP INDEX "User_email_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" DROP COLUMN "createdAt",
|
||||
DROP COLUMN "email",
|
||||
DROP COLUMN "image",
|
||||
DROP COLUMN "provider",
|
||||
DROP COLUMN "username";
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[email]` on the table `User` will be added. If there are existing duplicate values, this will fail.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
ADD COLUMN "email" TEXT,
|
||||
ADD COLUMN "image" TEXT,
|
||||
ADD COLUMN "provider" TEXT,
|
||||
ADD COLUMN "username" TEXT;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
|
||||
+11
-4
@@ -10,6 +10,16 @@ datasource db {
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
email String? @unique
|
||||
provider String?
|
||||
image String?
|
||||
username String?
|
||||
createdAt DateTime @default(now())
|
||||
projects Project[]
|
||||
}
|
||||
|
||||
model Project {
|
||||
id String @id @default(uuid())
|
||||
userId String
|
||||
@@ -18,10 +28,7 @@ model Project {
|
||||
prodTreeId String? // exists when published
|
||||
devTreeId String
|
||||
prodTreeIdHistory String @default("[]")
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
User User @relation(fields: [userId], references: [id])
|
||||
}
|
||||
|
||||
model Tree {
|
||||
|
||||
@@ -12144,7 +12144,14 @@ remix-auth-github@^1.1.1:
|
||||
remix-auth "^3.0.0"
|
||||
remix-auth-oauth2 "^1.0.0"
|
||||
|
||||
remix-auth-oauth2@^1.0.0:
|
||||
remix-auth-google@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/remix-auth-google/-/remix-auth-google-1.1.0.tgz#4ffdc41b180a7a622d9008e7a25b6e409dbf5f20"
|
||||
integrity sha512-yzZ8JEiSoY/cvo5eJQBIzqpnaWOjQkYCgBklCP1QwT01sdR2F066uhV+jR9Wcx0bPCntdMG4PrytVBJzWTg+BA==
|
||||
dependencies:
|
||||
remix-auth-oauth2 "^1.1.0"
|
||||
|
||||
remix-auth-oauth2@^1.0.0, remix-auth-oauth2@^1.1.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/remix-auth-oauth2/-/remix-auth-oauth2-1.2.2.tgz#bebe0ac586744ed94885bd47f6bcb710d377fede"
|
||||
integrity sha512-bbQw/SFAbilSE1zrZFaJN/NM7WUkC63CKJFVz2e/Y21qqMZo5eVQXooSV6d23mABfodeVk6wthngdLAjxak6fQ==
|
||||
|
||||
Reference in new issue
Block a user