Merge dev into main

This commit is contained in:
mARTin 2026-03-03 14:05:49 +01:00
commit 3a4e04702a
7 changed files with 78 additions and 6 deletions

View File

@ -35,6 +35,8 @@ The application requires the following environment variables:
- `DATABASE_URL`: PostgreSQL connection string
- `NEXTAUTH_SECRET`: Secret for NextAuth.js
- `NEXT_PUBLIC_BASE_URL`: Public URL of the application
- `MICROSOFT_CLIENT_ID`: Azure AD Application (client) ID for Microsoft Login
- `MICROSOFT_CLIENT_SECRET`: Azure AD Application secret for Microsoft Login
### Database Configuration

11
package-lock.json generated
View File

@ -10,6 +10,7 @@
"license": "MIT",
"dependencies": {
"@auth/prisma-adapter": "^2.11.1",
"@next-auth/prisma-adapter": "^1.0.7",
"@prisma/client": "^5.22.0",
"@types/bcryptjs": "^2.4.6",
"@types/nodemailer": "^7.0.11",
@ -1955,6 +1956,16 @@
"@tybys/wasm-util": "^0.10.0"
}
},
"node_modules/@next-auth/prisma-adapter": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@next-auth/prisma-adapter/-/prisma-adapter-1.0.7.tgz",
"integrity": "sha512-Cdko4KfcmKjsyHFrWwZ//lfLUbcLqlyFqjd/nYE2m3aZ7tjMNUjpks47iw7NTCnXf+5UWz5Ypyt1dSs1EP5QJw==",
"license": "ISC",
"peerDependencies": {
"@prisma/client": ">=2.26.0 || >=3",
"next-auth": "^4"
}
},
"node_modules/@next/env": {
"version": "14.2.35",
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz",

View File

@ -22,6 +22,7 @@
"license": "MIT",
"dependencies": {
"@auth/prisma-adapter": "^2.11.1",
"@next-auth/prisma-adapter": "^1.0.7",
"@prisma/client": "^5.22.0",
"@types/bcryptjs": "^2.4.6",
"@types/nodemailer": "^7.0.11",

View File

@ -50,6 +50,10 @@ function LoginContent() {
</div>
)}
<p className="weekly-auth-recommended">
Recommended: Log in with email
</p>
{/* Login Form */}
<form onSubmit={handleCredentialsSignIn} className="weekly-auth-form">
<div className="weekly-auth-field">
@ -85,7 +89,7 @@ function LoginContent() {
{/* Divider */}
<div className="weekly-auth-divider">
<span>or</span>
<span>or trust US Big Tech</span>
</div>
{/* Google Sign In */}
@ -118,6 +122,20 @@ function LoginContent() {
Continue with Apple
</button>
{/* Microsoft Sign In */}
<button
type="button"
onClick={() => { setIsLoading(true); signIn('azure-ad', { callbackUrl }); }}
disabled={isLoading}
className="weekly-auth-button"
style={{ marginTop: '0.75rem', backgroundColor: '#0078D4', color: '#fff', border: '1px solid #0078D4' }}
>
<svg className="microsoft-icon" viewBox="0 0 21 21" width="18" height="18" fill="currentColor">
<path d="M10 0H0v10h10V0zM21 0H11v10h10V0zM10 11H0v10h10V11zM21 11H11v10h10V11z" />
</svg>
Continue with Microsoft
</button>
{/* Links */}
<div className="weekly-auth-links">
<Link href="/auth/forgot-password" className="weekly-auth-link">

View File

@ -91,6 +91,10 @@ export default function SignupPage() {
</div>
)}
<p className="weekly-auth-recommended">
Recommended: Sign up with email
</p>
{/* Signup Form */}
<form onSubmit={handleSignup} className="weekly-auth-form">
<div className="weekly-auth-field">
@ -150,7 +154,7 @@ export default function SignupPage() {
{/* Divider */}
<div className="weekly-auth-divider">
<span>or</span>
<span>or trust US Big Tech</span>
</div>
{/* Google Sign Up */}
@ -183,6 +187,20 @@ export default function SignupPage() {
Sign up with Apple
</button>
{/* Microsoft Sign Up */}
<button
type="button"
onClick={() => { setIsLoading(true); signIn('azure-ad', { callbackUrl: '/tasks' }); }}
disabled={isLoading}
className="weekly-auth-button"
style={{ marginTop: '0.75rem', backgroundColor: '#0078D4', color: '#fff', border: '1px solid #0078D4' }}
>
<svg className="microsoft-icon" viewBox="0 0 21 21" width="18" height="18" fill="currentColor">
<path d="M10 0H0v10h10V0zM21 0H11v10h10V0zM10 11H0v10h10V11zM21 11H11v10h10V11z" />
</svg>
Sign up with Microsoft
</button>
{/* Links */}
<div className="weekly-auth-links">
<span className="weekly-auth-text">Already have an account?</span>

View File

@ -186,6 +186,14 @@ h3 {
color: #64748b;
}
.weekly-auth-recommended {
font-size: 0.85rem;
color: #475569;
text-align: center;
margin-bottom: 1rem;
font-weight: 500;
}
.time-indicator {
font-size: 0.875rem;
color: #3b82f6;
@ -330,7 +338,6 @@ h3 {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
/* Auth Form */
.auth-form {
background: white;
border-radius: 8px;

View File

@ -1,13 +1,14 @@
import { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import AzureADProvider from "next-auth/providers/azure-ad";
import AppleProvider from "next-auth/providers/apple";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import CredentialsProvider from "next-auth/providers/credentials";
import { compare } from "bcryptjs";
import { prisma } from "@/lib/prisma";
export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(prisma) as any,
adapter: PrismaAdapter(prisma),
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID || "",
@ -17,7 +18,8 @@ export const authOptions: NextAuthOptions = {
params: {
prompt: "consent",
access_type: "offline",
response_type: "code"
response_type: "code",
scope: "openid profile email https://www.googleapis.com/auth/calendar https://www.googleapis.com/auth/calendar.events https://www.googleapis.com/auth/tasks"
}
}
}),
@ -26,6 +28,18 @@ export const authOptions: NextAuthOptions = {
clientSecret: process.env.APPLE_SECRET || "",
allowDangerousEmailAccountLinking: true,
}),
AzureADProvider({
clientId: process.env.MICROSOFT_CLIENT_ID || "",
clientSecret: process.env.MICROSOFT_CLIENT_SECRET || "",
tenantId: "common",
allowDangerousEmailAccountLinking: true,
authorization: {
params: {
prompt: "consent",
scope: "openid profile email offline_access user.read Calendars.ReadWrite Tasks.ReadWrite"
}
},
}),
CredentialsProvider({
name: "credentials",
credentials: {
@ -70,6 +84,7 @@ export const authOptions: NextAuthOptions = {
}
})
],
debug: true,
session: {
strategy: "jwt"
},