| @@ -0,0 +1,10 @@ | |||||
| # /node_modules/* in the project root is ignored by default | |||||
| # build artefacts | |||||
| dist/* | |||||
| coverage/* | |||||
| # data definition files | |||||
| **/*.d.ts | |||||
| # 3rd party libs | |||||
| /src/public/ | |||||
| # custom definition files | |||||
| /src/types/ | |||||
| @@ -0,0 +1,20 @@ | |||||
| { | |||||
| "parser": "@typescript-eslint/parser", | |||||
| "extends": ["plugin:@typescript-eslint/recommended"], | |||||
| "parserOptions": { | |||||
| "ecmaVersion": 2018, | |||||
| "sourceType": "module" | |||||
| }, | |||||
| "rules": { | |||||
| "semi": ["error", "always"], | |||||
| "quotes": ["error", "double"], | |||||
| "@typescript-eslint/explicit-function-return-type": "off", | |||||
| "@typescript-eslint/no-explicit-any": 1, | |||||
| "@typescript-eslint/no-inferrable-types": [ | |||||
| "warn", { | |||||
| "ignoreParameters": true | |||||
| } | |||||
| ], | |||||
| "@typescript-eslint/no-unused-vars": "warn" | |||||
| } | |||||
| } | |||||
| @@ -14,6 +14,7 @@ | |||||
| # KDE directory preferences | # KDE directory preferences | ||||
| .directory | .directory | ||||
| .desktop | |||||
| # Linux trash folder which might appear on any partition or disk | # Linux trash folder which might appear on any partition or disk | ||||
| .Trash-* | .Trash-* | ||||
| @@ -21,3 +22,12 @@ | |||||
| # .nfs files are created when an open file is removed but is still being accessed | # .nfs files are created when an open file is removed but is still being accessed | ||||
| .nfs* | .nfs* | ||||
| # Dependency directory | |||||
| node_modules | |||||
| bower_components | |||||
| # Built files .js | |||||
| dist/**/*.js | |||||
| # Debug configs | |||||
| config/*.debug.json | |||||
| @@ -0,0 +1,12 @@ | |||||
| { | |||||
| "port": 8088, | |||||
| "realm": "manas", | |||||
| "mounts": { | |||||
| "Music": "/media/hd1/Music", | |||||
| "Movies": "/media/hd1/Movies", | |||||
| "Pictures": "/media/hd1/Bilder", | |||||
| "Books": "/media/hd1/Books", | |||||
| "EBooks": "/media/hd1/EBooks" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| [{ | |||||
| "username": "admin", | |||||
| "password": "#2020#admin", | |||||
| "isAdmin": true | |||||
| }, { | |||||
| "username": "media", | |||||
| "password": "#2020#dav", | |||||
| "access": { | |||||
| "Movies": ["canRead", "canReadContent"], | |||||
| "Music": ["canRead", "canReadContent"] | |||||
| } | |||||
| }] | |||||
| @@ -0,0 +1,30 @@ | |||||
| { | |||||
| "name": "nas-webdav", | |||||
| "version": "1.0.0", | |||||
| "description": "", | |||||
| "main": "index.js", | |||||
| "scripts": { | |||||
| "build": "tsc -p ./tsconfig.json", | |||||
| "start": "node dist/index.js", | |||||
| "start-debug": "nodemon --inspect dist/index.js", | |||||
| "test": "echo \"Error: no test specified\" && exit 1" | |||||
| }, | |||||
| "repository": { | |||||
| "type": "git", | |||||
| "url": "https://hgit.manelis.de/michael/nas-webdav.git" | |||||
| }, | |||||
| "keywords": [], | |||||
| "author": "Michael Manelis <mmanelis@gmal.com> (manelis.de)", | |||||
| "license": "MIT", | |||||
| "dependencies": { | |||||
| "webdav-server": "^2.6.2" | |||||
| }, | |||||
| "devDependencies": { | |||||
| "@types/node": "^14.11.2", | |||||
| "@typescript-eslint/eslint-plugin": "^4.1.1", | |||||
| "@typescript-eslint/parser": "^4.1.1", | |||||
| "eslint": "^7.9.0", | |||||
| "prettier": "^2.1.2", | |||||
| "rimraf": "^3.0.2" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,85 @@ | |||||
| import * as fs from 'fs'; | |||||
| import { v2 as webdav } from 'webdav-server'; | |||||
| function getConfig(name: string) : any { | |||||
| let config = {}; | |||||
| let base = "./config/" + name; | |||||
| let debug = base + '.debug.json'; | |||||
| let prod = base + '.json'; | |||||
| let path = fs.existsSync(debug) ? debug : prod; | |||||
| if (fs.existsSync(path)) { | |||||
| try { | |||||
| config = JSON.parse(fs.readFileSync(path, 'utf8')); | |||||
| } | |||||
| catch (err) { | |||||
| } | |||||
| } | |||||
| return config; | |||||
| } | |||||
| const config = getConfig('srvconfig'); | |||||
| const users = getConfig('users'); | |||||
| if (typeof config.port === undefined) | |||||
| config.port = 8080; | |||||
| if (typeof config.realm === undefined) | |||||
| config.realm = "realm"; | |||||
| let mountNames : string[] = []; | |||||
| for (let mount in config['mounts']) { | |||||
| if (!!config['mounts'][mount] && fs.existsSync(config['mounts'][mount])) | |||||
| mountNames.push(mount); | |||||
| } | |||||
| // User manager (tells who are the users) | |||||
| const userManager: webdav.SimpleUserManager = new webdav.SimpleUserManager(); | |||||
| const privilegeManager: webdav.SimplePathPrivilegeManager = new webdav.SimplePathPrivilegeManager(); | |||||
| for (let nuser = 0 ; nuser < users.length; nuser++) { | |||||
| let isAdmin = !!users[nuser]['isAdmin']; | |||||
| const user = userManager.addUser(users[nuser]['username'], users[nuser]['password'], isAdmin); | |||||
| if (isAdmin) { | |||||
| privilegeManager.setRights(user, '/', [ 'all' ]); | |||||
| } | |||||
| else { | |||||
| if (!!users[nuser]['access']) { | |||||
| for (let userMount in users[nuser]['access']) { | |||||
| if (mountNames.includes(userMount) && !!users[nuser]['access'][userMount]) { | |||||
| privilegeManager.setRights(user, '/' + userMount, users[nuser]['access'][userMount]); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| console.log(user); | |||||
| } | |||||
| const httpAuthentication = new webdav.HTTPBasicAuthentication(userManager); | |||||
| const serverOptions: webdav.WebDAVServerOptions = { | |||||
| port: config.port || 8080, | |||||
| requireAuthentification: true, | |||||
| httpAuthentication, | |||||
| privilegeManager, | |||||
| }; | |||||
| //serverOptions['userManager'] = userManager; | |||||
| const server = new webdav.WebDAVServer(serverOptions); | |||||
| let nMount = 0; | |||||
| //@ts-ignore | |||||
| function mountAndStart() : void { | |||||
| if (nMount < mountNames.length) { | |||||
| let fsEntry = mountNames[nMount]; | |||||
| let realPath = config['mounts'][fsEntry]; | |||||
| nMount++; | |||||
| console.log(`FileSystem ${fsEntry} -> ${realPath}`) | |||||
| server.setFileSystem( | |||||
| '/' + fsEntry, new webdav.PhysicalFileSystem(realPath), (_success) => {mountAndStart();}); | |||||
| } | |||||
| else { | |||||
| server.start(httpServer => { | |||||
| console.log('Server started with success on the port : ' + httpServer.address()['port']); | |||||
| }); | |||||
| } | |||||
| } | |||||
| mountAndStart(); | |||||
| @@ -0,0 +1,28 @@ | |||||
| { | |||||
| "compilerOptions": { | |||||
| "target": "es2016", | |||||
| "module": "commonjs", | |||||
| "sourceRoot": "src", | |||||
| "outDir": "dist", | |||||
| "moduleResolution": "node", | |||||
| "allowSyntheticDefaultImports": true, | |||||
| "allowJs": true, | |||||
| "importHelpers": true, | |||||
| "jsx": "react", | |||||
| "alwaysStrict": true, | |||||
| "sourceMap": true, | |||||
| "forceConsistentCasingInFileNames": true, | |||||
| "noFallthroughCasesInSwitch": true, | |||||
| "noImplicitReturns": true, | |||||
| "noUnusedLocals": true, | |||||
| "noUnusedParameters": true, | |||||
| "noImplicitAny": false, | |||||
| "noImplicitThis": false, | |||||
| "strictNullChecks": false, | |||||
| "experimentalDecorators": true | |||||
| }, | |||||
| "include": [ | |||||
| "src/**/*", | |||||
| "__tests__/**/*" | |||||
| ] | |||||
| } | |||||