Email verification frontend.

This commit is contained in:
2022-09-09 08:39:46 +02:00
parent 65d62e8e49
commit 637dfb45d8
10 changed files with 113 additions and 48 deletions

View File

@@ -5,7 +5,7 @@ import { ConfigModule } from '@nestjs/config';
import { GraphQLISODateTime, GraphQLModule } from '@nestjs/graphql'; import { GraphQLISODateTime, GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core'; import { ApolloServerPluginLandingPageLocalDefault } from 'apollo-server-core';
import { UsersModule } from './users/users.module'; // import { UsersModule } from './users/users.module';
@Module({ @Module({
imports: [ imports: [
@@ -29,7 +29,7 @@ import { UsersModule } from './users/users.module';
resolvers: { DateTime: GraphQLISODateTime }, resolvers: { DateTime: GraphQLISODateTime },
plugins: [ApolloServerPluginLandingPageLocalDefault()], plugins: [ApolloServerPluginLandingPageLocalDefault()],
}), }),
UsersModule, // UsersModule,
], ],
controllers: [AppController], controllers: [AppController],
providers: [], providers: [],

View File

@@ -46,15 +46,32 @@ export class SupertokensService {
}), }),
], ],
}), }),
Session Session.init({
.init // antiCsrf: "VIA_CUSTOM_HEADER",
// { jwt: {
// jwt: { enable: true,
// enable: true, issuer: `${process.env.APP_URL}/auth/api`,
// issuer: `${process.env.APP_URL}/auth/api`, },
// }, override: {
// } functions: function (originalImplementation) {
(), return {
...originalImplementation,
createNewSession: async function (input) {
input.accessTokenPayload = {
...input.accessTokenPayload,
'https://hasura.io/jwt/claims': {
'x-hasura-user-id': input.userId,
'x-hasura-default-role': 'user',
'x-hasura-allowed-roles': ['user'],
},
};
return originalImplementation.createNewSession(input);
},
};
},
},
}),
], ],
}); });
} }

View File

@@ -2,18 +2,18 @@ import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import supertokens from 'supertokens-node'; import supertokens from 'supertokens-node';
import { SupertokensExceptionFilter } from './auth/filters/auth.filter'; import { SupertokensExceptionFilter } from './auth/filters/auth.filter';
import { PrismaService } from 'prisma/prisma.service'; // import { PrismaService } from 'prisma/prisma.service';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule); const app = await NestFactory.create(AppModule);
app.enableCors({ app.enableCors({
origin: [process.env.WEBAPP_URL, 'https://studio.apollographql.com'], origin: [process.env.WEBAPP_URL, 'http://server.home:8081'],
allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()], allowedHeaders: ['content-type', ...supertokens.getAllCORSHeaders()],
credentials: true, credentials: true,
}); });
app.useGlobalFilters(new SupertokensExceptionFilter()); app.useGlobalFilters(new SupertokensExceptionFilter());
const prismaService = app.get(PrismaService); // const prismaService = app.get(PrismaService);
await prismaService.enableShutdownHooks(app); // await prismaService.enableShutdownHooks(app);
await app.listen(process.env.APP_PORT); await app.listen(process.env.APP_PORT);
} }

View File

