Compare commits

..

1 Commits

Author SHA1 Message Date
b6a033b68e build(python): update version to 1.15 in pyproject.toml 2026-03-11 17:40:27 +07:00
15 changed files with 135 additions and 232 deletions

View File

@ -15,10 +15,6 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: '1.23'
- name: Submodule Update
run: |
cd ${{ github.workspace }}

View File

@ -29,6 +29,7 @@ const config = require('config');
const mime = require('mime');
const urllib = require('urllib');
const urlModule = require('url');
const { emitWarning } = require('process');
const DocManager = require('./helpers/docManager');
const documentService = require('./helpers/documentService');
const fileUtility = require('./helpers/fileUtility');
@ -720,38 +721,12 @@ app.put('/restore', async (req, res) => { // define a handler for restore file v
res.end();
});
app.post('/forcesave', async (req, res) => {
req.DocManager = new DocManager(req, res);
const uAddress = req.query.useraddress;
const fName = fileUtility.getFileName(req.query.filename);
if (req.headers['content-type'] === 'application/octet-stream') {
const form = new formidable.IncomingForm();
form.parse(req, async (err, fields, files) => {
if (err) {
res.write('{"error":1, "message":"document data is empty"}');
res.end();
return;
}
const filePath = files.file.filepath || files.file[0].filepath;
const data = fileSystem.readFileSync(filePath);
await req.DocManager.forcesaveFile(data, fName, fileUtility.getFileExtension(fName), uAddress);
fileSystem.unlinkSync(filePath);
res.write('{"error":0}');
res.end();
});
} else {
res.write('{"error":0}');
res.end();
}
});
app.post('/track', async (req, res) => { // define a handler for tracking file changes
req.DocManager = new DocManager(req, res);
let uAddress = req.query.useraddress;
let fName = fileUtility.getFileName(req.query.filename);
let version = 0;
// track file changes
const processTrack = async function processTrack(response, bodyTrack, fileNameTrack, userAddressTrack) {
@ -776,7 +751,56 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
if (status !== 200) throw new Error(`Document editing service returned status: ${status}`);
await req.DocManager.saveFile(fileName, newFileName, userAddress, body, data);
const storagePath = req.DocManager.storagePath(newFileName, userAddress);
let historyPath = req.DocManager.historyPath(newFileName, userAddress); // get the path to the history data
if (historyPath === '') { // if the history path doesn't exist
historyPath = req.DocManager.historyPath(newFileName, userAddress, true); // create it
req.DocManager.createDirectory(historyPath); // and create a directory for the history data
}
const countVersion = req.DocManager.countVersion(historyPath); // get the next file version number
version = countVersion + 1;
// get the path to the specified file version
const versionPath = req.DocManager.versionPath(newFileName, userAddress, version);
req.DocManager.createDirectory(versionPath); // create a directory to the specified file version
const downloadZip = body.changesurl;
if (downloadZip) {
// get the path to the file with document versions differences
const pathChanges = req.DocManager.diffPath(newFileName, userAddress, version);
const zip = await urllib.request(downloadZip, { method: 'GET' });
const statusZip = zip.status;
const dataZip = zip.data;
if (statusZip === 200) {
fileSystem.writeFileSync(pathChanges, dataZip); // write the document version differences to the archive
} else {
emitWarning(`Document editing service returned status: ${statusZip}`);
}
}
const changeshistory = JSON.stringify(body.history);
if (changeshistory) {
// get the path to the file with document changes
const pathChangesJson = req.DocManager.changesPath(newFileName, userAddress, version);
fileSystem.writeFileSync(pathChangesJson, changeshistory); // and write this data to the path in json format
}
const pathKey = req.DocManager.keyPath(newFileName, userAddress, version); // get the path to the key.txt file
fileSystem.writeFileSync(pathKey, body.key); // write the key value to the key.txt file
// get the path to the previous file version
const pathPrev = path.join(versionPath, `prev${fileUtility.getFileExtension(fileName)}`);
// and write it to the current path
fileSystem.renameSync(req.DocManager.storagePath(fileName, userAddress), pathPrev);
fileSystem.writeFileSync(storagePath, data);
// get the path to the forcesaved file
const forcesavePath = req.DocManager.forcesavePath(newFileName, userAddress, false);
if (forcesavePath !== '') { // if this path is empty
fileSystem.unlinkSync(forcesavePath); // remove it
}
} catch (ex) {
console.log(ex);
response.setHeader('Content-Type', 'application/json');
@ -846,8 +870,64 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
const downloadExt = `.${body.fileType}`;
const isSubmitForm = body.forcesavetype === 3; // SubmitForm
let correctName = fileName;
let forcesavePath = '';
await req.DocManager.forcesaveFile(data, fileName, downloadExt, userAddress, body, newFileName, isSubmitForm);
if (isSubmitForm) {
// new file
if (newFileName) {
correctName = req.DocManager.getCorrectName(
`${fileUtility.getFileName(fileName, true)}-form${downloadExt}`,
userAddress,
);
} else {
const ext = fileUtility.getFileExtension(fileName);
correctName = req.DocManager.getCorrectName(
`${fileUtility.getFileName(fileName, true)}-form${ext}`,
userAddress,
);
}
forcesavePath = req.DocManager.storagePath(correctName, userAddress);
} else {
if (newFileName) {
correctName = req.DocManager.getCorrectName(fileUtility.getFileName(
fileName,
true,
) + downloadExt, userAddress);
}
// create forcesave path if it doesn't exist
forcesavePath = req.DocManager.forcesavePath(correctName, userAddress, false);
if (forcesavePath === '') {
forcesavePath = req.DocManager.forcesavePath(correctName, userAddress, true);
}
}
fileSystem.writeFileSync(forcesavePath, data);
if (isSubmitForm) {
const uid = body.actions[0].userid;
req.DocManager.saveFileData(correctName, uid, 'Filling Form', userAddress);
const { formsdataurl } = body;
if (formsdataurl) {
const formsdataName = req.DocManager.getCorrectName(
`${fileUtility.getFileName(correctName, true)}.txt`,
userAddress,
);
// get the path to the file with forms data
const formsdataPath = req.DocManager.storagePath(formsdataName, userAddress);
const formsdata = await urllib.request(formsdataurl, { method: 'GET' });
const statusFormsdata = formsdata.status;
const dataFormsdata = formsdata.data;
if (statusFormsdata === 200) {
fileSystem.writeFileSync(formsdataPath, dataFormsdata); // write the forms data
} else {
emitWarning(`Document editing service returned status: ${statusFormsdata}`);
}
} else {
emitWarning('Document editing service do not returned formsdataurl');
}
}
} catch (ex) {
console.log(ex);
response.write(`{ "error":1, "message":${JSON.stringify(ex)} }`);
@ -909,9 +989,6 @@ app.post('/track', async (req, res) => { // define a handler for tracking file c
}
}
}
if (bodyTrack.users.length <= 0 && req.DocManager.forcesavePath(fName, uAddress, false)) {
await req.DocManager.saveFile(fName, fName, uAddress, bodyTrack);
}
} else if (bodyTrack.status === 2 || bodyTrack.status === 3) { // MustSave, Corrupted
await processSave(bodyTrack.url, bodyTrack, fileNameTrack, userAddressTrack); // save file
return;
@ -1030,7 +1107,6 @@ app.get('/editor', (req, res) => { // define a handler for editing document
req.DocManager = new DocManager(req, res);
let { fileExt } = req.query;
const fromBuffer = req.query.fromBuffer === 'true';
const user = users.getUser(req.query.userid);
const userid = user.id;
const { name } = user;
@ -1174,12 +1250,11 @@ app.get('/editor', (req, res) => { // define a handler for editing document
// file config data
const argss = {
bufferCallback: req.DocManager.getCallback(fileName, fromBuffer),
apiUrl: siteUrl + configServer.get('apiUrl'),
file: {
name: fileName,
ext: fileUtility.getFileExtension(fileName, true),
uri: fromBuffer ? '_data_' : url,
uri: url,
directUrl: !userDirectUrl ? null : directUrl,
uriUser: directUrl,
created: new Date().toDateString(),

View File

@ -18,8 +18,6 @@
const path = require('path');
const fileSystem = require('fs');
const urllib = require('urllib');
const { emitWarning } = require('process');
const configServer = require('config').get('server');
const fileUtility = require('./fileUtility');
const documentService = require('./documentService');
@ -205,12 +203,11 @@ DocManager.prototype.getProtocol = function getProtocol() {
};
// get callback url
DocManager.prototype.getCallback = function getCallback(fileName, fromBuffer = false) {
DocManager.prototype.getCallback = function getCallback(fileName) {
const server = this.getServerUrl(true);
const hostAddress = this.curUserHostAddress();
const route = fromBuffer ? '/forcesave' : '/track';
// get callback handler
const handler = `${route}?filename=${encodeURIComponent(fileName)}&useraddress=${encodeURIComponent(hostAddress)}`;
const handler = `/track?filename=${encodeURIComponent(fileName)}&useraddress=${encodeURIComponent(hostAddress)}`;
return server + handler;
};
@ -272,129 +269,6 @@ DocManager.prototype.forcesavePath = function forcesavePath(fileName, userAddres
return directory;
};
DocManager.prototype.forcesaveFile = async function forcesaveFile(
data,
fileName,
downloadExt,
userAddress,
body = null,
newFileName = false,
isSubmitForm = false,
) {
let correctName = fileName;
let forcesavePath = '';
if (isSubmitForm) {
// new file
if (newFileName) {
correctName = this.getCorrectName(
`${fileUtility.getFileName(fileName, true)}-form${downloadExt}`,
userAddress,
);
} else {
const ext = fileUtility.getFileExtension(fileName);
correctName = this.getCorrectName(
`${fileUtility.getFileName(fileName, true)}-form${ext}`,
userAddress,
);
}
forcesavePath = this.storagePath(correctName, userAddress);
} else {
if (newFileName) {
correctName = this.getCorrectName(fileUtility.getFileName(
fileName,
true,
) + downloadExt, userAddress);
}
// create forcesave path if it doesn't exist
forcesavePath = this.forcesavePath(correctName, userAddress, false);
if (forcesavePath === '') {
forcesavePath = this.forcesavePath(correctName, userAddress, true);
}
}
fileSystem.writeFileSync(forcesavePath, data);
if (isSubmitForm) {
const uid = body.actions[0].userid;
this.saveFileData(correctName, uid, 'Filling Form', userAddress);
const { formsdataurl } = body;
if (formsdataurl) {
const formsdataName = this.getCorrectName(
`${fileUtility.getFileName(correctName, true)}.txt`,
userAddress,
);
// get the path to the file with forms data
const formsdataPath = this.storagePath(formsdataName, userAddress);
const formsdata = await urllib.request(formsdataurl, { method: 'GET' });
const statusFormsdata = formsdata.status;
const dataFormsdata = formsdata.data;
if (statusFormsdata === 200) {
fileSystem.writeFileSync(formsdataPath, dataFormsdata); // write the forms data
} else {
emitWarning(`Document editing service returned status: ${statusFormsdata}`);
}
} else {
emitWarning('Document editing service do not returned formsdataurl');
}
}
};
DocManager.prototype.saveFile = async function saveFile(fileName, newFileName, userAddress, body, data = null) {
const storagePath = this.storagePath(newFileName, userAddress);
let historyPath = this.historyPath(newFileName, userAddress); // get the path to the history data
if (historyPath === '') { // if the history path doesn't exist
historyPath = this.historyPath(newFileName, userAddress, true); // create it
this.createDirectory(historyPath); // and create a directory for the history data
}
const countVersion = this.countVersion(historyPath); // get the next file version number
const version = countVersion + 1;
// get the path to the specified file version
const versionPath = this.versionPath(newFileName, userAddress, version);
this.createDirectory(versionPath); // create a directory to the specified file version
const downloadZip = body.changesurl;
if (downloadZip) {
// get the path to the file with document versions differences
const pathChanges = this.diffPath(newFileName, userAddress, version);
const zip = await urllib.request(downloadZip, { method: 'GET' });
const statusZip = zip.status;
const dataZip = zip.data;
if (statusZip === 200) {
fileSystem.writeFileSync(pathChanges, dataZip); // write the document version differences to the archive
} else {
emitWarning(`Document editing service returned status: ${statusZip}`);
}
}
const changeshistory = body.changeshistory || JSON.stringify(body.history);
if (changeshistory) {
// get the path to the file with document changes
const pathChangesJson = this.changesPath(newFileName, userAddress, version);
fileSystem.writeFileSync(pathChangesJson, changeshistory); // and write this data to the path in json format
}
const pathKey = this.keyPath(newFileName, userAddress, version); // get the path to the key.txt file
fileSystem.writeFileSync(pathKey, body.key); // write the key value to the key.txt file
// get the path to the previous file version
const pathPrev = path.join(versionPath, `prev${fileUtility.getFileExtension(fileName)}`);
// and write it to the current path
fileSystem.renameSync(this.storagePath(fileName, userAddress), pathPrev);
// get the path to the forcesaved file
const forcesavePath = this.forcesavePath(newFileName, userAddress, false);
if (forcesavePath !== '') { // if this path is not empty
if (data === null) fileSystem.writeFileSync(storagePath, fileSystem.readFileSync(forcesavePath));
fileSystem.unlinkSync(forcesavePath); // remove it
}
if (data !== null) fileSystem.writeFileSync(storagePath, data);
};
// create the path to the file history
DocManager.prototype.historyPath = function historyPath(fileName, userAddress, create) {
let directory = this.storageRootPath(userAddress);

View File

@ -77,30 +77,8 @@
var onAppReady = function () { // the application is loaded into the browser
innerAlert("Document editor ready");
if (config.document.url === "_data_") {
let xhr = new XMLHttpRequest();
xhr.open("GET", "download?fileName=" + encodeURIComponent(config.document.title));
xhr.responseType = "arraybuffer";
xhr.send();
xhr.onload = () => {
if (xhr.status === 200) {
docEditor.openDocument(new Uint8Array(xhr.response));
} else {
innerAlert("Failed to download document");
}
};
};
};
var onSaveDocument = function (event) {
if (config.document.url !== "_data_") return;
let xhr = new XMLHttpRequest();
xhr.open("POST", "<%- bufferCallback %>");
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.send(event.data);
}
var onDocumentStateChange = function (event) { // the document is modified
var title = document.title.replace(/^\*/g, "");
document.title = (event.data ? "*" : "") + title;
@ -476,7 +454,6 @@
"onRequestSelectDocument": onRequestSelectDocument,
"onRequestSelectSpreadsheet": onRequestSelectSpreadsheet,
"onRequestOpen": onRequestOpen,
"onSaveDocument": onSaveDocument,
};
if (<%- JSON.stringify(editor.userid) %> != null) {

View File

@ -111,19 +111,11 @@
<tr>
<td valign="middle">
<label class="side-option">
<input id="directUrl" type="checkbox" class="checkbox collectable" name="directUrl" />Opening direct link
<input id="directUrl" type="checkbox" class="checkbox collectable" name="directUrl" />Try opening on client
<img id="directUrlInfo" class="info info-tooltip" data-id="directUrlInfo" data-tooltip="Some files can be opened in the user's browser without connecting to the document server. Open each file in only one way." src="images/info.svg" />
</label>
</td>
</tr>
<tr>
<td valign="middle">
<label class="side-option">
<input id="fromBuffer" type="checkbox" class="checkbox collectable" name="fromBuffer" />Opening on client
<img id="fromBufferInfo" class="info info-tooltip" data-id="fromBufferInfo" data-tooltip="Download the file and transfer it to the editor on the client without requests from the document server." src="images/info.svg" />
</label>
</td>
</tr>
</tbody>
</table>
</div>

View File

@ -14,7 +14,7 @@ class CheckAndDecodeJWTPayload
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{

View File

@ -11,7 +11,7 @@ class EnsureForgottenPageEnabled
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{

View File

@ -14,7 +14,7 @@ class EnsureJWTTokenIsPresent
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{

View File

@ -12,7 +12,7 @@ class EnsureUserDirectoryExists
/**
* Handle an incoming request.
*
* @param Closure(Request): (Response) $next
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{

View File

@ -1,7 +1,5 @@
<?php
use App\Providers\AppServiceProvider;
return [
AppServiceProvider::class,
App\Providers\AppServiceProvider::class,
];

View File

@ -6229,16 +6229,16 @@
},
{
"name": "laravel/pint",
"version": "v1.28.0",
"version": "v1.27.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/pint.git",
"reference": "1feae84bf9c1649d99ba8f7b8193bf0f09f04cc9"
"reference": "54cca2de13790570c7b6f0f94f37896bee4abcb5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/pint/zipball/1feae84bf9c1649d99ba8f7b8193bf0f09f04cc9",
"reference": "1feae84bf9c1649d99ba8f7b8193bf0f09f04cc9",
"url": "https://api.github.com/repos/laravel/pint/zipball/54cca2de13790570c7b6f0f94f37896bee4abcb5",
"reference": "54cca2de13790570c7b6f0f94f37896bee4abcb5",
"shasum": ""
},
"require": {
@ -6249,14 +6249,13 @@
"php": "^8.2.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.94.2",
"illuminate/view": "^12.54.1",
"larastan/larastan": "^3.9.3",
"friendsofphp/php-cs-fixer": "^3.93.1",
"illuminate/view": "^12.51.0",
"larastan/larastan": "^3.9.2",
"laravel-zero/framework": "^12.0.5",
"mockery/mockery": "^1.6.12",
"nunomaduro/termwind": "^2.4.0",
"pestphp/pest": "^3.8.5",
"shipfastlabs/agent-detector": "^1.0.2"
"nunomaduro/termwind": "^2.3.3",
"pestphp/pest": "^3.8.5"
},
"bin": [
"builds/pint"
@ -6293,7 +6292,7 @@
"issues": "https://github.com/laravel/pint/issues",
"source": "https://github.com/laravel/pint"
},
"time": "2026-03-10T20:37:18+00:00"
"time": "2026-02-10T20:00:20+00:00"
},
{
"name": "laravel/sail",
@ -8727,6 +8726,6 @@
"platform": {
"php": "^8.2"
},
"platform-dev": {},
"plugin-api-version": "2.9.0"
"platform-dev": [],
"plugin-api-version": "2.6.0"
}

View File

@ -1,7 +1,5 @@
<?php
use App\Models\User;
return [
/*
@ -64,7 +62,7 @@ return [
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => env('AUTH_MODEL', User::class),
'model' => env('AUTH_MODEL', App\Models\User::class),
],
// 'users' => [

View File

@ -2,13 +2,12 @@
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
/**
* @extends Factory<User>
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{

View File

@ -51,11 +51,6 @@
- msgspec
- :who:
:why: BSD-3-Clause
:versions: []
:when: 2025-11-07 10:13:51.477550000 Z
- - :approve
- pyjwt
- :who:
:why: MIT
:versions: []
:versions:
- 0.20.0
:when: 2025-11-07 10:13:51.477550000 Z

View File

@ -5,7 +5,7 @@ requires = [
[project]
name = "online-editor-example"
version = "1.6.0"
version = "1.15.0"
requires-python = ">=3.11.4"
dependencies = [
"django>=3.1.3",