mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-27 10:32:58 +02:00
Make fetch and FormData work in both RN and node
This commit is contained in:
parent
9e3a2a894e
commit
bdb250de8a
@ -7,6 +7,7 @@ import { FileApi } from 'lib/file-api.js';
|
||||
import { FileApiDriverOneDrive } from 'lib/file-api-driver-onedrive.js';
|
||||
import { FileApiDriverMemory } from 'lib/file-api-driver-memory.js';
|
||||
import { FileApiDriverLocal } from 'lib/file-api-driver-local.js';
|
||||
import { OneDriveApiNodeUtils } from './onedrive-api-node-utils.js';
|
||||
import { Database } from 'lib/database.js';
|
||||
import { DatabaseDriverNode } from 'lib/database-driver-node.js';
|
||||
import { BaseModel } from 'lib/base-model.js';
|
||||
@ -685,7 +686,9 @@ async function synchronizer(syncTarget) {
|
||||
if (auth) {
|
||||
auth = JSON.parse(auth);
|
||||
} else {
|
||||
auth = await driver.api().oauthDance(vorpal);
|
||||
//auth = await driver.api().oauthDance(vorpal);
|
||||
const oneDriveApiUtils = new OneDriveApiNodeUtils(driver.api());
|
||||
auth = await oneDriveApiUtils.oauthDance(vorpal);
|
||||
Setting.setValue('sync.onedrive.auth', JSON.stringify(auth));
|
||||
}
|
||||
|
||||
|
108
CliClient/app/onedrive-api-node-utils.js
Normal file
108
CliClient/app/onedrive-api-node-utils.js
Normal file
@ -0,0 +1,108 @@
|
||||
const fetch = require('node-fetch');
|
||||
const tcpPortUsed = require('tcp-port-used');
|
||||
const http = require("http");
|
||||
const urlParser = require("url");
|
||||
const FormData = require('form-data');
|
||||
const enableServerDestroy = require('server-destroy');
|
||||
|
||||
class OneDriveApiNodeUtils {
|
||||
|
||||
constructor(api) {
|
||||
this.api_ = api;
|
||||
}
|
||||
|
||||
api() {
|
||||
return this.api_;
|
||||
}
|
||||
|
||||
possibleOAuthDancePorts() {
|
||||
return [1917, 9917, 8917];
|
||||
}
|
||||
|
||||
async oauthDance(targetConsole = null) {
|
||||
if (targetConsole === null) targetConsole = console;
|
||||
|
||||
this.api().setAuth(null);
|
||||
|
||||
let ports = this.possibleOAuthDancePorts();
|
||||
let port = null;
|
||||
for (let i = 0; i < ports.length; i++) {
|
||||
let inUse = await tcpPortUsed.check(ports[i]);
|
||||
if (!inUse) {
|
||||
port = ports[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!port) throw new Error('All potential ports are in use - please report the issue at https://github.com/laurent22/joplin');
|
||||
|
||||
let authCodeUrl = this.api().authCodeUrl('http://localhost:' + port);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let server = http.createServer();
|
||||
let errorMessage = null;
|
||||
|
||||
server.on('request', (request, response) => {
|
||||
const query = urlParser.parse(request.url, true).query;
|
||||
|
||||
function writeResponse(code, message) {
|
||||
response.writeHead(code, {"Content-Type": "text/html"});
|
||||
response.write(message);
|
||||
response.end();
|
||||
}
|
||||
|
||||
if (!query.code) return writeResponse(400, '"code" query parameter is missing');
|
||||
|
||||
let body = new FormData();
|
||||
body.append('client_id', this.api().clientId());
|
||||
body.append('client_secret', this.api().clientSecret());
|
||||
body.append('code', query.code ? query.code : '');
|
||||
body.append('redirect_uri', 'http://localhost:' + port.toString());
|
||||
body.append('grant_type', 'authorization_code');
|
||||
|
||||
let options = {
|
||||
method: 'POST',
|
||||
body: body,
|
||||
};
|
||||
|
||||
fetch(this.api().tokenBaseUrl(), options).then((r) => {
|
||||
if (!r.ok) {
|
||||
errorMessage = 'Could not retrieve auth code: ' + r.status + ': ' + r.statusText;
|
||||
writeResponse(400, errorMessage);
|
||||
targetConsole.log('');
|
||||
targetConsole.log(errorMessage);
|
||||
server.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
return r.json().then((json) => {
|
||||
this.api().setAuth(json);
|
||||
writeResponse(200, 'The application has been authorised - you may now close this browser tab.');
|
||||
targetConsole.log('');
|
||||
targetConsole.log('The application has been successfully authorised.');
|
||||
server.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
server.on('close', () => {
|
||||
if (errorMessage) {
|
||||
reject(new Error(errorMessage));
|
||||
} else {
|
||||
resolve(this.api().auth());
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(port);
|
||||
|
||||
enableServerDestroy(server);
|
||||
|
||||
targetConsole.log('Please open this URL in your browser to authentify the application:');
|
||||
targetConsole.log('');
|
||||
targetConsole.log(authCodeUrl);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { OneDriveApiNodeUtils };
|
@ -5,6 +5,8 @@ import { Log } from 'lib/log.js';
|
||||
import { Menu, MenuOptions, MenuOption, MenuTrigger } from 'react-native-popup-menu';
|
||||
import { _ } from 'lib/locale.js';
|
||||
import { Setting } from 'lib/models/setting.js';
|
||||
import { FileApi } from 'lib/file-api.js';
|
||||
import { FileApiDriverOneDrive } from 'lib/file-api-driver-onedrive.js';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
divider: {
|
||||
@ -38,20 +40,20 @@ class ScreenHeaderComponent extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
menu_login() {
|
||||
this.props.dispatch({
|
||||
type: 'Navigation/NAVIGATE',
|
||||
routeName: 'Login',
|
||||
});
|
||||
}
|
||||
menu_synchronize() {
|
||||
// const CLIENT_ID = 'e09fc0de-c958-424f-83a2-e56a721d331b';
|
||||
// const CLIENT_SECRET = 'JA3cwsqSGHFtjMwd5XoF5L5';
|
||||
|
||||
menu_logout() {
|
||||
let user = { email: null, session: null };
|
||||
Setting.setObject('user', user);
|
||||
this.props.dispatch({
|
||||
type: 'USER_SET',
|
||||
user: user,
|
||||
});
|
||||
// let driver = new FileApiDriverOneDrive(CLIENT_ID, CLIENT_SECRET);
|
||||
// let auth = Setting.value('sync.onedrive.auth');
|
||||
|
||||
// if (auth) {
|
||||
// auth = JSON.parse(auth);
|
||||
// } else {
|
||||
// driver.api().oauthDance(vorpal);
|
||||
// //auth = driver.api().oauthDance(vorpal);
|
||||
// //Setting.setValue('sync.onedrive.auth', JSON.stringify(auth));
|
||||
// }
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -69,17 +71,10 @@ class ScreenHeaderComponent extends Component {
|
||||
menuOptionComponents.push(<View key={'menuOption_' + key++} style={styles.divider}/>);
|
||||
}
|
||||
|
||||
if (this.props.user && this.props.user.session) {
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={() => this.menu_logout()} key={'menuOption_' + key++}>
|
||||
<Text>{_('Logout')}</Text>
|
||||
</MenuOption>);
|
||||
} else {
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={() => this.menu_login()} key={'menuOption_' + key++}>
|
||||
<Text>{_('Login')}</Text>
|
||||
</MenuOption>);
|
||||
}
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={() => this.menu_synchronize()} key={'menuOption_' + key++}>
|
||||
<Text>{_('Synchronize')}</Text>
|
||||
</MenuOption>);
|
||||
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={1} key={'menuOption_' + key++}>
|
||||
|
@ -1,9 +1,4 @@
|
||||
const fetch = require('node-fetch');
|
||||
const tcpPortUsed = require('tcp-port-used');
|
||||
const http = require("http");
|
||||
const urlParser = require("url");
|
||||
const FormData = require('form-data');
|
||||
const enableServerDestroy = require('server-destroy');
|
||||
import { shim } from 'lib/shim.js';
|
||||
import { stringify } from 'query-string';
|
||||
|
||||
class OneDriveApi {
|
||||
@ -32,6 +27,10 @@ class OneDriveApi {
|
||||
return 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
|
||||
}
|
||||
|
||||
auth() {
|
||||
return this.auth_;
|
||||
}
|
||||
|
||||
setAuth(auth) {
|
||||
this.auth_ = auth;
|
||||
}
|
||||
@ -48,9 +47,9 @@ class OneDriveApi {
|
||||
return this.clientSecret_;
|
||||
}
|
||||
|
||||
possibleOAuthDancePorts() {
|
||||
return [1917, 9917, 8917];
|
||||
}
|
||||
// possibleOAuthDancePorts() {
|
||||
// return [1917, 9917, 8917];
|
||||
// }
|
||||
|
||||
async appDirectory() {
|
||||
let r = await this.execJson('GET', '/drive/special/approot');
|
||||
@ -122,7 +121,7 @@ class OneDriveApi {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
options.headers['Authorization'] = 'bearer ' + this.token();
|
||||
|
||||
let response = await fetch(url, options);
|
||||
let response = await shim.fetch(url, options);
|
||||
if (!response.ok) {
|
||||
let errorResponse = await response.json();
|
||||
let error = this.oneDriveErrorResponseToError(errorResponse);
|
||||
@ -157,7 +156,7 @@ class OneDriveApi {
|
||||
async refreshAccessToken() {
|
||||
if (!this.auth_) throw new Error('Cannot refresh token: authentication data is missing');
|
||||
|
||||
let body = new FormData();
|
||||
let body = new shim.FormData();
|
||||
body.append('client_id', this.clientId());
|
||||
body.append('client_secret', this.clientSecret());
|
||||
body.append('refresh_token', this.auth_.refresh_token);
|
||||
@ -171,7 +170,7 @@ class OneDriveApi {
|
||||
|
||||
this.auth_ = null;
|
||||
|
||||
let response = await fetch(this.tokenBaseUrl(), options);
|
||||
let response = await shim.fetch(this.tokenBaseUrl(), options);
|
||||
if (!response.ok) {
|
||||
let msg = await response.text();
|
||||
throw new Error(msg);
|
||||
@ -182,89 +181,89 @@ class OneDriveApi {
|
||||
this.dispatch('authRefreshed', this.auth_);
|
||||
}
|
||||
|
||||
async oauthDance(targetConsole = null) {
|
||||
if (targetConsole === null) targetConsole = console;
|
||||
// async oauthDance(targetConsole = null) {
|
||||
// if (targetConsole === null) targetConsole = console;
|
||||
|
||||
this.auth_ = null;
|
||||
// this.auth_ = null;
|
||||
|
||||
let ports = this.possibleOAuthDancePorts();
|
||||
let port = null;
|
||||
for (let i = 0; i < ports.length; i++) {
|
||||
let inUse = await tcpPortUsed.check(ports[i]);
|
||||
if (!inUse) {
|
||||
port = ports[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// let ports = this.possibleOAuthDancePorts();
|
||||
// let port = null;
|
||||
// for (let i = 0; i < ports.length; i++) {
|
||||
// let inUse = await tcpPortUsed.check(ports[i]);
|
||||
// if (!inUse) {
|
||||
// port = ports[i];
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!port) throw new Error('All potential ports are in use - please report the issue at https://github.com/laurent22/joplin');
|
||||
// if (!port) throw new Error('All potential ports are in use - please report the issue at https://github.com/laurent22/joplin');
|
||||
|
||||
let authCodeUrl = this.authCodeUrl('http://localhost:' + port);
|
||||
// let authCodeUrl = this.authCodeUrl('http://localhost:' + port);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let server = http.createServer();
|
||||
let errorMessage = null;
|
||||
// return new Promise((resolve, reject) => {
|
||||
// let server = http.createServer();
|
||||
// let errorMessage = null;
|
||||
|
||||
server.on('request', (request, response) => {
|
||||
const query = urlParser.parse(request.url, true).query;
|
||||
// server.on('request', (request, response) => {
|
||||
// const query = urlParser.parse(request.url, true).query;
|
||||
|
||||
function writeResponse(code, message) {
|
||||
response.writeHead(code, {"Content-Type": "text/html"});
|
||||
response.write(message);
|
||||
response.end();
|
||||
}
|
||||
// function writeResponse(code, message) {
|
||||
// response.writeHead(code, {"Content-Type": "text/html"});
|
||||
// response.write(message);
|
||||
// response.end();
|
||||
// }
|
||||
|
||||
if (!query.code) return writeResponse(400, '"code" query parameter is missing');
|
||||
// if (!query.code) return writeResponse(400, '"code" query parameter is missing');
|
||||
|
||||
let body = new FormData();
|
||||
body.append('client_id', this.clientId());
|
||||
body.append('client_secret', this.clientSecret());
|
||||
body.append('code', query.code ? query.code : '');
|
||||
body.append('redirect_uri', 'http://localhost:' + port.toString());
|
||||
body.append('grant_type', 'authorization_code');
|
||||
// let body = new shim.FormData();
|
||||
// body.append('client_id', this.clientId());
|
||||
// body.append('client_secret', this.clientSecret());
|
||||
// body.append('code', query.code ? query.code : '');
|
||||
// body.append('redirect_uri', 'http://localhost:' + port.toString());
|
||||
// body.append('grant_type', 'authorization_code');
|
||||
|
||||
let options = {
|
||||
method: 'POST',
|
||||
body: body,
|
||||
};
|
||||
// let options = {
|
||||
// method: 'POST',
|
||||
// body: body,
|
||||
// };
|
||||
|
||||
fetch(this.tokenBaseUrl(), options).then((r) => {
|
||||
if (!r.ok) {
|
||||
errorMessage = 'Could not retrieve auth code: ' + r.status + ': ' + r.statusText;
|
||||
writeResponse(400, errorMessage);
|
||||
targetConsole.log('');
|
||||
targetConsole.log(errorMessage);
|
||||
server.destroy();
|
||||
return;
|
||||
}
|
||||
// fetch(this.tokenBaseUrl(), options).then((r) => {
|
||||
// if (!r.ok) {
|
||||
// errorMessage = 'Could not retrieve auth code: ' + r.status + ': ' + r.statusText;
|
||||
// writeResponse(400, errorMessage);
|
||||
// targetConsole.log('');
|
||||
// targetConsole.log(errorMessage);
|
||||
// server.destroy();
|
||||
// return;
|
||||
// }
|
||||
|
||||
return r.json().then((json) => {
|
||||
this.auth_ = json;
|
||||
writeResponse(200, 'The application has been authorised - you may now close this browser tab.');
|
||||
targetConsole.log('');
|
||||
targetConsole.log('The application has been successfully authorised.');
|
||||
server.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
// return r.json().then((json) => {
|
||||
// this.auth_ = json;
|
||||
// writeResponse(200, 'The application has been authorised - you may now close this browser tab.');
|
||||
// targetConsole.log('');
|
||||
// targetConsole.log('The application has been successfully authorised.');
|
||||
// server.destroy();
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
server.on('close', () => {
|
||||
if (errorMessage) {
|
||||
reject(new Error(errorMessage));
|
||||
} else {
|
||||
resolve(this.auth_);
|
||||
}
|
||||
});
|
||||
// server.on('close', () => {
|
||||
// if (errorMessage) {
|
||||
// reject(new Error(errorMessage));
|
||||
// } else {
|
||||
// resolve(this.auth_);
|
||||
// }
|
||||
// });
|
||||
|
||||
server.listen(port);
|
||||
// server.listen(port);
|
||||
|
||||
enableServerDestroy(server);
|
||||
// enableServerDestroy(server);
|
||||
|
||||
targetConsole.log('Please open this URL in your browser to authentify the application:');
|
||||
targetConsole.log('');
|
||||
targetConsole.log(authCodeUrl);
|
||||
});
|
||||
}
|
||||
// targetConsole.log('Please open this URL in your browser to authentify the application:');
|
||||
// targetConsole.log('');
|
||||
// targetConsole.log(authCodeUrl);
|
||||
// });
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
15
ReactNativeClient/lib/shim.js
Normal file
15
ReactNativeClient/lib/shim.js
Normal file
@ -0,0 +1,15 @@
|
||||
let shim = {};
|
||||
|
||||
shim.fetch = typeof fetch !== 'undefined' ? fetch : null;
|
||||
|
||||
if (!shim.fetch) {
|
||||
let moduleName = 'node-fetch';
|
||||
shim.fetch = require(moduleName);
|
||||
}
|
||||
|
||||
if (!shim.FormData) {
|
||||
let moduleName = 'form-data';
|
||||
shim.FormData = require(moduleName);
|
||||
}
|
||||
|
||||
export { shim };
|
@ -10,7 +10,6 @@
|
||||
"dropbox": "^2.5.4",
|
||||
"form-data": "^2.1.4",
|
||||
"moment": "^2.18.1",
|
||||
"node-fetch": "^1.7.1",
|
||||
"react": "16.0.0-alpha.6",
|
||||
"react-native": "0.44.0",
|
||||
"react-native-action-button": "^2.6.9",
|
||||
|
Loading…
Reference in New Issue
Block a user