summary refs log tree commit diff stats
path: root/pkgs/by-name/ba/back/src/git_bug/format
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-12-26 17:50:54 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-12-26 17:58:27 +0100
commitdfb5714045e99a09bf3f67890ae3cdeab47058b3 (patch)
tree5e76e310892ea7e36099312e25023aa154217a28 /pkgs/by-name/ba/back/src/git_bug/format
parentfix(pkgs/back): Use rocket to manage the configuration values (diff)
downloadnixos-server-dfb5714045e99a09bf3f67890ae3cdeab47058b3.zip
feat(pkgs/back): Rewrite the `git-bug` interface code
The previous code was more or less reverse engineered, whilst this code
is based on the actually git-bug source code. This improves the whole
issue and operation handling immensely and also makes the code better
maintainable. Furthermore, it also adds support for the operations that
had not already used in `vhack.eu/nixos-server.git`.
Diffstat (limited to 'pkgs/by-name/ba/back/src/git_bug/format')
-rw-r--r--pkgs/by-name/ba/back/src/git_bug/format/mod.rs123
1 files changed, 123 insertions, 0 deletions
diff --git a/pkgs/by-name/ba/back/src/git_bug/format/mod.rs b/pkgs/by-name/ba/back/src/git_bug/format/mod.rs
new file mode 100644
index 0000000..4ebf6d4
--- /dev/null
+++ b/pkgs/by-name/ba/back/src/git_bug/format/mod.rs
@@ -0,0 +1,123 @@
+// Back - An extremely simple git issue tracking system. Inspired by tvix's
+// panettone
+//
+// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: AGPL-3.0-or-later
+//
+// This file is part of Back.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/agpl.txt>.
+
+use std::fmt::Display;
+
+use chrono::DateTime;
+use markdown::to_html;
+use serde::Deserialize;
+use serde_json::Value;
+
+#[derive(Debug, Default, Clone)]
+/// Markdown content.
+pub struct MarkDown {
+    value: String,
+}
+
+impl Display for MarkDown {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.write_str(to_html(&self.value).as_str())
+    }
+}
+impl From<&Value> for MarkDown {
+    fn from(value: &Value) -> Self {
+        Self {
+            value: value.as_str().expect("This will exist").to_owned(),
+        }
+    }
+}
+
+/// An UNIX time stamp.
+///
+/// These should only ever be used for human-display, because timestamps are unreliably in a
+/// distributed system.
+/// Because of this reason, there is no `value()` function.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct TimeStamp {
+    value: u64,
+}
+impl From<&Value> for TimeStamp {
+    fn from(value: &Value) -> Self {
+        Self {
+            value: value.as_u64().expect("This must exist"),
+        }
+    }
+}
+impl Display for TimeStamp {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let date =
+            DateTime::from_timestamp(self.value as i64, 0).expect("This timestamp should be vaild");
+
+        let newdate = date.format("%Y-%m-%d %H:%M:%S");
+        f.write_str(newdate.to_string().as_str())
+    }
+}
+
+#[derive(Debug, Default, Deserialize, Clone, PartialEq, Eq)]
+/// A string that should be escaped when injected into html content.
+pub struct HtmlString {
+    value: String,
+}
+
+impl From<MarkDown> for HtmlString {
+    fn from(value: MarkDown) -> Self {
+        Self { value: value.value }
+    }
+}
+
+impl From<&Value> for HtmlString {
+    fn from(value: &Value) -> Self {
+        Self {
+            value: value.as_str().expect("This will exist").to_owned(),
+        }
+    }
+}
+impl Display for HtmlString {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.write_str(escape_html(&self.value).as_str())
+    }
+}
+
+// From `tera::escape_html`
+/// Escape HTML following [OWASP](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet)
+///
+/// Escape the following characters with HTML entity encoding to prevent switching
+/// into any execution context, such as script, style, or event handlers. Using
+/// hex entities is recommended in the spec. In addition to the 5 characters
+/// significant in XML (&, <, >, ", '), the forward slash is included as it helps
+/// to end an HTML entity.
+///
+/// ```text
+/// & --> &amp;
+/// < --> &lt;
+/// > --> &gt;
+/// " --> &quot;
+/// ' --> &#x27;     &apos; is not recommended
+/// / --> &#x2F;     forward slash is included as it helps end an HTML entity
+/// ```
+#[inline]
+pub fn escape_html(input: &str) -> String {
+    let mut output = String::with_capacity(input.len() * 2);
+    for c in input.chars() {
+        match c {
+            '&' => output.push_str("&amp;"),
+            '<' => output.push_str("&lt;"),
+            '>' => output.push_str("&gt;"),
+            '"' => output.push_str("&quot;"),
+            '\'' => output.push_str("&#x27;"),
+            '/' => output.push_str("&#x2F;"),
+            _ => output.push(c),
+        }
+    }
+
+    // Not using shrink_to_fit() on purpose
+    output
+}