1
0
mirror of https://gitee.com/koogua/course-tencent-cloud.git synced 2025-06-26 20:52:44 +08:00

Merge branch 'koogua/v1.7.2' into demo

This commit is contained in:
xiaochong0302 2024-08-13 09:27:46 +08:00
commit 335f2fd5cf
22 changed files with 141 additions and 101 deletions

View File

@ -1,3 +1,14 @@
### [v1.7.2](https://gitee.com/koogua/course-tencent-cloud/releases/v1.7.2)(2024-07-31)
- 更新layui-v2.9.14
- 优化docker自动化脚本
- 修正教师直播通知
- 修正课程分类删选问题
- 后台增加客户服务入口
- redis增加expire方法
- 日志记录增加log.trace参数
- 精简代码
### [v1.7.1](https://gitee.com/koogua/course-tencent-cloud/releases/v1.7.1)(2024-06-31)
- 更新layui-v2.9.10

View File

@ -7,11 +7,29 @@
namespace App\Console\Migrations;
use App\Models\Setting as SettingModel;
use App\Repos\Setting as SettingRepo;
use App\Traits\Service as ServiceTrait;
abstract class Migration
{
use ServiceTrait;
abstract public function run();
protected function saveSetting(array $setting)
{
$settingRepo = new SettingRepo();
$item = $settingRepo->findItem($setting['section'], $setting['item_key']);
if (!$item) {
$item = new SettingModel();
$item->create($setting);
} else {
$item->update($setting);
}
}
}

View File

@ -30,7 +30,7 @@ class TeacherLiveNoticeTask extends Task
$keyName = $this->getCacheKeyName();
foreach ($lives as $live) {
$redis->sAdd($keyName, $live->chapter_id);
$redis->sAdd($keyName, $live->id);
}
$redis->expire($keyName, 86400);

View File

@ -0,0 +1,41 @@
<?php
/**
* @copyright Copyright (c) 2021 深圳市酷瓜软件有限公司
* @license https://opensource.org/licenses/GPL-2.0
* @link https://www.koogua.com
*/
namespace App\Http\Admin\Controllers;
use App\Traits\Response as ResponseTrait;
/**
* @RoutePrefix("/admin/koogua")
*/
class KooguaController extends \Phalcon\Mvc\Controller
{
use ResponseTrait;
/**
* @Get("/wiki", name="admin.koogua.wiki")
*/
public function wikiAction()
{
$url = 'https://www.koogua.com/page/wiki';
$this->response->redirect($url, true);
}
/**
* @Get("/community", name="admin.koogua.community")
*/
public function communityAction()
{
$url = 'https://www.koogua.com/question/list';
return $this->response->redirect($url, true);
}
}

View File

@ -28,6 +28,16 @@
{% endfor %}
</ul>
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item">
<a href="{{ url({'for':'home.index'}) }}" target="_blank">前台首页</a>
</li>
<li class="layui-nav-item">
<a href="javascript:">用户服务</a>
<dl class="layui-nav-child">
<dd><a href="{{ url({'for':'admin.koogua.wiki'}) }}" target="_blank">系统文档</a></dd>
<dd><a href="{{ url({'for':'admin.koogua.community'}) }}" target="_blank">开源社区</a></dd>
</dl>
</li>
<li class="layui-nav-item">
<a href="javascript:">{{ auth_user.name }}</a>
<dl class="layui-nav-child">
@ -36,9 +46,6 @@
<dd><a href="{{ url({'for':'admin.logout'}) }}">退出登录</a></dd>
</dl>
</li>
<li class="layui-nav-item">
<a href="{{ url({'for':'home.index'}) }}" target="_blank">前台</a>
</li>
</ul>
</div>
<div class="layui-side layui-bg-black">

View File

@ -4,7 +4,7 @@
<div class="layui-tab layui-tab-brief">
<ul class="layui-tab-title kg-tab-title">
<li class="layui-this">注册设置</li>
<li class="layui-this">基本设置</li>
<li>QQ登录</li>
<li>微信登录</li>
<li>微博登录</li>

