Skip to content

Commit

Permalink
create account (#12)
Browse files Browse the repository at this point in the history
Co-authored-by: Olivier JM Maniraho <manolivier93@gmail.com>
  • Loading branch information
brianmuks and OlivierJM authored Oct 8, 2023
1 parent d49f371 commit 0e43fa8
Show file tree
Hide file tree
Showing 34 changed files with 1,504 additions and 256 deletions.
Empty file added .env
Empty file.
24 changes: 12 additions & 12 deletions .github/workflows/sanity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ name: Check code sanity

on:
push:
branches: [ "main" ]
branches: ["main"]
pull_request:
branches: [ "main" ]
branches: ["main"]

jobs:
build:

runs-on: ubuntu-latest

strategy:
Expand All @@ -20,12 +19,13 @@ jobs:
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: yarn install --frozen-lockfile
- run: yarn build
# - run: npm test
- name: 'setup env file'
run: |
echo "${{ secrets.ENV_FILE }}" > .env
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: yarn install --frozen-lockfile
- run: yarn build
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
mongodb-realm
7 changes: 4 additions & 3 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
env: {
REALM_APP_ID: "sparked-next-vbuim",
NEXTAUTH_URL: "https://example.com",
env: {},
webpack: (config) => {
config.externals = [...config.externals, { realm: "realm" }]; // required to make realm
return config;
},
};

Expand Down
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,32 @@
"lint": "next lint"
},
"dependencies": {
"@auth/mongodb-adapter": "^2.0.0",
"@headlessui/react": "^1.7.17",
"@types/node": "20.5.0",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"antd": "^5.9.2",
"axios": "^1.5.0",
"eslint": "8.47.0",
"eslint-config-next": "13.4.17",
"flowbite": "^1.8.1",
"flowbite-react": "^0.5.0",
"i18next": "^23.5.1",
"mobx": "^6.10.0",
"mobx-react-lite": "^4.0.3",
"mongodb": "^6.1.0",
"next": "13.4.17",
"next-auth": "^4.23.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"realm": "^12.1.0",
"typescript": "5.1.6"
"typescript": "5.1.6",
"zod-form-data": "^2.0.1"
},
"devDependencies": {
"autoprefixer": "^10.4.15",
"nodemailer": "^6.9.5",
"postcss": "^8.4.28",
"tailwindcss": "^3.3.3"
}
Expand Down
6 changes: 6 additions & 0 deletions src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import NextAuth from "next-auth"
import { authOptions } from "../constants";

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST }
24 changes: 24 additions & 0 deletions src/app/api/auth/[slug]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import signup_ from "../signup";

const authApiHandler_ = async function GET(
request: Request,
{ params }: { params: { slug: string } }
) {
const slug = params.slug;

const authFunctions: { [key: string]: (request: Request) => {} } = {
signup: signup_,
};

if (authFunctions[slug]) {
return authFunctions[slug](request);
} else {
const response = { isError: true };

return new Response(JSON.stringify(response), {
status: 200,
});
}
};

export { authApiHandler_ as POST };
62 changes: 62 additions & 0 deletions src/app/api/auth/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { MongoDBAdapter } from "@auth/mongodb-adapter";
import NextAuth, { NextAuthOptions } from "next-auth";
import EmailProvider from "next-auth/providers/email";
import CredentialsProvider from "next-auth/providers/credentials";
import mongoClientPromise from "../lib/db";

