const cookieParser = require('cookie-parser'); const cors = require("cors"); const fs = require("fs"); const globalPath = require("path"); const express = require("express"); const axios = require("axios"); // const SERVER_PORT = process.env.port || process.env.PORT || 53000; const SERVER_PORT = process.env.port || process.env.PORT || 53000; // const authProvider = require('./auth/AuthProvider'); const {getFetch, updateFetch} = require('./fetch'); const bodyParser = require('body-parser'); const https = require('https'); const JSZIP = require('jszip'); require('dotenv').config({ path: './env/.env.local' }); const session = require('express-session'); const multer = require('multer'); const XLSX = require('xlsx'); const pptxgen = require('pptxgenjs'); const msal = require('@azure/msal-node'); const FormData = require("form-data"); const {pool, sql} = require('./config/sql.js'); const { v4: uuidv4 } = require('uuid'); const {init} = require('./ext.js'); let POSSIBLE_EXT; const apiUrl = 'http://192.168.20.99:5050'; const createErrors = require('http-errors'); const gateWayKey = process.env.GATE_WAY_KEY; const msalConfig = { auth: { clientId: process.env.TEAMS_APP_ID, authority: "https://login.microsoftonline.com/"+process.env.TEAMS_APP_TENANT_ID, clientSecret: process.env.TEAMS_APP_SECRET, knownAuthorities: [], }, cache: { // your implementation of caching }, system: { loggerOptions: { /** logging related options */ } } } const cca = new msal.ConfidentialClientApplication(msalConfig); const {Document, Packer, Paragraph, TextRun} = require('docx'); const messages = require('dote/src/messages.js'); const { rejects } = require('assert'); let WebSocketServer = require('websocket').server; // const redirectUri = 'https://localhost:53000/redirect'; const redirectUri = 'https://localhost:53000/redirect'; const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploads/') }, filename: function (req, file, cb) { cb(null, file.originalname) // 원래 파일이름으로 저장 } }) const upload = multer(storage); const serverApp = express(); const endPoint = process.env.GRAPH_API_ENDPOINT + 'v1.0'; serverApp.use(session({ secret: process.env.EXPRESS_SESSION_SECRET, resave: false, saveUninitialized: true, cookie: { httpOnly: true, secure: true, // set this to true on production sameSite: 'none', maxAge: 60 * 60 * 24 * 1000 } })); serverApp.set(express.json()); serverApp.use(cookieParser()); serverApp.use(express.urlencoded({ extended: false })); serverApp.use("/static", express.static(globalPath.join(__dirname, 'static'))); const options = { key: process.env.SSL_KEY_FILE ? fs.readFileSync(process.env.SSL_KEY_FILE) : undefined, cert: process.env.SSL_CRT_FILE ? fs.readFileSync(process.env.SSL_CRT_FILE) : undefined, }; const server = https.createServer(options, serverApp); let wsServer = new WebSocketServer({ httpServer: server, ssl : true, key : process.env.SSL_KEY_FILE ? fs.readFileSync(process.env.SSL_KEY_FILE) : undefined, cert: process.env.SSL_CRT_FILE ? fs.readFileSync(process.env.SSL_CRT_FILE) : undefined, }); wsServer.on('request', function(req) { var connection = req.accept(); connection.on('message', function(message) { if (message && message.type === 'utf8') { const { value } = JSON.parse(message.utf8Data); if (value) { try { getPercentageComplete(value, connection); } catch (error) { // console.log(error); console.log(error.message); console.log(error.name); console.log(error.errors); connection.sendUTF(error); // return res.json(error); } } } }) }); async function getPercentageComplete(url, connection) { const result = await axios.get(url); if (result && result.data && result.data.percentageComplete >= 0) { const percent = result.data.percentageComplete; // console.log(result.data); connection.sendUTF(Number(percent.toFixed(2))); if (result.data.percentageComplete !== 100) { setTimeout(()=>getPercentageComplete(url, connection), 1000); } } } const corsOption = { origin: "*", } serverApp.use(cors(corsOption)); serverApp.use(bodyParser.json()); serverApp.get("/tab", // isAuthenticated, async function (req, res, next) { POSSIBLE_EXT = await init(); res.sendFile(globalPath.join(__dirname, "/views/hello.html"), // { idTokenClaims: req.session.account.idTokenClaims } ); } ); serverApp.post("/getProfileOnBehalfOf", async (req, res, next) => { result = await cca.acquireTokenOnBehalfOf({ oboAssertion: req.body.token, scopes: [".default"] }); req.session.tokenCache = result.tokenCache; req.session.accessToken = result.accessToken; req.session.idToken = result.idToken; req.session.account = result.account; req.session.auth = result; return res.send(result); }) // function isAuthenticated(req, res, next) { // if (!req.session.isAuthenticated) { // return res.redirect('/auth/signin'); // redirect to sign-in route // } // next(); // }; // function isAccessToken(req, res, next) { // if (!req.session.accessToken) { // return authProvider.acquireToken({ // scopes: ['.default'], // redirectUri: redirectUri, // successRedirect: '/api-redirect' // })(req, res, next); // } // next(); // } // serverApp.get("/auth/signin", authProvider.login({ // scopes: ['.default'], // redirectUri: redirectUri, // successRedirect: '/tab' // })) // serverApp.post("/redirect", authProvider.handleRedirect()); serverApp.post("/redirect", (req, res, next)=>{ console.log(req); }); serverApp.get("/redirect", (req, res, next)=>{ console.log(req); }); serverApp.post("/api-get", // isAuthenticated, // isAccessToken, async (req, res, next) => { const uri = req.body.api_uri || req.session.apiUri; let param = {}; if (req.session.param) { param = req.session.param; } try { const graphResponse = await getFetch(endPoint + uri, req.session.accessToken, param); res.json(graphResponse); } catch (error) { next(error); } }); serverApp.get("/api-redirect", // isAuthenticated, async function (req, res, next) { const uri = req.session.apiUri; let param = {}; if (req.session.param) { param = req.session.param; } try { const graphResponse = await getFetch(endPoint + uri, req.session.accessToken, param); res.json(graphResponse); } catch (error) { next(error); } }) serverApp.get("/post-redirect", // isAuthenticated, async function (req, res, next) { const uri = req.session.apiUri; let param = {}; if (req.session.param) { param = req.session.param; } try { const graphResponse = await updateFetch(endPoint + uri, req.session.accessToken, param); res.json(graphResponse); } catch (error) { next(error); } } ) // serverApp.post("/api-update", authProvider.acquireToken({ // scopes: [], // redirectUri: redirectUri, // successRedirect: '/post-redirect' // })); // serverApp.post("/api-post", authProvider.acquireToken({ // scopes: ['.default'], // redirectUri: redirectUri, // successRedirect: '/post-redirect' // })); // serverApp.post("/getGroupList", authProvider.acquireToken({ // scopes: ['.default'], // redirectUri: redirectUri, // successRedirect: '/group-redirect' // })); serverApp.post("/getGroupList", async function (req, res, next) { try { // throw new Error('Error'); // const oneDrive = await getFetch(endPoint + "/me/drive/root", req.session.accessToken); // const sharePointIds = await getFetch(endPoint + "/me/drive/SharePointIds", req.session.accessToken); // // const publicTeam = await getFetch(endPoint + "/groups?$filter=groupTypes/any(c:c+eq+'Unified')", req.session.accessToken); // const graphResponse = await getFetch(endPoint + "/me/joinedTeams", req.session.accessToken); // const sites = await getFetch(endPoint + "/sites/root", req.session.accessToken); // const sitesSharePoint = await getFetch(endPoint + "/sites/root/SharePointIds", req.session.accessToken); const options = getOptions(req.session.accessToken); const uriArr = [ axios.get(endPoint + "/me/drive/root", options), axios.get(endPoint + "/me/drive/SharePointIds", options), axios.get(endPoint + "/me/joinedTeams", options), axios.get(endPoint + "/sites/root", options), axios.get(endPoint + "/sites/root/SharePointIds", options), ] const result = await Promise.all(uriArr); const oneDrive = result[0].data; const sharePointIds = result[1].data; const graphResponse = result[2].data; const sites = result[3].data; const sitesSharePoint = result[4].data; const teams = graphResponse.value; oneDrive.sharePoint = sharePointIds; sites.sharePoint = sitesSharePoint; const resultObj = { oneDrive : { teams: oneDrive, }, joinedTeams : { teams : teams, // teams : public, items : {}, }, sites : { teams : sites, }, } if (teams && teams.length) { // if (public && public.length) { // const options = { // responseType: 'arraybuffer', // headers: { // Authorization: `Bearer ${req.session.accessToken}`, // ConsistencyLevel: 'eventual', // withCredentials:true, // }, // }; for (let team of teams) { // for (let team of public) { const item = await getFetch(endPoint + "/groups/"+team.id+"/drive/items/root/children", req.session.accessToken); const sharePoint = await getFetch(endPoint + "/groups/"+team.id+"/drive/SharePointIds", req.session.accessToken); // const image = await axios.get(endPoint + "/groups/" + team.id + "/photo/$value", options); // if (image && image.data) { // team.image = image.data; // } if (sharePoint) { team.sharePoint = sharePoint; } if (item && item.value) { resultObj.joinedTeams.items[team.id] = item.value; } } } res.json(resultObj); } catch (error) { next(error); } }); function isAccessTokens(req, res, next) { if (!req.session.accessToken) { return authProvider.acquireToken({ scopes: ['.default'], redirectUri: redirectUri, successRedirect: req.url })(req, res, next); } next(); } serverApp.post('/api/makeFolder', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ const options = getOptions(req.session.accessToken); const {siteId, path, name} = req.body; const resultObj = {message:"", success: 'F'}; const param ={ name: name, folder: { }, '@microsoft.graph.conflictBehavior': 'rename' } try{ const sitesInfo = await axios.get(endPoint + "/sites/"+ siteId + path, options); if (sitesInfo.data && sitesInfo.data.id) { const itemId = sitesInfo.data.id; const result = await axios.post(endPoint + "/sites/"+ siteId +"/drive/items/" + itemId +"/children",param, options); if (result.data) { resultObj.message = "폴더가 생성되었습니다.
폴더명 : "+ name; resultObj.success = 'S'; } else { resultObj.message = "폴더가 생성되지 않았습니다."; } } else { resultObj.message = "생성할 폴더 경로를 찾을 수 없습니다."; } } catch(error) { resultObj.message = "폴더 생성 중 오류가 발생하였습니다.
" + getErrorMessage(error); } res.json(resultObj); }); function getErrorMessage(error) { let errorText = ""; if (error.response && error.response.status && error.response.statusText && error.response.data && error.response.data.error) { // console.log(error.response); console.log('=============================== Axios Error ===============================') console.log('발생시각 : '+ new Date().toLocaleString()); console.log(error.response); console.log(error.response.data.error); errorText = `status : ${error.response.status} - ${error.response.statusText}
message : ${error.response.data.error.message}`; } else { console.log('================================ Error =====================================') console.log('발생시각:'+ new Date().toLocaleString()); console.log('에러 : '+ error); errorText = error; } return errorText; } serverApp.post('/api/makeWord', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ const options = getOptions(req.session.accessToken); const {siteId, path, name} = req.body; const doc = new Document({ sections : [ { properties: {}, children : [ new Paragraph({ children: [ ] }) ] } ] }); Packer.toBuffer(doc).then(async (buffer)=>{ const resultObj = {message:"", success: 'F'};; try{ const base64EncodeData = Buffer.from(buffer).toString('base64'); const labelData = await setLabel(gateWayKey, req.session.account.idTokenClaims.email, name, "878173ae-cc36-4881-af57-604af868314c", base64EncodeData, "Make New Word 문서"); if (labelData.success === 'F') { return res.json(labelData); } const sitesInfo = await axios.get(endPoint + "/sites/"+ siteId + path, options); if (sitesInfo.data && sitesInfo.data.id) { const itemId = sitesInfo.data.id; const result = await axios.put(endPoint + "/sites/"+ siteId +"/drive/items/"+itemId+':/'+name+':/content', labelData.data, options); if (result.data) { resultObj.message = "요청하신 Word 파일이 생성되었습니다.
파일명 : "+ name; resultObj.success = 'S'; } else { resultObj.message = "요청하신 Word 파일이 생성되지 않았습니다."; } } else { resultObj.message = "생성할 폴더 경로를 찾을 수 없습니다."; } } catch(error) { resultObj.message = "요청하신 Word 파일 생성 중 오류가 발생하였습니다.
" + getErrorMessage(error); } res.send(resultObj); }); }) serverApp.post('/api/makeExcel', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ const options = getOptions(req.session.accessToken); const {siteId, path, name} = req.body; const wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet([]), 'Sheet1'); var wbout = XLSX.write(wb, {bookType:'xlsx', type: 'buffer'}); const base64EncodeData = Buffer.from(wbout).toString('base64'); const resultObj = {message:'', success: 'F'}; try{ const labelData = await setLabel(gateWayKey, req.session.account.idTokenClaims.email, name, "878173ae-cc36-4881-af57-604af868314c", base64EncodeData, "Make New Excel 통합 문서"); if (labelData.success === 'F') { return res.json(labelData); } const parentData = await axios.get(endPoint + "/sites/"+ siteId +path, options); if (parentData.data) { const result = await axios.put(endPoint + "/sites/"+ siteId +"/drive/items/"+parentData.data.id+':/'+name+':/content', labelData.data, options); if (result.data) { resultObj.message ='요청하신 Excel 파일이 생성 되었습니다.'; resultObj.success = 'S'; } else{ resultObj.message = '요청하신 Excel 파일이 생성 되지 않았습니다.'; } } } catch(error) { resultObj.message = "요청하신 Excel 파일 생성 중 오류가 발생하였습니다.
" + getErrorMessage(error); } res.json(resultObj); }) async function setLabelFiles(param, headers, lengthSync, apiKey, email) { console.log('======================setLabelFiles=====================================') // const param = { // apiKey: apiKey, // email: email, // file : files, // dispFileName: dispFileName, // aipGuid: aipGuid, // fileData: fileData, // comment: comment, // } const resultObj = { message : null, success : 'F', data : null, } const errorMessage = '레이블 적용 중 오류가 발생했습니다.
에러 : '; try { // const result = await axios.post(apiUrl + '/api/v1/stream/set-label', param); // console.log('실행') // console.log(param); const result = await axios.post(apiUrl + '/api/v1/file/encrypt', param, { headers : { ...headers, "Content-Length" : lengthSync, } }); // console.log(result.data); if (result && result.data) { if (result.data.statusCode === 200 && !result.data.result.errorCode) { // resultObj.data = Buffer.from(result.data.result.fileData, "base64"); // console.log(param.get('apiKey')); // console.log(param.get('email')); const infoParam = { apiKey: apiKey, email: email, dispFileName: result.data.result.dispFileName, realFileName: result.data.result.outputFileName, } // console.log(infoParam); const infoData = await axios.post(apiUrl + '/api/v1/file/info', infoParam); // console.log('=================infoData ========================'); // console.log(infoData.data); resultObj.data = result.data.result; resultObj.success = 'S'; } else { resultObj.message = errorMessage + result.data.result.errorMessage; } } else { resultObj.message = errorMessage + '수신 데이터 없음'; } } catch (error) { console.log(error); resultObj.message = errorMessage + JSON.stringify(error); } return resultObj; } async function setLabel(apiKey, email, dispFileName, aipGuid, fileData, comment) { const param = { apiKey: apiKey, email: email, dispFileName: dispFileName, aipGuid: aipGuid, fileData: fileData, comment: comment, } const resultObj = { message : null, success : 'F', data : null, } const errorMessage = '레이블 적용 중 오류가 발생했습니다.
에러 : '; try { const result = await axios.post(apiUrl + '/api/v1/stream/set-label', param); if (result && result.data) { if (result.data.statusCode === 200 && !result.data.result.errorCode && result.data.result.fileData) { resultObj.data = Buffer.from(result.data.result.fileData, "base64"); resultObj.success = 'S'; } else { resultObj.message = errorMessage + result.data.result.errorMessage; } } else { resultObj.message = errorMessage + '수신 데이터 없음'; } } catch (error) { resultObj.message = errorMessage + JSON.stringify(error); } return resultObj; } serverApp.post('/api/makePptx', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ const options = getOptions(req.session.accessToken); const {siteId, path, name} = req.body; const pres = new pptxgen(); pres.addSlide(); const resultObj = {message:'', success: 'F'}; pres.stream().then(async (data)=>{ try{ const base64EncodeData = Buffer.from(data).toString('base64'); const labelData = await setLabel(gateWayKey, req.session.account.idTokenClaims.email, name, "878173ae-cc36-4881-af57-604af868314c", base64EncodeData, "Make New PowerPoint 프레젠테이션"); if (labelData.success === 'F') { return res.json(labelData); } const parentData = await axios.get(endPoint + "/sites/"+ siteId +path, options); if (parentData.data) { const result = await axios.put(endPoint + "/sites/"+ siteId +"/drive/items/"+parentData.data.id+':/'+name+':/content', labelData.data, options); if (result.data) { resultObj.message ='요청하신 PowerPoint 프레젠테이션 파일이 생성 되었습니다.'; resultObj.success = 'S'; } else{ resultObj.message = '요청하신 PowerPoint 프레젠테이션 파일이 생성 되지 않았습니다.'; } } } catch(error) { resultObj.message = "요청하신 PowerPoint 프레젠테이션 파일 생성 중 오류가 발생하였습니다.
" + getErrorMessage(error); } res.json(resultObj); }) }) serverApp.post('/api/check-name', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ const options = getOptions(req.session.accessToken); const {siteId, path, name} = req.body; try{ const sitesInfo = await axios.get(endPoint + "/sites/"+ siteId + path, options); if (sitesInfo.data) { const itemId = sitesInfo.data.id; const result = await axios.get(endPoint + "/sites/"+ siteId +"/drive/items/" + itemId +"/children", options); if (result && result.data && result.data.value) { let idx = result.data.value.findIndex(obj=>obj.name === name); // console.log(name); // console.log(idx); // console.log((idx > -1)); // console.log(result.data.value); res.json({hasName: (idx > -1)}); } } } catch(error) { if (error.response) { console.log("error.response", error.response); const statusCode = err.response.status; // 400 const statusText = err.response.statusText; // Bad Request const message = err.response.data.message[0]; // id should not be empty console.log(`${statusCode} - ${statusText} - ${message}`); res.json(error.response); } else { console.log(error); res.json(error); } } }); async function uploadDrive(options, folder, siteId, path) { const startTime = new Date(); const resultObj = { success : 'S', message : '', } if (!Array.isArray(folder)) { folder = [folder]; } for (let item of folder) { const fileInfo = JSON.parse(item); const param = { name: fileInfo.name, folder: {}, // '@microsoft.graph.conflictBehavior': 'rename' }; let folderPath = ''; if (fileInfo.path) { folderPath = fileInfo.path; if (!path.includes(':')) { folderPath = ":" + folderPath; } } let uri = endPoint + "/sites/"+ siteId + path + folderPath; const result = await new Promise (async (resolve, reject)=>{ axios.get(uri, options).then((sitesInfo)=>{ resolve(sitesInfo.data); }) .catch((error)=>{ reject(error); }); }) .then(async (result)=>{ return await new Promise(async (resolve, reject)=>{ axios.post(endPoint + "/sites/"+ siteId +"/drive/items/" + result.id +"/children", param, options) .then((uploadFolder)=>{ resolve(uploadFolder.data); }) .catch((error)=>{ reject(error); }); }); }) .catch((error)=>{ return {success:'F', message: '요청하신 파일 업로드 중 오류가 발생하였습니다.
' + getErrorMessage(error)}; }); if (result.success === 'F') { return result; } } const makeFolderTime = new Date(); console.log('폴더 시작 시간 :', startTime.toLocaleString(), ', 폴더 종료 시간 :', makeFolderTime.toLocaleString(), ', 소요 시간 :', timeCheck(startTime, makeFolderTime)); return resultObj; } serverApp.post('/api/upload', upload.array('file'), async (req, res, next)=>{ const startTime = new Date(); const files = req.files; let {siteId, path, folder, file_path} = req.body; if (siteId && path) { const options = getOptions(req.session.accessToken); if (folder){ const uploadDriveResult = await uploadDrive(options, folder, siteId, path); if (uploadDriveResult.success === 'F') { return res.json(uploadDriveResult); } } let fileWriteTime = new Date(); if (files && files.length > 0) { const promiseArray = []; const labelPromiseArray = []; // const fileWriteArray = []; const possibleExt = POSSIBLE_EXT; const {supported_file_ext, protected_file_ext} = possibleExt; let supportedArr = []; // let protectedArr = []; // let protectedMap = new Map(); if (supported_file_ext && protected_file_ext) { supportedArr = supported_file_ext.split(';'); // protectedArr = protected_file_ext.split(';'); if (!supportedArr[supportedArr.length - 1]) { supportedArr.splice(supportedArr.length - 1); } // if (!protectedArr[protectedArr.length - 1]) { // protectedArr.splice(protectedArr.length - 1); // } // if (protectedArr.length > 0) { // for (let array of protectedArr) { // array = array.split('-'); // if (array.length === 2) { // protectedMap.set(array[0], array[1]); // } // } // } } let beforeUri = ''; let beforeItemId = ''; // const siteInfoArr = []; for (let idx in files) { const file = files[idx]; //const fileName = file.originalname; //let filePath = req.body[ fileName + "_path"]; file.originalname = Buffer.from(file.originalname, 'ascii').toString('utf8'); let originName = file.originalname; if (originName) { let ext = globalPath.extname(originName); if (supportedArr.length > 0 && !supportedArr.includes(ext)) { return res.json({success:'F', message: '파일명 : ' + originName +'
해당 파일은 업로드 불가 파일입니다. 다시 시도해주세요.
가능 확장자 :' + JSON.stringify(supportedArr)}); } // const uuid = uuidv4(); // const realFileName = uuid + ext; // fileWriteArray.push(new Promise((resolve, reject) => { // const data = fs.writeFileSync('Z:/Source/' + realFileName, file.buffer) // resolve({ // data // }) // })); const base64Data = Buffer.from(file.buffer).toString('base64'); const param = { apiKey: gateWayKey, email: req.session.account.idTokenClaims.email, dispFileName: originName, aipGuid: "878173ae-cc36-4881-af57-604af868314c", // aipGuid: "0166b75f-6a93-47f3-8fd3-e1e7c59141ab", // comment: "set-protection", comment: "set-label", fileData: base64Data, } // labelPromiseArray.push(new Promise(async (resolve)=>{resolve(await axios.post(apiUrl + '/api/v1/stream/set-label', param))})); labelPromiseArray.push(axios.post(apiUrl + '/api/v1/stream/set-label', param)); // labelPromiseArray.push(axios.post(apiUrl + '/api/v1/stream/set-protection', param)); let formatPath = ''; if (file_path[idx]) { // console.log(file_path[idx]); if (!path.includes(":")) { formatPath = ":" + file_path[idx]; } else { formatPath = file_path[idx]; } } let itemId = ''; const uri = endPoint + "/sites/"+ siteId + path + formatPath; // siteInfoArr.push(axios.get(uri, options)); if (beforeUri === uri) { itemId = beforeItemId; } else { try { const sitesInfo = await axios.get(uri, options); itemId = sitesInfo.data.id; beforeUri = uri; beforeItemId = itemId; } catch(error) { console.log(error); res.json({success:'F', message: '파일 업로드 작업 중 오류가 발생했습니다.
에러 : ' + JSON.stringify(error.message)}); } } // if (protectedMap.size > 0 && protectedMap.get(ext)) { // let name = originName.replace(ext, ''); // ext = protectedMap.get(ext); // originName = name + ext; // } promiseArray.push(endPoint + "/sites/"+ siteId +"/drive/items/"+itemId+':/'); } } try { // const siteInfos = await Promise.all(siteInfoArr); // siteInfos.forEach((obj)=>{ // promiseArray.push(endPoint + "/sites/"+ siteId +"/drive/items/"+obj.data.id+':/'); // }) //file write 시 사용 //const writeArr = await Promise.all(fileWriteArray); let writeTime = timeCheck(fileWriteTime, new Date()); console.log('파일 Write Time : '+ writeTime); const labelTime = new Date(); const labelResult = await Promise.all(labelPromiseArray); // console.log(labelResult[0].data.result.fileData); console.log('label time : ', timeCheck(labelTime, new Date())); for (let idx in labelResult) { const obj = labelResult[idx]; if (obj.data && !obj.data.result.errorCode && obj.data.result.fileData) { const data = Buffer.from(obj.data.result.fileData, 'base64'); // promiseArray[idx] = new Promise(async (resolve)=> resolve(await axios.put(promiseArray[idx] + obj.data.result.dispFileName + ':/content', data, options))); promiseArray[idx] = axios.put(promiseArray[idx] + obj.data.result.dispFileName + ':/content', data, options); // promiseArray.push(axios.put(endPoint + "/sites/"+ siteId +"/drive/items/"+ siteInfos[idx].data.id + ':/' + obj.data.result.dispFileName + ':/content', data, options)); } else { throw '파일명 : '+obj.data.result.dispFileName + '
에러 : ' + obj.data.result.errorMessage; } } // labelResult.forEach((obj, idx)=>{ // if (obj.data && !obj.data.result.errorCode && obj.data.result.fileData) { // const data = Buffer.from(obj.data.result.fileData, 'base64'); // promiseArray[idx] = axios.put(promiseArray[idx] + obj.data.result.dispFileName + ':/content', data, options); // // promiseArray.push(axios.put(endPoint + "/sites/"+ siteId +"/drive/items/"+ siteInfos[idx].data.id + ':/' + obj.data.result.dispFileName + ':/content', data, options)); // } // else { // throw '파일명 : '+obj.data.result.dispFileName + '
에러 : ' + obj.data.result.errorMessage; // } // }) // const readArray = []; // labelResult.forEach((obj)=>{ // readArray.push(new Promise((resolve, reject)=>{ // if (obj.data && !obj.data.result.errorCode) { // fs.readFile('Z:/Target/' + obj.data.result.outputFileName, (err, data)=>{ // if (err) { // reject({err}); // } // resolve({data}); // //promiseArray[idx] = axios.put(promiseArray[idx], data, options); // }); // } // else { // reject(obj.data.result.errorMessage); // } // })) // }); // console.log('labelResult : ', labelResult); // let readTime = new Date(); // const readResult = await Promise.all(readArray); // console.log(readResult); // console.log('File Read time : ', timeCheck(readTime, new Date())); let uploadTime = new Date(); // promiseArray.forEach((obj, idx)=>{ // // console.log(readResult[idx].data); // // console.log(obj[idx]); // promiseArray[idx] = axios.put(obj, readResult[idx].data, options); // }); const uploadResult = await Promise.all(promiseArray); console.log('File uploadTime : ', timeCheck(uploadTime, new Date())); } catch(error){ return res.json({success:'F', message: '요청하신 파일 업로드 중 오류가 발생하였습니다.
' + getErrorMessage(error)}); } } const endTime = new Date(); let betweenTime = timeCheck(startTime, endTime); console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', betweenTime); res.json({success:'S', message: '요청하신 파일 업로드가 정상적으로 처리 되었습니다.'}); } else { return res.json({success:'F', message: '업로드 요청 파라미터 정보를 확인해 주세요.'}); } }); function timeCheck(startTime, endTime) { let betweenTime = endTime - startTime; if (betweenTime > 60000) { betweenTime = (betweenTime/1000/60) + ' 분'; } else { betweenTime = (betweenTime/1000) + ' 초'; } return betweenTime; } serverApp.post('/api/download', async (req, res, next)=>{ try { let startTime = new Date(); const {siteId, path, fileIds, zipName} = req.body; if (siteId && path && fileIds) { const options = getOptions(req.session.accessToken); const arr = JSON.parse(fileIds); const url = endPoint + "/sites/"+ siteId + "/drive/items/"; const result = await axios(url + arr[0], options); // 단일 파일 다운로드 if (arr.length === 1 && result && result.data && result.data.file) { const dataUrl = result.data['@microsoft.graph.downloadUrl']; const fileOption = {responseType: 'arraybuffer', headers: { withCredentials : true }}; const fileData = await axios.get(dataUrl, fileOption); const bufferData = Buffer.from(fileData.data, 'base64'); const param = { apiKey: gateWayKey, email : res.session.account.idTokenClaims.email, dispFileName: result.data.name, comment: "", fileData: Buffer.from(bufferData).toString('base64') } const deleteLabelResult = await axios.post(apiUrl + '/api/v1/stream/delete-label', param); if (deleteLabelResult && deleteLabelResult.data && !deleteLabelResult.data.result.errorCode) { return res.json({success: 'S', data: Buffer.from(data.data, 'base64'), name: deleteLabelResult.data.result.name}) } } //폴더 또는 다중 파일 다운로드 else { const zip = new JSZIP(); // const downObj = await getFolderItems(url, arr, options, req.session, zip); const timer = new Date(); console.log('getFolderItems Start : ', timer.toLocaleString()); await getFolderItems(url, arr, options, req.session, zip); const timerEnd = new Date(); console.log('getFolderItems end : ', timerEnd.toLocaleString(), ',소요시간 : '+ timeCheck(timer,timerEnd)); // createZipFile(downObj, zip); const now = new Date(); const year = now.getFullYear().toString(); let month = now.getMonth() + 1; if (month < 10) month = "0" + month; let date = now.getDate(); if (date < 10) date = "0" + date; zip.generateAsync({ type: 'nodebuffer', // mimeType: 'application/epub+zip', // compression: 'DEFLATE', // compressionOptions: { // level: 9 // }, }).then((resZip)=>{ const endTime = new Date(); console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', timeCheck(startTime, endTime)); return res.json({success: 'S', data: resZip, name: zipName + '_' + year + '-' + month + '-' + date + '.zip'}); }) .catch((error)=>{ console.log(error); return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.', error: error}); }); } } else { return res.json({message:'다운로드 파일 정보를 확인 할 수 없습니다.', success:'F'}) } } catch(error) { return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.
'+ getErrorMessage(error)}); } } ); serverApp.post('/api/folderMove', async (req, res, next)=>{ if (req.body) { const {id, name, siteId, driveId, text, moveSiteId, movePath} = req.body; const resultObj = {message:'폴더 이동에 실패 하였습니다.', success: 'F'}; if (name && isNaN(name)) { const nameArray = JSON.parse(name); const options = getOptions(req.session.accessToken); if (nameArray && nameArray.length > 0) { for (let moveItem of nameArray) { if (moveItem) { try { const copyFolderPath = `${endPoint}/sites/${siteId}/drive/items/${moveItem.id}`; const result = await axios.get(copyFolderPath, options); if (result && result.data) { const data = result.data; const moveUri = `${endPoint}/sites/${moveSiteId}/${movePath}`; const moveFolderResult = await findSubFolder(data, moveUri, moveSiteId, options); console.log('moveFolderResult : ',moveFolderResult); if (!moveFolderResult) { resultObj.message ='폴더 이동 중 오류가 발생하였습니다.'; } else { await axios.delete(endPoint + "/sites/"+ siteId + "/drive/items/" + moveItem.id, options); resultObj.message ='폴더 이동 되었습니다.'; resultObj.success = 'S'; } } } catch (error) { console.log(error.message); console.log(error.name); console.log(error.errors); resultObj.message = error.errors; // resultObj.failItems.push(moveItem); } } } } } return res.json(resultObj); } }) async function findSubFolder(data, movePath, moveSiteId, options) { let resultType = false; try { const moveItem = await axios.get(movePath, options); if (moveItem.data && moveItem.data.id) { const param = { "name": data.name, "folder": {}, "@microsoft.graph.conflictBehavior": "rename" } const makeFolderData = await axios.post(`${endPoint}/sites/${moveSiteId}/drive/items/${moveItem.data.id}/children`, param, options); if (makeFolderData && makeFolderData.data) { const makeFolderPath = `${endPoint}/sites/${moveSiteId}/${makeFolderData.data.parentReference.path}/${data.name}`; if (data.folder.childCount) { const siteId = data.parentReference.siteId; const childrenData = await axios.get(`${endPoint}/sites/${siteId}/drive/items/${data.id}/children`, options); if (childrenData && childrenData.data && childrenData.data.value) { const childrenValues = childrenData.data.value; if (childrenValues.length > 0) { for (let ii = 0; ii < childrenValues.length; ii++) { const children = childrenValues[ii]; if (children && children.folder) { const result = await findSubFolder(children, makeFolderPath, moveSiteId, options); resultType = result; } else { const dataUrl = children['@microsoft.graph.downloadUrl']; const response = await axios.get(dataUrl, {responseType: 'arraybuffer', headers: { withCredentials:true, },}); if (response.data) { const file = response.data; const uploadResult = await axios.put(`${endPoint}/sites/${moveSiteId}/drive/items/${makeFolderData.data.id}:/${children.name}:/content`, file.buffer, options); if (uploadResult) { resultType = true; } } } } } } } } } } catch(error) { console.log(error); return resultType; } return resultType; } function createZipFile(obj, zip) { if (obj.files && obj.files.length > 0) { for (let file of obj.files) { console.log(file.name); zip.file(file.name, file.data, {base64: true}); } } if (obj.folder && obj.folder.length > 0) { for (let folder of obj.folder) { console.log(folder.name); zip.folder(folder.name); if (folder.subFolder) { createZipFile(folder.subFolder, zip.folder(folder.name)); } } } } async function getFolderItems(url, array, options, session, zip) { // const files = []; // const folder = []; const sitesInfoArr = []; const fileArr = []; const fileInfoArr = []; // const folderCheckTime = new Date(); // for (let fileId of array) { // sitesInfoArr.push(axios.get(url + fileId, options)); // } // const siteInfos = await Promise.all(sitesInfoArr).catch((error)=>{ // console.log(error); // throw error; // }); for (let fileId of array) { sitesInfoArr.push(axios.get(url + fileId, options)); } const siteInfos = await Promise.all(sitesInfoArr); for (let site of siteInfos) { const data = site.data; if (data) { if (data.folder) { // const folderObj = {name : data.name, subFolder : []}; zip.folder(data.name); if (data.folder.childCount) { const itemsData = await axios.get(url + data.id + '/children', options); if (itemsData && itemsData.data && itemsData.data.value.length > 0) { const idArr = []; for (let children of itemsData.data.value) { idArr.push(children.id); } try { // let result = await getFolderItems(url, idArr, options, session, zip.folder(data.name)); await getFolderItems(url, idArr, options, session, zip.folder(data.name)); // folderObj.subFolder = result; } catch(error) { if (error) { throw error; } } // subFolder.push(result); } } // folder.push(folderObj); } else { const dataUrl = data['@microsoft.graph.downloadUrl']; const fileOption = {responseType: 'arraybuffer', headers: { withCredentials : true }}; fileArr.push(axios.get(dataUrl, fileOption)); fileInfoArr.push(data); } } } // console.log('======================= folder check end ==============================='); // console.log('folder check 소요시간 : ', timeCheck(folderCheckTime, new Date())); // console.log('======================= delete label start ==============================='); const fileDataArr = await Promise.all(fileArr).then((result)=>{ let deleteLabelArr = []; for (let idx in result) { let fileData = result[idx].data; const param = { apiKey: gateWayKey, email : session.account.idTokenClaims.email, dispFileName: fileInfoArr[idx].name, comment: "", fileData: Buffer.from(fileData).toString('base64') } deleteLabelArr.push(axios.post(apiUrl + '/api/v1/stream/delete-label', param)); } return deleteLabelArr; }); // const deleteLabelTime = new Date(); // const deleteLabelArr = []; // for (let idx in fileDataArr) { // let fileData = fileDataArr[idx].data; // const param = { // apiKey: gateWayKey, // email : session.account.idTokenClaims.email, // dispFileName: fileInfoArr[idx].name, // comment: "", // fileData: Buffer.from(fileData).toString('base64') // } // deleteLabelArr.push(axios.post(apiUrl + '/api/v1/stream/delete-label', param)); // } const deleteLabelFiles = await Promise.all(fileDataArr); // const deleteLabelFiles = await Promise.all(deleteLabelArr); for (let idx in deleteLabelFiles) { const fileObj = deleteLabelFiles[idx]; const data = fileObj.data; if (data.success && !data.result.errorCode) { // files.push({name : data.result.dispFileName, data: data.result.fileData}); zip.file(data.result.dispFileName, data.result.fileData, {base64: true}); } else { throw data.result.dispFileName + ' : ' + data.result.errorMessage; } } // console.log('======================= delete label end ===============================') // console.log('delete label 소요시간 : ',timeCheck(deleteLabelTime, new Date())); // const resultObj = { // folder : folder, // files : files, // }; // return resultObj; } serverApp.post('/api/getPossibleExtList', async (req, res, next)=>{ return res.json(POSSIBLE_EXT); }) serverApp.post('/api/delete', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ if (req.body) { const {siteId, itemIds} = req.body; const resultObj = {success: '', message:''}; if (siteId && itemIds) { const itemIdArr = JSON.parse(itemIds); if (itemIdArr.length > 0) { const options = getOptions(req.session.accessToken); for (let itemId of itemIdArr) { try{ await axios.delete(endPoint + "/sites/"+ siteId + "/drive/items/" + itemId, options); } catch(error) { resultObj.success = 'F'; let message = '선택하신 파일 정보 삭제중 오류가 발생하였습니다.'; if (error && error.response && error.response.data && error.response.data.error && error.response.data.error.message) { console.log(error.response.data.error.message); message += '
' + error.response.data.error.message; } resultObj.message = message; return res.json(resultObj); } } resultObj.success = 'S'; resultObj.message = '파일 정보가 삭제되었습니다.'; res.json(resultObj); } } else { resultObj.success = 'F'; resultObj.message = '파라미터 정보를 확인해주세요.'; res.json(resultObj); } } }) serverApp.post('/api/update-name', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ if (req.body) { const {siteId, itemId, name} = req.body; const resultObj = {success: '', message:''}; if (siteId && itemId && name) { const options = getOptions(req.session.accessToken); try{ await axios.patch(endPoint + "/sites/"+ siteId + "/drive/items/" + itemId, {name : name}, options); } catch(error) { console.log(error.response.data.error); resultObj.success = 'F'; resultObj.message = '선택하신 파일의 이름 변경 중 오류가 발생하였습니다.
' + error.response.data.error.message; return res.json(resultObj); } resultObj.success = 'S'; resultObj.message = '선택하신 파일의 이름이 변경되었습니다.'; return res.json(resultObj); } } else { resultObj.success = 'F'; resultObj.message = '파라미터 정보를 확인해주세요.'; return res.json(resultObj); } }); serverApp.post('/api/move-item', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ if (req.body) { const {id, name, siteId, text} = req.body; const resultObj = {message:'', successItems : [], failItems : [], locations: []}; if (name && isNaN(name)) { const nameArray = JSON.parse(name); const options = getOptions(req.session.accessToken); if (nameArray && nameArray.length > 0) { for (let moveItem of nameArray) { if (moveItem) { const param = { parentReference: { id: id, }, name: moveItem.name }; try { const result = await axios.patch(`${endPoint}/sites/${siteId}/drive/items/${moveItem.id}`, param, options); if (result) { resultObj.successItems.push(moveItem); // resultObj.locations.push(result.headers.location); } } catch (error) { // console.log(error); console.log(error.message); console.log(error.name); console.log(error.errors); resultObj.failItems.push(moveItem); } } } resultObj.message = `요청 하신 ${nameArray.length} 개 파일 중 ${ resultObj.successItems.length} 개 파일이 ${text} 되었습니다.`; } } return res.json(resultObj); } }); serverApp.post('/api/copy-item', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ if (req.body) { const {id, name, siteId, driveId, text} = req.body; const resultObj = {message:'', successItems : [], failItems : [], locations: []}; if (name && isNaN(name)) { const nameArray = JSON.parse(name); const options = getOptions(req.session.accessToken); if (nameArray && nameArray.length > 0) { for (let moveItem of nameArray) { if (moveItem) { const param = { parentReference: { id: id, driveId : driveId, }, name: moveItem.name }; try { const result = await axios.post(`${endPoint}/sites/${siteId}/drive/items/${moveItem.id}/copy`, param, options); if (result) { resultObj.successItems.push(moveItem); resultObj.locations.push(result.headers.location); } } catch (error) { // console.log(error); console.log(error.message); console.log(error.name); console.log(error.errors); resultObj.failItems.push(moveItem); } } } resultObj.message = `요청 하신 ${nameArray.length} 개 파일 중 ${ resultObj.successItems.length} 개 파일이 ${text} 되었습니다.`; } } return res.json(resultObj); } }); serverApp.post('/api/loading', async (req, res, next)=>{ if (req.body) { const {url} = req.body; if (url) { try { const result = await axios.get(`${url}`); if (result && result.data) { console.log(result.data); return res.json(result.data); } } catch (error) { // console.log(error); console.log(error.message); console.log(error.name); console.log(error.errors); return res.json(error); } } } }); serverApp.post('/api/add-tab', // isAuthenticated, // isAccessTokens, async (req, res, next)=>{ if (req.body) { const {name, siteId, path, teamId, teamName, bindId} = req.body; const resultObj = {message:'', success: 'F'}; if (name && siteId && path && teamId && teamName) { const options = getOptions(req.session.accessToken); try { const teamInfo = await axios.get(`${endPoint}/teams/${teamId}/channels`, options); const sharePoint = await axios.get(`${endPoint}/sites/${siteId}/drive`, options); if (teamInfo.data && teamInfo.data.value && sharePoint.data) { const sharePointUrl = sharePoint.data.webUrl; if (path.includes('/drive/root:/') && sharePointUrl) { let channelName = path.replace('/drive/root:/', ''); const contentUrl = sharePointUrl + '/' + channelName; channelName = channelName.substring(0, channelName.indexOf('/')); const idx = teamInfo.data.value.findIndex(obj => obj.displayName === channelName); resultObj.message = `채널명 : ${channelName}
파일명 : ${name}
요청하신 채널에 탭으로 설정 되지않았습니다.`; if (idx >= 0 && contentUrl) { const channelId = teamInfo.data.value[idx].id; if (channelId) { const param = { displayName: name, "teamsApp@odata.bind" : `https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/${bindId}`, configuration: { entityId: null, contentUrl: contentUrl, websiteUrl: "", removeUrl: null } } //sites/root/lists const channelInfo = await axios.post(`${endPoint}/teams/${teamId}/channels/${channelId}/tabs`, param, options); if (channelInfo.data) { resultObj.success = 'S'; resultObj.message = '채널명 : ' + channelName + '
파일명 : '+name+'
요청하신 채널에 탭으로 설정 되었습니다.'; } } } } } } catch (error) { resultObj.message = `채널명 : ${channelName}
파일명 : ${name}
요청하신 채널에 탭으로 설정 중 오류가 발생하였습니다.
` + getErrorMessage(error); } } return res.json(resultObj); } }); // // 데이터베이스 연결 // pool.connect((err) => { // // 연결이 안될 경우 에러 내용 콘솔에 출력 // if (err) { // console.error('Error connecting to database:', err); // return; // } // // 연결에 성공할 경우 연결 성공 메시지 콘솔에 출력 // console.log('Connected to database'); // }); async function getPossibleExt() { const resultObj = { success : 'F', message : null, data : null, } const sqlQuery = `SELECT A.ConfigValue AS supported_file_ext, B.ConfigValue AS protected_file_ext FROM (SELECT * FROM TB_AIP_CONFIG WHERE ConfigKey = 'SupportedFileExt' AND AipServerId = 0) A, (SELECT * FROM TB_AIP_CONFIG WHERE ConfigKey = 'ProtectedFileExt' AND AipServerId = 0) B`; try { const query = await pool; const result = await query.request().query(sqlQuery); if (result && result.recordset.length) { resultObj.success = 'S'; resultObj.message = 'Success'; resultObj.data = result.recordset[0]; } else { resultObj.success = 'F'; resultObj.message = "Not Found Data"; } } catch(error) { // console.log(error); console.log(error); resultObj.success = 'F'; resultObj.message = JSON.stringify(error); } return resultObj; } async function setLabelFile(session, file, supported_file_ext) { const resultObj = { success : 'F', message : null, fileData : null, } const originName = file.originalname; // 파일 확장자 if (originName && originName.lastIndexOf('.') >= 0) { const ext = originName.substring(originName.lastIndexOf('.'), originName.length); if (supported_file_ext) { let supportedArr = supported_file_ext.split(';'); if (!supportedArr[supportedArr.length - 1]) { supportedArr.splice(supportedArr.length - 1); } if (!supportedArr.includes(ext)) { resultObj.status = 500; resultObj.error = '파일명 : ' + originName +'
해당 파일은 업로드 불가 파일입니다. 다시 시도해주세요.
가능 확장자 :' + JSON.stringify(supportedArr); return resultObj; } const fileData = Buffer.from(file.buffer).toString('base64'); const param = { apiKey: gateWayKey, email: session.account.idTokenClaims.email, dispFileName: originName, aipGuid: "878173ae-cc36-4881-af57-604af868314c", comment: "", fileData: fileData } try { const result = await axios.post(apiUrl + '/api/v1/stream/set-label', param); if (result) { if (result.data.statusCode === 200 && !result.data.result.errorCode) { resultObj.fileData = Buffer.from(result.data.result.fileData, "base64"); } else { console.log(result.data); resultObj.success = 'F'; resultObj.message = '파일명 : ' + originName + '
에러 : ' + result.data.result.errorMessage; } } } catch(error) { console.log(error); resultObj.success = 'F'; resultObj.message = '레이블 설정 중 오류가 발생하였습니다.
' + JSON.stringify(error.message); } } } return resultObj; } async function deleteLabelFile(session, name, file) { const resultObj = { error : false, errorMessage : null, fileData : null, } try { const param = { apiKey: gateWayKey, email : session.account.idTokenClaims.email, dispFileName: name, comment: "", fileData: file } const result = await axios.post(apiUrl + '/api/v1/stream/delete-label', param); if (result && result.data.statusCode === 200 && !result.data.result.errorCode) { resultObj.fileData = result.data.result.fileData; } else { resultObj.error = true; resultObj.errorMessage = '파일명 : ' + name + '
에러 : ' + result.data.result.errorMessage; console.log(result.data.result); } } catch(error) { console.log(error); resultObj.error = true; resultObj.errorMessage = '레이블 해제 중 오류가 발생하였습니다.
' + JSON.stringify(error.message); } return resultObj; } function getOptions(token) { const options = { headers: { Authorization: `Bearer ${token}`, }, }; return options; } serverApp.use((err, req, res, next)=>{ console.log(err.message); // console.log(err); console.log(res.statusCode); if (err) { res.status(400); res.json({message: err.message}); } else { res.status(500); res.json({message: err.message}); } }) server.listen(SERVER_PORT, function () { console.log(`\n${serverApp.name} listening to ${SERVER_PORT}`); });