-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Expand file tree
/
Copy pathSessionsRouter.js
More file actions
140 lines (134 loc) · 4.42 KB
/
SessionsRouter.js
File metadata and controls
140 lines (134 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import ClassesRouter from './ClassesRouter';
import Parse from 'parse/node';
import rest from '../rest';
import Auth from '../Auth';
import RestWrite from '../RestWrite';
export class SessionsRouter extends ClassesRouter {
className() {
return '_Session';
}
async handleMe(req) {
if (!req.info || !req.info.sessionToken) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token required.');
}
const sessionToken = req.info.sessionToken;
// Query with master key to validate the session token and get the session objectId
const sessionResponse = await rest.find(
req.config,
Auth.master(req.config),
'_Session',
{ sessionToken },
{},
req.info.clientSDK,
req.info.context
);
if (
!sessionResponse.results ||
sessionResponse.results.length == 0 ||
!sessionResponse.results[0].user
) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token not found.');
}
const sessionObjectId = sessionResponse.results[0].objectId;
const userId = sessionResponse.results[0].user.objectId;
// Re-fetch the session with the caller's auth context so that
// protectedFields and CLP apply correctly; if the caller used master key,
// protectedFields are bypassed, matching the behavior of GET /sessions/:id
const refetchAuth =
req.auth?.isMaster || req.auth?.isMaintenance
? req.auth
: new Auth.Auth({
config: req.config,
isMaster: false,
user: Parse.Object.fromJSON({ className: '_User', objectId: userId }),
installationId: req.info.installationId,
});
const response = await rest.get(
req.config,
refetchAuth,
'_Session',
sessionObjectId,
{},
req.info.clientSDK,
req.info.context
);
if (!response.results || response.results.length == 0) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token not found.');
}
return {
response: response.results[0],
};
}
async handleUpdateToRevocableSession(req) {
const config = req.config;
const user = req.auth.user;
// Issue #2720
// Calling without a session token would result in a not found user
if (!user) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'invalid session');
}
const { sessionData, createSession } = RestWrite.createSession(config, {
userId: user.id,
createdWith: {
action: 'upgrade',
},
installationId: req.auth.installationId,
});
await createSession();
// delete the session token, use the db to skip beforeSave
await config.database.update(
'_User',
{ objectId: user.id },
{ sessionToken: { __op: 'Delete' } }
);
// Re-fetch the session with the caller's auth context so that
// protectedFields filtering applies correctly; if the caller used master key,
// protectedFields are bypassed, matching the behavior of GET /sessions/:id
const refetchAuth =
req.auth.isMaster || req.auth.isMaintenance
? req.auth
: new Auth.Auth({
config,
isMaster: false,
user: Parse.Object.fromJSON({ className: '_User', objectId: user.id }),
installationId: req.auth.installationId,
});
const response = await rest.find(
config,
refetchAuth,
'_Session',
{ sessionToken: sessionData.sessionToken },
{},
req.info.clientSDK,
req.info.context
);
if (!response.results || response.results.length === 0) {
throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Failed to load upgraded session.');
}
return { response: response.results[0] };
}
mountRoutes() {
this.route('GET', '/sessions/me', req => {
return this.handleMe(req);
});
this.route('GET', '/sessions', req => {
return this.handleFind(req);
});
this.route('GET', '/sessions/:objectId', req => {
return this.handleGet(req);
});
this.route('POST', '/sessions', req => {
return this.handleCreate(req);
});
this.route('PUT', '/sessions/:objectId', req => {
return this.handleUpdate(req);
});
this.route('DELETE', '/sessions/:objectId', req => {
return this.handleDelete(req);
});
this.route('POST', '/upgradeToRevocableSession', req => {
return this.handleUpdateToRevocableSession(req);
});
}
}
export default SessionsRouter;