Skip to content

Commit

Permalink
refactoring authorized users
Browse files Browse the repository at this point in the history
  • Loading branch information
paolini committed Feb 1, 2025
1 parent c6e20d5 commit f821b21
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 39 deletions.
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,6 @@ To learn more about Next.js, take a look at the following resources:

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

## build docker image

```bash
Expand Down
17 changes: 17 additions & 0 deletions app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@ async function getClient() {
return client
}

async function getDb() {
const { db } = await databasePromise
return db
}

const {
GOOGLE_AUTH_CLIENT_ID,
GOOGLE_AUTH_CLIENT_SECRET,
DATABASE_NAME,
UNSAFE_AUTOMATIC_LOGIN_EMAIL,
PERMITTED_EMAIL_REGEX,
} = config

const PERMITTED_EMAIL_REGEXP = new RegExp(PERMITTED_EMAIL_REGEX)

const authOptions: AuthOptions = {
providers: discoverProviders(),
callbacks: {
Expand All @@ -27,6 +35,7 @@ const authOptions: AuthOptions = {
if (account?.provider === 'google') {
// you can inspect: profile.email_verified
// and: profile.email

}
return true
},
Expand All @@ -40,6 +49,14 @@ const authOptions: AuthOptions = {
}),
pages: {
signIn: '/api/auth/signin',
},
events: {
async createUser({ user }) {
const db = await getDb();
const authorized = user.email && PERMITTED_EMAIL_REGEXP.test(user.email)
const usersCollection = db.collection('users');
await usersCollection.updateOne({email: user.email}, {$set: {authorized}});
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const config = singleton || (() => {
GOOGLE_AUTH_CLIENT_SECRET: process.env.GOOGLE_AUTH_CLIENT_SECRET || '',
DATABASE_NAME,
DATABASE_URI: process.env.DATABASE_URI || ('mongodb://localhost:27017/' + DATABASE_NAME),
PERMITTED_EMAIL_REGEX: process.env.PERMITTED_EMAIL_REGEX || '.*',
// the following variables are used by next-auth.
// they are included here only for reference
// since they are extracted directly from
Expand All @@ -20,7 +21,6 @@ const config = singleton || (() => {
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
UNSAFE_AUTOMATIC_LOGIN_EMAIL: process.env.UNSAFE_AUTOMATIC_LOGIN_EMAIL,
PERMITTED_EMAIL_REGEX: process.env.PERMITTED_EMAIL_REGEX || '.*',
}

console.log(` ______ _______ _______ _______ _______ _______ _______ _______
Expand Down
21 changes: 3 additions & 18 deletions app/graphql/permissions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { User, Context } from './types'
import config from '../config'
import { isPermittedEmail } from '../utils'
import databasePromise from '../db'

/**
* @param context
Expand All @@ -16,26 +14,13 @@ export function requireAuthenticatedUser(context: Context) {

/**
* @param context
* @returns user object if authenticated and email is permitted by configuration
* @throws error if not authenticated or email is not permitted
* @returns user object if authenticated and authorized
* @throws error otherwise
*/
export function requirePermittedUser(context: Context) {
const user = requireAuthenticatedUser(context)
if (!user?.authorized) {
if (!isPermittedEmail(user?.email)) throw new Error("email not permitted")
/* user is permitted by regex on email address. Store the information in the user object */
user.authorized = true
// async function is being called in sync function
// should be fine... we are not waiting for the result
enableUserAuthorization(user)
return user
}
if (!user?.authorized) throw new Error("user not permitted")
return user

async function enableUserAuthorization(user: User) {
const db = (await databasePromise).db
await db.collection('users').updateOne({ email: user.email }, { $set: { authorized: true } })
}
}

/**
Expand Down
6 changes: 1 addition & 5 deletions app/graphql/resolvers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import databasePromise from "../db"
import { ObjectId } from 'mongodb'

import config from '../config'
import { isPermittedEmail } from '../utils'
import { Context } from './types'
import { requireAdminUser, requireAuthenticatedUser, requirePermittedUser, requireCardAuthentication } from './permissions'

Expand All @@ -23,9 +21,7 @@ export const resolvers = {
if (!context.user) return
const users = (await databasePromise).db.collection('users')
const user = await users.findOne({email: context.user.email})
const admin = config.ADMINS.split(',').includes(context.user.email)
const authorized = isPermittedEmail(context.user.email)
return {...user, admin, authorized}
return {...user}
},

credit: async(_: any, __: {}, context: Context) => {
Expand Down
8 changes: 0 additions & 8 deletions app/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {Temporal} from '@js-temporal/polyfill'

import config from './config'

export function myDateTime(isoTimestamp: string|undefined|null) {
if (isoTimestamp === undefined) return '???'
if (isoTimestamp === null) return '---'
Expand Down Expand Up @@ -31,9 +29,3 @@ export function myTime(isoTimestamp: string|undefined|null) {
const {hour, minute} = zonedDateTime
return `${hour}:${String(minute).padStart(2, '0')}`
}

const PERMITTED_EMAIL_REGEX = new RegExp(config.PERMITTED_EMAIL_REGEX)
export function isPermittedEmail(email: string|null|undefined) {
if (!email) return false
return PERMITTED_EMAIL_REGEX.test(email)
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "dm-coffee",
"version": "1.3.0",
"version": "1.3.1",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down

0 comments on commit f821b21

Please sign in to comment.