fix: require qdreader user binding for manual access
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
//[author: Hermes]
|
//[author: Hermes]
|
||||||
//[service: BOSS]
|
//[service: BOSS]
|
||||||
//[class: 工具类]
|
//[class: 工具类]
|
||||||
//[version: 2.3.2]
|
//[version: 2.3.3]
|
||||||
//[platform: web,qq,wx,tg,tb,fs,we]
|
//[platform: web,qq,wx,tg,tb,fs,we]
|
||||||
//[public: false]
|
//[public: false]
|
||||||
//[price: 0]
|
//[price: 0]
|
||||||
@@ -102,7 +102,7 @@ function currentUserId() {
|
|||||||
function boundToCurrent(uid, bind) {
|
function boundToCurrent(uid, bind) {
|
||||||
var owner = bind && bind[String(uid)] ? String(bind[String(uid)]) : ""
|
var owner = bind && bind[String(uid)] ? String(bind[String(uid)]) : ""
|
||||||
var me = currentUserId()
|
var me = currentUserId()
|
||||||
return !owner || !me || owner === me
|
return !!owner && !!me && owner === me
|
||||||
}
|
}
|
||||||
function visibleUids(store, bind, allUsers) {
|
function visibleUids(store, bind, allUsers) {
|
||||||
var uids = Object.keys(store || {}).sort()
|
var uids = Object.keys(store || {}).sort()
|
||||||
@@ -183,7 +183,7 @@ function contentText() {
|
|||||||
}
|
}
|
||||||
function usage() {
|
function usage() {
|
||||||
return [
|
return [
|
||||||
"启点读书签到插件 v2.3.2",
|
"启点读书签到插件 v2.3.3",
|
||||||
"【一级菜单】",
|
"【一级菜单】",
|
||||||
"账号管理:启点账号",
|
"账号管理:启点账号",
|
||||||
"执行查询:启点查询",
|
"执行查询:启点查询",
|
||||||
@@ -592,9 +592,18 @@ function handleSaveCookie(arg, store, bind) {
|
|||||||
var uid = entries[i].uid || parsedUid
|
var uid = entries[i].uid || parsedUid
|
||||||
if (!uid) return "无法从 Cookie 识别 uid。请确认 QX 抓的是启点读书福利中心 getlogininfo 请求,Cookie 内应包含 QDHeader 或 uid。"
|
if (!uid) return "无法从 Cookie 识别 uid。请确认 QX 抓的是启点读书福利中心 getlogininfo 请求,Cookie 内应包含 QDHeader 或 uid。"
|
||||||
var isNew = !store[uid]
|
var isNew = !store[uid]
|
||||||
|
var oldOwner = bind[uid] || ""
|
||||||
|
if (store[uid] && oldOwner && me && oldOwner !== me) {
|
||||||
|
lines.push("无权更新 uid: " + uid + "(该账号已绑定其他用户)")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (!me) {
|
||||||
|
lines.push("无法识别当前用户,拒绝保存 uid: " + uid)
|
||||||
|
continue
|
||||||
|
}
|
||||||
var changed = store[uid] !== cookie
|
var changed = store[uid] !== cookie
|
||||||
store[uid] = cookie
|
store[uid] = cookie
|
||||||
if (me) bind[uid] = me
|
bind[uid] = me
|
||||||
lines.push("启点读书CK" + (isNew ? "新增" : (changed ? "更新" : "未变化")) + "成功")
|
lines.push("启点读书CK" + (isNew ? "新增" : (changed ? "更新" : "未变化")) + "成功")
|
||||||
lines.push("uid: " + uid)
|
lines.push("uid: " + uid)
|
||||||
if (entries.length > 1 && parsedUid && parsedUid !== uid) lines.push("提示: JSON uid 与 Cookie 解析 uid 不一致,已按 JSON uid 保存")
|
if (entries.length > 1 && parsedUid && parsedUid !== uid) lines.push("提示: JSON uid 与 Cookie 解析 uid 不一致,已按 JSON uid 保存")
|
||||||
|
|||||||
@@ -69,8 +69,10 @@ qdreader sign
|
|||||||
|
|
||||||
## 账号与备注
|
## 账号与备注
|
||||||
|
|
||||||
- 保存 Cookie 后自动绑定当前 `sender.getUserID()`。
|
- 保存 Cookie 后必须绑定当前 `sender.getUserID()`;无法识别当前用户时拒绝保存。
|
||||||
- 查询、删除、手动签到默认只操作当前用户绑定的账号。
|
- 查询、删除、手动签到默认只操作当前用户绑定的账号。
|
||||||
|
- 未绑定到当前用户的全局 CK 不会在普通用户菜单中显示,也不会被普通用户手动签到使用。
|
||||||
|
- 已绑定其他用户的 UID 不能被当前用户覆盖更新。
|
||||||
- 账号详情、删除、单账号查询都使用编号选择,不要求用户复制/输入 UID。
|
- 账号详情、删除、单账号查询都使用编号选择,不要求用户复制/输入 UID。
|
||||||
- 添加/更新账号后会提示是否添加备注。
|
- 添加/更新账号后会提示是否添加备注。
|
||||||
- 修改备注在“账号详情/修改备注”中完成。
|
- 修改备注在“账号详情/修改备注”中完成。
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//[author: Hermes]
|
//[author: Hermes]
|
||||||
//[service: BOSS]
|
//[service: BOSS]
|
||||||
//[class: 工具类]
|
//[class: 工具类]
|
||||||
//[version: 2.3.2]
|
//[version: 2.3.3]
|
||||||
//[platform: web,qq,wx,tg,tb,fs,we]
|
//[platform: web,qq,wx,tg,tb,fs,we]
|
||||||
//[public: false]
|
//[public: false]
|
||||||
//[price: 0]
|
//[price: 0]
|
||||||
@@ -102,7 +102,7 @@ function currentUserId() {
|
|||||||
function boundToCurrent(uid, bind) {
|
function boundToCurrent(uid, bind) {
|
||||||
var owner = bind && bind[String(uid)] ? String(bind[String(uid)]) : ""
|
var owner = bind && bind[String(uid)] ? String(bind[String(uid)]) : ""
|
||||||
var me = currentUserId()
|
var me = currentUserId()
|
||||||
return !owner || !me || owner === me
|
return !!owner && !!me && owner === me
|
||||||
}
|
}
|
||||||
function visibleUids(store, bind, allUsers) {
|
function visibleUids(store, bind, allUsers) {
|
||||||
var uids = Object.keys(store || {}).sort()
|
var uids = Object.keys(store || {}).sort()
|
||||||
@@ -183,7 +183,7 @@ function contentText() {
|
|||||||
}
|
}
|
||||||
function usage() {
|
function usage() {
|
||||||
return [
|
return [
|
||||||
"启点读书签到插件 v2.3.2",
|
"启点读书签到插件 v2.3.3",
|
||||||
"【一级菜单】",
|
"【一级菜单】",
|
||||||
"账号管理:启点账号",
|
"账号管理:启点账号",
|
||||||
"执行查询:启点查询",
|
"执行查询:启点查询",
|
||||||
@@ -592,9 +592,18 @@ function handleSaveCookie(arg, store, bind) {
|
|||||||
var uid = entries[i].uid || parsedUid
|
var uid = entries[i].uid || parsedUid
|
||||||
if (!uid) return "无法从 Cookie 识别 uid。请确认 QX 抓的是启点读书福利中心 getlogininfo 请求,Cookie 内应包含 QDHeader 或 uid。"
|
if (!uid) return "无法从 Cookie 识别 uid。请确认 QX 抓的是启点读书福利中心 getlogininfo 请求,Cookie 内应包含 QDHeader 或 uid。"
|
||||||
var isNew = !store[uid]
|
var isNew = !store[uid]
|
||||||
|
var oldOwner = bind[uid] || ""
|
||||||
|
if (store[uid] && oldOwner && me && oldOwner !== me) {
|
||||||
|
lines.push("无权更新 uid: " + uid + "(该账号已绑定其他用户)")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (!me) {
|
||||||
|
lines.push("无法识别当前用户,拒绝保存 uid: " + uid)
|
||||||
|
continue
|
||||||
|
}
|
||||||
var changed = store[uid] !== cookie
|
var changed = store[uid] !== cookie
|
||||||
store[uid] = cookie
|
store[uid] = cookie
|
||||||
if (me) bind[uid] = me
|
bind[uid] = me
|
||||||
lines.push("启点读书CK" + (isNew ? "新增" : (changed ? "更新" : "未变化")) + "成功")
|
lines.push("启点读书CK" + (isNew ? "新增" : (changed ? "更新" : "未变化")) + "成功")
|
||||||
lines.push("uid: " + uid)
|
lines.push("uid: " + uid)
|
||||||
if (entries.length > 1 && parsedUid && parsedUid !== uid) lines.push("提示: JSON uid 与 Cookie 解析 uid 不一致,已按 JSON uid 保存")
|
if (entries.length > 1 && parsedUid && parsedUid !== uid) lines.push("提示: JSON uid 与 Cookie 解析 uid 不一致,已按 JSON uid 保存")
|
||||||
|
|||||||
@@ -92,7 +92,10 @@ test('manual cookie save falls back to QDHeader embedded UserId before ywguid',
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('manual sign and cron sign both call sign gateway then qidian checkin', () => {
|
test('manual sign and cron sign both call sign gateway then qidian checkin', () => {
|
||||||
const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }) };
|
const store = {
|
||||||
|
qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
|
||||||
|
qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }),
|
||||||
|
};
|
||||||
const manual = runPlugin({ content: '启点签到', store: { ...store } });
|
const manual = runPlugin({ content: '启点签到', store: { ...store } });
|
||||||
assert.equal(manual.calls.length, 2);
|
assert.equal(manual.calls.length, 2);
|
||||||
assert.match(manual.calls[0].url, /api\.120399\.xyz\/qdreader\/sign$/);
|
assert.match(manual.calls[0].url, /api\.120399\.xyz\/qdreader\/sign$/);
|
||||||
@@ -112,7 +115,7 @@ test('manual sign and cron sign both call sign gateway then qidian checkin', ()
|
|||||||
assert.equal(JSON.parse(cron.store.qdreader_last_run_json).source, 'cron');
|
assert.equal(JSON.parse(cron.store.qdreader_last_run_json).source, 'cron');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('bucketGet/bucketSet fallback works when get/set are unavailable in Autman-like env', () => {
|
test('bucketGet/bucketSet fallback requires identifiable user before saving', () => {
|
||||||
const replies = [];
|
const replies = [];
|
||||||
const bucketStore = {};
|
const bucketStore = {};
|
||||||
const ctx = {
|
const ctx = {
|
||||||
@@ -125,9 +128,8 @@ test('bucketGet/bucketSet fallback works when get/set are unavailable in Autman-
|
|||||||
};
|
};
|
||||||
vm.createContext(ctx);
|
vm.createContext(ctx);
|
||||||
vm.runInContext(code, ctx, { filename: pluginPath });
|
vm.runInContext(code, ctx, { filename: pluginPath });
|
||||||
assert.match(replies.join('\n'), /CK新增成功/);
|
assert.match(replies.join('\n'), /无法识别当前用户,拒绝保存/);
|
||||||
assert.equal(JSON.parse(bucketStore['hermes_qidian.qdreader_cookie_json'])['12345'], cookie);
|
assert.equal(bucketStore['hermes_qidian.qdreader_cookie_json'], '{}');
|
||||||
assert.equal(JSON.parse(bucketStore['hermes_qidian.qdreader_user_bind_json'])['12345'], undefined);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('hermes_qidian bucket values are read and written without legacy bucket fallback', () => {
|
test('hermes_qidian bucket values are read and written without legacy bucket fallback', () => {
|
||||||
@@ -141,7 +143,7 @@ test('hermes_qidian bucket values are read and written without legacy bucket fal
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('qidian request retries transient request errors', () => {
|
test('qidian request retries transient request errors', () => {
|
||||||
const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }), qdreader_retry_count: '2' };
|
const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }), qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }), qdreader_retry_count: '2' };
|
||||||
const r = runPlugin({
|
const r = runPlugin({
|
||||||
content: '启点签到',
|
content: '启点签到',
|
||||||
store,
|
store,
|
||||||
@@ -290,3 +292,29 @@ test('manual sign only runs current user accounts while cron runs all accounts',
|
|||||||
assert.equal(cron.calls.length, 4);
|
assert.equal(cron.calls.length, 4);
|
||||||
assert.match(cron.replies[0], /总计 2/);
|
assert.match(cron.replies[0], /总计 2/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('unbound global cookies are not visible or usable by normal users', () => {
|
||||||
|
const store = { qdreader_cookie_json: JSON.stringify({ '12345': cookie }) };
|
||||||
|
const account = runPlugin({ content: '启点账号', store: { ...store }, userId: 'user-a', listens: ['1'] });
|
||||||
|
assert.match(account.replies.join('\n'), /当前用户还没有保存启点读书CK/);
|
||||||
|
|
||||||
|
const manual = runPlugin({ content: '启点签到', store: { ...store }, userId: 'user-a' });
|
||||||
|
assert.equal(manual.calls.length, 0);
|
||||||
|
assert.match(manual.replies[0], /还没有保存启点读书CK/);
|
||||||
|
|
||||||
|
const cron = runPlugin({ content: '', store: { ...store }, userId: 'cron' });
|
||||||
|
assert.equal(cron.calls.length, 2);
|
||||||
|
assert.match(cron.replies[0], /总计 1/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('user cannot overwrite another user bound cookie', () => {
|
||||||
|
const store = {
|
||||||
|
qdreader_cookie_json: JSON.stringify({ '12345': cookie }),
|
||||||
|
qdreader_user_bind_json: JSON.stringify({ '12345': 'user-a' }),
|
||||||
|
};
|
||||||
|
const newCookie = cookie.replace('sessionyw=s', 'sessionyw=changed');
|
||||||
|
const r = runPlugin({ content: '启点ck ' + newCookie, store, userId: 'user-b' });
|
||||||
|
assert.match(r.replies.join('\n'), /无权更新 uid: 12345/);
|
||||||
|
assert.equal(JSON.parse(r.store.qdreader_cookie_json)['12345'], cookie);
|
||||||
|
assert.equal(JSON.parse(r.store.qdreader_user_bind_json)['12345'], 'user-a');
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user