feat: change permission for mino -resources

This commit is contained in:
2025-03-22 12:48:49 +08:00
parent ea094ee519
commit 5c3d48abab
12 changed files with 478 additions and 81 deletions

View File

@@ -36,3 +36,26 @@ export const checkAuth = async (req: http.IncomingMessage, res: http.ServerRespo
}
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 || '';
}
if (token) {
token = token.replace('Bearer ', '');
}
let tokenUser;
try {
tokenUser = await User.verifyToken(token);
return { tokenUser, token };
} catch (e) {
return null;
}
};

View File

@@ -1,11 +1,13 @@
/**
* 更新时间2025-03-17
* 第二次更新2025-03-22
*/
import { minioClient } from '@/app.ts';
import { IncomingMessage, ServerResponse } from 'http';
import { bucketName } from '@/modules/minio.ts';
import { checkAuth } from '../middleware/auth.ts';
import { getLoginUser } from '../middleware/auth.ts';
import { BucketItemStat } from 'minio';
import { UserPermission, Permission } from '@kevisual/permission';
/**
* 过滤 metaData 中的 key, 去除 password, accesskey, secretkey
@@ -23,54 +25,7 @@ const filterKeys = (metaData: Record<string, string>, clearKeys: string[] = [])
return acc;
}, {} as Record<string, string>);
};
export const checkMetaAuth = async (
metaData: Record<string, string>,
{ tokenUser, token, share, userKey, password }: { tokenUser: any; share: ShareType; token: string; userKey: string; password: string },
) => {
const tokenUsername = tokenUser?.username;
if (share === 'public') {
return {
code: 20000,
msg: '资源是公开的',
};
}
if (tokenUsername === userKey) {
return {
code: 20001,
msg: '用户是资源所有者',
};
}
// 1. 检查资源是否过期(有,则检查)
if (metaData['expiration-time']) {
const expirationTime = new Date(metaData['expiration-time']);
const currentTime = new Date();
if (expirationTime < currentTime) {
return {
code: 20100,
msg: '资源已过期',
};
}
}
// 2. 检查密码是否正确可选password存在的情况
if (password && metaData.password && password === metaData.password) {
return {
code: 20002,
msg: '用户通过密码正确访问',
};
}
const usernames = metaData['usernames'] || '';
if (usernames && usernames.includes(tokenUsername)) {
// TODO: 可以检查用户的orgs 是否在 metaData['orgs'] 中
return {
code: 20003,
msg: '用户在usernames列表中',
};
}
return {
code: 20101,
msg: '用户没有权限访问',
};
};
export const NotFoundFile = (res: ServerResponse, msg?: string, code = 404) => {
res.writeHead(code, { 'Content-Type': 'text/plain' });
res.end(msg || 'Not Found File');
@@ -95,22 +50,21 @@ export const authMinio = async (req: IncomingMessage, res: ServerResponse, objec
if (stat.size === 0) {
return NotFoundFile(res);
}
const share = (metaData.share as ShareType) || 'private'; // 默认是 private
let tokenUser: any = null;
let token: string | null = null;
if (password && metaData.password && password === metaData.password) {
// 密码正确,直接返回
} else if (share !== 'public') {
({ tokenUser, token } = await checkAuth(req, res));
if (!tokenUser) {
return;
}
const checkMetaAuthResult = await checkMetaAuth(metaData, { tokenUser, token, share, userKey, password });
const { code } = checkMetaAuthResult;
if (code >= 20100) {
return NotFoundFile(res);
}
const { tokenUser } = await getLoginUser(req);
const username = tokenUser?.username;
const owner = userKey;
const permission = new UserPermission({
permission: metaData as Permission,
owner,
});
const checkPermissionResult = permission.checkPermissionSuccess({
username,
password,
});
if (!checkPermissionResult.success) {
return NotFoundFile(res, checkPermissionResult.message, checkPermissionResult.code);
}
const contentLength = stat.size;
const etag = stat.etag;
const lastModified = stat.lastModified.toISOString();