nodebb-plugin-pdf-secure2 1.3.3 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/controllers.js +7 -0
- package/library.js +10 -18
- package/package.json +1 -1
- package/static/lib/main.js +0 -9
package/lib/controllers.js
CHANGED
|
@@ -42,13 +42,17 @@ Controllers.renderAdminPage = function (req, res) {
|
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
Controllers.servePdfBinary = async function (req, res) {
|
|
45
|
+
console.log('[PDF-Secure] servePdfBinary called - uid:', req.uid, 'nonce:', req.query.nonce ? 'present' : 'missing');
|
|
46
|
+
|
|
45
47
|
// Authentication gate - require logged-in user
|
|
46
48
|
if (!req.uid) {
|
|
49
|
+
console.log('[PDF-Secure] servePdfBinary - REJECTED: no uid');
|
|
47
50
|
return res.status(401).json({ error: 'Authentication required' });
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
const { nonce } = req.query;
|
|
51
54
|
if (!nonce) {
|
|
55
|
+
console.log('[PDF-Secure] servePdfBinary - REJECTED: no nonce');
|
|
52
56
|
return res.status(400).json({ error: 'Missing nonce' });
|
|
53
57
|
}
|
|
54
58
|
|
|
@@ -56,9 +60,12 @@ Controllers.servePdfBinary = async function (req, res) {
|
|
|
56
60
|
|
|
57
61
|
const data = nonceStore.validate(nonce, uid);
|
|
58
62
|
if (!data) {
|
|
63
|
+
console.log('[PDF-Secure] servePdfBinary - REJECTED: invalid/expired nonce for uid:', uid);
|
|
59
64
|
return res.status(403).json({ error: 'Invalid or expired nonce' });
|
|
60
65
|
}
|
|
61
66
|
|
|
67
|
+
console.log('[PDF-Secure] servePdfBinary - OK: file:', data.file, 'isPremium:', data.isPremium);
|
|
68
|
+
|
|
62
69
|
try {
|
|
63
70
|
// Server-side premium gate: non-premium users only get first page
|
|
64
71
|
const pdfBuffer = data.isPremium
|
package/library.js
CHANGED
|
@@ -10,7 +10,6 @@ const controllers = require('./lib/controllers');
|
|
|
10
10
|
const nonceStore = require('./lib/nonce-store');
|
|
11
11
|
const pdfHandler = require('./lib/pdf-handler');
|
|
12
12
|
const geminiChat = require('./lib/gemini-chat');
|
|
13
|
-
const topics = require.main.require('./src/topics');
|
|
14
13
|
|
|
15
14
|
const plugin = {};
|
|
16
15
|
|
|
@@ -102,6 +101,7 @@ plugin.init = async (params) => {
|
|
|
102
101
|
// Check if user is Premium or Lite (admins/global mods always premium)
|
|
103
102
|
let isPremium = false;
|
|
104
103
|
let isLite = false;
|
|
104
|
+
let isVip = false;
|
|
105
105
|
if (req.uid) {
|
|
106
106
|
const [isAdmin, isGlobalMod, isPremiumMember, isVipMember, isLiteMember] = await Promise.all([
|
|
107
107
|
groups.isMember(req.uid, 'administrators'),
|
|
@@ -111,10 +111,11 @@ plugin.init = async (params) => {
|
|
|
111
111
|
groups.isMember(req.uid, 'Lite'),
|
|
112
112
|
]);
|
|
113
113
|
isPremium = isAdmin || isGlobalMod || isPremiumMember || isVipMember;
|
|
114
|
-
|
|
114
|
+
isVip = isVipMember || isAdmin;
|
|
115
115
|
// Lite: full PDF access but restricted UI (no annotations, sidebar, etc.)
|
|
116
116
|
isLite = !isPremium && isLiteMember;
|
|
117
117
|
}
|
|
118
|
+
console.log('[PDF-Secure] Viewer request - uid:', req.uid, 'file:', safeName, 'isPremium:', isPremium, 'isVip:', isVip, 'isLite:', isLite);
|
|
118
119
|
|
|
119
120
|
// Lite users get full PDF like premium (for nonce/server-side PDF data)
|
|
120
121
|
const hasFullAccess = isPremium || isLite;
|
|
@@ -230,11 +231,9 @@ plugin.filterMetaTags = async (hookData) => {
|
|
|
230
231
|
return hookData;
|
|
231
232
|
};
|
|
232
233
|
|
|
233
|
-
// Inject
|
|
234
|
+
// Inject plugin config into client-side
|
|
234
235
|
plugin.filterConfig = async function (data) {
|
|
235
|
-
|
|
236
|
-
data.config.pdfSecureCategories = pluginSettings.allowedCategories || '';
|
|
237
|
-
}
|
|
236
|
+
console.log('[PDF-Secure] filterConfig called - data exists:', !!data, 'config exists:', !!(data && data.config));
|
|
238
237
|
return data;
|
|
239
238
|
};
|
|
240
239
|
|
|
@@ -242,26 +241,19 @@ plugin.filterConfig = async function (data) {
|
|
|
242
241
|
// This hides PDF URLs from: page source, API, RSS, ActivityPub
|
|
243
242
|
plugin.transformPdfLinks = async (data) => {
|
|
244
243
|
if (!data || !data.postData || !data.postData.content) {
|
|
244
|
+
console.log('[PDF-Secure] transformPdfLinks - no data/postData/content, skipping');
|
|
245
245
|
return data;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
|
|
249
|
-
const allowedStr = pluginSettings.allowedCategories || '';
|
|
250
|
-
const allowed = allowedStr.split(',').map(s => s.trim()).filter(Boolean);
|
|
251
|
-
if (allowed.length > 0 && data.postData.tid) {
|
|
252
|
-
let cid = data.postData.cid;
|
|
253
|
-
if (!cid) {
|
|
254
|
-
cid = await topics.getTopicField(data.postData.tid, 'cid');
|
|
255
|
-
}
|
|
256
|
-
if (cid && !allowed.includes(String(cid))) {
|
|
257
|
-
return data;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
248
|
+
console.log('[PDF-Secure] transformPdfLinks - processing post tid:', data.postData.tid, 'pid:', data.postData.pid);
|
|
260
249
|
|
|
261
250
|
// Regex to match PDF links: <a href="...xxx.pdf">text</a>
|
|
262
251
|
// Captures: full URL path, filename, link text
|
|
263
252
|
const pdfLinkRegex = /<a\s+[^>]*href=["']([^"']*\/([^"'\/]+\.pdf))["'][^>]*>([^<]*)<\/a>/gi;
|
|
264
253
|
|
|
254
|
+
const matchCount = (data.postData.content.match(pdfLinkRegex) || []).length;
|
|
255
|
+
console.log('[PDF-Secure] transformPdfLinks - found', matchCount, 'PDF links in post');
|
|
256
|
+
|
|
265
257
|
data.postData.content = data.postData.content.replace(pdfLinkRegex, (match, fullPath, filename, linkText) => {
|
|
266
258
|
// Decode filename to prevent double encoding (URL may already be encoded)
|
|
267
259
|
let decodedFilename;
|
package/package.json
CHANGED
package/static/lib/main.js
CHANGED
|
@@ -283,15 +283,6 @@
|
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
function interceptPdfLinks() {
|
|
286
|
-
// Category check — only intercept in allowed categories
|
|
287
|
-
var allowedCats = (config.pdfSecureCategories || '').split(',').filter(Boolean);
|
|
288
|
-
if (allowedCats.length > 0) {
|
|
289
|
-
var currentCid = ajaxify && ajaxify.data && String(ajaxify.data.cid || '');
|
|
290
|
-
if (currentCid && !allowedCats.includes(currentCid)) {
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
286
|
var postContents = document.querySelectorAll('[component="post/content"]');
|
|
296
287
|
|
|
297
288
|
postContents.forEach(function (content) {
|