JavaScript is disabled, refresh for a better experience. ambee/giterated

ambee/giterated

Git repository hosting, collaboration, and discovery for the Fediverse.

Add authentication back into the operation states

Amber - ⁨2⁩ years ago

parent: tbd commit: ⁨97a26fd

⁨giterated-models/src/authenticated.rs⁩ - ⁨5203⁩ bytes
Raw
1 use std::{fmt::Debug, sync::Arc};
2
3 use rsa::{
4 pkcs1::DecodeRsaPrivateKey,
5 pss::SigningKey,
6 sha2::Sha256,
7 signature::{RandomizedSigner, SignatureEncoding},
8 RsaPrivateKey,
9 };
10 use serde::{Deserialize, Serialize};
11 use serde_json::Value;
12
13 use crate::{
14 instance::Instance,
15 message::GiteratedMessage,
16 object::{AnyObject, GiteratedObject},
17 operation::{AnyOperation, GiteratedOperation},
18 user::User,
19 };
20
21 #[derive(Debug, Serialize, Deserialize)]
22 pub struct UserTokenMetadata {
23 pub user: User,
24 pub generated_for: Instance,
25 pub exp: u64,
26 }
27
28 #[derive(Debug)]
29 pub struct Authenticated<O: GiteratedObject, D: GiteratedOperation<O>> {
30 pub source: Vec<Arc<dyn AuthenticationSourceProviders + Send + Sync>>,
31 pub message: GiteratedMessage<O, D>,
32 }
33
34 #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
35 pub struct AuthenticatedPayload {
36 pub source: Vec<AuthenticationSource>,
37 pub object: String,
38 pub operation: String,
39 pub payload: Vec<u8>,
40 }
41
42 impl AuthenticatedPayload {
43 pub fn into_message(self) -> GiteratedMessage<AnyObject, AnyOperation> {
44 let payload = serde_json::from_slice::<Value>(&self.payload).unwrap();
45 GiteratedMessage {
46 object: AnyObject(self.object),
47 operation: self.operation,
48 payload: AnyOperation(payload),
49 }
50 }
51 }
52
53 pub trait AuthenticationSourceProvider: Debug {
54 fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource;
55 }
56
57 pub trait AuthenticationSourceProviders: Debug {
58 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource>;
59 }
60
61 impl<A> AuthenticationSourceProviders for A
62 where
63 A: AuthenticationSourceProvider,
64 {
65 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource> {
66 vec![self.authenticate(payload)]
67 }
68 }
69
70 impl<A, B> AuthenticationSourceProviders for (A, B)
71 where
72 A: AuthenticationSourceProvider,
73 B: AuthenticationSourceProvider,
74 {
75 fn authenticate_all(&self, payload: &Vec<u8>) -> Vec<AuthenticationSource> {
76 let (first, second) = self;
77
78 vec![first.authenticate(payload), second.authenticate(payload)]
79 }
80 }
81
82 impl<O: GiteratedObject, D: GiteratedOperation<O>> Authenticated<O, D> {
83 pub fn new(message: GiteratedMessage<O, D>) -> Self {
84 Self {
85 source: vec![],
86 message,
87 }
88 }
89
90 pub fn append_authentication(
91 &mut self,
92 authentication: Arc<dyn AuthenticationSourceProviders + Send + Sync>,
93 ) {
94 self.source.push(authentication);
95 }
96
97 pub fn into_payload(mut self) -> AuthenticatedPayload {
98 let payload = serde_json::to_vec(&self.message.payload).unwrap();
99
100 AuthenticatedPayload {
101 object: self.message.object.to_string(),
102 operation: self.message.operation,
103 source: self
104 .source
105 .drain(..)
106 .map(|provider| provider.as_ref().authenticate_all(&payload))
107 .flatten()
108 .collect::<Vec<_>>(),
109 payload,
110 }
111 }
112 }
113
114 mod verified {}
115
116 #[derive(Clone, Debug)]
117 pub struct UserAuthenticator {
118 pub user: User,
119 pub token: UserAuthenticationToken,
120 }
121
122 impl AuthenticationSourceProvider for UserAuthenticator {
123 fn authenticate(&self, _payload: &Vec<u8>) -> AuthenticationSource {
124 AuthenticationSource::User {
125 user: self.user.clone(),
126 token: self.token.clone(),
127 }
128 }
129 }
130
131 #[derive(Debug, Clone)]
132 pub struct InstanceAuthenticator {
133 pub instance: Instance,
134 pub private_key: String,
135 }
136
137 impl AuthenticationSourceProvider for InstanceAuthenticator {
138 fn authenticate(&self, payload: &Vec<u8>) -> AuthenticationSource {
139 let mut rng = rand::thread_rng();
140
141 let private_key = RsaPrivateKey::from_pkcs1_pem(&self.private_key).unwrap();
142 let signing_key = SigningKey::<Sha256>::new(private_key);
143 let signature = signing_key.sign_with_rng(&mut rng, payload);
144
145 AuthenticationSource::Instance {
146 instance: self.instance.clone(),
147 // TODO: Actually parse signature from private key
148 signature: InstanceSignature(signature.to_bytes().into_vec()),
149 }
150 }
151 }
152
153 #[repr(transparent)]
154 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
155 pub struct UserAuthenticationToken(String);
156
157 impl From<String> for UserAuthenticationToken {
158 fn from(value: String) -> Self {
159 Self(value)
160 }
161 }
162
163 impl ToString for UserAuthenticationToken {
164 fn to_string(&self) -> String {
165 self.0.clone()
166 }
167 }
168
169 impl AsRef<str> for UserAuthenticationToken {
170 fn as_ref(&self) -> &str {
171 &self.0
172 }
173 }
174
175 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
176 pub struct InstanceSignature(Vec<u8>);
177
178 impl AsRef<[u8]> for InstanceSignature {
179 fn as_ref(&self) -> &[u8] {
180 &self.0
181 }
182 }
183
184 #[derive(Clone, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
185 pub enum AuthenticationSource {
186 User {
187 user: User,
188 token: UserAuthenticationToken,
189 },
190 Instance {
191 instance: Instance,
192 signature: InstanceSignature,
193 },
194 }
195