@@ -6,19 +6,19 @@ import { UsersService } from './users.service';
export class UsersResolver { export class UsersResolver {
constructor(private readonly usersService: UsersService) {} constructor(private readonly usersService: UsersService) {}
@Mutation('createUser') // @Mutation('createUser')
create(@Args('createUserInput') createUserInput: Prisma.UserCreateInput) { // create(@Args('createUserInput') createUserInput: Prisma.UserCreateInput) {
return this.usersService.create(createUserInput); // return this.usersService.create(createUserInput);
} // }
@Query('users') // @Query('users')
findAll(@Args('params') params?: Prisma.UserFindManyArgs) { // findAll(@Args('params') params?: Prisma.UserFindManyArgs) {
return this.usersService.users(params); // return this.usersService.users(params);
} // }
@Query('user') // @Query('user')
findOne(@Args('id') id: string) { // findOne(@Args('id') id: string) {
return this.usersService.user({ id }); // return this.usersService.user({ id });
} // }
// @Mutation('updateUser') // @Mutation('updateUser')
// update(@Args('updateUserInput') updateUserInput: UpdateUserInput) { // update(@Args('updateUserInput') updateUserInput: UpdateUserInput) {

View File

@@ -1,29 +1,29 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { Prisma, User } from '@prisma/client'; // import { Prisma, User } from '@prisma/client';
import { PrismaService } from 'prisma/prisma.service'; import { PrismaService } from 'prisma/prisma.service';
@Injectable() @Injectable()
export class UsersService { export class UsersService {
constructor(private readonly prismaService: PrismaService) {} constructor(private readonly prismaService: PrismaService) {}
async user(uniqueInput: Prisma.UserWhereUniqueInput) { // async user(uniqueInput: Prisma.UserWhereUniqueInput) {
return await this.prismaService.user.findUnique({ where: uniqueInput }); // return await this.prismaService.user.findUnique({ where: uniqueInput });
} // }
async users(params?: Prisma.UserFindManyArgs) { // async users(params?: Prisma.UserFindManyArgs) {
return await this.prismaService.user.findMany(params); // return await this.prismaService.user.findMany(params);
} // }
create(createUserInput: Prisma.UserCreateInput) { // create(createUserInput: Prisma.UserCreateInput) {
return this.prismaService.user.create({ data: createUserInput }); // return this.prismaService.user.create({ data: createUserInput });
} // }
update(id: string, userUpdateInput: Prisma.UserUpdateInput) { // update(id: string, userUpdateInput: Prisma.UserUpdateInput) {
return this.prismaService.user.update({ // return this.prismaService.user.update({
where: { id }, // where: { id },
data: userUpdateInput, // data: userUpdateInput,
}); // });
} // }
// remove(id: string) { // remove(id: string) {
// return `This action removes a #${id} user`; // return `This action removes a #${id} user`;

View File

@@ -11,7 +11,10 @@ SuperTokens.init({
apiBasePath: "/auth/api", apiBasePath: "/auth/api",
appName: "Fluxem", appName: "Fluxem",
}, },
recipeList: [EmailPass.init(), Session.init()], recipeList: [
EmailPass.init(),
Session.init(),
],
}); });
const App: Component = () => { const App: Component = () => {

View File

@@ -2,6 +2,7 @@ import { createSignal } from "solid-js";
import { createStore } from "solid-js/store"; import { createStore } from "solid-js/store";
import EmailPassRecipe from "supertokens-web-js/recipe/emailpassword"; import EmailPassRecipe from "supertokens-web-js/recipe/emailpassword";
import Session from "supertokens-web-js/recipe/session";
const useLogin = () => { const useLogin = () => {
const [loading, setLoading] = createSignal(false); const [loading, setLoading] = createSignal(false);
@@ -22,7 +23,7 @@ const useLogin = () => {
{ id: "password", value: form.password }, { id: "password", value: form.password },
], ],
}); });
console.log(login); console.log(login)
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} finally { } finally {
@@ -30,7 +31,26 @@ const useLogin = () => {
} }
}; };
return { handleInput, loading, handleLogin, form }; const handleLogout = async () => {
const logout = await EmailPassRecipe.signOut();
};
const handleJwt = async () => {
const session = await Session.doesSessionExist();
if (session) {
let userId = await Session.getUserId();
let jwt = (await Session.getAccessTokenPayloadSecurely()).jwt;
// console.log(userId, jwt);
const {isVerified} = await EmailPassRecipe.isEmailVerified();
console.log(isVerified)
if(!isVerified) {
const sendEmail = await EmailPassRecipe.sendVerificationEmail()
console.log(sendEmail);
}
}
};
return { handleInput, loading, handleLogin, handleLogout, handleJwt, form };
}; };
export default useLogin; export default useLogin;

View File

@@ -5,7 +5,7 @@ const Home = lazy(() => import("./views/home/Home"));
const AuthLayout = lazy(() => import("./views/auth/AuthLayout")); const AuthLayout = lazy(() => import("./views/auth/AuthLayout"));
const Login = lazy(() => import("./views/auth/Login")); const Login = lazy(() => import("./views/auth/Login"));
const Register = lazy(() => import("./views/auth/Register")); const Register = lazy(() => import("./views/auth/Register"));
const VerifyEmail = lazy(() => import("./views/auth/VerifyEmail"));
const AppRouter: Component = () => { const AppRouter: Component = () => {
return ( return (
<Routes> <Routes>
@@ -13,6 +13,7 @@ const AppRouter: Component = () => {
<Route path="/auth" element={<AuthLayout />}> <Route path="/auth" element={<AuthLayout />}>
<Route path="/login" element={<Login />}></Route> <Route path="/login" element={<Login />}></Route>
<Route path="/register" element={<Register />}></Route> <Route path="/register" element={<Register />}></Route>
<Route path="/verify-email" element={<VerifyEmail />}></Route>
</Route> </Route>
</Routes> </Routes>
); );

View File

@@ -1,6 +1,6 @@
import { Component, Show } from "solid-js"; import { Component, Show } from "solid-js";
import useLogin from "../../../hooks/auth/login.hook"; import useLogin from "../../../hooks/auth/login.hook";
const { handleLogin, handleInput, loading, form } = useLogin(); const { handleLogin, handleLogout, handleInput, handleJwt, loading, form } = useLogin();
const Login: Component = () => { const Login: Component = () => {
return ( return (
<div> <div>
@@ -32,6 +32,12 @@ const Login: Component = () => {
</Show> </Show>
</button> </button>
</form> </form>
<button type="button" onclick={handleLogout}>
Logout
</button>
<button type="button" onclick={handleJwt}>
GetJWT
</button>
</div> </div>
); );
}; };

View File

@@ -0,0 +1,18 @@
import EmailPassRecipe from "supertokens-web-js/recipe/emailpassword";
const VerifyEmail = () => {
let text = "Verifying email";
const verifyEmail = EmailPassRecipe.verifyEmail();
verifyEmail.then((data) => {
console.log(data);
text = "Email verified successfully";
});
// console.log(verifyEmail);
return (
<div>
<h2>{text}</h2>
</div>
);
};
export default VerifyEmail;