Broaden Tasgird task lookup fallbacks
This commit is contained in:
@@ -533,16 +533,88 @@ app.get('/api/tasks/list', async (c) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const baseFields = 'id,user,title,startDate,dueDate,priority,completed,content,size,status,owner,assigned_to,user_name,Username,expand.user.id,expand.user.email,expand.user.name,expand.user.username';
|
const baseFields = 'id,user,title,startDate,dueDate,priority,completed,content,size,status,owner,assigned_to,user_name,Username,expand.user.id,expand.user.email,expand.user.name,expand.user.username';
|
||||||
const fetchTasksByRelationIds = async (userIds: string[]) => {
|
const uniqueById = (records: any[]) => {
|
||||||
|
const seen = new Map<string, any>();
|
||||||
|
for (const record of Array.isArray(records) ? records : []) {
|
||||||
|
const id = String(record?.id || '').trim();
|
||||||
|
if (!id || seen.has(id)) continue;
|
||||||
|
seen.set(id, record);
|
||||||
|
}
|
||||||
|
return Array.from(seen.values());
|
||||||
|
};
|
||||||
|
|
||||||
|
const taskMatchesTarget = (task: any, userIds: string[], nameHints: string[]) => {
|
||||||
|
const idSet = new Set(userIds.map((id) => String(id || '').trim()).filter(Boolean));
|
||||||
|
const lowerHints = nameHints.map((value) => String(value || '').trim().toLowerCase()).filter(Boolean);
|
||||||
|
|
||||||
|
const directUsers = Array.isArray(task?.user)
|
||||||
|
? task.user
|
||||||
|
: (task?.user ? [task.user] : []);
|
||||||
|
if (directUsers.some((value: any) => idSet.has(String(value || '').trim()))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const expandedUsers = Array.isArray(task?.expand?.user)
|
||||||
|
? task.expand.user
|
||||||
|
: (task?.expand?.user ? [task.expand.user] : []);
|
||||||
|
if (expandedUsers.some((user: any) => idSet.has(String(user?.id || '').trim()))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const textFields = [task?.user_name, task?.Username, task?.owner, task?.assigned_to]
|
||||||
|
.map((value) => String(value || '').trim().toLowerCase())
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
return lowerHints.some((hint) => textFields.some((value) => value === hint || value.includes(hint)));
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchTasksByRelationIds = async (userIds: string[], nameHints: string[]) => {
|
||||||
const ids = Array.from(new Set(userIds.map((id) => String(id || '').trim()).filter(Boolean)));
|
const ids = Array.from(new Set(userIds.map((id) => String(id || '').trim()).filter(Boolean)));
|
||||||
if (!ids.length) return [];
|
if (!ids.length) return { records: [], lookupMethod: 'no_user_ids' };
|
||||||
const relationFilter = ids.map((id) => `user = "${id.replace(/"/g, '\\"')}"`).join(' || ');
|
|
||||||
return taskPb.collection(PB_TASKS_COLLECTION).getFullList({
|
const filterAttempts = [
|
||||||
filter: relationFilter,
|
{
|
||||||
|
lookupMethod: 'relation_eq',
|
||||||
|
filter: ids.map((id) => `user = "${id.replace(/"/g, '\\"')}"`).join(' || '),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lookupMethod: 'relation_any_eq',
|
||||||
|
filter: ids.map((id) => `user ?= "${id.replace(/"/g, '\\"')}"`).join(' || '),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let lastError: unknown = null;
|
||||||
|
for (const attempt of filterAttempts) {
|
||||||
|
try {
|
||||||
|
const records = await taskPb.collection(PB_TASKS_COLLECTION).getFullList({
|
||||||
|
filter: attempt.filter,
|
||||||
sort: '-startDate,-created',
|
sort: '-startDate,-created',
|
||||||
expand: 'user',
|
expand: 'user',
|
||||||
fields: baseFields,
|
fields: baseFields,
|
||||||
});
|
});
|
||||||
|
if (records.length) {
|
||||||
|
return { records: uniqueById(records), lookupMethod: attempt.lookupMethod };
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
lastError = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const accessibleTasks = await taskPb.collection(PB_TASKS_COLLECTION).getFullList({
|
||||||
|
sort: '-startDate,-created',
|
||||||
|
expand: 'user',
|
||||||
|
fields: baseFields,
|
||||||
|
});
|
||||||
|
const filtered = accessibleTasks.filter((task: any) => taskMatchesTarget(task, ids, nameHints));
|
||||||
|
return {
|
||||||
|
records: uniqueById(filtered),
|
||||||
|
lookupMethod: 'accessible_fallback',
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
if (lastError) throw lastError;
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveUserIdsByName = async (name: string): Promise<string[]> => {
|
const resolveUserIdsByName = async (name: string): Promise<string[]> => {
|
||||||
@@ -587,6 +659,7 @@ app.get('/api/tasks/list', async (c) => {
|
|||||||
let warning = '';
|
let warning = '';
|
||||||
let effectiveUserId = requestedUserId || meId;
|
let effectiveUserId = requestedUserId || meId;
|
||||||
let effectiveUserName = targetUserName;
|
let effectiveUserName = targetUserName;
|
||||||
|
let lookupMethod = 'unresolved';
|
||||||
try {
|
try {
|
||||||
if (targetUserName) {
|
if (targetUserName) {
|
||||||
const targetUserIds = Array.from(new Set([
|
const targetUserIds = Array.from(new Set([
|
||||||
@@ -598,7 +671,9 @@ app.get('/api/tasks/list', async (c) => {
|
|||||||
warning = `No Users record matched name "${targetUserName}".`;
|
warning = `No Users record matched name "${targetUserName}".`;
|
||||||
records = [];
|
records = [];
|
||||||
} else {
|
} else {
|
||||||
records = await fetchTasksByRelationIds(targetUserIds);
|
const result = await fetchTasksByRelationIds(targetUserIds, [targetUserName, meName]);
|
||||||
|
records = result.records;
|
||||||
|
lookupMethod = result.lookupMethod;
|
||||||
if (!records.length) {
|
if (!records.length) {
|
||||||
warning = `No accessible Tasgird tasks matched Users.name "${targetUserName}".`;
|
warning = `No accessible Tasgird tasks matched Users.name "${targetUserName}".`;
|
||||||
}
|
}
|
||||||
@@ -606,7 +681,9 @@ app.get('/api/tasks/list', async (c) => {
|
|||||||
}
|
}
|
||||||
} else if (requestedUserId || meId) {
|
} else if (requestedUserId || meId) {
|
||||||
const fallbackId = String(requestedUserId || meId).trim();
|
const fallbackId = String(requestedUserId || meId).trim();
|
||||||
records = await fetchTasksByRelationIds([fallbackId]);
|
const result = await fetchTasksByRelationIds([fallbackId], [meName]);
|
||||||
|
records = result.records;
|
||||||
|
lookupMethod = result.lookupMethod;
|
||||||
if (!records.length) {
|
if (!records.length) {
|
||||||
warning = 'No accessible Tasgird tasks matched the current user relation.';
|
warning = 'No accessible Tasgird tasks matched the current user relation.';
|
||||||
}
|
}
|
||||||
@@ -628,7 +705,13 @@ app.get('/api/tasks/list', async (c) => {
|
|||||||
success: true,
|
success: true,
|
||||||
userId: effectiveUserId,
|
userId: effectiveUserId,
|
||||||
userName: effectiveUserName,
|
userName: effectiveUserName,
|
||||||
|
authUser: {
|
||||||
|
id: meId,
|
||||||
|
email: meRecord?.email || '',
|
||||||
|
name: meName,
|
||||||
|
},
|
||||||
count: records.length,
|
count: records.length,
|
||||||
|
lookupMethod,
|
||||||
warning: warning || undefined,
|
warning: warning || undefined,
|
||||||
tasks: records.map((task: any) => ({
|
tasks: records.map((task: any) => ({
|
||||||
id: task.id,
|
id: task.id,
|
||||||
|
|||||||
+6
-1
@@ -387,7 +387,10 @@
|
|||||||
});
|
});
|
||||||
const data = await resp.json().catch(() => ({}));
|
const data = await resp.json().catch(() => ({}));
|
||||||
if (!resp.ok || !data?.success) {
|
if (!resp.ok || !data?.success) {
|
||||||
throw new Error(data?.message || 'Failed to load tasks');
|
const details = data?.details
|
||||||
|
? (typeof data.details === 'string' ? data.details : JSON.stringify(data.details))
|
||||||
|
: '';
|
||||||
|
throw new Error(details ? `${data?.message || 'Failed to load tasks'}: ${details}` : (data?.message || 'Failed to load tasks'));
|
||||||
}
|
}
|
||||||
if (data?.userName && taskUserSelect.value !== data.userName) {
|
if (data?.userName && taskUserSelect.value !== data.userName) {
|
||||||
taskUserSelect.value = data.userName;
|
taskUserSelect.value = data.userName;
|
||||||
@@ -397,6 +400,8 @@
|
|||||||
message: `Loaded ${data?.count ?? 0} task(s)`,
|
message: `Loaded ${data?.count ?? 0} task(s)`,
|
||||||
userName: data?.userName || userName,
|
userName: data?.userName || userName,
|
||||||
userId: data?.userId || undefined,
|
userId: data?.userId || undefined,
|
||||||
|
authUser: data?.authUser || undefined,
|
||||||
|
lookupMethod: data?.lookupMethod || undefined,
|
||||||
warning: data?.warning || undefined,
|
warning: data?.warning || undefined,
|
||||||
tasks: data.tasks || [],
|
tasks: data.tasks || [],
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user