添加登录功能
This commit is contained in:
1 parent
20e9f4940e
commit
530e54a596
17 files changed
+617
-145
No files matched your search
@@ -32,3 +32,7 @@ coverage
|
|||||||
# files created with miaoShare service
|
# files created with miaoShare service
|
||||||
temp
|
temp
|
||||||
miaoShare.db
|
miaoShare.db
|
||||||
|
addUser.js
|
||||||
|
|
||||||
|
# JWT SK
|
||||||
|
*.key
|
||||||
@@ -1,3 +1,11 @@
|
|||||||
{
|
{
|
||||||
"PORT":17057
|
"PORT":17057,
|
||||||
|
"userGroupSetting":{
|
||||||
|
"admin":{
|
||||||
|
"cloudCapacity":2147483648
|
||||||
|
},
|
||||||
|
"guest":{
|
||||||
|
"cloudCapacity":2147483648
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Generated
+126
-8
@@ -13,6 +13,8 @@
|
|||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"node-cron": "^3.0.3",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"sm-crypto": "^0.3.13",
|
"sm-crypto": "^0.3.13",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
@@ -24,12 +26,13 @@
|
|||||||
"ws": "^8.16.0"
|
"ws": "^8.16.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@vicons/fluent": "^0.12.0",
|
||||||
"@vicons/ionicons5": "^0.12.0",
|
"@vicons/ionicons5": "^0.12.0",
|
||||||
"@vitejs/plugin-vue": "^5.0.3",
|
"@vitejs/plugin-vue": "^5.0.3",
|
||||||
"better-sqlite3": "^8.7.0",
|
"better-sqlite3": "^8.7.0",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^8.2.2",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"naive-ui": "^2.37.3",
|
"naive-ui": "^2.38.1",
|
||||||
"vfonts": "^0.0.3",
|
"vfonts": "^0.0.3",
|
||||||
"vite": "^5.0.11"
|
"vite": "^5.0.11"
|
||||||
}
|
}
|
||||||
@@ -656,6 +659,12 @@
|
|||||||
"@types/lodash": "*"
|
"@types/lodash": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vicons/fluent": {
|
||||||
|
"version": "0.12.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@vicons/fluent/-/fluent-0.12.0.tgz",
|
||||||
|
"integrity": "sha512-ATCiqPuiJ6RI5GBlD3BIpZ9Xw4MsCA4RpI5oR6MCti4quS4mX1Gp6N74FCzw7lgOj+80rV4HMKhZTVInwimpVQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@vicons/ionicons5": {
|
"node_modules/@vicons/ionicons5": {
|
||||||
"version": "0.12.0",
|
"version": "0.12.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@vicons/ionicons5/-/ionicons5-0.12.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@vicons/ionicons5/-/ionicons5-0.12.0.tgz",
|
||||||
@@ -889,6 +898,11 @@
|
|||||||
"ieee754": "^1.1.13"
|
"ieee754": "^1.1.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer-equal-constant-time": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz",
|
"resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz",
|
||||||
@@ -1174,6 +1188,14 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ecdsa-sig-formatter": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ee-first": {
|
"node_modules/ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
@@ -1577,6 +1599,51 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz",
|
||||||
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
|
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/jsonwebtoken": {
|
||||||
|
"version": "9.0.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz",
|
||||||
|
"integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"jws": "^3.2.2",
|
||||||
|
"lodash.includes": "^4.3.0",
|
||||||
|
"lodash.isboolean": "^3.0.3",
|
||||||
|
"lodash.isinteger": "^4.0.4",
|
||||||
|
"lodash.isnumber": "^3.0.3",
|
||||||
|
"lodash.isplainobject": "^4.0.6",
|
||||||
|
"lodash.isstring": "^4.0.1",
|
||||||
|
"lodash.once": "^4.0.0",
|
||||||
|
"ms": "^2.1.1",
|
||||||
|
"semver": "^7.5.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12",
|
||||||
|
"npm": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jsonwebtoken/node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
|
},
|
||||||
|
"node_modules/jwa": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/jwa/-/jwa-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-equal-constant-time": "1.0.1",
|
||||||
|
"ecdsa-sig-formatter": "1.0.11",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jws": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/jws/-/jws-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
|
||||||
|
"dependencies": {
|
||||||
|
"jwa": "^1.4.1",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
|
||||||
@@ -1589,11 +1656,45 @@
|
|||||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
|
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.includes": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash.includes/-/lodash.includes-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isboolean": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isinteger": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isnumber": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isplainobject": {
|
||||||
|
"version": "4.0.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
|
||||||
|
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.isstring": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
|
||||||
|
},
|
||||||
|
"node_modules/lodash.once": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/lodash.once/-/lodash.once-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
|
||||||
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"yallist": "^4.0.0"
|
"yallist": "^4.0.0"
|
||||||
},
|
},
|
||||||
@@ -1690,9 +1791,9 @@
|
|||||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
},
|
},
|
||||||
"node_modules/naive-ui": {
|
"node_modules/naive-ui": {
|
||||||
"version": "2.37.3",
|
"version": "2.38.1",
|
||||||
"resolved": "https://registry.npmmirror.com/naive-ui/-/naive-ui-2.37.3.tgz",
|
"resolved": "https://registry.npmmirror.com/naive-ui/-/naive-ui-2.38.1.tgz",
|
||||||
"integrity": "sha512-aUkHFXVIluSi8Me+npbcsdv1NYhVMj5t9YaruoCESlqmfqspj+R2QHEVXkTtUI1kQwVrABMCtAGq/wountqjZA==",
|
"integrity": "sha512-AnU1FQ7K/CbhguAX++V4kCFjk7h7RvWt4nvZPRjORMpq+fUIlzD+EcQ5Cv1VqDloNF8+eMv4Akc2Ogacc9S+5A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@css-render/plugin-bem": "^0.15.12",
|
"@css-render/plugin-bem": "^0.15.12",
|
||||||
@@ -1756,6 +1857,25 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-cron": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/node-cron/-/node-cron-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==",
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": "8.3.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-cron/node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
@@ -2056,7 +2176,6 @@
|
|||||||
"version": "7.6.0",
|
"version": "7.6.0",
|
||||||
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.0.tgz",
|
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.6.0.tgz",
|
||||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
},
|
},
|
||||||
@@ -2581,8 +2700,7 @@
|
|||||||
"node_modules/yallist": {
|
"node_modules/yallist": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
|
"resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/yargs": {
|
"node_modules/yargs": {
|
||||||
"version": "17.7.2",
|
"version": "17.7.2",
|
||||||
|
|||||||
+4
-1
@@ -17,6 +17,8 @@
|
|||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
|
"node-cron": "^3.0.3",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"sm-crypto": "^0.3.13",
|
"sm-crypto": "^0.3.13",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
@@ -28,12 +30,13 @@
|
|||||||
"ws": "^8.16.0"
|
"ws": "^8.16.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@vicons/fluent": "^0.12.0",
|
||||||
"@vicons/ionicons5": "^0.12.0",
|
"@vicons/ionicons5": "^0.12.0",
|
||||||
"@vitejs/plugin-vue": "^5.0.3",
|
"@vitejs/plugin-vue": "^5.0.3",
|
||||||
"better-sqlite3": "^8.7.0",
|
"better-sqlite3": "^8.7.0",
|
||||||
"concurrently": "^8.2.2",
|
"concurrently": "^8.2.2",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"naive-ui": "^2.37.3",
|
"naive-ui": "^2.38.1",
|
||||||
"vfonts": "^0.0.3",
|
"vfonts": "^0.0.3",
|
||||||
"vite": "^5.0.11"
|
"vite": "^5.0.11"
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 10 KiB |
@@ -5,15 +5,23 @@ import fs from "fs";
|
|||||||
import { WebSocketServer } from "ws";
|
import { WebSocketServer } from "ws";
|
||||||
import http from "http";
|
import http from "http";
|
||||||
import { v4 as uuid4 } from "uuid";
|
import { v4 as uuid4 } from "uuid";
|
||||||
// import Config from "./miaoShareConfig.json"
|
import jwt from "jsonwebtoken";
|
||||||
|
import sha256 from "crypto-js/sha256.js";
|
||||||
|
import Config from './miaoShareConfig.json' assert { type: 'json' };
|
||||||
|
// function loadJSON(path){
|
||||||
|
// return JSON.parse(fs.readFileSync(path).toString());
|
||||||
|
// }
|
||||||
|
// const Config = loadJSON("./miaoShareConfig.json");
|
||||||
|
|
||||||
const HOST = "0.0.0.0";
|
const HOST = "0.0.0.0";
|
||||||
// const PORT = Config.PORT
|
const PORT = Config.PORT
|
||||||
const PORT = 17057;
|
// const PORT = 17057;
|
||||||
const fileDir = "./temp";
|
const fileDir = "./temp";
|
||||||
const dbPath = "./miaoShare.db";
|
const dbPath = "./miaoShare.db";
|
||||||
const PATH = "./dist";
|
const PATH = "./dist";
|
||||||
|
|
||||||
|
const JWT_SK = fs.readFileSync("JWT_SK.key").toString();
|
||||||
|
|
||||||
// 上传文件最大大小:200MB
|
// 上传文件最大大小:200MB
|
||||||
const uploadMaxSize = 200 * 1024 * 1024;
|
const uploadMaxSize = 200 * 1024 * 1024;
|
||||||
// 一天的毫秒数
|
// 一天的毫秒数
|
||||||
@@ -24,27 +32,43 @@ const LifeOfFile = millisecondsOfOneDay * 3;
|
|||||||
|
|
||||||
// 数据库相关
|
// 数据库相关
|
||||||
const db = new Database(dbPath, { verbose: null });
|
const db = new Database(dbPath, { verbose: null });
|
||||||
db.prepare(
|
db.exec(
|
||||||
`CREATE TABLE IF NOT EXISTS id2fileName (
|
`CREATE TABLE IF NOT EXISTS id2fileName (
|
||||||
id CHAR(8) PRIMARY KEY NOT NULL UNIQUE,
|
id CHAR(8) PRIMARY KEY NOT NULL UNIQUE,
|
||||||
fileName TEXT NOT NULL,
|
fileName TEXT NOT NULL,
|
||||||
timestamp INT NOT NULL,
|
timestamp INT NOT NULL,
|
||||||
freeze tinyint(1) NOT NULL,
|
freeze tinyint(1) NOT NULL,
|
||||||
downloadCredit INT NOT NULL
|
downloadCredit INT NOT NULL,
|
||||||
|
fileSize INT NOT NULL,
|
||||||
|
sender_id CHAR(32) NOT NULL
|
||||||
);`
|
);`
|
||||||
).run();
|
);
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS USERS(
|
||||||
|
user_id CHAR(32) PRIMARY KEY UNIQUE,
|
||||||
|
password_hash CHAR(32) NOT NULL,
|
||||||
|
user_group VARCHAR(32) NOT NULL,
|
||||||
|
uploadFilesSizeCount BIGINT NOT NULL,
|
||||||
|
email CHAR(64)
|
||||||
|
);`);
|
||||||
|
const stmt_getPermissionGroup = db.prepare("SELECT user_group FROM USERS WHERE user_id = ? AND password_hash = ?");
|
||||||
const stmt_getFileName = db.prepare(`SELECT fileName FROM id2fileName WHERE id = ?`);
|
const stmt_getFileName = db.prepare(`SELECT fileName FROM id2fileName WHERE id = ?`);
|
||||||
|
const stmt_getUserUploadFilesSizeCount = db.prepare("SELECT uploadFilesSizeCount FROM USERS WHERE user_id = ?");
|
||||||
|
const stmt_getUserGroup = db.prepare("SELECT user_group FROM USERS WHERE user_id = ?");
|
||||||
const stmt_getTimestamp = db.prepare(`SELECT timestamp FROM id2fileName WHERE id = ?`);
|
const stmt_getTimestamp = db.prepare(`SELECT timestamp FROM id2fileName WHERE id = ?`);
|
||||||
|
const stmt_getFileSize = db.prepare(`SELECT fileSize FROM id2fileName WHERE id = ?`);
|
||||||
const stmt_getFreeze = db.prepare(`SELECT freeze FROM id2fileName WHERE id = ?`);
|
const stmt_getFreeze = db.prepare(`SELECT freeze FROM id2fileName WHERE id = ?`);
|
||||||
const stmt_getDownloadCredit = db.prepare(`SELECT downloadCredit FROM id2fileName WHERE id = ?`);
|
const stmt_getDownloadCredit = db.prepare(`SELECT downloadCredit FROM id2fileName WHERE id = ?`);
|
||||||
const stmt_getFreezenIDs = db.prepare(`SELECT id FROM id2fileName WHERE freeze = 1`);
|
const stmt_getFreezenIDs = db.prepare(`SELECT id,fileSize,sender_id FROM id2fileName WHERE freeze = 1`);
|
||||||
const stmt_insertId2FileName = db.prepare(`INSERT INTO id2fileName (id, fileName, timestamp, freeze, downloadCredit) VALUES (?, ?, ?, ?, ?)`);
|
const stmt_insertId2FileName = db.prepare(`INSERT INTO id2fileName (id, fileName, timestamp, freeze, downloadCredit, fileSize, sender_id) VALUES (?, ?, ?, ?, ?, ?, ?)`);
|
||||||
const stmt_deleteExpireData = db.prepare(`DELETE FROM id2fileName WHERE freeze=1`);
|
const stmt_deleteExpireData = db.prepare(`DELETE FROM id2fileName WHERE freeze=1`);
|
||||||
const stmt_freezeExpireData = db.prepare(`UPDATE id2fileName SET freeze=1 WHERE timestamp < ? OR downloadCredit < 1`);
|
const stmt_freezeExpireData = db.prepare(`UPDATE id2fileName SET freeze=1 WHERE timestamp < ? OR downloadCredit < 1`);
|
||||||
const stmt_updateDownloadCredit = db.prepare(`UPDATE id2fileName SET downloadCredit=downloadCredit-1 WHERE id = ?`);
|
const stmt_updateDownloadCredit = db.prepare(`UPDATE id2fileName SET downloadCredit=downloadCredit-1 WHERE id = ?`);
|
||||||
|
const stmt_updateUserUploadFilesSizeCount = db.prepare(`UPDATE USERS SET uploadFilesSizeCount=uploadFilesSizeCount+? WHERE user_id = ?`);
|
||||||
|
const stmt_updateUserUploadFilesSizeCount_d = db.prepare(`UPDATE USERS SET uploadFilesSizeCount=uploadFilesSizeCount-? WHERE user_id = ?`);
|
||||||
|
|
||||||
const db_insert = (id, fileName, downloadCredit) => {
|
const db_insert = (id, fileName, downloadCredit, fileSize, senderId) => {
|
||||||
stmt_insertId2FileName.run(id, fileName, parseInt(Date.now()), 0, downloadCredit);
|
stmt_insertId2FileName.run(id, fileName, parseInt(Date.now()), 0, downloadCredit, fileSize, senderId);
|
||||||
};
|
};
|
||||||
const db_getFileName = id => {
|
const db_getFileName = id => {
|
||||||
try {
|
try {
|
||||||
@@ -78,6 +102,22 @@ const db_getTimestamp = id => {
|
|||||||
return stmt_getTimestamp.get(id)["timestamp"];
|
return stmt_getTimestamp.get(id)["timestamp"];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const db_getFileSize = id => {
|
||||||
|
return stmt_getFileSize.get(id)["fileSize"];
|
||||||
|
};
|
||||||
|
const db_getUserUploadFilesSizeCount = id => {
|
||||||
|
return stmt_getUserUploadFilesSizeCount.get(id)["uploadFilesSizeCount"];
|
||||||
|
};
|
||||||
|
|
||||||
|
function db_updateUserUploadFilesSizeCount(id,size){
|
||||||
|
return stmt_updateUserUploadFilesSizeCount.run(size,id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 减
|
||||||
|
function db_updateUserUploadFilesSizeCount_d(id,size){
|
||||||
|
return stmt_updateUserUploadFilesSizeCount_d.run(size,id)
|
||||||
|
}
|
||||||
|
|
||||||
// 更新存储的文件,删除已经被冻结的文件以及相关记录,然后冻结过期文件
|
// 更新存储的文件,删除已经被冻结的文件以及相关记录,然后冻结过期文件
|
||||||
const updateDBAndFiles = () => {
|
const updateDBAndFiles = () => {
|
||||||
try {
|
try {
|
||||||
@@ -85,6 +125,9 @@ const updateDBAndFiles = () => {
|
|||||||
stmt_deleteExpireData.run();
|
stmt_deleteExpireData.run();
|
||||||
for (let row of rows) {
|
for (let row of rows) {
|
||||||
let fileName = row["id"];
|
let fileName = row["id"];
|
||||||
|
let sid = row['sender_id']
|
||||||
|
let fsize = row['fileSize']
|
||||||
|
db_updateUserUploadFilesSizeCount_d(sid,fsize)
|
||||||
let path = fileDir + "/" + fileName;
|
let path = fileDir + "/" + fileName;
|
||||||
try {
|
try {
|
||||||
fs.unlink(path, e => {
|
fs.unlink(path, e => {
|
||||||
@@ -117,6 +160,15 @@ if (!fs.existsSync(fileDir)) {
|
|||||||
fs.mkdirSync(fileDir);
|
fs.mkdirSync(fileDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function db_getPermissionGroup(id, pwdH) {
|
||||||
|
let res = stmt_getPermissionGroup.get(id, pwdH);
|
||||||
|
// console.log(id,pwdH,res)
|
||||||
|
if (res && res.user_group) {
|
||||||
|
return res.user_group;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function generateId(isGID) {
|
function generateId(isGID) {
|
||||||
var returnStr = "",
|
var returnStr = "",
|
||||||
range = 8,
|
range = 8,
|
||||||
@@ -134,10 +186,11 @@ function generateId(isGID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 上传文件接口
|
// 上传文件接口
|
||||||
function uploadFile(req, res, fileName, downloadCredit) {
|
function uploadFile(req, res, fileName, downloadCredit, fileSize) {
|
||||||
let id = generateId();
|
let id = generateId();
|
||||||
const fileStream = fs.createWriteStream(fileDir + "/" + id);
|
const fileStream = fs.createWriteStream(fileDir + "/" + id);
|
||||||
db_insert(id, fileName, downloadCredit);
|
db_insert(id, fileName, downloadCredit, fileSize, req.sender_id);
|
||||||
|
db_updateUserUploadFilesSizeCount(req.sender_id,fileSize)
|
||||||
// tempMap[id] = fileName;
|
// tempMap[id] = fileName;
|
||||||
// console.log(tempMap);
|
// console.log(tempMap);
|
||||||
req.pipe(fileStream);
|
req.pipe(fileStream);
|
||||||
@@ -184,9 +237,54 @@ function downloadFile(req, res, fileId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getUserGroup = (function(){
|
||||||
|
const cache = {}
|
||||||
|
return function(userId){
|
||||||
|
if(!cache[userId]){
|
||||||
|
cache[userId]= stmt_getUserGroup.get(userId)['user_group']
|
||||||
|
}
|
||||||
|
return cache[userId]
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
// 验证token
|
||||||
|
const verifyToken = (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const token = req.headers.authorization.split(" ")[1]; // 从Authorization头中提取JWT
|
||||||
|
console.log(req.headers.authorization,token)
|
||||||
|
let verifyData = jwt.verify(token, JWT_SK);
|
||||||
|
if (verifyData.exp > parseInt(Date.now())) {
|
||||||
|
throw "token has expired";
|
||||||
|
}
|
||||||
|
req.sender_id = verifyData.id
|
||||||
|
next();
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
return res.status(401).json({ message: "Invalid token", err });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
app.use(express.static(PATH));
|
app.use(express.static(PATH));
|
||||||
|
app.post("/user/login", express.json(),function (req, res) {
|
||||||
|
res.header("Access-Control-Allow-Origin", "*");
|
||||||
|
res.header("Access-Control-Allow-Headers", "*");
|
||||||
|
res.header("Access-Control-Allow-Methods", "POST");
|
||||||
|
// console.log(req.body)
|
||||||
|
let { id, pwd } = req.body;
|
||||||
|
console.log(req.body)
|
||||||
|
let pwdH = sha256(id + pwd).toString();
|
||||||
|
let userGroup = db_getPermissionGroup(id, pwdH);
|
||||||
|
if (userGroup !== null) {
|
||||||
|
res.writeHead(200);
|
||||||
|
let token = jwt.sign({ id, pwd }, JWT_SK, { expiresIn: "168h" });
|
||||||
|
res.end(JSON.stringify({ status: "Success", userGroup, token }));
|
||||||
|
} else {
|
||||||
|
res.end(JSON.stringify({ status: "Error" }));
|
||||||
|
}
|
||||||
|
// console.log(req)
|
||||||
|
});
|
||||||
// app.all()
|
// app.all()
|
||||||
app.post("/file/upload", function (req, res) {
|
app.post("/file/upload", verifyToken, function (req, res) {
|
||||||
res.header("Access-Control-Allow-Origin", "*");
|
res.header("Access-Control-Allow-Origin", "*");
|
||||||
res.header("Access-Control-Allow-Headers", "*");
|
res.header("Access-Control-Allow-Headers", "*");
|
||||||
res.header("Access-Control-Allow-Methods", "POST");
|
res.header("Access-Control-Allow-Methods", "POST");
|
||||||
@@ -198,15 +296,15 @@ app.post("/file/upload", function (req, res) {
|
|||||||
if (!fileName) {
|
if (!fileName) {
|
||||||
res.statusCode = 500;
|
res.statusCode = 500;
|
||||||
res.end("FileName Not Found");
|
res.end("FileName Not Found");
|
||||||
} else if (fileSize > uploadMaxSize) {
|
} else if (fileSize > uploadMaxSize || db_getUserUploadFilesSizeCount(req.sender_id) + fileSize > Config.userGroupSetting[getUserGroup(req.sender_id)].cloudCapacity) {
|
||||||
res.statusCode = 500;
|
res.statusCode = 500;
|
||||||
res.end("Maximum size limit exceeded");
|
res.end("Maximum size limit exceeded");
|
||||||
} else {
|
} else {
|
||||||
uploadFile(req, res, fileName, downloadCredit);
|
uploadFile(req, res, fileName, downloadCredit, fileSize);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/file/download", function (req, res) {
|
app.get("/file/download", verifyToken, function (req, res) {
|
||||||
res.header("Access-Control-Allow-Origin", "*");
|
res.header("Access-Control-Allow-Origin", "*");
|
||||||
res.header("Access-Control-Allow-Headers", "*");
|
res.header("Access-Control-Allow-Headers", "*");
|
||||||
res.header("Access-Control-Allow-Methods", "GET");
|
res.header("Access-Control-Allow-Methods", "GET");
|
||||||
@@ -234,29 +332,29 @@ const groupsMap = {};
|
|||||||
const LifeOfGroup = millisecondsOfOneDay * 1;
|
const LifeOfGroup = millisecondsOfOneDay * 1;
|
||||||
// const LifeOfGroup = 0;
|
// const LifeOfGroup = 0;
|
||||||
// 根据uuid查询加入的群组
|
// 根据uuid查询加入的群组
|
||||||
const uuid2Groups={}
|
const uuid2Groups = {};
|
||||||
|
|
||||||
db.exec(
|
db.exec(
|
||||||
`CREATE TABLE IF NOT EXISTS GROUPS (
|
`CREATE TABLE IF NOT EXISTS CHATGROUPS (
|
||||||
gID CHAR(8) PRIMARY KEY UNIQUE NOT NULL,
|
gID CHAR(8) PRIMARY KEY UNIQUE NOT NULL,
|
||||||
verify TEXT NOT NULL,
|
verify TEXT NOT NULL,
|
||||||
activeTimestamp INT NOT NULL
|
activeTimestamp INT NOT NULL
|
||||||
);`
|
);`
|
||||||
);
|
);
|
||||||
|
|
||||||
const stmt_getExpiredGroups = db.prepare(`SELECT gID FROM GROUPS WHERE activeTimestamp < ? `);
|
const stmt_getExpiredGroups = db.prepare(`SELECT gID FROM CHATGROUPS WHERE activeTimestamp < ? `);
|
||||||
|
|
||||||
const stmt_getGroupVerify = db.prepare(`SELECT verify FROM GROUPS WHERE gID = ? `);
|
const stmt_getGroupVerify = db.prepare(`SELECT verify FROM CHATGROUPS WHERE gID = ? `);
|
||||||
|
|
||||||
const stmt_insertGROUPS = db.prepare(`INSERT INTO GROUPS (gID,verify, activeTimestamp) VALUES (?, ?, ?)`);
|
const stmt_insertCHATGROUPS = db.prepare(`INSERT INTO CHATGROUPS (gID,verify, activeTimestamp) VALUES (?, ?, ?)`);
|
||||||
|
|
||||||
const stmt_updateGROUPS_ActiveTimestamp = db.prepare(`UPDATE GROUPS SET activeTimestamp=? WHERE gID=?`);
|
const stmt_updateCHATGROUPS_ActiveTimestamp = db.prepare(`UPDATE CHATGROUPS SET activeTimestamp=? WHERE gID=?`);
|
||||||
|
|
||||||
const stmt_deleteGroup = db.prepare(`DELETE FROM GROUPS WHERE gID=?`);
|
const stmt_deleteGroup = db.prepare(`DELETE FROM CHATGROUPS WHERE gID=?`);
|
||||||
|
|
||||||
const generateStmt_insertMessage_map = {};
|
const generateStmt_insertMessage_map = {};
|
||||||
|
|
||||||
const updateGROUPS = () => {
|
const updateCHATGROUPS = () => {
|
||||||
// console.log(1)
|
// console.log(1)
|
||||||
try {
|
try {
|
||||||
let gIDs = stmt_getExpiredGroups.all(parseInt(Date.now()) - LifeOfGroup);
|
let gIDs = stmt_getExpiredGroups.all(parseInt(Date.now()) - LifeOfGroup);
|
||||||
@@ -270,8 +368,8 @@ const updateGROUPS = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
updateGROUPS();
|
updateCHATGROUPS();
|
||||||
setInterval(updateGROUPS, 1000 * 3600 * 3);
|
setInterval(updateCHATGROUPS, 1000 * 3600 * 3);
|
||||||
|
|
||||||
// 创建群组的数据库
|
// 创建群组的数据库
|
||||||
function createGroupTableDB(gID, verify) {
|
function createGroupTableDB(gID, verify) {
|
||||||
@@ -283,7 +381,7 @@ function createGroupTableDB(gID, verify) {
|
|||||||
timestamp INT NOT NULL
|
timestamp INT NOT NULL
|
||||||
);`
|
);`
|
||||||
);
|
);
|
||||||
stmt_insertGROUPS.run(gID, verify, parseInt(Date.now()));
|
stmt_insertCHATGROUPS.run(gID, verify, parseInt(Date.now()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 插入信息
|
// 插入信息
|
||||||
@@ -295,7 +393,7 @@ function insertMessageByGID(gID, msg, from, timestamp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateActiveTimestamp(gID) {
|
function updateActiveTimestamp(gID) {
|
||||||
stmt_updateGROUPS_ActiveTimestamp.run(parseInt(Date.now()), gID);
|
stmt_updateCHATGROUPS_ActiveTimestamp.run(parseInt(Date.now()), gID);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createGroup(verify) {
|
function createGroup(verify) {
|
||||||
@@ -307,13 +405,13 @@ function createGroup(verify) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getGroupVerify(gID) {
|
function getGroupVerify(gID) {
|
||||||
initMsgHistory(gID)
|
initMsgHistory(gID);
|
||||||
return groupsMap[gID].verify;
|
return groupsMap[gID].verify;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 正式加入群组
|
// 正式加入群组
|
||||||
function joinGroup(socket, gID, callback) {
|
function joinGroup(socket, gID, callback) {
|
||||||
initMsgHistory(gID)
|
initMsgHistory(gID);
|
||||||
groupsMap[gID].member.push(socket);
|
groupsMap[gID].member.push(socket);
|
||||||
updateActiveTimestamp(gID);
|
updateActiveTimestamp(gID);
|
||||||
callback();
|
callback();
|
||||||
@@ -321,13 +419,13 @@ function joinGroup(socket, gID, callback) {
|
|||||||
|
|
||||||
// 暂时这么写
|
// 暂时这么写
|
||||||
function getHistory(gID) {
|
function getHistory(gID) {
|
||||||
initMsgHistory(gID)
|
initMsgHistory(gID);
|
||||||
return groupsMap[gID].msgHistory;
|
return groupsMap[gID].msgHistory;
|
||||||
}
|
}
|
||||||
|
|
||||||
function broadcastMsg(gID, msg, from) {
|
function broadcastMsg(gID, msg, from) {
|
||||||
const timestamp = parseInt(Date.now())
|
const timestamp = parseInt(Date.now());
|
||||||
initMsgHistory(gID)
|
initMsgHistory(gID);
|
||||||
updateActiveTimestamp(gID);
|
updateActiveTimestamp(gID);
|
||||||
insertMessageByGID(gID, msg, from, timestamp);
|
insertMessageByGID(gID, msg, from, timestamp);
|
||||||
|
|
||||||
@@ -338,7 +436,7 @@ function broadcastMsg(gID, msg, from) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initMsgHistory(gID){
|
function initMsgHistory(gID) {
|
||||||
if (!groupsMap[gID]) {
|
if (!groupsMap[gID]) {
|
||||||
let verify = stmt_getGroupVerify.get(gID).verify;
|
let verify = stmt_getGroupVerify.get(gID).verify;
|
||||||
// 暂时这么写
|
// 暂时这么写
|
||||||
@@ -346,7 +444,7 @@ function initMsgHistory(gID){
|
|||||||
.prepare(`SELECT message,type,sender,timestamp FROM ${gID}`)
|
.prepare(`SELECT message,type,sender,timestamp FROM ${gID}`)
|
||||||
.all()
|
.all()
|
||||||
.map(v => {
|
.map(v => {
|
||||||
return { type: v.type, msg: v.message,from:v.sender,timestamp:v.timestamp };
|
return { type: v.type, msg: v.message, from: v.sender, timestamp: v.timestamp };
|
||||||
});
|
});
|
||||||
// console.log(msgHistory)
|
// console.log(msgHistory)
|
||||||
groupsMap[gID] = { verify, member: [], msgHistory };
|
groupsMap[gID] = { verify, member: [], msgHistory };
|
||||||
@@ -359,8 +457,8 @@ wss.on("connection", socket => {
|
|||||||
const no = wss.clients.size;
|
const no = wss.clients.size;
|
||||||
const joinedGroup = [];
|
const joinedGroup = [];
|
||||||
var uuid = uuid4();
|
var uuid = uuid4();
|
||||||
function setUuid(new_uuid){
|
function setUuid(new_uuid) {
|
||||||
uuid = new_uuid
|
uuid = new_uuid;
|
||||||
}
|
}
|
||||||
socket.on("message", message => {
|
socket.on("message", message => {
|
||||||
try {
|
try {
|
||||||
@@ -392,14 +490,14 @@ wss.on("connection", socket => {
|
|||||||
}
|
}
|
||||||
} else if (type === "message") {
|
} else if (type === "message") {
|
||||||
let gID = msg.gID;
|
let gID = msg.gID;
|
||||||
broadcastMsg(gID, msg.msg,uuid);
|
broadcastMsg(gID, msg.msg, uuid);
|
||||||
} else if (type === "heartbeat") {
|
} else if (type === "heartbeat") {
|
||||||
socket.send(JSON.stringify({ type: "sMsg", type1: "heartbeat" }));
|
socket.send(JSON.stringify({ type: "sMsg", type1: "heartbeat" }));
|
||||||
} else if (type === "uuid") {
|
} else if (type === "uuid") {
|
||||||
if (msg.type1 === "get") {
|
if (msg.type1 === "get") {
|
||||||
socket.send(JSON.stringify({ type: "sMsg", type1: "uuid", uuid }));
|
socket.send(JSON.stringify({ type: "sMsg", type1: "uuid", uuid }));
|
||||||
} else if (msg.type1 === "set") {
|
} else if (msg.type1 === "set") {
|
||||||
uuid = msg.uuid
|
uuid = msg.uuid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+61
-25
@@ -3,58 +3,110 @@ import upload from "./views/uploadFileMiao.vue";
|
|||||||
import download from "./views/downloadFileMiao.vue";
|
import download from "./views/downloadFileMiao.vue";
|
||||||
import setting from "./views/setting.vue";
|
import setting from "./views/setting.vue";
|
||||||
import chat from "./views/chat.vue";
|
import chat from "./views/chat.vue";
|
||||||
import { NNotificationProvider, NMessageProvider, NCard, NMenu, NIcon } from 'naive-ui'
|
import login from "./views/login.vue";
|
||||||
import { ref, watch, h ,shallowRef} from "vue";
|
import account from "./views/accountInfo.vue";
|
||||||
// import { RouterView, useRouter } from "vue-router";
|
import getQueryString from '@/func/getQuery'
|
||||||
|
import { NNotificationProvider, NMessageProvider, NCard, NMenu, NIcon,NModalProvider } from 'naive-ui'
|
||||||
|
import { ref, watch, h ,shallowRef, onMounted, computed} from "vue";
|
||||||
|
// import { useRoute } from "vue-router";
|
||||||
import {
|
import {
|
||||||
ArrowUpCircleOutline as uploadIcon,
|
ArrowUpCircleOutline as uploadIcon,
|
||||||
ArrowDownCircleOutline as downloadIcon,
|
ArrowDownCircleOutline as downloadIcon,
|
||||||
ChatboxEllipsesOutline as chatIcon,
|
ChatboxEllipsesOutline as chatIcon,
|
||||||
SettingsOutline as settingIcon
|
SettingsOutline as settingIcon,
|
||||||
|
PersonOutline as AccountIcon
|
||||||
|
|
||||||
} from '@vicons/ionicons5'
|
} from '@vicons/ionicons5'
|
||||||
|
import { useSettingStore } from "@/pinia/store";
|
||||||
|
|
||||||
|
|
||||||
|
const settingData = useSettingStore();
|
||||||
const activePage = ref('upload')
|
const activePage = ref('upload')
|
||||||
const isComponent = shallowRef(upload)
|
const isComponent = shallowRef(upload)
|
||||||
watch(activePage, () => {
|
watch(activePage, () => {
|
||||||
isComponent.value={upload,download,setting,chat}[activePage.value]
|
isComponent.value={upload,download,setting,chat,login,account}[activePage.value]
|
||||||
})
|
})
|
||||||
function renderIcon(icon) {
|
function renderIcon(icon) {
|
||||||
return () => h(NIcon, null, { default: () => h(icon) })
|
return () => h(NIcon, null, { default: () => h(icon) })
|
||||||
}
|
}
|
||||||
|
|
||||||
const menuOptions = [
|
const menuOptions = ref([
|
||||||
{
|
{
|
||||||
label: '上传',
|
label: '上传',
|
||||||
key: 'upload',
|
key: 'upload',
|
||||||
icon: renderIcon(uploadIcon),
|
icon: renderIcon(uploadIcon),
|
||||||
|
disabled:computed(()=>{
|
||||||
|
// console.log(settingData)
|
||||||
|
return settingData.token === null
|
||||||
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '下载',
|
label: '下载',
|
||||||
key: 'download',
|
key: 'download',
|
||||||
icon: renderIcon(downloadIcon),
|
icon: renderIcon(downloadIcon),
|
||||||
|
disabled:computed(()=>{
|
||||||
|
return settingData.token === null
|
||||||
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Chat',
|
label: 'Chat',
|
||||||
key: 'chat',
|
key: 'chat',
|
||||||
icon: renderIcon(chatIcon),
|
icon: renderIcon(chatIcon),
|
||||||
|
disabled:computed(()=>{
|
||||||
|
return settingData.token === null
|
||||||
|
})
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '设置',
|
label: '设置',
|
||||||
key: 'setting',
|
key: 'setting',
|
||||||
icon: renderIcon(settingIcon),
|
icon: renderIcon(settingIcon),
|
||||||
|
disabled:computed(()=>{
|
||||||
|
return settingData.token === null
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:'账户',
|
||||||
|
key:'account',
|
||||||
|
icon: renderIcon(AccountIcon),
|
||||||
|
disabled:computed(()=>{
|
||||||
|
return settingData.token === null
|
||||||
|
})
|
||||||
}
|
}
|
||||||
]
|
])
|
||||||
|
// function getQueryString(key) {
|
||||||
|
// var reg = new RegExp('(^|&)' + key + '=([^&]*)(&|$)', 'i');
|
||||||
|
// var r = window.location.search.substr(1).match(reg);
|
||||||
|
// if (r != null) {
|
||||||
|
// return unescape(r[2]);
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(()=>{
|
||||||
|
let aP = getQueryString('aP')
|
||||||
|
// console.log(aP)
|
||||||
|
if(aP){
|
||||||
|
activePage.value = aP
|
||||||
|
}
|
||||||
|
if(settingData.token === null){
|
||||||
|
aP = activePage.value
|
||||||
|
activePage.value = 'login'
|
||||||
|
// 登录后跳原来的activePage
|
||||||
|
const w = watch(()=>settingData.token,()=>{
|
||||||
|
activePage.value = aP
|
||||||
|
w()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div id="windows">
|
<div id="windows">
|
||||||
<n-notification-provider placement="bottom-right" :max="3">
|
<n-notification-provider placement="bottom-right" :max="3">
|
||||||
<n-message-provider>
|
<n-message-provider>
|
||||||
|
<n-modal-provider>
|
||||||
<n-card content-style="padding: 0; margin:0" id="theCard">
|
<n-card content-style="padding: 0; margin:0" id="theCard">
|
||||||
<!-- <n-scrollbar style="max-height: 100%"> -->
|
|
||||||
<div id="menu">
|
<div id="menu">
|
||||||
<n-menu mode="horizontal" :responsive="true" v-model:value="activePage" :options="menuOptions" :icon-size="26"></n-menu>
|
<n-menu mode="horizontal" :responsive="true" v-model:value="activePage" :options="menuOptions" :icon-size="26"></n-menu>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,24 +116,8 @@ const menuOptions = [
|
|||||||
<component :is="isComponent"></component>
|
<component :is="isComponent"></component>
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- </n-scrollbar> -->
|
|
||||||
<!-- <n-tabs type="line" size="large" :tabs-padding="20" pane-style="padding: 20px;"
|
|
||||||
display-directive="show">
|
|
||||||
<n-tab-pane name="上传文件">
|
|
||||||
<uploadFileMiao style />
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="下载文件">
|
|
||||||
<downloadFileMiao style />
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="miaoChat">
|
|
||||||
<chat style />
|
|
||||||
</n-tab-pane>
|
|
||||||
<n-tab-pane name="设置">
|
|
||||||
<settingMiao style="max-width:100%" />
|
|
||||||
</n-tab-pane>
|
|
||||||
</n-tabs> -->
|
|
||||||
</n-card>
|
</n-card>
|
||||||
|
</n-modal-provider>
|
||||||
</n-message-provider>
|
</n-message-provider>
|
||||||
</n-notification-provider>
|
</n-notification-provider>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ const decryptString = (key, str) => {
|
|||||||
|
|
||||||
const downloadFromUint8Array = (data, fileName) => {
|
const downloadFromUint8Array = (data, fileName) => {
|
||||||
let uint8Array = data;
|
let uint8Array = data;
|
||||||
let blob = new Blob([uint8Array], { type: "text/plain" });
|
let blob = new Blob([uint8Array], { type: "application/octet-stream" });
|
||||||
// 使用file-saver.js
|
// 使用file-saver.js
|
||||||
saveAs(blob, fileName);
|
saveAs(blob, fileName);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function getQueryString(key) {
|
||||||
|
var reg = new RegExp('(^|&)' + key + '=([^&]*)(&|$)', 'i');
|
||||||
|
var r = window.location.search.substring(1).match(reg);
|
||||||
|
if (r != null) {
|
||||||
|
return decodeURI(r[2]);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
+22
-1
@@ -1,6 +1,11 @@
|
|||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import config from "../../miaoShareConfig.json"
|
import config from "../../miaoShareConfig.json"
|
||||||
|
|
||||||
|
const userID = localStorage.getItem('userID');
|
||||||
|
const userGroup = localStorage.getItem('userGroup');
|
||||||
|
|
||||||
|
const token = localStorage.getItem('token');
|
||||||
|
// console.log(token)
|
||||||
|
|
||||||
var activeFuctionLocal = localStorage.getItem('activeFuction')
|
var activeFuctionLocal = localStorage.getItem('activeFuction')
|
||||||
if (activeFuctionLocal == null){
|
if (activeFuctionLocal == null){
|
||||||
@@ -18,12 +23,28 @@ export const useSettingStore = defineStore("setting", {
|
|||||||
state: () => ({
|
state: () => ({
|
||||||
activeFuction: activeFuctionLocal,
|
activeFuction: activeFuctionLocal,
|
||||||
activeKeyMap:JSON.parse(activeKeyMap),
|
activeKeyMap:JSON.parse(activeKeyMap),
|
||||||
serverPort:config.PORT
|
serverPort:config.PORT,
|
||||||
|
token,userID,userGroup
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
// double: state => state.count * 2
|
// double: state => state.count * 2
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
setJWT( token,keepTokenLocal ){
|
||||||
|
this.token = token
|
||||||
|
if(keepTokenLocal)
|
||||||
|
localStorage.setItem('token',token)
|
||||||
|
},
|
||||||
|
setUserID( id,keepTokenLocal ){
|
||||||
|
this.userID = id
|
||||||
|
if(keepTokenLocal)
|
||||||
|
localStorage.setItem('userID',id)
|
||||||
|
},
|
||||||
|
setUserGroup( g,keepTokenLocal ){
|
||||||
|
this.userGroup = g
|
||||||
|
if(keepTokenLocal)
|
||||||
|
localStorage.setItem('userGroup',g)
|
||||||
|
}
|
||||||
// increment() {
|
// increment() {
|
||||||
// this.count++;
|
// this.count++;
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<n-button @click="signOut" type="error">
|
||||||
|
退出登录
|
||||||
|
</n-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
import { NCheckbox, NInputGroupLabel, NInputGroup, NP, NFlex, NDataTable, NButton, NInput, NCard } from 'naive-ui'
|
||||||
|
|
||||||
|
function signOut(){
|
||||||
|
const items = ['token']
|
||||||
|
items.forEach(v=>{
|
||||||
|
localStorage.removeItem(v)
|
||||||
|
})
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
+112
-66
@@ -1,15 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-flex style="padding-top: 10px;padding-bottom: 10px;">
|
<n-flex style="padding-top: 10px;padding-bottom: 10px;">
|
||||||
<n-input v-model:value="groupCode" type="text" placeholder="输入进群码" style="flex:1">
|
<n-input v-model:value="groupCode" type="text" placeholder="输入邀请码" style="flex:1">
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<n-icon :component="CopyOutline" style="cursor: pointer;" @click='toClipboard(groupCode)' />
|
<n-icon :component="CopyOutline" style="cursor: pointer;" @click='toClipboard(groupCode)' />
|
||||||
</template>
|
</template>
|
||||||
</n-input>
|
</n-input>
|
||||||
<n-flex>
|
<n-flex>
|
||||||
<n-button @click="createGroup" :disabled="groupCode !== ''" :type="groupCode !== ''?'default':'primary'" ghost >
|
<n-button @click="createGroup" :disabled="groupCode !== ''" :type="groupCode !== '' ? 'default' : 'primary'"
|
||||||
|
ghost>
|
||||||
创建群组
|
创建群组
|
||||||
</n-button>
|
</n-button>
|
||||||
<n-button @click="joinGroup(groupCode)" :disabled="groupCode === ''" :type="groupCode === ''?'default':'primary'" ghost>
|
<n-button @click="joinGroup(groupCode)" :disabled="groupCode === ''"
|
||||||
|
:type="groupCode === '' ? 'default' : 'primary'" ghost>
|
||||||
加入群组
|
加入群组
|
||||||
</n-button>
|
</n-button>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
@@ -23,54 +25,65 @@
|
|||||||
<n-button @click="joinGroup(codeInput)">
|
<n-button @click="joinGroup(codeInput)">
|
||||||
joinTest
|
joinTest
|
||||||
</n-button> -->
|
</n-button> -->
|
||||||
<n-input
|
<n-input v-model:value="msg" type="textarea" placeholder="测试发送信息" :autosize="{
|
||||||
v-model:value="msg"
|
|
||||||
type="textarea"
|
|
||||||
placeholder="测试发送信息"
|
|
||||||
:autosize="{
|
|
||||||
minRows: 3,
|
minRows: 3,
|
||||||
maxRows: 3
|
maxRows: 3
|
||||||
}"
|
}" />
|
||||||
/>
|
|
||||||
<n-flex style="padding-top: 10px;padding-bottom: 10px;">
|
<n-flex style="padding-top: 10px;padding-bottom: 10px;">
|
||||||
<n-select v-model:value="activeGID" :options="joinedGroup.map(gid=>{return {label:gid,value:gid}})" placeholder="选择当前查看群组"
|
<n-select v-model:value="activeGID" :options="joinedGroup.map(gid => { return { label: gid, value: gid } })"
|
||||||
style="flex:1"/>
|
placeholder="选择当前查看群组" style="flex:1" />
|
||||||
<n-button @click="sendMsg(activeGID,msg)" :disabled="msg === '' || activeGID === null" :type="msg === '' || activeGID === null?'default':'primary'">
|
<n-button @click="sendMsg(activeGID, msg)" :disabled="msg === '' || activeGID === null"
|
||||||
|
:type="msg === '' || activeGID === null ? 'default' : 'primary'">
|
||||||
发送消息
|
发送消息
|
||||||
</n-button>
|
</n-button>
|
||||||
|
<n-button @click="shareWithQR()" :disabled="activeGID === null"
|
||||||
|
:type="activeGID === null ? 'default' : 'primary'">
|
||||||
|
分享群组
|
||||||
|
</n-button>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
<!-- <n-button @click="dataTest.length = 0">
|
<!-- <n-button @click="dataTest.length = 0">
|
||||||
clearMsg
|
clearMsg
|
||||||
</n-button> -->
|
</n-button> -->
|
||||||
<n-data-table
|
<n-data-table :columns="columns"
|
||||||
:columns="columns"
|
:data="activeGID ? Messages[activeGID].map(v => { v.timestampString = new Date(v.timestamp).toLocaleString(); return v }).reverse() : []"
|
||||||
:data="activeGID?Messages[activeGID].map(v=>{v.timestampString = new Date(v.timestamp).toLocaleString();return v}):[]"
|
:row-props="null" :bordered="false" :single-line="false" :max-height="400" />
|
||||||
:row-props="null"
|
|
||||||
|
|
||||||
|
<n-modal v-model:show="showModal">
|
||||||
|
<n-card
|
||||||
|
style="width: fit-content;"
|
||||||
|
title=""
|
||||||
:bordered="false"
|
:bordered="false"
|
||||||
:single-line="false"
|
size="huge"
|
||||||
:max-height="400"
|
role="dialog"
|
||||||
/>
|
aria-modal="true"
|
||||||
|
>
|
||||||
|
<n-qr-code :value="QRCodeData" style="padding: 0;" :size="256" error-correction-level="Q" :v-if="showModal" :icon-src='QRIconUrl' :icon-size="128"/>
|
||||||
|
</n-card>
|
||||||
|
</n-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref} from 'vue'
|
import { ref,onMounted } from 'vue'
|
||||||
import { useNotification } from "naive-ui";
|
// import { useModal } from "naive-ui";
|
||||||
import useClipboard from "vue-clipboard3";
|
import useClipboard from "vue-clipboard3";
|
||||||
import {NIcon,NFlex,NDataTable,NButton,NInput,NSelect} from 'naive-ui'
|
import { NIcon, NFlex, NDataTable, NButton, NInput, NSelect,NModal,NCard , NQrCode} from 'naive-ui'
|
||||||
import { useSettingStore } from "@/pinia/store";
|
import { useSettingStore } from "@/pinia/store";
|
||||||
import { generateKey,encryptString } from '@/func/upload';
|
import { generateKey, encryptString } from '@/func/upload';
|
||||||
import { decryptString } from '@/func/download';
|
import { decryptString } from '@/func/download';
|
||||||
import WebsocketHeartbeatJs from 'websocket-heartbeat-js';
|
import WebsocketHeartbeatJs from 'websocket-heartbeat-js';
|
||||||
import {CopyOutline} from '@vicons/ionicons5'
|
import { CopyOutline } from '@vicons/ionicons5'
|
||||||
|
import getQueryString from '@/func/getQuery'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const notification = useNotification();
|
// const modal = useModal();
|
||||||
const { toClipboard } = useClipboard();
|
const { toClipboard } = useClipboard();
|
||||||
|
|
||||||
const setting = useSettingStore();
|
const setting = useSettingStore();
|
||||||
const serverPort = setting.serverPort;
|
const serverPort = setting.serverPort;
|
||||||
const baseUrl = 'ws' + "://" + location.hostname + ":" + serverPort;
|
const baseUrl = 'ws' + "://" + location.hostname + ":" + serverPort;
|
||||||
|
const QRIconUrl = ref(location.protocol + "//" + location.hostname + ":" + serverPort + "/favicon.ico")
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@@ -110,6 +123,15 @@ const columnsTest = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// 用于二维码分享
|
||||||
|
const showModal = ref(false)
|
||||||
|
const QRCodeData = ref('')
|
||||||
|
function shareWithQR(){
|
||||||
|
let code = activeGID.value+gID2key[activeGID.value].key
|
||||||
|
QRCodeData.value = location.protocol + "//" + location.hostname + ":" + serverPort + `/?aP=chat&cG=${code}`
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
// 凭此code进入群组
|
// 凭此code进入群组
|
||||||
const groupCode = ref('')
|
const groupCode = ref('')
|
||||||
|
|
||||||
@@ -139,7 +161,7 @@ const options = {
|
|||||||
pingTimeout: 20000,
|
pingTimeout: 20000,
|
||||||
pongTimeout: 10000,
|
pongTimeout: 10000,
|
||||||
reconnectTimeout: 3000,
|
reconnectTimeout: 3000,
|
||||||
pingMsg: JSON.stringify({type:'heartbeat'})
|
pingMsg: JSON.stringify({ type: 'heartbeat' })
|
||||||
}
|
}
|
||||||
let socket = new WebsocketHeartbeatJs(options);
|
let socket = new WebsocketHeartbeatJs(options);
|
||||||
|
|
||||||
@@ -150,64 +172,64 @@ let socket = new WebsocketHeartbeatJs(options);
|
|||||||
// setInterval(()=>console.log(activeGID.value),1000)
|
// setInterval(()=>console.log(activeGID.value),1000)
|
||||||
|
|
||||||
|
|
||||||
socket.onmessage= (event) => {
|
socket.onmessage = (event) => {
|
||||||
const msg = JSON.parse(event.data)
|
const msg = JSON.parse(event.data)
|
||||||
dataTest.value.push({from:'server',msg:event.data})
|
dataTest.value.push({ from: 'server', msg: event.data })
|
||||||
if(msg.type){
|
if (msg.type) {
|
||||||
let type = msg.type
|
let type = msg.type
|
||||||
if(type === 'sMsg'){
|
if (type === 'sMsg') {
|
||||||
let type1 = msg.type1
|
let type1 = msg.type1
|
||||||
if(type1 === 'create'){
|
if (type1 === 'create') {
|
||||||
gID.value=msg.gID
|
gID.value = msg.gID
|
||||||
groupCode.value = msg.gID + key.value
|
groupCode.value = msg.gID + key.value
|
||||||
joinGroup(groupCode.value)
|
joinGroup(groupCode.value)
|
||||||
}else if(type1 === 'joinVerify'){
|
} else if (type1 === 'joinVerify') {
|
||||||
let gID = msg.gID
|
let gID = msg.gID
|
||||||
let key = gID2key[gID].key
|
let key = gID2key[gID].key
|
||||||
let res = decryptString(key,msg.verify)
|
let res = decryptString(key, msg.verify)
|
||||||
console.log(res,key,msg.verify)
|
// console.log(res, key, msg.verify)
|
||||||
|
|
||||||
// 验证成功,正式加入群组
|
// 验证成功,正式加入群组
|
||||||
if(res === 'miaoSpring'){
|
if (res === 'miaoSpring') {
|
||||||
socket.send(JSON.stringify({type:'join',type1:'success',gID}))
|
socket.send(JSON.stringify({ type: 'join', type1: 'success', gID }))
|
||||||
joinedGroup.value.push(msg.gID)
|
joinedGroup.value.push(msg.gID)
|
||||||
Messages.value[msg.gID] = []
|
Messages.value[msg.gID] = []
|
||||||
if(activeGID.value === null){
|
// if(activeGID.value === null){
|
||||||
activeGID.value = msg.gID
|
activeGID.value = msg.gID
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
} else if (type1 === 'history') {
|
||||||
}else if(type1 === 'history'){
|
|
||||||
let gID = msg.gID
|
let gID = msg.gID
|
||||||
let key = gID2key[gID].key
|
let key = gID2key[gID].key
|
||||||
Messages.value[msg.gID].length = 0
|
Messages.value[msg.gID].length = 0
|
||||||
for(let m of JSON.parse(msg.history)){
|
for (let m of JSON.parse(msg.history)) {
|
||||||
Messages.value[msg.gID].push({type:m.type,msg:decryptString(key,m.msg),from:m.from,timestamp:m.timestamp})
|
Messages.value[msg.gID].push({ type: m.type, msg: decryptString(key, m.msg), from: m.from, timestamp: m.timestamp })
|
||||||
dataTest.value.push({from:'decrypt',msg:decryptString(key,m.msg)})
|
dataTest.value.push({ from: 'decrypt', msg: decryptString(key, m.msg) })
|
||||||
}
|
}
|
||||||
}else if(type1 === 'uuid'){
|
} else if (type1 === 'uuid') {
|
||||||
uuid.value = msg.uuid
|
uuid.value = msg.uuid
|
||||||
}
|
}
|
||||||
}else if(type === 'gMsg'){
|
} else if (type === 'gMsg') {
|
||||||
let gID = msg.gID
|
let gID = msg.gID
|
||||||
let key = gID2key[gID].key
|
let key = gID2key[gID].key
|
||||||
Messages.value[msg.gID].push({type:msg.type,msg:decryptString(key,msg.msg),from:msg.from,timestamp:msg.timestamp})
|
Messages.value[msg.gID].push({ type: msg.type, msg: decryptString(key, msg.msg), from: msg.from, timestamp: msg.timestamp })
|
||||||
// console.log(Messages.value)
|
// console.log(Messages.value)
|
||||||
dataTest.value.push({from:'decrypt',msg:decryptString(key,msg.msg)})
|
dataTest.value.push({ from: 'decrypt', msg: decryptString(key, msg.msg) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
socket.onopen = ()=>{
|
socket.onopen = () => {
|
||||||
if(uuid.value){
|
if (uuid.value) {
|
||||||
socket.send(JSON.stringify({type:'uuid',type1:'set',uuid:uuid.value}))
|
socket.send(JSON.stringify({ type: 'uuid', type1: 'set', uuid: uuid.value }))
|
||||||
}else{
|
} else {
|
||||||
socket.send(JSON.stringify({type:'uuid',type1:'get'}))
|
socket.send(JSON.stringify({ type: 'uuid', type1: 'get' }))
|
||||||
}
|
}
|
||||||
// console.log(joinedGroup)
|
// console.log(joinedGroup)
|
||||||
let toJoin = [...joinedGroup.value]
|
let toJoin = [...joinedGroup.value]
|
||||||
joinedGroup.value.length = 0
|
joinedGroup.value.length = 0
|
||||||
for(let gID of toJoin){
|
for (let gID of toJoin) {
|
||||||
let code = gID+gID2key[gID].key
|
let code = gID + gID2key[gID].key
|
||||||
console.log(code)
|
console.log(code)
|
||||||
joinGroup(code)
|
joinGroup(code)
|
||||||
}
|
}
|
||||||
@@ -217,16 +239,16 @@ socket.onreconnect = (e) => {
|
|||||||
console.log('reconnecting...');
|
console.log('reconnecting...');
|
||||||
}
|
}
|
||||||
|
|
||||||
function createGroup(){
|
function createGroup() {
|
||||||
let keyt = generateKey(setting)
|
let keyt = generateKey(setting)
|
||||||
key.value = keyt
|
key.value = keyt
|
||||||
socket.send(JSON.stringify({type:'create',verify:encryptString(keyt,'miaoSpring',setting)}))
|
socket.send(JSON.stringify({ type: 'create', verify: encryptString(keyt, 'miaoSpring', setting) }))
|
||||||
}
|
}
|
||||||
|
|
||||||
function joinGroup(code){
|
function joinGroup(code) {
|
||||||
var gID = code.substring(0, 8);
|
var gID = code.substring(0, 8);
|
||||||
var key = code.substring(8);
|
var key = code.substring(8);
|
||||||
if(joinedGroup.value.includes(gID)){
|
if (joinedGroup.value.includes(gID)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gID2key[gID] = {}
|
gID2key[gID] = {}
|
||||||
@@ -234,18 +256,42 @@ function joinGroup(code){
|
|||||||
joinGroup_Verify(gID)
|
joinGroup_Verify(gID)
|
||||||
}
|
}
|
||||||
|
|
||||||
function joinGroup_Verify(gID){
|
function joinGroup_Verify(gID) {
|
||||||
socket.send(JSON.stringify({type:'join',type1:'verify',gID}))
|
socket.send(JSON.stringify({ type: 'join', type1: 'verify', gID }))
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMsg(gID,msg){
|
function sendMsg(gID, msg) {
|
||||||
let key = gID2key[gID].key
|
let key = gID2key[gID].key
|
||||||
msg = encryptString(key,msg,setting)
|
msg = encryptString(key, msg, setting)
|
||||||
socket.send(JSON.stringify({type:'message',msg,gID}))
|
socket.send(JSON.stringify({ type: 'message', msg, gID }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 通过地址传参并加入传入的群组
|
||||||
|
// function getQueryString(key) {
|
||||||
|
// var reg = new RegExp('(^|&)' + key + '=([^&]*)(&|$)', 'i');
|
||||||
|
// var r = window.location.search.substring(1).match(reg);
|
||||||
|
// if (r != null) {
|
||||||
|
// return unescape(r[2]);
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
onMounted(()=>{
|
||||||
|
let aP = getQueryString('aP')
|
||||||
|
let cG = getQueryString('cG')
|
||||||
|
if(aP === 'chat' && cG){
|
||||||
|
groupCode.value = cG
|
||||||
|
var st = setInterval(()=>{
|
||||||
|
if(joinedGroup.value.includes(cG.substring(0,8))){
|
||||||
|
clearInterval(st)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
joinGroup(cG)
|
||||||
|
},2000)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
</style>
|
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted,computed } from "vue";
|
||||||
import { useSettingStore } from "@/pinia/store";
|
import { useSettingStore } from "@/pinia/store";
|
||||||
import {decrypt, decryptString, downloadFromUint8Array} from '../func/download'
|
import {decrypt, decryptString, downloadFromUint8Array} from '../func/download'
|
||||||
import {NInput,NFlex,NDataTable,NButton} from 'naive-ui'
|
import {NInput,NFlex,NDataTable,NButton} from 'naive-ui'
|
||||||
@@ -158,7 +158,11 @@ const downloadFile = code => {
|
|||||||
fileName: id
|
fileName: id
|
||||||
};
|
};
|
||||||
const options = {
|
const options = {
|
||||||
method: "GET"
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${setting.token}`
|
||||||
|
// 'Content-Type':'application/json'
|
||||||
|
},
|
||||||
};
|
};
|
||||||
fetch(baseUrl + "file/download?" + new URLSearchParams(params), options)
|
fetch(baseUrl + "file/download?" + new URLSearchParams(params), options)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<n-card style="box-shadow: 10px 10px 5px #888888;margin-top: 100px; padding-left: 25px;padding-right: 25px; padding-bottom: 30px" size="small">
|
||||||
|
<n-flex vertical justify="center">
|
||||||
|
<n-flex justify="center">
|
||||||
|
<h1 style="letter-spacing:25px;font-size: 40px;">登录</h1>
|
||||||
|
</n-flex>
|
||||||
|
<n-input-group>
|
||||||
|
<n-input-group-label>账号</n-input-group-label>
|
||||||
|
<n-input placeholder="userID" v-model:value="userIDInput" :loading="isLogining" :disabled="isLogining"></n-input>
|
||||||
|
</n-input-group>
|
||||||
|
<n-input-group>
|
||||||
|
<n-input-group-label>密码</n-input-group-label>
|
||||||
|
<n-input placeholder="userPassword" v-model:value="userPasswordInput" type="password"
|
||||||
|
show-password-on="click" :loading="isLogining" :disabled="isLogining"></n-input>
|
||||||
|
</n-input-group>
|
||||||
|
<n-flex justify="end">
|
||||||
|
<n-flex style="flex:1;align-items: center;">
|
||||||
|
<n-checkbox size="large" label="保持登录状态" v-model:checked="keepTokenLocal" />
|
||||||
|
</n-flex>
|
||||||
|
<n-flex justify="end">
|
||||||
|
<n-button @click="useGuestAccount">使用访客账号登录</n-button>
|
||||||
|
<n-button @click="login">登录</n-button>
|
||||||
|
</n-flex>
|
||||||
|
</n-flex>
|
||||||
|
</n-flex>
|
||||||
|
</n-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { NCheckbox, NInputGroupLabel, NInputGroup, NP, NFlex, NDataTable, NButton, NInput, NCard } from 'naive-ui'
|
||||||
|
import { useSettingStore } from "@/pinia/store";
|
||||||
|
import { useMessage, useNotification } from "naive-ui";
|
||||||
|
import sha256 from "crypto-js/sha256.js";
|
||||||
|
|
||||||
|
const message = useMessage()
|
||||||
|
|
||||||
|
const settingData = useSettingStore();
|
||||||
|
|
||||||
|
const serverPort = settingData.serverPort;
|
||||||
|
|
||||||
|
|
||||||
|
const userIDInput = ref('')
|
||||||
|
const userPasswordInput = ref('')
|
||||||
|
const isLogining = ref(false)
|
||||||
|
const baseUrl =
|
||||||
|
location.protocol + "//" + location.hostname + ":" + serverPort + "/";
|
||||||
|
|
||||||
|
const Token = computed(() => settingData.token)
|
||||||
|
const keepTokenLocal = ref(true)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function useGuestAccount() {
|
||||||
|
userIDInput.value = 'guest'
|
||||||
|
userPasswordInput.value = 'guest'
|
||||||
|
login()
|
||||||
|
}
|
||||||
|
async function login() {
|
||||||
|
try {
|
||||||
|
isLogining.value = true
|
||||||
|
const response = await fetch(`${baseUrl}user/login`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
// 'Authorization': `Bearer ${Token}`
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
id: userIDInput.value,
|
||||||
|
pwd: sha256(userPasswordInput.value).toString()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
let data = await response.json()
|
||||||
|
if (data.status === 'Error') {
|
||||||
|
console.log('error')
|
||||||
|
throw ('failed')
|
||||||
|
}
|
||||||
|
console.log(data.token, data)
|
||||||
|
settingData.setJWT(data.token,keepTokenLocal)
|
||||||
|
settingData.setUserID(userIDInput.value,keepTokenLocal)
|
||||||
|
settingData.setUserGroup(data.userGroup,keepTokenLocal)
|
||||||
|
} catch (e) {
|
||||||
|
isLogining.value = false
|
||||||
|
message.error(`登录失败`);
|
||||||
|
console.log('failed')
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted,computed } from "vue";
|
||||||
// import aesjs from "aes-js";
|
// import aesjs from "aes-js";
|
||||||
// import { Base64 } from "js-base64";
|
// import { Base64 } from "js-base64";
|
||||||
import { useMessage, useNotification } from "naive-ui";
|
import { useMessage, useNotification } from "naive-ui";
|
||||||
@@ -204,6 +204,8 @@ const customRequest = ({
|
|||||||
"POST",
|
"POST",
|
||||||
baseUrl + "file/upload?" + new URLSearchParams(params)
|
baseUrl + "file/upload?" + new URLSearchParams(params)
|
||||||
);
|
);
|
||||||
|
console.log(setting.token)
|
||||||
|
xhr.setRequestHeader('Authorization', `Bearer ${setting.token}`);
|
||||||
xhr.send(data);
|
xhr.send(data);
|
||||||
xhr.onreadystatechange = () => {
|
xhr.onreadystatechange = () => {
|
||||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
import jwt from 'jsonwebtoken'
|
||||||
|
import sha256 from 'crypto-js/sha256.js';
|
||||||
|
import fs from 'fs'
|
||||||
|
|
||||||
|
const JWT_SK = fs.readFileSync('JWT_SK.key').toString()
|
||||||
|
|
||||||
|
let login = {id:123456,pwd:sha256('nmsl').toString()}
|
||||||
|
console.log(JWT_SK,login)
|
||||||
|
|
||||||
|
let token = jwt.sign(login,JWT_SK,{ expiresIn: '1h' })
|
||||||
|
|
||||||
|
let fakeToken = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTIzNDU2LCJwd2QiOiIwNmYxYTIzOTE2MGZhNTQ2ZTAyOWM5YWQxNTU4OGYwYTI0YWVjYWNhN2M1ZjkyZTE4YmFlNjMzMDk1ZmRjM2JlIiwiaWF0IjoxNzExNTEzMjIwLCJleHAiOjE3MTE1MTY4MjB9.O4-0DkT8Nn0jwZUj09DFK-dOhOfG0n1Mmx3QvsfU8x1`
|
||||||
|
|
||||||
|
// error
|
||||||
|
let verify = jwt.verify(token,JWT_SK)
|
||||||
|
|
||||||
|
console.log(token,verify,parseInt(Date.now()/1000))
|
||||||
Reference in new issue
Block a user