-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lift to updated versions completed. authv5 implemented
- Loading branch information
1 parent
c23d565
commit 4d44ab5
Showing
10 changed files
with
218 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,99 +1,3 @@ | ||
import NextAuth, { AzureADProfile } from 'next-auth'; | ||
import AzureADProvider from 'next-auth/providers/azure-ad'; | ||
import { UserAuthRoles } from '@/config/macros'; | ||
import { SitesRDS, SitesResult } from '@/config/sqlrdsdefinitions/zones'; | ||
import ConnectionManager from '@/config/connectionmanager'; | ||
import MapperFactory from '@/config/datamapper'; | ||
import { handlers } from '@/auth'; | ||
|
||
const handler = NextAuth({ | ||
secret: process.env.NEXTAUTH_SECRET!, | ||
providers: [ | ||
AzureADProvider({ | ||
clientId: process.env.AZURE_AD_CLIENT_ID!, | ||
clientSecret: process.env.AZURE_AD_CLIENT_SECRET!, | ||
tenantId: process.env.AZURE_AD_TENANT_ID!, | ||
authorization: { params: { scope: 'openid profile email user.Read' } } | ||
}) | ||
], | ||
session: { | ||
strategy: 'jwt', | ||
maxAge: 24 * 60 * 60 // 24 hours (you can adjust this value as needed) | ||
}, | ||
callbacks: { | ||
async signIn({ user, profile, email: signInEmail }) { | ||
const azureProfile = profile as AzureADProfile; | ||
const userEmail = user.email || signInEmail || azureProfile.preferred_username; | ||
if (typeof userEmail !== 'string') { | ||
console.error('User email is not a string:', userEmail); | ||
return false; // Email is not a valid string, abort sign-in | ||
} | ||
if (userEmail) { | ||
const connectionManager = ConnectionManager.getInstance(); | ||
let emailVerified, userStatus, userID; | ||
try { | ||
const query = `SELECT UserID, UserStatus FROM catalog.users WHERE Email = '${userEmail}' LIMIT 1`; | ||
const results = await connectionManager.executeQuery(query); | ||
|
||
// emailVerified is true if there is at least one result | ||
emailVerified = results.length > 0; | ||
if (!emailVerified) { | ||
console.error('User email not found.'); | ||
return false; | ||
} | ||
userStatus = results[0].UserStatus; | ||
userID = results[0].UserID; | ||
} catch (e: any) { | ||
console.error('Error fetching user status:', e); | ||
throw new Error('Failed to fetch user status.'); | ||
} | ||
user.userStatus = userStatus as UserAuthRoles; | ||
user.email = userEmail; | ||
const allSites = MapperFactory.getMapper<SitesRDS, SitesResult>('sites').mapData(await connectionManager.executeQuery(`SELECT * FROM catalog.sites`)); | ||
const allowedSites = MapperFactory.getMapper<SitesRDS, SitesResult>('sites').mapData( | ||
await connectionManager.executeQuery( | ||
`SELECT s.* FROM catalog.sites AS s JOIN catalog.usersiterelations AS usr ON s.SiteID = usr.SiteID WHERE usr.UserID = ?`, | ||
[userID] | ||
) | ||
); | ||
if (!allowedSites || !allSites) { | ||
console.error('User does not have any allowed sites.'); | ||
return false; | ||
} | ||
|
||
user.sites = allowedSites; | ||
user.allsites = allSites; | ||
} | ||
return true; | ||
}, | ||
|
||
async jwt({ token, user }) { | ||
// If this is the first time the JWT is issued, persist custom properties | ||
if (user) { | ||
token.userStatus = user.userStatus; | ||
token.sites = user.sites; | ||
token.allsites = user.allsites; | ||
} | ||
return token; | ||
}, | ||
|
||
async session({ session, token }) { | ||
if (typeof token.userStatus === 'string') { | ||
session.user.userStatus = token.userStatus as UserAuthRoles; | ||
} else { | ||
session.user.userStatus = 'field crew' as UserAuthRoles; // default no admin permissions | ||
} | ||
if (token && token.allsites && Array.isArray(token.allsites)) { | ||
session.user.allsites = token.allsites as SitesRDS[]; | ||
} | ||
if (token && token.sites && Array.isArray(token.sites)) { | ||
session.user.sites = token.sites as SitesRDS[]; | ||
} | ||
return session; | ||
} | ||
}, | ||
pages: { | ||
error: '/loginfailed' | ||
} | ||
}); | ||
|
||
export { handler as GET, handler as POST }; | ||
export const { GET, POST } = handlers; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { NextResponse } from 'next/server'; | ||
import ConnectionManager from '@/config/connectionmanager'; | ||
import MapperFactory from '@/config/datamapper'; | ||
import { SitesRDS, SitesResult } from '@/config/sqlrdsdefinitions/zones'; | ||
|
||
export async function POST(req: Request) { | ||
const { email } = await req.json(); | ||
const connectionManager = ConnectionManager.getInstance(); | ||
|
||
try { | ||
const query = `SELECT UserID, UserStatus FROM catalog.users WHERE Email = ? LIMIT 1`; | ||
const results = await connectionManager.executeQuery(query, [email]); | ||
|
||
if (results.length === 0) { | ||
return NextResponse.json({ error: 'User not found' }, { status: 401 }); | ||
} | ||
|
||
const userID = results[0].UserID; | ||
const userStatus = results[0].UserStatus; | ||
|
||
const allSites = MapperFactory.getMapper<SitesRDS, SitesResult>('sites').mapData(await connectionManager.executeQuery(`SELECT * FROM catalog.sites`)); | ||
|
||
const allowedSites = MapperFactory.getMapper<SitesRDS, SitesResult>('sites').mapData( | ||
await connectionManager.executeQuery( | ||
`SELECT s.* FROM catalog.sites AS s JOIN catalog.usersiterelations AS usr ON s.SiteID = usr.SiteID WHERE usr.UserID = ?`, | ||
[userID] | ||
) | ||
); | ||
|
||
return NextResponse.json({ | ||
userStatus, | ||
allSites, | ||
allowedSites | ||
}); | ||
} catch (error) { | ||
console.error('Database error:', error); | ||
return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// auth.ts | ||
import NextAuth from 'next-auth'; | ||
import { UserAuthRoles } from '@/config/macros'; | ||
import { SitesRDS } from '@/config/sqlrdsdefinitions/zones'; | ||
import MicrosoftEntraID from '@auth/core/providers/microsoft-entra-id'; | ||
|
||
export const { auth, handlers, signIn, signOut } = NextAuth({ | ||
secret: process.env.AUTH_SECRET!, | ||
providers: [ | ||
MicrosoftEntraID({ | ||
clientId: process.env.AZURE_AD_CLIENT_ID, | ||
clientSecret: process.env.AZURE_AD_CLIENT_SECRET, | ||
issuer: `https://login.microsoftonline.com/${process.env.AZURE_AD_TENANT_ID}/v2.0` | ||
}) | ||
], | ||
session: { | ||
strategy: 'jwt', | ||
maxAge: 24 * 60 * 60 // 24 hours | ||
}, | ||
callbacks: { | ||
async signIn({ user, profile, email: signInEmail }) { | ||
console.log('url: ', process.env.AUTH_URL); | ||
const userEmail = user.email || signInEmail || profile?.preferred_username; | ||
if (!userEmail) { | ||
return false; // No email, reject sign-in | ||
} | ||
try { | ||
const response = await fetch(`${process.env.NEXTAUTH_URL ?? 'http://localhost:3000'}/api/customsignin`, { | ||
method: 'POST', | ||
headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify({ email: userEmail }) | ||
}); | ||
|
||
if (!response.ok) { | ||
return false; | ||
} | ||
|
||
const data = await response.json(); | ||
user.userStatus = data.userStatus; | ||
user.sites = data.allowedSites; | ||
user.allsites = data.allSites; | ||
} catch (error) { | ||
console.error('Error fetching user data:', error); | ||
return false; | ||
} | ||
|
||
return true; | ||
}, | ||
|
||
async jwt({ token, user }) { | ||
if (user) { | ||
token.userStatus = user.userStatus; | ||
token.sites = user.sites; | ||
token.allsites = user.allsites; | ||
} | ||
return token; | ||
}, | ||
|
||
async session({ session, token }) { | ||
session.user.userStatus = token.userStatus as UserAuthRoles; | ||
session.user.sites = token.sites as SitesRDS[]; | ||
session.user.allsites = token.allsites as SitesRDS[]; | ||
return session; | ||
} | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/// <reference types="next" /> | ||
/// <reference types="next/image-types/global" /> | ||
/// <reference types="next/navigation-types/compat/navigation" /> | ||
|
||
// NOTE: This file should not be edited | ||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. |
Oops, something went wrong.