Skip to main content

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