View File

@ -16,13 +16,13 @@
<div class="layui-form-item" style="margin-bottom:20px;">
<label class="layui-form-label">用户协议</label>
<div class="layui-input-block">
<a class="layui-btn layui-btn-normal" href="{{ url({'for':'admin.page.edit','id':'terms'}) }}">前往设置</a>
<a class="layui-btn layui-btn-normal" href="{{ url({'for':'admin.page.edit','id':'terms'}) }}">设置</a>
</div>
</div>
<div class="layui-form-item" style="margin-bottom:20px;">
<label class="layui-form-label">隐私政策</label>
<div class="layui-input-block">
<a class="layui-btn layui-btn-normal" href="{{ url({'for':'admin.page.edit','id':'privacy'}) }}">前往设置</a>
<a class="layui-btn layui-btn-normal" href="{{ url({'for':'admin.page.edit','id':'privacy'}) }}">设置</a>
</div>
</div>
<div class="layui-form-item">

View File

@ -16,7 +16,7 @@ class AppInfo
protected $link = 'https://www.koogua.com';
protected $version = '1.7.1';
protected $version = '1.7.2';
public function __get($name)
{

View File

@ -161,7 +161,7 @@ class Redis extends \Phalcon\Cache\Backend\Redis
$redis->setOption(\Redis::OPT_SCAN, \Redis::SCAN_RETRY);
$it = null;
$it = 0;
while ($keys = $redis->scan($it, $pattern)) {
if (count($result) > $limit) break;
@ -191,6 +191,35 @@ class Redis extends \Phalcon\Cache\Backend\Redis
return (bool)$redis->exists($lastKey);
}
/**
* @param string $keyName
* @return bool
*/
public function expire($keyName = null, $lifetime = null): bool
{
$redis = $this->getRedis();
/**
* @var FrontendInterface $frontend
*/
$frontend = $this->_frontend;
if ($keyName === null) {
$lastKey = $this->_lastKey;
} else {
$lastKey = $this->getKeyName($keyName);
}
if ($lifetime === null) {
$tmp = $this->_lastLifetime;
$ttl = $tmp ?: $frontend->getLifetime();
} else {
$ttl = $lifetime;
}
return $redis->expire($lastKey, $ttl);
}
/**
* @param string $keyName
* @return int|bool

View File

@ -26,19 +26,4 @@ class UserSession extends Repository
->execute();
}
/**
* @param int $userId
* @param int $minutes
* @return ResultsetInterface|Resultset|UserSessionModel[]
*/
public function findUserRecentSessions($userId, $minutes = 10)
{
$createTime = time() - $minutes * 60;
return UserSessionModel::query()
->where('user_id = :user_id:', ['user_id' => $userId])
->andWhere('create_time > :create_time:', ['create_time' => $createTime])
->execute();
}
}

View File

@ -25,19 +25,4 @@ class UserToken extends Repository
->execute();
}
/**
* @param int $userId
* @param int $minutes
* @return ResultsetInterface|Resultset|UserTokenModel[]
*/
public function findUserRecentTokens($userId, $minutes = 10)
{
$createTime = time() - $minutes * 60;
return UserTokenModel::query()
->where('user_id = :user_id:', ['user_id' => $userId])
->andWhere('create_time > :create_time:', ['create_time' => $createTime])
->execute();
}
}

View File

@ -56,19 +56,4 @@ class Admin extends AuthService
return 'admin_auth_info';
}
public function hasPermission($route)
{
$authUser = $this->getAuthInfo();
if ($authUser['root'] == 1) {
return true;
}
if (in_array($route, $authUser['routes'])) {
return true;
}
return false;
}
}

View File

@ -57,11 +57,6 @@ class Home extends AuthService
return $authInfo ?: null;
}
public function getAuthKey()
{
return 'home_auth_info';
}
public function logoutClients($userId)
{
$cache = $this->getCache();
@ -104,4 +99,9 @@ class Home extends AuthService
return "_PHCR_SESSION_:{$sessionId}";
}
protected function getAuthKey()
{
return 'home_auth_info';
}
}

