因此,我试图向现有用户发送补丁请求以更新一些信息。我已经设置了api权限并授予了他们同意,所以我真的不明白为什么会出现这个错误;
{
"error": {
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
"innerError": {
"date": "2024-12-30T06:59:17",
"request-id": "55f9f873-b7b3-424a-95ab-5b5f21e3593b",
"client-request-id": "// wont show this"
}
}
}
如您所见,我是一名全球管理员
这些也是我的api权限,因为我在nextjs代码中使用了graphapi。
如果需要,这是我的代码。
import { useState, useEffect } from "react";
import axios from "axios";
import Head from "next/head";
import { useRouter } from "next/router";
interface FormData {
displayName: string;
mailNickname: string;
password: string;
customField: string;
organizationalUnitCode: string;
}
interface OrganizationalUnit {
code: string;
name: string;
}
const getAccessToken = async (): Promise<string> => {
try {
const response = await axios.post("/api/register");
return response.data.accessToken;
} catch (error) {
console.error("Error fetching token:", error);
throw new Error("Failed to fetch access token");
}
};
const findExistingUserByEmail = async (accessToken: string, email: string) => {
try {
const response = await axios.get(
`https:
{
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
}
);
if (response.data.value.length > 0) {
const user = response.data.value[0];
console.log("Found user:", user);
return user;
}
return null;
} catch (error) {
const err = error as any;
console.error("Error finding user by email:", err.response?.data || err.message);
throw new Error("Failed to find user by email");
}
};
const updateUser = async (accessToken: string, userId: string, userData: FormData) => {
console.log(userId)
try {
const response = await axios.patch(
`https:
{
id: userId,
displayName: userData.displayName,
mailNickname: userData.mailNickname,
passwordProfile: userData.password ? { password: userData.password } : undefined,
[ `extension_${process.env.NEXT_PUBLIC_AZURE_AD_B2C_Extension_ID}_organizationalUnitCode` ]: userData.organizationalUnitCode,
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
}
);
console.log("User updated successfully:", response.data);
return response.data;
} catch (error) {
const err = error as any;
console.error("Error updating user:", err.response?.data || err.message);
throw new Error(`Failed to update user: ${err.response?.data?.error?.message || err.message}`);
}
};
const createUser = async (accessToken: string, userData: FormData) => {
try {
const mailNickname = userData.mailNickname;
const email = userData.displayName;
if (!email.includes("@")) {
throw new Error("Display Name must be a valid email address.");
}
const domain = email.split("@")[1];
const formattedMailNickname = `${mailNickname}_${domain.split(".")[0]}.com`;
const formattedEmail = `${formattedMailNickname}#EXT#@floadingwatkanikladen.onmicrosoft.com`;
const response = await axios.post(
"https://graph.microsoft.com/v1.0/users",
{
accountEnabled: true,
displayName: userData.displayName,
mailNickname: formattedMailNickname,
userPrincipalName: formattedEmail,
otherMails: [userData.displayName],
passwordProfile: {
forceChangePasswordNextSignIn: false,
password: userData.password,
},
[`extension_${process.env.NEXT_PUBLIC_AZURE_AD_B2C_Extension_ID}_organizationalUnitCode`]:
userData.organizationalUnitCode,
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
}
);
return response.data;
} catch (err) {
console.error("Error creating user:", err);
throw err;
}
};
const SignupForm = () => {
const router = useRouter();
const { email, organizationalUnitCode } = router.query;
const [formData, setFormData] = useState<FormData>({
displayName: "",
mailNickname: "",
password: "",
customField: "",
organizationalUnitCode: "",
});
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState<string | null>(null);
const [organizationalUnits, setOrganizationalUnits] = useState<OrganizationalUnit[]>([]);
useEffect(() => {
const fetchOrganizationalUnits = async () => {
try {
const response = await axios.get(
"https://watkanikladenapi2-gwhpc3htfzhrh7e2.westeurope-01.azurewebsites.net/organizational-units"
);
setOrganizationalUnits(response.data.organizationalUnits);
} catch (error) {
console.error("Error fetching organizational units:", error);
}
};
fetchOrganizationalUnits();
}, []);
useEffect(() => {
if (email) {
setFormData((prevData) => ({
...prevData,
mailNickname: email as string,
organizationalUnitCode: organizationalUnitCode as string || "",
}));
}
}, [email, organizationalUnitCode]);
const handleCreate = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
setSuccess(null);
try {
const accessToken = await getAccessToken();
const result = await createUser(accessToken, formData);
console.log("User created:", result);
setSuccess("User created successfully!");
} catch (err) {
console.error("Error creating user:", err);
setError(`An error occurred: ${(err as Error).message}`);
} finally {
setLoading(false);
}
};
const handleUpdate = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
setSuccess(null);
try {
const accessToken = await getAccessToken();
const existingUser = await findExistingUserByEmail(accessToken, formData.displayName);
if (existingUser) {
console.log("User ID to update:", existingUser.id);
const result = await updateUser(accessToken, existingUser.id, formData);
console.log("User updated:", result);
setSuccess("User updated successfully!");
} else {
setError("User not found for updating.");
}
} catch (err) {
console.error("Error updating user:", err);
setError(`An error occurred: ${(err as Error).message}`);
} finally {
setLoading(false);
}
};
return (
<>
<Head>
<link
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css"
rel="stylesheet"
/>
</Head>
<div className="min-h-screen flex items-center justify-center bg-gray-100 py-12 px-4">
<div className="bg-white p-8 rounded-lg shadow-lg max-w-md w-full">
<h1 className="text-2xl font-bold text-center text-gray-800 mb-6">Sign Up / Update</h1>
<form>
<input
type="text"
placeholder="Display Name"
value={formData.displayName}
onChange={(e) => setFormData({ ...formData, displayName: e.target.value })}
className="w-full p-3 mb-4 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<input
type="text"
placeholder="Mail Nickname"
value={formData.mailNickname}
onChange={(e) => setFormData({ ...formData, mailNickname: e.target.value })}
className="w-full p-3 mb-4 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
readOnly={!!email}
/>
<input
type="password"
placeholder="Password"
value={formData.password}
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
className="w-full p-3 mb-4 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<select
value={formData.organizationalUnitCode}
onChange={(e) => setFormData({ ...formData, organizationalUnitCode: e.target.value })}
className="w-full p-3 mb-4 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">Select Organizational Unit</option>
{organizationalUnits.map((unit) => (
<option key={unit.code} value={unit.code}>
{unit.name}
</option>
))}
</select>
<button
onClick={handleCreate}
disabled={loading}
className="w-full bg-green-500 hover:bg-green-600 text-white font-bold py-3 rounded-lg focus:outline-none focus:ring-2 focus:ring-green-500 mb-4"
>
{loading ? "Processing..." : "Create User"}
</button>
<button
onClick={handleUpdate}
disabled={loading}
className="w-full bg-blue-500 hover:bg-blue-600 text-white font-bold py-3 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
>
{loading ? "Processing..." : "Update User"}
</button>
{error && <p className="text-red-500 text-center mt-4">{error}</p>}
{success && <p className="text-green-500 text-center mt-4">{success}</p>}
</form>
</div>
</div>
</>
);
};
export default SignupForm;
enter code here