Perform a pseudo-refresh for admin token users (#1599)
* Perform a pseudo-refresh for admin token users Although we don't need to actually refresh the token, when multiplexing is enabled we do still need to hit ROS to let it know we're accessing a Realm and get the sync label. * Adding brief JSdoc and TS definition for isAdminToken. * Perform a pseudo-refresh for admin token users Although we don't need to actually refresh the token, when multiplexing is enabled we do still need to hit ROS to let it know we're accessing a Realm and get the sync label. * Adding brief JSdoc and TS definition for isAdminToken. * Make the timeout consistent * Add basic docs for multiprocess notifications (#1594) * Add basic docs for multiprocess notifications * Adopt core's query parser and update to core v5.1.2 (#1563) * Adopt core's query parser. * Realm Core 5.1.2 * Realm Sync 2.2.9 * Remove tar.xz (#1585) * remove tar.xz decompression and lzma deps * Fixing merge * Updating object store
This commit is contained in:
parent
795be904a1
commit
ce67446976
|
@ -242,7 +242,7 @@ class User {
|
|||
* @return {Promise<User>} Returns a promise with a user
|
||||
*/
|
||||
static authenticate(server, provider, options) {}
|
||||
|
||||
|
||||
/**
|
||||
* Register/login a sync user using an external login provider.
|
||||
* @param {string} server - authentication server
|
||||
|
@ -312,11 +312,16 @@ class User {
|
|||
get token() {}
|
||||
|
||||
/**
|
||||
* Returns true if this user is an administrator
|
||||
* Returns true if this user is an administrator.
|
||||
* @type {bool}
|
||||
*/
|
||||
get isAdmin() {}
|
||||
|
||||
/**
|
||||
* Returns true if the token is an administrator token.
|
||||
*/
|
||||
get isAdminToken() {}
|
||||
|
||||
/**
|
||||
* Logs out the user from the Realm Object Server.
|
||||
*/
|
||||
|
|
|
@ -145,9 +145,9 @@ declare namespace Realm {
|
|||
*/
|
||||
isValid(): boolean;
|
||||
|
||||
min(property?: string): number|Date|null;
|
||||
max(property?: string): number|Date|null;
|
||||
sum(property?: string): number|null;
|
||||
min(property?: string): number | Date | null;
|
||||
max(property?: string): number | Date | null;
|
||||
sum(property?: string): number | null;
|
||||
avg(property?: string): number;
|
||||
|
||||
/**
|
||||
|
@ -268,6 +268,7 @@ declare namespace Realm.Sync {
|
|||
static readonly current: User;
|
||||
readonly identity: string;
|
||||
readonly isAdmin: boolean;
|
||||
readonly isAdminToken: boolean;
|
||||
readonly server: string;
|
||||
readonly token: string;
|
||||
static adminUser(adminToken: string, server?: string): User;
|
||||
|
@ -349,9 +350,9 @@ declare namespace Realm.Sync {
|
|||
|
||||
interface SyncError {
|
||||
name: string;
|
||||
message: string;
|
||||
message: string;
|
||||
isFatal: boolean;
|
||||
category?: string;
|
||||
category?: string;
|
||||
code: number;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,11 +46,8 @@ const postHeaders = {
|
|||
'accept': 'application/json'
|
||||
};
|
||||
|
||||
function auth_url(server) {
|
||||
if (server.charAt(server.length - 1) != '/') {
|
||||
return server + '/auth';
|
||||
}
|
||||
return server + 'auth';
|
||||
function append_url(server, path) {
|
||||
return server + (server.charAt(server.length - 1) != '/' ? '/' : '') + path;
|
||||
}
|
||||
|
||||
function scheduleAccessTokenRefresh(user, localRealmPath, realmUrl, expirationDate) {
|
||||
|
@ -63,13 +60,63 @@ function print_error() {
|
|||
(console.error || console.log).apply(console, arguments);
|
||||
}
|
||||
|
||||
function validateRefresh(user, localRealmPath, response, json) {
|
||||
let session = user._sessionForOnDiskPath(localRealmPath);
|
||||
if (!session) {
|
||||
print_error(`Unhandled session token refresh error: could not look up session at path ${localRealmPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const errorHandler = session.config.error;
|
||||
if (response.status != 200) {
|
||||
let error = new AuthError(json);
|
||||
if (errorHandler) {
|
||||
errorHandler(session, error);
|
||||
} else {
|
||||
print_error('Unhandled session token refresh error', error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (session.state === 'invalid') {
|
||||
return;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
function refreshAdminToken(user, localRealmPath, realmUrl) {
|
||||
const token = user.token;
|
||||
const server = user.server;
|
||||
|
||||
// We don't need to actually refresh the token, but we need to let ROS know
|
||||
// we're accessing the file and get the sync label for multiplexing
|
||||
let parsedRealmUrl = url_parse(realmUrl);
|
||||
const url = append_url(user.server, 'realms/files/' + encodeURIComponent(parsedRealmUrl.pathname));
|
||||
performFetch(url, {method: 'GET', timeout: 10000.0, headers: {Authorization: user.token}})
|
||||
.then((response) => response.json().then((json) => { return { response, json }; }))
|
||||
.then((responseAndJson) => {
|
||||
const response = responseAndJson.response;
|
||||
const json = responseAndJson.json;
|
||||
|
||||
const newUser = user.constructor.adminUser(token, server);
|
||||
const session = validateRefresh(newUser, localRealmPath, response, json);
|
||||
if (session) {
|
||||
parsedRealmUrl.set('pathname', json.path);
|
||||
session._refreshAccessToken(user.token, parsedRealmUrl.href, json.syncLabel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refreshAccessToken(user, localRealmPath, realmUrl) {
|
||||
if (!user.server) {
|
||||
throw new Error("Server for user must be specified");
|
||||
}
|
||||
|
||||
let parsedRealmUrl = url_parse(realmUrl);
|
||||
const url = auth_url(user.server);
|
||||
if (user.isAdminToken) {
|
||||
return refreshAdminToken(user, localRealmPath, realmUrl);
|
||||
}
|
||||
|
||||
const url = append_url(user.server, 'auth');
|
||||
const options = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
|
@ -91,26 +138,13 @@ function refreshAccessToken(user, localRealmPath, realmUrl) {
|
|||
// Look up a fresh instance of the user.
|
||||
// We do this because in React Native Remote Debugging
|
||||
// `Realm.clearTestState()` will have invalidated the user object
|
||||
let newUser = user.constructor.all[user.identity];
|
||||
const newUser = user.constructor.all[user.identity];
|
||||
if (!newUser) {
|
||||
return;
|
||||
}
|
||||
let session = newUser._sessionForOnDiskPath(localRealmPath);
|
||||
if (!session) {
|
||||
print_error(`Unhandled session token refresh error: could not look up session at path ${localRealmPath}`);
|
||||
}
|
||||
|
||||
const errorHandler = session.config.error;
|
||||
if (response.status != 200) {
|
||||
let error = new AuthError(json);
|
||||
if (errorHandler) {
|
||||
errorHandler(session, error);
|
||||
} else {
|
||||
print_error('Unhandled session token refresh error', error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (session.state === 'invalid') {
|
||||
const session = validateRefresh(newUser, localRealmPath, response, json);
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -119,6 +153,7 @@ function refreshAccessToken(user, localRealmPath, realmUrl) {
|
|||
parsedRealmUrl.set('pathname', tokenData.path);
|
||||
session._refreshAccessToken(json.access_token.token, parsedRealmUrl.href, tokenData.sync_label);
|
||||
|
||||
const errorHandler = session.config.error;
|
||||
if (errorHandler && errorHandler._notifyOnAccessTokenRefreshed) {
|
||||
errorHandler(session, errorHandler._notifyOnAccessTokenRefreshed)
|
||||
}
|
||||
|
@ -144,7 +179,7 @@ function refreshAccessToken(user, localRealmPath, realmUrl) {
|
|||
*/
|
||||
function _authenticate(userConstructor, server, json, callback) {
|
||||
json.app_id = '';
|
||||
const url = auth_url(server);
|
||||
const url = append_url(server, 'auth');
|
||||
const options = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(json),
|
||||
|
|
|
@ -69,12 +69,14 @@ public:
|
|||
static void get_identity(ContextType, ObjectType, ReturnValue &);
|
||||
static void get_token(ContextType, ObjectType, ReturnValue &);
|
||||
static void is_admin(ContextType, ObjectType, ReturnValue &);
|
||||
static void is_admin_token(ContextType, ObjectType, ReturnValue &);
|
||||
|
||||
PropertyMap<T> const properties = {
|
||||
{"server", {wrap<get_server>, nullptr}},
|
||||
{"identity", {wrap<get_identity>, nullptr}},
|
||||
{"token", {wrap<get_token>, nullptr}},
|
||||
{"isAdmin", {wrap<is_admin>, nullptr}},
|
||||
{"isAdminToken", {wrap<is_admin_token>, nullptr}},
|
||||
};
|
||||
|
||||
static void create_user(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||
|
@ -125,6 +127,11 @@ void UserClass<T>::is_admin(ContextType ctx, ObjectType object, ReturnValue &ret
|
|||
return_value.set(get_internal<T, UserClass<T>>(object)->get()->is_admin());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void UserClass<T>::is_admin_token(ContextType ctx, ObjectType object, ReturnValue &return_value) {
|
||||
return_value.set(get_internal<T, UserClass<T>>(object)->get()->token_type() == SyncUser::TokenType::Admin);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void UserClass<T>::create_user(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||
validate_argument_count(argc, 3, 5);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 21e671a155989f4e34e279fc8a7ace5817495de0
|
||||
Subproject commit 8517ee7f4378fe0f54945b3e4973766ff65e455d
|
Loading…
Reference in New Issue