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.
@@ -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
- const isVip = isVipMember || isAdmin;
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 allowed categories into client-side config
234
+ // Inject plugin config into client-side
234
235
  plugin.filterConfig = async function (data) {
235
- if (data && data.config) {
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
- // Category check only transform in allowed categories
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-pdf-secure2",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "description": "Secure PDF viewer plugin for NodeBB - prevents downloading, enables canvas-only rendering with Premium group support",
5
5
  "main": "library.js",
6
6
  "repository": {
@@ -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) {