Use user name for tasks lookup with robust fallbacks
This commit is contained in:
@@ -495,39 +495,98 @@ app.get('/api/tasks/list', async (c) => {
|
|||||||
try {
|
try {
|
||||||
const me = pb.authStore.model;
|
const me = pb.authStore.model;
|
||||||
const meId = String(me?.id || '').trim();
|
const meId = String(me?.id || '').trim();
|
||||||
|
const meName = String(me?.name || me?.username || me?.email || '').trim();
|
||||||
|
const requestedUserName = String(c.req.query('userName') || '').trim();
|
||||||
const requestedUserId = String(c.req.query('userId') || '').trim();
|
const requestedUserId = String(c.req.query('userId') || '').trim();
|
||||||
const targetUserId = requestedUserId || meId;
|
const targetUserName = requestedUserName || meName;
|
||||||
if (!targetUserId) return c.json({ success: false, message: 'No target user available' }, 400);
|
if (!targetUserName && !requestedUserId && !meId) {
|
||||||
|
return c.json({ success: false, message: 'No target user available' }, 400);
|
||||||
|
}
|
||||||
|
|
||||||
const fetchTasks = async (userId: string) => {
|
const baseFields = 'id,user,title,startDate,dueDate,priority,completed,content,size,status,expand.user.id,expand.user.email,expand.user.name,expand.user.username';
|
||||||
const filter = `user = "${userId.replace(/"/g, '\\"')}"`;
|
const fetchTasksWithFilter = async (filter: string) => {
|
||||||
return pb.collection(PB_TASKS_COLLECTION).getFullList({
|
return pb.collection(PB_TASKS_COLLECTION).getFullList({
|
||||||
filter,
|
filter,
|
||||||
sort: '-startDate,-created',
|
sort: '-startDate,-created',
|
||||||
expand: 'user',
|
expand: 'user',
|
||||||
fields: 'id,user,title,startDate,dueDate,priority,completed,content,size,status,expand.user.id,expand.user.email,expand.user.name,expand.user.username',
|
fields: baseFields,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchAllTasks = async () => {
|
||||||
|
return pb.collection(PB_TASKS_COLLECTION).getFullList({
|
||||||
|
sort: '-startDate,-created',
|
||||||
|
expand: 'user',
|
||||||
|
fields: baseFields,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const matchTaskByName = (task: any, name: string): boolean => {
|
||||||
|
const target = String(name || '').trim().toLowerCase();
|
||||||
|
if (!target) return false;
|
||||||
|
const taskUserDisplay = String(task?.expand?.user?.name || task?.expand?.user?.username || task?.expand?.user?.email || '').trim().toLowerCase();
|
||||||
|
const taskUserRaw = String(task?.user || '').trim().toLowerCase();
|
||||||
|
const owner = String(task?.owner || '').trim().toLowerCase();
|
||||||
|
const assignedTo = String(task?.assigned_to || '').trim().toLowerCase();
|
||||||
|
const userName = String(task?.user_name || task?.Username || '').trim().toLowerCase();
|
||||||
|
return [taskUserDisplay, taskUserRaw, owner, assignedTo, userName].some((v) => v && v === target);
|
||||||
|
};
|
||||||
|
|
||||||
let records: any[] = [];
|
let records: any[] = [];
|
||||||
let warning = '';
|
let warning = '';
|
||||||
let effectiveUserId = targetUserId;
|
let effectiveUserId = requestedUserId || meId;
|
||||||
|
let effectiveUserName = targetUserName;
|
||||||
try {
|
try {
|
||||||
records = await fetchTasks(targetUserId);
|
const escapedName = targetUserName.replace(/"/g, '\\"');
|
||||||
|
const escapedUserId = (requestedUserId || meId).replace(/"/g, '\\"');
|
||||||
|
const candidateFilters = [
|
||||||
|
targetUserName ? `user = "${escapedName}"` : '',
|
||||||
|
targetUserName ? `user_name = "${escapedName}"` : '',
|
||||||
|
targetUserName ? `Username = "${escapedName}"` : '',
|
||||||
|
targetUserName ? `assigned_to = "${escapedName}"` : '',
|
||||||
|
targetUserName ? `owner = "${escapedName}"` : '',
|
||||||
|
escapedUserId ? `user = "${escapedUserId}"` : '',
|
||||||
|
].filter(Boolean);
|
||||||
|
|
||||||
|
for (const filter of candidateFilters) {
|
||||||
|
try {
|
||||||
|
const found = await fetchTasksWithFilter(filter);
|
||||||
|
if (Array.isArray(found) && found.length) {
|
||||||
|
records = found;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!records.length) {
|
||||||
|
const all = await fetchAllTasks();
|
||||||
|
if (targetUserName) {
|
||||||
|
records = all.filter((task: any) => matchTaskByName(task, targetUserName));
|
||||||
|
} else if (escapedUserId) {
|
||||||
|
records = all.filter((task: any) => String(task?.user || '') === escapedUserId);
|
||||||
|
} else {
|
||||||
|
records = all;
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (listErr) {
|
} catch (listErr) {
|
||||||
if (targetUserId !== meId && meId) {
|
if (targetUserName && meName && targetUserName !== meName) {
|
||||||
try {
|
try {
|
||||||
records = await fetchTasks(meId);
|
const all = await fetchAllTasks();
|
||||||
|
records = all.filter((task: any) => matchTaskByName(task, meName));
|
||||||
effectiveUserId = meId;
|
effectiveUserId = meId;
|
||||||
|
effectiveUserName = meName;
|
||||||
warning = 'Requested user tasks are restricted by PocketBase rules; showing your tasks instead.';
|
warning = 'Requested user tasks are restricted by PocketBase rules; showing your tasks instead.';
|
||||||
} catch {
|
} catch {
|
||||||
records = [];
|
records = [];
|
||||||
effectiveUserId = meId;
|
effectiveUserId = meId;
|
||||||
|
effectiveUserName = meName;
|
||||||
warning = 'Task list is restricted by PocketBase rules; no accessible tasks for current user.';
|
warning = 'Task list is restricted by PocketBase rules; no accessible tasks for current user.';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
records = [];
|
records = [];
|
||||||
effectiveUserId = meId || targetUserId;
|
effectiveUserId = meId || requestedUserId;
|
||||||
|
effectiveUserName = targetUserName || meName;
|
||||||
warning = 'Task list is restricted by PocketBase rules; no accessible tasks for current user.';
|
warning = 'Task list is restricted by PocketBase rules; no accessible tasks for current user.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -535,6 +594,7 @@ app.get('/api/tasks/list', async (c) => {
|
|||||||
return c.json({
|
return c.json({
|
||||||
success: true,
|
success: true,
|
||||||
userId: effectiveUserId,
|
userId: effectiveUserId,
|
||||||
|
userName: effectiveUserName,
|
||||||
count: records.length,
|
count: records.length,
|
||||||
warning: warning || undefined,
|
warning: warning || undefined,
|
||||||
tasks: records.map((task: any) => ({
|
tasks: records.map((task: any) => ({
|
||||||
|
|||||||
+15
-11
@@ -317,22 +317,25 @@
|
|||||||
usersCache = Array.isArray(data.users) ? data.users : [];
|
usersCache = Array.isArray(data.users) ? data.users : [];
|
||||||
const meId = String(data?.me?.id || '').trim();
|
const meId = String(data?.me?.id || '').trim();
|
||||||
const meName = data?.me?.name || data?.me?.email || 'Me';
|
const meName = data?.me?.name || data?.me?.email || 'Me';
|
||||||
|
const meLookupName = String(data?.me?.name || data?.me?.email || '').trim();
|
||||||
|
|
||||||
taskUserSelect.innerHTML = '';
|
taskUserSelect.innerHTML = '';
|
||||||
for (const user of usersCache) {
|
for (const user of usersCache) {
|
||||||
const opt = document.createElement('option');
|
const opt = document.createElement('option');
|
||||||
opt.value = user.id;
|
const lookupName = String(user.name || user.email || user.id || '').trim();
|
||||||
|
opt.value = lookupName;
|
||||||
|
opt.dataset.userId = user.id;
|
||||||
opt.textContent = `${user.name || user.email || user.id}${user.id === meId ? ' (Me)' : ''}`;
|
opt.textContent = `${user.name || user.email || user.id}${user.id === meId ? ' (Me)' : ''}`;
|
||||||
taskUserSelect.appendChild(opt);
|
taskUserSelect.appendChild(opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meId) {
|
if (meLookupName) {
|
||||||
taskUserSelect.value = meId;
|
taskUserSelect.value = meLookupName;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeOutput({ message: `Loaded ${usersCache.length} users`, me: { id: meId, name: meName } });
|
writeOutput({ message: `Loaded ${usersCache.length} users`, me: { id: meId, name: meName, lookupName: meLookupName } });
|
||||||
if (data?.warning) {
|
if (data?.warning) {
|
||||||
writeOutput({ message: `Loaded ${usersCache.length} users`, warning: data.warning, me: { id: meId, name: meName } });
|
writeOutput({ message: `Loaded ${usersCache.length} users`, warning: data.warning, me: { id: meId, name: meName, lookupName: meLookupName } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,9 +370,9 @@
|
|||||||
async function loadTasks() {
|
async function loadTasks() {
|
||||||
await ensurePocketBaseClient();
|
await ensurePocketBaseClient();
|
||||||
const token = getCurrentToken();
|
const token = getCurrentToken();
|
||||||
const userId = String(taskUserSelect.value || '').trim();
|
const userName = String(taskUserSelect.value || '').trim();
|
||||||
const url = userId
|
const url = userName
|
||||||
? `/api/tasks/list?userId=${encodeURIComponent(userId)}`
|
? `/api/tasks/list?userName=${encodeURIComponent(userName)}`
|
||||||
: '/api/tasks/list';
|
: '/api/tasks/list';
|
||||||
const resp = await fetch(url, {
|
const resp = await fetch(url, {
|
||||||
headers: { 'x-pb-token': token },
|
headers: { 'x-pb-token': token },
|
||||||
@@ -378,13 +381,14 @@
|
|||||||
if (!resp.ok || !data?.success) {
|
if (!resp.ok || !data?.success) {
|
||||||
throw new Error(data?.message || 'Failed to load tasks');
|
throw new Error(data?.message || 'Failed to load tasks');
|
||||||
}
|
}
|
||||||
if (data?.userId && taskUserSelect.value !== data.userId) {
|
if (data?.userName && taskUserSelect.value !== data.userName) {
|
||||||
taskUserSelect.value = data.userId;
|
taskUserSelect.value = data.userName;
|
||||||
}
|
}
|
||||||
renderTasks(data.tasks || []);
|
renderTasks(data.tasks || []);
|
||||||
writeOutput({
|
writeOutput({
|
||||||
message: `Loaded ${data?.count ?? 0} task(s)`,
|
message: `Loaded ${data?.count ?? 0} task(s)`,
|
||||||
userId: data?.userId || userId,
|
userName: data?.userName || userName,
|
||||||
|
userId: data?.userId || undefined,
|
||||||
warning: data?.warning || undefined,
|
warning: data?.warning || undefined,
|
||||||
tasks: data.tasks || [],
|
tasks: data.tasks || [],
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user