diff --git a/back-end-cf/index.js b/back-end-cf/index.js index 0c9ed94d..accb45a9 100644 --- a/back-end-cf/index.js +++ b/back-end-cf/index.js @@ -35,14 +35,14 @@ const OAUTH = { async function handleRequest(request) { // Preflight - if(request.method === 'OPTIONS') { + if (request.method === 'OPTIONS') { return new Response(null, { - status: 204, + status: 204, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'Content-Type', 'Access-Control-Max-Age': '86400', - } + }, }); } @@ -72,16 +72,19 @@ async function handleRequest(request) { // Upload files if (requestUrl.searchParams.has('upload')) { - const allowUpload = (await downloadFile(`${requestPath}/.upload`)).status === 302; + const allowUpload = + (await downloadFile(`${requestPath}/.upload`)).status === 302; + await authenticate(requestPath, body.passwd); - const uploadAttack = + + if ( !allowUpload || body.files.some( (file) => file.remotePath.split('/').pop().toLowerCase() === PASSWD_FILENAME.toLowerCase() - ); - if (uploadAttack) { + ) + ) { throw new Error('access denied'); } @@ -170,12 +173,15 @@ async function fetchAccessToken() { } async function authenticate(path, passwd) { - const pwFileContent = await downloadFile(`${path}/${PASSWD_FILENAME}`, null, true) - .then(resp => resp.status === 404 ? '' : resp.text()); + const pwFileContent = await downloadFile( + `${path}/${PASSWD_FILENAME}`, + null, + true + ).then((resp) => (resp.status === 404 ? '' : resp.text())); if (pwFileContent) { if (passwd !== pwFileContent) { - throw new Error("wrong password"); + throw new Error('wrong password'); } } else if (path !== '/' && path.split('/').length <= PROTECTED_LAYERS) { return authenticate('/', passwd); @@ -186,7 +192,7 @@ async function fetchFiles(path, passwd) { const parent = path || '/'; try { await authenticate(path, passwd); - } catch(_) { + } catch (_) { return JSON.stringify({ parent, files: [], @@ -195,10 +201,11 @@ async function fetchFiles(path, passwd) { } if (path === '/') path = ''; - if (path || EXPOSE_PATH) path = ':' + encodeURIComponent(EXPOSE_PATH + path) + ':'; + if (path || EXPOSE_PATH) + path = ':' + encodeURIComponent(EXPOSE_PATH + path) + ':'; const accessToken = await fetchAccessToken(); - const expand = + const expand = '/children?select=name,size,parentReference,lastModifiedDateTime,@microsoft.graph.downloadUrl&$top=200'; const uri = OAUTH.apiUrl + path + expand; @@ -230,18 +237,20 @@ async function fetchFiles(path, passwd) { }); } -async function downloadFile(filePath, format, stream){ +async function downloadFile(filePath, format, stream) { const supportedFormats = ['glb', 'html', 'jpg', 'pdf']; if (format && !supportedFormats.includes(format.toLowerCase())) { throw new Error('unsupported target format'); } filePath = encodeURIComponent(`${EXPOSE_PATH}${filePath}`); - const uri = `${OAUTH.apiUrl}:${filePath}:/content` + (format ? `?format=${format}` : ''); + const uri = + `${OAUTH.apiUrl}:${filePath}:/content` + + (format ? `?format=${format}` : ''); const accessToken = await fetchAccessToken(); return cacheFetch(uri, { - redirect: stream ? 'follow': 'manual', + redirect: stream ? 'follow' : 'manual', headers: { Authorization: 'Bearer ' + accessToken, }, diff --git a/back-end-deployment-helper/src/App.js b/back-end-deployment-helper/src/App.js index cf24b331..76d9d467 100644 --- a/back-end-deployment-helper/src/App.js +++ b/back-end-deployment-helper/src/App.js @@ -6,7 +6,7 @@ import './App.css'; import { generateCode } from './util'; const defaultConfig = { - replayURL: 'http://localhost/onedrive-login', + replyURL: 'http://localhost/onedrive-login', publicParams: '&scope=offline_access%20User.Read%20Files.ReadWrite.All&response_type=code', version: { @@ -31,14 +31,13 @@ function App() { const antIcon = ; const [version, setVersion] = useState(); - const [replayURL, setReplayURL] = useState(); + const [replyURL, setreplyURL] = useState(); const [clientID, setClientID] = useState(); const [clientSecret, setClientSecret] = useState(); const [redirectURL, setRedirectURL] = useState(); const [passwordFilename, setPasswordFilename] = useState(); const [exposedPath, setExposedPath] = useState(); const [protectedLayers, setProtected] = useState(); - const [exposePw, setExposePw] = useState(); const [code, setCode] = useState(); const [error, setError] = useState(); const [loading, setLoading] = useState(); @@ -47,7 +46,7 @@ function App() { const changeVersion = (v) => { if (v === 'select') { setVersion(null); - setReplayURL(null); + setreplyURL(null); setClientID(null); setClientSecret(null); return; @@ -55,7 +54,7 @@ function App() { setRedirectURL(null); setVersion(v); const config = defaultConfig.version[v]; - setReplayURL(defaultConfig.replayURL); + setreplyURL(defaultConfig.replyURL); setClientID(config.clientID); setClientSecret(config.clientSecret); }; @@ -65,7 +64,7 @@ function App() { const config = defaultConfig.version[version]; window.open( `${config.api}/common/oauth2/v2.0/authorize?client_id=` + - `${clientID}${defaultConfig.publicParams}&redirect_uri=${replayURL}` + `${clientID}${defaultConfig.publicParams}&redirect_uri=${replyURL}` ); }; @@ -86,7 +85,7 @@ function App() { const urlencoded = new URLSearchParams(); urlencoded.append('client_id', clientID); - urlencoded.append('redirect_uri', replayURL); + urlencoded.append('redirect_uri', replyURL); urlencoded.append('client_secret', clientSecret); urlencoded.append('code', code); urlencoded.append('grant_type', 'authorization_code'); @@ -115,12 +114,11 @@ function App() { defaultConfig.version[version].restApi, clientID, clientSecret, - replayURL, + replyURL, data.refresh_token, exposedPath || '', passwordFilename || '.password', - protectedLayers || '-1', - exposePw || '' + protectedLayers || '-1' ) .then((code) => setCode(code)) .catch((err) => setError(err.message)); @@ -192,9 +190,9 @@ function App() {
setReplayURL(e.target.value)} + placeholder="replyURL(自定义 ID、SECRET 时,需要填写)" + value={replyURL} + onChange={(e) => setreplyURL(e.target.value)} />
@@ -207,30 +205,25 @@ function App() { /> -
+
setExposedPath(e.target.value)} /> +
+ +
setPasswordFilename(e.target.value)} /> -
- -
setProtected(e.target.value)} /> - setExposePw(e.target.value)} - />
diff --git a/back-end-deployment-helper/src/util.js b/back-end-deployment-helper/src/util.js index 2a04dd88..e181b68b 100644 --- a/back-end-deployment-helper/src/util.js +++ b/back-end-deployment-helper/src/util.js @@ -4,23 +4,21 @@ export const generateCode = async ( apiHost, clientId, clientSecret, - replayURL, + replyURL, refreshToken, exposePath, passwordFilename, - protectedLayers, - exposePw + protectedLayers ) => { const constants = `const EXPOSE_PATH = "${exposePath}"; const ONEDRIVE_REFRESHTOKEN = "${refreshToken}"; const PASSWD_FILENAME = "${passwordFilename}"; const PROTECTED_LAYERS = ${protectedLayers}; -const EXPOSE_PASSWD = "${exposePw}"; const clientId = "${clientId}"; const clientSecret = "${clientSecret}"; const loginHost = "${loginHost}"; const apiHost = "${apiHost}"; -const redirectUri = "${replayURL}" +const redirectUri = "${replyURL}" `;