@@ -6,6 +6,7 @@ const { whatis } = require("../util/langutil");
6
6
const { Actor, UserActorType } = require ( "./auth/Actor" ) ;
7
7
const BaseService = require ( "./BaseService" ) ;
8
8
const { DB_WRITE } = require ( "./database/consts" ) ;
9
+ const { UsernameNotifSelector } = require ( "./NotificationService" ) ;
9
10
10
11
class ShareService extends BaseService {
11
12
static MODULES = {
@@ -85,16 +86,16 @@ class ShareService extends BaseService {
85
86
uid : share_uid ,
86
87
} ) ;
87
88
89
+ if ( ! share ) {
90
+ throw APIError . create ( 'share_expired' ) ;
91
+ }
92
+
88
93
share . data = this . db . case ( {
89
94
mysql : ( ) => share . data ,
90
95
otherwise : ( ) =>
91
96
JSON . parse ( share . data ?? '{}' ) ,
92
97
} ) ( ) ;
93
98
94
- if ( ! share ) {
95
- throw APIError . create ( 'share_expired' ) ;
96
- }
97
-
98
99
const actor = Actor . adapt ( req . actor ?? req . user ) ;
99
100
if ( ! actor ) {
100
101
// this shouldn't happen; auth should catch it
@@ -137,6 +138,74 @@ class ShareService extends BaseService {
137
138
} ) ;
138
139
}
139
140
} ) . attach ( router ) ;
141
+
142
+ Endpoint ( {
143
+ route : '/request' ,
144
+ methods : [ 'POST' ] ,
145
+ mw : [ configurable_auth ( ) ] ,
146
+ handler : async ( req , res ) => {
147
+ const share_uid = req . body . uid ;
148
+
149
+ const share = await svc_share . get_share ( {
150
+ uid : share_uid ,
151
+ } ) ;
152
+
153
+ // track: null check before processing
154
+ if ( ! share ) {
155
+ throw APIError . create ( 'share_expired' ) ;
156
+ }
157
+
158
+ share . data = this . db . case ( {
159
+ mysql : ( ) => share . data ,
160
+ otherwise : ( ) =>
161
+ JSON . parse ( share . data ?? '{}' ) ,
162
+ } ) ( ) ;
163
+
164
+ const actor = Actor . adapt ( req . actor ?? req . user ) ;
165
+ if ( ! actor ) {
166
+ // this shouldn't happen; auth should catch it
167
+ throw new Error ( 'actor missing' ) ;
168
+ }
169
+
170
+ // track: opposite condition of sibling
171
+ // :: sibling: /apply endpoint
172
+ if (
173
+ actor . type . user . email_confirmed &&
174
+ actor . type . user . email === share . recipient_email
175
+ ) {
176
+ throw APIError . create ( 'no_need_to_request' ) ;
177
+ }
178
+
179
+ const issuer_user = await get_user ( {
180
+ id : share . issuer_user_id ,
181
+ } ) ;
182
+
183
+ if ( ! issuer_user ) {
184
+ throw APIError . create ( 'share_expired' ) ;
185
+ }
186
+
187
+ const svc_notification = this . services . get ( 'notification' ) ;
188
+ svc_notification . notify (
189
+ UsernameNotifSelector ( issuer_user . username ) ,
190
+ {
191
+ source : 'sharing' ,
192
+ title : `User ${ actor . type . user . username } is ` +
193
+ `trying to open a share you sent to ` +
194
+ share . recipient_email ,
195
+ template : 'user-requesting-share' ,
196
+ fields : {
197
+ username : actor . type . user . username ,
198
+ intended_recipient : share . recipient_email ,
199
+ permissions : share . data . permissions ,
200
+ } ,
201
+ }
202
+ ) ;
203
+ res . json ( {
204
+ $ : 'api:status-report' ,
205
+ status : 'success' ,
206
+ } ) ;
207
+ }
208
+ } ) . attach ( router ) ;
140
209
}
141
210
142
211
async get_share ( { uid } ) {
0 commit comments