wiki-server 0.25.9 → 0.26.0-rc.0

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/search.coffee DELETED
@@ -1,304 +0,0 @@
1
- ###
2
- * Federated Wiki : Node Server
3
- *
4
- * Copyright Ward Cunningham and other contributors
5
- * Licensed under the MIT license.
6
- * https://github.com/fedwiki/wiki-server/blob/master/LICENSE.txt
7
- ###
8
-
9
- # **search.coffee**
10
-
11
- fs = require 'fs'
12
- path = require 'path'
13
- events = require 'events'
14
- url = require 'node:url'
15
- writeFileAtomic = require 'write-file-atomic'
16
-
17
- miniSearch = require 'minisearch'
18
-
19
- module.exports = exports = (argv) ->
20
-
21
- wikiName = new URL(argv.url).hostname
22
-
23
- siteIndex = []
24
-
25
- queue = []
26
-
27
- searchPageHandler = null
28
-
29
- # ms since last update we will remove index from memory
30
- # orig - searchTimeoutMs = 1200000
31
- searchTimeoutMs = 120000 # temp reduce to 2 minutes
32
- searchTimeoutHandler = null
33
-
34
- siteIndexLoc = path.join(argv.status, 'site-index.json')
35
- indexUpdateFlag = path.join(argv.status, 'index-updated')
36
-
37
- working = false
38
-
39
- touch = (file, cb) ->
40
- fs.stat file, (err, stats) ->
41
- return cb() if err is null
42
- fs.open file, 'w', (err,fd) ->
43
- cb(err) if err
44
- fs.close fd, (err) ->
45
- cb(err)
46
-
47
- searchPageUpdate = (slug, page, cb) ->
48
- # to update we have to remove the page first, and then readd it
49
- try
50
- pageText = page.story.reduce( extractPageText, '')
51
- catch err
52
- console.log "SITE INDEX *** #{wikiName} reduce to extract the text on #{slug} failed", err.message
53
- pageText = ""
54
- if siteIndex.has slug
55
- siteIndex.replace {
56
- 'id': slug
57
- 'title': page.title
58
- 'content': pageText
59
- }
60
- else
61
- siteIndex.add {
62
- 'id': slug
63
- 'title': page.title
64
- 'content': pageText
65
- }
66
- cb()
67
-
68
- searchPageRemove = (slug, cb) ->
69
- # remove page from index
70
- timeLabel = "SITE INDEX page remove #{slug} - #{wikiName}"
71
- try
72
- siteIndex.discard slug
73
- catch err
74
- # swallow error, if the page was not in index
75
- console.log "removing #{slug} from index #{wikiName} failed", err unless err.message.includes('not in the index')
76
- cb()
77
-
78
- searchSave = (siteIndex, cb) ->
79
- # save index to file
80
- fs.exists argv.status, (exists) ->
81
- if exists
82
- writeFileAtomic siteIndexLoc, JSON.stringify(siteIndex), (e) ->
83
- return cb(e) if e
84
- touch indexUpdateFlag, (err) ->
85
- cb()
86
- else
87
- fs.mkdir argv.status, { recursive: true }, ->
88
- writeFileAtomic siteIndexLoc, JSON.stringify(siteIndex), (e) ->
89
- return cb(e) if e
90
- touch indexUpdateFlag, (err) ->
91
- cb()
92
-
93
-
94
- searchRestore = (cb) ->
95
- # restore index, or create if it doesn't already exist
96
- fs.exists siteIndexLoc, (exists) ->
97
- if exists
98
- fs.readFile(siteIndexLoc, (err, data) ->
99
- return cb(err) if err
100
- try
101
- siteIndex = miniSearch.loadJSON data,
102
- fields: ['title', 'content']
103
- catch e
104
- return cb(e)
105
- process.nextTick( ->
106
- serial(queue.shift())))
107
-
108
- serial = (item) ->
109
- if item
110
- switch item.action
111
- when "update"
112
- itself.start()
113
- searchPageUpdate(item.slug, item.page, (e) ->
114
- process.nextTick( ->
115
- serial(queue.shift())
116
- )
117
- )
118
- when "remove"
119
- itself.start()
120
- searchPageRemove(item.slug, (e) ->
121
- process.nextTick( ->
122
- serial(queue.shift())
123
- )
124
- )
125
- else
126
- console.log "SITE INDEX *** unexpected action #{item.action} for #{item.page}"
127
- process.nextTick( ->
128
- serial(queue.shift))
129
- else
130
- searchSave siteIndex, (e) ->
131
- console.log "SITE INDEX *** save failed: " + e if e
132
- itself.stop()
133
-
134
- extractItemText = (text) ->
135
- return text.replace(/\[([^\]]*?)\][\[\(].*?[\]\)]/g, " $1 ")
136
- .replace(/\[{2}|\[(?:[\S]+)|\]{1,2}/g, ' ')
137
- .replace(/\n/g, ' ')
138
- .replace(/<style.*?<\/style>/g, ' ')
139
- .replace(/<(?:"[^"]*"['"]*|'[^']*'['"]*|[^'">])+>/g, ' ')
140
- .replace(/<(?:[^>])+>/g, ' ')
141
- .replace(/(https?.*?)(?=\p{White_Space}|\p{Quotation_Mark}|$)/gu, (match) ->
142
- myUrl = url.parse(match)
143
- return myUrl.hostname + ' ' + myUrl.pathname)
144
- .replace(/[\p{P}\p{Emoji}\p{Symbol}}]+/gu, ' ')
145
- .replace /[\p{White_Space}\n\t]+/gu, ' '
146
-
147
-
148
- extractPageText = (pageText, currentItem, currentIndex, array) ->
149
- # console.log('extractPageText', pageText, currentItem, currentIndex, array)
150
- try
151
- if currentItem.text?
152
- switch currentItem.type
153
- when 'paragraph', 'markdown', 'html', 'reference', 'image', 'pagefold', 'math', 'mathjax', 'code'
154
- pageText += ' ' + extractItemText currentItem.text
155
- when 'audio', 'video', 'frame'
156
- pageText += ' ' + extractItemText(currentItem.text.split(/\r\n?|\n/)
157
- .map((line) ->
158
- firstWord = line.split(/\p{White_Space}/u)[0]
159
- if firstWord.startsWith('http') or firstWord.toUpperCase() is firstWord or firstWord.startsWith('//')
160
- # line is markup
161
- return ''
162
- else
163
- return line
164
- ).join(' '))
165
- catch err
166
- throw new Error("Error extracting text from #{currentIndex}, #{JSON.stringify(currentItem)} #{err}, #{err.stack}")
167
- pageText
168
-
169
-
170
- #### Public stuff ####
171
-
172
- itself = new events.EventEmitter
173
- itself.start = ->
174
- clearTimeout(searchTimeoutHandler)
175
- working = true
176
- @emit 'indexing'
177
- itself.stop = ->
178
- clearsearch = ->
179
- console.log "SITE INDEX #{wikiName} : removed from memory"
180
- siteIndex = []
181
- clearTimeout(searchTimeoutHandler)
182
- searchTimeoutHandler = setTimeout clearsearch, searchTimeoutMs
183
- working = false
184
- @emit 'indexed'
185
-
186
- itself.isWorking = ->
187
- working
188
-
189
- itself.createIndex = (pagehandler) ->
190
-
191
- itself.start()
192
-
193
- # we save the pagehandler, so we can recreate the site index if it is removed
194
- searchPageHandler = pagehandler if !searchPageHandler?
195
-
196
- #timeLabel = "SITE INDEX #{wikiName} : Created"
197
- #console.time timeLabel
198
-
199
- pagehandler.slugs (e, slugs) ->
200
- if e
201
- console.log "SITE INDEX *** createIndex #{wikiName} error:", e
202
- itself.stop()
203
- return e
204
-
205
- siteIndex = new miniSearch({
206
- fields: ['title', 'content']
207
- })
208
-
209
- indexPromises = slugs.map (slug) ->
210
- return new Promise (resolve) ->
211
- pagehandler.get slug, (err, page) ->
212
- if err
213
- console.log "SITE INDEX *** #{wikiName}: error reading page", slug
214
- return
215
- # page
216
- try
217
- pageText = page.story.reduce( extractPageText, '')
218
- catch err
219
- console.log "SITE INDEX *** #{wikiName} reduce to extract text on #{slug} failed", err.message
220
- # console.log "page", page
221
- pageText = ""
222
- siteIndex.add {
223
- 'id': slug
224
- 'title': page.title
225
- 'content': pageText
226
- }
227
- resolve()
228
-
229
- Promise.all(indexPromises)
230
- .then () ->
231
- # console.timeEnd timeLabel
232
- process.nextTick ( ->
233
- serial(queue.shift()))
234
-
235
- itself.removePage = (slug) ->
236
- action = "remove"
237
- queue.push({action, slug })
238
- if Array.isArray(siteIndex) and !working
239
- itself.start()
240
- searchRestore (e) ->
241
- console.log "SITE INDEX *** Problems restoring search index #{wikiName}:" + e if e
242
- itself.createIndex(searchPageHandler)
243
- else
244
- serial(queue.shift()) unless working
245
-
246
- itself.update = (slug, page) ->
247
- action = "update"
248
- queue.push({action, slug, page})
249
- if Array.isArray(siteIndex) and !working
250
- itself.start()
251
- searchRestore( (e) ->
252
- console.log "SITE INDEX *** Problems restoring search index #{wikiName}:" + e if e
253
- itself.createIndex(searchPageHandler))
254
- else
255
- serial(queue.shift()) unless working
256
-
257
- itself.startUp = (pagehandler) ->
258
- # called on server startup, here we check if wiki already is index
259
- # we only create an index if there is either no index or there have been updates since last startup
260
- console.log "SITE INDEX #{wikiName} : StartUp"
261
- fs.stat siteIndexLoc, (err, stats) ->
262
- if err is null
263
- # site index exists, but has it been updated?
264
- fs.stat indexUpdateFlag, (err, stats) ->
265
- if !err
266
- # index has been updated, so recreate it.
267
- itself.createIndex pagehandler
268
- # remove the update flag once the index has been created
269
- itself.once 'indexed', ->
270
- fs.unlink indexUpdateFlag, (err) ->
271
- console.log "+++ SITE INDEX #{wikiName} : unable to delete update flag" if err
272
- else
273
- # not been updated, but is it the correct version?
274
- fs.readFile siteIndexLoc, (err, data) ->
275
- if !err
276
- try
277
- testIndex = JSON.parse(data)
278
- catch err
279
- testIndex = {}
280
- if testIndex.serializationVersion != 2
281
- console.log "+++ SITE INDEX #{wikiName} : updating to latest version."
282
- itself.createIndex pagehandler
283
- # remove the update flag once the index has been created
284
- itself.once 'indexed', ->
285
- fs.unlink indexUpdateFlag, (err) ->
286
- console.log "+++ SITE INDEX #{wikiName} : unable to delete update flag" if err
287
- else
288
- console.log "+++ SITE INDEX #{wikiName} : error reading index - attempting creating"
289
- itself.createIndex pagehandler
290
- # remove the update flag once the index has been created
291
- itself.once 'indexed', ->
292
- fs.unlink indexUpdateFlag, (err) ->
293
- console.log "+++ SITE INDEX #{wikiName} : unable to delete update flag" if err
294
- else
295
- # index does not exist, so create it
296
- itself.createIndex pagehandler
297
- # remove the update flag once the index has been created
298
- itself.once 'indexed', ->
299
- fs.unlink indexUpdateFlag, (err) ->
300
- console.log "+++ SITE INDEX #{wikiName} : unable to delete update flag" if err
301
-
302
-
303
-
304
- itself
@@ -1,86 +0,0 @@
1
- ###
2
- * Federated Wiki : Node Server
3
- *
4
- * Copyright Ward Cunningham and other contributors
5
- * Licensed under the MIT license.
6
- * https://github.com/fedwiki/wiki-node-server/blob/master/LICENSE.txt
7
- ###
8
- # **security.coffee**
9
- # Module for default site security.
10
- #
11
- # This module is not intented for use, but is here to catch a problem with
12
- # configuration of security. It does not provide any authentication, but will
13
- # allow the server to run read-only.
14
-
15
- #### Requires ####
16
- fs = require 'fs'
17
-
18
-
19
- # Export a function that generates security handler
20
- # when called with options object.
21
- module.exports = exports = (log, loga, argv) ->
22
- security={}
23
-
24
- #### Private utility methods. ####
25
-
26
- user = ''
27
-
28
- owner = ''
29
-
30
- admin = argv.admin
31
-
32
- # save the location of the identity file
33
- idFile = argv.id
34
-
35
- #### Public stuff ####
36
-
37
- security.authenticate_session = ->
38
- (req, res, next) ->
39
- # not possible to login, so always false
40
- req.isAuthenticated = ->
41
- return false
42
- next()
43
-
44
- # Retrieve owner infomation from identity file in status directory
45
- security.retrieveOwner = (cb) ->
46
- fs.exists idFile, (exists) ->
47
- if exists
48
- fs.readFile(idFile, (err, data) ->
49
- if err then return cb err
50
- owner += data
51
- cb())
52
- else
53
- owner = ''
54
- cb()
55
-
56
- # Return the owners name
57
- security.getOwner = ->
58
- if !owner.name?
59
- ownerName = ''
60
- else
61
- ownerName = owner.name
62
- ownerName
63
-
64
- security.getUser = (req) ->
65
- return ''
66
-
67
- security.isAuthorized = (req) ->
68
- # nobody is authorized - everything is read-only
69
- # unless legacy support, when unclaimed sites can be editted.
70
- if owner == ''
71
- if argv.security_legacy
72
- return true
73
- else
74
- return false
75
- else
76
- return false
77
-
78
- # Wiki server admin
79
- security.isAdmin = ->
80
- return false
81
-
82
- security.defineRoutes = (app, cors, updateOwner) ->
83
- # default security does not have any routes
84
-
85
-
86
- security