mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-02-10 18:05:07 +08:00
Merge remote-tracking branch 'remotes/origin/release/v8.1.0' into develop
# Conflicts: # Common/config/default.json # Common/sources/constants.js # DocService/sources/DocsCoServer.js
This commit is contained in:
4
.github/workflows/damengDatabaseTests.yml
vendored
4
.github/workflows/damengDatabaseTests.yml
vendored
@ -1,6 +1,8 @@
|
|||||||
name: Dameng database tests
|
name: Dameng database tests
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
paths:
|
paths:
|
||||||
- 'tests/integration/databaseTests/**'
|
- 'tests/integration/databaseTests/**'
|
||||||
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
||||||
@ -46,4 +48,4 @@ jobs:
|
|||||||
docker exec dameng bash -c "cat /createdb.sql | /opt/dmdbms/bin/disql SYSDBA/SYSDBA001:5236"
|
docker exec dameng bash -c "cat /createdb.sql | /opt/dmdbms/bin/disql SYSDBA/SYSDBA001:5236"
|
||||||
|
|
||||||
- name: Run Jest
|
- name: Run Jest
|
||||||
run: npm run "integration database tests"
|
run: npm run "integration database tests"
|
||||||
|
|||||||
4
.github/workflows/mssqlDatabaseTests.yml
vendored
4
.github/workflows/mssqlDatabaseTests.yml
vendored
@ -1,6 +1,8 @@
|
|||||||
name: MSSQL database tests
|
name: MSSQL database tests
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
paths:
|
paths:
|
||||||
- 'tests/integration/databaseTests/**'
|
- 'tests/integration/databaseTests/**'
|
||||||
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
||||||
@ -46,4 +48,4 @@ jobs:
|
|||||||
docker exec mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P onlYoff1ce -i /createdb.sql
|
docker exec mssql /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P onlYoff1ce -i /createdb.sql
|
||||||
|
|
||||||
- name: Run Jest
|
- name: Run Jest
|
||||||
run: npm run "integration database tests"
|
run: npm run "integration database tests"
|
||||||
|
|||||||
6
.github/workflows/mysqlDatabaseTests.yml
vendored
6
.github/workflows/mysqlDatabaseTests.yml
vendored
@ -1,6 +1,8 @@
|
|||||||
name: MYSQL database tests
|
name: MYSQL database tests
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
paths:
|
paths:
|
||||||
- 'tests/integration/databaseTests/**'
|
- 'tests/integration/databaseTests/**'
|
||||||
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
||||||
@ -20,7 +22,7 @@ jobs:
|
|||||||
- name: Caching dependencies
|
- name: Caching dependencies
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '16'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
cache-dependency-path: |
|
cache-dependency-path: |
|
||||||
./npm-shrinkwrap.json
|
./npm-shrinkwrap.json
|
||||||
@ -43,4 +45,4 @@ jobs:
|
|||||||
docker exec mysql mysql -h 127.0.0.1 -u root --password=onlyoffice -D onlyoffice -e 'source /createdb.sql'
|
docker exec mysql mysql -h 127.0.0.1 -u root --password=onlyoffice -D onlyoffice -e 'source /createdb.sql'
|
||||||
|
|
||||||
- name: Run Jest
|
- name: Run Jest
|
||||||
run: npm run "integration database tests"
|
run: npm run "integration database tests"
|
||||||
|
|||||||
4
.github/workflows/oracleDatabaseTests.yml
vendored
4
.github/workflows/oracleDatabaseTests.yml
vendored
@ -1,6 +1,8 @@
|
|||||||
name: Oracle database tests
|
name: Oracle database tests
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
paths:
|
paths:
|
||||||
- 'tests/integration/databaseTests/**'
|
- 'tests/integration/databaseTests/**'
|
||||||
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
||||||
@ -46,4 +48,4 @@ jobs:
|
|||||||
docker exec oracle sqlplus -s onlyoffice/onlyoffice@//localhost/xepdb1 @/createdb.sql
|
docker exec oracle sqlplus -s onlyoffice/onlyoffice@//localhost/xepdb1 @/createdb.sql
|
||||||
|
|
||||||
- name: Run Jest
|
- name: Run Jest
|
||||||
run: npm run "integration database tests"
|
run: npm run "integration database tests"
|
||||||
|
|||||||
4
.github/workflows/postgreDatabaseTests.yml
vendored
4
.github/workflows/postgreDatabaseTests.yml
vendored
@ -1,6 +1,8 @@
|
|||||||
name: Postgre database tests
|
name: Postgre database tests
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
paths:
|
paths:
|
||||||
- 'tests/integration/databaseTests/**'
|
- 'tests/integration/databaseTests/**'
|
||||||
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
- 'DocService/sources/databaseConnectors/baseConnector.js'
|
||||||
@ -43,4 +45,4 @@ jobs:
|
|||||||
docker exec postgres psql -d onlyoffice -U onlyoffice -a -f /createdb.sql
|
docker exec postgres psql -d onlyoffice -U onlyoffice -a -f /createdb.sql
|
||||||
|
|
||||||
- name: Run Jest
|
- name: Run Jest
|
||||||
run: npm run "integration database tests"
|
run: npm run "integration database tests"
|
||||||
|
|||||||
4
.github/workflows/unitTests.yml
vendored
4
.github/workflows/unitTests.yml
vendored
@ -1,6 +1,8 @@
|
|||||||
name: Service unit tests
|
name: Service unit tests
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
paths:
|
paths:
|
||||||
- '**.js'
|
- '**.js'
|
||||||
- '!tests/integration/**'
|
- '!tests/integration/**'
|
||||||
@ -31,4 +33,4 @@ jobs:
|
|||||||
npm --prefix DocService ci
|
npm --prefix DocService ci
|
||||||
|
|
||||||
- name: Run Jest
|
- name: Run Jest
|
||||||
run: npm run "unit tests"
|
run: npm run "unit tests"
|
||||||
|
|||||||
@ -35,6 +35,8 @@
|
|||||||
"s3ForcePathStyle": true,
|
"s3ForcePathStyle": true,
|
||||||
"externalHost": ""
|
"externalHost": ""
|
||||||
},
|
},
|
||||||
|
"persistentStorage": {
|
||||||
|
},
|
||||||
"rabbitmq": {
|
"rabbitmq": {
|
||||||
"url": "amqp://guest:guest@localhost:5672",
|
"url": "amqp://guest:guest@localhost:5672",
|
||||||
"socketOptions": {},
|
"socketOptions": {},
|
||||||
@ -93,25 +95,28 @@
|
|||||||
"favIconUrlWord" : "/web-apps/apps/documenteditor/main/resources/img/favicon.ico",
|
"favIconUrlWord" : "/web-apps/apps/documenteditor/main/resources/img/favicon.ico",
|
||||||
"favIconUrlCell" : "/web-apps/apps/spreadsheeteditor/main/resources/img/favicon.ico",
|
"favIconUrlCell" : "/web-apps/apps/spreadsheeteditor/main/resources/img/favicon.ico",
|
||||||
"favIconUrlSlide" : "/web-apps/apps/presentationeditor/main/resources/img/favicon.ico",
|
"favIconUrlSlide" : "/web-apps/apps/presentationeditor/main/resources/img/favicon.ico",
|
||||||
|
"favIconUrlPdf" : "/web-apps/apps/pdfeditor/main/resources/img/favicon.ico",
|
||||||
"fileInfoBlockList" : ["FileUrl"],
|
"fileInfoBlockList" : ["FileUrl"],
|
||||||
"pdfView": ["pdf", "djvu", "xps", "oxps"],
|
"pdfView": ["djvu", "xps", "oxps"],
|
||||||
"wordView": ["doc", "dotx", "dotm", "dot", "fodt", "ott", "rtf", "mht", "mhtml", "html", "htm", "xml", "epub", "fb2", "sxw", "stw", "wps", "wpt"],
|
"pdfEdit": ["pdf"],
|
||||||
"wordEdit": ["docx", "docm", "docxf", "oform", "odt", "txt"],
|
"forms": ["pdf"],
|
||||||
|
"wordView": ["doc", "dotx", "dotm", "dot", "fodt", "ott", "rtf", "mht", "mhtml", "html", "htm", "xml", "epub", "fb2", "sxw", "stw", "wps", "wpt", "docxf", "oform"],
|
||||||
|
"wordEdit": ["docx", "docm", "odt", "txt"],
|
||||||
"cellView": ["xls", "xlsb", "xltx", "xltm", "xlt", "fods", "ots", "sxc", "xml", "et", "ett"],
|
"cellView": ["xls", "xlsb", "xltx", "xltm", "xlt", "fods", "ots", "sxc", "xml", "et", "ett"],
|
||||||
"cellEdit": ["xlsx", "xlsm", "ods", "csv"],
|
"cellEdit": ["xlsx", "xlsm", "ods", "csv"],
|
||||||
"slideView": ["ppt", "ppsx", "ppsm", "pps", "potx", "potm", "pot", "fodp", "otp", "sxi", "dps", "dpt"],
|
"slideView": ["ppt", "ppsx", "ppsm", "pps", "potx", "potm", "pot", "fodp", "otp", "sxi", "dps", "dpt"],
|
||||||
"slideEdit": ["pptx", "pptm", "odp"],
|
"slideEdit": ["pptx", "pptm", "odp"],
|
||||||
"publicKey": "BgIAAACkAABSU0ExAAgAAAEAAQD/NVqekFNi8X3p6Bvdlaxm0GGuggW5kKfVEQzPGuOkGVrz6DrOMNR+k7Pq8tONY+1NHgS6Z+v3959em78qclVDuQX77Tkml0xMHAQHN4sAHF9iQJS8gOBUKSVKaHD7Z8YXch6F212YSUSc8QphpDSHWVShU7rcUeLQsd/0pkflh5+um4YKEZhm4Mou3vstp5p12NeffyK1WFZF7q4jB7jclAslYKQsP82YY3DcRwu5Tl/+W0ifVcXze0mI7v1reJ12pKn8ifRiq+0q5oJST3TRSrvmjLg9Gt3ozhVIt2HUi3La7Qh40YOAUXm0g/hUq2BepeOp1C7WSvaOFHXe6Hqq",
|
"publicKey": "BgIAAACkAABSU0ExAAgAAAEAAQBpTpiJQ2hD8plpGTfEEmcq4IKyr31HikXpuVSBraMfqyodn2PGXBJ3daNSmdPOc0Nz4HO9Auljn8YYXDPBdpiABptSKvEDPF23Q+Qytg0+vCRyondyBcW91w7KLzXce3fnk8ZfJ8QtbZPL9m11wJIWZueQF+l0HKYx4lty+nccbCanytFTADkGQ3SnmExGEF3rBz6I9+OcrDDK9NKPJgEmCiuyei/d4XbPgKls3EIG0h38X5mVF2VytfWm2Yu850B6z3N4MYhj4b4vsYT62zEC4pMRUeb8dIBy4Jsmr3avtmeO00MUH6DVyPC8nirixj2YIOPKk13CdVqGDSXA3cvl",
|
||||||
"modulus": "qnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/w==",
|
"modulus": "E5CBDDC0250D865A75C25D93CAE320983DC6E22A9EBCF0C8D5A01F1443D38E67B6AF76AF269BE0728074FCE6511193E20231DBFA84B12FBEE16388317873CF7A40E7BC8BD9A6F5B572651795995FFC1DD20642DC6CA980CF76E1DD2F7AB22B0A2601268FD2F4CA30AC9CE3F7883E07EB5D10464C98A7744306390053D1CAA7266C1C77FA725BE231A61C74E91790E7661692C0756DF6CB936D2DC4275FC693E7777BDC352FCA0ED7BDC5057277A27224BC3E0DB632E443B75D3C03F12A529B06809876C1335C18C69F63E902BD73E0734373CED39952A37577125CC6639F1D2AAB1FA3AD8154B9E9458A477DAFB282E02A6712C437196999F243684389984E69",
|
||||||
"exponent": "AQAB",
|
"exponent": "65537",
|
||||||
"privateKey": "MIIEowIBAAKCAQEAqnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/wIDAQABAoIBAQCKtUSBs8tNYrGTQTlBHXrwpkDg+u7WSZt5sEcfnkxA39BLtlHU8gGO0E9Ihr8GAL+oWjUsEltJ9GTtN8CJ9lFdPVS8sTiCZR/YQOggmFRZTJyVzMrkXgF7Uwwiu3+KxLiTOZx9eRhfDBlTD8W9fXaegX2i2Xp2ohUhBHthEBLdaZTWFi5Sid/Y0dDzBeP6UIJorZ5D+1ybaeIVHjndpwNsIEUGUxPFLrkeiU8Rm4MJ9ahxfywcP7DjQoPGY9Ge5cBhpxfzERWf732wUD6o3+L9tvOBU00CLVjULbGZKTVE2FJMyXK9jr6Zor9Mkhomp6/8Agkr9rp+TPyelFGYEz8hAoGBAOEc09CrL3eYBkhNEcaMQzxBLvOGpg8kaDX5SaArHfl9+U9yzRqss4ARECanp9HuHfjMQo7iejao0ngDjL7BNMSaH74QlSsPOY2iOm8Qvx8/zb7g4h9r1zLjFZb3mpSA4snRZvvdiZ9ugbuVPmhXnDzRRMg45MibJeeOTJNylofRAoGBAMHfF/WutqKDoX25qZo9m74W4bttOj6oIDk1N4/c6M1Z1v/aptYSE06bkWngj9P46kqjaay4hgMtzyGruc5aojPx5MHHf5bo14+Jv4NzYtR2llrUxO+UJX7aCfUYXI7RC93GUmhpeQ414j7SNAXec58d7e+ETw+6cHiAWO4uOSTPAoGATPq5qDLR4Zi4FUNdn8LZPyKfNqHF6YmupT5hIgd8kZO1jKiaYNPL8jBjkIRmjBBcaXcYD5p85nImvumf2J9jNxPpZOpwyC/Fo5xlVROp97qu1eY7DTmodntXJ6/2SXAlnZQhHmHsrPtyG752f+HtyJJbbgiem8cKWDu+DfHybfECgYBbSLo1WiBwgN4nHqZ3E48jgA6le5azLeKOTTpuKKwNFMIhEkj//t7MYn+jhLL0Mf3PSwZU50Vidc1To1IHkbFSGBGIFHFFEzl8QnXEZS4hr/y3o/teezj0c6HAn8nlDRUzRVBEDXWMdV6kCcGpCccTIrqHzpqTY0vV0UkOTQFnDQKBgAxSEhm/gtCYJIMCBe+KBJT9uECV5xDQopTTjsGOkd4306EN2dyPOIlAfwM6K/0qWisa0Ei5i8TbRRuBeTTdLEYLqXCJ7fj5tdD1begBdSVtHQ2WHqzPJSuImTkFi9NXxd1XUyZFM3y6YQvlssSuL7QSxUIEtZHnrJTt3QDd10dj",
|
"privateKey": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tDQpNSUlFdndJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLa3dnZ1NsQWdFQUFvSUJBUURseTkzQUpRMkdXblhDDQpYWlBLNHlDWVBjYmlLcDY4OE1qVm9COFVROU9PWjdhdmRxOG1tK0J5Z0hUODVsRVJrK0lDTWR2NmhMRXZ2dUZqDQppREY0Yzg5NlFPZThpOW1tOWJWeVpSZVZtVi84SGRJR1F0eHNxWURQZHVIZEwzcXlLd29tQVNhUDB2VEtNS3ljDQo0L2VJUGdmclhSQkdUSmluZEVNR09RQlQwY3FuSm13Y2QvcHlXK0l4cGh4MDZSZVE1MllXa3NCMWJmYkxrMjB0DQp4Q2RmeHBQbmQzdmNOUy9LRHRlOXhRVnlkNkp5Skx3K0RiWXk1RU8zWFR3RDhTcFNtd2FBbUhiQk0xd1l4cDlqDQo2UUs5YytCelEzUE8wNWxTbzNWM0VsekdZNThkS3FzZm82MkJWTG5wUllwSGZhK3lndUFxWnhMRU54bHBtZkpEDQphRU9KbUU1cEFnTUJBQUVDZ2dFQUxpTCtSS09yMFh1OEJPZ1EwajFEd0EwM0x4VnJoWGU2ZXRtSkkrSnlTVGNkDQpnS0VOald6aVpWclJJaTJEdlVtNXFNTWw3V2hTd3NsS0sxZWV4eFpKWTd4QVNxU3hjRW9Jd2d6MTdUMDcvanhtDQpmSWRVQmlVS0RaMUt2OFBXbUlyM29LVytma1hXaS9tMXpsSWUwcVhScFRtc0dORXNIUUxFcWkwcm1haVhUWE9SDQovMkxkd2k2a1pSM3NXRng5N1lTNE14L3B1ZUdKVFhFYWk2QVZFWnpONUdvZzZ4RDhIWFIxUnZxK2hoZCtNb2NHDQpmblU0SGdpbEtSZm9KbFdkOUZPc2NnU3VmS0cwTDNWaU80ZlNLVTQ2bDVhdWxsRFlVazVFQ01XaXd1S1NxU0U3DQpxRDQ1akkzbWJPcmU3UzR1M1MzVFdkRDNsendpWEw0OUxkd0tsRUM0bVFLQmdRRDBzTHIwR0g0V3IrUVgyeEpFDQp1QS9DYjhRVzQxbDhpU0NCVFJaWlIvc0pPZCtvM3JiY1ZpZGx6Ty9FYlpibFhHNFpQRG1SamdCQ0dLSVA1RVppDQowRHNMK1d2MzJXT280NExweEpHaHFFeGJtMEgxaVoxelo5N2wwUDhmdkloSEU0MmdtYUxUb09JR0RoUFNYR3Z2DQp6bHFPSGJHYnE0anNFUmMxanAxYmVqNXE2d0tCZ1FEd2F1ZUljNHBSY2hIOThRWWlkY3lyOFZ3ZzlLaGJuZllYDQp5M1c0UlBsWnRCZEYzNGlKYWlvK0FTenVnby96eTFSVGNWcnNDc2tZV1h5S0RVUXoxeXUwaUNuZytmRENVblRtDQpYR21Fb0VHTmhrNHZUSk90N2hCYXYxL0phL2RVaXBHZjZtWFV1YW53SjBlKzEvRXQvQjBhaDVYMVVtNUF5TlpJDQpNK1N5UnozdSt3S0JnUUNqdnRVTlhvcWFnaENCQ21CNlRqWjFwcmV4bldrWUZ1Z0N2MlNTVU1JazFXN2dJbEo2DQp0c2pjcmoxUjFRaWk2cXpmQkZkK0dXb0EwVjA2aDBlMi9xUlZDZy8vcDZHeXRyVzMzSXljZ3ZTK1pQTEo3dExJDQpGUjJyNjZXZlJscG9QaVNMOGVSdC9QN2trRzBoWENuN0s3dWIyVEV1L0thL1cxeU53YWQ2UFI4aUN3S0JnUUM4DQpYY1pTcnRRc3hBYzh3OTllbUpWb0VvOXdjc0NHSjlsdEEwaVV1OVh5WnB2bGJ5SjNKK3M0OFlyV3hRMHNvcDdMDQpVZ0UrOTZSZm81MWtQTWkzSlZ0azgxcDhudGY0S01yV3dva2FGTVhIc1BjSk1DSjFJQlZJUkxFMEM1ZVpjWWh2DQpseU41N0k0dFQxbHpPWllKeFlLNENvdC96cm43b0YvajZtVEJHZmg0aVFLQmdRQ2lKTVV4UnowMS9jekgvWFNYDQpnbzNkVmJIUTRGRU91ZlduRTNFYjkzUzhyMC9lcTFSTTExOHJiMFRxenVpYWRXMnhZRFU0bnVjV1FscmxtcTBkDQpGWS9tK0h5OTdwcXlrNmptb1U1SS9EK3NzQklvWUhXTG5IOS94ZnZERWsySkdTSlNIdHp1MEQ0RURDL3JnUTQ5DQpNYllzTzVvVXJGOHRQbGhqNXZ6YmYzR0tMQT09DQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tDQo=",
|
||||||
"publicKeyOld": "BgIAAACkAABSU0ExAAgAAAEAAQD/NVqekFNi8X3p6Bvdlaxm0GGuggW5kKfVEQzPGuOkGVrz6DrOMNR+k7Pq8tONY+1NHgS6Z+v3959em78qclVDuQX77Tkml0xMHAQHN4sAHF9iQJS8gOBUKSVKaHD7Z8YXch6F212YSUSc8QphpDSHWVShU7rcUeLQsd/0pkflh5+um4YKEZhm4Mou3vstp5p12NeffyK1WFZF7q4jB7jclAslYKQsP82YY3DcRwu5Tl/+W0ifVcXze0mI7v1reJ12pKn8ifRiq+0q5oJST3TRSrvmjLg9Gt3ozhVIt2HUi3La7Qh40YOAUXm0g/hUq2BepeOp1C7WSvaOFHXe6Hqq",
|
"publicKeyOld": "BgIAAACkAABSU0ExAAgAAAEAAQBpTpiJQ2hD8plpGTfEEmcq4IKyr31HikXpuVSBraMfqyodn2PGXBJ3daNSmdPOc0Nz4HO9Auljn8YYXDPBdpiABptSKvEDPF23Q+Qytg0+vCRyondyBcW91w7KLzXce3fnk8ZfJ8QtbZPL9m11wJIWZueQF+l0HKYx4lty+nccbCanytFTADkGQ3SnmExGEF3rBz6I9+OcrDDK9NKPJgEmCiuyei/d4XbPgKls3EIG0h38X5mVF2VytfWm2Yu850B6z3N4MYhj4b4vsYT62zEC4pMRUeb8dIBy4Jsmr3avtmeO00MUH6DVyPC8nirixj2YIOPKk13CdVqGDSXA3cvl",
|
||||||
"modulusOld": "qnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/w==",
|
"modulusOld": "E5CBDDC0250D865A75C25D93CAE320983DC6E22A9EBCF0C8D5A01F1443D38E67B6AF76AF269BE0728074FCE6511193E20231DBFA84B12FBEE16388317873CF7A40E7BC8BD9A6F5B572651795995FFC1DD20642DC6CA980CF76E1DD2F7AB22B0A2601268FD2F4CA30AC9CE3F7883E07EB5D10464C98A7744306390053D1CAA7266C1C77FA725BE231A61C74E91790E7661692C0756DF6CB936D2DC4275FC693E7777BDC352FCA0ED7BDC5057277A27224BC3E0DB632E443B75D3C03F12A529B06809876C1335C18C69F63E902BD73E0734373CED39952A37577125CC6639F1D2AAB1FA3AD8154B9E9458A477DAFB282E02A6712C437196999F243684389984E69",
|
||||||
"exponentOld": "AQAB",
|
"exponentOld": "65537",
|
||||||
"privateKeyOld": "MIIEowIBAAKCAQEAqnro3nUUjvZK1i7UqeOlXmCrVPiDtHlRgIPReAjt2nKL1GG3SBXO6N0aPbiM5rtK0XRPUoLmKu2rYvSJ/Kmkdp14a/3uiEl788VVn0hb/l9OuQtH3HBjmM0/LKRgJQuU3LgHI67uRVZYtSJ/n9fYdZqnLfveLsrgZpgRCoabrp+H5Uem9N+x0OJR3LpToVRZhzSkYQrxnERJmF3bhR5yF8Zn+3BoSiUpVOCAvJRAYl8cAIs3BwQcTEyXJjnt+wW5Q1VyKr+bXp/39+tnugQeTe1jjdPy6rOTftQwzjro81oZpOMazwwR1aeQuQWCrmHQZqyV3Rvo6X3xYlOQnlo1/wIDAQABAoIBAQCKtUSBs8tNYrGTQTlBHXrwpkDg+u7WSZt5sEcfnkxA39BLtlHU8gGO0E9Ihr8GAL+oWjUsEltJ9GTtN8CJ9lFdPVS8sTiCZR/YQOggmFRZTJyVzMrkXgF7Uwwiu3+KxLiTOZx9eRhfDBlTD8W9fXaegX2i2Xp2ohUhBHthEBLdaZTWFi5Sid/Y0dDzBeP6UIJorZ5D+1ybaeIVHjndpwNsIEUGUxPFLrkeiU8Rm4MJ9ahxfywcP7DjQoPGY9Ge5cBhpxfzERWf732wUD6o3+L9tvOBU00CLVjULbGZKTVE2FJMyXK9jr6Zor9Mkhomp6/8Agkr9rp+TPyelFGYEz8hAoGBAOEc09CrL3eYBkhNEcaMQzxBLvOGpg8kaDX5SaArHfl9+U9yzRqss4ARECanp9HuHfjMQo7iejao0ngDjL7BNMSaH74QlSsPOY2iOm8Qvx8/zb7g4h9r1zLjFZb3mpSA4snRZvvdiZ9ugbuVPmhXnDzRRMg45MibJeeOTJNylofRAoGBAMHfF/WutqKDoX25qZo9m74W4bttOj6oIDk1N4/c6M1Z1v/aptYSE06bkWngj9P46kqjaay4hgMtzyGruc5aojPx5MHHf5bo14+Jv4NzYtR2llrUxO+UJX7aCfUYXI7RC93GUmhpeQ414j7SNAXec58d7e+ETw+6cHiAWO4uOSTPAoGATPq5qDLR4Zi4FUNdn8LZPyKfNqHF6YmupT5hIgd8kZO1jKiaYNPL8jBjkIRmjBBcaXcYD5p85nImvumf2J9jNxPpZOpwyC/Fo5xlVROp97qu1eY7DTmodntXJ6/2SXAlnZQhHmHsrPtyG752f+HtyJJbbgiem8cKWDu+DfHybfECgYBbSLo1WiBwgN4nHqZ3E48jgA6le5azLeKOTTpuKKwNFMIhEkj//t7MYn+jhLL0Mf3PSwZU50Vidc1To1IHkbFSGBGIFHFFEzl8QnXEZS4hr/y3o/teezj0c6HAn8nlDRUzRVBEDXWMdV6kCcGpCccTIrqHzpqTY0vV0UkOTQFnDQKBgAxSEhm/gtCYJIMCBe+KBJT9uECV5xDQopTTjsGOkd4306EN2dyPOIlAfwM6K/0qWisa0Ei5i8TbRRuBeTTdLEYLqXCJ7fj5tdD1begBdSVtHQ2WHqzPJSuImTkFi9NXxd1XUyZFM3y6YQvlssSuL7QSxUIEtZHnrJTt3QDd10dj",
|
"privateKeyOld": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tDQpNSUlFdndJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0JLa3dnZ1NsQWdFQUFvSUJBUURseTkzQUpRMkdXblhDDQpYWlBLNHlDWVBjYmlLcDY4OE1qVm9COFVROU9PWjdhdmRxOG1tK0J5Z0hUODVsRVJrK0lDTWR2NmhMRXZ2dUZqDQppREY0Yzg5NlFPZThpOW1tOWJWeVpSZVZtVi84SGRJR1F0eHNxWURQZHVIZEwzcXlLd29tQVNhUDB2VEtNS3ljDQo0L2VJUGdmclhSQkdUSmluZEVNR09RQlQwY3FuSm13Y2QvcHlXK0l4cGh4MDZSZVE1MllXa3NCMWJmYkxrMjB0DQp4Q2RmeHBQbmQzdmNOUy9LRHRlOXhRVnlkNkp5Skx3K0RiWXk1RU8zWFR3RDhTcFNtd2FBbUhiQk0xd1l4cDlqDQo2UUs5YytCelEzUE8wNWxTbzNWM0VsekdZNThkS3FzZm82MkJWTG5wUllwSGZhK3lndUFxWnhMRU54bHBtZkpEDQphRU9KbUU1cEFnTUJBQUVDZ2dFQUxpTCtSS09yMFh1OEJPZ1EwajFEd0EwM0x4VnJoWGU2ZXRtSkkrSnlTVGNkDQpnS0VOald6aVpWclJJaTJEdlVtNXFNTWw3V2hTd3NsS0sxZWV4eFpKWTd4QVNxU3hjRW9Jd2d6MTdUMDcvanhtDQpmSWRVQmlVS0RaMUt2OFBXbUlyM29LVytma1hXaS9tMXpsSWUwcVhScFRtc0dORXNIUUxFcWkwcm1haVhUWE9SDQovMkxkd2k2a1pSM3NXRng5N1lTNE14L3B1ZUdKVFhFYWk2QVZFWnpONUdvZzZ4RDhIWFIxUnZxK2hoZCtNb2NHDQpmblU0SGdpbEtSZm9KbFdkOUZPc2NnU3VmS0cwTDNWaU80ZlNLVTQ2bDVhdWxsRFlVazVFQ01XaXd1S1NxU0U3DQpxRDQ1akkzbWJPcmU3UzR1M1MzVFdkRDNsendpWEw0OUxkd0tsRUM0bVFLQmdRRDBzTHIwR0g0V3IrUVgyeEpFDQp1QS9DYjhRVzQxbDhpU0NCVFJaWlIvc0pPZCtvM3JiY1ZpZGx6Ty9FYlpibFhHNFpQRG1SamdCQ0dLSVA1RVppDQowRHNMK1d2MzJXT280NExweEpHaHFFeGJtMEgxaVoxelo5N2wwUDhmdkloSEU0MmdtYUxUb09JR0RoUFNYR3Z2DQp6bHFPSGJHYnE0anNFUmMxanAxYmVqNXE2d0tCZ1FEd2F1ZUljNHBSY2hIOThRWWlkY3lyOFZ3ZzlLaGJuZllYDQp5M1c0UlBsWnRCZEYzNGlKYWlvK0FTenVnby96eTFSVGNWcnNDc2tZV1h5S0RVUXoxeXUwaUNuZytmRENVblRtDQpYR21Fb0VHTmhrNHZUSk90N2hCYXYxL0phL2RVaXBHZjZtWFV1YW53SjBlKzEvRXQvQjBhaDVYMVVtNUF5TlpJDQpNK1N5UnozdSt3S0JnUUNqdnRVTlhvcWFnaENCQ21CNlRqWjFwcmV4bldrWUZ1Z0N2MlNTVU1JazFXN2dJbEo2DQp0c2pjcmoxUjFRaWk2cXpmQkZkK0dXb0EwVjA2aDBlMi9xUlZDZy8vcDZHeXRyVzMzSXljZ3ZTK1pQTEo3dExJDQpGUjJyNjZXZlJscG9QaVNMOGVSdC9QN2trRzBoWENuN0s3dWIyVEV1L0thL1cxeU53YWQ2UFI4aUN3S0JnUUM4DQpYY1pTcnRRc3hBYzh3OTllbUpWb0VvOXdjc0NHSjlsdEEwaVV1OVh5WnB2bGJ5SjNKK3M0OFlyV3hRMHNvcDdMDQpVZ0UrOTZSZm81MWtQTWkzSlZ0azgxcDhudGY0S01yV3dva2FGTVhIc1BjSk1DSjFJQlZJUkxFMEM1ZVpjWWh2DQpseU41N0k0dFQxbHpPWllKeFlLNENvdC96cm43b0YvajZtVEJHZmg0aVFLQmdRQ2lKTVV4UnowMS9jekgvWFNYDQpnbzNkVmJIUTRGRU91ZlduRTNFYjkzUzhyMC9lcTFSTTExOHJiMFRxenVpYWRXMnhZRFU0bnVjV1FscmxtcTBkDQpGWS9tK0h5OTdwcXlrNmptb1U1SS9EK3NzQklvWUhXTG5IOS94ZnZERWsySkdTSlNIdHp1MEQ0RURDL3JnUTQ5DQpNYllzTzVvVXJGOHRQbGhqNXZ6YmYzR0tMQT09DQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tDQo=",
|
||||||
"refreshLockInterval": "10m",
|
"refreshLockInterval": "10m",
|
||||||
"dummy" : {
|
"dummy" : {
|
||||||
"enable": true,
|
"enable": false,
|
||||||
"sampleFilePath": ""
|
"sampleFilePath": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -137,7 +142,7 @@
|
|||||||
"allow": true,
|
"allow": true,
|
||||||
"blockPrivateIP": true,
|
"blockPrivateIP": true,
|
||||||
"proxyUrl": "",
|
"proxyUrl": "",
|
||||||
"proxyAuth": {
|
"proxyUser": {
|
||||||
"username": "",
|
"username": "",
|
||||||
"password": ""
|
"password": ""
|
||||||
},
|
},
|
||||||
@ -170,11 +175,11 @@
|
|||||||
"openProtectedFile": true,
|
"openProtectedFile": true,
|
||||||
"isAnonymousSupport": true,
|
"isAnonymousSupport": true,
|
||||||
"editorDataStorage": "editorDataMemory",
|
"editorDataStorage": "editorDataMemory",
|
||||||
|
"editorStatStorage": "",
|
||||||
"assemblyFormatAsOrigin": true,
|
"assemblyFormatAsOrigin": true,
|
||||||
"newFileTemplate" : "../../document-templates/new",
|
"newFileTemplate" : "../../document-templates/new",
|
||||||
"downloadFileAllowExt": ["pdf", "xlsx"],
|
"downloadFileAllowExt": ["pdf", "xlsx"],
|
||||||
"tokenRequiredParams": true,
|
"tokenRequiredParams": true,
|
||||||
"allowPrivateIPAddressForSignedRequests": true,
|
|
||||||
"forceSaveUsingButtonWithoutChanges": false
|
"forceSaveUsingButtonWithoutChanges": false
|
||||||
},
|
},
|
||||||
"requestDefaults": {
|
"requestDefaults": {
|
||||||
@ -235,7 +240,8 @@
|
|||||||
"pool": {
|
"pool": {
|
||||||
"idleTimeoutMillis": 30000
|
"idleTimeoutMillis": 30000
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"mysqlExtraOptions": {}
|
||||||
},
|
},
|
||||||
"redis": {
|
"redis": {
|
||||||
"name": "redis",
|
"name": "redis",
|
||||||
@ -244,10 +250,14 @@
|
|||||||
"port": 6379,
|
"port": 6379,
|
||||||
"options": {},
|
"options": {},
|
||||||
"optionsCluster": {},
|
"optionsCluster": {},
|
||||||
"iooptions": {},
|
"iooptions": {
|
||||||
|
"lazyConnect": true
|
||||||
|
},
|
||||||
"iooptionsClusterNodes": [
|
"iooptionsClusterNodes": [
|
||||||
],
|
],
|
||||||
"iooptionsClusterOptions": {}
|
"iooptionsClusterOptions": {
|
||||||
|
"lazyConnect": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"pubsub": {
|
"pubsub": {
|
||||||
"maxChanges": 1000
|
"maxChanges": 1000
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const config = require("config");
|
||||||
const constants = require('./constants');
|
const constants = require('./constants');
|
||||||
|
|
||||||
function InputCommand(data, copyExplicit) {
|
function InputCommand(data, copyExplicit) {
|
||||||
@ -108,6 +109,7 @@ function InputCommand(data, copyExplicit) {
|
|||||||
this['status_info_in'] = data['status_info_in'];
|
this['status_info_in'] = data['status_info_in'];
|
||||||
this['attempt'] = data['attempt'];
|
this['attempt'] = data['attempt'];
|
||||||
this['convertToOrigin'] = data['convertToOrigin'];
|
this['convertToOrigin'] = data['convertToOrigin'];
|
||||||
|
this['isSaveAs'] = data['isSaveAs'];
|
||||||
if (copyExplicit) {
|
if (copyExplicit) {
|
||||||
this['withAuthorization'] = data['withAuthorization'];
|
this['withAuthorization'] = data['withAuthorization'];
|
||||||
this['externalChangeInfo'] = data['externalChangeInfo'];
|
this['externalChangeInfo'] = data['externalChangeInfo'];
|
||||||
@ -171,6 +173,7 @@ function InputCommand(data, copyExplicit) {
|
|||||||
this['attempt'] = undefined;
|
this['attempt'] = undefined;
|
||||||
this['convertToOrigin'] = undefined;
|
this['convertToOrigin'] = undefined;
|
||||||
this['originformat'] = undefined;
|
this['originformat'] = undefined;
|
||||||
|
this['isSaveAs'] = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InputCommand.prototype = {
|
InputCommand.prototype = {
|
||||||
@ -363,8 +366,12 @@ InputCommand.prototype = {
|
|||||||
getJsonParams: function() {
|
getJsonParams: function() {
|
||||||
return this['jsonparams'];
|
return this['jsonparams'];
|
||||||
},
|
},
|
||||||
setJsonParams: function(data) {
|
appendJsonParams: function (data) {
|
||||||
this['jsonparams'] = data;
|
if (this['jsonparams']) {
|
||||||
|
config.util.extendDeep(this['jsonparams'], data);
|
||||||
|
} else {
|
||||||
|
this['jsonparams'] = data;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
getLCID: function() {
|
getLCID: function() {
|
||||||
return this['lcid'];
|
return this['lcid'];
|
||||||
@ -503,6 +510,12 @@ InputCommand.prototype = {
|
|||||||
},
|
},
|
||||||
setConvertToOrigin: function(data) {
|
setConvertToOrigin: function(data) {
|
||||||
this['convertToOrigin'] = data;
|
this['convertToOrigin'] = data;
|
||||||
|
},
|
||||||
|
getIsSaveAs: function() {
|
||||||
|
return this['isSaveAs'];
|
||||||
|
},
|
||||||
|
setIsSaveAs: function(data) {
|
||||||
|
this['isSaveAs'] = data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -50,7 +50,8 @@ exports.VIEWER_ONLY = /^(?:(pdf|djvu|xps|oxps))$/;
|
|||||||
exports.DEFAULT_DOC_ID = 'docId';
|
exports.DEFAULT_DOC_ID = 'docId';
|
||||||
exports.DEFAULT_USER_ID = 'userId';
|
exports.DEFAULT_USER_ID = 'userId';
|
||||||
exports.ALLOWED_PROTO = /^https?$/i;
|
exports.ALLOWED_PROTO = /^https?$/i;
|
||||||
exports.SHARED_KEY_NAME = 'WOPISrc';
|
exports.SHARD_KEY_WOPI_NAME = 'WOPISrc';
|
||||||
|
exports.SHARD_KEY_API_NAME = 'shardkey';
|
||||||
|
|
||||||
exports.RIGHTS = {
|
exports.RIGHTS = {
|
||||||
None : 0,
|
None : 0,
|
||||||
@ -282,6 +283,7 @@ exports.FILE_STATUS_UPDATE_VERSION = 'updateversion';
|
|||||||
exports.ACTIVEMQ_QUEUE_PREFIX = 'queue://';
|
exports.ACTIVEMQ_QUEUE_PREFIX = 'queue://';
|
||||||
exports.ACTIVEMQ_TOPIC_PREFIX = 'topic://';
|
exports.ACTIVEMQ_TOPIC_PREFIX = 'topic://';
|
||||||
|
|
||||||
|
exports.TEMPLATES_DEFAULT_LOCALE = 'en-US';
|
||||||
exports.TEMPLATES_FOLDER_LOCALE_COLLISON_MAP = {
|
exports.TEMPLATES_FOLDER_LOCALE_COLLISON_MAP = {
|
||||||
'en': 'en-US',
|
'en': 'en-US',
|
||||||
'pt': 'pt-BR',
|
'pt': 'pt-BR',
|
||||||
@ -289,11 +291,6 @@ exports.TEMPLATES_FOLDER_LOCALE_COLLISON_MAP = {
|
|||||||
'pt-PT': 'pt-PT',
|
'pt-PT': 'pt-PT',
|
||||||
'zh-TW': 'zh-TW'
|
'zh-TW': 'zh-TW'
|
||||||
};
|
};
|
||||||
exports.SUPPORTED_TEMPLATES_EXTENSIONS = {
|
|
||||||
'Word': ['docx', 'docxf'],
|
|
||||||
'Excel': ['xlsx'],
|
|
||||||
'PowerPoint': ['pptx']
|
|
||||||
};
|
|
||||||
exports.TABLE_RESULT_SCHEMA = [
|
exports.TABLE_RESULT_SCHEMA = [
|
||||||
'tenant',
|
'tenant',
|
||||||
'id',
|
'id',
|
||||||
|
|||||||
@ -41,11 +41,12 @@ function Context(){
|
|||||||
this.logger = logger.getLogger('nodeJS');
|
this.logger = logger.getLogger('nodeJS');
|
||||||
this.initDefault();
|
this.initDefault();
|
||||||
}
|
}
|
||||||
Context.prototype.init = function(tenant, docId, userId, opt_shardKey) {
|
Context.prototype.init = function(tenant, docId, userId, opt_shardKey, opt_WopiSrc) {
|
||||||
this.setTenant(tenant);
|
this.setTenant(tenant);
|
||||||
this.setDocId(docId);
|
this.setDocId(docId);
|
||||||
this.setUserId(userId);
|
this.setUserId(userId);
|
||||||
this.setShardKey(opt_shardKey);
|
this.setShardKey(opt_shardKey);
|
||||||
|
this.setWopiSrc(opt_WopiSrc);
|
||||||
|
|
||||||
this.config = null;
|
this.config = null;
|
||||||
this.secret = null;
|
this.secret = null;
|
||||||
@ -65,21 +66,23 @@ Context.prototype.initFromConnection = function(conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let userId = conn.user?.id;
|
let userId = conn.user?.id;
|
||||||
let shardKey = utils.getShardByConnection(this, conn);
|
let shardKey = utils.getShardKeyByConnection(this, conn);
|
||||||
this.init(tenant, docId || this.docId, userId || this.userId, shardKey);
|
let wopiSrc = utils.getWopiSrcByConnection(this, conn);
|
||||||
|
this.init(tenant, docId || this.docId, userId || this.userId, shardKey, wopiSrc);
|
||||||
};
|
};
|
||||||
Context.prototype.initFromRequest = function(req) {
|
Context.prototype.initFromRequest = function(req) {
|
||||||
let tenant = tenantManager.getTenantByRequest(this, req);
|
let tenant = tenantManager.getTenantByRequest(this, req);
|
||||||
let shardKey = utils.getShardKeyByRequest(this, req);
|
let shardKey = utils.getShardKeyByRequest(this, req);
|
||||||
this.init(tenant, this.docId, this.userId, shardKey);
|
let wopiSrc = utils.getWopiSrcByRequest(this, req);
|
||||||
|
this.init(tenant, this.docId, this.userId, shardKey, wopiSrc);
|
||||||
};
|
};
|
||||||
Context.prototype.initFromTaskQueueData = function(task) {
|
Context.prototype.initFromTaskQueueData = function(task) {
|
||||||
let ctx = task.getCtx();
|
let ctx = task.getCtx();
|
||||||
this.init(ctx.tenant, ctx.docId, ctx.userId, ctx.shardKey);
|
this.init(ctx.tenant, ctx.docId, ctx.userId, ctx.shardKey, ctx.wopiSrc);
|
||||||
};
|
};
|
||||||
Context.prototype.initFromPubSub = function(data) {
|
Context.prototype.initFromPubSub = function(data) {
|
||||||
let ctx = data.ctx;
|
let ctx = data.ctx;
|
||||||
this.init(ctx.tenant, ctx.docId, ctx.userId, ctx.shardKey);
|
this.init(ctx.tenant, ctx.docId, ctx.userId, ctx.shardKey, ctx.wopiSrc);
|
||||||
};
|
};
|
||||||
Context.prototype.initTenantCache = async function() {
|
Context.prototype.initTenantCache = async function() {
|
||||||
this.config = await tenantManager.getTenantConfig(this);
|
this.config = await tenantManager.getTenantConfig(this);
|
||||||
@ -101,12 +104,16 @@ Context.prototype.setUserId = function(userId) {
|
|||||||
Context.prototype.setShardKey = function(shardKey) {
|
Context.prototype.setShardKey = function(shardKey) {
|
||||||
this.shardKey = shardKey;
|
this.shardKey = shardKey;
|
||||||
};
|
};
|
||||||
|
Context.prototype.setWopiSrc = function(wopiSrc) {
|
||||||
|
this.wopiSrc = wopiSrc;
|
||||||
|
};
|
||||||
Context.prototype.toJSON = function() {
|
Context.prototype.toJSON = function() {
|
||||||
return {
|
return {
|
||||||
tenant: this.tenant,
|
tenant: this.tenant,
|
||||||
docId: this.docId,
|
docId: this.docId,
|
||||||
userId: this.userId,
|
userId: this.userId,
|
||||||
shardKey: this.shardKey
|
shardKey: this.shardKey,
|
||||||
|
wopiSrc: this.wopiSrc
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Context.prototype.getCfg = function(property, defaultValue) {
|
Context.prototype.getCfg = function(property, defaultValue) {
|
||||||
|
|||||||
@ -31,102 +31,185 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
const os = require('os');
|
||||||
|
const cluster = require('cluster');
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
var utils = require('./utils');
|
var utils = require('./utils');
|
||||||
|
|
||||||
var storage = require('./' + config.get('storage.name'));
|
const cfgCacheStorage = config.get('storage');
|
||||||
var tenantManager = require('./tenantManager');
|
const cfgPersistentStorage = utils.deepMergeObjects({}, cfgCacheStorage, config.get('persistentStorage'));
|
||||||
|
|
||||||
const cfgCacheFolderName = config.get('storage.cacheFolderName');
|
const cacheStorage = require('./' + cfgCacheStorage.name);
|
||||||
|
const persistentStorage = require('./' + cfgPersistentStorage.name);
|
||||||
|
const tenantManager = require('./tenantManager');
|
||||||
|
|
||||||
|
const HEALTH_CHECK_KEY_MAX = 10000;
|
||||||
|
|
||||||
function getStoragePath(ctx, strPath, opt_specialDir) {
|
function getStoragePath(ctx, strPath, opt_specialDir) {
|
||||||
opt_specialDir = opt_specialDir || cfgCacheFolderName;
|
opt_specialDir = opt_specialDir || cfgCacheStorage.cacheFolderName;
|
||||||
return opt_specialDir + '/' + tenantManager.getTenantPathPrefix(ctx) + strPath.replace(/\\/g, '/')
|
return opt_specialDir + '/' + tenantManager.getTenantPathPrefix(ctx) + strPath.replace(/\\/g, '/');
|
||||||
|
}
|
||||||
|
function getStorage(opt_specialDir) {
|
||||||
|
return opt_specialDir ? persistentStorage : cacheStorage;
|
||||||
|
}
|
||||||
|
function getStorageCfg(ctx, opt_specialDir) {
|
||||||
|
return opt_specialDir ? cfgPersistentStorage : cfgCacheStorage;
|
||||||
|
}
|
||||||
|
function canCopyBetweenStorage(storageCfgSrc, storageCfgDst) {
|
||||||
|
return storageCfgSrc.name === storageCfgDst.name && storageCfgSrc.endpoint === storageCfgDst.endpoint;
|
||||||
|
}
|
||||||
|
function isDiffrentPersistentStorage() {
|
||||||
|
return !canCopyBetweenStorage(cacheStorage, cfgPersistentStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.headObject = function(ctx, strPath, opt_specialDir) {
|
async function headObject(ctx, strPath, opt_specialDir) {
|
||||||
return storage.headObject(getStoragePath(ctx, strPath, opt_specialDir));
|
let storage = getStorage(opt_specialDir);
|
||||||
};
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
exports.getObject = function(ctx, strPath, opt_specialDir) {
|
return await storage.headObject(storageCfg, getStoragePath(storageCfg, strPath, opt_specialDir));
|
||||||
return storage.getObject(getStoragePath(ctx, strPath, opt_specialDir));
|
}
|
||||||
};
|
async function getObject(ctx, strPath, opt_specialDir) {
|
||||||
exports.createReadStream = function(ctx, strPath, opt_specialDir) {
|
let storage = getStorage(opt_specialDir);
|
||||||
return storage.createReadStream(getStoragePath(ctx, strPath, opt_specialDir));
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
};
|
return await storage.getObject(storageCfg, getStoragePath(storageCfg, strPath, opt_specialDir));
|
||||||
exports.putObject = function(ctx, strPath, buffer, contentLength, opt_specialDir) {
|
}
|
||||||
return storage.putObject(getStoragePath(ctx, strPath, opt_specialDir), buffer, contentLength);
|
async function createReadStream(ctx, strPath, opt_specialDir) {
|
||||||
};
|
let storage = getStorage(opt_specialDir);
|
||||||
exports.uploadObject = function(ctx, strPath, filePath, opt_specialDir) {
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
return storage.uploadObject(getStoragePath(ctx, strPath, opt_specialDir), filePath);
|
return await storage.createReadStream(storageCfg, getStoragePath(storageCfg, strPath, opt_specialDir));
|
||||||
};
|
}
|
||||||
exports.copyObject = function(ctx, sourceKey, destinationKey, opt_specialDirSrc, opt_specialDirDst) {
|
async function putObject(ctx, strPath, buffer, contentLength, opt_specialDir) {
|
||||||
let storageSrc = getStoragePath(ctx, sourceKey, opt_specialDirSrc);
|
let storage = getStorage(opt_specialDir);
|
||||||
let storageDst = getStoragePath(ctx, destinationKey, opt_specialDirDst);
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
return storage.copyObject(storageSrc, storageDst);
|
return await storage.putObject(storageCfg, getStoragePath(ctx, strPath, opt_specialDir), buffer, contentLength);
|
||||||
};
|
}
|
||||||
exports.copyPath = function(ctx, sourcePath, destinationPath, opt_specialDirSrc, opt_specialDirDst) {
|
async function uploadObject(ctx, strPath, filePath, opt_specialDir) {
|
||||||
let storageSrc = getStoragePath(ctx, sourcePath, opt_specialDirSrc);
|
let storage = getStorage(opt_specialDir);
|
||||||
let storageDst = getStoragePath(ctx, destinationPath, opt_specialDirDst);
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
return storage.listObjects(storageSrc).then(function(list) {
|
return await storage.uploadObject(storageCfg, getStoragePath(ctx, strPath, opt_specialDir), filePath);
|
||||||
return Promise.all(list.map(function(curValue) {
|
}
|
||||||
return storage.copyObject(curValue, storageDst + '/' + exports.getRelativePath(storageSrc, curValue));
|
async function copyObject(ctx, sourceKey, destinationKey, opt_specialDirSrc, opt_specialDirDst) {
|
||||||
}));
|
let storageSrc = getStorage(opt_specialDirSrc);
|
||||||
});
|
let storagePathSrc = getStoragePath(ctx, sourceKey, opt_specialDirSrc);
|
||||||
};
|
let storagePathDst = getStoragePath(ctx, destinationKey, opt_specialDirDst);
|
||||||
exports.listObjects = function(ctx, strPath, opt_specialDir) {
|
let storageCfgSrc = getStorageCfg(ctx, opt_specialDirSrc);
|
||||||
|
let storageCfgDst = getStorageCfg(ctx, opt_specialDirDst);
|
||||||
|
if (canCopyBetweenStorage(storageCfgSrc, storageCfgDst)){
|
||||||
|
return await storageSrc.copyObject(storageCfgSrc, storageCfgDst, storagePathSrc, storagePathDst);
|
||||||
|
} else {
|
||||||
|
let storageDst = getStorage(opt_specialDirDst);
|
||||||
|
//todo stream
|
||||||
|
let buffer = await storageSrc.getObject(storageCfgSrc, storagePathSrc);
|
||||||
|
return await storageDst.putObject(storageCfgDst, storagePathDst, buffer, buffer.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function copyPath(ctx, sourcePath, destinationPath, opt_specialDirSrc, opt_specialDirDst) {
|
||||||
|
let list = await listObjects(ctx, sourcePath, opt_specialDirSrc);
|
||||||
|
await Promise.all(list.map(function(curValue) {
|
||||||
|
return copyObject(ctx, curValue, destinationPath + '/' + getRelativePath(sourcePath, curValue), opt_specialDirSrc, opt_specialDirDst);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
async function listObjects(ctx, strPath, opt_specialDir) {
|
||||||
|
let storage = getStorage(opt_specialDir);
|
||||||
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
let prefix = getStoragePath(ctx, "", opt_specialDir);
|
let prefix = getStoragePath(ctx, "", opt_specialDir);
|
||||||
return storage.listObjects(getStoragePath(ctx, strPath, opt_specialDir)).then(function(list) {
|
try {
|
||||||
|
let list = await storage.listObjects(storageCfg, getStoragePath(ctx, strPath, opt_specialDir));
|
||||||
return list.map((currentValue) => {
|
return list.map((currentValue) => {
|
||||||
return currentValue.substring(prefix.length);
|
return currentValue.substring(prefix.length);
|
||||||
});
|
});
|
||||||
}).catch(function(e) {
|
} catch (e) {
|
||||||
ctx.logger.error('storage.listObjects: %s', e.stack);
|
ctx.logger.error('storage.listObjects: %s', e.stack);
|
||||||
return [];
|
return [];
|
||||||
});
|
}
|
||||||
};
|
}
|
||||||
exports.deleteObject = function(ctx, strPath, opt_specialDir) {
|
async function deleteObject(ctx, strPath, opt_specialDir) {
|
||||||
return storage.deleteObject(getStoragePath(ctx, strPath, opt_specialDir));
|
let storage = getStorage(opt_specialDir);
|
||||||
};
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
exports.deletePath = function(ctx, strPath, opt_specialDir) {
|
return await storage.deleteObject(storageCfg, getStoragePath(ctx, strPath, opt_specialDir));
|
||||||
return storage.deletePath(getStoragePath(ctx, strPath, opt_specialDir));
|
}
|
||||||
};
|
async function deletePath(ctx, strPath, opt_specialDir) {
|
||||||
exports.getSignedUrl = function(ctx, baseUrl, strPath, urlType, optFilename, opt_creationDate, opt_specialDir) {
|
let storage = getStorage(opt_specialDir);
|
||||||
return storage.getSignedUrl(ctx, baseUrl, getStoragePath(ctx, strPath, opt_specialDir), urlType, optFilename, opt_creationDate);
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
};
|
return await storage.deletePath(storageCfg, getStoragePath(ctx, strPath, opt_specialDir));
|
||||||
exports.getSignedUrls = function(ctx, baseUrl, strPath, urlType, opt_creationDate, opt_specialDir) {
|
}
|
||||||
let storageSrc = getStoragePath(ctx, strPath, opt_specialDir);
|
async function getSignedUrl(ctx, baseUrl, strPath, urlType, optFilename, opt_creationDate, opt_specialDir) {
|
||||||
return storage.listObjects(storageSrc).then(function(list) {
|
let storage = getStorage(opt_specialDir);
|
||||||
return Promise.all(list.map(function(curValue) {
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
return storage.getSignedUrl(ctx, baseUrl, curValue, urlType, undefined, opt_creationDate);
|
return await storage.getSignedUrl(ctx, storageCfg, baseUrl, getStoragePath(ctx, strPath, opt_specialDir), urlType, optFilename, opt_creationDate);
|
||||||
})).then(function(urls) {
|
}
|
||||||
var outputMap = {};
|
async function getSignedUrls(ctx, baseUrl, strPath, urlType, opt_creationDate, opt_specialDir) {
|
||||||
for (var i = 0; i < list.length && i < urls.length; ++i) {
|
let storagePathSrc = getStoragePath(ctx, strPath, opt_specialDir);
|
||||||
outputMap[exports.getRelativePath(storageSrc, list[i])] = urls[i];
|
let storage = getStorage(opt_specialDir);
|
||||||
}
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
return outputMap;
|
let list = await storage.listObjects(storageCfg, storagePathSrc, storageCfg);
|
||||||
});
|
let urls = await Promise.all(list.map(function(curValue) {
|
||||||
});
|
return storage.getSignedUrl(ctx, storageCfg, baseUrl, curValue, urlType, undefined, opt_creationDate);
|
||||||
};
|
|
||||||
exports.getSignedUrlsArrayByArray = function(ctx, baseUrl, list, urlType, opt_specialDir) {
|
|
||||||
return Promise.all(list.map(function(curValue) {
|
|
||||||
let storageSrc = getStoragePath(ctx, curValue, opt_specialDir);
|
|
||||||
return storage.getSignedUrl(ctx, baseUrl, storageSrc, urlType, undefined);
|
|
||||||
}));
|
}));
|
||||||
};
|
let outputMap = {};
|
||||||
exports.getSignedUrlsByArray = function(ctx, baseUrl, list, optPath, urlType, opt_specialDir) {
|
for (let i = 0; i < list.length && i < urls.length; ++i) {
|
||||||
return exports.getSignedUrlsArrayByArray(ctx, baseUrl, list, urlType, opt_specialDir).then(function(urls) {
|
outputMap[getRelativePath(storagePathSrc, list[i])] = urls[i];
|
||||||
var outputMap = {};
|
}
|
||||||
for (var i = 0; i < list.length && i < urls.length; ++i) {
|
return outputMap;
|
||||||
if (optPath) {
|
}
|
||||||
let storageSrc = getStoragePath(ctx, optPath, opt_specialDir);
|
async function getSignedUrlsArrayByArray(ctx, baseUrl, list, urlType, opt_specialDir) {
|
||||||
outputMap[exports.getRelativePath(storageSrc, list[i])] = urls[i];
|
return await Promise.all(list.map(function (curValue) {
|
||||||
} else {
|
let storage = getStorage(opt_specialDir);
|
||||||
outputMap[list[i]] = urls[i];
|
let storageCfg = getStorageCfg(ctx, opt_specialDir);
|
||||||
}
|
let storagePathSrc = getStoragePath(ctx, curValue, opt_specialDir);
|
||||||
|
return storage.getSignedUrl(ctx, storageCfg, baseUrl, storagePathSrc, urlType, undefined);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
async function getSignedUrlsByArray(ctx, baseUrl, list, optPath, urlType, opt_specialDir) {
|
||||||
|
let urls = await getSignedUrlsArrayByArray(ctx, baseUrl, list, urlType, opt_specialDir);
|
||||||
|
var outputMap = {};
|
||||||
|
for (var i = 0; i < list.length && i < urls.length; ++i) {
|
||||||
|
if (optPath) {
|
||||||
|
let storagePathSrc = getStoragePath(ctx, optPath, opt_specialDir);
|
||||||
|
outputMap[getRelativePath(storagePathSrc, list[i])] = urls[i];
|
||||||
|
} else {
|
||||||
|
outputMap[list[i]] = urls[i];
|
||||||
}
|
}
|
||||||
return outputMap;
|
}
|
||||||
});
|
return outputMap;
|
||||||
};
|
}
|
||||||
exports.getRelativePath = function(strBase, strPath) {
|
function getRelativePath(strBase, strPath) {
|
||||||
return strPath.substring(strBase.length + 1);
|
return strPath.substring(strBase.length + 1);
|
||||||
|
}
|
||||||
|
async function healthCheck(ctx, opt_specialDir) {
|
||||||
|
const clusterId = cluster.isWorker ? cluster.worker.id : '';
|
||||||
|
const tempName = 'hc_' + os.hostname() + '_' + clusterId + '_' + Math.round(Math.random() * HEALTH_CHECK_KEY_MAX);
|
||||||
|
const tempBuffer = Buffer.from([1, 2, 3, 4, 5]);
|
||||||
|
try {
|
||||||
|
//It's proper to putObject one tempName
|
||||||
|
await putObject(ctx, tempName, tempBuffer, tempBuffer.length, opt_specialDir);
|
||||||
|
//try to prevent case, when another process can remove same tempName
|
||||||
|
await deleteObject(ctx, tempName, opt_specialDir);
|
||||||
|
} catch (err) {
|
||||||
|
ctx.logger.warn('healthCheck storage(%s) error %s', opt_specialDir, err.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function needServeStatic(opt_specialDir) {
|
||||||
|
let storage = getStorage(opt_specialDir);
|
||||||
|
return storage.needServeStatic();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
headObject,
|
||||||
|
getObject,
|
||||||
|
createReadStream,
|
||||||
|
putObject,
|
||||||
|
uploadObject,
|
||||||
|
copyObject,
|
||||||
|
copyPath,
|
||||||
|
listObjects,
|
||||||
|
deleteObject,
|
||||||
|
deletePath,
|
||||||
|
getSignedUrl,
|
||||||
|
getSignedUrls,
|
||||||
|
getSignedUrlsArrayByArray,
|
||||||
|
getSignedUrlsByArray,
|
||||||
|
getRelativePath,
|
||||||
|
isDiffrentPersistentStorage,
|
||||||
|
healthCheck,
|
||||||
|
needServeStatic
|
||||||
};
|
};
|
||||||
|
|||||||
@ -38,39 +38,33 @@ var path = require('path');
|
|||||||
var utils = require("./utils");
|
var utils = require("./utils");
|
||||||
var crypto = require('crypto');
|
var crypto = require('crypto');
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
|
const config = require('config');
|
||||||
const commonDefines = require('./../../Common/sources/commondefines');
|
const commonDefines = require('./../../Common/sources/commondefines');
|
||||||
const constants = require('./../../Common/sources/constants');
|
const constants = require('./../../Common/sources/constants');
|
||||||
|
|
||||||
var config = require('config');
|
|
||||||
var configStorage = config.get('storage');
|
|
||||||
var cfgBucketName = configStorage.get('bucketName');
|
|
||||||
var cfgStorageFolderName = configStorage.get('storageFolderName');
|
|
||||||
var configFs = configStorage.get('fs');
|
|
||||||
var cfgStorageFolderPath = configFs.get('folderPath');
|
|
||||||
var cfgStorageSecretString = configFs.get('secretString');
|
|
||||||
var cfgStorageUrlExpires = configFs.get('urlExpires');
|
|
||||||
const cfgExpSessionAbsolute = ms(config.get('services.CoAuthoring.expire.sessionabsolute'));
|
const cfgExpSessionAbsolute = ms(config.get('services.CoAuthoring.expire.sessionabsolute'));
|
||||||
|
|
||||||
function getFilePath(strPath) {
|
function getFilePath(storageCfg, strPath) {
|
||||||
return path.join(cfgStorageFolderPath, strPath);
|
const storageFolderPath = storageCfg.fs.folderPath;
|
||||||
|
return path.join(storageFolderPath, strPath);
|
||||||
}
|
}
|
||||||
function getOutputPath(strPath) {
|
function getOutputPath(strPath) {
|
||||||
return strPath.replace(/\\/g, '/');
|
return strPath.replace(/\\/g, '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function headObject(strPath) {
|
async function headObject(storageCfg, strPath) {
|
||||||
let fsPath = getFilePath(strPath);
|
let fsPath = getFilePath(storageCfg, strPath);
|
||||||
let stats = await stat(fsPath);
|
let stats = await stat(fsPath);
|
||||||
return {ContentLength: stats.size};
|
return {ContentLength: stats.size};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getObject(strPath) {
|
async function getObject(storageCfg, strPath) {
|
||||||
let fsPath = getFilePath(strPath);
|
let fsPath = getFilePath(storageCfg, strPath);
|
||||||
return await readFile(fsPath);
|
return await readFile(fsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createReadStream(strPath) {
|
async function createReadStream(storageCfg, strPath) {
|
||||||
let fsPath = getFilePath(strPath);
|
let fsPath = getFilePath(storageCfg, strPath);
|
||||||
let stats = await stat(fsPath);
|
let stats = await stat(fsPath);
|
||||||
let contentLength = stats.size;
|
let contentLength = stats.size;
|
||||||
let readStream = await utils.promiseCreateReadStream(fsPath);
|
let readStream = await utils.promiseCreateReadStream(fsPath);
|
||||||
@ -80,8 +74,8 @@ async function createReadStream(strPath) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function putObject(strPath, buffer, contentLength) {
|
async function putObject(storageCfg, strPath, buffer, contentLength) {
|
||||||
var fsPath = getFilePath(strPath);
|
var fsPath = getFilePath(storageCfg, strPath);
|
||||||
await mkdir(path.dirname(fsPath), {recursive: true});
|
await mkdir(path.dirname(fsPath), {recursive: true});
|
||||||
|
|
||||||
if (Buffer.isBuffer(buffer)) {
|
if (Buffer.isBuffer(buffer)) {
|
||||||
@ -92,63 +86,75 @@ async function putObject(strPath, buffer, contentLength) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function uploadObject(strPath, filePath) {
|
async function uploadObject(storageCfg, strPath, filePath) {
|
||||||
let fsPath = getFilePath(strPath);
|
let fsPath = getFilePath(storageCfg, strPath);
|
||||||
await cp(filePath, fsPath, {force: true, recursive: true});
|
await cp(filePath, fsPath, {force: true, recursive: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyObject(sourceKey, destinationKey) {
|
async function copyObject(storageCfgSrc, storageCfgDst, sourceKey, destinationKey) {
|
||||||
let fsPathSource = getFilePath(sourceKey);
|
let fsPathSource = getFilePath(storageCfgSrc, sourceKey);
|
||||||
let fsPathDestination = getFilePath(destinationKey);
|
let fsPathDestination = getFilePath(storageCfgDst, destinationKey);
|
||||||
await cp(fsPathSource, fsPathDestination, {force: true, recursive: true});
|
await cp(fsPathSource, fsPathDestination, {force: true, recursive: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listObjects(strPath) {
|
async function listObjects(storageCfg, strPath) {
|
||||||
let fsPath = getFilePath(strPath);
|
const storageFolderPath = storageCfg.fs.folderPath;
|
||||||
|
let fsPath = getFilePath(storageCfg, strPath);
|
||||||
let values = await utils.listObjects(fsPath);
|
let values = await utils.listObjects(fsPath);
|
||||||
return values.map(function(curvalue) {
|
return values.map(function(curvalue) {
|
||||||
return getOutputPath(curvalue.substring(cfgStorageFolderPath.length + 1));
|
return getOutputPath(curvalue.substring(storageFolderPath.length + 1));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteObject(strPath) {
|
async function deleteObject(storageCfg, strPath) {
|
||||||
const fsPath = getFilePath(strPath);
|
const fsPath = getFilePath(storageCfg, strPath);
|
||||||
return rm(fsPath, {force: true, recursive: true});
|
return rm(fsPath, {force: true, recursive: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deletePath(strPath) {
|
async function deletePath(storageCfg, strPath) {
|
||||||
const fsPath = getFilePath(strPath);
|
const fsPath = getFilePath(storageCfg, strPath);
|
||||||
return rm(fsPath, {force: true, recursive: true});
|
return rm(fsPath, {force: true, recursive: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSignedUrl(ctx, baseUrl, strPath, urlType, optFilename, opt_creationDate) {
|
async function getSignedUrl(ctx, storageCfg, baseUrl, strPath, urlType, optFilename, opt_creationDate) {
|
||||||
|
const storageSecretString = storageCfg.fs.secretString;
|
||||||
|
const storageUrlExpires = storageCfg.fs.urlExpires;
|
||||||
|
const bucketName = storageCfg.bucketName;
|
||||||
|
const storageFolderName = storageCfg.storageFolderName;
|
||||||
//replace '/' with %2f before encodeURIComponent becase nginx determine %2f as '/' and get wrong system path
|
//replace '/' with %2f before encodeURIComponent becase nginx determine %2f as '/' and get wrong system path
|
||||||
var userFriendlyName = optFilename ? encodeURIComponent(optFilename.replace(/\//g, "%2f")) : path.basename(strPath);
|
const userFriendlyName = optFilename ? encodeURIComponent(optFilename.replace(/\//g, "%2f")) : path.basename(strPath);
|
||||||
var uri = '/' + cfgBucketName + '/' + cfgStorageFolderName + '/' + strPath + '/' + userFriendlyName;
|
var uri = '/' + bucketName + '/' + storageFolderName + '/' + strPath + '/' + userFriendlyName;
|
||||||
//RFC 1123 does not allow underscores https://stackoverflow.com/questions/2180465/can-domain-name-subdomains-have-an-underscore-in-it
|
//RFC 1123 does not allow underscores https://stackoverflow.com/questions/2180465/can-domain-name-subdomains-have-an-underscore-in-it
|
||||||
var url = utils.checkBaseUrl(ctx, baseUrl).replace(/_/g, "%5f");
|
var url = utils.checkBaseUrl(ctx, baseUrl, storageCfg).replace(/_/g, "%5f");
|
||||||
url += uri;
|
url += uri;
|
||||||
|
|
||||||
var date = Date.now();
|
var date = Date.now();
|
||||||
let creationDate = opt_creationDate || date;
|
let creationDate = opt_creationDate || date;
|
||||||
let expiredAfter = (commonDefines.c_oAscUrlTypes.Session === urlType ? (cfgExpSessionAbsolute / 1000) : cfgStorageUrlExpires) || 31536000;
|
let expiredAfter = (commonDefines.c_oAscUrlTypes.Session === urlType ? (cfgExpSessionAbsolute / 1000) : storageUrlExpires) || 31536000;
|
||||||
//todo creationDate can be greater because mysql CURRENT_TIMESTAMP uses local time, not UTC
|
//todo creationDate can be greater because mysql CURRENT_TIMESTAMP uses local time, not UTC
|
||||||
var expires = creationDate + Math.ceil(Math.abs(date - creationDate) / expiredAfter) * expiredAfter;
|
var expires = creationDate + Math.ceil(Math.abs(date - creationDate) / expiredAfter) * expiredAfter;
|
||||||
expires = Math.ceil(expires / 1000);
|
expires = Math.ceil(expires / 1000);
|
||||||
expires += expiredAfter;
|
expires += expiredAfter;
|
||||||
|
|
||||||
var md5 = crypto.createHash('md5').update(expires + decodeURIComponent(uri) + cfgStorageSecretString).digest("base64");
|
var md5 = crypto.createHash('md5').update(expires + decodeURIComponent(uri) + storageSecretString).digest("base64");
|
||||||
md5 = md5.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
md5 = md5.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
||||||
|
|
||||||
url += '?md5=' + encodeURIComponent(md5);
|
url += '?md5=' + encodeURIComponent(md5);
|
||||||
url += '&expires=' + encodeURIComponent(expires);
|
url += '&expires=' + encodeURIComponent(expires);
|
||||||
if (ctx.shardKey) {
|
if (ctx.shardKey) {
|
||||||
url += `&${constants.SHARED_KEY_NAME}=${encodeURIComponent(ctx.shardKey)}`;
|
url += `&${constants.SHARD_KEY_API_NAME}=${encodeURIComponent(ctx.shardKey)}`;
|
||||||
|
}
|
||||||
|
if (ctx.wopiSrc) {
|
||||||
|
url += `&${constants.SHARD_KEY_WOPI_NAME}=${encodeURIComponent(ctx.wopiSrc)}`;
|
||||||
}
|
}
|
||||||
url += '&filename=' + userFriendlyName;
|
url += '&filename=' + userFriendlyName;
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function needServeStatic() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
headObject,
|
headObject,
|
||||||
getObject,
|
getObject,
|
||||||
@ -159,5 +165,6 @@ module.exports = {
|
|||||||
listObjects,
|
listObjects,
|
||||||
deleteObject,
|
deleteObject,
|
||||||
deletePath,
|
deletePath,
|
||||||
getSignedUrl
|
getSignedUrl,
|
||||||
|
needServeStatic
|
||||||
};
|
};
|
||||||
|
|||||||
@ -39,190 +39,190 @@ const { GetObjectCommand, PutObjectCommand, CopyObjectCommand} = require("@aws-s
|
|||||||
const { DeleteObjectsCommand, DeleteObjectCommand } = require("@aws-sdk/client-s3");
|
const { DeleteObjectsCommand, DeleteObjectCommand } = require("@aws-sdk/client-s3");
|
||||||
const { getSignedUrl } = require("@aws-sdk/s3-request-presigner");
|
const { getSignedUrl } = require("@aws-sdk/s3-request-presigner");
|
||||||
const mime = require('mime');
|
const mime = require('mime');
|
||||||
|
const config = require('config');
|
||||||
const utils = require('./utils');
|
const utils = require('./utils');
|
||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
const commonDefines = require('./../../Common/sources/commondefines');
|
const commonDefines = require('./../../Common/sources/commondefines');
|
||||||
|
|
||||||
const config = require('config');
|
|
||||||
const configStorage = require('config').get('storage');
|
|
||||||
const cfgRegion = configStorage.get('region');
|
|
||||||
const cfgEndpoint = configStorage.get('endpoint');
|
|
||||||
const cfgBucketName = configStorage.get('bucketName');
|
|
||||||
const cfgStorageFolderName = configStorage.get('storageFolderName');
|
|
||||||
const cfgAccessKeyId = configStorage.get('accessKeyId');
|
|
||||||
const cfgSecretAccessKey = configStorage.get('secretAccessKey');
|
|
||||||
const cfgSslEnabled = configStorage.get('sslEnabled');
|
|
||||||
const cfgS3ForcePathStyle = configStorage.get('s3ForcePathStyle');
|
|
||||||
const configFs = configStorage.get('fs');
|
|
||||||
const cfgStorageUrlExpires = configFs.get('urlExpires');
|
|
||||||
const cfgExpSessionAbsolute = ms(config.get('services.CoAuthoring.expire.sessionabsolute'));
|
const cfgExpSessionAbsolute = ms(config.get('services.CoAuthoring.expire.sessionabsolute'));
|
||||||
|
|
||||||
/**
|
|
||||||
* Don't hard-code your credentials!
|
|
||||||
* Export the following environment variables instead:
|
|
||||||
*
|
|
||||||
* export AWS_ACCESS_KEY_ID='AKID'
|
|
||||||
* export AWS_SECRET_ACCESS_KEY='SECRET'
|
|
||||||
*/
|
|
||||||
let configS3 = {
|
|
||||||
region: cfgRegion,
|
|
||||||
endpoint: cfgEndpoint,
|
|
||||||
credentials : {
|
|
||||||
accessKeyId: cfgAccessKeyId,
|
|
||||||
secretAccessKey: cfgSecretAccessKey
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (configS3.endpoint) {
|
|
||||||
configS3.tls = cfgSslEnabled;
|
|
||||||
configS3.forcePathStyle = cfgS3ForcePathStyle;
|
|
||||||
}
|
|
||||||
const client = new S3Client(configS3);
|
|
||||||
|
|
||||||
//This operation enables you to delete multiple objects from a bucket using a single HTTP request. You may specify up to 1000 keys.
|
//This operation enables you to delete multiple objects from a bucket using a single HTTP request. You may specify up to 1000 keys.
|
||||||
const MAX_DELETE_OBJECTS = 1000;
|
const MAX_DELETE_OBJECTS = 1000;
|
||||||
|
let clients = {};
|
||||||
|
|
||||||
function getFilePath(strPath) {
|
function getS3Client(storageCfg) {
|
||||||
//todo
|
/**
|
||||||
return cfgStorageFolderName + '/' + strPath;
|
* Don't hard-code your credentials!
|
||||||
|
* Export the following environment variables instead:
|
||||||
|
*
|
||||||
|
* export AWS_ACCESS_KEY_ID='AKID'
|
||||||
|
* export AWS_SECRET_ACCESS_KEY='SECRET'
|
||||||
|
*/
|
||||||
|
let configS3 = {
|
||||||
|
region: storageCfg.region,
|
||||||
|
endpoint: storageCfg.endpoint,
|
||||||
|
credentials : {
|
||||||
|
accessKeyId: storageCfg.accessKeyId,
|
||||||
|
secretAccessKey: storageCfg.secretAccessKey
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (configS3.endpoint) {
|
||||||
|
configS3.tls = storageCfg.sslEnabled;
|
||||||
|
configS3.forcePathStyle = storageCfg.s3ForcePathStyle;
|
||||||
|
}
|
||||||
|
let configJson = JSON.stringify(configS3);
|
||||||
|
let client = clients[configJson];
|
||||||
|
if (!client) {
|
||||||
|
client = new S3Client(configS3);
|
||||||
|
clients[configJson] = client;
|
||||||
|
}
|
||||||
|
return client;
|
||||||
}
|
}
|
||||||
function joinListObjects(inputArray, outputArray) {
|
|
||||||
|
function getFilePath(storageCfg, strPath) {
|
||||||
|
const storageFolderName = storageCfg.storageFolderName;
|
||||||
|
return storageFolderName + '/' + strPath;
|
||||||
|
}
|
||||||
|
function joinListObjects(storageCfg, inputArray, outputArray) {
|
||||||
if (!inputArray) {
|
if (!inputArray) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const storageFolderName = storageCfg.storageFolderName;
|
||||||
let length = inputArray.length;
|
let length = inputArray.length;
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
outputArray.push(inputArray[i].Key.substring((cfgStorageFolderName + '/').length));
|
outputArray.push(inputArray[i].Key.substring((storageFolderName + '/').length));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function listObjectsExec(output, params) {
|
async function listObjectsExec(storageCfg, output, params) {
|
||||||
const data = await client.send(new ListObjectsCommand(params));
|
const data = await getS3Client(storageCfg).send(new ListObjectsCommand(params));
|
||||||
joinListObjects(data.Contents, output);
|
joinListObjects(storageCfg, data.Contents, output);
|
||||||
if (data.IsTruncated && (data.NextMarker || (data.Contents && data.Contents.length > 0))) {
|
if (data.IsTruncated && (data.NextMarker || (data.Contents && data.Contents.length > 0))) {
|
||||||
params.Marker = data.NextMarker || data.Contents[data.Contents.length - 1].Key;
|
params.Marker = data.NextMarker || data.Contents[data.Contents.length - 1].Key;
|
||||||
return await listObjectsExec(output, params);
|
return await listObjectsExec(storageCfg, output, params);
|
||||||
} else {
|
} else {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function deleteObjectsHelp(aKeys) {
|
async function deleteObjectsHelp(storageCfg, aKeys) {
|
||||||
//By default, the operation uses verbose mode in which the response includes the result of deletion of each key in your request.
|
//By default, the operation uses verbose mode in which the response includes the result of deletion of each key in your request.
|
||||||
//In quiet mode the response includes only keys where the delete operation encountered an error.
|
//In quiet mode the response includes only keys where the delete operation encountered an error.
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Delete: {
|
Delete: {
|
||||||
Objects: aKeys,
|
Objects: aKeys,
|
||||||
Quiet: true
|
Quiet: true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const command = new DeleteObjectsCommand(input);
|
const command = new DeleteObjectsCommand(input);
|
||||||
await client.send(command);
|
await getS3Client(storageCfg).send(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function headObject(strPath) {
|
async function headObject(storageCfg, strPath) {
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Key: getFilePath(strPath)
|
Key: getFilePath(storageCfg, strPath)
|
||||||
};
|
};
|
||||||
const command = new HeadObjectCommand(input);
|
const command = new HeadObjectCommand(input);
|
||||||
let output = await client.send(command);
|
let output = await getS3Client(storageCfg).send(command);
|
||||||
return {ContentLength: output.ContentLength};
|
return {ContentLength: output.ContentLength};
|
||||||
}
|
}
|
||||||
async function getObject(strPath) {
|
async function getObject(storageCfg, strPath) {
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Key: getFilePath(strPath)
|
Key: getFilePath(storageCfg, strPath)
|
||||||
};
|
};
|
||||||
const command = new GetObjectCommand(input);
|
const command = new GetObjectCommand(input);
|
||||||
const output = await client.send(command);
|
const output = await getS3Client(storageCfg).send(command);
|
||||||
|
|
||||||
return await utils.stream2Buffer(output.Body);
|
return await utils.stream2Buffer(output.Body);
|
||||||
}
|
}
|
||||||
async function createReadStream(strPath) {
|
async function createReadStream(storageCfg, strPath) {
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Key: getFilePath(strPath)
|
Key: getFilePath(storageCfg, strPath)
|
||||||
};
|
};
|
||||||
const command = new GetObjectCommand(input);
|
const command = new GetObjectCommand(input);
|
||||||
const output = await client.send(command);
|
const output = await getS3Client(storageCfg).send(command);
|
||||||
return {
|
return {
|
||||||
contentLength: output.ContentLength,
|
contentLength: output.ContentLength,
|
||||||
readStream: output.Body
|
readStream: output.Body
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function putObject(strPath, buffer, contentLength) {
|
async function putObject(storageCfg, strPath, buffer, contentLength) {
|
||||||
//todo consider Expires
|
//todo consider Expires
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Key: getFilePath(strPath),
|
Key: getFilePath(storageCfg, strPath),
|
||||||
Body: buffer,
|
Body: buffer,
|
||||||
ContentLength: contentLength,
|
ContentLength: contentLength,
|
||||||
ContentType: mime.getType(strPath)
|
ContentType: mime.getType(strPath)
|
||||||
};
|
};
|
||||||
const command = new PutObjectCommand(input);
|
const command = new PutObjectCommand(input);
|
||||||
await client.send(command);
|
await getS3Client(storageCfg).send(command);
|
||||||
}
|
}
|
||||||
async function uploadObject(strPath, filePath) {
|
async function uploadObject(storageCfg, strPath, filePath) {
|
||||||
const file = fs.createReadStream(filePath);
|
const file = fs.createReadStream(filePath);
|
||||||
//todo рассмотреть Expires
|
//todo рассмотреть Expires
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Key: getFilePath(strPath),
|
Key: getFilePath(storageCfg, strPath),
|
||||||
Body: file,
|
Body: file,
|
||||||
ContentType: mime.getType(strPath)
|
ContentType: mime.getType(strPath)
|
||||||
};
|
};
|
||||||
const command = new PutObjectCommand(input);
|
const command = new PutObjectCommand(input);
|
||||||
await client.send(command);
|
await getS3Client(storageCfg).send(command);
|
||||||
}
|
}
|
||||||
async function copyObject(sourceKey, destinationKey) {
|
async function copyObject(storageCfgSrc, storageCfgDst, sourceKey, destinationKey) {
|
||||||
//todo source bucket
|
//todo source bucket
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfgDst.bucketName,
|
||||||
Key: getFilePath(destinationKey),
|
Key: getFilePath(storageCfgDst, destinationKey),
|
||||||
CopySource: `/${cfgBucketName}/${getFilePath(sourceKey)}`
|
CopySource: `/${storageCfgSrc.bucketName}/${getFilePath(storageCfgSrc, sourceKey)}`
|
||||||
};
|
};
|
||||||
const command = new CopyObjectCommand(input);
|
const command = new CopyObjectCommand(input);
|
||||||
await client.send(command);
|
await getS3Client(storageCfgDst).send(command);
|
||||||
}
|
}
|
||||||
async function listObjects(strPath) {
|
async function listObjects(storageCfg, strPath) {
|
||||||
let params = {
|
let params = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Prefix: getFilePath(strPath)
|
Prefix: getFilePath(storageCfg, strPath)
|
||||||
};
|
};
|
||||||
let output = [];
|
let output = [];
|
||||||
await listObjectsExec(output, params);
|
await listObjectsExec(storageCfg, output, params);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
async function deleteObject(strPath) {
|
async function deleteObject(storageCfg, strPath) {
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Key: getFilePath(strPath)
|
Key: getFilePath(storageCfg, strPath)
|
||||||
};
|
};
|
||||||
const command = new DeleteObjectCommand(input);
|
const command = new DeleteObjectCommand(input);
|
||||||
await client.send(command);
|
await getS3Client(storageCfg).send(command);
|
||||||
};
|
};
|
||||||
async function deleteObjects(strPaths) {
|
async function deleteObjects(storageCfg, strPaths) {
|
||||||
let aKeys = strPaths.map(function (currentValue) {
|
let aKeys = strPaths.map(function (currentValue) {
|
||||||
return {Key: getFilePath(currentValue)};
|
return {Key: getFilePath(storageCfg, currentValue)};
|
||||||
});
|
});
|
||||||
for (let i = 0; i < aKeys.length; i += MAX_DELETE_OBJECTS) {
|
for (let i = 0; i < aKeys.length; i += MAX_DELETE_OBJECTS) {
|
||||||
await deleteObjectsHelp(aKeys.slice(i, i + MAX_DELETE_OBJECTS));
|
await deleteObjectsHelp(storageCfg, aKeys.slice(i, i + MAX_DELETE_OBJECTS));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function deletePath(strPath) {
|
async function deletePath(storageCfg, strPath) {
|
||||||
let list = await listObjects(strPath);
|
let list = await listObjects(storageCfg, strPath);
|
||||||
await deleteObjects(list);
|
await deleteObjects(storageCfg, list);
|
||||||
}
|
}
|
||||||
async function getSignedUrlWrapper(ctx, baseUrl, strPath, urlType, optFilename, opt_creationDate) {
|
async function getSignedUrlWrapper(ctx, storageCfg, baseUrl, strPath, urlType, optFilename, opt_creationDate) {
|
||||||
let expires = (commonDefines.c_oAscUrlTypes.Session === urlType ? cfgExpSessionAbsolute / 1000 : cfgStorageUrlExpires) || 31536000;
|
const storageUrlExpires = storageCfg.fs.urlExpires;
|
||||||
|
let expires = (commonDefines.c_oAscUrlTypes.Session === urlType ? cfgExpSessionAbsolute / 1000 : storageUrlExpires) || 31536000;
|
||||||
// Signature version 4 presigned URLs must have an expiration date less than one week in the future
|
// Signature version 4 presigned URLs must have an expiration date less than one week in the future
|
||||||
expires = Math.min(expires, 604800);
|
expires = Math.min(expires, 604800);
|
||||||
let userFriendlyName = optFilename ? optFilename.replace(/\//g, "%2f") : path.basename(strPath);
|
let userFriendlyName = optFilename ? optFilename.replace(/\//g, "%2f") : path.basename(strPath);
|
||||||
let contentDisposition = utils.getContentDisposition(userFriendlyName, null, null);
|
let contentDisposition = utils.getContentDisposition(userFriendlyName, null, null);
|
||||||
|
|
||||||
const input = {
|
const input = {
|
||||||
Bucket: cfgBucketName,
|
Bucket: storageCfg.bucketName,
|
||||||
Key: getFilePath(strPath),
|
Key: getFilePath(storageCfg, strPath),
|
||||||
ResponseContentDisposition: contentDisposition
|
ResponseContentDisposition: contentDisposition
|
||||||
};
|
};
|
||||||
const command = new GetObjectCommand(input);
|
const command = new GetObjectCommand(input);
|
||||||
@ -230,12 +230,16 @@ async function getSignedUrlWrapper(ctx, baseUrl, strPath, urlType, optFilename,
|
|||||||
let options = {
|
let options = {
|
||||||
expiresIn: expires
|
expiresIn: expires
|
||||||
};
|
};
|
||||||
return await getSignedUrl(client, command, options);
|
return await getSignedUrl(getS3Client(storageCfg), command, options);
|
||||||
//extra query params cause SignatureDoesNotMatch
|
//extra query params cause SignatureDoesNotMatch
|
||||||
//https://stackoverflow.com/questions/55503009/amazon-s3-signature-does-not-match-when-extra-query-params-ga-added-in-url
|
//https://stackoverflow.com/questions/55503009/amazon-s3-signature-does-not-match-when-extra-query-params-ga-added-in-url
|
||||||
// return utils.changeOnlyOfficeUrl(url, strPath, optFilename);
|
// return utils.changeOnlyOfficeUrl(url, strPath, optFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function needServeStatic() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
headObject,
|
headObject,
|
||||||
getObject,
|
getObject,
|
||||||
@ -246,5 +250,6 @@ module.exports = {
|
|||||||
listObjects,
|
listObjects,
|
||||||
deleteObject,
|
deleteObject,
|
||||||
deletePath,
|
deletePath,
|
||||||
getSignedUrl: getSignedUrlWrapper
|
getSignedUrl: getSignedUrlWrapper,
|
||||||
|
needServeStatic
|
||||||
};
|
};
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
//Fix EPROTO error in node 8.x at some web sites(https://github.com/nodejs/node/issues/21513)
|
//Fix EPROTO error in node 8.x at some web sites(https://github.com/nodejs/node/issues/21513)
|
||||||
require("tls").DEFAULT_ECDH_CURVE = "auto";
|
require("tls").DEFAULT_ECDH_CURVE = "auto";
|
||||||
|
|
||||||
|
const { pipeline } = require('node:stream/promises');
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
@ -51,7 +52,6 @@ const NodeCache = require( "node-cache" );
|
|||||||
const ms = require('ms');
|
const ms = require('ms');
|
||||||
const constants = require('./constants');
|
const constants = require('./constants');
|
||||||
const commonDefines = require('./commondefines');
|
const commonDefines = require('./commondefines');
|
||||||
const logger = require('./logger');
|
|
||||||
const forwarded = require('forwarded');
|
const forwarded = require('forwarded');
|
||||||
const { RequestFilteringHttpAgent, RequestFilteringHttpsAgent } = require("request-filtering-agent");
|
const { RequestFilteringHttpAgent, RequestFilteringHttpsAgent } = require("request-filtering-agent");
|
||||||
const https = require('https');
|
const https = require('https');
|
||||||
@ -83,7 +83,6 @@ const cfgTokenOutboxUrlExclusionRegex = config.get('services.CoAuthoring.token.o
|
|||||||
const cfgSecret = config.get('aesEncrypt.secret');
|
const cfgSecret = config.get('aesEncrypt.secret');
|
||||||
const cfgAESConfig = config.get('aesEncrypt.config');
|
const cfgAESConfig = config.get('aesEncrypt.config');
|
||||||
const cfgRequesFilteringAgent = config.get('services.CoAuthoring.request-filtering-agent');
|
const cfgRequesFilteringAgent = config.get('services.CoAuthoring.request-filtering-agent');
|
||||||
const cfgAllowPrivateIPAddressForSignedRequests = config.get('services.CoAuthoring.server.allowPrivateIPAddressForSignedRequests');
|
|
||||||
const cfgStorageExternalHost = config.get('storage.externalHost');
|
const cfgStorageExternalHost = config.get('storage.externalHost');
|
||||||
const cfgExternalRequestDirectIfIn = config.get('externalRequest.directIfIn');
|
const cfgExternalRequestDirectIfIn = config.get('externalRequest.directIfIn');
|
||||||
const cfgExternalRequestAction = config.get('externalRequest.action');
|
const cfgExternalRequestAction = config.get('externalRequest.action');
|
||||||
@ -273,7 +272,6 @@ function isRedirectResponse(response) {
|
|||||||
function isAllowDirectRequest(ctx, uri, isInJwtToken) {
|
function isAllowDirectRequest(ctx, uri, isInJwtToken) {
|
||||||
let res = false;
|
let res = false;
|
||||||
const tenExternalRequestDirectIfIn = ctx.getCfg('externalRequest.directIfIn', cfgExternalRequestDirectIfIn);
|
const tenExternalRequestDirectIfIn = ctx.getCfg('externalRequest.directIfIn', cfgExternalRequestDirectIfIn);
|
||||||
const tenAllowPrivateIPAddressForSignedRequests = ctx.getCfg('services.CoAuthoring.server.allowPrivateIPAddressForSignedRequests', cfgAllowPrivateIPAddressForSignedRequests);
|
|
||||||
let allowList = tenExternalRequestDirectIfIn.allowList;
|
let allowList = tenExternalRequestDirectIfIn.allowList;
|
||||||
if (allowList.length > 0) {
|
if (allowList.length > 0) {
|
||||||
let allowIndex = allowList.findIndex((allowPrefix) => {
|
let allowIndex = allowList.findIndex((allowPrefix) => {
|
||||||
@ -281,7 +279,7 @@ function isAllowDirectRequest(ctx, uri, isInJwtToken) {
|
|||||||
}, uri);
|
}, uri);
|
||||||
res = -1 !== allowIndex;
|
res = -1 !== allowIndex;
|
||||||
ctx.logger.debug("isAllowDirectRequest check allow list res=%s", res);
|
ctx.logger.debug("isAllowDirectRequest check allow list res=%s", res);
|
||||||
} else if (tenExternalRequestDirectIfIn.jwtToken && tenAllowPrivateIPAddressForSignedRequests) {
|
} else if (tenExternalRequestDirectIfIn.jwtToken) {
|
||||||
res = isInJwtToken;
|
res = isInJwtToken;
|
||||||
ctx.logger.debug("isAllowDirectRequest url in jwt token res=%s", res);
|
ctx.logger.debug("isAllowDirectRequest url in jwt token res=%s", res);
|
||||||
}
|
}
|
||||||
@ -353,7 +351,7 @@ function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_A
|
|||||||
uri = URI.serialize(URI.parse(uri));
|
uri = URI.serialize(URI.parse(uri));
|
||||||
var urlParsed = url.parse(uri);
|
var urlParsed = url.parse(uri);
|
||||||
let sizeLimit = optLimit || Number.MAX_VALUE;
|
let sizeLimit = optLimit || Number.MAX_VALUE;
|
||||||
let bufferLength = 0;
|
let bufferLength = 0, timeoutId;
|
||||||
let hash = crypto.createHash('sha256');
|
let hash = crypto.createHash('sha256');
|
||||||
//if you expect binary data, you should set encoding: null
|
//if you expect binary data, you should set encoding: null
|
||||||
let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity);
|
let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity);
|
||||||
@ -378,6 +376,7 @@ function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_A
|
|||||||
Object.assign(options.headers, opt_headers);
|
Object.assign(options.headers, opt_headers);
|
||||||
}
|
}
|
||||||
let fError = function(err) {
|
let fError = function(err) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
if (!opt_streamWriter) {
|
if (!opt_streamWriter) {
|
||||||
@ -389,6 +388,7 @@ function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_A
|
|||||||
}
|
}
|
||||||
executed = true;
|
executed = true;
|
||||||
if (err) {
|
if (err) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
var contentLength = response.caseless.get('content-length');
|
var contentLength = response.caseless.get('content-length');
|
||||||
@ -396,6 +396,7 @@ function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_A
|
|||||||
ctx.logger.warn('downloadUrlPromise body size mismatch: uri=%s; content-length=%s; body.length=%d', uri, contentLength, body.length);
|
ctx.logger.warn('downloadUrlPromise body size mismatch: uri=%s; content-length=%s; body.length=%d', uri, contentLength, body.length);
|
||||||
}
|
}
|
||||||
let sha256 = hash.digest('hex');
|
let sha256 = hash.digest('hex');
|
||||||
|
clearTimeout(timeoutId);
|
||||||
resolve({response: response, body: body, sha256: sha256});
|
resolve({response: response, body: body, sha256: sha256});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -417,13 +418,21 @@ function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_A
|
|||||||
error.response = response;
|
error.response = response;
|
||||||
if (opt_streamWriter && !isRedirectResponse(response)) {
|
if (opt_streamWriter && !isRedirectResponse(response)) {
|
||||||
this.off('error', fError);
|
this.off('error', fError);
|
||||||
resolve(pipeStreams(this, opt_streamWriter, true));
|
pipeline(this, opt_streamWriter)
|
||||||
|
.then(resolve, reject)
|
||||||
|
.finally(() => {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
raiseErrorObj(this, error);
|
raiseErrorObj(this, error);
|
||||||
}
|
}
|
||||||
} else if (opt_streamWriter) {
|
} else if (opt_streamWriter) {
|
||||||
this.off('error', fError);
|
this.off('error', fError);
|
||||||
resolve(pipeStreams(this, opt_streamWriter, true));
|
pipeline(this, opt_streamWriter)
|
||||||
|
.then(resolve, reject)
|
||||||
|
.finally(() => {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let fData = function(chunk) {
|
let fData = function(chunk) {
|
||||||
@ -439,13 +448,13 @@ function downloadUrlPromiseWithoutRedirect(ctx, uri, optTimeout, optLimit, opt_A
|
|||||||
.on('data', fData)
|
.on('data', fData)
|
||||||
.on('error', fError);
|
.on('error', fError);
|
||||||
if (optTimeout && optTimeout.wholeCycle) {
|
if (optTimeout && optTimeout.wholeCycle) {
|
||||||
setTimeout(function() {
|
timeoutId = setTimeout(function() {
|
||||||
raiseError(ro, 'ETIMEDOUT', 'Error: whole request cycle timeout');
|
raiseError(ro, 'ETIMEDOUT', 'Error: whole request cycle timeout');
|
||||||
}, ms(optTimeout.wholeCycle));
|
}, ms(optTimeout.wholeCycle));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function postRequestPromise(ctx, uri, postData, postDataStream, postDataSize, optTimeout, opt_Authorization, opt_header) {
|
function postRequestPromise(ctx, uri, postData, postDataStream, postDataSize, optTimeout, opt_Authorization, opt_headers) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults);
|
const tenTenantRequestDefaults = ctx.getCfg('services.CoAuthoring.requestDefaults', cfgRequestDefaults);
|
||||||
const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader);
|
const tenTokenOutboxHeader = ctx.getCfg('services.CoAuthoring.token.outbox.header', cfgTokenOutboxHeader);
|
||||||
@ -453,29 +462,32 @@ function postRequestPromise(ctx, uri, postData, postDataStream, postDataSize, op
|
|||||||
//IRI to URI
|
//IRI to URI
|
||||||
uri = URI.serialize(URI.parse(uri));
|
uri = URI.serialize(URI.parse(uri));
|
||||||
var urlParsed = url.parse(uri);
|
var urlParsed = url.parse(uri);
|
||||||
var headers = {'Content-Type': 'application/json'};
|
let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity);
|
||||||
|
let options = config.util.extendDeep({}, tenTenantRequestDefaults);
|
||||||
|
Object.assign(options, {uri: urlParsed, encoding: 'utf8', timeout: connectionAndInactivity});
|
||||||
|
//baseRequest creates new agent(win-ca injects in globalAgent)
|
||||||
|
options.agentOptions = https.globalAgent.options;
|
||||||
|
if (postData) {
|
||||||
|
options.body = postData;
|
||||||
|
}
|
||||||
|
if (!options.headers) {
|
||||||
|
options.headers = {};
|
||||||
|
}
|
||||||
if (opt_Authorization) {
|
if (opt_Authorization) {
|
||||||
//todo ctx.getCfg
|
//todo ctx.getCfg
|
||||||
headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization;
|
options.headers[tenTokenOutboxHeader] = tenTokenOutboxPrefix + opt_Authorization;
|
||||||
|
}
|
||||||
|
if (opt_headers) {
|
||||||
|
Object.assign(options.headers, opt_headers);
|
||||||
}
|
}
|
||||||
headers = opt_header || headers;
|
|
||||||
if (undefined !== postDataSize) {
|
if (undefined !== postDataSize) {
|
||||||
//If no Content-Length is set, data will automatically be encoded in HTTP Chunked transfer encoding,
|
//If no Content-Length is set, data will automatically be encoded in HTTP Chunked transfer encoding,
|
||||||
//so that server knows when the data ends. The Transfer-Encoding: chunked header is added.
|
//so that server knows when the data ends. The Transfer-Encoding: chunked header is added.
|
||||||
//https://nodejs.org/api/http.html#requestwritechunk-encoding-callback
|
//https://nodejs.org/api/http.html#requestwritechunk-encoding-callback
|
||||||
//issue with Transfer-Encoding: chunked wopi and sharepoint 2019
|
//issue with Transfer-Encoding: chunked wopi and sharepoint 2019
|
||||||
//https://community.alteryx.com/t5/Dev-Space/Download-Tool-amp-Microsoft-SharePoint-Chunked-Request-Error/td-p/735824
|
//https://community.alteryx.com/t5/Dev-Space/Download-Tool-amp-Microsoft-SharePoint-Chunked-Request-Error/td-p/735824
|
||||||
headers['Content-Length'] = postDataSize;
|
options.headers['Content-Length'] = postDataSize;
|
||||||
}
|
}
|
||||||
let connectionAndInactivity = optTimeout && optTimeout.connectionAndInactivity && ms(optTimeout.connectionAndInactivity);
|
|
||||||
let options = config.util.extendDeep({}, tenTenantRequestDefaults);
|
|
||||||
Object.assign(options, {uri: urlParsed, encoding: 'utf8', headers: headers, timeout: connectionAndInactivity});
|
|
||||||
//baseRequest creates new agent(win-ca injects in globalAgent)
|
|
||||||
options.agentOptions = https.globalAgent.options;
|
|
||||||
if (postData) {
|
|
||||||
options.body = postData;
|
|
||||||
}
|
|
||||||
|
|
||||||
let executed = false;
|
let executed = false;
|
||||||
let ro = request.post(options, function(err, response, body) {
|
let ro = request.post(options, function(err, response, body) {
|
||||||
if (executed) {
|
if (executed) {
|
||||||
@ -535,6 +547,8 @@ exports.mapAscServerErrorToOldError = function(error) {
|
|||||||
res = -7;
|
res = -7;
|
||||||
break;
|
break;
|
||||||
case constants.CONVERT_LIMITS :
|
case constants.CONVERT_LIMITS :
|
||||||
|
res = -10;
|
||||||
|
break;
|
||||||
case constants.CONVERT_NEED_PARAMS :
|
case constants.CONVERT_NEED_PARAMS :
|
||||||
case constants.CONVERT_LIBREOFFICE :
|
case constants.CONVERT_LIBREOFFICE :
|
||||||
case constants.CONVERT_CORRUPTED :
|
case constants.CONVERT_CORRUPTED :
|
||||||
@ -783,14 +797,22 @@ function getDomainByRequest(ctx, req) {
|
|||||||
}
|
}
|
||||||
exports.getDomainByConnection = getDomainByConnection;
|
exports.getDomainByConnection = getDomainByConnection;
|
||||||
exports.getDomainByRequest = getDomainByRequest;
|
exports.getDomainByRequest = getDomainByRequest;
|
||||||
function getShardByConnection(ctx, conn) {
|
function getShardKeyByConnection(ctx, conn) {
|
||||||
return conn?.handshake?.query?.[constants.SHARED_KEY_NAME];
|
return conn?.handshake?.query?.[constants.SHARD_KEY_API_NAME];
|
||||||
|
}
|
||||||
|
function getWopiSrcByConnection(ctx, conn) {
|
||||||
|
return conn?.handshake?.query?.[constants.SHARD_KEY_WOPI_NAME];
|
||||||
}
|
}
|
||||||
function getShardKeyByRequest(ctx, req) {
|
function getShardKeyByRequest(ctx, req) {
|
||||||
return req.query[constants.SHARED_KEY_NAME];
|
return req.query?.[constants.SHARD_KEY_API_NAME];
|
||||||
}
|
}
|
||||||
exports.getShardByConnection = getShardByConnection;
|
function getWopiSrcByRequest(ctx, req) {
|
||||||
|
return req.query?.[constants.SHARD_KEY_WOPI_NAME];
|
||||||
|
}
|
||||||
|
exports.getShardKeyByConnection = getShardKeyByConnection;
|
||||||
|
exports.getWopiSrcByConnection = getWopiSrcByConnection;
|
||||||
exports.getShardKeyByRequest = getShardKeyByRequest;
|
exports.getShardKeyByRequest = getShardKeyByRequest;
|
||||||
|
exports.getWopiSrcByRequest = getWopiSrcByRequest;
|
||||||
function stream2Buffer(stream) {
|
function stream2Buffer(stream) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
if (!stream.readable) {
|
if (!stream.readable) {
|
||||||
@ -1142,8 +1164,9 @@ exports.convertLicenseInfoToServerParams = function(licenseInfo) {
|
|||||||
license.buildNumber = commonDefines.buildNumber;
|
license.buildNumber = commonDefines.buildNumber;
|
||||||
return license;
|
return license;
|
||||||
};
|
};
|
||||||
exports.checkBaseUrl = function(ctx, baseUrl) {
|
exports.checkBaseUrl = function(ctx, baseUrl, opt_storageCfg) {
|
||||||
const tenStorageExternalHost = ctx.getCfg('storage.externalHost', cfgStorageExternalHost);
|
let storageExternalHost = opt_storageCfg ? opt_storageCfg.externalHost : cfgStorageExternalHost
|
||||||
|
const tenStorageExternalHost = ctx.getCfg('storage.externalHost', storageExternalHost);
|
||||||
return tenStorageExternalHost ? tenStorageExternalHost : baseUrl;
|
return tenStorageExternalHost ? tenStorageExternalHost : baseUrl;
|
||||||
};
|
};
|
||||||
exports.resolvePath = function(object, path, defaultValue) {
|
exports.resolvePath = function(object, path, defaultValue) {
|
||||||
|
|||||||
154
DocService/npm-shrinkwrap.json
generated
154
DocService/npm-shrinkwrap.json
generated
@ -843,9 +843,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"async": {
|
"async": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
|
||||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
|
||||||
},
|
},
|
||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
@ -1148,9 +1148,9 @@
|
|||||||
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
|
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
|
||||||
},
|
},
|
||||||
"cookie": {
|
"cookie": {
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||||
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw=="
|
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="
|
||||||
},
|
},
|
||||||
"cookie-signature": {
|
"cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
@ -1243,9 +1243,9 @@
|
|||||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||||
},
|
},
|
||||||
"denque": {
|
"denque": {
|
||||||
"version": "2.0.1",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||||
"integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ=="
|
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
|
||||||
},
|
},
|
||||||
"depd": {
|
"depd": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@ -1332,9 +1332,9 @@
|
|||||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||||
},
|
},
|
||||||
"ejs": {
|
"ejs": {
|
||||||
"version": "3.1.8",
|
"version": "3.1.10",
|
||||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
|
||||||
"integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==",
|
"integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"jake": "^10.8.5"
|
"jake": "^10.8.5"
|
||||||
}
|
}
|
||||||
@ -1519,16 +1519,16 @@
|
|||||||
"integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="
|
"integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="
|
||||||
},
|
},
|
||||||
"express": {
|
"express": {
|
||||||
"version": "4.18.2",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
||||||
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
|
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"accepts": "~1.3.8",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
"body-parser": "1.20.1",
|
"body-parser": "1.20.2",
|
||||||
"content-disposition": "0.5.4",
|
"content-disposition": "0.5.4",
|
||||||
"content-type": "~1.0.4",
|
"content-type": "~1.0.4",
|
||||||
"cookie": "0.5.0",
|
"cookie": "0.6.0",
|
||||||
"cookie-signature": "1.0.6",
|
"cookie-signature": "1.0.6",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "2.0.0",
|
"depd": "2.0.0",
|
||||||
@ -1556,15 +1556,30 @@
|
|||||||
"vary": "~1.1.2"
|
"vary": "~1.1.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": {
|
"body-parser": {
|
||||||
"version": "1.3.8",
|
"version": "1.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
||||||
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-types": "~2.1.34",
|
"bytes": "3.1.2",
|
||||||
"negotiator": "0.6.3"
|
"content-type": "~1.0.5",
|
||||||
|
"debug": "2.6.9",
|
||||||
|
"depd": "2.0.0",
|
||||||
|
"destroy": "1.2.0",
|
||||||
|
"http-errors": "2.0.0",
|
||||||
|
"iconv-lite": "0.4.24",
|
||||||
|
"on-finished": "2.4.1",
|
||||||
|
"qs": "6.11.0",
|
||||||
|
"raw-body": "2.5.2",
|
||||||
|
"type-is": "~1.6.18",
|
||||||
|
"unpipe": "1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"bytes": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
|
||||||
|
},
|
||||||
"depd": {
|
"depd": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
@ -1583,11 +1598,6 @@
|
|||||||
"mime-db": "1.52.0"
|
"mime-db": "1.52.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"negotiator": {
|
|
||||||
"version": "0.6.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
|
||||||
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
|
|
||||||
},
|
|
||||||
"on-finished": {
|
"on-finished": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||||
@ -1596,6 +1606,17 @@
|
|||||||
"ee-first": "1.1.1"
|
"ee-first": "1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"raw-body": {
|
||||||
|
"version": "2.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||||
|
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
||||||
|
"requires": {
|
||||||
|
"bytes": "3.1.2",
|
||||||
|
"http-errors": "2.0.0",
|
||||||
|
"iconv-lite": "0.4.24",
|
||||||
|
"unpipe": "1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@ -2117,7 +2138,7 @@
|
|||||||
"is-property": {
|
"is-property": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
|
||||||
"integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ="
|
"integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="
|
||||||
},
|
},
|
||||||
"is-regex": {
|
"is-regex": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
@ -2191,14 +2212,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jake": {
|
"jake": {
|
||||||
"version": "10.8.5",
|
"version": "10.8.7",
|
||||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
|
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz",
|
||||||
"integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
|
"integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"async": "^3.2.3",
|
"async": "^3.2.3",
|
||||||
"chalk": "^4.0.2",
|
"chalk": "^4.0.2",
|
||||||
"filelist": "^1.0.1",
|
"filelist": "^1.0.4",
|
||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jimp": {
|
"jimp": {
|
||||||
@ -2347,9 +2368,9 @@
|
|||||||
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
|
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
|
||||||
},
|
},
|
||||||
"long": {
|
"long": {
|
||||||
"version": "4.0.0",
|
"version": "5.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
|
||||||
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
|
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
|
||||||
},
|
},
|
||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
@ -2531,16 +2552,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"mysql2": {
|
"mysql2": {
|
||||||
"version": "2.3.3",
|
"version": "3.9.8",
|
||||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.8.tgz",
|
||||||
"integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==",
|
"integrity": "sha512-+5JKNjPuks1FNMoy9TYpl77f+5frbTklz7eb3XDwbpsERRLEeXiW2PDEkakYF50UuKU2qwfGnyXpKYvukv8mGA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"denque": "^2.0.1",
|
"denque": "^2.1.0",
|
||||||
"generate-function": "^2.3.1",
|
"generate-function": "^2.3.1",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
"long": "^4.0.0",
|
"long": "^5.2.1",
|
||||||
"lru-cache": "^6.0.0",
|
"lru-cache": "^8.0.0",
|
||||||
"named-placeholders": "^1.1.2",
|
"named-placeholders": "^1.1.3",
|
||||||
"seq-queue": "^0.0.5",
|
"seq-queue": "^0.0.5",
|
||||||
"sqlstring": "^2.3.2"
|
"sqlstring": "^2.3.2"
|
||||||
},
|
},
|
||||||
@ -2553,34 +2574,25 @@
|
|||||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sqlstring": {
|
"lru-cache": {
|
||||||
"version": "2.3.3",
|
"version": "8.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz",
|
||||||
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="
|
"integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"named-placeholders": {
|
"named-placeholders": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz",
|
||||||
"integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==",
|
"integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"lru-cache": "^4.1.3"
|
"lru-cache": "^7.14.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lru-cache": {
|
"lru-cache": {
|
||||||
"version": "4.1.5",
|
"version": "7.18.3",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
|
||||||
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
"integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="
|
||||||
"requires": {
|
|
||||||
"pseudomap": "^1.0.2",
|
|
||||||
"yallist": "^2.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"yallist": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
|
||||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -2836,11 +2848,6 @@
|
|||||||
"ipaddr.js": "1.9.1"
|
"ipaddr.js": "1.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pseudomap": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
|
||||||
},
|
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
@ -2884,7 +2891,7 @@
|
|||||||
},
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.3.6",
|
"version": "2.3.6",
|
||||||
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"core-util-is": "~1.0.0",
|
"core-util-is": "~1.0.0",
|
||||||
@ -3086,7 +3093,7 @@
|
|||||||
"seq-queue": {
|
"seq-queue": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
|
||||||
"integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4="
|
"integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
|
||||||
},
|
},
|
||||||
"serve-static": {
|
"serve-static": {
|
||||||
"version": "1.15.0",
|
"version": "1.15.0",
|
||||||
@ -3215,6 +3222,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||||
},
|
},
|
||||||
|
"sqlstring": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="
|
||||||
|
},
|
||||||
"standard-as-callback": {
|
"standard-as-callback": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
||||||
|
|||||||
@ -20,9 +20,9 @@
|
|||||||
"cron": "1.5.0",
|
"cron": "1.5.0",
|
||||||
"deep-equal": "1.0.1",
|
"deep-equal": "1.0.1",
|
||||||
"dmdb": "1.0.14280",
|
"dmdb": "1.0.14280",
|
||||||
"ejs": "3.1.8",
|
"ejs": "3.1.10",
|
||||||
"exif-parser": "0.1.12",
|
"exif-parser": "0.1.12",
|
||||||
"express": "4.18.2",
|
"express": "4.19.2",
|
||||||
"fakeredis": "2.0.0",
|
"fakeredis": "2.0.0",
|
||||||
"ioredis": "5.3.1",
|
"ioredis": "5.3.1",
|
||||||
"jimp": "0.22.10",
|
"jimp": "0.22.10",
|
||||||
@ -35,7 +35,7 @@
|
|||||||
"multer": "1.4.3",
|
"multer": "1.4.3",
|
||||||
"multi-integer-range": "4.0.7",
|
"multi-integer-range": "4.0.7",
|
||||||
"multiparty": "4.2.1",
|
"multiparty": "4.2.1",
|
||||||
"mysql2": "2.3.3",
|
"mysql2": "3.9.8",
|
||||||
"oracledb": "6.3.0",
|
"oracledb": "6.3.0",
|
||||||
"pg": "8.11.3",
|
"pg": "8.11.3",
|
||||||
"redis": "4.6.11",
|
"redis": "4.6.11",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -53,6 +53,7 @@ var statsDClient = require('./../../Common/sources/statsdclient');
|
|||||||
var operationContext = require('./../../Common/sources/operationContext');
|
var operationContext = require('./../../Common/sources/operationContext');
|
||||||
var tenantManager = require('./../../Common/sources/tenantManager');
|
var tenantManager = require('./../../Common/sources/tenantManager');
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
const cfgTypesUpload = config.get('services.CoAuthoring.utils.limits_image_types_upload');
|
const cfgTypesUpload = config.get('services.CoAuthoring.utils.limits_image_types_upload');
|
||||||
const cfgImageSize = config.get('services.CoAuthoring.server.limits_image_size');
|
const cfgImageSize = config.get('services.CoAuthoring.server.limits_image_size');
|
||||||
@ -70,6 +71,7 @@ const cfgAssemblyFormatAsOrigin = config.get('services.CoAuthoring.server.assemb
|
|||||||
const cfgDownloadMaxBytes = config.get('FileConverter.converter.maxDownloadBytes');
|
const cfgDownloadMaxBytes = config.get('FileConverter.converter.maxDownloadBytes');
|
||||||
const cfgDownloadTimeout = config.get('FileConverter.converter.downloadTimeout');
|
const cfgDownloadTimeout = config.get('FileConverter.converter.downloadTimeout');
|
||||||
const cfgDownloadFileAllowExt = config.get('services.CoAuthoring.server.downloadFileAllowExt');
|
const cfgDownloadFileAllowExt = config.get('services.CoAuthoring.server.downloadFileAllowExt');
|
||||||
|
const cfgNewFileTemplate = config.get('services.CoAuthoring.server.newFileTemplate');
|
||||||
|
|
||||||
var SAVE_TYPE_PART_START = 0;
|
var SAVE_TYPE_PART_START = 0;
|
||||||
var SAVE_TYPE_PART = 1;
|
var SAVE_TYPE_PART = 1;
|
||||||
@ -160,7 +162,7 @@ function getOpenedAt(row) {
|
|||||||
function getOpenedAtJSONParams(row) {
|
function getOpenedAtJSONParams(row) {
|
||||||
let openedAt = getOpenedAt(row);
|
let openedAt = getOpenedAt(row);
|
||||||
if (openedAt) {
|
if (openedAt) {
|
||||||
return JSON.stringify({'documentLayout': {'openedAt': openedAt}});
|
return {'documentLayout': {'openedAt': openedAt}};
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -278,17 +280,13 @@ var getOutputData = co.wrap(function* (ctx, cmd, outputData, key, optConn, optAd
|
|||||||
outputData.setData(statusInfo);
|
outputData.setData(statusInfo);
|
||||||
break;
|
break;
|
||||||
case commonDefines.FileStatus.Err:
|
case commonDefines.FileStatus.Err:
|
||||||
|
outputData.setStatus('err');
|
||||||
|
outputData.setData(statusInfo);
|
||||||
|
break;
|
||||||
case commonDefines.FileStatus.ErrToReload:
|
case commonDefines.FileStatus.ErrToReload:
|
||||||
outputData.setStatus('err');
|
outputData.setStatus('err');
|
||||||
outputData.setData(statusInfo);
|
outputData.setData(statusInfo);
|
||||||
if (commonDefines.FileStatus.ErrToReload == status) {
|
yield cleanupErrToReload(ctx, key);
|
||||||
let userAuthStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback);
|
|
||||||
let wopiParams = wopiClient.parseWopiCallback(ctx, userAuthStr);
|
|
||||||
if (!wopiParams) {
|
|
||||||
//todo rework ErrToReload to clean up on next open
|
|
||||||
yield cleanupCache(ctx, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case commonDefines.FileStatus.None:
|
case commonDefines.FileStatus.None:
|
||||||
//this status has no handler
|
//this status has no handler
|
||||||
@ -377,38 +375,40 @@ function getSaveTask(ctx, cmd) {
|
|||||||
//}
|
//}
|
||||||
return queueData;
|
return queueData;
|
||||||
}
|
}
|
||||||
function* getUpdateResponse(ctx, cmd) {
|
async function getUpdateResponse(ctx, cmd) {
|
||||||
const tenOpenProtectedFile = ctx.getCfg('services.CoAuthoring.server.openProtectedFile', cfgOpenProtectedFile);
|
const tenOpenProtectedFile = ctx.getCfg('services.CoAuthoring.server.openProtectedFile', cfgOpenProtectedFile);
|
||||||
|
|
||||||
var updateTask = new taskResult.TaskResultData();
|
var updateTask = new taskResult.TaskResultData();
|
||||||
updateTask.tenant = ctx.tenant;
|
updateTask.tenant = ctx.tenant;
|
||||||
updateTask.key = cmd.getSaveKey() ? cmd.getSaveKey() : cmd.getDocId();
|
updateTask.key = cmd.getSaveKey() ? cmd.getSaveKey() : cmd.getDocId();
|
||||||
var statusInfo = cmd.getStatusInfo();
|
var statusInfo = cmd.getStatusInfo();
|
||||||
if (constants.NO_ERROR == statusInfo) {
|
if (constants.NO_ERROR === statusInfo) {
|
||||||
updateTask.status = commonDefines.FileStatus.Ok;
|
updateTask.status = commonDefines.FileStatus.Ok;
|
||||||
let password = cmd.getPassword();
|
let password = cmd.getPassword();
|
||||||
if (password) {
|
if (password) {
|
||||||
if (false === hasPasswordCol) {
|
if (false === hasPasswordCol) {
|
||||||
let selectRes = yield taskResult.select(ctx, updateTask.key);
|
let selectRes = await taskResult.select(ctx, updateTask.key);
|
||||||
hasPasswordCol = selectRes.length > 0 && undefined !== selectRes[0].password;
|
hasPasswordCol = selectRes.length > 0 && undefined !== selectRes[0].password;
|
||||||
}
|
}
|
||||||
if(hasPasswordCol) {
|
if(hasPasswordCol) {
|
||||||
updateTask.password = password;
|
updateTask.password = password;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (constants.CONVERT_DOWNLOAD == statusInfo) {
|
} else if (constants.CONVERT_DOWNLOAD === statusInfo) {
|
||||||
updateTask.status = commonDefines.FileStatus.ErrToReload;
|
updateTask.status = commonDefines.FileStatus.ErrToReload;
|
||||||
} else if (constants.CONVERT_NEED_PARAMS == statusInfo) {
|
} else if (constants.CONVERT_LIMITS === statusInfo) {
|
||||||
|
updateTask.status = commonDefines.FileStatus.ErrToReload;
|
||||||
|
} else if (constants.CONVERT_NEED_PARAMS === statusInfo) {
|
||||||
updateTask.status = commonDefines.FileStatus.NeedParams;
|
updateTask.status = commonDefines.FileStatus.NeedParams;
|
||||||
} else if (constants.CONVERT_DRM == statusInfo || constants.CONVERT_PASSWORD == statusInfo) {
|
} else if (constants.CONVERT_DRM === statusInfo || constants.CONVERT_PASSWORD === statusInfo) {
|
||||||
if (tenOpenProtectedFile) {
|
if (tenOpenProtectedFile) {
|
||||||
updateTask.status = commonDefines.FileStatus.NeedPassword;
|
updateTask.status = commonDefines.FileStatus.NeedPassword;
|
||||||
} else {
|
} else {
|
||||||
updateTask.status = commonDefines.FileStatus.Err;
|
updateTask.status = commonDefines.FileStatus.Err;
|
||||||
}
|
}
|
||||||
} else if (constants.CONVERT_DRM_UNSUPPORTED == statusInfo) {
|
} else if (constants.CONVERT_DRM_UNSUPPORTED === statusInfo) {
|
||||||
updateTask.status = commonDefines.FileStatus.Err;
|
updateTask.status = commonDefines.FileStatus.Err;
|
||||||
} else if (constants.CONVERT_DEAD_LETTER == statusInfo) {
|
} else if (constants.CONVERT_DEAD_LETTER === statusInfo) {
|
||||||
updateTask.status = commonDefines.FileStatus.ErrToReload;
|
updateTask.status = commonDefines.FileStatus.ErrToReload;
|
||||||
} else {
|
} else {
|
||||||
updateTask.status = commonDefines.FileStatus.Err;
|
updateTask.status = commonDefines.FileStatus.Err;
|
||||||
@ -439,6 +439,14 @@ var cleanupCacheIf = co.wrap(function* (ctx, mask) {
|
|||||||
ctx.logger.debug("cleanupCacheIf db.affectedRows=%d", removeRes.affectedRows);
|
ctx.logger.debug("cleanupCacheIf db.affectedRows=%d", removeRes.affectedRows);
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
|
async function cleanupErrToReload(ctx, key) {
|
||||||
|
let updateTask = new taskResult.TaskResultData();
|
||||||
|
updateTask.tenant = ctx.tenant;
|
||||||
|
updateTask.key = key;
|
||||||
|
updateTask.status = commonDefines.FileStatus.None;
|
||||||
|
updateTask.statusInfo = constants.NO_ERROR;
|
||||||
|
await taskResult.update(ctx, updateTask);
|
||||||
|
}
|
||||||
|
|
||||||
function commandOpenStartPromise(ctx, docId, baseUrl, opt_documentCallbackUrl, opt_format) {
|
function commandOpenStartPromise(ctx, docId, baseUrl, opt_documentCallbackUrl, opt_format) {
|
||||||
var task = new taskResult.TaskResultData();
|
var task = new taskResult.TaskResultData();
|
||||||
@ -616,10 +624,11 @@ let commandSfctByCmd = co.wrap(function*(ctx, cmd, opt_priority, opt_expiration,
|
|||||||
var selectRes = yield taskResult.select(ctx, cmd.getDocId());
|
var selectRes = yield taskResult.select(ctx, cmd.getDocId());
|
||||||
var row = selectRes.length > 0 ? selectRes[0] : null;
|
var row = selectRes.length > 0 ? selectRes[0] : null;
|
||||||
if (!row) {
|
if (!row) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (opt_initShardKey) {
|
if (opt_initShardKey) {
|
||||||
ctx.setShardKey(sqlBase.DocumentAdditional.prototype.getShardKey(row.additional));
|
ctx.setShardKey(sqlBase.DocumentAdditional.prototype.getShardKey(row.additional));
|
||||||
|
ctx.setWopiSrc(sqlBase.DocumentAdditional.prototype.getWopiSrc(row.additional));
|
||||||
}
|
}
|
||||||
yield* addRandomKeyTaskCmd(ctx, cmd);
|
yield* addRandomKeyTaskCmd(ctx, cmd);
|
||||||
addPasswordToCmd(ctx, cmd, row.password);
|
addPasswordToCmd(ctx, cmd, row.password);
|
||||||
@ -627,11 +636,12 @@ let commandSfctByCmd = co.wrap(function*(ctx, cmd, opt_priority, opt_expiration,
|
|||||||
let userAuthStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback);
|
let userAuthStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback);
|
||||||
cmd.setWopiParams(wopiClient.parseWopiCallback(ctx, userAuthStr, row.callback));
|
cmd.setWopiParams(wopiClient.parseWopiCallback(ctx, userAuthStr, row.callback));
|
||||||
cmd.setOutputFormat(changeFormatByOrigin(ctx, row, cmd.getOutputFormat()));
|
cmd.setOutputFormat(changeFormatByOrigin(ctx, row, cmd.getOutputFormat()));
|
||||||
cmd.setJsonParams(getOpenedAtJSONParams(row));
|
cmd.appendJsonParams(getOpenedAtJSONParams(row));
|
||||||
var queueData = getSaveTask(ctx, cmd);
|
var queueData = getSaveTask(ctx, cmd);
|
||||||
queueData.setFromChanges(true);
|
queueData.setFromChanges(true);
|
||||||
let priority = null != opt_priority ? opt_priority : constants.QUEUE_PRIORITY_LOW;
|
let priority = null != opt_priority ? opt_priority : constants.QUEUE_PRIORITY_LOW;
|
||||||
yield* docsCoServer.addTask(queueData, priority, opt_queue, opt_expiration);
|
yield* docsCoServer.addTask(queueData, priority, opt_queue, opt_expiration);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
function isDisplayedImage(strName) {
|
function isDisplayedImage(strName) {
|
||||||
var res = 0;
|
var res = 0;
|
||||||
@ -827,6 +837,7 @@ function* commandSaveFromOrigin(ctx, cmd, outputData, password) {
|
|||||||
if (docPassword.initial) {
|
if (docPassword.initial) {
|
||||||
cmd.setPassword(docPassword.initial);
|
cmd.setPassword(docPassword.initial);
|
||||||
}
|
}
|
||||||
|
//todo setLCID in browser
|
||||||
var queueData = getSaveTask(ctx, cmd);
|
var queueData = getSaveTask(ctx, cmd);
|
||||||
queueData.setFromOrigin(true);
|
queueData.setFromOrigin(true);
|
||||||
queueData.setFromChanges(true);
|
queueData.setFromChanges(true);
|
||||||
@ -847,8 +858,11 @@ function* commandSetPassword(ctx, conn, cmd, outputData) {
|
|||||||
hasDocumentPassword = true;
|
hasDocumentPassword = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.logger.debug('commandSetPassword isEnterCorrectPassword=%s, hasDocumentPassword=%s, hasPasswordCol=%s', conn.isEnterCorrectPassword, hasDocumentPassword, hasPasswordCol);
|
//https://github.com/ONLYOFFICE/web-apps/blob/4a7879b4f88f315fe94d9f7d97c0ed8aa9f82221/apps/documenteditor/main/app/controller/Main.js#L1652
|
||||||
if (tenOpenProtectedFile && (conn.isEnterCorrectPassword || !hasDocumentPassword) && hasPasswordCol) {
|
//this.appOptions.isPasswordSupport = this.appOptions.isEdit && this.api.asc_isProtectionSupport() && (this.permissions.protect!==false);
|
||||||
|
let isPasswordSupport = tenOpenProtectedFile && !conn.user?.view && false !== conn.permissions?.protect;
|
||||||
|
ctx.logger.debug('commandSetPassword isEnterCorrectPassword=%s, hasDocumentPassword=%s, hasPasswordCol=%s, isPasswordSupport=%s', conn.isEnterCorrectPassword, hasDocumentPassword, hasPasswordCol, isPasswordSupport);
|
||||||
|
if (isPasswordSupport && (conn.isEnterCorrectPassword || !hasDocumentPassword) && hasPasswordCol) {
|
||||||
let updateMask = new taskResult.TaskResultData();
|
let updateMask = new taskResult.TaskResultData();
|
||||||
updateMask.tenant = ctx.tenant;
|
updateMask.tenant = ctx.tenant;
|
||||||
updateMask.key = cmd.getDocId();
|
updateMask.key = cmd.getDocId();
|
||||||
@ -861,7 +875,7 @@ function* commandSetPassword(ctx, conn, cmd, outputData) {
|
|||||||
task.password = cmd.getPassword() || "";
|
task.password = cmd.getPassword() || "";
|
||||||
let changeInfo = null;
|
let changeInfo = null;
|
||||||
if (conn.user) {
|
if (conn.user) {
|
||||||
changeInfo = task.innerPasswordChange = docsCoServer.getExternalChangeInfo(conn.user, newChangesLastDate.getTime());
|
changeInfo = task.innerPasswordChange = docsCoServer.getExternalChangeInfo(conn.user, newChangesLastDate.getTime(), conn.lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
var upsertRes = yield taskResult.updateIf(ctx, task, updateMask);
|
var upsertRes = yield taskResult.updateIf(ctx, task, updateMask);
|
||||||
@ -1066,8 +1080,17 @@ const commandSfcCallback = co.wrap(function*(ctx, cmd, isSfcm, isEncrypted) {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
if (wopiParams) {
|
if (wopiParams) {
|
||||||
let isAutoSave = forceSaveType !== commonDefines.c_oAscForceSaveTypes.Button && forceSaveType !== commonDefines.c_oAscForceSaveTypes.Form;
|
if (outputSfc.getUrl()) {
|
||||||
replyStr = yield processWopiPutFile(ctx, docId, wopiParams, savePathDoc, userLastChangeId, true, isAutoSave, false);
|
if (forceSaveType === commonDefines.c_oAscForceSaveTypes.Form) {
|
||||||
|
yield processWopiSaveAs(ctx, cmd);
|
||||||
|
replyStr = JSON.stringify({error: 0});
|
||||||
|
} else {
|
||||||
|
let isAutoSave = forceSaveType !== commonDefines.c_oAscForceSaveTypes.Button && forceSaveType !== commonDefines.c_oAscForceSaveTypes.Form;
|
||||||
|
replyStr = yield processWopiPutFile(ctx, docId, wopiParams, savePathDoc, userLastChangeId, true, isAutoSave, false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
replyStr = JSON.stringify({error: 1, descr: "wopi: no file"});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
replyStr = yield docsCoServer.sendServerRequest(ctx, uri, outputSfc, checkAndFixAuthorizationLength);
|
replyStr = yield docsCoServer.sendServerRequest(ctx, uri, outputSfc, checkAndFixAuthorizationLength);
|
||||||
}
|
}
|
||||||
@ -1100,7 +1123,11 @@ const commandSfcCallback = co.wrap(function*(ctx, cmd, isSfcm, isEncrypted) {
|
|||||||
updateMask.statusInfo = updateIfTask.statusInfo;
|
updateMask.statusInfo = updateIfTask.statusInfo;
|
||||||
try {
|
try {
|
||||||
if (wopiParams) {
|
if (wopiParams) {
|
||||||
replyStr = yield processWopiPutFile(ctx, docId, wopiParams, savePathDoc, userLastChangeId, !notModified, false, true);
|
if (outputSfc.getUrl()) {
|
||||||
|
replyStr = yield processWopiPutFile(ctx, docId, wopiParams, savePathDoc, userLastChangeId, !notModified, false, true);
|
||||||
|
} else {
|
||||||
|
replyStr = JSON.stringify({error: 1, descr: "wopi: no file"});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
replyStr = yield docsCoServer.sendServerRequest(ctx, uri, outputSfc, checkAndFixAuthorizationLength);
|
replyStr = yield docsCoServer.sendServerRequest(ctx, uri, outputSfc, checkAndFixAuthorizationLength);
|
||||||
}
|
}
|
||||||
@ -1167,6 +1194,8 @@ const commandSfcCallback = co.wrap(function*(ctx, cmd, isSfcm, isEncrypted) {
|
|||||||
}
|
}
|
||||||
if (!isSfcm) {
|
if (!isSfcm) {
|
||||||
//todo simultaneous opening
|
//todo simultaneous opening
|
||||||
|
//clean redis (redisKeyPresenceSet and redisKeyPresenceHash removed with last element)
|
||||||
|
yield docsCoServer.editorData.cleanDocumentOnExit(ctx, docId);
|
||||||
//to unlock wopi file
|
//to unlock wopi file
|
||||||
yield docsCoServer.unlockWopiDoc(ctx, docId, callbackUserIndex);
|
yield docsCoServer.unlockWopiDoc(ctx, docId, callbackUserIndex);
|
||||||
//cleanupRes can be false in case of simultaneous opening. it is OK
|
//cleanupRes can be false in case of simultaneous opening. it is OK
|
||||||
@ -1194,7 +1223,7 @@ const commandSfcCallback = co.wrap(function*(ctx, cmd, isSfcm, isEncrypted) {
|
|||||||
|
|
||||||
if ((docsCoServer.getIsShutdown() && !isSfcm) || cmd.getRedisKey()) {
|
if ((docsCoServer.getIsShutdown() && !isSfcm) || cmd.getRedisKey()) {
|
||||||
let keyRedis = cmd.getRedisKey() ? cmd.getRedisKey() : redisKeyShutdown;
|
let keyRedis = cmd.getRedisKey() ? cmd.getRedisKey() : redisKeyShutdown;
|
||||||
yield docsCoServer.editorData.removeShutdown(keyRedis, docId);
|
yield docsCoServer.editorStat.removeShutdown(keyRedis, docId);
|
||||||
}
|
}
|
||||||
ctx.logger.debug('End commandSfcCallback');
|
ctx.logger.debug('End commandSfcCallback');
|
||||||
return replyStr;
|
return replyStr;
|
||||||
@ -1513,7 +1542,10 @@ function getPrintFileUrl(ctx, docId, baseUrl, filename) {
|
|||||||
let userFriendlyName = encodeURIComponent(filename.replace(/\//g, "%2f"));
|
let userFriendlyName = encodeURIComponent(filename.replace(/\//g, "%2f"));
|
||||||
let res = `${baseUrl}/printfile/${encodeURIComponent(docId)}/${userFriendlyName}?token=${encodeURIComponent(token)}`;
|
let res = `${baseUrl}/printfile/${encodeURIComponent(docId)}/${userFriendlyName}?token=${encodeURIComponent(token)}`;
|
||||||
if (ctx.shardKey) {
|
if (ctx.shardKey) {
|
||||||
res += `&${constants.SHARED_KEY_NAME}=${encodeURIComponent(ctx.shardKey)}`;
|
res += `&${constants.SHARD_KEY_API_NAME}=${encodeURIComponent(ctx.shardKey)}`;
|
||||||
|
}
|
||||||
|
if (ctx.wopiSrc) {
|
||||||
|
res += `&${constants.SHARD_KEY_WOPI_NAME}=${encodeURIComponent(ctx.wopiSrc)}`;
|
||||||
}
|
}
|
||||||
res += `&filename=${userFriendlyName}`;
|
res += `&filename=${userFriendlyName}`;
|
||||||
return res;
|
return res;
|
||||||
@ -1594,10 +1626,12 @@ exports.downloadFile = function(req, res) {
|
|||||||
const tenDownloadMaxBytes = ctx.getCfg('FileConverter.converter.maxDownloadBytes', cfgDownloadMaxBytes);
|
const tenDownloadMaxBytes = ctx.getCfg('FileConverter.converter.maxDownloadBytes', cfgDownloadMaxBytes);
|
||||||
const tenDownloadTimeout = ctx.getCfg('FileConverter.converter.downloadTimeout', cfgDownloadTimeout);
|
const tenDownloadTimeout = ctx.getCfg('FileConverter.converter.downloadTimeout', cfgDownloadTimeout);
|
||||||
const tenDownloadFileAllowExt = ctx.getCfg('services.CoAuthoring.server.downloadFileAllowExt', cfgDownloadFileAllowExt);
|
const tenDownloadFileAllowExt = ctx.getCfg('services.CoAuthoring.server.downloadFileAllowExt', cfgDownloadFileAllowExt);
|
||||||
|
const tenNewFileTemplate = ctx.getCfg('services.CoAuthoring.server.newFileTemplate', cfgNewFileTemplate);
|
||||||
|
|
||||||
let authorization;
|
let authorization;
|
||||||
let isInJwtToken = false;
|
let isInJwtToken = false;
|
||||||
let errorDescription;
|
let errorDescription;
|
||||||
|
let headers, fromTemplate;
|
||||||
let authRes = yield docsCoServer.getRequestParams(ctx, req);
|
let authRes = yield docsCoServer.getRequestParams(ctx, req);
|
||||||
if (authRes.code === constants.NO_ERROR) {
|
if (authRes.code === constants.NO_ERROR) {
|
||||||
let decoded = authRes.params;
|
let decoded = authRes.params;
|
||||||
@ -1610,6 +1644,21 @@ exports.downloadFile = function(req, res) {
|
|||||||
} else if (decoded.url && -1 !== tenDownloadFileAllowExt.indexOf(decoded.fileType)) {
|
} else if (decoded.url && -1 !== tenDownloadFileAllowExt.indexOf(decoded.fileType)) {
|
||||||
url = decoded.url;
|
url = decoded.url;
|
||||||
isInJwtToken = true;
|
isInJwtToken = true;
|
||||||
|
} else if (wopiClient.isWopiJwtToken(decoded)) {
|
||||||
|
if (decoded.fileInfo.Size === 0) {
|
||||||
|
//editnew case
|
||||||
|
fromTemplate = pathModule.extname(decoded.fileInfo.BaseFileName).substring(1);
|
||||||
|
} else {
|
||||||
|
({url, headers} = yield wopiClient.getWopiFileUrl(ctx, decoded.fileInfo, decoded.userAuth));
|
||||||
|
let filterStatus = yield wopiClient.checkIpFilter(ctx, url);
|
||||||
|
if (0 === filterStatus) {
|
||||||
|
//todo false? (true because it passed checkIpFilter for wopi)
|
||||||
|
//todo use directIfIn
|
||||||
|
isInJwtToken = true;
|
||||||
|
} else {
|
||||||
|
errorDescription = 'access deny';
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (!tenTokenEnableBrowser) {
|
} else if (!tenTokenEnableBrowser) {
|
||||||
//todo token required
|
//todo token required
|
||||||
if (decoded.url) {
|
if (decoded.url) {
|
||||||
@ -1627,45 +1676,59 @@ exports.downloadFile = function(req, res) {
|
|||||||
res.sendStatus(403);
|
res.sendStatus(403);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (utils.canIncludeOutboxAuthorization(ctx, url)) {
|
if (fromTemplate) {
|
||||||
let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Outbox);
|
ctx.logger.debug('downloadFile from file template: %s', fromTemplate);
|
||||||
authorization = utils.fillJwtForRequest(ctx, {url: url}, secret, false);
|
let locale = constants.TEMPLATES_DEFAULT_LOCALE;
|
||||||
}
|
let fileTemplatePath = pathModule.join(tenNewFileTemplate, locale, 'new.' + fromTemplate);
|
||||||
let urlParsed = urlModule.parse(url);
|
res.sendFile(pathModule.resolve(fileTemplatePath));
|
||||||
let filterStatus = yield* utils.checkHostFilter(ctx, urlParsed.hostname);
|
} else {
|
||||||
if (0 !== filterStatus) {
|
if (utils.canIncludeOutboxAuthorization(ctx, url)) {
|
||||||
ctx.logger.warn('Error downloadFile checkIpFilter error: url = %s', url);
|
let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Outbox);
|
||||||
res.sendStatus(filterStatus);
|
authorization = utils.fillJwtForRequest(ctx, {url: url}, secret, false);
|
||||||
return;
|
}
|
||||||
}
|
let urlParsed = urlModule.parse(url);
|
||||||
let headers;
|
let filterStatus = yield* utils.checkHostFilter(ctx, urlParsed.hostname);
|
||||||
if (req.get('Range')) {
|
if (0 !== filterStatus) {
|
||||||
headers = {
|
ctx.logger.warn('Error downloadFile checkIpFilter error: url = %s', url);
|
||||||
'Range': req.get('Range')
|
res.sendStatus(filterStatus);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
yield utils.downloadUrlPromise(ctx, url, tenDownloadTimeout, tenDownloadMaxBytes, authorization, isInJwtToken, headers, res);
|
if (req.get('Range')) {
|
||||||
|
if (!headers) {
|
||||||
|
headers = {};
|
||||||
|
}
|
||||||
|
headers['Range'] = req.get('Range');
|
||||||
|
}
|
||||||
|
|
||||||
|
yield utils.downloadUrlPromise(ctx, url, tenDownloadTimeout, tenDownloadMaxBytes, authorization, isInJwtToken, headers, res);
|
||||||
|
}
|
||||||
|
|
||||||
if (clientStatsD) {
|
if (clientStatsD) {
|
||||||
clientStatsD.timing('coauth.downloadFile', new Date() - startDate);
|
clientStatsD.timing('coauth.downloadFile', new Date() - startDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
ctx.logger.error('Error downloadFile: %s', err.stack);
|
if (err.code === "ERR_STREAM_PREMATURE_CLOSE") {
|
||||||
//catch errors because status may be sent while piping to response
|
ctx.logger.debug('Error downloadFile: %s', err.stack);
|
||||||
try {
|
} else {
|
||||||
if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') {
|
|
||||||
res.sendStatus(408);
|
|
||||||
} else if (err.code === 'EMSGSIZE') {
|
|
||||||
res.sendStatus(413);
|
|
||||||
} else if (err.response) {
|
|
||||||
res.sendStatus(err.response.statusCode);
|
|
||||||
} else {
|
|
||||||
res.sendStatus(400);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
ctx.logger.error('Error downloadFile: %s', err.stack);
|
ctx.logger.error('Error downloadFile: %s', err.stack);
|
||||||
|
//catch errors because status may be sent while piping to response
|
||||||
|
if (!res.headersSent) {
|
||||||
|
try {
|
||||||
|
if (err.code === 'ETIMEDOUT' || err.code === 'ESOCKETTIMEDOUT') {
|
||||||
|
res.sendStatus(408);
|
||||||
|
} else if (err.code === 'EMSGSIZE') {
|
||||||
|
res.sendStatus(413);
|
||||||
|
} else if (err.response) {
|
||||||
|
res.sendStatus(err.response.statusCode);
|
||||||
|
} else {
|
||||||
|
res.sendStatus(400);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
ctx.logger.error('Error downloadFile: %s', err.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
@ -1673,7 +1736,7 @@ exports.downloadFile = function(req, res) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.saveFromChanges = function(ctx, docId, statusInfo, optFormat, opt_userId, opt_userIndex, opt_queue, opt_initShardKey) {
|
exports.saveFromChanges = function(ctx, docId, statusInfo, optFormat, opt_userId, opt_userIndex, opt_userLcid, opt_queue, opt_initShardKey) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
try {
|
try {
|
||||||
var startDate = null;
|
var startDate = null;
|
||||||
@ -1690,6 +1753,7 @@ exports.saveFromChanges = function(ctx, docId, statusInfo, optFormat, opt_userId
|
|||||||
}
|
}
|
||||||
if (opt_initShardKey) {
|
if (opt_initShardKey) {
|
||||||
ctx.setShardKey(sqlBase.DocumentAdditional.prototype.getShardKey(row.additional));
|
ctx.setShardKey(sqlBase.DocumentAdditional.prototype.getShardKey(row.additional));
|
||||||
|
ctx.setWopiSrc(sqlBase.DocumentAdditional.prototype.getWopiSrc(row.additional));
|
||||||
}
|
}
|
||||||
var cmd = new commonDefines.InputCommand();
|
var cmd = new commonDefines.InputCommand();
|
||||||
cmd.setCommand('sfc');
|
cmd.setCommand('sfc');
|
||||||
@ -1698,7 +1762,9 @@ exports.saveFromChanges = function(ctx, docId, statusInfo, optFormat, opt_userId
|
|||||||
cmd.setStatusInfoIn(statusInfo);
|
cmd.setStatusInfoIn(statusInfo);
|
||||||
cmd.setUserActionId(opt_userId);
|
cmd.setUserActionId(opt_userId);
|
||||||
cmd.setUserActionIndex(opt_userIndex);
|
cmd.setUserActionIndex(opt_userIndex);
|
||||||
cmd.setJsonParams(getOpenedAtJSONParams(row));
|
cmd.appendJsonParams(getOpenedAtJSONParams(row));
|
||||||
|
//todo lang and region are different
|
||||||
|
cmd.setLCID(opt_userLcid);
|
||||||
let userAuthStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback);
|
let userAuthStr = sqlBase.UserCallback.prototype.getCallbackByUserIndex(ctx, row.callback);
|
||||||
cmd.setWopiParams(wopiClient.parseWopiCallback(ctx, userAuthStr, row.callback));
|
cmd.setWopiParams(wopiClient.parseWopiCallback(ctx, userAuthStr, row.callback));
|
||||||
addPasswordToCmd(ctx, cmd, row && row.password);
|
addPasswordToCmd(ctx, cmd, row && row.password);
|
||||||
@ -1708,7 +1774,7 @@ exports.saveFromChanges = function(ctx, docId, statusInfo, optFormat, opt_userId
|
|||||||
queueData.setFromChanges(true);
|
queueData.setFromChanges(true);
|
||||||
yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_NORMAL, opt_queue);
|
yield* docsCoServer.addTask(queueData, constants.QUEUE_PRIORITY_NORMAL, opt_queue);
|
||||||
if (docsCoServer.getIsShutdown()) {
|
if (docsCoServer.getIsShutdown()) {
|
||||||
yield docsCoServer.editorData.addShutdown(redisKeyShutdown, docId);
|
yield docsCoServer.editorStat.addShutdown(redisKeyShutdown, docId);
|
||||||
}
|
}
|
||||||
ctx.logger.debug('AddTask saveFromChanges');
|
ctx.logger.debug('AddTask saveFromChanges');
|
||||||
} else {
|
} else {
|
||||||
@ -1725,6 +1791,18 @@ exports.saveFromChanges = function(ctx, docId, statusInfo, optFormat, opt_userId
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function processWopiSaveAs(ctx, cmd) {
|
||||||
|
const info = await docsCoServer.getCallback(ctx, cmd.getDocId(), cmd.getUserIndex());
|
||||||
|
// info.wopiParams is null if it is not wopi
|
||||||
|
if (info.wopiParams) {
|
||||||
|
const suggestedTargetType = `.${formatChecker.getStringFromFormat(cmd.getOutputFormat())}`;
|
||||||
|
const storageFilePath = `${cmd.getSaveKey()}/${cmd.getOutputPath()}`;
|
||||||
|
const stream = await storage.createReadStream(ctx, storageFilePath);
|
||||||
|
const { wopiSrc, access_token } = info.wopiParams.userAuth;
|
||||||
|
await wopiClient.putRelativeFile(ctx, wopiSrc, access_token, null, stream.readStream, stream.contentLength, suggestedTargetType, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
exports.receiveTask = function(data, ack) {
|
exports.receiveTask = function(data, ack) {
|
||||||
return co(function* () {
|
return co(function* () {
|
||||||
let ctx = new operationContext.Context();
|
let ctx = new operationContext.Context();
|
||||||
@ -1735,29 +1813,33 @@ exports.receiveTask = function(data, ack) {
|
|||||||
ctx.initFromTaskQueueData(task);
|
ctx.initFromTaskQueueData(task);
|
||||||
yield ctx.initTenantCache();
|
yield ctx.initTenantCache();
|
||||||
ctx.logger.info('receiveTask start: %s', data);
|
ctx.logger.info('receiveTask start: %s', data);
|
||||||
var updateTask = yield* getUpdateResponse(ctx, cmd);
|
var updateTask = yield getUpdateResponse(ctx, cmd);
|
||||||
var updateRes = yield taskResult.update(ctx, updateTask);
|
var updateRes = yield taskResult.update(ctx, updateTask);
|
||||||
if (updateRes.affectedRows > 0) {
|
if (updateRes.affectedRows > 0) {
|
||||||
var outputData = new OutputData(cmd.getCommand());
|
var outputData = new OutputData(cmd.getCommand());
|
||||||
var command = cmd.getCommand();
|
var command = cmd.getCommand();
|
||||||
var additionalOutput = {needUrlKey: null, needUrlMethod: null, needUrlType: null, needUrlIsCorrectPassword: undefined, creationDate: undefined, openedAt: undefined};
|
var additionalOutput = {needUrlKey: null, needUrlMethod: null, needUrlType: null, needUrlIsCorrectPassword: undefined, creationDate: undefined, openedAt: undefined};
|
||||||
if ('open' == command || 'reopen' == command) {
|
if ('open' === command || 'reopen' === command) {
|
||||||
yield getOutputData(ctx, cmd, outputData, cmd.getDocId(), null, additionalOutput);
|
yield getOutputData(ctx, cmd, outputData, cmd.getDocId(), null, additionalOutput);
|
||||||
} else if ('save' == command || 'savefromorigin' == command) {
|
} else if ('save' === command || 'savefromorigin' === command) {
|
||||||
yield getOutputData(ctx, cmd, outputData, cmd.getSaveKey(), null, additionalOutput);
|
let status = yield getOutputData(ctx, cmd, outputData, cmd.getSaveKey(), null, additionalOutput);
|
||||||
} else if ('sfcm' == command) {
|
if (commonDefines.FileStatus.Ok === status && cmd.getIsSaveAs()) {
|
||||||
|
yield processWopiSaveAs(ctx, cmd);
|
||||||
|
//todo in case of wopi no need to send url. send it to avoid stubs in sdk
|
||||||
|
}
|
||||||
|
} else if ('sfcm' === command) {
|
||||||
yield commandSfcCallback(ctx, cmd, true);
|
yield commandSfcCallback(ctx, cmd, true);
|
||||||
} else if ('sfc' == command) {
|
} else if ('sfc' === command) {
|
||||||
yield commandSfcCallback(ctx, cmd, false);
|
yield commandSfcCallback(ctx, cmd, false);
|
||||||
} else if ('sendmm' == command) {
|
} else if ('sendmm' === command) {
|
||||||
yield* commandSendMMCallback(ctx, cmd);
|
yield* commandSendMMCallback(ctx, cmd);
|
||||||
} else if ('conv' == command) {
|
} else if ('conv' === command) {
|
||||||
//nothing
|
//nothing
|
||||||
}
|
}
|
||||||
if (outputData.getStatus()) {
|
if (outputData.getStatus()) {
|
||||||
ctx.logger.debug('receiveTask publish: %s', JSON.stringify(outputData));
|
ctx.logger.debug('receiveTask publish: %s', JSON.stringify(outputData));
|
||||||
var output = new OutputDataWrap('documentOpen', outputData);
|
var output = new OutputDataWrap('documentOpen', outputData);
|
||||||
yield* docsCoServer.publish(ctx, {
|
yield docsCoServer.publish(ctx, {
|
||||||
type: commonDefines.c_oPublishType.receiveTask, ctx: ctx, cmd: cmd, output: output,
|
type: commonDefines.c_oPublishType.receiveTask, ctx: ctx, cmd: cmd, output: output,
|
||||||
needUrlKey: additionalOutput.needUrlKey,
|
needUrlKey: additionalOutput.needUrlKey,
|
||||||
needUrlMethod: additionalOutput.needUrlMethod,
|
needUrlMethod: additionalOutput.needUrlMethod,
|
||||||
@ -1780,6 +1862,7 @@ exports.receiveTask = function(data, ack) {
|
|||||||
|
|
||||||
exports.cleanupCache = cleanupCache;
|
exports.cleanupCache = cleanupCache;
|
||||||
exports.cleanupCacheIf = cleanupCacheIf;
|
exports.cleanupCacheIf = cleanupCacheIf;
|
||||||
|
exports.cleanupErrToReload = cleanupErrToReload;
|
||||||
exports.getOpenedAt = getOpenedAt;
|
exports.getOpenedAt = getOpenedAt;
|
||||||
exports.commandSfctByCmd = commandSfctByCmd;
|
exports.commandSfctByCmd = commandSfctByCmd;
|
||||||
exports.commandOpenStartPromise = commandOpenStartPromise;
|
exports.commandOpenStartPromise = commandOpenStartPromise;
|
||||||
|
|||||||
@ -44,7 +44,9 @@ const operationContext = require('./../../Common/sources/operationContext');
|
|||||||
const sqlBase = require('./databaseConnectors/baseConnector');
|
const sqlBase = require('./databaseConnectors/baseConnector');
|
||||||
const docsCoServer = require('./DocsCoServer');
|
const docsCoServer = require('./DocsCoServer');
|
||||||
const taskResult = require('./taskresult');
|
const taskResult = require('./taskresult');
|
||||||
const editorDataStorage = require('./' + config.get('services.CoAuthoring.server.editorDataStorage'));
|
const cfgEditorDataStorage = config.get('services.CoAuthoring.server.editorDataStorage');
|
||||||
|
const cfgEditorStatStorage = config.get('services.CoAuthoring.server.editorStatStorage');
|
||||||
|
const editorStatStorage = require('./' + (cfgEditorStatStorage || cfgEditorDataStorage));
|
||||||
|
|
||||||
const cfgForgottenFiles = config.get('services.CoAuthoring.server.forgottenfiles');
|
const cfgForgottenFiles = config.get('services.CoAuthoring.server.forgottenfiles');
|
||||||
const cfgTableResult = config.get('services.CoAuthoring.sql.tableResult');
|
const cfgTableResult = config.get('services.CoAuthoring.sql.tableResult');
|
||||||
@ -81,7 +83,7 @@ function shutdown() {
|
|||||||
var res = true;
|
var res = true;
|
||||||
let ctx = new operationContext.Context();
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
let editorData = new editorDataStorage();
|
let editorStat = editorStatStorage.EditorStat ? new editorStatStorage.EditorStat() : new editorStatStorage();
|
||||||
ctx.logger.debug('shutdown start:' + EXEC_TIMEOUT);
|
ctx.logger.debug('shutdown start:' + EXEC_TIMEOUT);
|
||||||
|
|
||||||
//redisKeyShutdown is not a simple counter, so it doesn't get decremented by a build that started before Shutdown started
|
//redisKeyShutdown is not a simple counter, so it doesn't get decremented by a build that started before Shutdown started
|
||||||
@ -130,9 +132,9 @@ function shutdown() {
|
|||||||
yield ctx.initTenantCache();
|
yield ctx.initTenantCache();
|
||||||
|
|
||||||
yield updateDoc(ctx, docId, commonDefines.FileStatus.Ok, "");
|
yield updateDoc(ctx, docId, commonDefines.FileStatus.Ok, "");
|
||||||
yield editorData.addShutdown(redisKeyShutdown, docId);
|
yield editorStat.addShutdown(redisKeyShutdown, docId);
|
||||||
ctx.logger.debug('shutdown createSaveTimerPromise %s', docId);
|
ctx.logger.debug('shutdown createSaveTimerPromise %s', docId);
|
||||||
yield docsCoServer.createSaveTimer(ctx, docId, null, null, queue, true);
|
yield docsCoServer.createSaveTimer(ctx, docId, null, null, null, queue, true);
|
||||||
}
|
}
|
||||||
ctx.initDefault();
|
ctx.initDefault();
|
||||||
//sleep because of bugs in createSaveTimerPromise
|
//sleep because of bugs in createSaveTimerPromise
|
||||||
@ -140,7 +142,7 @@ function shutdown() {
|
|||||||
|
|
||||||
let startTime = new Date().getTime();
|
let startTime = new Date().getTime();
|
||||||
while (true) {
|
while (true) {
|
||||||
let remainingFiles = yield editorData.getShutdownCount(redisKeyShutdown);
|
let remainingFiles = yield editorStat.getShutdownCount(redisKeyShutdown);
|
||||||
ctx.logger.debug('shutdown remaining files:%d', remainingFiles);
|
ctx.logger.debug('shutdown remaining files:%d', remainingFiles);
|
||||||
let curTime = new Date().getTime() - startTime;
|
let curTime = new Date().getTime() - startTime;
|
||||||
if (curTime >= EXEC_TIMEOUT || remainingFiles <= 0) {
|
if (curTime >= EXEC_TIMEOUT || remainingFiles <= 0) {
|
||||||
@ -169,7 +171,7 @@ function shutdown() {
|
|||||||
|
|
||||||
//todo needs to check queues, because there may be long conversions running before Shutdown
|
//todo needs to check queues, because there may be long conversions running before Shutdown
|
||||||
//clean up
|
//clean up
|
||||||
yield editorData.cleanupShutdown(redisKeyShutdown);
|
yield editorStat.cleanupShutdown(redisKeyShutdown);
|
||||||
yield pubsub.close();
|
yield pubsub.close();
|
||||||
yield queue.close();
|
yield queue.close();
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,6 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
var config = require('config');
|
var config = require('config');
|
||||||
var co = require('co');
|
var co = require('co');
|
||||||
const locale = require('windows-locale');
|
|
||||||
const mime = require('mime');
|
const mime = require('mime');
|
||||||
var taskResult = require('./taskresult');
|
var taskResult = require('./taskresult');
|
||||||
var utils = require('./../../Common/sources/utils');
|
var utils = require('./../../Common/sources/utils');
|
||||||
@ -50,6 +49,7 @@ var statsDClient = require('./../../Common/sources/statsdclient');
|
|||||||
var storageBase = require('./../../Common/sources/storage-base');
|
var storageBase = require('./../../Common/sources/storage-base');
|
||||||
var operationContext = require('./../../Common/sources/operationContext');
|
var operationContext = require('./../../Common/sources/operationContext');
|
||||||
const sqlBase = require('./databaseConnectors/baseConnector');
|
const sqlBase = require('./databaseConnectors/baseConnector');
|
||||||
|
const utilsDocService = require("./utilsDocService");
|
||||||
|
|
||||||
const cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.browser');
|
const cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.browser');
|
||||||
|
|
||||||
@ -83,12 +83,12 @@ function* getConvertStatus(ctx, docId, encryptedUserPassword, selectRes, opt_che
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case commonDefines.FileStatus.Err:
|
case commonDefines.FileStatus.Err:
|
||||||
|
status.err = row.status_info;
|
||||||
|
break;
|
||||||
case commonDefines.FileStatus.ErrToReload:
|
case commonDefines.FileStatus.ErrToReload:
|
||||||
case commonDefines.FileStatus.NeedPassword:
|
case commonDefines.FileStatus.NeedPassword:
|
||||||
status.err = row.status_info;
|
status.err = row.status_info;
|
||||||
if (commonDefines.FileStatus.ErrToReload == row.status || commonDefines.FileStatus.NeedPassword == row.status) {
|
yield canvasService.cleanupErrToReload(ctx, docId);
|
||||||
yield canvasService.cleanupCache(ctx, docId);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case commonDefines.FileStatus.NeedParams:
|
case commonDefines.FileStatus.NeedParams:
|
||||||
case commonDefines.FileStatus.SaveVersion:
|
case commonDefines.FileStatus.SaveVersion:
|
||||||
@ -147,7 +147,8 @@ function* convertByCmd(ctx, cmd, async, opt_fileTo, opt_taskExist, opt_priority,
|
|||||||
if (!bCreate) {
|
if (!bCreate) {
|
||||||
selectRes = yield taskResult.select(ctx, docId);
|
selectRes = yield taskResult.select(ctx, docId);
|
||||||
status = yield* getConvertStatus(ctx, cmd.getDocId() ,cmd.getPassword(), selectRes, opt_checkPassword);
|
status = yield* getConvertStatus(ctx, cmd.getDocId() ,cmd.getPassword(), selectRes, opt_checkPassword);
|
||||||
} else {
|
}
|
||||||
|
if (bCreate || (commonDefines.FileStatus.None === selectRes?.[0]?.status)) {
|
||||||
var queueData = new commonDefines.TaskQueueData();
|
var queueData = new commonDefines.TaskQueueData();
|
||||||
queueData.setCtx(ctx);
|
queueData.setCtx(ctx);
|
||||||
queueData.setCmd(cmd);
|
queueData.setCmd(cmd);
|
||||||
@ -182,8 +183,9 @@ function* convertByCmd(ctx, cmd, async, opt_fileTo, opt_taskExist, opt_priority,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function convertFromChanges(ctx, docId, baseUrl, forceSave, externalChangeInfo, opt_userdata, opt_formdata, opt_userConnectionId,
|
async function convertFromChanges(ctx, docId, baseUrl, forceSave, externalChangeInfo, opt_userdata, opt_formdata,
|
||||||
opt_userConnectionDocId, opt_responseKey, opt_priority, opt_expiration, opt_queue, opt_redisKey, opt_initShardKey) {
|
opt_userConnectionId, opt_userConnectionDocId, opt_responseKey, opt_priority,
|
||||||
|
opt_expiration, opt_queue, opt_redisKey, opt_initShardKey, opt_jsonParams) {
|
||||||
var cmd = new commonDefines.InputCommand();
|
var cmd = new commonDefines.InputCommand();
|
||||||
cmd.setCommand('sfcm');
|
cmd.setCommand('sfcm');
|
||||||
cmd.setDocId(docId);
|
cmd.setDocId(docId);
|
||||||
@ -193,6 +195,10 @@ async function convertFromChanges(ctx, docId, baseUrl, forceSave, externalChange
|
|||||||
cmd.setDelimiter(commonDefines.c_oAscCsvDelimiter.Comma);
|
cmd.setDelimiter(commonDefines.c_oAscCsvDelimiter.Comma);
|
||||||
cmd.setForceSave(forceSave);
|
cmd.setForceSave(forceSave);
|
||||||
cmd.setExternalChangeInfo(externalChangeInfo);
|
cmd.setExternalChangeInfo(externalChangeInfo);
|
||||||
|
if (externalChangeInfo.lang) {
|
||||||
|
//todo lang and region are different
|
||||||
|
cmd.setLCID(utilsDocService.localeToLCID(externalChangeInfo.lang));
|
||||||
|
}
|
||||||
if (opt_userdata) {
|
if (opt_userdata) {
|
||||||
cmd.setUserData(opt_userdata);
|
cmd.setUserData(opt_userdata);
|
||||||
}
|
}
|
||||||
@ -212,8 +218,14 @@ async function convertFromChanges(ctx, docId, baseUrl, forceSave, externalChange
|
|||||||
if (opt_redisKey) {
|
if (opt_redisKey) {
|
||||||
cmd.setRedisKey(opt_redisKey);
|
cmd.setRedisKey(opt_redisKey);
|
||||||
}
|
}
|
||||||
|
if (opt_jsonParams) {
|
||||||
|
cmd.appendJsonParams(opt_jsonParams);
|
||||||
|
}
|
||||||
|
|
||||||
await canvasService.commandSfctByCmd(ctx, cmd, opt_priority, opt_expiration, opt_queue, opt_initShardKey);
|
let commandSfctByCmdRes = await canvasService.commandSfctByCmd(ctx, cmd, opt_priority, opt_expiration, opt_queue, opt_initShardKey);
|
||||||
|
if (!commandSfctByCmdRes) {
|
||||||
|
return new commonDefines.ConvertStatus(constants.UNKNOWN);
|
||||||
|
}
|
||||||
var fileTo = constants.OUTPUT_NAME;
|
var fileTo = constants.OUTPUT_NAME;
|
||||||
let outputExt = formatChecker.getStringFromFormat(cmd.getOutputFormat());
|
let outputExt = formatChecker.getStringFromFormat(cmd.getOutputFormat());
|
||||||
if (outputExt) {
|
if (outputExt) {
|
||||||
@ -268,6 +280,17 @@ function convertRequest(req, res, isJson) {
|
|||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (params.pdf) {
|
||||||
|
if (true === params.pdf.pdfa && constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === outputFormat) {
|
||||||
|
outputFormat = constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA;
|
||||||
|
} else if (false === params.pdf.pdfa && constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA === outputFormat) {
|
||||||
|
outputFormat = constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF;
|
||||||
|
}
|
||||||
|
if (params.pdf.form && (constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === outputFormat ||
|
||||||
|
constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA === outputFormat)) {
|
||||||
|
outputFormat = constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_OFORM_PDF;
|
||||||
|
}
|
||||||
|
}
|
||||||
var cmd = new commonDefines.InputCommand();
|
var cmd = new commonDefines.InputCommand();
|
||||||
cmd.setCommand('conv');
|
cmd.setCommand('conv');
|
||||||
cmd.setUrl(params.url);
|
cmd.setUrl(params.url);
|
||||||
@ -281,8 +304,8 @@ function convertRequest(req, res, isJson) {
|
|||||||
cmd.setDelimiter(parseIntParam(params.delimiter) || commonDefines.c_oAscCsvDelimiter.Comma);
|
cmd.setDelimiter(parseIntParam(params.delimiter) || commonDefines.c_oAscCsvDelimiter.Comma);
|
||||||
if(undefined != params.delimiterChar)
|
if(undefined != params.delimiterChar)
|
||||||
cmd.setDelimiterChar(params.delimiterChar);
|
cmd.setDelimiterChar(params.delimiterChar);
|
||||||
if (params.region && locale[params.region.toLowerCase()]) {
|
if (params.region) {
|
||||||
cmd.setLCID(locale[params.region.toLowerCase()].id);
|
cmd.setLCID(utilsDocService.localeToLCID(params.region));
|
||||||
}
|
}
|
||||||
let jsonParams = {};
|
let jsonParams = {};
|
||||||
if (params.documentLayout) {
|
if (params.documentLayout) {
|
||||||
@ -295,7 +318,7 @@ function convertRequest(req, res, isJson) {
|
|||||||
jsonParams['watermark'] = params.watermark;
|
jsonParams['watermark'] = params.watermark;
|
||||||
}
|
}
|
||||||
if (Object.keys(jsonParams).length > 0) {
|
if (Object.keys(jsonParams).length > 0) {
|
||||||
cmd.setJsonParams(JSON.stringify(jsonParams));
|
cmd.appendJsonParams(jsonParams);
|
||||||
}
|
}
|
||||||
if (params.password) {
|
if (params.password) {
|
||||||
if (params.password.length > constants.PASSWORD_MAX_LENGTH) {
|
if (params.password.length > constants.PASSWORD_MAX_LENGTH) {
|
||||||
@ -530,22 +553,22 @@ function convertTo(req, res) {
|
|||||||
cmd.setOutputFormat(outputFormat);
|
cmd.setOutputFormat(outputFormat);
|
||||||
cmd.setCodepage(commonDefines.c_oAscCodePageUtf8);
|
cmd.setCodepage(commonDefines.c_oAscCodePageUtf8);
|
||||||
cmd.setDelimiter(commonDefines.c_oAscCsvDelimiter.Comma);
|
cmd.setDelimiter(commonDefines.c_oAscCsvDelimiter.Comma);
|
||||||
if (lang && locale[lang.toLowerCase()]) {
|
if (lang) {
|
||||||
cmd.setLCID(locale[lang.toLowerCase()].id);
|
cmd.setLCID(utilsDocService.localeToLCID(lang));
|
||||||
}
|
}
|
||||||
if (fullSheetPreview) {
|
if (fullSheetPreview) {
|
||||||
cmd.setJsonParams(JSON.stringify({'spreadsheetLayout': {
|
cmd.appendJsonParams({'spreadsheetLayout': {
|
||||||
"ignorePrintArea": true,
|
"ignorePrintArea": true,
|
||||||
"fitToWidth": 1,
|
"fitToWidth": 1,
|
||||||
"fitToHeight": 1
|
"fitToHeight": 1
|
||||||
}}));
|
}});
|
||||||
} else {
|
} else {
|
||||||
cmd.setJsonParams(JSON.stringify({'spreadsheetLayout': {
|
cmd.appendJsonParams({'spreadsheetLayout': {
|
||||||
"ignorePrintArea": true,
|
"ignorePrintArea": true,
|
||||||
"fitToWidth": 0,
|
"fitToWidth": 0,
|
||||||
"fitToHeight": 0,
|
"fitToHeight": 0,
|
||||||
"scale": 100
|
"scale": 100
|
||||||
}}));
|
}});
|
||||||
}
|
}
|
||||||
if (password) {
|
if (password) {
|
||||||
let encryptedPassword = yield utils.encryptPassword(ctx, password);
|
let encryptedPassword = yield utils.encryptPassword(ctx, password);
|
||||||
@ -651,7 +674,7 @@ function getConverterHtmlHandler(req, res) {
|
|||||||
ctx.setDocId(docId);
|
ctx.setDocId(docId);
|
||||||
if (!(wopiSrc && access_token && access_token && targetext && docId) ||
|
if (!(wopiSrc && access_token && access_token && targetext && docId) ||
|
||||||
constants.AVS_OFFICESTUDIO_FILE_UNKNOWN === formatChecker.getFormatFromString(targetext)) {
|
constants.AVS_OFFICESTUDIO_FILE_UNKNOWN === formatChecker.getFormatFromString(targetext)) {
|
||||||
ctx.logger.debug('convert-and-edit-handler invalid params: wopiSrc=%s; access_token=%s; targetext=%s; docId=%s', wopiSrc, access_token, targetext, docId);
|
ctx.logger.debug('convert-and-edit-handler invalid params: WOPISrc=%s; access_token=%s; targetext=%s; docId=%s', wopiSrc, access_token, targetext, docId);
|
||||||
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
utils.fillResponse(req, res, new commonDefines.ConvertStatus(constants.CONVERT_PARAMS), isJson);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -200,6 +200,23 @@ DocumentAdditional.prototype.getShardKey = function(str) {
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DocumentAdditional.prototype.setWopiSrc = function(wopiSrc) {
|
||||||
|
let additional = new DocumentAdditional();
|
||||||
|
additional.data.push({wopiSrc});
|
||||||
|
return additional.toSQLInsert();
|
||||||
|
};
|
||||||
|
DocumentAdditional.prototype.getWopiSrc = function(str) {
|
||||||
|
let res;
|
||||||
|
let val = new DocumentAdditional();
|
||||||
|
val.fromString(str);
|
||||||
|
val.data.forEach((elem) => {
|
||||||
|
if (elem.wopiSrc) {
|
||||||
|
res = elem.wopiSrc;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
UserCallback,
|
UserCallback,
|
||||||
DocumentPassword,
|
DocumentPassword,
|
||||||
|
|||||||
@ -32,14 +32,14 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const mysql = require('mysql2');
|
const mysql = require('mysql2/promise');
|
||||||
const connectorUtilities = require('./connectorUtilities');
|
const connectorUtilities = require('./connectorUtilities');
|
||||||
const config = require('config');
|
const config = require('config');
|
||||||
|
|
||||||
const configSql = config.get('services.CoAuthoring.sql');
|
const configSql = config.get('services.CoAuthoring.sql');
|
||||||
const cfgTableResult = config.get('services.CoAuthoring.sql.tableResult');
|
const cfgTableResult = configSql.get('tableResult');
|
||||||
|
|
||||||
const pool = mysql.createPool({
|
const connectionConfiguration = {
|
||||||
host : configSql.get('dbHost'),
|
host : configSql.get('dbHost'),
|
||||||
port : parseInt(configSql.get('dbPort')),
|
port : parseInt(configSql.get('dbPort')),
|
||||||
user : configSql.get('dbUser'),
|
user : configSql.get('dbUser'),
|
||||||
@ -49,120 +49,120 @@ const pool = mysql.createPool({
|
|||||||
connectionLimit : configSql.get('connectionlimit'),
|
connectionLimit : configSql.get('connectionlimit'),
|
||||||
timezone : 'Z',
|
timezone : 'Z',
|
||||||
flags : '-FOUND_ROWS'
|
flags : '-FOUND_ROWS'
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const additionalOptions = configSql.get('mysqlExtraOptions');
|
||||||
|
const configuration = Object.assign({}, connectionConfiguration, additionalOptions);
|
||||||
|
|
||||||
|
let pool = mysql.createPool(configuration);
|
||||||
|
|
||||||
function sqlQuery(ctx, sqlCommand, callbackFunction, opt_noModifyRes = false, opt_noLog = false, opt_values = []) {
|
function sqlQuery(ctx, sqlCommand, callbackFunction, opt_noModifyRes = false, opt_noLog = false, opt_values = []) {
|
||||||
pool.getConnection(function(connectionError, connection) {
|
return executeQuery(ctx, sqlCommand, opt_values, opt_noModifyRes, opt_noLog).then(
|
||||||
if (connectionError) {
|
result => callbackFunction?.(null, result),
|
||||||
if (!opt_noLog) {
|
error => callbackFunction?.(error)
|
||||||
ctx.logger.error('pool.getConnection error: %s', connectionError);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
callbackFunction?.(connectionError, null);
|
async function executeQuery(ctx, sqlCommand, values = [], noModifyRes = false, noLog = false) {
|
||||||
|
let connection = null;
|
||||||
|
try {
|
||||||
|
connection = await pool.getConnection();
|
||||||
|
|
||||||
return;
|
const result = await connection.query(sqlCommand, values);
|
||||||
|
|
||||||
|
let output;
|
||||||
|
if (!noModifyRes) {
|
||||||
|
output = result[0]?.affectedRows ? { affectedRows: result[0].affectedRows } : result[0];
|
||||||
|
} else {
|
||||||
|
output = result[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
let queryCallback = function (error, result) {
|
return output ?? { rows: [], affectedRows: 0 };
|
||||||
connection.release();
|
} catch (error) {
|
||||||
if (error && !opt_noLog) {
|
if (!noLog) {
|
||||||
ctx.logger.error('_______________________error______________________');
|
ctx.logger.error(`sqlQuery() error while executing query: ${sqlCommand}\n${error.stack}`);
|
||||||
ctx.logger.error('sqlQuery: %s sqlCommand: %s', error.code, sqlCommand);
|
}
|
||||||
ctx.logger.error(error);
|
|
||||||
ctx.logger.error('_____________________end_error____________________');
|
throw error;
|
||||||
|
} finally {
|
||||||
|
if (connection) {
|
||||||
|
try {
|
||||||
|
// Put the connection back in the pool
|
||||||
|
connection.release();
|
||||||
|
} catch (error) {
|
||||||
|
if (!noLog) {
|
||||||
|
ctx.logger.error(`connection.release() error while executing query: ${sqlCommand}\n${error.stack}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let output;
|
}
|
||||||
if (!opt_noModifyRes) {
|
|
||||||
output = result?.affectedRows ? { affectedRows: result.affectedRows } : result;
|
|
||||||
} else {
|
|
||||||
output = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
output = output ?? { rows: [], affectedRows: 0 };
|
|
||||||
|
|
||||||
callbackFunction?.(error, output);
|
|
||||||
};
|
|
||||||
|
|
||||||
connection.query(sqlCommand, opt_values, queryCallback);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function closePool() {
|
async function closePool() {
|
||||||
return new Promise((resolve, reject) => {
|
return await pool.end();
|
||||||
pool.end((error) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSqlParameter(val, values) {
|
function addSqlParameter(parameter, accumulatedArray) {
|
||||||
values.push(val);
|
accumulatedArray.push(parameter);
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
function concatParams(val1, val2) {
|
function concatParams(firstParameter, secondParameter) {
|
||||||
return `CONCAT(COALESCE(${val1}, ''), COALESCE(${val2}, ''))`;
|
return `CONCAT(COALESCE(${firstParameter}, ''), COALESCE(${secondParameter}, ''))`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function upsert(ctx, task) {
|
async function upsert(ctx, task) {
|
||||||
return new Promise(function(resolve, reject) {
|
task.completeDefaults();
|
||||||
task.completeDefaults();
|
const dateNow = new Date();
|
||||||
let dateNow = new Date();
|
|
||||||
let values = [];
|
|
||||||
let cbInsert = task.callback;
|
|
||||||
if (task.callback) {
|
|
||||||
let userCallback = new connectorUtilities.UserCallback();
|
|
||||||
userCallback.fromValues(task.userIndex, task.callback);
|
|
||||||
cbInsert = userCallback.toSQLInsert();
|
|
||||||
}
|
|
||||||
let p0 = addSqlParameter(task.tenant, values);
|
|
||||||
let p1 = addSqlParameter(task.key, values);
|
|
||||||
let p2 = addSqlParameter(task.status, values);
|
|
||||||
let p3 = addSqlParameter(task.statusInfo, values);
|
|
||||||
let p4 = addSqlParameter(dateNow, values);
|
|
||||||
let p5 = addSqlParameter(task.userIndex, values);
|
|
||||||
let p6 = addSqlParameter(task.changeId, values);
|
|
||||||
let p7 = addSqlParameter(cbInsert, values);
|
|
||||||
let p8 = addSqlParameter(task.baseurl, values);
|
|
||||||
let p9 = addSqlParameter(dateNow, values);
|
|
||||||
var sqlCommand = `INSERT INTO ${cfgTableResult} (tenant, id, status, status_info, last_open_date, user_index, change_id, callback, baseurl)`+
|
|
||||||
` VALUES (${p0}, ${p1}, ${p2}, ${p3}, ${p4}, ${p5}, ${p6}, ${p7}, ${p8}) ON DUPLICATE KEY UPDATE` +
|
|
||||||
` last_open_date = ${p9}`;
|
|
||||||
if (task.callback) {
|
|
||||||
let p10 = addSqlParameter(JSON.stringify(task.callback), values);
|
|
||||||
sqlCommand += `, callback = CONCAT(callback , '${connectorUtilities.UserCallback.prototype.delimiter}{"userIndex":' , (user_index + 1) , ',"callback":', ${p10}, '}')`;
|
|
||||||
}
|
|
||||||
if (task.baseurl) {
|
|
||||||
let p11 = addSqlParameter(task.baseurl, values);
|
|
||||||
sqlCommand += `, baseurl = ${p11}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlCommand += ', user_index = LAST_INSERT_ID(user_index + 1);';
|
let cbInsert = task.callback;
|
||||||
|
if (task.callback) {
|
||||||
|
const userCallback = new connectorUtilities.UserCallback();
|
||||||
|
userCallback.fromValues(task.userIndex, task.callback);
|
||||||
|
cbInsert = userCallback.toSQLInsert();
|
||||||
|
}
|
||||||
|
|
||||||
sqlQuery(ctx, sqlCommand, function(error, result) {
|
const values = [];
|
||||||
if (error) {
|
const valuesPlaceholder = [
|
||||||
reject(error);
|
addSqlParameter(task.tenant, values),
|
||||||
} else {
|
addSqlParameter(task.key, values),
|
||||||
const insertId = result.affectedRows === 1 ? task.userIndex : result.insertId;
|
addSqlParameter(task.status, values),
|
||||||
//if CLIENT_FOUND_ROWS don't specify 1 row is inserted , 2 row is updated, and 0 row is set to its current values
|
addSqlParameter(task.statusInfo, values),
|
||||||
//http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
|
addSqlParameter(dateNow, values),
|
||||||
const isInsert = result.affectedRows === 1;
|
addSqlParameter(task.userIndex, values),
|
||||||
|
addSqlParameter(task.changeId, values),
|
||||||
|
addSqlParameter(cbInsert, values),
|
||||||
|
addSqlParameter(task.baseurl, values)
|
||||||
|
];
|
||||||
|
|
||||||
resolve({ isInsert, insertId });
|
let updateStatement = `last_open_date = ${addSqlParameter(dateNow, values)}`;
|
||||||
}
|
if (task.callback) {
|
||||||
}, true, false, values);
|
let callbackPlaceholder = addSqlParameter(JSON.stringify(task.callback), values);
|
||||||
});
|
updateStatement += `, callback = CONCAT(callback , '${connectorUtilities.UserCallback.prototype.delimiter}{"userIndex":' , (user_index + 1) , ',"callback":', ${callbackPlaceholder}, '}')`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task.baseurl) {
|
||||||
|
let baseUrlPlaceholder = addSqlParameter(task.baseurl, values);
|
||||||
|
updateStatement += `, baseurl = ${baseUrlPlaceholder}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStatement += ', user_index = LAST_INSERT_ID(user_index + 1);';
|
||||||
|
|
||||||
|
const sqlCommand = `INSERT INTO ${cfgTableResult} (tenant, id, status, status_info, last_open_date, user_index, change_id, callback, baseurl) `+
|
||||||
|
`VALUES (${valuesPlaceholder.join(', ')}) ` +
|
||||||
|
`ON DUPLICATE KEY UPDATE ${updateStatement}`;
|
||||||
|
|
||||||
|
const result = await executeQuery(ctx, sqlCommand, values, true);
|
||||||
|
const insertId = result.affectedRows === 1 ? task.userIndex : result.insertId;
|
||||||
|
//if CLIENT_FOUND_ROWS don't specify 1 row is inserted , 2 row is updated, and 0 row is set to its current values
|
||||||
|
//http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
|
||||||
|
const isInsert = result.affectedRows === 1;
|
||||||
|
|
||||||
|
return { isInsert, insertId };
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports.sqlQuery = sqlQuery;
|
||||||
sqlQuery,
|
module.exports.closePool = closePool;
|
||||||
closePool,
|
module.exports.addSqlParameter = addSqlParameter;
|
||||||
addSqlParameter,
|
module.exports.concatParams = concatParams;
|
||||||
concatParams,
|
module.exports.upsert = upsert;
|
||||||
upsert
|
|
||||||
}
|
|
||||||
|
|||||||
@ -39,19 +39,29 @@ const tenantManager = require('./../../Common/sources/tenantManager');
|
|||||||
|
|
||||||
const cfgExpMonthUniqueUsers = ms(config.get('services.CoAuthoring.expire.monthUniqueUsers'));
|
const cfgExpMonthUniqueUsers = ms(config.get('services.CoAuthoring.expire.monthUniqueUsers'));
|
||||||
|
|
||||||
|
function EditorCommon() {
|
||||||
|
}
|
||||||
|
EditorCommon.prototype.connect = async function () {};
|
||||||
|
EditorCommon.prototype.isConnected = function() {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
EditorCommon.prototype.ping = async function() {return "PONG"};
|
||||||
|
EditorCommon.prototype.close = async function() {};
|
||||||
|
EditorCommon.prototype.healthCheck = async function() {
|
||||||
|
if (this.isConnected()) {
|
||||||
|
await this.ping();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
function EditorData() {
|
function EditorData() {
|
||||||
|
EditorCommon.call(this);
|
||||||
this.data = {};
|
this.data = {};
|
||||||
this.forceSaveTimer = {};
|
this.forceSaveTimer = {};
|
||||||
this.uniqueUser = {};
|
|
||||||
this.uniqueUsersOfMonth = {};
|
|
||||||
this.uniqueViewUser = {};
|
|
||||||
this.uniqueViewUsersOfMonth = {};
|
|
||||||
this.shutdown = {};
|
|
||||||
this.stat = {};
|
|
||||||
}
|
}
|
||||||
EditorData.prototype.connect = function() {
|
EditorData.prototype = Object.create(EditorCommon.prototype);
|
||||||
return Promise.resolve();
|
EditorData.prototype.constructor = EditorData;
|
||||||
};
|
|
||||||
EditorData.prototype._getDocumentData = function(ctx, docId) {
|
EditorData.prototype._getDocumentData = function(ctx, docId) {
|
||||||
let tenantData = this.data[ctx.tenant];
|
let tenantData = this.data[ctx.tenant];
|
||||||
if (!tenantData) {
|
if (!tenantData) {
|
||||||
@ -73,7 +83,7 @@ EditorData.prototype._checkAndLock = function(ctx, name, docId, fencingToken, tt
|
|||||||
const expireAt = now + ttl * 1000;
|
const expireAt = now + ttl * 1000;
|
||||||
data[name] = {fencingToken: fencingToken, expireAt: expireAt};
|
data[name] = {fencingToken: fencingToken, expireAt: expireAt};
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
EditorData.prototype._checkAndUnlock = function(ctx, name, docId, fencingToken) {
|
EditorData.prototype._checkAndUnlock = function(ctx, name, docId, fencingToken) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
@ -90,106 +100,117 @@ EditorData.prototype._checkAndUnlock = function(ctx, name, docId, fencingToken)
|
|||||||
res = commonDefines.c_oAscUnlockRes.Empty;
|
res = commonDefines.c_oAscUnlockRes.Empty;
|
||||||
delete data[name];
|
delete data[name];
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addPresence = function(ctx, docId, userId, userInfo) {
|
EditorData.prototype.addPresence = async function(ctx, docId, userId, userInfo) {};
|
||||||
return Promise.resolve();
|
EditorData.prototype.updatePresence = async function(ctx, docId, userId) {};
|
||||||
};
|
EditorData.prototype.removePresence = async function(ctx, docId, userId) {};
|
||||||
EditorData.prototype.updatePresence = function(ctx, docId, userId) {
|
EditorData.prototype.getPresence = async function(ctx, docId, connections) {
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
EditorData.prototype.removePresence = function(ctx, docId, userId) {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
EditorData.prototype.getPresence = function(ctx, docId, connections) {
|
|
||||||
let hvals = [];
|
let hvals = [];
|
||||||
for (let i = 0; i < connections.length; ++i) {
|
if (connections) {
|
||||||
let conn = connections[i];
|
for (let i = 0; i < connections.length; ++i) {
|
||||||
if (conn.docId === docId && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
let conn = connections[i];
|
||||||
hvals.push(utils.getConnectionInfoStr(conn));
|
if (conn.docId === docId && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
||||||
|
hvals.push(utils.getConnectionInfoStr(conn));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(hvals);
|
return hvals;
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.lockSave = function(ctx, docId, userId, ttl) {
|
EditorData.prototype.lockSave = async function(ctx, docId, userId, ttl) {
|
||||||
return this._checkAndLock(ctx, 'lockSave', docId, userId, ttl);
|
return this._checkAndLock(ctx, 'lockSave', docId, userId, ttl);
|
||||||
};
|
};
|
||||||
EditorData.prototype.unlockSave = function(ctx, docId, userId) {
|
EditorData.prototype.unlockSave = async function(ctx, docId, userId) {
|
||||||
return this._checkAndUnlock(ctx, 'lockSave', docId, userId);
|
return this._checkAndUnlock(ctx, 'lockSave', docId, userId);
|
||||||
};
|
};
|
||||||
EditorData.prototype.lockAuth = function(ctx, docId, userId, ttl) {
|
EditorData.prototype.lockAuth = async function(ctx, docId, userId, ttl) {
|
||||||
return this._checkAndLock(ctx, 'lockAuth', docId, userId, ttl);
|
return this._checkAndLock(ctx, 'lockAuth', docId, userId, ttl);
|
||||||
};
|
};
|
||||||
EditorData.prototype.unlockAuth = function(ctx, docId, userId) {
|
EditorData.prototype.unlockAuth = async function(ctx, docId, userId) {
|
||||||
return this._checkAndUnlock(ctx, 'lockAuth', docId, userId);
|
return this._checkAndUnlock(ctx, 'lockAuth', docId, userId);
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.getDocumentPresenceExpired = function(now) {
|
EditorData.prototype.getDocumentPresenceExpired = async function(now) {
|
||||||
return Promise.resolve([]);
|
return [];
|
||||||
};
|
|
||||||
EditorData.prototype.removePresenceDocument = function(ctx, docId) {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
|
EditorData.prototype.removePresenceDocument = async function(ctx, docId) {};
|
||||||
|
|
||||||
EditorData.prototype.addLocks = function(ctx, docId, locks) {
|
EditorData.prototype.addLocks = async function(ctx, docId, locks) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
if (!data.locks) {
|
if (!data.locks) {
|
||||||
data.locks = [];
|
data.locks = {};
|
||||||
}
|
}
|
||||||
data.locks = data.locks.concat(locks);
|
Object.assign(data.locks, locks);
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.removeLocks = function(ctx, docId) {
|
EditorData.prototype.addLocksNX = async function(ctx, docId, locks) {
|
||||||
|
let data = this._getDocumentData(ctx, docId);
|
||||||
|
if (!data.locks) {
|
||||||
|
data.locks = {};
|
||||||
|
}
|
||||||
|
let lockConflict = {};
|
||||||
|
for (let lockId in locks) {
|
||||||
|
if (undefined === data.locks[lockId]) {
|
||||||
|
data.locks[lockId] = locks[lockId];
|
||||||
|
} else {
|
||||||
|
lockConflict[lockId] = locks[lockId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {lockConflict, allLocks: data.locks};
|
||||||
|
};
|
||||||
|
EditorData.prototype.removeLocks = async function(ctx, docId, locks) {
|
||||||
|
let data = this._getDocumentData(ctx, docId);
|
||||||
|
if (data.locks) {
|
||||||
|
for (let lockId in locks) {
|
||||||
|
delete data.locks[lockId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EditorData.prototype.removeAllLocks = async function(ctx, docId) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.locks = undefined;
|
data.locks = undefined;
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getLocks = function(ctx, docId) {
|
EditorData.prototype.getLocks = async function(ctx, docId) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
return Promise.resolve(data.locks || []);
|
return data.locks || {};
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addMessage = function(ctx, docId, msg) {
|
EditorData.prototype.addMessage = async function(ctx, docId, msg) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
if (!data.messages) {
|
if (!data.messages) {
|
||||||
data.messages = [];
|
data.messages = [];
|
||||||
}
|
}
|
||||||
data.messages.push(msg);
|
data.messages.push(msg);
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.removeMessages = function(ctx, docId) {
|
EditorData.prototype.removeMessages = async function(ctx, docId) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.messages = undefined;
|
data.messages = undefined;
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getMessages = function(ctx, docId) {
|
EditorData.prototype.getMessages = async function(ctx, docId) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
return Promise.resolve(data.messages || []);
|
return data.messages || [];
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.setSaved = function(ctx, docId, status) {
|
EditorData.prototype.setSaved = async function(ctx, docId, status) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.saved = status;
|
data.saved = status;
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getdelSaved = function(ctx, docId) {
|
EditorData.prototype.getdelSaved = async function(ctx, docId) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
let res = data.saved;
|
let res = data.saved;
|
||||||
data.saved = undefined;
|
data.saved = null;
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
EditorData.prototype.setForceSave = function(ctx, docId, time, index, baseUrl, changeInfo, convertInfo) {
|
EditorData.prototype.setForceSave = async function(ctx, docId, time, index, baseUrl, changeInfo, convertInfo) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.forceSave = {time, index, baseUrl, changeInfo, started: false, ended: false, convertInfo};
|
data.forceSave = {time, index, baseUrl, changeInfo, started: false, ended: false, convertInfo};
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getForceSave = function(ctx, docId) {
|
EditorData.prototype.getForceSave = async function(ctx, docId) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
return Promise.resolve(data.forceSave || null);
|
return data.forceSave || null;
|
||||||
};
|
};
|
||||||
EditorData.prototype.checkAndStartForceSave = function(ctx, docId) {
|
EditorData.prototype.checkAndStartForceSave = async function(ctx, docId) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
let res;
|
let res;
|
||||||
if (data.forceSave && !data.forceSave.started) {
|
if (data.forceSave && !data.forceSave.started) {
|
||||||
@ -197,9 +218,9 @@ EditorData.prototype.checkAndStartForceSave = function(ctx, docId) {
|
|||||||
data.forceSave.ended = false;
|
data.forceSave.ended = false;
|
||||||
res = data.forceSave;
|
res = data.forceSave;
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
EditorData.prototype.checkAndSetForceSave = function(ctx, docId, time, index, started, ended, convertInfo) {
|
EditorData.prototype.checkAndSetForceSave = async function(ctx, docId, time, index, started, ended, convertInfo) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
let res;
|
let res;
|
||||||
if (data.forceSave && time === data.forceSave.time && index === data.forceSave.index) {
|
if (data.forceSave && time === data.forceSave.time && index === data.forceSave.index) {
|
||||||
@ -208,15 +229,14 @@ EditorData.prototype.checkAndSetForceSave = function(ctx, docId, time, index, st
|
|||||||
data.forceSave.convertInfo = convertInfo;
|
data.forceSave.convertInfo = convertInfo;
|
||||||
res = data.forceSave;
|
res = data.forceSave;
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
EditorData.prototype.removeForceSave = function(ctx, docId) {
|
EditorData.prototype.removeForceSave = async function(ctx, docId) {
|
||||||
let data = this._getDocumentData(ctx, docId);
|
let data = this._getDocumentData(ctx, docId);
|
||||||
data.forceSave = undefined;
|
data.forceSave = undefined;
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.cleanDocumentOnExit = function(ctx, docId) {
|
EditorData.prototype.cleanDocumentOnExit = async function(ctx, docId) {
|
||||||
let tenantData = this.data[ctx.tenant];
|
let tenantData = this.data[ctx.tenant];
|
||||||
if (tenantData) {
|
if (tenantData) {
|
||||||
delete tenantData[docId];
|
delete tenantData[docId];
|
||||||
@ -225,10 +245,9 @@ EditorData.prototype.cleanDocumentOnExit = function(ctx, docId) {
|
|||||||
if (tenantTimer) {
|
if (tenantTimer) {
|
||||||
delete tenantTimer[docId];
|
delete tenantTimer[docId];
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addForceSaveTimerNX = function(ctx, docId, expireAt) {
|
EditorData.prototype.addForceSaveTimerNX = async function(ctx, docId, expireAt) {
|
||||||
let tenantTimer = this.forceSaveTimer[ctx.tenant];
|
let tenantTimer = this.forceSaveTimer[ctx.tenant];
|
||||||
if (!tenantTimer) {
|
if (!tenantTimer) {
|
||||||
this.forceSaveTimer[ctx.tenant] = tenantTimer = {};
|
this.forceSaveTimer[ctx.tenant] = tenantTimer = {};
|
||||||
@ -236,9 +255,8 @@ EditorData.prototype.addForceSaveTimerNX = function(ctx, docId, expireAt) {
|
|||||||
if (!tenantTimer[docId]) {
|
if (!tenantTimer[docId]) {
|
||||||
tenantTimer[docId] = expireAt;
|
tenantTimer[docId] = expireAt;
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getForceSaveTimer = function(now) {
|
EditorData.prototype.getForceSaveTimer = async function(now) {
|
||||||
let res = [];
|
let res = [];
|
||||||
for (let tenant in this.forceSaveTimer) {
|
for (let tenant in this.forceSaveTimer) {
|
||||||
if (this.forceSaveTimer.hasOwnProperty(tenant)) {
|
if (this.forceSaveTimer.hasOwnProperty(tenant)) {
|
||||||
@ -253,18 +271,29 @@ EditorData.prototype.getForceSaveTimer = function(now) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addPresenceUniqueUser = function(ctx, userId, expireAt, userInfo) {
|
function EditorStat() {
|
||||||
|
EditorCommon.call(this);
|
||||||
|
this.uniqueUser = {};
|
||||||
|
this.uniqueUsersOfMonth = {};
|
||||||
|
this.uniqueViewUser = {};
|
||||||
|
this.uniqueViewUsersOfMonth = {};
|
||||||
|
this.stat = {};
|
||||||
|
this.shutdown = {};
|
||||||
|
this.license = {};
|
||||||
|
}
|
||||||
|
EditorStat.prototype = Object.create(EditorCommon.prototype);
|
||||||
|
EditorStat.prototype.constructor = EditorStat;
|
||||||
|
EditorStat.prototype.addPresenceUniqueUser = async function(ctx, userId, expireAt, userInfo) {
|
||||||
let tenantUser = this.uniqueUser[ctx.tenant];
|
let tenantUser = this.uniqueUser[ctx.tenant];
|
||||||
if (!tenantUser) {
|
if (!tenantUser) {
|
||||||
this.uniqueUser[ctx.tenant] = tenantUser = {};
|
this.uniqueUser[ctx.tenant] = tenantUser = {};
|
||||||
}
|
}
|
||||||
tenantUser[userId] = {expireAt: expireAt, userInfo: userInfo};
|
tenantUser[userId] = {expireAt: expireAt, userInfo: userInfo};
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresenceUniqueUser = function(ctx, nowUTC) {
|
EditorStat.prototype.getPresenceUniqueUser = async function(ctx, nowUTC) {
|
||||||
let res = [];
|
let res = [];
|
||||||
let tenantUser = this.uniqueUser[ctx.tenant];
|
let tenantUser = this.uniqueUser[ctx.tenant];
|
||||||
if (!tenantUser) {
|
if (!tenantUser) {
|
||||||
@ -282,9 +311,9 @@ EditorData.prototype.getPresenceUniqueUser = function(ctx, nowUTC) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
EditorData.prototype.addPresenceUniqueUsersOfMonth = function(ctx, userId, period, userInfo) {
|
EditorStat.prototype.addPresenceUniqueUsersOfMonth = async function(ctx, userId, period, userInfo) {
|
||||||
let tenantUser = this.uniqueUsersOfMonth[ctx.tenant];
|
let tenantUser = this.uniqueUsersOfMonth[ctx.tenant];
|
||||||
if (!tenantUser) {
|
if (!tenantUser) {
|
||||||
this.uniqueUsersOfMonth[ctx.tenant] = tenantUser = {};
|
this.uniqueUsersOfMonth[ctx.tenant] = tenantUser = {};
|
||||||
@ -294,9 +323,8 @@ EditorData.prototype.addPresenceUniqueUsersOfMonth = function(ctx, userId, perio
|
|||||||
tenantUser[period] = {expireAt: expireAt, data: {}};
|
tenantUser[period] = {expireAt: expireAt, data: {}};
|
||||||
}
|
}
|
||||||
tenantUser[period].data[userId] = userInfo;
|
tenantUser[period].data[userId] = userInfo;
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresenceUniqueUsersOfMonth = function(ctx) {
|
EditorStat.prototype.getPresenceUniqueUsersOfMonth = async function(ctx) {
|
||||||
let res = {};
|
let res = {};
|
||||||
let nowUTC = Date.now();
|
let nowUTC = Date.now();
|
||||||
let tenantUser = this.uniqueUsersOfMonth[ctx.tenant];
|
let tenantUser = this.uniqueUsersOfMonth[ctx.tenant];
|
||||||
@ -313,18 +341,17 @@ EditorData.prototype.getPresenceUniqueUsersOfMonth = function(ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.addPresenceUniqueViewUser = function(ctx, userId, expireAt, userInfo) {
|
EditorStat.prototype.addPresenceUniqueViewUser = async function(ctx, userId, expireAt, userInfo) {
|
||||||
let tenantUser = this.uniqueViewUser[ctx.tenant];
|
let tenantUser = this.uniqueViewUser[ctx.tenant];
|
||||||
if (!tenantUser) {
|
if (!tenantUser) {
|
||||||
this.uniqueViewUser[ctx.tenant] = tenantUser = {};
|
this.uniqueViewUser[ctx.tenant] = tenantUser = {};
|
||||||
}
|
}
|
||||||
tenantUser[userId] = {expireAt: expireAt, userInfo: userInfo};
|
tenantUser[userId] = {expireAt: expireAt, userInfo: userInfo};
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresenceUniqueViewUser = function(ctx, nowUTC) {
|
EditorStat.prototype.getPresenceUniqueViewUser = async function(ctx, nowUTC) {
|
||||||
let res = [];
|
let res = [];
|
||||||
let tenantUser = this.uniqueViewUser[ctx.tenant];
|
let tenantUser = this.uniqueViewUser[ctx.tenant];
|
||||||
if (!tenantUser) {
|
if (!tenantUser) {
|
||||||
@ -342,9 +369,9 @@ EditorData.prototype.getPresenceUniqueViewUser = function(ctx, nowUTC) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
EditorData.prototype.addPresenceUniqueViewUsersOfMonth = function(ctx, userId, period, userInfo) {
|
EditorStat.prototype.addPresenceUniqueViewUsersOfMonth = async function(ctx, userId, period, userInfo) {
|
||||||
let tenantUser = this.uniqueViewUsersOfMonth[ctx.tenant];
|
let tenantUser = this.uniqueViewUsersOfMonth[ctx.tenant];
|
||||||
if (!tenantUser) {
|
if (!tenantUser) {
|
||||||
this.uniqueViewUsersOfMonth[ctx.tenant] = tenantUser = {};
|
this.uniqueViewUsersOfMonth[ctx.tenant] = tenantUser = {};
|
||||||
@ -354,9 +381,8 @@ EditorData.prototype.addPresenceUniqueViewUsersOfMonth = function(ctx, userId, p
|
|||||||
tenantUser[period] = {expireAt: expireAt, data: {}};
|
tenantUser[period] = {expireAt: expireAt, data: {}};
|
||||||
}
|
}
|
||||||
tenantUser[period].data[userId] = userInfo;
|
tenantUser[period].data[userId] = userInfo;
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getPresenceUniqueViewUsersOfMonth = function(ctx) {
|
EditorStat.prototype.getPresenceUniqueViewUsersOfMonth = async function(ctx) {
|
||||||
let res = {};
|
let res = {};
|
||||||
let nowUTC = Date.now();
|
let nowUTC = Date.now();
|
||||||
let tenantUser = this.uniqueViewUsersOfMonth[ctx.tenant];
|
let tenantUser = this.uniqueViewUsersOfMonth[ctx.tenant];
|
||||||
@ -373,10 +399,9 @@ EditorData.prototype.getPresenceUniqueViewUsersOfMonth = function(ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(res);
|
return res;
|
||||||
};
|
};
|
||||||
|
EditorStat.prototype.setEditorConnections = async function(ctx, countEdit, countLiveView, countView, now, precision) {
|
||||||
EditorData.prototype.setEditorConnections = function(ctx, countEdit, countLiveView, countView, now, precision) {
|
|
||||||
let tenantStat = this.stat[ctx.tenant];
|
let tenantStat = this.stat[ctx.tenant];
|
||||||
if (!tenantStat) {
|
if (!tenantStat) {
|
||||||
this.stat[ctx.tenant] = tenantStat = [];
|
this.stat[ctx.tenant] = tenantStat = [];
|
||||||
@ -387,79 +412,69 @@ EditorData.prototype.setEditorConnections = function(ctx, countEdit, countLiveVi
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
tenantStat.splice(0, i);
|
tenantStat.splice(0, i);
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getEditorConnections = function(ctx) {
|
EditorStat.prototype.getEditorConnections = async function(ctx) {
|
||||||
let tenantStat = this.stat[ctx.tenant];
|
let tenantStat = this.stat[ctx.tenant];
|
||||||
if (!tenantStat) {
|
if (!tenantStat) {
|
||||||
this.stat[ctx.tenant] = tenantStat = [];
|
this.stat[ctx.tenant] = tenantStat = [];
|
||||||
}
|
}
|
||||||
return Promise.resolve(tenantStat);
|
return tenantStat;
|
||||||
};
|
};
|
||||||
EditorData.prototype.setEditorConnectionsCountByShard = function(ctx, shardId, count) {
|
EditorStat.prototype.setEditorConnectionsCountByShard = async function(ctx, shardId, count) {};
|
||||||
return Promise.resolve();
|
EditorStat.prototype.incrEditorConnectionsCountByShard = async function(ctx, shardId, count) {};
|
||||||
};
|
EditorStat.prototype.getEditorConnectionsCount = async function(ctx, connections) {
|
||||||
EditorData.prototype.incrEditorConnectionsCountByShard = function(ctx, shardId, count) {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
EditorData.prototype.getEditorConnectionsCount = function(ctx, connections) {
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (let i = 0; i < connections.length; ++i) {
|
if (connections) {
|
||||||
let conn = connections[i];
|
for (let i = 0; i < connections.length; ++i) {
|
||||||
if (!(conn.isCloseCoAuthoring || (conn.user && conn.user.view)) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
let conn = connections[i];
|
||||||
count++;
|
if (!(conn.isCloseCoAuthoring || (conn.user && conn.user.view)) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(count);
|
return count;
|
||||||
};
|
};
|
||||||
EditorData.prototype.setViewerConnectionsCountByShard = function(ctx, shardId, count) {
|
EditorStat.prototype.setViewerConnectionsCountByShard = async function(ctx, shardId, count) {};
|
||||||
return Promise.resolve();
|
EditorStat.prototype.incrViewerConnectionsCountByShard = async function(ctx, shardId, count) {};
|
||||||
};
|
EditorStat.prototype.getViewerConnectionsCount = async function(ctx, connections) {
|
||||||
EditorData.prototype.incrViewerConnectionsCountByShard = function(ctx, shardId, count) {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
EditorData.prototype.getViewerConnectionsCount = function(ctx, connections) {
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (let i = 0; i < connections.length; ++i) {
|
if (connections) {
|
||||||
let conn = connections[i];
|
for (let i = 0; i < connections.length; ++i) {
|
||||||
if (conn.isCloseCoAuthoring || (conn.user && conn.user.view) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
let conn = connections[i];
|
||||||
count++;
|
if (conn.isCloseCoAuthoring || (conn.user && conn.user.view) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(count);
|
return count;
|
||||||
};
|
};
|
||||||
EditorData.prototype.setLiveViewerConnectionsCountByShard = function(ctx, shardId, count) {
|
EditorStat.prototype.setLiveViewerConnectionsCountByShard = async function(ctx, shardId, count) {};
|
||||||
return Promise.resolve();
|
EditorStat.prototype.incrLiveViewerConnectionsCountByShard = async function(ctx, shardId, count) {};
|
||||||
};
|
EditorStat.prototype.getLiveViewerConnectionsCount = async function(ctx, connections) {
|
||||||
EditorData.prototype.incrLiveViewerConnectionsCountByShard = function(ctx, shardId, count) {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
EditorData.prototype.getLiveViewerConnectionsCount = function(ctx, connections) {
|
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for (let i = 0; i < connections.length; ++i) {
|
if (connections) {
|
||||||
let conn = connections[i];
|
for (let i = 0; i < connections.length; ++i) {
|
||||||
if (utils.isLiveViewer(conn) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
let conn = connections[i];
|
||||||
count++;
|
if (utils.isLiveViewer(conn) && ctx.tenant === tenantManager.getTenantByConnection(ctx, conn)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(count);
|
return count;
|
||||||
};
|
};
|
||||||
|
EditorStat.prototype.addShutdown = async function(key, docId) {
|
||||||
EditorData.prototype.addShutdown = function(key, docId) {
|
|
||||||
if (!this.shutdown[key]) {
|
if (!this.shutdown[key]) {
|
||||||
this.shutdown[key] = {};
|
this.shutdown[key] = {};
|
||||||
}
|
}
|
||||||
this.shutdown[key][docId] = 1;
|
this.shutdown[key][docId] = 1;
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.removeShutdown = function(key, docId) {
|
EditorStat.prototype.removeShutdown = async function(key, docId) {
|
||||||
if (!this.shutdown[key]) {
|
if (!this.shutdown[key]) {
|
||||||
this.shutdown[key] = {};
|
this.shutdown[key] = {};
|
||||||
}
|
}
|
||||||
delete this.shutdown[key][docId];
|
delete this.shutdown[key][docId];
|
||||||
return Promise.resolve();
|
|
||||||
};
|
};
|
||||||
EditorData.prototype.getShutdownCount = function(key) {
|
EditorStat.prototype.getShutdownCount = async function(key) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
if (this.shutdown[key]) {
|
if (this.shutdown[key]) {
|
||||||
for (let docId in this.shutdown[key]) {
|
for (let docId in this.shutdown[key]) {
|
||||||
@ -468,31 +483,22 @@ EditorData.prototype.getShutdownCount = function(key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Promise.resolve(count);
|
return count;
|
||||||
};
|
};
|
||||||
EditorData.prototype.cleanupShutdown = function(key) {
|
EditorStat.prototype.cleanupShutdown = async function(key) {
|
||||||
delete this.shutdown[key];
|
delete this.shutdown[key];
|
||||||
return Promise.resolve();
|
};
|
||||||
|
EditorStat.prototype.setLicense = async function(key, val) {
|
||||||
|
this.license[key] = val;
|
||||||
|
};
|
||||||
|
EditorStat.prototype.getLicense = async function(key) {
|
||||||
|
return this.license[key] || null;
|
||||||
|
};
|
||||||
|
EditorStat.prototype.removeLicense = async function(key) {
|
||||||
|
delete this.license[key];
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorData.prototype.setLicense = function(key, val) {
|
module.exports = {
|
||||||
return Promise.resolve();
|
EditorData,
|
||||||
};
|
EditorStat
|
||||||
EditorData.prototype.getLicense = function(key) {
|
}
|
||||||
return Promise.resolve(null);
|
|
||||||
};
|
|
||||||
EditorData.prototype.removeLicense = function(key) {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
EditorData.prototype.isConnected = function() {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
EditorData.prototype.ping = function() {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
EditorData.prototype.close = function() {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = EditorData;
|
|
||||||
|
|||||||
@ -78,7 +78,8 @@ var checkFileExpire = function(expireSeconds) {
|
|||||||
let tenant = expired[i].tenant;
|
let tenant = expired[i].tenant;
|
||||||
let docId = expired[i].id;
|
let docId = expired[i].id;
|
||||||
let shardKey = sqlBase.DocumentAdditional.prototype.getShardKey(expired[i].additional);
|
let shardKey = sqlBase.DocumentAdditional.prototype.getShardKey(expired[i].additional);
|
||||||
ctx.init(tenant, docId, ctx.userId, shardKey);
|
let wopiSrc = sqlBase.DocumentAdditional.prototype.getWopiSrc(expired[i].additional);
|
||||||
|
ctx.init(tenant, docId, ctx.userId, shardKey, wopiSrc);
|
||||||
yield ctx.initTenantCache();
|
yield ctx.initTenantCache();
|
||||||
//todo tenant
|
//todo tenant
|
||||||
//check that no one is in the document
|
//check that no one is in the document
|
||||||
@ -125,7 +126,7 @@ var checkDocumentExpire = function() {
|
|||||||
var hasChanges = yield docsCoServer.hasChanges(ctx, docId);
|
var hasChanges = yield docsCoServer.hasChanges(ctx, docId);
|
||||||
if (hasChanges) {
|
if (hasChanges) {
|
||||||
//todo opt_initShardKey from getDocumentPresenceExpired data or from db
|
//todo opt_initShardKey from getDocumentPresenceExpired data or from db
|
||||||
yield docsCoServer.createSaveTimer(ctx, docId, null, null, queue, true, true);
|
yield docsCoServer.createSaveTimer(ctx, docId, null, null, null, queue, true, true);
|
||||||
startSaveCount++;
|
startSaveCount++;
|
||||||
} else {
|
} else {
|
||||||
yield docsCoServer.cleanDocumentOnExitNoChangesPromise(ctx, docId);
|
yield docsCoServer.cleanDocumentOnExitNoChangesPromise(ctx, docId);
|
||||||
|
|||||||
104
DocService/sources/routes/static.js
Normal file
104
DocService/sources/routes/static.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright Ascensio System SIA 2010-2023
|
||||||
|
*
|
||||||
|
* This program is a free software product. You can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||||||
|
* version 3 as published by the Free Software Foundation. In accordance with
|
||||||
|
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||||||
|
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||||||
|
* of any third-party rights.
|
||||||
|
*
|
||||||
|
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||||||
|
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
*
|
||||||
|
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||||||
|
* street, Riga, Latvia, EU, LV-1050.
|
||||||
|
*
|
||||||
|
* The interactive user interfaces in modified source and object code versions
|
||||||
|
* of the Program must display Appropriate Legal Notices, as required under
|
||||||
|
* Section 5 of the GNU AGPL version 3.
|
||||||
|
*
|
||||||
|
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||||||
|
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||||||
|
* grant you any rights under trademark law for use of our trademarks.
|
||||||
|
*
|
||||||
|
* All the Product's GUI elements, including illustrations and icon sets, as
|
||||||
|
* well as technical writing content are licensed under the terms of the
|
||||||
|
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||||||
|
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
const express = require('express');
|
||||||
|
const config = require("config");
|
||||||
|
const operationContext = require('./../../../Common/sources/operationContext');
|
||||||
|
const utils = require('./../../../Common/sources/utils');
|
||||||
|
const storage = require('./../../../Common/sources/storage-base');
|
||||||
|
const urlModule = require("url");
|
||||||
|
const path = require("path");
|
||||||
|
const mime = require("mime");
|
||||||
|
|
||||||
|
const cfgStaticContent = config.has('services.CoAuthoring.server.static_content') ? config.get('services.CoAuthoring.server.static_content') : {};
|
||||||
|
const cfgCacheStorage = config.get('storage');
|
||||||
|
const cfgPersistentStorage = utils.deepMergeObjects({}, cfgCacheStorage, config.get('persistentStorage'));
|
||||||
|
const cfgForgottenFiles = config.get('services.CoAuthoring.server.forgottenfiles');
|
||||||
|
const cfgErrorFiles = config.get('FileConverter.converter.errorfiles');
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
function initCacheRouter(cfgStorage, routs) {
|
||||||
|
const bucketName = cfgStorage.bucketName;
|
||||||
|
const storageFolderName = cfgStorage.storageFolderName;
|
||||||
|
const folderPath = cfgStorage.fs.folderPath;
|
||||||
|
routs.forEach((rout) => {
|
||||||
|
//special dirs are empty by default
|
||||||
|
if (!rout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let rootPath = path.join(folderPath, rout);
|
||||||
|
router.use(`/${bucketName}/${storageFolderName}/${rout}`, (req, res, next) => {
|
||||||
|
const index = req.url.lastIndexOf('/');
|
||||||
|
if ('GET' === req.method && index > 0) {
|
||||||
|
let sendFileOptions = {
|
||||||
|
root: rootPath, dotfiles: 'deny', headers: {
|
||||||
|
'Content-Disposition': 'attachment'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const urlParsed = urlModule.parse(req.url);
|
||||||
|
if (urlParsed && urlParsed.pathname) {
|
||||||
|
const filename = decodeURIComponent(path.basename(urlParsed.pathname));
|
||||||
|
sendFileOptions.headers['Content-Type'] = mime.getType(filename);
|
||||||
|
}
|
||||||
|
const realUrl = decodeURI(req.url.substring(0, index));
|
||||||
|
res.sendFile(realUrl, sendFileOptions, (err) => {
|
||||||
|
if (err) {
|
||||||
|
operationContext.global.logger.error(err);
|
||||||
|
res.status(400).end();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
res.sendStatus(404);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i in cfgStaticContent) {
|
||||||
|
if (cfgStaticContent.hasOwnProperty(i)) {
|
||||||
|
router.use(i, express.static(cfgStaticContent[i]['path'], cfgStaticContent[i]['options']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (storage.needServeStatic()) {
|
||||||
|
initCacheRouter(cfgCacheStorage, [cfgCacheStorage.cacheFolderName]);
|
||||||
|
}
|
||||||
|
if (storage.needServeStatic(cfgForgottenFiles)) {
|
||||||
|
let persistentRouts = [cfgForgottenFiles, cfgErrorFiles];
|
||||||
|
persistentRouts.filter((rout) => {return rout && rout.length > 0;});
|
||||||
|
if (persistentRouts.length > 0) {
|
||||||
|
initCacheRouter(cfgPersistentStorage, [cfgForgottenFiles, cfgErrorFiles]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@ -57,7 +57,7 @@ const utils = require('./../../Common/sources/utils');
|
|||||||
const commonDefines = require('./../../Common/sources/commondefines');
|
const commonDefines = require('./../../Common/sources/commondefines');
|
||||||
const operationContext = require('./../../Common/sources/operationContext');
|
const operationContext = require('./../../Common/sources/operationContext');
|
||||||
const tenantManager = require('./../../Common/sources/tenantManager');
|
const tenantManager = require('./../../Common/sources/tenantManager');
|
||||||
const configStorage = config.get('storage');
|
const staticRouter = require('./routes/static');
|
||||||
|
|
||||||
const cfgWopiEnable = config.get('wopi.enable');
|
const cfgWopiEnable = config.get('wopi.enable');
|
||||||
const cfgWopiDummyEnable = config.get('wopi.dummy.enable');
|
const cfgWopiDummyEnable = config.get('wopi.dummy.enable');
|
||||||
@ -132,44 +132,6 @@ updateLicense();
|
|||||||
fs.watchFile(cfgLicenseFile, updateLicense);
|
fs.watchFile(cfgLicenseFile, updateLicense);
|
||||||
setInterval(updateLicense, 86400000);
|
setInterval(updateLicense, 86400000);
|
||||||
|
|
||||||
if (config.has('services.CoAuthoring.server.static_content')) {
|
|
||||||
const staticContent = config.get('services.CoAuthoring.server.static_content');
|
|
||||||
for (let i in staticContent) {
|
|
||||||
if (staticContent.hasOwnProperty(i)) {
|
|
||||||
app.use(i, express.static(staticContent[i]['path'], staticContent[i]['options']));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configStorage.has('fs.folderPath')) {
|
|
||||||
const cfgBucketName = configStorage.get('bucketName');
|
|
||||||
const cfgStorageFolderName = configStorage.get('storageFolderName');
|
|
||||||
app.use('/' + cfgBucketName + '/' + cfgStorageFolderName, (req, res, next) => {
|
|
||||||
const index = req.url.lastIndexOf('/');
|
|
||||||
if ('GET' === req.method && index > 0) {
|
|
||||||
let sendFileOptions = {
|
|
||||||
root: configStorage.get('fs.folderPath'), dotfiles: 'deny', headers: {
|
|
||||||
'Content-Disposition': 'attachment'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const urlParsed = urlModule.parse(req.url);
|
|
||||||
if (urlParsed && urlParsed.pathname) {
|
|
||||||
const filename = decodeURIComponent(path.basename(urlParsed.pathname));
|
|
||||||
sendFileOptions.headers['Content-Type'] = mime.getType(filename);
|
|
||||||
}
|
|
||||||
const realUrl = decodeURI(req.url.substring(0, index));
|
|
||||||
res.sendFile(realUrl, sendFileOptions, (err) => {
|
|
||||||
if (err) {
|
|
||||||
operationContext.global.logger.error(err);
|
|
||||||
res.status(400).end();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
res.sendStatus(404);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.watch(config.get('services.CoAuthoring.plugins.path'), updatePlugins);
|
fs.watch(config.get('services.CoAuthoring.plugins.path'), updatePlugins);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -211,6 +173,9 @@ docsCoServer.install(server, () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use('/', staticRouter);
|
||||||
|
|
||||||
const rawFileParser = bodyParser.raw(
|
const rawFileParser = bodyParser.raw(
|
||||||
{inflate: true, limit: config.get('services.CoAuthoring.server.limits_tempfile_upload'), type: function() {return true;}});
|
{inflate: true, limit: config.get('services.CoAuthoring.server.limits_tempfile_upload'), type: function() {return true;}});
|
||||||
const urleEcodedParser = bodyParser.urlencoded({ extended: false });
|
const urleEcodedParser = bodyParser.urlencoded({ extended: false });
|
||||||
|
|||||||
@ -47,7 +47,7 @@ var WAIT_TIMEOUT = 30000;
|
|||||||
var LOOP_TIMEOUT = 1000;
|
var LOOP_TIMEOUT = 1000;
|
||||||
var EXEC_TIMEOUT = WAIT_TIMEOUT + utils.getConvertionTimeout(undefined);
|
var EXEC_TIMEOUT = WAIT_TIMEOUT + utils.getConvertionTimeout(undefined);
|
||||||
|
|
||||||
exports.shutdown = function(ctx, editorData, status) {
|
exports.shutdown = function(ctx, editorStat, status) {
|
||||||
return co(function*() {
|
return co(function*() {
|
||||||
var res = true;
|
var res = true;
|
||||||
try {
|
try {
|
||||||
@ -55,7 +55,7 @@ exports.shutdown = function(ctx, editorData, status) {
|
|||||||
|
|
||||||
//redisKeyShutdown is not a simple counter, so it doesn't get decremented by a build that started before Shutdown started
|
//redisKeyShutdown is not a simple counter, so it doesn't get decremented by a build that started before Shutdown started
|
||||||
//reset redisKeyShutdown just in case the previous run didn't finish
|
//reset redisKeyShutdown just in case the previous run didn't finish
|
||||||
yield editorData.cleanupShutdown(redisKeyShutdown);
|
yield editorStat.cleanupShutdown(redisKeyShutdown);
|
||||||
|
|
||||||
var pubsub = new pubsubService();
|
var pubsub = new pubsubService();
|
||||||
yield pubsub.initPromise();
|
yield pubsub.initPromise();
|
||||||
@ -76,7 +76,7 @@ exports.shutdown = function(ctx, editorData, status) {
|
|||||||
ctx.logger.debug('shutdown timeout');
|
ctx.logger.debug('shutdown timeout');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var remainingFiles = yield editorData.getShutdownCount(redisKeyShutdown);
|
var remainingFiles = yield editorStat.getShutdownCount(redisKeyShutdown);
|
||||||
ctx.logger.debug('shutdown remaining files:%d', remainingFiles);
|
ctx.logger.debug('shutdown remaining files:%d', remainingFiles);
|
||||||
if (!isStartWait && remainingFiles <= 0) {
|
if (!isStartWait && remainingFiles <= 0) {
|
||||||
break;
|
break;
|
||||||
@ -85,7 +85,7 @@ exports.shutdown = function(ctx, editorData, status) {
|
|||||||
}
|
}
|
||||||
//todo need to check the queues, because there may be long conversions running before Shutdown
|
//todo need to check the queues, because there may be long conversions running before Shutdown
|
||||||
//clean up
|
//clean up
|
||||||
yield editorData.cleanupShutdown(redisKeyShutdown);
|
yield editorStat.cleanupShutdown(redisKeyShutdown);
|
||||||
yield pubsub.close();
|
yield pubsub.close();
|
||||||
|
|
||||||
ctx.logger.debug('shutdown end');
|
ctx.logger.debug('shutdown end');
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
const exifParser = require("exif-parser");
|
const exifParser = require("exif-parser");
|
||||||
const Jimp = require("jimp");
|
const Jimp = require("jimp");
|
||||||
|
const locale = require('windows-locale');
|
||||||
|
|
||||||
async function fixImageExifRotation(ctx, buffer) {
|
async function fixImageExifRotation(ctx, buffer) {
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
@ -59,7 +60,17 @@ async function fixImageExifRotation(ctx, buffer) {
|
|||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} lang
|
||||||
|
* @returns {number | undefined}
|
||||||
|
*/
|
||||||
|
function localeToLCID(lang) {
|
||||||
|
let elem = locale[lang && lang.toLowerCase()];
|
||||||
|
return elem && elem.id;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
fixImageExifRotation
|
fixImageExifRotation,
|
||||||
|
localeToLCID
|
||||||
};
|
};
|
||||||
@ -35,6 +35,7 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { pipeline } = require('node:stream/promises');
|
const { pipeline } = require('node:stream/promises');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
let util = require('util');
|
||||||
const {URL} = require('url');
|
const {URL} = require('url');
|
||||||
const co = require('co');
|
const co = require('co');
|
||||||
const jwt = require('jsonwebtoken');
|
const jwt = require('jsonwebtoken');
|
||||||
@ -63,18 +64,22 @@ const cfgTokenEnableBrowser = config.get('services.CoAuthoring.token.enable.brow
|
|||||||
const cfgCallbackRequestTimeout = config.get('services.CoAuthoring.server.callbackRequestTimeout');
|
const cfgCallbackRequestTimeout = config.get('services.CoAuthoring.server.callbackRequestTimeout');
|
||||||
const cfgNewFileTemplate = config.get('services.CoAuthoring.server.newFileTemplate');
|
const cfgNewFileTemplate = config.get('services.CoAuthoring.server.newFileTemplate');
|
||||||
const cfgDownloadTimeout = config.get('FileConverter.converter.downloadTimeout');
|
const cfgDownloadTimeout = config.get('FileConverter.converter.downloadTimeout');
|
||||||
|
const cfgMaxDownloadBytes = config.get('FileConverter.converter.maxDownloadBytes');
|
||||||
const cfgWopiFileInfoBlockList = config.get('wopi.fileInfoBlockList');
|
const cfgWopiFileInfoBlockList = config.get('wopi.fileInfoBlockList');
|
||||||
const cfgWopiWopiZone = config.get('wopi.wopiZone');
|
const cfgWopiWopiZone = config.get('wopi.wopiZone');
|
||||||
const cfgWopiPdfView = config.get('wopi.pdfView');
|
const cfgWopiPdfView = config.get('wopi.pdfView');
|
||||||
|
const cfgWopiPdfEdit = config.get('wopi.pdfEdit');
|
||||||
const cfgWopiWordView = config.get('wopi.wordView');
|
const cfgWopiWordView = config.get('wopi.wordView');
|
||||||
const cfgWopiWordEdit = config.get('wopi.wordEdit');
|
const cfgWopiWordEdit = config.get('wopi.wordEdit');
|
||||||
const cfgWopiCellView = config.get('wopi.cellView');
|
const cfgWopiCellView = config.get('wopi.cellView');
|
||||||
const cfgWopiCellEdit = config.get('wopi.cellEdit');
|
const cfgWopiCellEdit = config.get('wopi.cellEdit');
|
||||||
const cfgWopiSlideView = config.get('wopi.slideView');
|
const cfgWopiSlideView = config.get('wopi.slideView');
|
||||||
const cfgWopiSlideEdit = config.get('wopi.slideEdit');
|
const cfgWopiSlideEdit = config.get('wopi.slideEdit');
|
||||||
|
const cfgWopiForms = config.get('wopi.forms');
|
||||||
const cfgWopiFavIconUrlWord = config.get('wopi.favIconUrlWord');
|
const cfgWopiFavIconUrlWord = config.get('wopi.favIconUrlWord');
|
||||||
const cfgWopiFavIconUrlCell = config.get('wopi.favIconUrlCell');
|
const cfgWopiFavIconUrlCell = config.get('wopi.favIconUrlCell');
|
||||||
const cfgWopiFavIconUrlSlide = config.get('wopi.favIconUrlSlide');
|
const cfgWopiFavIconUrlSlide = config.get('wopi.favIconUrlSlide');
|
||||||
|
const cfgWopiFavIconUrlPdf = config.get('wopi.favIconUrlPdf');
|
||||||
const cfgWopiPublicKey = config.get('wopi.publicKey');
|
const cfgWopiPublicKey = config.get('wopi.publicKey');
|
||||||
const cfgWopiModulus = config.get('wopi.modulus');
|
const cfgWopiModulus = config.get('wopi.modulus');
|
||||||
const cfgWopiExponent = config.get('wopi.exponent');
|
const cfgWopiExponent = config.get('wopi.exponent');
|
||||||
@ -86,8 +91,12 @@ const cfgWopiPrivateKeyOld = config.get('wopi.privateKeyOld');
|
|||||||
const cfgWopiHost = config.get('wopi.host');
|
const cfgWopiHost = config.get('wopi.host');
|
||||||
const cfgWopiDummySampleFilePath = config.get('wopi.dummy.sampleFilePath');
|
const cfgWopiDummySampleFilePath = config.get('wopi.dummy.sampleFilePath');
|
||||||
|
|
||||||
|
let cryptoSign = util.promisify(crypto.sign);
|
||||||
|
|
||||||
let templatesFolderLocalesCache = null;
|
let templatesFolderLocalesCache = null;
|
||||||
|
let templatesFolderExtsCache = null;
|
||||||
const templateFilesSizeCache = {};
|
const templateFilesSizeCache = {};
|
||||||
|
let shutdownFlag = false;
|
||||||
|
|
||||||
let mimeTypesByExt = (function() {
|
let mimeTypesByExt = (function() {
|
||||||
let mimeTypesByExt = {};
|
let mimeTypesByExt = {};
|
||||||
@ -107,9 +116,24 @@ let mimeTypesByExt = (function() {
|
|||||||
return mimeTypesByExt;
|
return mimeTypesByExt;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
async function getTemplatesFolderExts(ctx){
|
||||||
|
//find available template files
|
||||||
|
if (templatesFolderExtsCache === null) {
|
||||||
|
const tenNewFileTemplate = ctx.getCfg('services.CoAuthoring.server.newFileTemplate', cfgNewFileTemplate);
|
||||||
|
const dirContent = await readdir(`${tenNewFileTemplate}/${constants.TEMPLATES_DEFAULT_LOCALE}/`, { withFileTypes: true });
|
||||||
|
templatesFolderExtsCache = dirContent
|
||||||
|
.filter(dirObject => dirObject.isFile())
|
||||||
|
.reduce((result, item, index, array) => {
|
||||||
|
let ext = path.extname(item.name).substring(1);
|
||||||
|
result[ext] = ext;
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
return templatesFolderExtsCache;
|
||||||
|
}
|
||||||
|
|
||||||
function discovery(req, res) {
|
function discovery(req, res) {
|
||||||
return co(function*() {
|
return co(function*() {
|
||||||
let output = '';
|
|
||||||
const xml = xmlbuilder2.create({version: '1.0', encoding: 'utf-8'});
|
const xml = xmlbuilder2.create({version: '1.0', encoding: 'utf-8'});
|
||||||
let ctx = new operationContext.Context();
|
let ctx = new operationContext.Context();
|
||||||
try {
|
try {
|
||||||
@ -118,15 +142,18 @@ function discovery(req, res) {
|
|||||||
ctx.logger.info('wopiDiscovery start');
|
ctx.logger.info('wopiDiscovery start');
|
||||||
const tenWopiWopiZone = ctx.getCfg('wopi.wopiZone', cfgWopiWopiZone);
|
const tenWopiWopiZone = ctx.getCfg('wopi.wopiZone', cfgWopiWopiZone);
|
||||||
const tenWopiPdfView = ctx.getCfg('wopi.pdfView', cfgWopiPdfView);
|
const tenWopiPdfView = ctx.getCfg('wopi.pdfView', cfgWopiPdfView);
|
||||||
|
const tenWopiPdfEdit = ctx.getCfg('wopi.pdfEdit', cfgWopiPdfEdit);
|
||||||
const tenWopiWordView = ctx.getCfg('wopi.wordView', cfgWopiWordView);
|
const tenWopiWordView = ctx.getCfg('wopi.wordView', cfgWopiWordView);
|
||||||
const tenWopiWordEdit = ctx.getCfg('wopi.wordEdit', cfgWopiWordEdit);
|
const tenWopiWordEdit = ctx.getCfg('wopi.wordEdit', cfgWopiWordEdit);
|
||||||
const tenWopiCellView = ctx.getCfg('wopi.cellView', cfgWopiCellView);
|
const tenWopiCellView = ctx.getCfg('wopi.cellView', cfgWopiCellView);
|
||||||
const tenWopiCellEdit = ctx.getCfg('wopi.cellEdit', cfgWopiCellEdit);
|
const tenWopiCellEdit = ctx.getCfg('wopi.cellEdit', cfgWopiCellEdit);
|
||||||
const tenWopiSlideView = ctx.getCfg('wopi.slideView', cfgWopiSlideView);
|
const tenWopiSlideView = ctx.getCfg('wopi.slideView', cfgWopiSlideView);
|
||||||
const tenWopiSlideEdit = ctx.getCfg('wopi.slideEdit', cfgWopiSlideEdit);
|
const tenWopiSlideEdit = ctx.getCfg('wopi.slideEdit', cfgWopiSlideEdit);
|
||||||
|
const tenWopiForms = ctx.getCfg('wopi.forms', cfgWopiForms);
|
||||||
const tenWopiFavIconUrlWord = ctx.getCfg('wopi.favIconUrlWord', cfgWopiFavIconUrlWord);
|
const tenWopiFavIconUrlWord = ctx.getCfg('wopi.favIconUrlWord', cfgWopiFavIconUrlWord);
|
||||||
const tenWopiFavIconUrlCell = ctx.getCfg('wopi.favIconUrlCell', cfgWopiFavIconUrlCell);
|
const tenWopiFavIconUrlCell = ctx.getCfg('wopi.favIconUrlCell', cfgWopiFavIconUrlCell);
|
||||||
const tenWopiFavIconUrlSlide = ctx.getCfg('wopi.favIconUrlSlide', cfgWopiFavIconUrlSlide);
|
const tenWopiFavIconUrlSlide = ctx.getCfg('wopi.favIconUrlSlide', cfgWopiFavIconUrlSlide);
|
||||||
|
const tenWopiFavIconUrlPdf = ctx.getCfg('wopi.favIconUrlSlide', cfgWopiFavIconUrlPdf);
|
||||||
const tenWopiPublicKey = ctx.getCfg('wopi.publicKey', cfgWopiPublicKey);
|
const tenWopiPublicKey = ctx.getCfg('wopi.publicKey', cfgWopiPublicKey);
|
||||||
const tenWopiModulus = ctx.getCfg('wopi.modulus', cfgWopiModulus);
|
const tenWopiModulus = ctx.getCfg('wopi.modulus', cfgWopiModulus);
|
||||||
const tenWopiExponent = ctx.getCfg('wopi.exponent', cfgWopiExponent);
|
const tenWopiExponent = ctx.getCfg('wopi.exponent', cfgWopiExponent);
|
||||||
@ -136,20 +163,27 @@ function discovery(req, res) {
|
|||||||
const tenWopiHost = ctx.getCfg('wopi.host', cfgWopiHost);
|
const tenWopiHost = ctx.getCfg('wopi.host', cfgWopiHost);
|
||||||
|
|
||||||
let baseUrl = tenWopiHost || utils.getBaseUrlByRequest(ctx, req);
|
let baseUrl = tenWopiHost || utils.getBaseUrlByRequest(ctx, req);
|
||||||
let names = ['Word','Excel','PowerPoint'];
|
let names = ['Word','Excel','PowerPoint','Pdf'];
|
||||||
let favIconUrls = [tenWopiFavIconUrlWord, tenWopiFavIconUrlCell, tenWopiFavIconUrlSlide];
|
let favIconUrls = [tenWopiFavIconUrlWord, tenWopiFavIconUrlCell, tenWopiFavIconUrlSlide, tenWopiFavIconUrlPdf];
|
||||||
let exts = [
|
let exts = [
|
||||||
{targetext: 'docx', view: tenWopiPdfView.concat(tenWopiWordView), edit: tenWopiWordEdit},
|
{targetext: 'docx', view: tenWopiWordView, edit: tenWopiWordEdit},
|
||||||
{targetext: 'xlsx', view: tenWopiCellView, edit: tenWopiCellEdit},
|
{targetext: 'xlsx', view: tenWopiCellView, edit: tenWopiCellEdit},
|
||||||
{targetext: 'pptx', view: tenWopiSlideView, edit: tenWopiSlideEdit}
|
{targetext: 'pptx', view: tenWopiSlideView, edit: tenWopiSlideEdit},
|
||||||
|
{targetext: null, view: tenWopiPdfView, edit: tenWopiPdfEdit}
|
||||||
];
|
];
|
||||||
|
let documentTypes = [`word`, `cell`, `slide`, `pdf`];
|
||||||
|
|
||||||
|
let templatesFolderExtsCache = yield getTemplatesFolderExts(ctx);
|
||||||
|
let formsExts = tenWopiForms.reduce((result, item, index, array) => {
|
||||||
|
result[item] = item;
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
|
||||||
let templateStart = `${baseUrl}/hosting/wopi`;
|
let templateStart = `${baseUrl}/hosting/wopi`;
|
||||||
let templateEnd = `<rs=DC_LLCC&><dchat=DISABLE_CHAT&><embed=EMBEDDED&>`;
|
let templateEnd = `<rs=DC_LLCC&><dchat=DISABLE_CHAT&><embed=EMBEDDED&>`;
|
||||||
templateEnd += `<fs=FULLSCREEN&><hid=HOST_SESSION_ID&><rec=RECORDING&>`;
|
templateEnd += `<fs=FULLSCREEN&><hid=HOST_SESSION_ID&><rec=RECORDING&>`;
|
||||||
templateEnd += `<sc=SESSION_CONTEXT&><thm=THEME_ID&><ui=UI_LLCC&>`;
|
templateEnd += `<sc=SESSION_CONTEXT&><thm=THEME_ID&><ui=UI_LLCC&>`;
|
||||||
templateEnd += `<wopisrc=WOPI_SOURCE&>&`;
|
templateEnd += `<wopisrc=WOPI_SOURCE&>&`;
|
||||||
let documentTypes = [`word`, `cell`, `slide`];
|
|
||||||
let xmlZone = xml.ele('wopi-discovery').ele('net-zone', { name: tenWopiWopiZone });
|
let xmlZone = xml.ele('wopi-discovery').ele('net-zone', { name: tenWopiWopiZone });
|
||||||
//start section for MS WOPI connectors
|
//start section for MS WOPI connectors
|
||||||
for(let i = 0; i < names.length; ++i) {
|
for(let i = 0; i < names.length; ++i) {
|
||||||
@ -164,12 +198,13 @@ function discovery(req, res) {
|
|||||||
let urlTemplateMobileView = `${templateStart}/${documentTypes[i]}/view?mobile=1&${templateEnd}`;
|
let urlTemplateMobileView = `${templateStart}/${documentTypes[i]}/view?mobile=1&${templateEnd}`;
|
||||||
let urlTemplateEdit = `${templateStart}/${documentTypes[i]}/edit?${templateEnd}`;
|
let urlTemplateEdit = `${templateStart}/${documentTypes[i]}/edit?${templateEnd}`;
|
||||||
let urlTemplateMobileEdit = `${templateStart}/${documentTypes[i]}/edit?mobile=1&${templateEnd}`;
|
let urlTemplateMobileEdit = `${templateStart}/${documentTypes[i]}/edit?mobile=1&${templateEnd}`;
|
||||||
|
let urlTemplateFormSubmit = `${templateStart}/${documentTypes[i]}/edit?formsubmit=1&${templateEnd}`;
|
||||||
let xmlApp = xmlZone.ele('app', {name: name, favIconUrl: favIconUrl});
|
let xmlApp = xmlZone.ele('app', {name: name, favIconUrl: favIconUrl});
|
||||||
for (let j = 0; j < ext.view.length; ++j) {
|
for (let j = 0; j < ext.view.length; ++j) {
|
||||||
xmlApp.ele('action', {name: 'view', ext: ext.view[j], urlsrc: urlTemplateView}).up();
|
xmlApp.ele('action', {name: 'view', ext: ext.view[j], default: 'true', urlsrc: urlTemplateView}).up();
|
||||||
xmlApp.ele('action', {name: 'embedview', ext: ext.view[j], urlsrc: urlTemplateEmbedView}).up();
|
xmlApp.ele('action', {name: 'embedview', ext: ext.view[j], urlsrc: urlTemplateEmbedView}).up();
|
||||||
xmlApp.ele('action', {name: 'mobileView', ext: ext.view[j], urlsrc: urlTemplateMobileView}).up();
|
xmlApp.ele('action', {name: 'mobileView', ext: ext.view[j], urlsrc: urlTemplateMobileView}).up();
|
||||||
if (-1 === tenWopiPdfView.indexOf(ext.view[j])) {
|
if (ext.targetext) {
|
||||||
let urlConvert = `${templateStart}/convert-and-edit/${ext.view[j]}/${ext.targetext}?${templateEnd}`;
|
let urlConvert = `${templateStart}/convert-and-edit/${ext.view[j]}/${ext.targetext}?${templateEnd}`;
|
||||||
xmlApp.ele('action', {name: 'convert', ext: ext.view[j], targetext: ext.targetext, requires: 'update', urlsrc: urlConvert}).up();
|
xmlApp.ele('action', {name: 'convert', ext: ext.view[j], targetext: ext.targetext, requires: 'update', urlsrc: urlConvert}).up();
|
||||||
}
|
}
|
||||||
@ -178,12 +213,17 @@ function discovery(req, res) {
|
|||||||
xmlApp.ele('action', {name: 'view', ext: ext.edit[j], urlsrc: urlTemplateView}).up();
|
xmlApp.ele('action', {name: 'view', ext: ext.edit[j], urlsrc: urlTemplateView}).up();
|
||||||
xmlApp.ele('action', {name: 'embedview', ext: ext.edit[j], urlsrc: urlTemplateEmbedView}).up();
|
xmlApp.ele('action', {name: 'embedview', ext: ext.edit[j], urlsrc: urlTemplateEmbedView}).up();
|
||||||
xmlApp.ele('action', {name: 'mobileView', ext: ext.edit[j], urlsrc: urlTemplateMobileView}).up();
|
xmlApp.ele('action', {name: 'mobileView', ext: ext.edit[j], urlsrc: urlTemplateMobileView}).up();
|
||||||
xmlApp.ele('action', {name: 'edit', ext: ext.edit[j], default: 'true', requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
if (formsExts[ext.edit[j]]) {
|
||||||
|
xmlApp.ele('action', {name: 'formsubmit', ext: ext.edit[j], default: 'true', requires: 'locks,update', urlsrc: urlTemplateFormSubmit}).up();
|
||||||
|
xmlApp.ele('action', {name: 'edit', ext: ext.edit[j], requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
||||||
|
} else {
|
||||||
|
xmlApp.ele('action', {name: 'edit', ext: ext.edit[j], default: 'true', requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
||||||
|
}
|
||||||
xmlApp.ele('action', {name: 'mobileEdit', ext: ext.edit[j], requires: 'locks,update', urlsrc: urlTemplateMobileEdit}).up();
|
xmlApp.ele('action', {name: 'mobileEdit', ext: ext.edit[j], requires: 'locks,update', urlsrc: urlTemplateMobileEdit}).up();
|
||||||
|
if (templatesFolderExtsCache[ext.edit[j]]) {
|
||||||
|
xmlApp.ele('action', {name: 'editnew', ext: ext.edit[j], requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
constants.SUPPORTED_TEMPLATES_EXTENSIONS[name].forEach(
|
|
||||||
extension => xmlApp.ele('action', {name: 'editnew', ext: extension, requires: 'locks,update', urlsrc: urlTemplateEdit}).up()
|
|
||||||
);
|
|
||||||
xmlApp.up();
|
xmlApp.up();
|
||||||
}
|
}
|
||||||
//end section for MS WOPI connectors
|
//end section for MS WOPI connectors
|
||||||
@ -195,6 +235,7 @@ function discovery(req, res) {
|
|||||||
let urlTemplateMobileView = `${templateStart}/${documentTypes[i]}/view?mobile=1&${templateEnd}`;
|
let urlTemplateMobileView = `${templateStart}/${documentTypes[i]}/view?mobile=1&${templateEnd}`;
|
||||||
let urlTemplateEdit = `${templateStart}/${documentTypes[i]}/edit?${templateEnd}`;
|
let urlTemplateEdit = `${templateStart}/${documentTypes[i]}/edit?${templateEnd}`;
|
||||||
let urlTemplateMobileEdit = `${templateStart}/${documentTypes[i]}/edit?mobile=1&${templateEnd}`;
|
let urlTemplateMobileEdit = `${templateStart}/${documentTypes[i]}/edit?mobile=1&${templateEnd}`;
|
||||||
|
let urlTemplateFormSubmit = `${templateStart}/${documentTypes[i]}/edit?formsubmit=1&${templateEnd}`;
|
||||||
for (let j = 0; j < ext.view.length; ++j) {
|
for (let j = 0; j < ext.view.length; ++j) {
|
||||||
let mimeTypes = mimeTypesByExt[ext.view[j]];
|
let mimeTypes = mimeTypesByExt[ext.view[j]];
|
||||||
if (mimeTypes) {
|
if (mimeTypes) {
|
||||||
@ -203,7 +244,7 @@ function discovery(req, res) {
|
|||||||
xmlApp.ele('action', {name: 'view', ext: '', default: 'true', urlsrc: urlTemplateView}).up();
|
xmlApp.ele('action', {name: 'view', ext: '', default: 'true', urlsrc: urlTemplateView}).up();
|
||||||
xmlApp.ele('action', {name: 'embedview', ext: '', urlsrc: urlTemplateEmbedView}).up();
|
xmlApp.ele('action', {name: 'embedview', ext: '', urlsrc: urlTemplateEmbedView}).up();
|
||||||
xmlApp.ele('action', {name: 'mobileView', ext: '', urlsrc: urlTemplateMobileView}).up();
|
xmlApp.ele('action', {name: 'mobileView', ext: '', urlsrc: urlTemplateMobileView}).up();
|
||||||
if (-1 === tenWopiPdfView.indexOf(ext.view[j])) {
|
if (ext.targetext) {
|
||||||
let urlConvert = `${templateStart}/convert-and-edit/${ext.view[j]}/${ext.targetext}?${templateEnd}`;
|
let urlConvert = `${templateStart}/convert-and-edit/${ext.view[j]}/${ext.targetext}?${templateEnd}`;
|
||||||
xmlApp.ele('action', {name: 'convert', ext: '', targetext: ext.targetext, requires: 'update', urlsrc: urlConvert}).up();
|
xmlApp.ele('action', {name: 'convert', ext: '', targetext: ext.targetext, requires: 'update', urlsrc: urlConvert}).up();
|
||||||
}
|
}
|
||||||
@ -216,8 +257,16 @@ function discovery(req, res) {
|
|||||||
if (mimeTypes) {
|
if (mimeTypes) {
|
||||||
mimeTypes.forEach((value) => {
|
mimeTypes.forEach((value) => {
|
||||||
let xmlApp = xmlZone.ele('app', {name: value});
|
let xmlApp = xmlZone.ele('app', {name: value});
|
||||||
xmlApp.ele('action', {name: 'edit', ext: '', default: 'true', requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
if (formsExts[ext.edit[j]]) {
|
||||||
|
xmlApp.ele('action', {name: 'formsubmit', ext: '', default: 'true', requires: 'locks,update', urlsrc: urlTemplateFormSubmit}).up();
|
||||||
|
xmlApp.ele('action', {name: 'edit', ext: '', requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
||||||
|
} else {
|
||||||
|
xmlApp.ele('action', {name: 'edit', ext: '', default: 'true', requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
||||||
|
}
|
||||||
xmlApp.ele('action', {name: 'mobileEdit', ext: '', requires: 'locks,update', urlsrc: urlTemplateMobileEdit}).up();
|
xmlApp.ele('action', {name: 'mobileEdit', ext: '', requires: 'locks,update', urlsrc: urlTemplateMobileEdit}).up();
|
||||||
|
if (templatesFolderExtsCache[ext.edit[j]]) {
|
||||||
|
xmlApp.ele('action', {name: 'editnew', ext: '', requires: 'locks,update', urlsrc: urlTemplateEdit}).up();
|
||||||
|
}
|
||||||
xmlApp.up();
|
xmlApp.up();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -229,9 +278,11 @@ function discovery(req, res) {
|
|||||||
//end section for collabora nexcloud connectors
|
//end section for collabora nexcloud connectors
|
||||||
let xmlDiscovery = xmlZone.up();
|
let xmlDiscovery = xmlZone.up();
|
||||||
if (tenWopiPublicKeyOld && tenWopiPublicKey) {
|
if (tenWopiPublicKeyOld && tenWopiPublicKey) {
|
||||||
|
let exponent = numberToBase64(tenWopiExponent - 0);
|
||||||
|
let exponentOld = numberToBase64(tenWopiExponentOld - 0);
|
||||||
xmlDiscovery.ele('proof-key', {
|
xmlDiscovery.ele('proof-key', {
|
||||||
oldvalue: tenWopiPublicKeyOld, oldmodulus: tenWopiModulusOld, oldexponent: tenWopiExponentOld,
|
oldvalue: tenWopiPublicKeyOld, oldmodulus: tenWopiModulusOld, oldexponent: exponentOld,
|
||||||
value: tenWopiPublicKey, modulus: tenWopiModulus, exponent: tenWopiExponent
|
value: tenWopiPublicKey, modulus: tenWopiModulus, exponent: exponent
|
||||||
}).up();
|
}).up();
|
||||||
}
|
}
|
||||||
xmlDiscovery.up();
|
xmlDiscovery.up();
|
||||||
@ -289,6 +340,28 @@ function getFileTypeByInfo(fileInfo) {
|
|||||||
fileType = fileInfo.FileExtension ? fileInfo.FileExtension.substr(1) : fileType;
|
fileType = fileInfo.FileExtension ? fileInfo.FileExtension.substr(1) : fileType;
|
||||||
return fileType.toLowerCase();
|
return fileType.toLowerCase();
|
||||||
}
|
}
|
||||||
|
async function getWopiFileUrl(ctx, fileInfo, userAuth) {
|
||||||
|
const tenMaxDownloadBytes = ctx.getCfg('FileConverter.converter.maxDownloadBytes', cfgMaxDownloadBytes);
|
||||||
|
let url;
|
||||||
|
let headers = {'X-WOPI-MaxExpectedSize': tenMaxDownloadBytes};
|
||||||
|
if (fileInfo?.FileUrl) {
|
||||||
|
//Requests to the FileUrl can not be signed using proof keys. The FileUrl is used exactly as provided by the host, so it does not necessarily include the access token, which is required to construct the expected proof.
|
||||||
|
url = fileInfo.FileUrl;
|
||||||
|
} else if (fileInfo?.TemplateSource) {
|
||||||
|
url = fileInfo.TemplateSource;
|
||||||
|
} else if (userAuth) {
|
||||||
|
url = `${userAuth.wopiSrc}/contents?access_token=${userAuth.access_token}`;
|
||||||
|
await fillStandardHeaders(ctx, headers, url, userAuth.access_token);
|
||||||
|
}
|
||||||
|
ctx.logger.debug('getWopiFileUrl url=%s; headers=%j', url, headers);
|
||||||
|
return {url, headers};
|
||||||
|
}
|
||||||
|
function isWopiJwtToken(decoded) {
|
||||||
|
return !!decoded.fileInfo;
|
||||||
|
}
|
||||||
|
function setIsShutdown(val) {
|
||||||
|
shutdownFlag = val;
|
||||||
|
}
|
||||||
function getLastModifiedTimeFromCallbacks(callbacks) {
|
function getLastModifiedTimeFromCallbacks(callbacks) {
|
||||||
for (let i = callbacks.length; i >= 0; --i) {
|
for (let i = callbacks.length; i >= 0; --i) {
|
||||||
let callback = callbacks[i];
|
let callback = callbacks[i];
|
||||||
@ -443,45 +516,47 @@ function getEditorHtml(req, res) {
|
|||||||
params.fileInfo = {};
|
params.fileInfo = {};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//save common info
|
if (!shutdownFlag) {
|
||||||
const fileType = getFileTypeByInfo(fileInfo);
|
//save common info
|
||||||
if (undefined === lockId) {
|
const fileType = getFileTypeByInfo(fileInfo);
|
||||||
lockId = crypto.randomBytes(16).toString('base64');
|
if (undefined === lockId) {
|
||||||
let commonInfo = JSON.stringify({lockId: lockId, fileInfo: fileInfo});
|
lockId = crypto.randomBytes(16).toString('base64');
|
||||||
yield canvasService.commandOpenStartPromise(ctx, docId, utils.getBaseUrlByRequest(ctx, req), commonInfo, fileType);
|
let commonInfo = JSON.stringify({lockId: lockId, fileInfo: fileInfo});
|
||||||
}
|
yield canvasService.commandOpenStartPromise(ctx, docId, utils.getBaseUrlByRequest(ctx, req), commonInfo, fileType);
|
||||||
|
|
||||||
// TODO: throw error if format not supported?
|
|
||||||
if (fileInfo.Size === 0 && fileType.length !== 0) {
|
|
||||||
const wopiParams = getWopiParams(undefined, fileInfo, wopiSrc, access_token, access_token_ttl);
|
|
||||||
|
|
||||||
if (templatesFolderLocalesCache === null) {
|
|
||||||
const dirContent = yield readdir(`${tenNewFileTemplate}/`, { withFileTypes: true });
|
|
||||||
templatesFolderLocalesCache = dirContent.filter(dirObject => dirObject.isDirectory()).map(dirObject => dirObject.name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const localePrefix = lang || ui || 'en';
|
// TODO: throw error if format not supported?
|
||||||
let locale = constants.TEMPLATES_FOLDER_LOCALE_COLLISON_MAP[localePrefix] ?? templatesFolderLocalesCache.find(locale => locale.startsWith(localePrefix));
|
if (fileInfo.Size === 0 && fileType.length !== 0) {
|
||||||
if (locale === undefined) {
|
const wopiParams = getWopiParams(undefined, fileInfo, wopiSrc, access_token, access_token_ttl);
|
||||||
locale = 'en-US';
|
|
||||||
|
if (templatesFolderLocalesCache === null) {
|
||||||
|
const dirContent = yield readdir(`${tenNewFileTemplate}/`, { withFileTypes: true });
|
||||||
|
templatesFolderLocalesCache = dirContent.filter(dirObject => dirObject.isDirectory()).map(dirObject => dirObject.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const localePrefix = lang || ui || 'en';
|
||||||
|
let locale = constants.TEMPLATES_FOLDER_LOCALE_COLLISON_MAP[localePrefix] ?? templatesFolderLocalesCache.find(locale => locale.startsWith(localePrefix));
|
||||||
|
if (locale === undefined) {
|
||||||
|
locale = constants.TEMPLATES_DEFAULT_LOCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filePath = `${tenNewFileTemplate}/${locale}/new.${fileType}`;
|
||||||
|
if (!templateFilesSizeCache[filePath]) {
|
||||||
|
templateFilesSizeCache[filePath] = yield lstat(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
const templateFileInfo = templateFilesSizeCache[filePath];
|
||||||
|
const templateFileStream = createReadStream(filePath);
|
||||||
|
yield putFile(ctx, wopiParams, undefined, templateFileStream, templateFileInfo.size, fileInfo.UserId, false, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const filePath = `${tenNewFileTemplate}/${locale}/new.${fileType}`;
|
//Lock
|
||||||
if (!templateFilesSizeCache[filePath]) {
|
if ('view' !== mode) {
|
||||||
templateFilesSizeCache[filePath] = yield lstat(filePath);
|
let lockRes = yield lock(ctx, 'LOCK', lockId, fileInfo, userAuth);
|
||||||
}
|
if (!lockRes) {
|
||||||
|
params.fileInfo = {};
|
||||||
const templateFileInfo = templateFilesSizeCache[filePath];
|
return;
|
||||||
const templateFileStream = createReadStream(filePath);
|
}
|
||||||
yield putFile(ctx, wopiParams, undefined, templateFileStream, templateFileInfo.size, fileInfo.UserId, false, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Lock
|
|
||||||
if ('view' !== mode) {
|
|
||||||
let lockRes = yield lock(ctx, 'LOCK', lockId, fileInfo, userAuth);
|
|
||||||
if (!lockRes) {
|
|
||||||
params.fileInfo = {};
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,7 +607,7 @@ function getConverterHtml(req, res) {
|
|||||||
let targetext = req.params.targetext;
|
let targetext = req.params.targetext;
|
||||||
|
|
||||||
if (!(wopiSrc && access_token && access_token_ttl && ext && targetext)) {
|
if (!(wopiSrc && access_token && access_token_ttl && ext && targetext)) {
|
||||||
ctx.logger.debug('convert-and-edit invalid params: wopiSrc=%s; access_token=%s; access_token_ttl=%s; ext=%s; targetext=%s', wopiSrc, access_token, access_token_ttl, ext, targetext);
|
ctx.logger.debug('convert-and-edit invalid params: WOPISrc=%s; access_token=%s; access_token_ttl=%s; ext=%s; targetext=%s', wopiSrc, access_token, access_token_ttl, ext, targetext);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,15 +623,15 @@ function getConverterHtml(req, res) {
|
|||||||
if (docId) {
|
if (docId) {
|
||||||
let baseUrl = tenWopiHost || utils.getBaseUrlByRequest(ctx, req);
|
let baseUrl = tenWopiHost || utils.getBaseUrlByRequest(ctx, req);
|
||||||
params.statusHandler = `${baseUrl}/hosting/wopi/convert-and-edit-handler`;
|
params.statusHandler = `${baseUrl}/hosting/wopi/convert-and-edit-handler`;
|
||||||
params.statusHandler += `?wopiSrc=${encodeURI(wopiSrc)}&access_token=${encodeURI(access_token)}`;
|
params.statusHandler += `?${constants.SHARD_KEY_WOPI_NAME}=${encodeURIComponent(wopiSrc)}&access_token=${encodeURIComponent(access_token)}`;
|
||||||
params.statusHandler += `&targetext=${encodeURI(targetext)}&docId=${encodeURI(docId)}`;
|
params.statusHandler += `&targetext=${encodeURIComponent(targetext)}&docId=${encodeURIComponent(docId)}`;
|
||||||
if (tenTokenEnableBrowser) {
|
if (tenTokenEnableBrowser) {
|
||||||
let tokenData = {docId: docId};
|
let tokenData = {docId: docId};
|
||||||
let options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
let options = {algorithm: tenTokenOutboxAlgorithm, expiresIn: tenTokenOutboxExpires};
|
||||||
let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
let secret = yield tenantManager.getTenantSecret(ctx, commonDefines.c_oAscSecretType.Browser);
|
||||||
let token = jwt.sign(tokenData, secret, options);
|
let token = jwt.sign(tokenData, secret, options);
|
||||||
|
|
||||||
params.statusHandler += `&token=${encodeURI(token)}`;
|
params.statusHandler += `&token=${encodeURIComponent(token)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -596,7 +671,7 @@ function putFile(ctx, wopiParams, data, dataStream, dataSize, userLastChangeId,
|
|||||||
let commonInfo = wopiParams.commonInfo;
|
let commonInfo = wopiParams.commonInfo;
|
||||||
//todo add all the users who contributed changes to the document in this PutFile request to X-WOPI-Editors
|
//todo add all the users who contributed changes to the document in this PutFile request to X-WOPI-Editors
|
||||||
let headers = {'X-WOPI-Override': 'PUT', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-Editors': userLastChangeId};
|
let headers = {'X-WOPI-Override': 'PUT', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-Editors': userLastChangeId};
|
||||||
fillStandardHeaders(ctx, headers, uri, userAuth.access_token);
|
yield fillStandardHeaders(ctx, headers, uri, userAuth.access_token);
|
||||||
headers['X-LOOL-WOPI-IsModifiedByUser'] = isModifiedByUser;
|
headers['X-LOOL-WOPI-IsModifiedByUser'] = isModifiedByUser;
|
||||||
headers['X-LOOL-WOPI-IsAutosave'] = isAutosave;
|
headers['X-LOOL-WOPI-IsAutosave'] = isAutosave;
|
||||||
headers['X-LOOL-WOPI-IsExitSave'] = isExitSave;
|
headers['X-LOOL-WOPI-IsExitSave'] = isExitSave;
|
||||||
@ -604,6 +679,7 @@ function putFile(ctx, wopiParams, data, dataStream, dataSize, userLastChangeId,
|
|||||||
//collabora nexcloud connector
|
//collabora nexcloud connector
|
||||||
headers['X-LOOL-WOPI-Timestamp'] = wopiParams.LastModifiedTime;
|
headers['X-LOOL-WOPI-Timestamp'] = wopiParams.LastModifiedTime;
|
||||||
}
|
}
|
||||||
|
headers['Content-Type'] = mime.getType(getFileTypeByInfo(fileInfo));
|
||||||
|
|
||||||
ctx.logger.debug('wopi PutFile request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi PutFile request uri=%s headers=%j', uri, headers);
|
||||||
postRes = yield utils.postRequestPromise(ctx, uri, data, dataStream, dataSize, tenCallbackRequestTimeout, undefined, headers);
|
postRes = yield utils.postRequestPromise(ctx, uri, data, dataStream, dataSize, tenCallbackRequestTimeout, undefined, headers);
|
||||||
@ -633,9 +709,12 @@ function putRelativeFile(ctx, wopiSrc, access_token, data, dataStream, dataSize,
|
|||||||
return postRes;
|
return postRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
let headers = {'X-WOPI-Override': 'PUT_RELATIVE', 'X-WOPI-SuggestedTarget': utf7.encode(suggestedTarget),
|
let headers = {'X-WOPI-Override': 'PUT_RELATIVE', 'X-WOPI-SuggestedTarget': utf7.encode(suggestedTarget)};
|
||||||
'X-WOPI-FileConversion': isFileConversion};
|
if (isFileConversion) {
|
||||||
fillStandardHeaders(ctx, headers, uri, access_token);
|
headers['X-WOPI-FileConversion'] = isFileConversion;
|
||||||
|
}
|
||||||
|
yield fillStandardHeaders(ctx, headers, uri, access_token);
|
||||||
|
headers['Content-Type'] = mime.getType(suggestedTarget);
|
||||||
|
|
||||||
ctx.logger.debug('wopi putRelativeFile request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi putRelativeFile request uri=%s headers=%j', uri, headers);
|
||||||
postRes = yield utils.postRequestPromise(ctx, uri, data, dataStream, dataSize, tenCallbackRequestTimeout, undefined, headers);
|
postRes = yield utils.postRequestPromise(ctx, uri, data, dataStream, dataSize, tenCallbackRequestTimeout, undefined, headers);
|
||||||
@ -673,7 +752,7 @@ function renameFile(ctx, wopiParams, name) {
|
|||||||
let commonInfo = wopiParams.commonInfo;
|
let commonInfo = wopiParams.commonInfo;
|
||||||
|
|
||||||
let headers = {'X-WOPI-Override': 'RENAME_FILE', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-RequestedName': utf7.encode(name)};
|
let headers = {'X-WOPI-Override': 'RENAME_FILE', 'X-WOPI-Lock': commonInfo.lockId, 'X-WOPI-RequestedName': utf7.encode(name)};
|
||||||
fillStandardHeaders(ctx, headers, uri, userAuth.access_token);
|
yield fillStandardHeaders(ctx, headers, uri, userAuth.access_token);
|
||||||
|
|
||||||
ctx.logger.debug('wopi RenameFile request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi RenameFile request uri=%s headers=%j', uri, headers);
|
||||||
let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers);
|
let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers);
|
||||||
@ -711,9 +790,10 @@ function checkFileInfo(ctx, wopiSrc, access_token, opt_sc) {
|
|||||||
if (opt_sc) {
|
if (opt_sc) {
|
||||||
headers['X-WOPI-SessionContext'] = opt_sc;
|
headers['X-WOPI-SessionContext'] = opt_sc;
|
||||||
}
|
}
|
||||||
fillStandardHeaders(ctx, headers, uri, access_token);
|
yield fillStandardHeaders(ctx, headers, uri, access_token);
|
||||||
ctx.logger.debug('wopi checkFileInfo request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi checkFileInfo request uri=%s headers=%j', uri, headers);
|
||||||
//todo false?
|
//todo false? (true because it passed checkIpFilter for wopi)
|
||||||
|
//todo use directIfIn
|
||||||
let isInJwtToken = true;
|
let isInJwtToken = true;
|
||||||
let getRes = yield utils.downloadUrlPromise(ctx, uri, tenDownloadTimeout, undefined, undefined, isInJwtToken, headers);
|
let getRes = yield utils.downloadUrlPromise(ctx, uri, tenDownloadTimeout, undefined, undefined, isInJwtToken, headers);
|
||||||
ctx.logger.debug(`wopi checkFileInfo headers=%j body=%s`, getRes.response.headers, getRes.body);
|
ctx.logger.debug(`wopi checkFileInfo headers=%j body=%s`, getRes.response.headers, getRes.body);
|
||||||
@ -746,7 +826,7 @@ function lock(ctx, command, lockId, fileInfo, userAuth) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let headers = {"X-WOPI-Override": command, "X-WOPI-Lock": lockId};
|
let headers = {"X-WOPI-Override": command, "X-WOPI-Lock": lockId};
|
||||||
fillStandardHeaders(ctx, headers, uri, access_token);
|
yield fillStandardHeaders(ctx, headers, uri, access_token);
|
||||||
ctx.logger.debug('wopi %s request uri=%s headers=%j', command, uri, headers);
|
ctx.logger.debug('wopi %s request uri=%s headers=%j', command, uri, headers);
|
||||||
let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers);
|
let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers);
|
||||||
ctx.logger.debug('wopi %s response headers=%j', command, postRes.response.headers);
|
ctx.logger.debug('wopi %s response headers=%j', command, postRes.response.headers);
|
||||||
@ -783,7 +863,7 @@ function unlock(ctx, wopiParams) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let headers = {"X-WOPI-Override": "UNLOCK", "X-WOPI-Lock": lockId};
|
let headers = {"X-WOPI-Override": "UNLOCK", "X-WOPI-Lock": lockId};
|
||||||
fillStandardHeaders(ctx, headers, uri, access_token);
|
yield fillStandardHeaders(ctx, headers, uri, access_token);
|
||||||
ctx.logger.debug('wopi Unlock request uri=%s headers=%j', uri, headers);
|
ctx.logger.debug('wopi Unlock request uri=%s headers=%j', uri, headers);
|
||||||
let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers);
|
let postRes = yield utils.postRequestPromise(ctx, uri, undefined, undefined, undefined, tenCallbackRequestTimeout, undefined, headers);
|
||||||
ctx.logger.debug('wopi Unlock response headers=%j', postRes.response.headers);
|
ctx.logger.debug('wopi Unlock response headers=%j', postRes.response.headers);
|
||||||
@ -816,28 +896,32 @@ function generateProofBuffer(url, accessToken, timeStamp) {
|
|||||||
buffer.writeBigUInt64BE(timeStamp, offset);
|
buffer.writeBigUInt64BE(timeStamp, offset);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
function generateProofSign(url, accessToken, timeStamp, privateKey) {
|
|
||||||
let signer = crypto.createSign('RSA-SHA256');
|
async function generateProofSign(url, accessToken, timeStamp, privateKey) {
|
||||||
signer.update(generateProofBuffer(url, accessToken, timeStamp));
|
let data = generateProofBuffer(url, accessToken, timeStamp);
|
||||||
return signer.sign({key:privateKey}, "base64");
|
let sign = await cryptoSign('RSA-SHA256', data, privateKey);
|
||||||
|
return sign.toString('base64');
|
||||||
}
|
}
|
||||||
function generateProof(ctx, url, accessToken, timeStamp) {
|
|
||||||
const tenWopiPrivateKey = ctx.getCfg('wopi.privateKey', cfgWopiPrivateKey);
|
function numberToBase64(val) {
|
||||||
let privateKey = `-----BEGIN RSA PRIVATE KEY-----\n${tenWopiPrivateKey}\n-----END RSA PRIVATE KEY-----`;
|
// Convert to hexadecimal
|
||||||
return generateProofSign(url, accessToken, timeStamp, privateKey);
|
let hexString = val.toString(16);
|
||||||
|
//Ensure the hexadecimal string has an even length
|
||||||
|
if (hexString.length % 2 !== 0) {
|
||||||
|
hexString = '0' + hexString;
|
||||||
|
}
|
||||||
|
//Convert the hexadecimal string to a buffer
|
||||||
|
const buffer = Buffer.from(hexString, 'hex');
|
||||||
|
return buffer.toString('base64');
|
||||||
}
|
}
|
||||||
function generateProofOld(ctx, url, accessToken, timeStamp) {
|
|
||||||
const tenWopiPrivateKeyOld = ctx.getCfg('wopi.privateKeyOld', cfgWopiPrivateKeyOld);
|
async function fillStandardHeaders(ctx, headers, url, access_token) {
|
||||||
let privateKey = `-----BEGIN RSA PRIVATE KEY-----\n${tenWopiPrivateKeyOld}\n-----END RSA PRIVATE KEY-----`;
|
|
||||||
return generateProofSign(url, accessToken, timeStamp, privateKey);
|
|
||||||
}
|
|
||||||
function fillStandardHeaders(ctx, headers, url, access_token) {
|
|
||||||
let timeStamp = utils.getDateTimeTicks(new Date());
|
let timeStamp = utils.getDateTimeTicks(new Date());
|
||||||
const tenWopiPrivateKey = ctx.getCfg('wopi.privateKey', cfgWopiPrivateKey);
|
const tenWopiPrivateKey = ctx.getCfg('wopi.privateKey', cfgWopiPrivateKey);
|
||||||
const tenWopiPrivateKeyOld = ctx.getCfg('wopi.privateKeyOld', cfgWopiPrivateKeyOld);
|
const tenWopiPrivateKeyOld = ctx.getCfg('wopi.privateKeyOld', cfgWopiPrivateKeyOld);
|
||||||
if (tenWopiPrivateKey && tenWopiPrivateKeyOld) {
|
if (tenWopiPrivateKey && tenWopiPrivateKeyOld) {
|
||||||
headers['X-WOPI-Proof'] = generateProof(ctx, url, access_token, timeStamp);
|
headers['X-WOPI-Proof'] = await generateProofSign(url, access_token, timeStamp, Buffer.from(tenWopiPrivateKey, 'base64'));
|
||||||
headers['X-WOPI-ProofOld'] = generateProofOld(ctx, url, access_token, timeStamp);
|
headers['X-WOPI-ProofOld'] = await generateProofSign(url, access_token, timeStamp, Buffer.from(tenWopiPrivateKeyOld, 'base64'));
|
||||||
headers['X-WOPI-TimeStamp'] = timeStamp;
|
headers['X-WOPI-TimeStamp'] = timeStamp;
|
||||||
headers['X-WOPI-ClientVersion'] = commonDefines.buildVersion + '.' + commonDefines.buildNumber;
|
headers['X-WOPI-ClientVersion'] = commonDefines.buildVersion + '.' + commonDefines.buildNumber;
|
||||||
// todo
|
// todo
|
||||||
@ -923,7 +1007,12 @@ async function dummyGetFile(req, res) {
|
|||||||
res,
|
res,
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.logger.error('dummyGetFile error:%s', err.stack);
|
if (err.code === "ERR_STREAM_PREMATURE_CLOSE") {
|
||||||
|
//xhr.abort case
|
||||||
|
ctx.logger.debug('dummyGetFile error: %s', err.stack);
|
||||||
|
} else {
|
||||||
|
ctx.logger.error('dummyGetFile error:%s', err.stack);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (!res.headersSent) {
|
if (!res.headersSent) {
|
||||||
res.sendStatus(400);
|
res.sendStatus(400);
|
||||||
@ -934,6 +1023,7 @@ function dummyOk(req, res) {
|
|||||||
res.sendStatus(200);
|
res.sendStatus(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.checkIpFilter = checkIpFilter;
|
||||||
exports.discovery = discovery;
|
exports.discovery = discovery;
|
||||||
exports.collaboraCapabilities = collaboraCapabilities;
|
exports.collaboraCapabilities = collaboraCapabilities;
|
||||||
exports.parseWopiCallback = parseWopiCallback;
|
exports.parseWopiCallback = parseWopiCallback;
|
||||||
@ -944,12 +1034,13 @@ exports.putRelativeFile = putRelativeFile;
|
|||||||
exports.renameFile = renameFile;
|
exports.renameFile = renameFile;
|
||||||
exports.lock = lock;
|
exports.lock = lock;
|
||||||
exports.unlock = unlock;
|
exports.unlock = unlock;
|
||||||
exports.generateProof = generateProof;
|
|
||||||
exports.generateProofOld = generateProofOld;
|
|
||||||
exports.fillStandardHeaders = fillStandardHeaders;
|
exports.fillStandardHeaders = fillStandardHeaders;
|
||||||
exports.getWopiUnlockMarker = getWopiUnlockMarker;
|
exports.getWopiUnlockMarker = getWopiUnlockMarker;
|
||||||
exports.getWopiModifiedMarker = getWopiModifiedMarker;
|
exports.getWopiModifiedMarker = getWopiModifiedMarker;
|
||||||
exports.getFileTypeByInfo = getFileTypeByInfo;
|
exports.getFileTypeByInfo = getFileTypeByInfo;
|
||||||
|
exports.getWopiFileUrl = getWopiFileUrl;
|
||||||
|
exports.isWopiJwtToken = isWopiJwtToken;
|
||||||
|
exports.setIsShutdown = setIsShutdown;
|
||||||
exports.dummyCheckFileInfo = dummyCheckFileInfo;
|
exports.dummyCheckFileInfo = dummyCheckFileInfo;
|
||||||
exports.dummyGetFile = dummyGetFile;
|
exports.dummyGetFile = dummyGetFile;
|
||||||
exports.dummyOk = dummyOk;
|
exports.dummyOk = dummyOk;
|
||||||
|
|||||||
@ -123,7 +123,7 @@ function TaskQueueDataConvert(ctx, task) {
|
|||||||
this.mailMergeSend = cmd.mailmergesend;
|
this.mailMergeSend = cmd.mailmergesend;
|
||||||
this.thumbnail = cmd.thumbnail;
|
this.thumbnail = cmd.thumbnail;
|
||||||
this.textParams = cmd.getTextParams();
|
this.textParams = cmd.getTextParams();
|
||||||
this.jsonParams = cmd.getJsonParams();
|
this.jsonParams = JSON.stringify(cmd.getJsonParams());
|
||||||
this.lcid = cmd.getLCID();
|
this.lcid = cmd.getLCID();
|
||||||
this.password = cmd.getPassword();
|
this.password = cmd.getPassword();
|
||||||
this.savePassword = cmd.getSavePassword();
|
this.savePassword = cmd.getSavePassword();
|
||||||
@ -341,13 +341,15 @@ function* isUselessConvertion(ctx, task, cmd) {
|
|||||||
return constants.NO_ERROR;
|
return constants.NO_ERROR;
|
||||||
}
|
}
|
||||||
async function changeFormatToExtendedPdf(ctx, dataConvert, cmd) {
|
async function changeFormatToExtendedPdf(ctx, dataConvert, cmd) {
|
||||||
|
let forceSave = cmd.getForceSave();
|
||||||
|
let isSendForm = forceSave && forceSave.getType() === commonDefines.c_oAscForceSaveTypes.Form;
|
||||||
let originFormat = cmd.getOriginFormat();
|
let originFormat = cmd.getOriginFormat();
|
||||||
let isOriginFormatWithForms = constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === originFormat ||
|
let isOriginFormatWithForms = constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === originFormat ||
|
||||||
constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_OFORM === originFormat ||
|
constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_OFORM === originFormat ||
|
||||||
constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCXF === originFormat;
|
constants.AVS_OFFICESTUDIO_FILE_DOCUMENT_DOCXF === originFormat;
|
||||||
let isFormatToPdf = constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === dataConvert.formatTo ||
|
let isFormatToPdf = constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDF === dataConvert.formatTo ||
|
||||||
constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA === dataConvert.formatTo;
|
constants.AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA === dataConvert.formatTo;
|
||||||
if (isFormatToPdf && isOriginFormatWithForms) {
|
if (isFormatToPdf && isOriginFormatWithForms && !isSendForm) {
|
||||||
let format = await formatChecker.getDocumentFormatByFile(dataConvert.fileFrom);
|
let format = await formatChecker.getDocumentFormatByFile(dataConvert.fileFrom);
|
||||||
if (constants.AVS_OFFICESTUDIO_FILE_CANVAS_WORD === format) {
|
if (constants.AVS_OFFICESTUDIO_FILE_CANVAS_WORD === format) {
|
||||||
ctx.logger.debug('change format to extended pdf');
|
ctx.logger.debug('change format to extended pdf');
|
||||||
@ -358,7 +360,7 @@ async function changeFormatToExtendedPdf(ctx, dataConvert, cmd) {
|
|||||||
function* replaceEmptyFile(ctx, fileFrom, ext, _lcid) {
|
function* replaceEmptyFile(ctx, fileFrom, ext, _lcid) {
|
||||||
const tenNewFileTemplate = ctx.getCfg('services.CoAuthoring.server.newFileTemplate', cfgNewFileTemplate);
|
const tenNewFileTemplate = ctx.getCfg('services.CoAuthoring.server.newFileTemplate', cfgNewFileTemplate);
|
||||||
if (!fs.existsSync(fileFrom) || 0 === fs.lstatSync(fileFrom).size) {
|
if (!fs.existsSync(fileFrom) || 0 === fs.lstatSync(fileFrom).size) {
|
||||||
let locale = 'en-US';
|
let locale = constants.TEMPLATES_DEFAULT_LOCALE;
|
||||||
if (_lcid) {
|
if (_lcid) {
|
||||||
let localeNew = lcid.from(_lcid);
|
let localeNew = lcid.from(_lcid);
|
||||||
if (localeNew) {
|
if (localeNew) {
|
||||||
@ -370,14 +372,24 @@ function* replaceEmptyFile(ctx, fileFrom, ext, _lcid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.logger.debug('replaceEmptyFile format=%s locale=%s', ext, locale);
|
let fileTemplatePath = path.join(tenNewFileTemplate, locale, 'new.');
|
||||||
let format = formatChecker.getFormatFromString(ext);
|
if (fs.existsSync(fileTemplatePath + ext)) {
|
||||||
if (formatChecker.isDocumentFormat(format)) {
|
ctx.logger.debug('replaceEmptyFile format=%s locale=%s', ext, locale);
|
||||||
fs.copyFileSync(path.join(tenNewFileTemplate, locale, 'new.docx'), fileFrom);
|
fs.copyFileSync(fileTemplatePath + ext, fileFrom);
|
||||||
} else if (formatChecker.isSpreadsheetFormat(format)) {
|
} else {
|
||||||
fs.copyFileSync(path.join(tenNewFileTemplate, locale, 'new.xlsx'), fileFrom);
|
let format = formatChecker.getFormatFromString(ext);
|
||||||
} else if (formatChecker.isPresentationFormat(format)) {
|
let editorFormat;
|
||||||
fs.copyFileSync(path.join(tenNewFileTemplate, locale, 'new.pptx'), fileFrom);
|
if (formatChecker.isDocumentFormat(format)) {
|
||||||
|
editorFormat = 'docx';
|
||||||
|
} else if (formatChecker.isSpreadsheetFormat(format)) {
|
||||||
|
editorFormat = 'xlsx';
|
||||||
|
} else if (formatChecker.isPresentationFormat(format)) {
|
||||||
|
editorFormat = 'pptx';
|
||||||
|
}
|
||||||
|
if (fs.existsSync(fileTemplatePath + editorFormat)) {
|
||||||
|
ctx.logger.debug('replaceEmptyFile format=%s locale=%s', ext, locale);
|
||||||
|
fs.copyFileSync(fileTemplatePath + editorFormat, fileFrom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,7 +441,6 @@ function* downloadFile(ctx, uri, fileFrom, withAuthorization, isInJwtToken, opt_
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
function* downloadFileFromStorage(ctx, strPath, dir, opt_specialDir) {
|
function* downloadFileFromStorage(ctx, strPath, dir, opt_specialDir) {
|
||||||
const tenMaxDownloadBytes = ctx.getCfg('FileConverter.converter.maxDownloadBytes', cfgMaxDownloadBytes);
|
|
||||||
var list = yield storage.listObjects(ctx, strPath, opt_specialDir);
|
var list = yield storage.listObjects(ctx, strPath, opt_specialDir);
|
||||||
ctx.logger.debug('downloadFileFromStorage list %s', list.toString());
|
ctx.logger.debug('downloadFileFromStorage list %s', list.toString());
|
||||||
//create dirs
|
//create dirs
|
||||||
@ -1002,7 +1013,6 @@ function* spawnProcess(ctx, builderParams, tempDirs, dataConvert, authorProps, g
|
|||||||
}
|
}
|
||||||
|
|
||||||
function* ExecuteTask(ctx, task) {
|
function* ExecuteTask(ctx, task) {
|
||||||
const tenMaxDownloadBytes = ctx.getCfg('FileConverter.converter.maxDownloadBytes', cfgMaxDownloadBytes);
|
|
||||||
const tenForgottenFiles = ctx.getCfg('services.CoAuthoring.server.forgottenfiles', cfgForgottenFiles);
|
const tenForgottenFiles = ctx.getCfg('services.CoAuthoring.server.forgottenfiles', cfgForgottenFiles);
|
||||||
const tenForgottenFilesName = ctx.getCfg('services.CoAuthoring.server.forgottenfilesname', cfgForgottenFilesName);
|
const tenForgottenFilesName = ctx.getCfg('services.CoAuthoring.server.forgottenfilesname', cfgForgottenFilesName);
|
||||||
var startDate = null;
|
var startDate = null;
|
||||||
@ -1039,19 +1049,8 @@ function* ExecuteTask(ctx, task) {
|
|||||||
withAuthorization = false;
|
withAuthorization = false;
|
||||||
isInJwtToken = true;
|
isInJwtToken = true;
|
||||||
let fileInfo = wopiParams.commonInfo?.fileInfo;
|
let fileInfo = wopiParams.commonInfo?.fileInfo;
|
||||||
let userAuth = wopiParams.userAuth;
|
|
||||||
fileSize = fileInfo?.Size;
|
fileSize = fileInfo?.Size;
|
||||||
if (fileInfo?.FileUrl) {
|
({url, headers} = yield wopiClient.getWopiFileUrl(ctx, fileInfo, wopiParams.userAuth));
|
||||||
//Requests to the FileUrl can not be signed using proof keys. The FileUrl is used exactly as provided by the host, so it does not necessarily include the access token, which is required to construct the expected proof.
|
|
||||||
url = fileInfo.FileUrl;
|
|
||||||
} else if (fileInfo?.TemplateSource) {
|
|
||||||
url = fileInfo.TemplateSource;
|
|
||||||
} else if (userAuth) {
|
|
||||||
url = `${userAuth.wopiSrc}/contents?access_token=${userAuth.access_token}`;
|
|
||||||
headers = {'X-WOPI-MaxExpectedSize': tenMaxDownloadBytes};
|
|
||||||
wopiClient.fillStandardHeaders(ctx, headers, url, userAuth.access_token);
|
|
||||||
}
|
|
||||||
ctx.logger.debug('wopi url=%s; headers=%j', url, headers);
|
|
||||||
}
|
}
|
||||||
if (undefined === fileSize || fileSize > 0) {
|
if (undefined === fileSize || fileSize > 0) {
|
||||||
error = yield* downloadFile(ctx, url, dataConvert.fileFrom, withAuthorization, isInJwtToken, headers);
|
error = yield* downloadFile(ctx, url, dataConvert.fileFrom, withAuthorization, isInJwtToken, headers);
|
||||||
|
|||||||
465
SpellChecker/npm-shrinkwrap.json
generated
465
SpellChecker/npm-shrinkwrap.json
generated
@ -5,40 +5,54 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"accepts": {
|
"accepts": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||||
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
|
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-types": "~2.1.18",
|
"mime-types": "~2.1.34",
|
||||||
"negotiator": "0.6.1"
|
"negotiator": "0.6.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"array-flatten": {
|
"array-flatten": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
||||||
},
|
},
|
||||||
"body-parser": {
|
"body-parser": {
|
||||||
"version": "1.18.3",
|
"version": "1.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
|
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
||||||
"integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
|
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bytes": "3.0.0",
|
"bytes": "3.1.2",
|
||||||
"content-type": "~1.0.4",
|
"content-type": "~1.0.5",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "~1.1.2",
|
"depd": "2.0.0",
|
||||||
"http-errors": "~1.6.3",
|
"destroy": "1.2.0",
|
||||||
"iconv-lite": "0.4.23",
|
"http-errors": "2.0.0",
|
||||||
"on-finished": "~2.3.0",
|
"iconv-lite": "0.4.24",
|
||||||
"qs": "6.5.2",
|
"on-finished": "2.4.1",
|
||||||
"raw-body": "2.3.3",
|
"qs": "6.11.0",
|
||||||
"type-is": "~1.6.16"
|
"raw-body": "2.5.2",
|
||||||
|
"type-is": "~1.6.18",
|
||||||
|
"unpipe": "1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bytes": {
|
"bytes": {
|
||||||
"version": "3.0.0",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||||
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
|
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
|
||||||
|
},
|
||||||
|
"call-bind": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
||||||
|
"requires": {
|
||||||
|
"es-define-property": "^1.0.0",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-intrinsic": "^1.2.4",
|
||||||
|
"set-function-length": "^1.2.1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"co": {
|
"co": {
|
||||||
"version": "4.6.0",
|
"version": "4.6.0",
|
||||||
@ -54,24 +68,34 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"content-disposition": {
|
"content-disposition": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||||
"integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
|
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "5.2.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"content-type": {
|
"content-type": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
|
||||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
|
||||||
},
|
},
|
||||||
"cookie": {
|
"cookie": {
|
||||||
"version": "0.3.1",
|
"version": "0.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||||
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
|
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="
|
||||||
},
|
},
|
||||||
"cookie-signature": {
|
"cookie-signature": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
@ -81,71 +105,102 @@
|
|||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"define-data-property": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||||
|
"requires": {
|
||||||
|
"es-define-property": "^1.0.0",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"depd": {
|
"depd": {
|
||||||
"version": "1.1.2",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||||
},
|
},
|
||||||
"destroy": {
|
"destroy": {
|
||||||
"version": "1.0.4",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
|
||||||
},
|
},
|
||||||
"ee-first": {
|
"ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||||
},
|
},
|
||||||
"encodeurl": {
|
"encodeurl": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
|
||||||
|
},
|
||||||
|
"es-define-property": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||||
|
"requires": {
|
||||||
|
"get-intrinsic": "^1.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"es-errors": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
|
||||||
},
|
},
|
||||||
"escape-html": {
|
"escape-html": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
||||||
},
|
},
|
||||||
"etag": {
|
"etag": {
|
||||||
"version": "1.8.1",
|
"version": "1.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
|
||||||
},
|
},
|
||||||
"express": {
|
"express": {
|
||||||
"version": "4.16.4",
|
"version": "4.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
|
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
||||||
"integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
|
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"accepts": "~1.3.5",
|
"accepts": "~1.3.8",
|
||||||
"array-flatten": "1.1.1",
|
"array-flatten": "1.1.1",
|
||||||
"body-parser": "1.18.3",
|
"body-parser": "1.20.2",
|
||||||
"content-disposition": "0.5.2",
|
"content-disposition": "0.5.4",
|
||||||
"content-type": "~1.0.4",
|
"content-type": "~1.0.4",
|
||||||
"cookie": "0.3.1",
|
"cookie": "0.6.0",
|
||||||
"cookie-signature": "1.0.6",
|
"cookie-signature": "1.0.6",
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "~1.1.2",
|
"depd": "2.0.0",
|
||||||
"encodeurl": "~1.0.2",
|
"encodeurl": "~1.0.2",
|
||||||
"escape-html": "~1.0.3",
|
"escape-html": "~1.0.3",
|
||||||
"etag": "~1.8.1",
|
"etag": "~1.8.1",
|
||||||
"finalhandler": "1.1.1",
|
"finalhandler": "1.2.0",
|
||||||
"fresh": "0.5.2",
|
"fresh": "0.5.2",
|
||||||
|
"http-errors": "2.0.0",
|
||||||
"merge-descriptors": "1.0.1",
|
"merge-descriptors": "1.0.1",
|
||||||
"methods": "~1.1.2",
|
"methods": "~1.1.2",
|
||||||
"on-finished": "~2.3.0",
|
"on-finished": "2.4.1",
|
||||||
"parseurl": "~1.3.2",
|
"parseurl": "~1.3.3",
|
||||||
"path-to-regexp": "0.1.7",
|
"path-to-regexp": "0.1.7",
|
||||||
"proxy-addr": "~2.0.4",
|
"proxy-addr": "~2.0.7",
|
||||||
"qs": "6.5.2",
|
"qs": "6.11.0",
|
||||||
"range-parser": "~1.2.0",
|
"range-parser": "~1.2.1",
|
||||||
"safe-buffer": "5.1.2",
|
"safe-buffer": "5.2.1",
|
||||||
"send": "0.16.2",
|
"send": "0.18.0",
|
||||||
"serve-static": "1.13.2",
|
"serve-static": "1.15.0",
|
||||||
"setprototypeof": "1.1.0",
|
"setprototypeof": "1.2.0",
|
||||||
"statuses": "~1.4.0",
|
"statuses": "2.0.1",
|
||||||
"type-is": "~1.6.16",
|
"type-is": "~1.6.18",
|
||||||
"utils-merge": "1.0.1",
|
"utils-merge": "1.0.1",
|
||||||
"vary": "~1.1.2"
|
"vary": "~1.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"faye-websocket": {
|
"faye-websocket": {
|
||||||
@ -157,38 +212,90 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"finalhandler": {
|
"finalhandler": {
|
||||||
"version": "1.1.1",
|
"version": "1.2.0",
|
||||||
"resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
|
"resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||||
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
|
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"encodeurl": "~1.0.2",
|
"encodeurl": "~1.0.2",
|
||||||
"escape-html": "~1.0.3",
|
"escape-html": "~1.0.3",
|
||||||
"on-finished": "~2.3.0",
|
"on-finished": "2.4.1",
|
||||||
"parseurl": "~1.3.2",
|
"parseurl": "~1.3.3",
|
||||||
"statuses": "~1.4.0",
|
"statuses": "2.0.1",
|
||||||
"unpipe": "~1.0.0"
|
"unpipe": "~1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"forwarded": {
|
"forwarded": {
|
||||||
"version": "0.1.2",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||||
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
|
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
|
||||||
},
|
},
|
||||||
"fresh": {
|
"fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
|
||||||
|
},
|
||||||
|
"function-bind": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
|
||||||
|
},
|
||||||
|
"get-intrinsic": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||||
|
"requires": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"has-proto": "^1.0.1",
|
||||||
|
"has-symbols": "^1.0.3",
|
||||||
|
"hasown": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gopd": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||||
|
"requires": {
|
||||||
|
"get-intrinsic": "^1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has-property-descriptors": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||||
|
"requires": {
|
||||||
|
"es-define-property": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has-proto": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q=="
|
||||||
|
},
|
||||||
|
"has-symbols": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
|
||||||
|
},
|
||||||
|
"hasown": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"http-errors": {
|
"http-errors": {
|
||||||
"version": "1.6.3",
|
"version": "2.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
"resolved": "http://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
|
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"depd": "~1.1.2",
|
"depd": "2.0.0",
|
||||||
"inherits": "2.0.3",
|
"inherits": "2.0.4",
|
||||||
"setprototypeof": "1.1.0",
|
"setprototypeof": "1.2.0",
|
||||||
"statuses": ">= 1.4.0 < 2"
|
"statuses": "2.0.1",
|
||||||
|
"toidentifier": "1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"http-parser-js": {
|
"http-parser-js": {
|
||||||
@ -197,22 +304,22 @@
|
|||||||
"integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg=="
|
"integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg=="
|
||||||
},
|
},
|
||||||
"iconv-lite": {
|
"iconv-lite": {
|
||||||
"version": "0.4.23",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
|
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"safer-buffer": ">= 2.1.2 < 3"
|
"safer-buffer": ">= 2.1.2 < 3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
},
|
},
|
||||||
"ipaddr.js": {
|
"ipaddr.js": {
|
||||||
"version": "1.8.0",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||||
"integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
|
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||||
},
|
},
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -225,34 +332,34 @@
|
|||||||
"media-typer": {
|
"media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
|
||||||
},
|
},
|
||||||
"merge-descriptors": {
|
"merge-descriptors": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
|
||||||
},
|
},
|
||||||
"methods": {
|
"methods": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
|
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
|
||||||
},
|
},
|
||||||
"mime": {
|
"mime": {
|
||||||
"version": "1.4.1",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||||
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
|
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||||
},
|
},
|
||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.37.0",
|
"version": "1.52.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.21",
|
"version": "2.1.35",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-db": "~1.37.0"
|
"mime-db": "1.52.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
@ -263,12 +370,12 @@
|
|||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
},
|
},
|
||||||
"negotiator": {
|
"negotiator": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||||
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
|
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
|
||||||
},
|
},
|
||||||
"node-addon-api": {
|
"node-addon-api": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
@ -282,51 +389,59 @@
|
|||||||
"node-addon-api": "*"
|
"node-addon-api": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"object-inspect": {
|
||||||
|
"version": "1.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||||
|
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ=="
|
||||||
|
},
|
||||||
"on-finished": {
|
"on-finished": {
|
||||||
"version": "2.3.0",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ee-first": "1.1.1"
|
"ee-first": "1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"parseurl": {
|
"parseurl": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||||
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
|
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||||
},
|
},
|
||||||
"path-to-regexp": {
|
"path-to-regexp": {
|
||||||
"version": "0.1.7",
|
"version": "0.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
|
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
||||||
},
|
},
|
||||||
"proxy-addr": {
|
"proxy-addr": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||||
"integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
|
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"forwarded": "~0.1.2",
|
"forwarded": "0.2.0",
|
||||||
"ipaddr.js": "1.8.0"
|
"ipaddr.js": "1.9.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"qs": {
|
"qs": {
|
||||||
"version": "6.5.2",
|
"version": "6.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||||
|
"requires": {
|
||||||
|
"side-channel": "^1.0.4"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"range-parser": {
|
"range-parser": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||||
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
|
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
|
||||||
},
|
},
|
||||||
"raw-body": {
|
"raw-body": {
|
||||||
"version": "2.3.3",
|
"version": "2.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||||
"integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
|
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"bytes": "3.0.0",
|
"bytes": "3.1.2",
|
||||||
"http-errors": "1.6.3",
|
"http-errors": "2.0.0",
|
||||||
"iconv-lite": "0.4.23",
|
"iconv-lite": "0.4.24",
|
||||||
"unpipe": "1.0.0"
|
"unpipe": "1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -341,40 +456,71 @@
|
|||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
"send": {
|
"send": {
|
||||||
"version": "0.16.2",
|
"version": "0.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||||
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
|
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "2.6.9",
|
"debug": "2.6.9",
|
||||||
"depd": "~1.1.2",
|
"depd": "2.0.0",
|
||||||
"destroy": "~1.0.4",
|
"destroy": "1.2.0",
|
||||||
"encodeurl": "~1.0.2",
|
"encodeurl": "~1.0.2",
|
||||||
"escape-html": "~1.0.3",
|
"escape-html": "~1.0.3",
|
||||||
"etag": "~1.8.1",
|
"etag": "~1.8.1",
|
||||||
"fresh": "0.5.2",
|
"fresh": "0.5.2",
|
||||||
"http-errors": "~1.6.2",
|
"http-errors": "2.0.0",
|
||||||
"mime": "1.4.1",
|
"mime": "1.6.0",
|
||||||
"ms": "2.0.0",
|
"ms": "2.1.3",
|
||||||
"on-finished": "~2.3.0",
|
"on-finished": "2.4.1",
|
||||||
"range-parser": "~1.2.0",
|
"range-parser": "~1.2.1",
|
||||||
"statuses": "~1.4.0"
|
"statuses": "2.0.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"serve-static": {
|
"serve-static": {
|
||||||
"version": "1.13.2",
|
"version": "1.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
|
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
|
||||||
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
|
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"encodeurl": "~1.0.2",
|
"encodeurl": "~1.0.2",
|
||||||
"escape-html": "~1.0.3",
|
"escape-html": "~1.0.3",
|
||||||
"parseurl": "~1.3.2",
|
"parseurl": "~1.3.3",
|
||||||
"send": "0.16.2"
|
"send": "0.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"set-function-length": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||||
|
"requires": {
|
||||||
|
"define-data-property": "^1.1.4",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-intrinsic": "^1.2.4",
|
||||||
|
"gopd": "^1.0.1",
|
||||||
|
"has-property-descriptors": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"setprototypeof": {
|
"setprototypeof": {
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||||
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
|
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
||||||
|
},
|
||||||
|
"side-channel": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
|
||||||
|
"requires": {
|
||||||
|
"call-bind": "^1.0.7",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.4",
|
||||||
|
"object-inspect": "^1.13.1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"sockjs": {
|
"sockjs": {
|
||||||
"version": "0.3.21",
|
"version": "0.3.21",
|
||||||
@ -387,28 +533,33 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statuses": {
|
"statuses": {
|
||||||
"version": "1.4.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||||
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
|
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
|
||||||
|
},
|
||||||
|
"toidentifier": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
|
||||||
},
|
},
|
||||||
"type-is": {
|
"type-is": {
|
||||||
"version": "1.6.16",
|
"version": "1.6.18",
|
||||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
|
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||||
"integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
|
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"media-typer": "0.3.0",
|
"media-typer": "0.3.0",
|
||||||
"mime-types": "~2.1.18"
|
"mime-types": "~2.1.24"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"unpipe": {
|
"unpipe": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
|
||||||
},
|
},
|
||||||
"utils-merge": {
|
"utils-merge": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"version": "3.4.0",
|
"version": "3.4.0",
|
||||||
@ -418,7 +569,7 @@
|
|||||||
"vary": {
|
"vary": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
|
||||||
},
|
},
|
||||||
"websocket-driver": {
|
"websocket-driver": {
|
||||||
"version": "0.7.4",
|
"version": "0.7.4",
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"co": "4.6.0",
|
"co": "4.6.0",
|
||||||
"config": "2.0.1",
|
"config": "2.0.1",
|
||||||
"express": "4.16.4",
|
"express": "4.19.2",
|
||||||
"nodehun": "git+https://git@github.com/ONLYOFFICE/nodehun.git#2411a56828c7d58214c61781b4a5c63d18adba99",
|
"nodehun": "git+https://git@github.com/ONLYOFFICE/nodehun.git#2411a56828c7d58214c61781b4a5c63d18adba99",
|
||||||
"sockjs": "0.3.21"
|
"sockjs": "0.3.21"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -53,7 +53,8 @@ const utils = require('../../../Common/sources/utils');
|
|||||||
const commonDefines = require("../../../Common/sources/commondefines");
|
const commonDefines = require("../../../Common/sources/commondefines");
|
||||||
const config = require('../../../Common/node_modules/config');
|
const config = require('../../../Common/node_modules/config');
|
||||||
|
|
||||||
const cfgStorageName = config.get('storage.name');
|
const cfgCacheStorage = config.get('storage');
|
||||||
|
const cfgPersistentStorage = utils.deepMergeObjects({}, cfgCacheStorage, config.get('persistentStorage'));
|
||||||
|
|
||||||
const ctx = operationContext.global;
|
const ctx = operationContext.global;
|
||||||
const rand = Math.floor(Math.random() * 1000000);
|
const rand = Math.floor(Math.random() * 1000000);
|
||||||
@ -64,9 +65,15 @@ let testFile1 = testDir + "/test1.txt";
|
|||||||
let testFile2 = testDir + "/test2.txt";
|
let testFile2 = testDir + "/test2.txt";
|
||||||
let testFile3 = testDir + "/test3.txt";
|
let testFile3 = testDir + "/test3.txt";
|
||||||
let testFile4 = testDir + "/test4.txt";
|
let testFile4 = testDir + "/test4.txt";
|
||||||
|
let specialDirCache = "";
|
||||||
|
let specialDirForgotten = "forgotten";
|
||||||
|
|
||||||
console.debug(`testDir: ${testDir}`)
|
console.debug(`testDir: ${testDir}`)
|
||||||
|
|
||||||
|
function getStorageCfg(specialDir) {
|
||||||
|
return specialDir ? cfgPersistentStorage : cfgCacheStorage;
|
||||||
|
}
|
||||||
|
|
||||||
function request(url) {
|
function request(url) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
let module = url.startsWith('https') ? https : http;
|
let module = url.startsWith('https') ? https : http;
|
||||||
@ -97,7 +104,7 @@ function runTestForDir(specialDir) {
|
|||||||
let list = await storage.listObjects(ctx, testDir, specialDir);
|
let list = await storage.listObjects(ctx, testDir, specialDir);
|
||||||
expect(list.sort()).toEqual([testFile1, testFile2].sort());
|
expect(list.sort()).toEqual([testFile1, testFile2].sort());
|
||||||
});
|
});
|
||||||
if ("storage-fs" === cfgStorageName) {
|
if ("storage-fs" === getStorageCfg(specialDir).name) {
|
||||||
test("UploadObject", async () => {
|
test("UploadObject", async () => {
|
||||||
let res = await storage.uploadObject(ctx, testFile3, "createReadStream.txt", specialDir);
|
let res = await storage.uploadObject(ctx, testFile3, "createReadStream.txt", specialDir);
|
||||||
expect(res).toEqual(undefined);
|
expect(res).toEqual(undefined);
|
||||||
@ -113,6 +120,7 @@ function runTestForDir(specialDir) {
|
|||||||
let list = await storage.listObjects(ctx, testDir, specialDir);
|
let list = await storage.listObjects(ctx, testDir, specialDir);
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled();
|
||||||
expect(list.sort()).toEqual([testFile1, testFile2, testFile3].sort());
|
expect(list.sort()).toEqual([testFile1, testFile2, testFile3].sort());
|
||||||
|
spy.mockRestore();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
test("copyObject", async () => {
|
test("copyObject", async () => {
|
||||||
@ -172,7 +180,7 @@ function runTestForDir(specialDir) {
|
|||||||
expect(outputText.toString("utf8")).toEqual(testFileData3);
|
expect(outputText.toString("utf8")).toEqual(testFileData3);
|
||||||
});
|
});
|
||||||
test("getSignedUrl", async () => {
|
test("getSignedUrl", async () => {
|
||||||
let url, data;
|
let url, urls, data;
|
||||||
url = await storage.getSignedUrl(ctx, baseUrl, testFile1, urlType, undefined, undefined, specialDir);
|
url = await storage.getSignedUrl(ctx, baseUrl, testFile1, urlType, undefined, undefined, specialDir);
|
||||||
data = await request(url);
|
data = await request(url);
|
||||||
expect(data).toEqual(testFileData1);
|
expect(data).toEqual(testFileData1);
|
||||||
@ -189,6 +197,33 @@ function runTestForDir(specialDir) {
|
|||||||
data = await request(url);
|
data = await request(url);
|
||||||
expect(data).toEqual(testFileData4);
|
expect(data).toEqual(testFileData4);
|
||||||
});
|
});
|
||||||
|
test("getSignedUrls", async () => {
|
||||||
|
let urls, data;
|
||||||
|
urls = await storage.getSignedUrls(ctx, baseUrl, testDir, urlType, undefined, specialDir);
|
||||||
|
data = [];
|
||||||
|
for(let i in urls) {
|
||||||
|
data.push(await request(urls[i]));
|
||||||
|
}
|
||||||
|
expect(data.sort()).toEqual([testFileData1, testFileData2, testFileData3, testFileData4].sort());
|
||||||
|
});
|
||||||
|
test("getSignedUrlsArrayByArray", async () => {
|
||||||
|
let urls, data;
|
||||||
|
urls = await storage.getSignedUrlsArrayByArray(ctx, baseUrl, [testFile1, testFile2], urlType, specialDir);
|
||||||
|
data = [];
|
||||||
|
for(let i = 0; i < urls.length; ++i) {
|
||||||
|
data.push(await request(urls[i]));
|
||||||
|
}
|
||||||
|
expect(data.sort()).toEqual([testFileData1, testFileData2].sort());
|
||||||
|
});
|
||||||
|
test("getSignedUrlsByArray", async () => {
|
||||||
|
let urls, data;
|
||||||
|
urls = await storage.getSignedUrlsByArray(ctx, baseUrl, [testFile3, testFile4], undefined, urlType, specialDir);
|
||||||
|
data = [];
|
||||||
|
for(let i in urls) {
|
||||||
|
data.push(await request(urls[i]));
|
||||||
|
}
|
||||||
|
expect(data.sort()).toEqual([testFileData3, testFileData4].sort());
|
||||||
|
});
|
||||||
test("deleteObject", async () => {
|
test("deleteObject", async () => {
|
||||||
let list;
|
let list;
|
||||||
list = await storage.listObjects(ctx, testDir, specialDir);
|
list = await storage.listObjects(ctx, testDir, specialDir);
|
||||||
@ -215,9 +250,57 @@ function runTestForDir(specialDir) {
|
|||||||
|
|
||||||
// Assumed, that server is already up.
|
// Assumed, that server is already up.
|
||||||
describe('storage common dir', function () {
|
describe('storage common dir', function () {
|
||||||
runTestForDir("");
|
runTestForDir(specialDirCache);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('storage forgotten dir', function () {
|
describe('storage forgotten dir', function () {
|
||||||
runTestForDir("forgotten");
|
runTestForDir(specialDirForgotten);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('storage mix common and forgotten dir', function () {
|
||||||
|
test("putObject", async () => {
|
||||||
|
let buffer = Buffer.from(testFileData1);
|
||||||
|
let res = await storage.putObject(ctx, testFile1, buffer, buffer.length, specialDirCache);
|
||||||
|
expect(res).toEqual(undefined);
|
||||||
|
let list = await storage.listObjects(ctx, testDir, specialDirCache);
|
||||||
|
expect(list.sort()).toEqual([testFile1].sort());
|
||||||
|
|
||||||
|
buffer = Buffer.from(testFileData2);
|
||||||
|
res = await storage.putObject(ctx, testFile2, buffer, buffer.length, specialDirForgotten);
|
||||||
|
expect(res).toEqual(undefined);
|
||||||
|
list = await storage.listObjects(ctx, testDir, specialDirForgotten);
|
||||||
|
expect(list.sort()).toEqual([testFile2].sort());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("copyPath", async () => {
|
||||||
|
let list, res;
|
||||||
|
res = await storage.copyPath(ctx, testDir, testDir, specialDirCache, specialDirForgotten);
|
||||||
|
expect(res).toEqual(undefined);
|
||||||
|
|
||||||
|
list = await storage.listObjects(ctx, testDir, specialDirForgotten);
|
||||||
|
expect(list.sort()).toEqual([testFile1, testFile2].sort());
|
||||||
|
});
|
||||||
|
test("copyObject", async () => {
|
||||||
|
let list, res;
|
||||||
|
res = await storage.copyObject(ctx, testFile2, testFile2, specialDirForgotten, specialDirCache);
|
||||||
|
expect(res).toEqual(undefined);
|
||||||
|
|
||||||
|
list = await storage.listObjects(ctx, testDir, specialDirCache);
|
||||||
|
expect(list.sort()).toEqual([testFile1, testFile2].sort());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("deletePath", async () => {
|
||||||
|
let list, res;
|
||||||
|
res = await storage.deletePath(ctx, testDir, specialDirCache);
|
||||||
|
expect(res).toEqual(undefined);
|
||||||
|
|
||||||
|
list = await storage.listObjects(ctx, testDir, specialDirCache);
|
||||||
|
expect(list.sort()).toEqual([].sort());
|
||||||
|
|
||||||
|
res = await storage.deletePath(ctx, testDir, specialDirForgotten);
|
||||||
|
expect(res).toEqual(undefined);
|
||||||
|
|
||||||
|
list = await storage.listObjects(ctx, testDir, specialDirForgotten);
|
||||||
|
expect(list.sort()).toEqual([].sort());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user