Skip to content

Commit c3b1ba1

Browse files
committed
mobx: Created addSessionView, added support for custom sessions
1 parent 45613bb commit c3b1ba1

File tree

4 files changed

+243
-2
lines changed

4 files changed

+243
-2
lines changed

app/src/store/store.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
} from './stores';
2121
import {
2222
AccountSectionView,
23+
AddSessionView,
2324
AppView,
2425
BatchesView,
2526
BuildSwapView,
@@ -66,6 +67,7 @@ export class Store {
6667
orderListView = new OrderListView(this);
6768
batchesView = new BatchesView(this);
6869
registerSidecarView = new RegisterSidecarView(this);
70+
addSessionView = new AddSessionView(this);
6971

7072
/** the backend api services to be used by child stores */
7173
api: {

app/src/store/stores/sessionStore.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ export default class SessionStore {
102102
type: LIT.SessionTypeMap[keyof LIT.SessionTypeMap],
103103
expiry: Date,
104104
copy = false,
105+
proxy?: string,
106+
customPermissions?: LIT.MacaroonPermission[],
105107
) {
106108
try {
107109
this._store.log.info(`submitting session with label ${label}`, {
@@ -114,9 +116,9 @@ export default class SessionStore {
114116
label,
115117
type,
116118
expiry,
117-
this.proxyServer,
119+
proxy || this.proxyServer,
118120
!IS_PROD,
119-
[],
121+
customPermissions || [],
120122
);
121123

122124
// fetch all sessions to update the store's state

app/src/store/views/addSessionView.ts

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
import { makeAutoObservable, observable } from 'mobx';
2+
import { Store } from 'store';
3+
import * as LIT from 'types/generated/lit-sessions_pb';
4+
import { MAX_DATE, PermissionUriMap } from 'util/constants';
5+
6+
export default class AddSessionView {
7+
private _store: Store;
8+
9+
label = '';
10+
permissionType = 'admin'; // Expected values: admin | read-only | custom | liquidity | payments
11+
editing = false;
12+
permissions: { [key: string]: boolean } = {
13+
openChannel: false,
14+
closeChannel: false,
15+
setFees: false,
16+
loop: false,
17+
pool: false,
18+
send: false,
19+
receive: false,
20+
};
21+
expiration = 'never'; // Expected values: 7 | 30 | 60 | 90 | never | custom
22+
expirationOptions = [
23+
{ label: '7 Days', value: '7' },
24+
{ label: '30 Days', value: '30' },
25+
{ label: '60 Days', value: '60' },
26+
{ label: '90 Days', value: '90' },
27+
{ label: 'Never', value: 'never' },
28+
{ label: 'Custom', value: 'custom' },
29+
];
30+
expirationDate = '';
31+
showAdvanced = false;
32+
proxy = '';
33+
34+
constructor(store: Store) {
35+
makeAutoObservable(
36+
this,
37+
{
38+
permissions: observable.deep,
39+
},
40+
{ deep: false, autoBind: true },
41+
);
42+
43+
this._store = store;
44+
}
45+
46+
//
47+
// Computed properties
48+
//
49+
50+
get sessionType() {
51+
if (this.permissionType === 'admin') {
52+
return LIT.SessionType.TYPE_MACAROON_ADMIN;
53+
} else if (this.permissionType === 'read-only') {
54+
return LIT.SessionType.TYPE_MACAROON_READONLY;
55+
}
56+
57+
return LIT.SessionType.TYPE_MACAROON_CUSTOM;
58+
}
59+
60+
get sessionDate() {
61+
// If the expiration date is a number of days
62+
if (Number.isInteger(parseInt(this.expiration))) {
63+
const expirationDate = new Date();
64+
expirationDate.setDate(expirationDate.getDate() + parseInt(this.expiration));
65+
return expirationDate;
66+
} else if (this.expiration === 'custom') {
67+
return new Date(this.expirationDate);
68+
}
69+
70+
// Default to max date for when the expiration is "never"
71+
return MAX_DATE;
72+
}
73+
74+
get sessionProxy() {
75+
if (this.proxy) {
76+
return this.proxy;
77+
}
78+
79+
return undefined;
80+
}
81+
82+
get getMacaroonPermissions() {
83+
// Only output macaroon permissions when the session type is custom
84+
if (this.sessionType === LIT.SessionType.TYPE_MACAROON_CUSTOM) {
85+
// Include all read-only URIs by default
86+
const permissions: string[] = ['***readonly***'];
87+
88+
// Loop over all permissions to determine which are enabled
89+
Object.entries(this.permissions).forEach(([permissionName, permissionEnabled]) => {
90+
if (permissionEnabled) {
91+
// Add all of the URIs for this permission
92+
permissions.push(...PermissionUriMap[permissionName]);
93+
}
94+
});
95+
96+
// Convert all of the permission strings into MacaroonPermission objects
97+
return permissions.map(uri => {
98+
const mp = new LIT.MacaroonPermission();
99+
mp.setEntity('uri');
100+
mp.setAction(uri);
101+
return mp;
102+
});
103+
}
104+
105+
return [];
106+
}
107+
108+
//
109+
// Actions
110+
//
111+
112+
setLabel(label: string) {
113+
this.label = label;
114+
}
115+
116+
setExpiration(expiration: string) {
117+
this.expiration = expiration;
118+
}
119+
120+
setExpirationDate(expirationDate: string) {
121+
this.expirationDate = expirationDate;
122+
}
123+
124+
setProxy(proxy: string) {
125+
this.proxy = proxy;
126+
}
127+
128+
setPermissionType(permissionType: string) {
129+
this.permissionType = permissionType;
130+
131+
switch (permissionType) {
132+
case 'admin':
133+
this.setAllPermissions(true);
134+
break;
135+
136+
case 'read-only':
137+
this.setAllPermissions(false);
138+
break;
139+
140+
case 'liquidity':
141+
this.setAllPermissions(false);
142+
this.permissions.setFees = true;
143+
this.permissions.loop = true;
144+
this.permissions.pool = true;
145+
break;
146+
147+
case 'payments':
148+
this.setAllPermissions(false);
149+
this.permissions.send = true;
150+
this.permissions.receive = true;
151+
break;
152+
153+
case 'custom':
154+
// We don't need to change anything, let the user customize permissions how they want
155+
break;
156+
}
157+
}
158+
159+
togglePermission(permission: string) {
160+
this.setPermissionType('custom');
161+
this.permissions[permission] = !this.permissions[permission];
162+
}
163+
164+
toggleEditing() {
165+
this.editing = !this.editing;
166+
}
167+
168+
toggleAdvanced() {
169+
this.showAdvanced = !this.showAdvanced;
170+
}
171+
172+
cancel() {
173+
this.label = '';
174+
this.permissionType = 'admin';
175+
this.editing = false;
176+
this.setAllPermissions(false);
177+
this.expiration = 'never';
178+
this.showAdvanced = false;
179+
this._store.settingsStore.sidebarVisible = true;
180+
}
181+
182+
//
183+
// Async Actions
184+
//
185+
186+
async handleSubmit() {
187+
if (this.permissionType === 'custom') {
188+
this._store.settingsStore.sidebarVisible = false;
189+
this._store.router.push('/connect/custom');
190+
} else {
191+
const session = await this._store.sessionStore.addSession(
192+
this.label,
193+
this.sessionType,
194+
MAX_DATE,
195+
true,
196+
);
197+
198+
if (session) {
199+
this.cancel();
200+
}
201+
}
202+
}
203+
204+
async handleCustomSubmit() {
205+
let label = this.label;
206+
207+
// Automatically generate human friendly labels for custom sessions
208+
if (label === '') {
209+
label = `My ${this.permissionType} session`;
210+
}
211+
212+
const session = await this._store.sessionStore.addSession(
213+
label,
214+
this.sessionType,
215+
this.sessionDate,
216+
true,
217+
this.sessionProxy,
218+
this.getMacaroonPermissions,
219+
);
220+
221+
if (session) {
222+
this.cancel();
223+
this._store.router.push('/connect');
224+
}
225+
}
226+
227+
//
228+
// Private helper functions
229+
//
230+
231+
private setAllPermissions(value: boolean) {
232+
Object.keys(this.permissions).forEach(permissionName => {
233+
this.permissions[permissionName] = value;
234+
});
235+
}
236+
}

app/src/store/views/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export { default as OrderListView } from './orderListView';
1010
export { default as LeaseView } from './leaseView';
1111
export { default as BatchesView } from './batchesView';
1212
export { default as RegisterSidecarView } from './registerSidecarView';
13+
export { default as AddSessionView } from './addSessionView';

0 commit comments

Comments
 (0)