add user leantime api
This commit is contained in:
parent
9a51d8cd88
commit
dc0021dc91
@ -200,6 +200,57 @@ function validateUsername(username: string): { isValid: boolean; error?: string
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
// Helper function to create user in Leantime
|
||||
async function createLeantimeUser(userData: {
|
||||
username: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
email: string;
|
||||
}): Promise<{ success: boolean; error?: string }> {
|
||||
try {
|
||||
const response = await fetch('https://agilite.slm-lab.net/api/jsonrpc', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${process.env.LEANTIME_TOKEN}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
method: 'leantime.rpc.Users.Users.addUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
values: {
|
||||
firstname: userData.firstName,
|
||||
lastname: userData.lastName,
|
||||
username: userData.username,
|
||||
email: userData.email,
|
||||
status: 'active',
|
||||
role: 'user', // Default role in Leantime
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!response.ok || !data.result) {
|
||||
console.error('Leantime user creation failed:', data);
|
||||
return {
|
||||
success: false,
|
||||
error: 'Failed to create user in Leantime'
|
||||
};
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('Error creating Leantime user:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: 'Error creating user in Leantime'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const session = await getServerSession(authOptions);
|
||||
|
||||
@ -257,7 +308,7 @@ export async function POST(req: Request) {
|
||||
);
|
||||
}
|
||||
|
||||
// Create the user
|
||||
// Create the user in Keycloak
|
||||
const createResponse = await fetch(
|
||||
`${process.env.KEYCLOAK_BASE_URL}/admin/realms/${process.env.KEYCLOAK_REALM}/users`,
|
||||
{
|
||||
@ -356,6 +407,20 @@ export async function POST(req: Request) {
|
||||
);
|
||||
}
|
||||
|
||||
// Create user in Leantime
|
||||
const leantimeResult = await createLeantimeUser({
|
||||
username: data.username,
|
||||
firstName: data.firstName,
|
||||
lastName: data.lastName,
|
||||
email: data.email,
|
||||
});
|
||||
|
||||
if (!leantimeResult.success) {
|
||||
console.error("Leantime user creation failed:", leantimeResult.error);
|
||||
// We don't return an error here since Keycloak user was created successfully
|
||||
// We just log the error and continue
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
user: {
|
||||
|
||||
338
keycloak-user-creation-workflow.json
Normal file
338
keycloak-user-creation-workflow.json
Normal file
@ -0,0 +1,338 @@
|
||||
{
|
||||
"name": "Keycloak User Creation",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {
|
||||
"path": "create-user",
|
||||
"options": {
|
||||
"responseMode": "lastNode",
|
||||
"responseData": "allEntries"
|
||||
}
|
||||
},
|
||||
"name": "Webhook",
|
||||
"type": "n8n-nodes-base.webhook",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
100,
|
||||
300
|
||||
],
|
||||
"webhookId": "create-user-webhook"
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://connect.slm-lab.net/admin/realms/cercle/users",
|
||||
"options": {},
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"nodeCredentialType": "httpHeaderAuth",
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Authorization",
|
||||
"value": "={{$node[\"Get Admin Token\"].json[\"access_token\"]}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "HTTP Request",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 3,
|
||||
"position": [
|
||||
500,
|
||||
300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://connect.slm-lab.net/realms/cercle/protocol/openid-connect/token",
|
||||
"options": {},
|
||||
"authentication": "genericCredentialType",
|
||||
"genericAuthType": "httpHeaderAuth",
|
||||
"nodeCredentialType": "httpHeaderAuth",
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/x-www-form-urlencoded"
|
||||
}
|
||||
]
|
||||
},
|
||||
"bodyParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "grant_type",
|
||||
"value": "client_credentials"
|
||||
},
|
||||
{
|
||||
"name": "client_id",
|
||||
"value": "lab"
|
||||
},
|
||||
{
|
||||
"name": "client_secret",
|
||||
"value": "LwgeE1ntADD20OuWC88S3pR0EaO7FtO4"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "Get Admin Token",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 3,
|
||||
"position": [
|
||||
300,
|
||||
300
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"conditions": {
|
||||
"string": [
|
||||
{
|
||||
"value1": "={{$json[\"isValid\"]}}",
|
||||
"value2": "false"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "IF",
|
||||
"type": "n8n-nodes-base.if",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
300,
|
||||
500
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"functionCode": "// Validate username according to Keycloak requirements\nconst username = $input.item.json.username;\n\n// Keycloak username requirements:\n// - Only alphanumeric characters, dots (.), hyphens (-), and underscores (_)\n// - Must start with a letter or number\n// - Must be between 3 and 255 characters\nconst usernameRegex = /^[a-zA-Z0-9][a-zA-Z0-9._-]{2,254}$/;\n\nif (!usernameRegex.test(username)) {\n return {\n isValid: false,\n error: \"Le nom d'utilisateur doit commencer par une lettre ou un chiffre, ne contenir que des lettres, chiffres, points, tirets et underscores, et faire entre 3 et 255 caractères\"\n };\n}\n\nreturn { isValid: true };"
|
||||
},
|
||||
"name": "Validate Username",
|
||||
"type": "n8n-nodes-base.function",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
300,
|
||||
400
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://connect.slm-lab.net/admin/realms/cercle/roles",
|
||||
"options": {}
|
||||
},
|
||||
"name": "Get Available Roles",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 3,
|
||||
"position": [
|
||||
500,
|
||||
400
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"functionCode": "// Filter valid roles\nconst requestedRoles = $input.item.json.roles || [];\nconst availableRoles = $input.item.json.roles;\n\nconst validRoles = requestedRoles.filter(roleName => \n availableRoles.some(r => r.name === roleName)\n);\n\nif (validRoles.length === 0) {\n return {\n isValid: false,\n error: \"Aucun rôle valide n'a été spécifié\"\n };\n}\n\nreturn {\n isValid: true,\n validRoles: validRoles,\n roleObjects: validRoles.map(roleName => \n availableRoles.find(r => r.name === roleName)\n )\n};"
|
||||
},
|
||||
"name": "Validate Roles",
|
||||
"type": "n8n-nodes-base.function",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
700,
|
||||
400
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://connect.slm-lab.net/admin/realms/cercle/users",
|
||||
"options": {},
|
||||
"body": {
|
||||
"username": "={{$input.item.json.username}}",
|
||||
"enabled": true,
|
||||
"emailVerified": true,
|
||||
"firstName": "={{$input.item.json.firstName}}",
|
||||
"lastName": "={{$input.item.json.lastName}}",
|
||||
"email": "={{$input.item.json.email}}",
|
||||
"credentials": [
|
||||
{
|
||||
"type": "password",
|
||||
"value": "={{$input.item.json.password}}",
|
||||
"temporary": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"name": "Create User",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 3,
|
||||
"position": [
|
||||
900,
|
||||
400
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://connect.slm-lab.net/admin/realms/cercle/users?username={{$input.item.json.username}}",
|
||||
"options": {}
|
||||
},
|
||||
"name": "Get Created User",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 3,
|
||||
"position": [
|
||||
1100,
|
||||
400
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"url": "https://connect.slm-lab.net/admin/realms/cercle/users/{{$input.item.json[0].id}}/role-mappings/realm",
|
||||
"options": {},
|
||||
"body": "={{$input.item.json.roleObjects}}"
|
||||
},
|
||||
"name": "Assign Roles",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 3,
|
||||
"position": [
|
||||
1300,
|
||||
400
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"functionCode": "// Format success response\nreturn {\n success: true,\n user: {\n ...$input.item.json[0],\n roles: $input.item.json.validRoles\n }\n};"
|
||||
},
|
||||
"name": "Format Response",
|
||||
"type": "n8n-nodes-base.function",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
1500,
|
||||
400
|
||||
]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"functionCode": "// Format error response\nreturn {\n success: false,\n error: $input.item.json.error\n};"
|
||||
},
|
||||
"name": "Format Error",
|
||||
"type": "n8n-nodes-base.function",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
500,
|
||||
600
|
||||
]
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Webhook": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Admin Token",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Admin Token": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "HTTP Request",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"node": "Validate Username",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Validate Username": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "IF",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"IF": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Format Error",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"node": "Get Available Roles",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Available Roles": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Validate Roles",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Validate Roles": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Create User",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Create User": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Created User",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Created User": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Assign Roles",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Assign Roles": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Format Response",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user