feat: force set password

This commit is contained in:
shinya
2025-07-27 15:14:22 +08:00
parent 905ee2457e
commit 54d2a548c5
3 changed files with 105 additions and 7 deletions

View File

@@ -86,7 +86,7 @@
1. **Fork** 本仓库到你的 GitHub 账户。
2. 登陆 [Vercel](https://vercel.com/),点击 **Add New → Project**,选择 Fork 后的仓库。
3. (强烈建议)设置 PASSWORD 环境变量。
3. 设置 PASSWORD 环境变量。
4. 保持默认设置完成首次部署。
5. 如需自定义 `config.json`,请直接修改 Fork 后仓库中该文件。
6. 每次 Push 到 `main` 分支将自动触发重新构建。
@@ -113,7 +113,7 @@
3. 选择 Pages导入现有的 Git 存储库,选择 Fork 后的仓库
4. 构建命令填写 **pnpm install --frozen-lockfile && pnpm run pages:build**,预设框架为无,构建输出目录为 `.vercel/output/static`
5. 保持默认设置完成首次部署。进入设置,将兼容性标志设置为 `nodejs_compat`
6. (强烈建议)首次部署完成后进入设置,新增 PASSWORD 密钥(变量和机密下),而后重试部署。
6. 首次部署完成后进入设置,新增 PASSWORD 密钥(变量和机密下),而后重试部署。
7. 如需自定义 `config.json`,请直接修改 Fork 后仓库中该文件。
8. 每次 Push 到 `main` 分支将自动触发重新构建。
@@ -136,7 +136,7 @@ docker pull ghcr.io/senshinya/moontv:latest
# 运行容器
# -d: 后台运行 -p: 映射端口 3000 -> 3000
docker run -d --name moontv -p 3000:3000 ghcr.io/senshinya/moontv:latest
docker run -d --name moontv -p 3000:3000 --env PASSWORD=your_password ghcr.io/senshinya/moontv:latest
```
访问 `http://服务器 IP:3000` 即可。(需自行到服务器控制台放通 `3000` 端口)

97
src/app/warning/page.tsx Normal file
View File

@@ -0,0 +1,97 @@
import { Metadata } from 'next';
export const metadata: Metadata = {
title: '安全警告 - MoonTV',
description: '站点安全配置警告',
};
export default function WarningPage() {
return (
<div className='min-h-screen bg-gradient-to-br from-red-50 to-orange-50 flex items-center justify-center p-4'>
<div className='max-w-2xl w-full bg-white rounded-2xl shadow-2xl p-4 sm:p-8 border border-red-200'>
{/* 警告图标 */}
<div className='flex justify-center mb-4 sm:mb-6'>
<div className='w-16 h-16 sm:w-20 sm:h-20 bg-red-100 rounded-full flex items-center justify-center'>
<svg
className='w-10 h-10 sm:w-12 sm:h-12 text-red-600'
fill='none'
stroke='currentColor'
viewBox='0 0 24 24'
>
<path
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth={2}
d='M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z'
/>
</svg>
</div>
</div>
{/* 标题 */}
<div className='text-center mb-6 sm:mb-8'>
<h1 className='text-2xl sm:text-3xl font-bold text-gray-900 mb-2'>
</h1>
<div className='w-12 sm:w-16 h-1 bg-red-500 mx-auto rounded-full'></div>
</div>
{/* 警告内容 */}
<div className='space-y-4 sm:space-y-6 text-gray-700'>
<div className='bg-red-50 border-l-4 border-red-500 p-3 sm:p-4 rounded-r-lg'>
<p className='text-base sm:text-lg font-semibold text-red-800 mb-2'>
</p>
<p className='text-sm sm:text-base text-red-700'>
访
</p>
</div>
<div className='space-y-3 sm:space-y-4'>
<h2 className='text-lg sm:text-xl font-semibold text-gray-900'>
</h2>
<ul className='space-y-2 sm:space-y-3 text-sm sm:text-base text-gray-600'>
<li className='flex items-start'>
<span className='text-red-500 mr-2 mt-0.5'></span>
<span>访</span>
</li>
<li className='flex items-start'>
<span className='text-red-500 mr-2 mt-0.5'></span>
<span></span>
</li>
<li className='flex items-start'>
<span className='text-red-500 mr-2 mt-0.5'></span>
<span></span>
</li>
<li className='flex items-start'>
<span className='text-red-500 mr-2 mt-0.5'></span>
<span></span>
</li>
</ul>
</div>
<div className='bg-yellow-50 border border-yellow-200 rounded-lg p-3 sm:p-4'>
<h3 className='text-base sm:text-lg font-semibold text-yellow-800 mb-2'>
🔒
</h3>
<p className='text-sm sm:text-base text-yellow-700'>
{' '}
<code className='bg-yellow-100 px-1.5 py-0.5 rounded text-xs sm:text-sm font-mono'>
PASSWORD
</code>{' '}
访
</p>
</div>
</div>
{/* 底部装饰 */}
<div className='mt-6 sm:mt-8 pt-4 sm:pt-6 border-t border-gray-200'>
<div className='text-center text-xs sm:text-sm text-gray-500'>
<p></p>
</div>
</div>
</div>
</div>
);
}

View File

@@ -14,9 +14,10 @@ export async function middleware(request: NextRequest) {
const storageType = process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage';
// 如果没有设置密码,直接放行
if (storageType === 'localstorage' && !process.env.PASSWORD) {
return NextResponse.next();
if (!process.env.PASSWORD) {
// 如果没有设置密码,重定向到警告页面
const warningUrl = new URL('/warning', request.url);
return NextResponse.redirect(warningUrl);
}
// 从cookie获取认证信息
@@ -132,6 +133,6 @@ function shouldSkipAuth(pathname: string): boolean {
// 配置middleware匹配规则
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico|login|api/login|api/register|api/logout|api/cron|api/server-config).*)',
'/((?!_next/static|_next/image|favicon.ico|login|warning|api/login|api/register|api/logout|api/cron|api/server-config).*)',
],
};