-class EditMarkdownAction
- super Action
-
- redef fun answer(http_request, turi)
- do
- var response = new HttpResponse(200)
- var file_path = turi.substring(1, turi.length)
- var md_file = new FileReader.open(file_path)
- response.body = html_document("""
- <form method="POST" action="/preview">
- You may edit the file. When you are done, click on "Submit".<br/>
- <textarea name="content" rows="30" cols="80" style="font-family: Courier">""" + md_file.read_all + """</textarea><br/>
- <input type="submit" name="action" value="Preview">
- <input type="submit" name="action" value="Submit">
- <input type="hidden" name="filepath" value="""" + file_path + """">
- </form>""")
- md_file.close
- return response
- end
+# Action to serve edit forms, show previews and apply changes
+class EditAction
+ super Action
+
+ # Full public URL for the root of this wiki
+ var root_url: String
+
+ # Path to the wiki config
+ var config_file_path: String
+
+ # Configuration of the Wiki, loaded once
+ var wiki_config = new WikiConfig(config_file_path) is lazy
+
+ # Path to the root of the wiki
+ private var wiki_root: String = config_file_path.dirname is lazy
+
+ # Path to the source files
+ private var source_dir: String = (wiki_root / wiki_config.source_dir).simplify_path + "/" is lazy
+
+ # List of acceptable password to apply modifications
+ #
+ # If `null`, no password checks are applied and all modifications are accepted.
+ var passwords: nullable Collection[String]
+
+ # Reload the wiki instance with the latest changes
+ fun wiki: Nitiwiki
+ do
+ var wiki = new Nitiwiki(wiki_config)
+ wiki.parse
+ return wiki
+ end
+
+ redef fun answer(http_request, turi)
+ do
+ var action = http_request.string_arg("action")
+ var markdown = http_request.post_args.get_or_default("content", "")
+
+ var file_path = turi.strip_leading_slash
+ file_path = wiki_root / file_path
+
+ if not file_path.simplify_path.has_prefix(source_dir) then
+ # Attempting to access a file outside the source directory
+ var entity = new WikiEditForm(wiki, turi.strip_leading_slash,
+ "Access denied: ", "", "<p>Target outside of the source directory</p>")
+ return entity.to_http_response
+ end
+
+ if action == "Submit" then
+ var passwords = passwords
+ var password = http_request.post_args.get_or_null("password")
+ if passwords != null and (password == null or not passwords.has(password.md5)) then
+ # Deny modification
+ var entity = new WikiEditForm(wiki, turi.strip_leading_slash,
+ "Changes rejected: ", "", "<p>Password invalid</p>")
+ return entity.to_http_response
+ end
+
+ # Save markdown source
+ markdown = markdown.replace('\r', "")
+ markdown.write_to_file file_path
+
+ # Update HTML files
+ var wiki = wiki
+ wiki.render
+
+ var link
+ if turi.has_prefix("/pages/") then
+ link = root_url / turi.substring_from(7)
+ else link = root_url / turi
+ link = link.strip_extension(".md") + ".html"
+
+ # Show confirmation
+ var body = """
+<p>Your edits were recorded and the file is updated: <a href="{{{link}}}">{{{link}}}</a></p>
+"""
+ var entity = new WikiEditForm(wiki, turi.strip_leading_slash, "Changes saved: ", "", body)
+ return entity.to_http_response
+ else
+ # Show edit form, and preview when requested
+
+ # When not in a preview, use the local content of the file
+ if action != "Preview" then markdown = file_path.to_path.read_all
+
+ var form = """
+<form method="POST" action="/edit{{{turi}}}">
+ You may edit the file. When you are done, click on "Submit".<br/>
+ <textarea name="content" rows="30" cols="80">{{{markdown.html_escape}}}</textarea><br/>
+"""
+ if passwords != null then form += """
+ Password: <input type="password" name="password"><br/>
+"""
+ form += """
+ <input type="submit" name="action" value="Preview">
+ <input type="submit" name="action" value="Submit">
+</form>
+"""
+
+ # Show processed markdown only on preview
+ if action != "Preview" then markdown = ""
+
+ var entity = new WikiEditForm(wiki, turi.strip_leading_slash, "Edit source: ", markdown, form)
+ return entity.to_http_response
+ end
+ end