wip
This commit is contained in:
parent
5deba2fdb1
commit
9fe5d3c70e
45 changed files with 5311 additions and 815 deletions
20
common/Cargo.toml
Normal file
20
common/Cargo.toml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "webcomment-common"
|
||||
version = "0.1.0"
|
||||
authors = ["tuxmain <tuxmain@zettascript.org>"]
|
||||
license = "AGPL-3.0-only"
|
||||
repository = "https://git.txmn.tk/tuxmain/webcomment"
|
||||
description = "Templatable comment web server"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
argon2 = "0.4.1"
|
||||
base64 = "0.21.0"
|
||||
log = "0.4.17"
|
||||
percent-encoding = "2.2.0"
|
||||
rand = "0.8.5"
|
||||
rand_core = { version = "0.6.4", features = ["std"] }
|
||||
serde = { version = "1.0.154", features = ["derive", "rc"] }
|
||||
serde_json = "1.0.94"
|
||||
sha2 = "0.10.6"
|
||||
unic-langid = { version = "0.9.1", features = ["macros"] }
|
||||
2
common/src/api.rs
Normal file
2
common/src/api.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod queries;
|
||||
pub mod resps;
|
||||
34
common/src/api/queries.rs
Normal file
34
common/src/api/queries.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/*#[derive(Deserialize)]
|
||||
pub struct Admin<T> {
|
||||
pub admin_psw: String,
|
||||
#[serde(flatten)]
|
||||
pub query: T,
|
||||
}*/
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct CommentsByTopic {
|
||||
pub mutation_token: Option<String>,
|
||||
pub topic: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct CommentsByTopicAdmin {
|
||||
pub admin_psw: String,
|
||||
pub topic: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct NewComment {
|
||||
pub author: String,
|
||||
pub email: String,
|
||||
pub text: String,
|
||||
pub topic: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct RemoveCommentAdmin {
|
||||
pub admin_psw: String,
|
||||
pub comment_id: String,
|
||||
}
|
||||
90
common/src/api/resps.rs
Normal file
90
common/src/api/resps.rs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
use crate::types::*;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/*/// Use Ok only when there is no dedicated struct
|
||||
/// (because serde doesn't allow flattening enums)
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum Result {
|
||||
Ok,
|
||||
#[serde(rename = "error")]
|
||||
Err(Error),
|
||||
}*/
|
||||
|
||||
pub type Result = std::result::Result<Response, Error>;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum Error {
|
||||
Antispam {
|
||||
timeout: Time,
|
||||
},
|
||||
BadAdminAuth,
|
||||
IllegalContent,
|
||||
Internal,
|
||||
InvalidRequest,
|
||||
/// Admin only! Error messages may contain sensitive information.
|
||||
Message(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum Response {
|
||||
CommentsByTopic(CommentsByTopic),
|
||||
CommentsByTopicAdmin(CommentsByTopicAdmin),
|
||||
NewComment(NewComment),
|
||||
Ok,
|
||||
}
|
||||
|
||||
/*#[derive(Serialize)]
|
||||
pub struct GenericOk {}*/
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct CommentsByTopic {
|
||||
pub approved_comments: Vec<ApprovedCommentWithMeta>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct CommentsByTopicAdmin {
|
||||
pub approved_comments: Vec<ApprovedCommentWithMeta>,
|
||||
pub pending_comments: Vec<PendingCommentWithMeta>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct OriginalComment {
|
||||
pub author: String,
|
||||
pub editable: bool,
|
||||
pub last_edit_time: Option<Time>,
|
||||
pub post_time: Time,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct ApprovedCommentWithMeta {
|
||||
pub email: Option<String>,
|
||||
pub author: String,
|
||||
pub editable: bool,
|
||||
pub id: String,
|
||||
pub last_edit_time: Option<Time>,
|
||||
pub post_time: Time,
|
||||
pub status: CommentStatus,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct PendingCommentWithMeta {
|
||||
pub addr: Option<String>,
|
||||
pub email: Option<String>,
|
||||
pub author: String,
|
||||
pub editable: bool,
|
||||
pub id: String,
|
||||
pub last_edit_time: Option<Time>,
|
||||
pub post_time: Time,
|
||||
pub status: CommentStatus,
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct NewComment {
|
||||
pub id: String,
|
||||
pub mutation_token: String,
|
||||
pub post_time: Time,
|
||||
}
|
||||
2
common/src/lib.rs
Normal file
2
common/src/lib.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod api;
|
||||
pub mod types;
|
||||
111
common/src/types.rs
Normal file
111
common/src/types.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
use base64::Engine;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
pub type Time = u64;
|
||||
|
||||
pub const BASE64: base64::engine::general_purpose::GeneralPurpose =
|
||||
base64::engine::general_purpose::GeneralPurpose::new(
|
||||
&base64::alphabet::URL_SAFE,
|
||||
base64::engine::general_purpose::NO_PAD,
|
||||
);
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct MutationToken(pub [u8; 16]);
|
||||
|
||||
impl MutationToken {
|
||||
pub fn new() -> Self {
|
||||
Self(rand::random())
|
||||
}
|
||||
|
||||
pub fn to_base64(&self) -> String {
|
||||
BASE64.encode(self.0)
|
||||
}
|
||||
|
||||
pub fn from_base64(s: &str) -> Result<Self, base64::DecodeError> {
|
||||
std::panic::catch_unwind(|| {
|
||||
let mut buf = [0; 16];
|
||||
BASE64.decode_slice_unchecked(s.as_bytes(), &mut buf)?;
|
||||
Ok(Self(buf))
|
||||
})
|
||||
.map_err(|_| base64::DecodeError::InvalidLength)?
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for MutationToken {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct TopicHash(pub [u8; 32]);
|
||||
|
||||
impl TopicHash {
|
||||
pub fn from_topic(topic: &str) -> Self {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(topic.as_bytes());
|
||||
Self(hasher.finalize().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for TopicHash {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub struct CommentId(pub [u8; 16]);
|
||||
|
||||
impl CommentId {
|
||||
pub fn new() -> Self {
|
||||
Self(rand::random())
|
||||
}
|
||||
|
||||
pub fn zero() -> Self {
|
||||
Self([0; 16])
|
||||
}
|
||||
|
||||
pub fn max() -> Self {
|
||||
Self([255; 16])
|
||||
}
|
||||
|
||||
pub fn to_base64(&self) -> String {
|
||||
BASE64.encode(self.0)
|
||||
}
|
||||
|
||||
pub fn from_base64(s: &str) -> Result<Self, base64::DecodeError> {
|
||||
std::panic::catch_unwind(|| {
|
||||
let mut buf = [0; 16];
|
||||
BASE64.decode_slice_unchecked(s.as_bytes(), &mut buf)?;
|
||||
Ok(Self(buf))
|
||||
})
|
||||
.map_err(|_| base64::DecodeError::InvalidLength)?
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for CommentId {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum CommentStatus {
|
||||
Pending = 0,
|
||||
Approved = 1,
|
||||
ApprovedEdited(Comment) = 2,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub struct Comment {
|
||||
pub author: String,
|
||||
pub email: Option<String>,
|
||||
pub last_edit_time: Option<u64>,
|
||||
pub mutation_token: MutationToken,
|
||||
pub post_time: u64,
|
||||
pub text: String,
|
||||
pub topic_hash: TopicHash,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue