Skip to content

Commit fe319f1

Browse files
authored
Merge pull request 4x99#34 from 4x99/develop
v 1.1.0
2 parents 520ec40 + 7b0242f commit fe319f1

File tree

18 files changed

+425
-157
lines changed

18 files changed

+425
-157
lines changed

Dockerfile

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
FROM php:7.4-apache
2+
3+
EXPOSE 80
4+
5+
ENV MYSQL_HOST="172.17.0.1"
6+
ENV MYSQL_PORT="3306"
7+
ENV MYSQL_DATABASE="code6"
8+
ENV MYSQL_USERNAME=""
9+
ENV MYSQL_PASSWORD=""
10+
11+
# 复制代码
12+
COPY . /var/www/html
13+
WORKDIR /var/www/html
14+
15+
# 安装 PHP 扩展
16+
RUN docker-php-ext-install pdo_mysql
17+
18+
# 配置 Web 路径
19+
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
20+
RUN sed -ri -e "s!/var/www/html!${APACHE_DOCUMENT_ROOT}!g" /etc/apache2/sites-available/*.conf
21+
RUN sed -ri -e "s!/var/www/!${APACHE_DOCUMENT_ROOT}!g" /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
22+
23+
# 使用阿里镜像并安装包
24+
RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak
25+
RUN echo 'deb http://mirrors.aliyun.com/debian buster main' >> /etc/apt/sources.list
26+
RUN echo 'deb http://mirrors.aliyun.com/debian buster-updates main' >> /etc/apt/sources.list
27+
RUN apt-get update && apt-get install -y zip cron
28+
RUN rm -rf /var/lib/apt/lists/* && apt-get clean
29+
30+
# 安装 Composer 及项目依赖包
31+
RUN curl -O https://mirrors.aliyun.com/composer/composer.phar
32+
RUN chmod +x composer.phar
33+
RUN mv composer.phar /usr/local/bin/composer
34+
RUN composer config repo.packagist composer https://mirrors.aliyun.com/composer/
35+
RUN composer install --no-dev --optimize-autoloader
36+
37+
RUN chmod +x docker-entrypoint.sh
38+
ENTRYPOINT /bin/bash docker-entrypoint.sh

README.md

Lines changed: 5 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232

3333
---
3434

35+
## 安装部署
36+
码小六支持 [Docker 部署](doc/deploy-docker.md)[源码部署](doc/deploy-source.md),请根据情况选择!
37+
38+
---
39+
3540
## 系统界面
3641
请点击浏览大图 :P
3742

@@ -40,97 +45,3 @@
4045
![应用概况](https://raw.githubusercontent.com/4x99/snapshot/master/code6/home.png)
4146

4247
![扫描结果](https://raw.githubusercontent.com/4x99/snapshot/master/code6/code-leak.png)
43-
44-
---
45-
46-
## 安装指南
47-
48-
### 克隆代码
49-
```
50-
git clone https://github.com/4x99/code6.git <项目目录>
51-
```
52-
53-
### 配置 Apache
54-
请确保已开启 `mod_rewrite` 模块
55-
```
56-
<VirtualHost *:80>
57-
ServerName <ServerName>
58-
DocumentRoot "<项目目录>/public"
59-
</VirtualHost>
60-
```
61-
62-
### 下载依赖包
63-
安装 Composer:
64-
```
65-
curl -O https://mirrors.aliyun.com/composer/composer.phar
66-
chmod +x composer.phar
67-
mv composer.phar /usr/local/bin/composer
68-
```
69-
70-
配置阿里云镜像:
71-
```
72-
composer config repo.packagist composer https://mirrors.aliyun.com/composer/
73-
```
74-
75-
下载项目依赖包:
76-
```
77-
cd <项目目录> && composer install --no-dev --prefer-dist --optimize-autoloader
78-
```
79-
80-
### 项目配置
81-
设置目录权限:
82-
```
83-
chmod -R 755 storage
84-
chown -R <用户名>:<组名> storage
85-
```
86-
87-
创建配置文件:
88-
```
89-
cp .env.example .env
90-
```
91-
92-
生成应用密钥:
93-
```
94-
php artisan key:generate
95-
```
96-
97-
创建并配置数据库:
98-
```
99-
vim .env
100-
```
101-
```
102-
DB_CONNECTION=mysql
103-
DB_HOST=127.0.0.1
104-
DB_PORT=3306
105-
DB_DATABASE=
106-
DB_USERNAME=
107-
DB_PASSWORD=
108-
```
109-
110-
自动生成表结构:
111-
```
112-
php artisan migrate
113-
```
114-
115-
### 配置任务调度
116-
```
117-
crontab -e -u <用户>
118-
```
119-
120-
```
121-
* * * * * cd <项目目录> && php artisan schedule:run >> /dev/null 2>&1
122-
```
123-
124-
### 创建用户
125-
```
126-
php artisan code6:user-add <邮箱> <密码>
127-
```
128-
129-
如需查看用户列表或删除用户请执行:
130-
```
131-
php artisan code6:user-list
132-
php artisan code6:user-delete <邮箱>
133-
```
134-
135-
### 配置令牌与任务
136-
进入系统后请前往 `[ 令牌配置 ]``[ 任务配置 ]` 模块进行配置,配置完毕即可使用!

app/Console/Commands/JobRunCommand.php

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -72,24 +72,26 @@ public function handle()
7272
$this->log = Log::channel($this->signature);
7373
$this->log->info('Start job');
7474

75-
while ($job = $this->takeJob()) {
76-
if (!$this->service) {
77-
$this->createGitHubService();
78-
$this->whitelist = ConfigWhitelist::all()->keyBy('value');
79-
}
75+
if (!QueueJob::count()) {
76+
$this->log->info('The queue is empty');
77+
exit;
78+
}
79+
80+
$this->createGitHubService();
81+
$this->whitelist = ConfigWhitelist::all()->keyBy('value');
8082

83+
while ($job = $this->takeJob()) {
8184
$page = 1;
8285
$keyword = $job->keyword;
8386
$configJob = ConfigJob::where('keyword', $keyword)->first();
8487
$configJob->last_scan_at = date('Y-m-d H:i:s');
8588
do {
8689
$client = $this->service->getClient();
87-
$data = $this->searchCode($client, $keyword, $nextPage ?? null);
88-
$count = $this->store($data, $keyword);
90+
$data = $this->searchCode($client, $keyword, $page);
91+
$count = $this->store($data, $configJob);
8992
$this->log->info('Stored', ['keyword' => $keyword, 'page' => $page, 'count' => $count]);
9093
$lastResponse = ResponseMediator::getPagination($client->getLastResponse());
91-
$nextPage = $lastResponse['next'] ?? false;
92-
} while ($nextPage && (++$page <= $configJob->scan_page));
94+
} while ($lastResponse['next'] && (++$page <= $configJob->scan_page));
9395
$configJob->save();
9496
}
9597

@@ -117,7 +119,6 @@ private function createGitHubService()
117119
private function takeJob()
118120
{
119121
if (!$job = QueueJob::orderBy('created_at')->first()) {
120-
$this->log->info('The queue is empty');
121122
return false;
122123
}
123124
$job->delete();
@@ -129,17 +130,14 @@ private function takeJob()
129130
*
130131
* @param $client
131132
* @param $keyword
132-
* @param null $url
133+
* @param int $page
133134
* @return array|bool|string
134135
*/
135-
private function searchCode($client, $keyword, $url = null)
136+
private function searchCode($client, $keyword, $page = 1)
136137
{
137138
try {
138-
if ($url) { // 非首页
139-
return ResponseMediator::getContent($client->getHttpClient()->get($url));
140-
}
141139
$keyword = sprintf('"%s"', $keyword); // 精确匹配
142-
return $client->api('search')->code($keyword, 'indexed'); // 首页
140+
return $client->api('search')->setPage($page)->code($keyword, 'indexed');
143141
} catch (Exception $e) {
144142
$this->log->warning($e->getMessage());
145143
return false;
@@ -150,10 +148,10 @@ private function searchCode($client, $keyword, $url = null)
150148
* 保存数据
151149
*
152150
* @param $data
153-
* @param $keyword
154-
* @return array
151+
* @param $configJob
152+
* @return int[]
155153
*/
156-
private function store($data, $keyword)
154+
private function store($data, $configJob)
157155
{
158156
$count = ['leak' => 0, 'fragment' => 0];
159157

@@ -162,8 +160,8 @@ private function store($data, $keyword)
162160
}
163161

164162
foreach ($data['items'] as $item) {
165-
$item['keyword'] = $keyword;
166-
if (!$uuid = $this->storeLeak($item)) {
163+
$item['keyword'] = $configJob->keyword;
164+
if (!$uuid = $this->storeLeak($item, $configJob->store_type)) {
167165
continue;
168166
}
169167
$count['leak']++;
@@ -181,9 +179,10 @@ private function store($data, $keyword)
181179
* 保存代码泄露数据
182180
*
183181
* @param $item
182+
* @param $storeType
184183
* @return bool|string
185184
*/
186-
private function storeLeak($item)
185+
private function storeLeak($item, $storeType)
187186
{
188187
$repoOwner = $item['repository']['owner']['login'];
189188
$repoName = $item['repository']['name'];
@@ -200,10 +199,22 @@ private function storeLeak($item)
200199
}
201200

202201
// 数据入库
202+
$where = [];
203203
$uuid = md5("$repoOwner/$repoName/$blob/{$item['path']}");
204-
$leak = CodeLeak::firstOrCreate(
205-
['uuid' => $uuid],
206-
[
204+
switch ($storeType) {
205+
case configJob::STORE_TYPE_ALL:
206+
$where = ['uuid' => $uuid];
207+
break;
208+
case configJob::STORE_TYPE_FILE_STORE_ONCE:
209+
$where = ['repo_owner' => $repoOwner, 'repo_name' => $repoName, 'path' => $item['path']];
210+
break;
211+
case configJob::STORE_TYPE_REPO_STORE_ONCE:
212+
$where = ['repo_owner' => $repoOwner, 'repo_name' => $repoName];
213+
break;
214+
}
215+
216+
$leak = CodeLeak::firstOrCreate($where, [
217+
'uuid' => $uuid,
207218
'keyword' => $item['keyword'],
208219
'repo_owner' => $repoOwner,
209220
'repo_name' => $repoName,

app/Http/Controllers/ConfigJobController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public function index(Request $request)
2626
}
2727

2828
/**
29-
* 保存令牌
29+
* 保存任务
3030
*
3131
* @param Request $request
3232
* @return array
@@ -40,6 +40,7 @@ public function store(Request $request)
4040
[
4141
'scan_page' => $request->input('scan_page', 100),
4242
'scan_interval_min' => $request->input('scan_interval_min', 60),
43+
'store_type' => $request->input('store_type', 0),
4344
'description' => $request->input('description') ?? ''
4445
]
4546
);
@@ -63,7 +64,7 @@ public function update(Request $request, $id)
6364
{
6465
try {
6566
$request->validate(['keyword' => ['required', 'string', 'max:255']]);
66-
$fields = ['keyword', 'scan_page', 'scan_interval_min', 'description'];
67+
$fields = ['keyword', 'scan_page', 'scan_interval_min', 'store_type', 'description'];
6768
$configJob = ConfigJob::find($id);
6869
$success = $configJob->update($request->all($fields));
6970
return ['success' => $success, 'data' => $configJob];

app/Models/ConfigJob.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
class ConfigJob extends ModelBase
66
{
7+
const STORE_TYPE_ALL = 0;
8+
const STORE_TYPE_FILE_STORE_ONCE = 1;
9+
const STORE_TYPE_REPO_STORE_ONCE = 2;
710
protected $table = 'config_job';
8-
protected $fillable = ['keyword', 'scan_page', 'scan_interval_min', 'description'];
11+
protected $fillable = ['keyword', 'scan_page', 'scan_interval_min', 'store_type', 'description'];
912
}

config/logging.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
'daily' => [
4141
'driver' => 'daily',
42-
'path' => storage_path(sprintf('logs/%s.log', config('app.name'))),
42+
'path' => storage_path('logs/code6.log'),
4343
'level' => 'info',
4444
'days' => 7,
4545
],
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
class AddStoreTypeToConfigJobTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::table('config_job', function (Blueprint $table) {
17+
$table->tinyInteger('store_type')->unsigned()->after('scan_interval_min')->comment('0:All 1:File Store Once 2:Repo Store Once');
18+
});
19+
}
20+
21+
/**
22+
* Reverse the migrations.
23+
*
24+
* @return void
25+
*/
26+
public function down()
27+
{
28+
Schema::table('config_job', function (Blueprint $table) {
29+
$table->dropColumn('storage_type');
30+
});
31+
}
32+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
class AddIndexRepoOwnerAndRepoNameToCodeLeakTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::table('code_leak', function (Blueprint $table) {
17+
$table->index('repo_owner');
18+
$table->index('repo_name');
19+
});
20+
}
21+
22+
/**
23+
* Reverse the migrations.
24+
*
25+
* @return void
26+
*/
27+
public function down()
28+
{
29+
Schema::table('code_leak', function (Blueprint $table) {
30+
$table->dropIndex('code_leak_repo_owner_index');
31+
$table->dropIndex('code_leak_repo_name_index');
32+
});
33+
}
34+
}

0 commit comments

Comments
 (0)