FastMovieAI 二开基线 v1.0 (完整源码)
This commit is contained in:
@@ -0,0 +1,445 @@
|
||||
<?php
|
||||
|
||||
namespace plugin\user\app\api\controller;
|
||||
|
||||
use app\Basic;
|
||||
use app\expose\enum\ResponseCode;
|
||||
use app\expose\enum\ResponseEvent;
|
||||
use app\expose\enum\State;
|
||||
use plugin\control\expose\helper\Vcode;
|
||||
use app\expose\utils\TwofaAuthenticator;
|
||||
use app\model\Uploads;
|
||||
use app\model\UploadsClassify;
|
||||
use plugin\finance\app\model\PluginFinanceWallet;
|
||||
use plugin\user\app\model\PluginUser;
|
||||
use plugin\user\app\model\PluginUserInvitationCode;
|
||||
use plugin\user\app\model\PluginUserTwofaSecret;
|
||||
use plugin\user\app\model\PluginUserWechat;
|
||||
use plugin\user\expose\helper\User;
|
||||
use plugin\user\utils\enum\TotpApp;
|
||||
use plugin\user\utils\enum\VcodeScene;
|
||||
use Shopwwi\WebmanFilesystem\Facade\Storage;
|
||||
use support\Request;
|
||||
use think\facade\Db;
|
||||
|
||||
class UserController extends Basic
|
||||
{
|
||||
protected $notNeedTwofa = ['getTwofaList', 'refreshTwofaSecret'];
|
||||
protected $notNeedLogin = ['checkInvitationCode'];
|
||||
public function info(Request $request)
|
||||
{
|
||||
$user = PluginUser::where(['id' => $request->uid])->find();
|
||||
if (!$user) {
|
||||
return $this->fail('用户不存在');
|
||||
}
|
||||
$info = PluginUser::getTokenInfo($user, $request->twofa);
|
||||
$count = PluginUserInvitationCode::where(['uid' => $request->uid])->where('state', State::YES['value'])->where('status', 'unused')->count();
|
||||
$info->invitation_code_count = $count;
|
||||
return $this->resData($info);
|
||||
}
|
||||
public function update(Request $request)
|
||||
{
|
||||
$D = $request->post();
|
||||
try {
|
||||
if ($request->twofa_state) {
|
||||
$time = time() - (10 * 60);
|
||||
if ($request->twofa['time'] < $time) {
|
||||
return $this->fail('请验证你的身份', [
|
||||
'code' => ResponseCode::NEED_TWOFA,
|
||||
'action' => 'stop'
|
||||
]);
|
||||
}
|
||||
switch (true) {
|
||||
case isset($D['username']):
|
||||
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
|
||||
$username_time = $PluginUser->username_time ? 30 - ceil((time() - strtotime($PluginUser->username_time)) / 86400) : 0;
|
||||
if ($username_time > 0) {
|
||||
return $this->fail('30天内仅支持修改一次');
|
||||
}
|
||||
break;
|
||||
case isset($D['mobile']):
|
||||
Vcode::check($D['mobile'], $D['vcode'], VcodeScene::BIND_MOBILE['value'], $D['token']);
|
||||
break;
|
||||
case isset($D['email']):
|
||||
Vcode::check($D['email'], $D['vcode'], VcodeScene::BIND_EMAIL['value'], $D['token']);
|
||||
break;
|
||||
case isset($D['password']):
|
||||
if (empty($D['vpassword'])) {
|
||||
return $this->fail('两次输入的密码不一致');
|
||||
}
|
||||
if ($D['password'] != $D['vpassword']) {
|
||||
return $this->fail('两次输入的密码不一致');
|
||||
}
|
||||
Vcode::check($D['username'], $D['vcode'], VcodeScene::SET_PASSWORD['value'], $D['token'] ?? null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$D['channels_uid'] = $request->channels_uid;
|
||||
User::update($request->uid, $D);
|
||||
} catch (\Throwable $th) {
|
||||
return $this->exception($th);
|
||||
}
|
||||
return $this->code(ResponseCode::SUCCESS_EVENT_PUSH, '更新成功', [
|
||||
'event' => ResponseEvent::UPDATE_USERINFO
|
||||
]);
|
||||
}
|
||||
public function checkUsername(Request $request)
|
||||
{
|
||||
$username = $request->post('username');
|
||||
$user = PluginUser::where(['username' => $username])->find();
|
||||
if ($user && $user->id != $request->uid) {
|
||||
return $this->fail('用户名已存在');
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
public function checkMobile(Request $request)
|
||||
{
|
||||
$mobile = $request->post('mobile');
|
||||
$user = PluginUser::where(['mobile' => $mobile])->find();
|
||||
if ($user) {
|
||||
if ($user->id == $request->uid) {
|
||||
return $this->fail('和原手机号一致');
|
||||
}
|
||||
return $this->fail('手机号已存在');
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
public function checkEmail(Request $request)
|
||||
{
|
||||
$email = $request->post('email');
|
||||
$user = PluginUser::where(['email' => $email])->find();
|
||||
if ($user) {
|
||||
if ($user->id == $request->uid) {
|
||||
return $this->fail('和原邮箱一致');
|
||||
}
|
||||
return $this->fail('邮箱已存在');
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
public function checkTwofa(Request $request)
|
||||
{
|
||||
if (!$request->twofa_state) {
|
||||
return $this->success();
|
||||
}
|
||||
$time = time() - (10 * 60);
|
||||
if ($request->twofa['time'] < $time) {
|
||||
return $this->fail('请验证你的身份', [
|
||||
'code' => ResponseCode::NEED_TWOFA,
|
||||
'action' => 'stop'
|
||||
]);
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
public function uploadHeadimg(Request $request)
|
||||
{
|
||||
$default_channels = config('plugin.shopwwi.filesystem.app.default');
|
||||
$UploadsClassify = UploadsClassify::where(['dir_name' => 'uploads/default', 'is_system' => 1, 'channels' => $default_channels])->find();
|
||||
if (!$UploadsClassify) {
|
||||
return $this->fail('分类不存在');
|
||||
}
|
||||
$date_path = date('Ymd');
|
||||
//单文件上传
|
||||
$file = $request->file('file');
|
||||
try {
|
||||
$result = Storage::adapter($UploadsClassify->channels)->path($UploadsClassify->dir_name . '/' . $date_path)->upload($file);
|
||||
} catch (\Throwable $th) {
|
||||
return $this->exception($th);
|
||||
}
|
||||
try {
|
||||
$Uploads = new Uploads();
|
||||
$Uploads->uid = $request->uid;
|
||||
$Uploads->classify_id = $UploadsClassify->id;
|
||||
$Uploads->filename = $result->origin_name;
|
||||
$Uploads->path = $result->file_name;
|
||||
$Uploads->ext = $result->extension;
|
||||
$Uploads->mime = $result->mime_type;
|
||||
$Uploads->size = $result->size;
|
||||
$Uploads->channels = $UploadsClassify->channels;
|
||||
$Uploads->save();
|
||||
} catch (\Throwable $th) {
|
||||
return $this->exception($th);
|
||||
}
|
||||
$user = PluginUser::where(['id' => $request->uid])->find();
|
||||
$user->headimg = $result->file_url;
|
||||
$user->save();
|
||||
return $this->code(ResponseCode::SUCCESS_EVENT_PUSH, '保存成功', [
|
||||
'event' => ResponseEvent::UPDATE_USERINFO
|
||||
]);
|
||||
}
|
||||
public function outLogin(Request $request)
|
||||
{
|
||||
return $this->success();
|
||||
}
|
||||
/**
|
||||
* 获取两步验证密钥
|
||||
*/
|
||||
public function getTwofaSecret(Request $request)
|
||||
{
|
||||
try {
|
||||
$ga = new TwofaAuthenticator();
|
||||
$secret = $ga->createSecret();
|
||||
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
|
||||
|
||||
// 生成 otpauth URL
|
||||
$appName = "XH";
|
||||
$accountName = $PluginUser->nickname;
|
||||
$qrCodeUrl = $ga->getQRCode($appName . ':' . $accountName, $secret, $appName);
|
||||
} catch (\Throwable $th) {
|
||||
return $this->exception($th);
|
||||
}
|
||||
|
||||
return $this->resData([
|
||||
'secret' => $secret,
|
||||
'qrcode' => $qrCodeUrl
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证两步验证密钥
|
||||
*/
|
||||
public function verifyTwofaSecret(Request $request)
|
||||
{
|
||||
$code = $request->post('code');
|
||||
$secret = $request->post('secret');
|
||||
$totp_app = $request->post('totp_app');
|
||||
$ga = new TwofaAuthenticator();
|
||||
|
||||
$isValid = $ga->verifyCode($secret, $code, 2); // 1 = 30 秒容差
|
||||
|
||||
if ($isValid) {
|
||||
Db::startTrans();
|
||||
try {
|
||||
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
|
||||
$PluginUser->twofa_state = State::YES['value'];
|
||||
$PluginUser->save();
|
||||
$PluginUserTwofaSecret = new PluginUserTwofaSecret();
|
||||
$PluginUserTwofaSecret->uid = $request->uid;
|
||||
$PluginUserTwofaSecret->secret = $secret;
|
||||
$PluginUserTwofaSecret->totp_app = $totp_app;
|
||||
$PluginUserTwofaSecret->is_default = PluginUserTwofaSecret::where(['uid' => $request->uid])->count() == 0 ? 1 : 0;
|
||||
$PluginUserTwofaSecret->save();
|
||||
Db::commit();
|
||||
} catch (\Throwable $th) {
|
||||
Db::rollback();
|
||||
return $this->exception($th);
|
||||
}
|
||||
return $this->success('验证成功');
|
||||
} else {
|
||||
return $this->fail('验证码错误');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 刷新账户两步验证时效
|
||||
*/
|
||||
public function refreshTwofaSecret(Request $request)
|
||||
{
|
||||
$code = $request->post('code');
|
||||
$totp_app = $request->post('totp_app');
|
||||
$ga = new TwofaAuthenticator();
|
||||
$PluginUserTwofaSecret = PluginUserTwofaSecret::where(['uid' => $request->uid, 'id' => $totp_app])->find();
|
||||
if (!$PluginUserTwofaSecret) {
|
||||
return $this->fail('两步验证密钥不存在');
|
||||
}
|
||||
$secret = $PluginUserTwofaSecret->secret;
|
||||
$isValid = $ga->verifyCode($secret, $code, 2); // 1 = 30 秒容差
|
||||
|
||||
if ($isValid) {
|
||||
$user = PluginUser::where(['id' => $request->uid])->find();
|
||||
if (!$user) {
|
||||
return $this->fail('用户不存在');
|
||||
}
|
||||
$info = PluginUser::getTokenInfo($user, true);
|
||||
return $this->resData($info);
|
||||
} else {
|
||||
return $this->fail('验证码错误');
|
||||
}
|
||||
}
|
||||
public function getTwofaList(Request $request)
|
||||
{
|
||||
$PluginUserTwofaSecret = PluginUserTwofaSecret::where(['uid' => $request->uid])->order('is_default desc,id desc')->select()->scene('external')->each(function ($item) {
|
||||
$item->totp_app_text = TotpApp::get($item->totp_app);
|
||||
});
|
||||
return $this->resData($PluginUserTwofaSecret);
|
||||
}
|
||||
public function setDefaultTwofa(Request $request)
|
||||
{
|
||||
$id = $request->post('id');
|
||||
$PluginUserTwofaSecret = PluginUserTwofaSecret::where(['uid' => $request->uid, 'id' => $id])->find();
|
||||
if (!$PluginUserTwofaSecret) {
|
||||
return $this->fail('两步验证密钥不存在');
|
||||
}
|
||||
Db::startTrans();
|
||||
try {
|
||||
PluginUserTwofaSecret::where(['uid' => $request->uid])->update(['is_default' => 0]);
|
||||
$PluginUserTwofaSecret->is_default = 1;
|
||||
$PluginUserTwofaSecret->save();
|
||||
Db::commit();
|
||||
} catch (\Throwable $th) {
|
||||
Db::rollback();
|
||||
return $this->exception($th);
|
||||
}
|
||||
return $this->success('设置成功');
|
||||
}
|
||||
public function deleteTwofa(Request $request)
|
||||
{
|
||||
$id = $request->post('id');
|
||||
$PluginUserTwofaSecret = PluginUserTwofaSecret::where(['uid' => $request->uid, 'id' => $id])->find();
|
||||
if (!$PluginUserTwofaSecret) {
|
||||
return $this->fail('两步验证密钥不存在');
|
||||
}
|
||||
Db::startTrans();
|
||||
try {
|
||||
// 判断是否还有其它两步验证密钥
|
||||
$PluginUserTwofaSecretOther = PluginUserTwofaSecret::where(['uid' => $request->uid])->where('id', '<>', $id)->order('id desc')->find();
|
||||
if ($PluginUserTwofaSecretOther) {
|
||||
if ($PluginUserTwofaSecret->is_default == 1) {
|
||||
$PluginUserTwofaSecretOther->is_default = 1;
|
||||
$PluginUserTwofaSecretOther->save();
|
||||
}
|
||||
} else {
|
||||
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
|
||||
$PluginUser->twofa_state = State::NO['value'];
|
||||
$PluginUser->save();
|
||||
}
|
||||
$PluginUserTwofaSecret->delete();
|
||||
Db::commit();
|
||||
} catch (\Throwable $th) {
|
||||
Db::rollback();
|
||||
return $this->exception($th);
|
||||
}
|
||||
return $this->success('删除成功');
|
||||
}
|
||||
/**
|
||||
* 获取用户未使用的邀请码
|
||||
* @author:1950781041@qq.com
|
||||
* @Date:2026-01-07
|
||||
*/
|
||||
public function getUnusedInvitationCode(Request $request)
|
||||
{
|
||||
$PluginUserInvitationCode = PluginUserInvitationCode::where(['uid' => $request->uid])
|
||||
->with(['useUser'])
|
||||
->where('channels_uid', $request->channels_uid)
|
||||
->where('state', State::YES['value'])
|
||||
->select();
|
||||
return $this->resData($PluginUserInvitationCode);
|
||||
}
|
||||
/**
|
||||
* 用户绑定邀请码
|
||||
* @author:1950781041@qq.com
|
||||
* @Date:2026-01-15
|
||||
*/
|
||||
public function bindInvitationCode(Request $request)
|
||||
{
|
||||
$code = $request->post('code');
|
||||
$PluginUserInvitationCode = PluginUserInvitationCode::where(['code' => $code])->find();
|
||||
if (!$PluginUserInvitationCode) {
|
||||
return $this->fail('邀请码不存在');
|
||||
}
|
||||
if ($PluginUserInvitationCode->uid == $request->uid) {
|
||||
return $this->fail('不能邀请自己');
|
||||
}
|
||||
if (!empty($PluginUserInvitationCode->use_uid)) {
|
||||
return $this->fail('邀请码已使用');
|
||||
}
|
||||
if ($PluginUserInvitationCode->status != 'unused') {
|
||||
return $this->fail('邀请码已使用');
|
||||
}
|
||||
if ($PluginUserInvitationCode->state != State::YES['value']) {
|
||||
return $this->fail('邀请码已失效');
|
||||
}
|
||||
$PluginUserInvitationCode->status = 'used';
|
||||
$PluginUserInvitationCode->use_uid = $request->uid;
|
||||
$PluginUserInvitationCode->use_time = date('Y-m-d H:i:s');
|
||||
$PluginUserInvitationCode->save();
|
||||
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
|
||||
$PluginUser->activation_time = date('Y-m-d H:i:s');
|
||||
$PluginUser->puid = $PluginUserInvitationCode->uid;
|
||||
$PluginUser->save();
|
||||
return $this->success('绑定成功');
|
||||
}
|
||||
/**
|
||||
* 用户绑定电话
|
||||
* @author:1950781041@qq.com
|
||||
* @Date:2026-01-15
|
||||
*/
|
||||
public function bindMobile(Request $request)
|
||||
{
|
||||
$mobile = $request->post('username');
|
||||
$username = $request->post('username');
|
||||
$vcode = $request->post('vcode');
|
||||
$token = $request->post('token');
|
||||
if (empty($username) || empty($vcode) || empty($token)) {
|
||||
return $this->fail('参数错误');
|
||||
}
|
||||
Vcode::check($username, $vcode, VcodeScene::BIND_MOBILE['value'], $token);
|
||||
$PluginUser = PluginUser::where(['mobile' => $mobile, 'channels_uid' => $request->channels_uid])->find();
|
||||
if ($PluginUser) {
|
||||
PluginUser::where(['id' => $request->uid])->update(['username' => '']);
|
||||
$wechat = PluginUserWechat::where(['uid' => $request->uid])->find();
|
||||
$wechat->uid = $PluginUser->id;
|
||||
$wechat->save();
|
||||
return $this->resData(PluginUser::getTokenInfo($PluginUser, true));
|
||||
}
|
||||
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
|
||||
if ($PluginUser->mobile) {
|
||||
return $this->fail('电话已绑定');
|
||||
}
|
||||
$PluginUser->mobile = $mobile;
|
||||
$PluginUser->save();
|
||||
return $this->resData(PluginUser::getTokenInfo($PluginUser, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @author:1950781041@qq.com
|
||||
* @Date:2026-01-17
|
||||
*/
|
||||
public function setPassword(Request $request)
|
||||
{
|
||||
$password = $request->post('password');
|
||||
$token = $request->post('token');
|
||||
$vcode = $request->post('vcode');
|
||||
$username = $request->post('username');
|
||||
if (empty($password) || empty($token) || empty($vcode) || empty($username)) {
|
||||
return $this->fail('参数错误');
|
||||
}
|
||||
Vcode::check($username, $vcode, VcodeScene::BIND_MOBILE['value'], $token);
|
||||
$PluginUser = PluginUser::where(['id' => $request->uid])->find();
|
||||
$PluginUser->password = $password;
|
||||
$PluginUser->save();
|
||||
return $this->success('修改成功');
|
||||
}
|
||||
|
||||
public function wallet(Request $request)
|
||||
{
|
||||
$wallet = PluginFinanceWallet::where(['uid' => $request->uid])->find();
|
||||
if (!$wallet) {
|
||||
return $this->fail('钱包不存在');
|
||||
}
|
||||
return $this->resData($wallet);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证邀请码是否被使用
|
||||
* @author:1950781041@qq.com
|
||||
* @Date:2026-01-26
|
||||
*/
|
||||
public function checkInvitationCode(Request $request)
|
||||
{
|
||||
$code = $request->post('code');
|
||||
$PluginUserInvitationCode = PluginUserInvitationCode::where(['code' => $code])->find();
|
||||
if (!$PluginUserInvitationCode) {
|
||||
return $this->fail('邀请码不存在');
|
||||
}
|
||||
if ($PluginUserInvitationCode->uid == $request->uid) {
|
||||
return $this->fail('不能邀请自己');
|
||||
}
|
||||
if (!empty($PluginUserInvitationCode->use_uid)) {
|
||||
return $this->fail('邀请码已使用');
|
||||
}
|
||||
if ($PluginUserInvitationCode->status != 'unused') {
|
||||
return $this->fail('邀请码已使用');
|
||||
}
|
||||
return $this->success();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user