fix bug for user app login
This commit is contained in:
63
src/middleware/auth.ts
Normal file
63
src/middleware/auth.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { User } from '@/module/models.ts';
|
||||
import http from 'http';
|
||||
import cookie from 'cookie';
|
||||
export const error = (msg: string, code = 500) => {
|
||||
return JSON.stringify({ code, message: msg });
|
||||
};
|
||||
export const checkAuth = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||
let token = (req.headers?.['authorization'] as string) || (req.headers?.['Authorization'] as string) || '';
|
||||
const url = new URL(req.url || '', 'http://localhost');
|
||||
const resNoPermission = () => {
|
||||
res.statusCode = 401;
|
||||
res.end(error('Invalid authorization'));
|
||||
return { tokenUser: null, token: null };
|
||||
};
|
||||
if (!token) {
|
||||
token = url.searchParams.get('token') || '';
|
||||
}
|
||||
if (!token) {
|
||||
const parsedCookies = cookie.parse(req.headers.cookie || '');
|
||||
token = parsedCookies.token || '';
|
||||
}
|
||||
if (!token) {
|
||||
return resNoPermission();
|
||||
}
|
||||
if (token) {
|
||||
token = token.replace('Bearer ', '');
|
||||
}
|
||||
let tokenUser;
|
||||
try {
|
||||
tokenUser = await User.verifyToken(token);
|
||||
} catch (e) {
|
||||
console.log('checkAuth error', e);
|
||||
res.statusCode = 401;
|
||||
res.end(error('Invalid token'));
|
||||
return { tokenUser: null, token: null };
|
||||
}
|
||||
return { tokenUser, token };
|
||||
};
|
||||
|
||||
export const getLoginUser = async (req: http.IncomingMessage) => {
|
||||
let token = (req.headers?.['authorization'] as string) || (req.headers?.['Authorization'] as string) || '';
|
||||
const url = new URL(req.url || '', 'http://localhost');
|
||||
if (!token) {
|
||||
token = url.searchParams.get('token') || '';
|
||||
}
|
||||
if (!token) {
|
||||
const parsedCookies = cookie.parse(req.headers.cookie || '');
|
||||
token = parsedCookies.token || '';
|
||||
}
|
||||
const parsedCookies = cookie.parse(req.headers.cookie || '');
|
||||
console.log('getLoginUser', parsedCookies, 'parsedCookies.token', parsedCookies.token);
|
||||
|
||||
if (token) {
|
||||
token = token.replace('Bearer ', '');
|
||||
}
|
||||
let tokenUser;
|
||||
try {
|
||||
tokenUser = await User.verifyToken(token);
|
||||
return { tokenUser, token };
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -63,16 +63,25 @@ export class UserApp {
|
||||
const app = this.app;
|
||||
const user = this.user;
|
||||
const key = 'user:app:exist:' + app + ':' + user;
|
||||
const permissionKey = 'user:app:permission:' + app + ':' + user;
|
||||
const value = await redis.get(key);
|
||||
const permission = await redis.get(permissionKey);
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
const [indexFilePath, etag, proxy] = value.split('||');
|
||||
return {
|
||||
indexFilePath,
|
||||
etag,
|
||||
proxy: proxy === 'true',
|
||||
};
|
||||
try {
|
||||
return {
|
||||
indexFilePath,
|
||||
etag,
|
||||
proxy: proxy === 'true',
|
||||
permission: permission ? JSON.parse(permission) : { share: 'private' },
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('getExist error parse', e);
|
||||
await this.clearCacheData();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取缓存数据,不存在不会加载
|
||||
@@ -197,7 +206,7 @@ export class UserApp {
|
||||
console.error('fetchData status is not running', fetchData.user, fetchData.key);
|
||||
return { code: 500, message: 'app status is not running' };
|
||||
}
|
||||
console.log('fetchData', JSON.stringify(fetchData.data.files, null, 2));
|
||||
// console.log('fetchData', JSON.stringify(fetchData.data.files, null, 2));
|
||||
|
||||
this.setLoaded('loading', 'loading');
|
||||
const loadProxy = async () => {
|
||||
@@ -206,6 +215,7 @@ export class UserApp {
|
||||
const version = value.version;
|
||||
let indexHtml = resources + '/' + user + '/' + app + '/' + version + '/index.html';
|
||||
const files = value?.data?.files || [];
|
||||
const permission = value?.data?.permission || { share: 'private' };
|
||||
const data = {};
|
||||
|
||||
// 将文件名和路径添加到 `data` 对象中
|
||||
@@ -216,6 +226,7 @@ export class UserApp {
|
||||
data[file.name] = resources + '/' + file.path;
|
||||
});
|
||||
await redis.set('user:app:exist:' + app + ':' + user, indexHtml + '||etag||true', 'EX', 60 * 60 * 24 * 7); // 7天
|
||||
await redis.set('user:app:permission:' + app + ':' + user, JSON.stringify(permission), 'EX', 60 * 60 * 24 * 7); // 7天
|
||||
await redis.hset('user:app:set:' + app + ':' + user, data);
|
||||
this.setLoaded('running', 'loaded');
|
||||
};
|
||||
@@ -241,6 +252,7 @@ export class UserApp {
|
||||
}
|
||||
await redis.set(key, JSON.stringify(value));
|
||||
const files = value.data.files;
|
||||
const permission = fetchData?.data?.permission || { share: 'private' };
|
||||
const data = {};
|
||||
let indexHtml = path.join(fileStore, user, app, 'index.html') + '||etag||false';
|
||||
// 将文件名和路径添加到 `data` 对象中
|
||||
@@ -251,7 +263,7 @@ export class UserApp {
|
||||
}
|
||||
});
|
||||
await redis.set('user:app:exist:' + app + ':' + user, indexHtml, 'EX', 60 * 60 * 24 * 7); // 7天
|
||||
|
||||
await redis.set('user:app:permission:' + app + ':' + user, JSON.stringify(permission), 'EX', 60 * 60 * 24 * 7); // 7天
|
||||
await redis.hset('user:app:set:' + app + ':' + user, data);
|
||||
this.setLoaded('running', 'loaded');
|
||||
};
|
||||
@@ -293,6 +305,7 @@ export class UserApp {
|
||||
await redis.del('user:app:exist:' + app + ':' + user);
|
||||
await redis.del('user:app:set:' + app + ':' + user);
|
||||
await redis.del('user:app:status:' + app + ':' + user);
|
||||
await redis.del('user:app:permission:' + app + ':' + user);
|
||||
const userDomainApp = 'user:domain:app:' + user + ':' + app;
|
||||
const domainKeys = await redis.get(userDomainApp);
|
||||
if (domainKeys) {
|
||||
|
||||
@@ -8,7 +8,8 @@ import { getContentType } from './get-content-type.ts';
|
||||
import { createRefreshHtml } from './html/create-refresh-html.ts';
|
||||
import { fileProxy } from './proxy/file-proxy.ts';
|
||||
import { getTextFromStreamAndAddStat, httpProxy } from './proxy/http-proxy.ts';
|
||||
|
||||
import { UserPermission } from '@kevisual/permission';
|
||||
import { getLoginUser } from '@/middleware/auth.ts';
|
||||
const api = config?.api || { host: 'kevisual.xiongxiao.me', path: '/api/router' };
|
||||
const domain = config?.proxy?.domain || 'kevisual.xiongxiao.me';
|
||||
const allowedOrigins = config?.proxy?.allowedOrigin || [];
|
||||
@@ -16,6 +17,10 @@ const home = config?.proxy?.home || '/ai/chat';
|
||||
|
||||
const noProxyUrl = ['/', '/favicon.ico'];
|
||||
export const handleRequest = async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
||||
const querySearch = new URL(req.url, `http://${req.headers.host}`).searchParams;
|
||||
const password = querySearch.get('p');
|
||||
const loginUser = await getLoginUser(req);
|
||||
console.log('loginUser', loginUser);
|
||||
if (req.url === '/favicon.ico') {
|
||||
res.writeHead(200, { 'Content-Type': 'image/x-icon' });
|
||||
res.end('proxy no favicon.ico\n');
|
||||
@@ -44,6 +49,7 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
|
||||
const host = req.headers['host'];
|
||||
console.log('host', host);
|
||||
console.log('headers', headers);
|
||||
|
||||
headers.forEach((item) => {
|
||||
header[item] = req.headers[item];
|
||||
});
|
||||
@@ -97,7 +103,6 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
|
||||
|
||||
let user, app;
|
||||
let domainApp = false;
|
||||
console.log('dns.hostName', dns.hostName, domain);
|
||||
if (isLocalhost(dns.hostName)) {
|
||||
// 本地开发环境 测试
|
||||
// user = 'root';
|
||||
@@ -132,6 +137,7 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
|
||||
}
|
||||
// const url = req.url;
|
||||
const pathname = new URL(req.url, `http://${dns.hostName}`).pathname;
|
||||
|
||||
/**
|
||||
* url是pathname的路径
|
||||
*/
|
||||
@@ -207,6 +213,20 @@ export const handleRequest = async (req: http.IncomingMessage, res: http.ServerR
|
||||
if (!isExist) {
|
||||
return createNotFoundPage();
|
||||
}
|
||||
const notAuthUser = ['root', 'admin', 'user', 'public'];
|
||||
if (!notAuthUser.includes(user)) {
|
||||
const { permission } = isExist;
|
||||
const permissionInstance = new UserPermission({ permission, owner: user });
|
||||
const loginUser = await getLoginUser(req);
|
||||
const checkPermission = permissionInstance.checkPermissionSuccess({
|
||||
username: loginUser?.tokenUser?.username || '',
|
||||
password: password,
|
||||
});
|
||||
console.log('checkPermission', loginUser, permission);
|
||||
if (!checkPermission.success) {
|
||||
return createNotFoundPage('no permission');
|
||||
}
|
||||
}
|
||||
const indexFile = isExist.indexFilePath; // 已经必定存在了
|
||||
try {
|
||||
let appFileUrl: string;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { User, UserInit, Org, OrgInit } from '@kevisual/code-center-module';
|
||||
import { User, UserInit, Org, OrgInit } from '@kevisual/code-center-module/models';
|
||||
|
||||
export { User, Org };
|
||||
UserInit();
|
||||
OrgInit();
|
||||
|
||||
export const initModels = () => {
|
||||
OrgInit();
|
||||
UserInit();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user