export const authOptions: NextAuthOptions = {
adapter: MongoDBAdapter(mongoClientPromise),


pages: {
signIn: "/auth/signin",
signOut: "/auth/signout",
error: "/auth/error", // Error code passed in query string as ?error=
verifyRequest: "/auth/verify-request", // (used for check email message)
newUser: "/auth/new-user", // New users will be directed here on first sign in (leave the property out if not of interest)
},

providers: [
CredentialsProvider({
// The name to display on the sign in form (e.g. "Sign in with...")
name: "Credentials",
// `credentials` is used to generate a form on the sign in page.
// You can specify which fields should be submitted, by adding keys to the `credentials` object.
// e.g. domain, username, password, 2FA token, etc.
// You can pass any HTML attribute to the <input> tag through the object.
credentials: {
username: { label: "Username", type: "text", placeholder: "jsmith" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, req) {
// Add logic here to look up the user from the credentials supplied
const user = { id: "1", name: "J Smith", email: "jsmith@example.com" };

if (!user) {
// Any object returned will be saved in `user` property of the JWT
return user;
} else {
// If you return null then an error will be displayed advising the user to check their details.
return null;

// You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
}
},
}),
EmailProvider({
server: process.env.EMAIL_SERVER,
from: process.env.EMAIL_FROM,
}),
],
theme: {
colorScheme: "light",
},
callbacks: {
async jwt({ token }) {
token.userRole = "admin";
return token;
},
},
};

export default NextAuth(authOptions);
84 changes: 84 additions & 0 deletions src/app/api/auth/signup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { zfd } from "zod-form-data";
import { realmApp } from "../lib/db/realm";
import { dbClient } from "../lib/db";
import { dbCollections } from "../lib/db/collections";
import i18next from "i18next";

export default async function signup_(request: Request) {
const schema = zfd.formData({
email: zfd.text(),
password: zfd.text(),
});
const formBody = await request.json();

const { email, password } = schema.parse(formBody);

try {
const db = await dbClient();

if (!db) {
const response = {
isError: true,
msg: i18next.t("home"),
};
return new Response(JSON.stringify(response), {
status: 200,
});
}

const user = await db.collection(dbCollections.users.name).findOne({
email,
});

if (user) {
const response = {
isError: true,
msg: i18next.t("user_exist"),
};
return new Response(JSON.stringify(response), {
status: 200,
});
}

const resp = await realmApp.emailPasswordAuth.registerUser({
email,
password,
});

//TODO: verify schema
await db.collection(dbCollections.users.name).insertOne({
email,
is_verified: false,
created_at: new Date(),
});

const response = {
isError: false,
msg: i18next.t('user_created'),
email,
};

return new Response(JSON.stringify(response), {
status: 200,
});
} catch (error) {
const errorCodeIndex = `${JSON.stringify(error)}`.lastIndexOf("code");

const code =
errorCodeIndex === -1
? 0
: Number(`${error}`.substring(errorCodeIndex).match(/\d+/g));

const resp = {
isError: true,
msg:
code === 4348
? i18next.t("email_error")
: i18next.t('unknown_error'),
};

return new Response(JSON.stringify(resp), {
status: 200,
});
}
}
65 changes: 0 additions & 65 deletions src/app/api/db/auth/[...nextauth].ts

This file was deleted.

8 changes: 8 additions & 0 deletions src/app/api/lib/db/collections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { TdbCollection } from "./types";

export const dbCollections: TdbCollection = {
users: {
name: "users",
label: "Users",
},
};
37 changes: 37 additions & 0 deletions src/app/api/lib/db/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { MongoClient } from "mongodb";

if (!process.env.MONGODB_URI) {
throw new Error('Invalid/Missing environment variable: "MONGODB_URI"');
}

const uri = process.env.MONGODB_URI;
const options = {};

let client: MongoClient;
let mongoClientPromise: Promise<MongoClient>;

if (process.env.NODE_ENV === "development") {
//@ts-ignore
if (!global._mongomongoClientPromise) {
client = new MongoClient(uri, options);
//@ts-ignore
global._mongomongoClientPromise = client.connect();
}
//@ts-ignore
mongoClientPromise = global._mongomongoClientPromise;
} else {
client = new MongoClient(uri, options);
mongoClientPromise = client.connect();
}

export const dbClient = async () => {
try {
const mongoClient = new MongoClient(uri, options);
const dbConnection = await mongoClient.connect();
return dbConnection.db(process.env.MONGODB_DB);
} catch (error) {
return null;
}
};

export default mongoClientPromise;
5 changes: 5 additions & 0 deletions src/app/api/lib/db/realm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Realm from "realm";

export const realmApp = new Realm.App({
id: process.env.REALM_APP_ID as string,
});
Loading

0 comments on commit 0e43fa8

Please sign in to comment.