You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Making oneDrive work on RN
This commit is contained in:
		| @@ -677,27 +677,28 @@ async function synchronizer(syncTarget) { | ||||
| 	let fileApi = null; | ||||
|  | ||||
| 	if (syncTarget == 'onedrive') { | ||||
| 		const CLIENT_ID = 'e09fc0de-c958-424f-83a2-e56a721d331b'; | ||||
| 		const CLIENT_SECRET = 'JA3cwsqSGHFtjMwd5XoF5L5'; | ||||
| 		let oneDriveApi = oneDriveApi.instance(); | ||||
| 		// const CLIENT_ID = 'e09fc0de-c958-424f-83a2-e56a721d331b'; | ||||
| 		// const CLIENT_SECRET = 'JA3cwsqSGHFtjMwd5XoF5L5'; | ||||
|  | ||||
| 		let driver = new FileApiDriverOneDrive(CLIENT_ID, CLIENT_SECRET); | ||||
| 		//let driver = new FileApiDriverOneDrive(CLIENT_ID, CLIENT_SECRET); | ||||
| 		let driver = new FileApiDriverOneDrive(oneDriveApi); | ||||
| 		let auth = Setting.value('sync.onedrive.auth'); | ||||
| 		 | ||||
| 		if (auth) { | ||||
| 			auth = JSON.parse(auth); | ||||
| 		} else { | ||||
| 			//auth = await driver.api().oauthDance(vorpal); | ||||
| 			const oneDriveApiUtils = new OneDriveApiNodeUtils(driver.api()); | ||||
| 			const oneDriveApiUtils = new OneDriveApiNodeUtils(oneDriveApi); | ||||
| 			auth = await oneDriveApiUtils.oauthDance(vorpal); | ||||
| 			Setting.setValue('sync.onedrive.auth', JSON.stringify(auth)); | ||||
| 		} | ||||
|  | ||||
| 		driver.api().setAuth(auth); | ||||
| 		driver.api().on('authRefreshed', (a) => { | ||||
| 		//oneDriveApi.setAuth(auth); | ||||
| 		oneDriveApi.on('authRefreshed', (a) => { | ||||
| 			Setting.setValue('sync.onedrive.auth', JSON.stringify(a)); | ||||
| 		}); | ||||
|  | ||||
| 		let appDir = await driver.api().appDirectory(); | ||||
| 		let appDir = await oneDriveApi.appDirectory(); | ||||
| 		logger.info('App dir: ' + appDir); | ||||
| 		fileApi = new FileApi(appDir, driver); | ||||
| 		fileApi.setLogger(logger); | ||||
|   | ||||
| @@ -53,35 +53,49 @@ class OneDriveApiNodeUtils { | ||||
|  | ||||
| 				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 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, | ||||
| 				}; | ||||
| 				// 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; | ||||
| 					} | ||||
| 				// fetch(this.api().tokenBaseUrl(), options).then((r) => { | ||||
|  | ||||
| 					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(); | ||||
| 					}); | ||||
| 				// this.api().execTokenRequest(query.code, 'http://localhost:' + port.toString()).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(); | ||||
| 				// 	}); | ||||
| 				// }); | ||||
|  | ||||
| 				this.api().execTokenRequest(query.code, 'http://localhost:' + port.toString()).then(() => { | ||||
| 					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(); | ||||
| 				}).catch((error) => { | ||||
| 					writeResponse(400, error.message); | ||||
| 					targetConsole.log(''); | ||||
| 					targetConsole.log(error.message); | ||||
| 					server.destroy(); | ||||
| 				}); | ||||
| 			}); | ||||
|  | ||||
|   | ||||
| @@ -41,6 +41,11 @@ class ScreenHeaderComponent extends Component { | ||||
| 	} | ||||
|  | ||||
| 	menu_synchronize() { | ||||
| 		this.props.dispatch({ | ||||
| 			type: 'Navigation/NAVIGATE', | ||||
| 			routeName: 'OneDriveLogin', | ||||
| 		}); | ||||
|  | ||||
| 		// const CLIENT_ID = 'e09fc0de-c958-424f-83a2-e56a721d331b'; | ||||
| 		// const CLIENT_SECRET = 'JA3cwsqSGHFtjMwd5XoF5L5'; | ||||
|  | ||||
|   | ||||
							
								
								
									
										90
									
								
								ReactNativeClient/lib/components/screens/onedrive-login.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								ReactNativeClient/lib/components/screens/onedrive-login.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| import React, { Component } from 'react'; | ||||
| import { View } from 'react-native'; | ||||
| import { WebView, Button } from 'react-native'; | ||||
| import { connect } from 'react-redux' | ||||
| import { Log } from 'lib/log.js' | ||||
| import { ScreenHeader } from 'lib/components/screen-header.js'; | ||||
| import { OneDriveApi } from 'lib/onedrive-api.js'; | ||||
| import { _ } from 'lib/locale.js'; | ||||
|  | ||||
| class OneDriveLoginScreenComponent extends React.Component { | ||||
| 	 | ||||
| 	static navigationOptions(options) { | ||||
| 		return { header: null }; | ||||
| 	} | ||||
|  | ||||
| 	constructor() { | ||||
| 		super(); | ||||
| 		this.state = { webviewUrl: '' }; | ||||
| 		this.authCode_ = null; | ||||
| 	} | ||||
|  | ||||
| 	componentWillMount() { | ||||
| 		this.setState({ | ||||
| 			webviewUrl: this.api().authCodeUrl(this.redirectUrl()), | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	api() { | ||||
| 		return OneDriveApi.instance(); | ||||
|  | ||||
| 	redirectUrl() { | ||||
| 		return 'https://login.microsoftonline.com/common/oauth2/nativeclient'; | ||||
| 	} | ||||
|  | ||||
| 	async webview_load(noIdeaWhatThisIs) { | ||||
| 		// This is deprecated according to the doc but since the non-deprecated property (source) | ||||
| 		// doesn't exist, use this for now. The whole component is completely undocumented | ||||
| 		// at the moment so it's likely to change. | ||||
| 		const url = noIdeaWhatThisIs.url; | ||||
|  | ||||
| 		console.info('URL: ' + url); | ||||
|  | ||||
| 		if (!this.authCode_) { | ||||
| 			if (url.indexOf(this.redirectUrl() + '?code=') === 0) { | ||||
| 				let code = url.split('?code='); | ||||
| 				this.authCode_ = code[1]; | ||||
|  | ||||
| 				await this.api().execTokenRequest(this.authCode_, this.redirectUrl(), true); | ||||
| 				Setting.setValue('sync.onedrive.auth', JSON.stringify(this.api().auth())); | ||||
| 				oneDriveApi.on('authRefreshed', (a) => { | ||||
| 					Setting.setValue('sync.onedrive.auth', JSON.stringify(a)); | ||||
| 				}); | ||||
|  | ||||
| 				let appDir = await this.api().appDirectory(); | ||||
|  | ||||
| 				Log.info('APP DIR: ' + appDir); | ||||
| 				// fileApi = new FileApi(appDir, driver); | ||||
| 				// fileApi.setLogger(logger); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	render() { | ||||
| 		const source = { | ||||
| 			uri: this.state.webviewUrl, | ||||
| 		} | ||||
|  | ||||
| 		// <Button title="Start" onPress={() => this.startButton_press()}></Button> | ||||
|  | ||||
| 		return ( | ||||
| 			<View style={{flex: 1}}> | ||||
| 				<ScreenHeader navState={this.props.navigation.state} /> | ||||
| 				<WebView | ||||
| 					source={source} | ||||
| 					style={{marginTop: 20}} | ||||
| 					onNavigationStateChange={(o) => { this.webview_load(o); }} | ||||
| 				/> | ||||
| 			</View> | ||||
| 		); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| const OneDriveLoginScreen = connect( | ||||
| 	(state) => { | ||||
| 		return {}; | ||||
| 	} | ||||
| )(OneDriveLoginScreenComponent) | ||||
|  | ||||
| export { OneDriveLoginScreen }; | ||||
| @@ -5,8 +5,10 @@ import { OneDriveApi } from 'lib/onedrive-api.js'; | ||||
|  | ||||
| class FileApiDriverOneDrive { | ||||
|  | ||||
| 	constructor(clientId, clientSecret) { | ||||
| 		this.api_ = new OneDriveApi(clientId, clientSecret); | ||||
| 	//constructor(clientId, clientSecret) { | ||||
| 	constructor(api) { | ||||
| 		this.api_ = api; | ||||
| 		//this.api_ = new OneDriveApi(clientId, clientSecret); | ||||
| 	} | ||||
|  | ||||
| 	api() { | ||||
|   | ||||
| @@ -12,6 +12,15 @@ class OneDriveApi { | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
| 	static instance() { | ||||
| 		if (this.instance_) return this.instance_; | ||||
|  | ||||
| 		const CLIENT_ID = 'e09fc0de-c958-424f-83a2-e56a721d331b'; | ||||
| 		const CLIENT_SECRET = 'JA3cwsqSGHFtjMwd5XoF5L5'; | ||||
| 		this.instance_ = new OneDriveApi(CLIENT_ID, CLIENT_SECRET); | ||||
| 		return this.instance_; | ||||
| 	} | ||||
|  | ||||
| 	dispatch(eventName, param) { | ||||
| 		let ls = this.listeners_[eventName]; | ||||
| 		for (let i = 0; i < ls.length; i++) { | ||||
| @@ -47,10 +56,6 @@ class OneDriveApi { | ||||
| 		return this.clientSecret_; | ||||
| 	} | ||||
|  | ||||
| 	// possibleOAuthDancePorts() { | ||||
| 	// 	return [1917, 9917, 8917]; | ||||
| 	// } | ||||
|  | ||||
| 	async appDirectory() { | ||||
| 		let r = await this.execJson('GET', '/drive/special/approot'); | ||||
| 		return r.parentReference.path + '/' + r.name; | ||||
| @@ -66,6 +71,34 @@ class OneDriveApi { | ||||
| 		return 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize?' + stringify(query); | ||||
| 	} | ||||
|  | ||||
| 	async execTokenRequest(code, redirectUri, isPublic = false) { | ||||
| 		let body = new shim.FormData(); | ||||
| 		body.append('client_id', this.clientId()); | ||||
| 		if (!isPublic) body.append('client_secret', this.clientSecret()); | ||||
| 		body.append('code', code); | ||||
| 		body.append('redirect_uri', redirectUri); | ||||
| 		body.append('grant_type', 'authorization_code'); | ||||
|  | ||||
| 		const r = await shim.fetch(this.tokenBaseUrl(), { | ||||
| 			method: 'POST', | ||||
| 			body: body, | ||||
| 		}) | ||||
|  | ||||
| 		if (!r.ok) { | ||||
| 			const text = await r.text(); | ||||
| 			throw new Error('Could not retrieve auth code: ' + r.status + ': ' + r.statusText + ': ' + text); | ||||
| 		} | ||||
|  | ||||
| 		try { | ||||
| 			const json = await r.json(); | ||||
| 			this.setAuth(json); | ||||
| 		} catch (error) { | ||||
| 			const text = await r.text(); | ||||
| 			error.message += ': ' + text; | ||||
| 			throw error; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	oneDriveErrorResponseToError(errorResponse) { | ||||
| 		if (!errorResponse) return new Error('Undefined error'); | ||||
|  | ||||
| @@ -181,90 +214,6 @@ class OneDriveApi { | ||||
| 		this.dispatch('authRefreshed', this.auth_); | ||||
| 	} | ||||
|  | ||||
| 	// async oauthDance(targetConsole = null) { | ||||
| 	// 	if (targetConsole === null) targetConsole = console; | ||||
|  | ||||
| 	// 	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; | ||||
| 	// 		} | ||||
| 	// 	} | ||||
|  | ||||
| 	// 	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); | ||||
|  | ||||
| 	// 	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 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, | ||||
| 	// 			}; | ||||
|  | ||||
| 	// 			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(); | ||||
| 	// 				}); | ||||
| 	// 			}); | ||||
| 	// 		}); | ||||
|  | ||||
| 	// 		server.on('close', () => { | ||||
| 	// 			if (errorMessage) { | ||||
| 	// 				reject(new Error(errorMessage)); | ||||
| 	// 			} else { | ||||
| 	// 				resolve(this.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 { OneDriveApi }; | ||||
| @@ -1,6 +1,7 @@ | ||||
| let shim = {}; | ||||
|  | ||||
| shim.fetch = typeof fetch !== 'undefined' ? fetch : null; | ||||
| shim.FormData = typeof FormData !== 'undefined' ? FormData : null; | ||||
|  | ||||
| if (!shim.fetch) { | ||||
| 	let moduleName = 'node-fetch'; | ||||
|   | ||||
| @@ -19,6 +19,7 @@ import { FolderScreen } from 'lib/components/screens/folder.js' | ||||
| import { FoldersScreen } from 'lib/components/screens/folders.js' | ||||
| import { LoginScreen } from 'lib/components/screens/login.js' | ||||
| import { LoadingScreen } from 'lib/components/screens/loading.js' | ||||
| import { OneDriveLoginScreen } from 'lib/components/screens/onedrive-login.js' | ||||
| import { Setting } from 'lib/models/setting.js' | ||||
| import { Synchronizer } from 'lib/synchronizer.js' | ||||
| import { MenuContext } from 'react-native-popup-menu'; | ||||
| @@ -184,6 +185,7 @@ const AppNavigator = StackNavigator({ | ||||
| 	Folders: { screen: FoldersScreen }, | ||||
| 	Login: { screen: LoginScreen }, | ||||
| 	Loading: { screen: LoadingScreen }, | ||||
| 	OneDriveLogin: { screen: OneDriveLoginScreen }, | ||||
| }); | ||||
|  | ||||
| class AppComponent extends React.Component { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user