View File

@ -38,10 +38,11 @@ class CourseList extends LogicService
$childCategoryIds = $categoryService->getChildCategoryIds($params['tc']);
/**
* 构造空记录条件
*/
$params['category_id'] = $childCategoryIds ?: -999;
$parentCategoryIds = [$params['tc']];
$allCategoryIds = array_merge($parentCategoryIds, $childCategoryIds);
$params['category_id'] = $allCategoryIds;
}
$params['published'] = 1;

View File

@ -12,12 +12,9 @@ use App\Exceptions\Forbidden as ForbiddenException;
use App\Library\Utils\Password as PasswordUtil;
use App\Library\Validators\Common as CommonValidator;
use App\Models\Account as AccountModel;
use App\Models\Client as ClientModel;
use App\Models\User as UserModel;
use App\Repos\Account as AccountRepo;
use App\Repos\User as UserRepo;
use App\Repos\UserSession as UserSessionRepo;
use App\Repos\UserToken as UserTokenRepo;
use App\Traits\Client as ClientTrait;
class Account extends Validator
@ -193,34 +190,6 @@ class Account extends Validator
if ($case1 && $case2) {
throw new ForbiddenException('account.locked');
}
$this->checkFloodLogin($user->id);
}
public function checkFloodLogin($userId)
{
$clientIp = $this->getClientIp();
$clientType = $this->getClientType();
if ($clientType == ClientModel::TYPE_PC) {
$repo = new UserSessionRepo();
$records = $repo->findUserRecentSessions($userId, 10);
} else {
$repo = new UserTokenRepo();
$records = $repo->findUserRecentTokens($userId, 10);
}
if ($records->count() == 0) return;
$clientIps = array_column($records->toArray(), 'client_ip');
$countValues = array_count_values($clientIps);
foreach ($countValues as $ip => $count) {
if ($clientIp == $ip && $count > 4) {
throw new ForbiddenException('account.flood_login');
}
}
}
}

View File

@ -33,9 +33,12 @@ class ConsoleErrorHandler extends Injectable
$config = $this->getConfig();
if ($config->get('env') == 'dev') {
$trace = sprintf('%sTrace Content: %s', PHP_EOL, $e->getTraceAsString());
if ($config->path('env') == 'dev' || $config->path('log.trace')) {
$trace = sprintf('Trace Content: %s', $e->getTraceAsString());
$logger->error($trace);
$content .= $trace;
}

View File

@ -77,8 +77,10 @@ class HttpErrorHandler extends Injectable
$config = $this->getConfig();
if ($config->get('env') == 'dev') {
if ($config->path('env') == 'dev' || $config->path('log.trace')) {
$content = sprintf('Trace Content: %s', $e->getTraceAsString());
$logger->error($content);
}
}

View File

@ -27,6 +27,11 @@ $config['timezone'] = 'Asia/Shanghai';
*/
$config['log']['level'] = Phalcon\Logger::INFO;
/**
* 日志链路
*/
$config['log']['trace'] = false;
/**
* 网站根地址,必须以"/"结尾
*/

View File

@ -47,7 +47,6 @@ $error['captcha.invalid_code'] = '无效的验证码';
*/
$error['account.not_found'] = '账号不存在';
$error['account.locked'] = '账号被锁定,无法登录';
$error['account.flood_login'] = '帐号泛滥登录';
$error['account.login_pwd_incorrect'] = '登录密码不正确';
$error['account.invalid_login_name'] = '无效的登录名';
$error['account.invalid_email'] = '无效的电子邮箱';

View File

@ -11,7 +11,7 @@ layui.use(['jquery', 'layer', 'helper'], function () {
var url = '/verify/captcha?type=all&account=' + $account.val();
layer.open({
type: 2,
title: '获取验证码',
title: '验证码',
area: ['500px', '250px'],
content: [url, 'no'],
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long