ng_wallet/permissions.rs
1// Copyright (c) 2022-2025 Niko Bonnieure, Par le Peuple, NextGraph.org developers
2// All rights reserved.
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE2 or http://www.apache.org/licenses/LICENSE-2.0>
5// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
6// at your option. All files in the project carrying such
7// notice may not be copied, modified, or distributed except
8// according to those terms.
9
10use serde::{Deserialize, Serialize};
11
12use std::collections::HashMap;
13
14use ng_repo::types::UserId;
15
16/// Access Mode
17#[derive(Clone, Debug, Serialize, Deserialize)]
18pub enum AccessMode {
19 Read,
20 Write,
21 Create,
22 HookCreate,
23 HookDelete,
24 Control,
25 Sign,
26 Run,
27 Cron,
28 Query,
29 SocialQuery,
30 Share,
31 DeviceCapability,
32}
33
34/// Access Scope
35#[derive(Clone, Debug, Serialize, Deserialize)]
36pub enum AccessScope {
37 Once,
38 OnceSub,
39 OnceMany,
40 OnceManySub,
41 Permanent,
42 Foreground,
43 Background,
44}
45
46/// Access Request Version 0
47#[derive(Clone, Debug, Serialize, Deserialize)]
48pub struct AccessRequestV0 {
49 /// ID of the Access Request. Should be the tokenized CommitID of the RDF AccessRequest in the App's manifest Document.
50 pub id: String,
51
52 pub mode: AccessMode,
53
54 /// allowed types for this access mode. Usually a PrimaryClass. can be "any".
55 /// for Runs: name of the service
56 /// for Queries: Nuri of the Sparql, Fragment, ShapeTree or GraphQL
57 /// for Cron: the time interval
58 /// for Share: Stream, e:mail, e:xxx, Contact, Document
59 /// for DeviceCapability: camera, microphone, location, receiveSMS, scanQR, internet
60 pub types: Vec<String>,
61
62 /// allowed scopes for this access mode
63 pub scopes: Vec<AccessScope>,
64
65 /// is this access request optional?
66 pub optional: bool,
67
68 /// request depends on another request (only if optional)
69 pub depends_on: Option<String>
70}
71
72impl AccessRequestV0 {
73 pub fn new_access_all() -> Self {
74 Self {
75 id: "".to_string(),
76 mode: AccessMode::Read,
77 types: vec!["any".to_string()],
78 scopes: vec![AccessScope::Permanent],
79 optional: false,
80 depends_on: None,
81 }
82 }
83}
84
85/// App Component type
86#[derive(Clone, Debug, Serialize, Deserialize)]
87pub enum AppComponentType {
88 Viewer,
89 Editor,
90 ReadService,
91 WriteService,
92 Model,
93}
94
95/// AppComponentV0 Version 0
96#[derive(Clone, Debug, Serialize, Deserialize)]
97pub struct AppComponentV0 {
98 /// Name of the component, can be an official component of the for n:g:z, or custom ones n:xxx:z:yyy or o:xxx
99 pub name: String,
100
101 pub component_type: AppComponentType
102}
103
104/// Primary Class Install Version 0
105#[derive(Clone, Debug, Serialize, Deserialize)]
106pub struct PrimaryClassInstallV0 {
107 /// Primary Class name, can be an official name or a custom name of the form app:n... or app:o:...
108 pub primary_class: String,
109
110 pub components: Vec<AppComponentV0>
111}
112
113/// App Manifest Version 0
114#[derive(Clone, Debug, Serialize, Deserialize)]
115pub struct AppManifestV0 {
116 /// Nuri
117 pub nuri: Option<String>,
118
119 /// Origin (for webapps only)
120 pub origin: Option<String>,
121
122 /// cannot create Documents?
123 pub singleton: bool,
124
125 /// list of Access Requests
126 pub access_requests: Vec<AccessRequestV0>,
127
128 /// installs: list of Viewers, Editors, Services and Models, by PrimaryClass, that will be installed by this app
129 pub installs: HashMap<String, PrimaryClassInstallV0>,
130
131 /// dependencies: list of other apps (Nuri) that needs to be installed before this app can be installed
132 pub dependencies: Vec<String>,
133
134 /// optional name. Only for registered or official apps
135 pub name: Option<String>,
136
137 /// optional title. Broker will enter the domain's homepage title here, if any
138 pub title: Option<String>,
139
140 /// optional description. Broker will enter the domain's homepage description here, if any
141 pub description: Option<String>,
142
143 /// optional icon. Broker will enter the domain's homepage favicon here, if any
144 #[serde(with = "serde_bytes")]
145 pub icon: Vec<u8>,
146
147 /// optional image. Broker will enter the domain's homepage main image here, if any
148 #[serde(with = "serde_bytes")]
149 pub image: Vec<u8>,
150}
151
152/// Web App Manifest
153#[derive(Clone, Debug, Serialize, Deserialize)]
154pub enum AppManifest {
155 V0(AppManifestV0),
156}
157
158impl AppManifest {
159 pub fn new_for_origin_all_access_v0(origin: String) -> Self {
160 AppManifest::V0(
161 AppManifestV0 {
162 nuri: None,
163 origin: Some(origin),
164 singleton: true,
165 access_requests: vec![AccessRequestV0::new_access_all()],
166 installs: HashMap::new(),
167 dependencies: vec![],
168 name: None,
169 title: None,
170 description: None,
171 icon: vec![],
172 image: vec![]
173 }
174 )
175 }
176 pub fn new_v0(origin: String, singleton: bool, access_requests: Vec<AccessRequestV0>) -> Self {
177 AppManifest::V0(
178 AppManifestV0 {
179 nuri: None,
180 origin: Some(origin),
181 singleton,
182 access_requests,
183 installs: HashMap::new(),
184 dependencies: vec![],
185 name: None,
186 title: None,
187 description: None,
188 icon: vec![],
189 image: vec![]
190 }
191 )
192 }
193 pub fn to_url_param(&self) -> String {
194 let ser = serde_bare::to_vec(self).unwrap();
195 base64_url::encode(&ser)
196 }
197}
198
199/// Access Grant Version 0
200#[derive(Clone, Debug, Serialize, Deserialize)]
201pub struct AccessGrantV0 {
202 /// Nuri of tokenized commitID of this grant
203 pub id: String,
204
205 /// reference to the AccessRequest. can be None for PermaCaps
206 pub request: Option<String>,
207
208 pub mode: AccessMode,
209
210 /// Usually a PrimaryClass.
211 /// for Runs: name of the service
212 /// for Queries: Nuri of the Sparql, Fragment, ShapeTree or GraphQL
213 /// for Cron: the time interval
214 /// for Share: Stream, e:mail, e:xxx, Contact, Document
215 /// for DeviceCapability: camera, microphone, location, receiveSMS, scanQR, internet
216 pub access_type: String,
217
218 pub scope: AccessScope,
219
220 /// Nuri of target. Can be None for services
221 pub target: Option<String>,
222
223 /// UserId of grantee (a user or a robot)
224 pub grantee: UserId,
225
226 /// grant depends on another grant
227 pub depends_on: Option<String>
228}
229
230
231
232