missions api2
This commit is contained in:
parent
95efd51e30
commit
8cc401f09a
@ -64,98 +64,17 @@ export class LeantimeService {
|
||||
|
||||
console.log('Creating project with data:', JSON.stringify(projectData, null, 2));
|
||||
|
||||
// Create with direct call to createProject
|
||||
const createResponse = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.createProject',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: projectData
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Log the response
|
||||
console.log('Create response status:', createResponse.status);
|
||||
console.log('Create response data:', JSON.stringify(createResponse.data, null, 2));
|
||||
|
||||
if (createResponse.data && createResponse.data.result) {
|
||||
const projectId = createResponse.data.result;
|
||||
console.log(`Created Leantime project with ID: ${projectId}`);
|
||||
|
||||
// If the mission has a logo, set it as project avatar
|
||||
if (mission.logo) {
|
||||
await this.setProjectAvatar(projectId, mission.logo);
|
||||
}
|
||||
|
||||
try {
|
||||
// Wait a bit before attempting to add any users to avoid rate limits
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
// Check if we can make at least one API call without hitting rate limits
|
||||
const testResponse = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Auth.getCurrentUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// If test API call succeeds, try to assign users
|
||||
if (mission.missionUsers && mission.missionUsers.length > 0) {
|
||||
await this.assignUsersToProject(projectId, mission.missionUsers);
|
||||
}
|
||||
} catch (apiError) {
|
||||
// If we hit rate limits on the test call, skip user assignment completely
|
||||
if (axios.isAxiosError(apiError) && apiError.response?.status === 429) {
|
||||
console.log('⚠️ Rate limiting detected. Skipping all user assignments.');
|
||||
console.log(`⚠️ Users will need to be added manually at: ${this.getProjectUrl(projectId)}`);
|
||||
} else {
|
||||
// Try to assign users anyway for other types of errors
|
||||
if (mission.missionUsers && mission.missionUsers.length > 0) {
|
||||
await this.assignUsersToProject(projectId, mission.missionUsers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return projectId;
|
||||
}
|
||||
|
||||
// Fall back to addProject if createProject fails
|
||||
console.log('createProject failed, trying addProject...');
|
||||
|
||||
// Based on the error message, Leantime expects a nested 'values' parameter
|
||||
// Use only the method that we know works
|
||||
const payload = {
|
||||
method: 'leantime.rpc.Projects.Projects.addProject',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
values: {
|
||||
name: mission.name,
|
||||
clientId: clientId,
|
||||
details: mission.intention || '',
|
||||
type: 'project',
|
||||
start: formattedStartDate,
|
||||
end: formattedEndDate,
|
||||
status: 'open',
|
||||
psettings: 'restricted'
|
||||
}
|
||||
values: projectData
|
||||
}
|
||||
};
|
||||
|
||||
console.log('addProject payload:', JSON.stringify(payload, null, 2));
|
||||
console.log('Project creation payload:', JSON.stringify(payload, null, 2));
|
||||
|
||||
const response = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
@ -168,14 +87,14 @@ export class LeantimeService {
|
||||
}
|
||||
);
|
||||
|
||||
console.log('addProject response status:', response.status);
|
||||
console.log('addProject response data:', JSON.stringify(response.data, null, 2));
|
||||
console.log('Project creation response status:', response.status);
|
||||
console.log('Project creation response data:', JSON.stringify(response.data, null, 2));
|
||||
|
||||
if (!response.data || !response.data.result) {
|
||||
throw new Error(`Failed to create Leantime project: ${JSON.stringify(response.data)}`);
|
||||
}
|
||||
|
||||
const projectId = response.data.result;
|
||||
const projectId = response.data.result[0]; // We need the first element in the array
|
||||
console.log(`Created Leantime project with ID: ${projectId}`);
|
||||
|
||||
// If the mission has a logo, set it as project avatar
|
||||
@ -183,40 +102,13 @@ export class LeantimeService {
|
||||
await this.setProjectAvatar(projectId, mission.logo);
|
||||
}
|
||||
|
||||
try {
|
||||
// Wait a bit before attempting to add any users to avoid rate limits
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
// Check if we can make at least one API call without hitting rate limits
|
||||
const testResponse = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Auth.getCurrentUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// If test API call succeeds, try to assign users
|
||||
if (mission.missionUsers && mission.missionUsers.length > 0) {
|
||||
await this.assignUsersToProject(projectId, mission.missionUsers);
|
||||
}
|
||||
} catch (apiError) {
|
||||
// If we hit rate limits on the test call, skip user assignment completely
|
||||
if (axios.isAxiosError(apiError) && apiError.response?.status === 429) {
|
||||
console.log('⚠️ Rate limiting detected. Skipping all user assignments.');
|
||||
console.log(`⚠️ Users will need to be added manually at: ${this.getProjectUrl(projectId)}`);
|
||||
} else {
|
||||
// Try to assign users anyway for other types of errors
|
||||
if (mission.missionUsers && mission.missionUsers.length > 0) {
|
||||
await this.assignUsersToProject(projectId, mission.missionUsers);
|
||||
}
|
||||
}
|
||||
// Check if mission has users to assign
|
||||
if (mission.missionUsers && mission.missionUsers.length > 0) {
|
||||
await this.assignUsersToProject(projectId, mission.missionUsers);
|
||||
} else {
|
||||
// No users to assign
|
||||
const projectUrl = this.getProjectUrl(projectId);
|
||||
console.log(`ℹ️ No users to assign. Project created at: ${projectUrl}`);
|
||||
}
|
||||
|
||||
return projectId;
|
||||
@ -332,112 +224,12 @@ export class LeantimeService {
|
||||
* @param missionUsers The mission users with roles
|
||||
*/
|
||||
async assignUsersToProject(projectId: number, missionUsers: any[]): Promise<void> {
|
||||
console.log(`Attempting to add ${missionUsers.length} users to project ${projectId}`);
|
||||
const projectUrl = this.getProjectUrl(projectId);
|
||||
console.log(`⚠️ For best results, please assign users manually at: ${projectUrl}`);
|
||||
console.log('ℹ️ Automatic user assignment is currently disabled due to API limitations.');
|
||||
|
||||
// Create a direct URL to the project that can be shared with users
|
||||
const baseUrl = this.apiUrl
|
||||
.replace('/api/jsonrpc', '')
|
||||
.replace('/api/jsonrpc.php', '');
|
||||
|
||||
const projectUrl = baseUrl.endsWith('/')
|
||||
? `${baseUrl}projects/showProject/${projectId}`
|
||||
: `${baseUrl}/projects/showProject/${projectId}`;
|
||||
|
||||
console.log(`🔗 Project created successfully. Direct project URL: ${projectUrl}`);
|
||||
|
||||
if (!missionUsers || missionUsers.length === 0) {
|
||||
console.log('No users to assign to the project.');
|
||||
|
||||
// Ensure at least the API user is assigned to prevent "Current team member is New API Access" issue
|
||||
console.log('Ensuring API user is assigned to the project to prevent orphaned projects.');
|
||||
// Wait a bit longer before API user request to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
const apiUserId = await this.getApiUserId();
|
||||
if (apiUserId) {
|
||||
try {
|
||||
const apiAssigned = await this.assignApiUserToProject(projectId, apiUserId);
|
||||
if (apiAssigned) {
|
||||
console.log('API user successfully assigned to project as admin.');
|
||||
}
|
||||
} catch (apiUserError) {
|
||||
console.error('Error assigning API user to project:', apiUserError);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Users will need to be added manually if the automatic assignment fails
|
||||
console.log('Attempting to assign users to the project - if this fails, users can be added manually through the Leantime interface.');
|
||||
|
||||
try {
|
||||
let successCount = 0;
|
||||
let errorCount = 0;
|
||||
|
||||
// First try to assign just one user (the first one) to reduce API calls and avoid rate limits
|
||||
const firstUser = missionUsers[0];
|
||||
try {
|
||||
const leantimeUserId = await this.getUserByEmail(firstUser.user.email);
|
||||
if (leantimeUserId) {
|
||||
const role = firstUser.role === 'gardien-temps' ? 'editor' : 'commenter';
|
||||
const success = await this.assignUserToProject(projectId, leantimeUserId, role);
|
||||
if (success) {
|
||||
successCount++;
|
||||
console.log(`✅ Successfully assigned user ${firstUser.user.email} to project ${projectId}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error assigning first user: ${error}`);
|
||||
}
|
||||
|
||||
// Skip other users if we got at least one successful assignment
|
||||
if (successCount > 0) {
|
||||
console.log(`Successfully assigned ${successCount} user to project. Skipping other users to avoid rate limits.`);
|
||||
console.log(`⚠️ Other users will need to be added manually at: ${projectUrl}`);
|
||||
errorCount = missionUsers.length - successCount;
|
||||
} else {
|
||||
// If first user failed, try API user assignment
|
||||
console.log('No regular users successfully assigned. Adding API user as a fallback.');
|
||||
// Wait a bit longer before API user request to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
const apiUserId = await this.getApiUserId();
|
||||
if (apiUserId) {
|
||||
try {
|
||||
const apiAssigned = await this.assignApiUserToProject(projectId, apiUserId);
|
||||
if (apiAssigned) {
|
||||
successCount++;
|
||||
console.log('✅ API user successfully assigned to project as admin.');
|
||||
}
|
||||
} catch (apiUserError) {
|
||||
console.error('Error assigning API user to project:', apiUserError);
|
||||
}
|
||||
}
|
||||
errorCount = missionUsers.length;
|
||||
}
|
||||
|
||||
console.log(`User assignment complete: ${successCount} successful, ${errorCount} failed.`);
|
||||
|
||||
if (errorCount > 0) {
|
||||
console.log(`⚠️ Some users could not be assigned automatically. They will need to be added manually at: ${projectUrl}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error assigning users to project:', error);
|
||||
console.log(`⚠️ Users will need to be added manually at: ${projectUrl}`);
|
||||
|
||||
// Always ensure the API user is assigned as a last resort
|
||||
try {
|
||||
// Wait a bit longer before API user request to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
const apiUserId = await this.getApiUserId();
|
||||
if (apiUserId) {
|
||||
const apiAssigned = await this.assignApiUserToProject(projectId, apiUserId);
|
||||
if (apiAssigned) {
|
||||
console.log('✅ API user assigned as fallback to prevent orphaned project.');
|
||||
}
|
||||
}
|
||||
} catch (apiUserError) {
|
||||
console.error('Error assigning API user as fallback:', apiUserError);
|
||||
}
|
||||
}
|
||||
// No automatic user assignment - this was causing too many issues
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -499,159 +291,41 @@ export class LeantimeService {
|
||||
try {
|
||||
console.log(`Assigning user ${userId} to project ${projectId} with role ${role}`);
|
||||
|
||||
// First, check if the user is already assigned to the project
|
||||
const alreadyAssigned = await this.verifyUserAssignedToProject(userId, projectId);
|
||||
if (alreadyAssigned) {
|
||||
console.log(`✅ User ${userId} is already assigned to project ${projectId}`);
|
||||
// Wait before making the API call to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
// Use only the method that we know works best
|
||||
const response = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.addProjectUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
projectId: projectId,
|
||||
userId: userId,
|
||||
role: role
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response.data && response.data.result) {
|
||||
console.log(`✅ Assigned user ${userId} to project ${projectId} with role ${role}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try method 1: Projects.Projects.addUser
|
||||
try {
|
||||
const response = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.Projects.addUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
projectId: projectId,
|
||||
userId: userId,
|
||||
role: role
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response.data && response.data.result) {
|
||||
console.log(`Assigned user ${userId} to project ${projectId} with role ${role} (method 1)`);
|
||||
|
||||
// Verify assignment was successful
|
||||
const verified = await this.verifyUserAssignedToProject(userId, projectId);
|
||||
if (verified) {
|
||||
return true;
|
||||
} else {
|
||||
console.log('Assignment appeared successful but verification failed. Trying next method...');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Method 1 failed, trying next method...');
|
||||
}
|
||||
|
||||
// Try method 2: Projects.addProjectUser
|
||||
try {
|
||||
const response2 = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.addProjectUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
projectId: projectId,
|
||||
userId: userId,
|
||||
role: role
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response2.data && response2.data.result) {
|
||||
console.log(`Assigned user ${userId} to project ${projectId} with role ${role} (method 2)`);
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Method 2 failed, trying next method...');
|
||||
}
|
||||
|
||||
// Try method 3: Projects.Projects.addProjectUser
|
||||
try {
|
||||
const response3 = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.Projects.addProjectUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
projectId: projectId,
|
||||
userId: userId,
|
||||
role: role
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response3.data && response3.data.result) {
|
||||
console.log(`Assigned user ${userId} to project ${projectId} with role ${role} (method 3)`);
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Method 3 failed, trying next method...');
|
||||
}
|
||||
|
||||
// Try method 4: Projects.editUserProjectRelations
|
||||
try {
|
||||
// This method might take a different param structure
|
||||
const response4 = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.editUserProjectRelations',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
action: 'add',
|
||||
userId: userId,
|
||||
projects: [{
|
||||
id: projectId,
|
||||
role: role
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response4.data && response4.data.result) {
|
||||
console.log(`Assigned user ${userId} to project ${projectId} with role ${role} (method 4)`);
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Method 4 failed.');
|
||||
}
|
||||
|
||||
// After all methods, verify one last time
|
||||
const finalVerification = await this.verifyUserAssignedToProject(userId, projectId);
|
||||
if (finalVerification) {
|
||||
console.log(`✅ Verified user ${userId} is now assigned to project ${projectId}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we reach here, all methods failed
|
||||
console.warn(`⚠️ Could not assign user ${userId} to project ${projectId} with any method. This is not a critical error, the project was created.`);
|
||||
console.warn(`⚠️ Could not assign user ${userId} to project ${projectId}.`);
|
||||
return false;
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error assigning user ${userId} to project ${projectId}:`, error);
|
||||
// We'll allow this to fail since the project was created successfully
|
||||
console.warn(`⚠️ User assignment failed, but this is not critical. The project ${projectId} was created successfully.`);
|
||||
console.warn(`⚠️ User assignment failed. The project ${projectId} was created successfully, but users will need to be added manually.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -671,14 +345,15 @@ export class LeantimeService {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try various methods to assign the API user
|
||||
|
||||
// Method 1: Direct API assignment
|
||||
// Wait before making the API call to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
// Use only the method that we know works best
|
||||
try {
|
||||
const response = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.Projects.addUser',
|
||||
method: 'leantime.rpc.Projects.addProjectUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
@ -696,81 +371,11 @@ export class LeantimeService {
|
||||
);
|
||||
|
||||
if (response.data && response.data.result) {
|
||||
console.log(`Successfully assigned API user to project ${projectId}`);
|
||||
console.log(`✅ API user successfully assigned to project ${projectId}`);
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('API user assignment method 1 failed, trying next method...');
|
||||
}
|
||||
|
||||
// Method 2: editUserProjectRelations
|
||||
try {
|
||||
const response = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.editUserProjectRelations',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
action: 'add',
|
||||
userId: apiUserId,
|
||||
projects: [{
|
||||
id: projectId,
|
||||
role: 'admin'
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response.data && response.data.result) {
|
||||
console.log(`Successfully assigned API user to project ${projectId} (method 2)`);
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('API user assignment method 2 failed, trying next method...');
|
||||
}
|
||||
|
||||
// Method 3: addProjectUser
|
||||
try {
|
||||
const response = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Projects.addProjectUser',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
projectId: projectId,
|
||||
userId: apiUserId,
|
||||
role: 'admin'
|
||||
}
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-API-Key': this.apiToken
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (response.data && response.data.result) {
|
||||
console.log(`Successfully assigned API user to project ${projectId} (method 3)`);
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('API user assignment method 3 failed.');
|
||||
}
|
||||
|
||||
// After all methods, verify assignment one last time
|
||||
const finalVerification = await this.verifyUserAssignedToProject(apiUserId, projectId);
|
||||
if (finalVerification) {
|
||||
console.log(`✅ Verified API user ${apiUserId} is now assigned to project ${projectId}`);
|
||||
return true;
|
||||
console.error('Error assigning API user to project:', error);
|
||||
}
|
||||
|
||||
console.warn(`⚠️ Could not assign API user to project ${projectId}. The project may appear with "New API Access" as the only team member.`);
|
||||
@ -851,10 +456,14 @@ export class LeantimeService {
|
||||
*/
|
||||
async createClient(clientName: string): Promise<number | null> {
|
||||
try {
|
||||
// Wait before making the API call to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// Use only the method that works consistently
|
||||
const response = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
method: 'leantime.rpc.Clients.Clients.create',
|
||||
method: 'leantime.rpc.Clients.Clients.addClient',
|
||||
jsonrpc: '2.0',
|
||||
id: 1,
|
||||
params: {
|
||||
@ -894,7 +503,7 @@ export class LeantimeService {
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
|
||||
try {
|
||||
// Try again with a different API method name
|
||||
// Retry with the same method after waiting
|
||||
const retryResponse = await axios.post(
|
||||
this.getApiEndpoint(),
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user