From 3e837b5fec987464cbad14bc27d1c3a78067b78b Mon Sep 17 00:00:00 2001 From: luorijun Date: Sat, 26 Apr 2025 17:59:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E8=AE=A4=E8=AF=81=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=20introspect=20=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20.gitignore=20=E5=BF=BD=E7=95=A5=20scripts=20?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- README.md | 4 + scripts/dev/docker-compose.yaml | 24 - scripts/prev/docker-compose.yaml | 40 -- scripts/speed-tool/links.txt | 220 -------- scripts/speed-tool/speed.sh | 172 ------- scripts/sql/init.sql | 860 ------------------------------- web/auth/auth.go | 14 +- web/common/errors.go | 6 + web/handlers/auth.go | 29 +- web/handlers/user.go | 41 -- web/router.go | 20 +- web/services/session.go | 12 +- 13 files changed, 67 insertions(+), 1378 deletions(-) delete mode 100644 scripts/dev/docker-compose.yaml delete mode 100644 scripts/prev/docker-compose.yaml delete mode 100644 scripts/speed-tool/links.txt delete mode 100644 scripts/speed-tool/speed.sh delete mode 100644 scripts/sql/init.sql diff --git a/.gitignore b/.gitignore index 6c180c6..e355020 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ bin/ *.pem *.http -*/playground/ \ No newline at end of file +*/playground/ +scripts/ \ No newline at end of file diff --git a/README.md b/README.md index 2d2222b..b2eac58 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,10 @@ - [ ] Limiter - [ ] Compress +检查 device 权限验证,限制到特定于 web 客户端的权限 + +白名单限制可输入网段 + 废弃 password 授权模式,迁移到 authorization code 授权模式 使用 fiber 自带 validator 进行参数验证 diff --git a/scripts/dev/docker-compose.yaml b/scripts/dev/docker-compose.yaml deleted file mode 100644 index add8574..0000000 --- a/scripts/dev/docker-compose.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: platform-dev - -services: - - postgres: - image: postgres:17 - restart: always - environment: - POSTGRES_USER: ${DB_USERNAME} - POSTGRES_PASSWORD: ${DB_PASSWORD} - POSTGRES_DB: ${DB_NAME} - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - - redis: - image: redis:7.4 - restart: always - ports: - - "6379:6379" - -volumes: - postgres_data: diff --git a/scripts/prev/docker-compose.yaml b/scripts/prev/docker-compose.yaml deleted file mode 100644 index 6e59708..0000000 --- a/scripts/prev/docker-compose.yaml +++ /dev/null @@ -1,40 +0,0 @@ -name: platform-prev - -services: - - postgres: - image: postgres:17 - restart: always - environment: - POSTGRES_USER: ${DB_USERNAME} - POSTGRES_PASSWORD: ${DB_PASSWORD} - POSTGRES_DB: ${DB_NAME} - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - - redis: - image: redis:7.4 - restart: always - ports: - - "6379:6379" - command: redis-server --requirepass ${REDIS_PASS} - volumes: - - redis_data:/data - - platform: - build: - context: ../.. - dockerfile: Dockerfile - depends_on: - - postgres - - redis - ports: - - 8080:8080 - env_file: - - ../../.env - -volumes: - postgres_data: - redis_data: diff --git a/scripts/speed-tool/links.txt b/scripts/speed-tool/links.txt deleted file mode 100644 index 4168fce..0000000 --- a/scripts/speed-tool/links.txt +++ /dev/null @@ -1,220 +0,0 @@ -110.40.82.248|10000|bx8365|242469 -110.40.82.248|10001|eu9328|493237 -110.40.82.248|10002|tn6479|247579 -110.40.82.248|10003|yx8657|232695 -110.40.82.248|10004|ru8396|776448 -110.40.82.248|10005|hk2957|897393 -110.40.82.248|10006|fk5569|979277 -110.40.82.248|10007|nn8859|622638 -110.40.82.248|10008|kf4546|927798 -110.40.82.248|10009|xd3275|763356 -110.40.82.248|10010|jj3257|343429 -110.40.82.248|10011|jg2356|944246 -110.40.82.248|10012|nc8746|545784 -110.40.82.248|10013|vu8328|763628 -110.40.82.248|10014|cn2486|725339 -110.40.82.248|10015|sn7499|959423 -110.40.82.248|10016|am3336|995524 -110.40.82.248|10017|tv2487|756939 -110.40.82.248|10018|af3324|395465 -110.40.82.248|10019|jr3978|279833 -110.40.82.248|10020|cd8436|463733 -110.40.82.248|10021|cx5686|926872 -110.40.82.248|10022|gy7228|769775 -110.40.82.248|10023|kk5434|494548 -110.40.82.248|10024|fs8824|573884 -110.40.82.248|10025|ta3545|994543 -110.40.82.248|10026|nu6993|346966 -110.40.82.248|10027|qm6599|797659 -110.40.82.248|10028|ag3955|322752 -110.40.82.248|10029|rp5937|553687 -110.40.82.248|10030|qx5558|967645 -110.40.82.248|10031|bt4494|426495 -110.40.82.248|10032|ng6876|235567 -110.40.82.248|10033|un6855|386394 -110.40.82.248|10034|yu8965|377993 -110.40.82.248|10035|cc5532|366957 -110.40.82.248|10036|mc8998|388652 -110.40.82.248|10037|hy9866|953847 -110.40.82.248|10038|zy3654|677364 -110.40.82.248|10039|bw7278|573267 -110.40.82.248|10040|cu9527|985595 -110.40.82.248|10041|pg9832|843382 -110.40.82.248|10042|qm3297|899273 -110.40.82.248|10043|gs7356|282863 -110.40.82.248|10044|gm7877|432425 -110.40.82.248|10045|hm4697|758247 -110.40.82.248|10046|tf9359|633623 -110.40.82.248|10047|wb8726|863766 -110.40.82.248|10048|ah2743|878986 -110.40.82.248|10049|pq3996|363742 -110.40.82.248|10050|nn3345|632583 -110.40.82.248|10051|sc5535|673946 -110.40.82.248|10052|rm3356|357357 -110.40.82.248|10053|je4855|682973 -110.40.82.248|10054|mk9733|697479 -110.40.82.248|10055|zk5548|394528 -110.40.82.248|10056|et7965|793473 -110.40.82.248|10057|xt9423|898449 -110.40.82.248|10058|qa5527|645327 -110.40.82.248|10059|um2688|289728 -110.40.82.248|10060|nk5828|242476 -110.40.82.248|10061|yx9554|856994 -110.40.82.248|10062|ns4939|759352 -110.40.82.248|10063|vb7485|874824 -110.40.82.248|10064|zb2372|528727 -110.40.82.248|10065|ar6253|955428 -110.40.82.248|10066|fr9365|642756 -110.40.82.248|10067|zd2644|943294 -110.40.82.248|10068|hs4394|675892 -110.40.82.248|10069|sh2332|489286 -110.40.82.248|10070|cd5293|634294 -110.40.82.248|10071|gn6398|839753 -110.40.82.248|10072|fc4557|664265 -110.40.82.248|10073|ay3762|247893 -110.40.82.248|10074|ka2877|796724 -110.40.82.248|10075|du8626|278792 -110.40.82.248|10076|wq4238|569397 -110.40.82.248|10077|ug4962|992737 -110.40.82.248|10078|cn4882|642566 -110.40.82.248|10079|tq6329|377375 -110.40.82.248|10080|dp9622|765854 -110.40.82.248|10081|kr8825|849629 -110.40.82.248|10082|uk9472|869689 -110.40.82.248|10083|hm3646|892348 -110.40.82.248|10084|bg9252|497243 -110.40.82.248|10085|uh6946|739494 -110.40.82.248|10086|rg5298|587796 -110.40.82.248|10087|tj7977|726453 -110.40.82.248|10088|ze3987|222244 -110.40.82.248|10089|em8588|227953 -110.40.82.248|10090|tr6446|679972 -110.40.82.248|10091|gk8868|298239 -110.40.82.248|10092|ut3822|668853 -110.40.82.248|10093|pm6427|672442 -110.40.82.248|10094|gb2833|755822 -110.40.82.248|10095|zm6949|369698 -110.40.82.248|10096|xq2658|852574 -110.40.82.248|10097|qe8839|464228 -110.40.82.248|10098|fp2923|937235 -110.40.82.248|10099|xc6925|999539 -110.40.82.248|10100|wa8574|732452 -110.40.82.248|10101|yx8465|375486 -110.40.82.248|10102|ww5494|739866 -110.40.82.248|10103|jr7442|567485 -110.40.82.248|10104|sd6985|959745 -110.40.82.248|10105|xb2244|595966 -110.40.82.248|10106|yn7857|372255 -110.40.82.248|10107|vw4566|538227 -110.40.82.248|10108|pv4723|686467 -110.40.82.248|10109|hu8226|222586 -110.40.82.248|10110|zr6555|863735 -110.40.82.248|10111|rw9996|565957 -110.40.82.248|10112|fb4287|549768 -110.40.82.248|10113|av8488|877575 -110.40.82.248|10114|xv2597|747758 -110.40.82.248|10115|bv6832|434947 -110.40.82.248|10116|zx3462|674699 -110.40.82.248|10117|et4423|272678 -110.40.82.248|10118|mr6542|974889 -110.40.82.248|10119|df4937|259752 -110.40.82.248|10120|rb5549|483455 -110.40.82.248|10121|pf6353|588782 -110.40.82.248|10122|gp2463|979239 -110.40.82.248|10123|zn4727|939486 -110.40.82.248|10124|nc8972|223754 -110.40.82.248|10125|uc6742|568289 -110.40.82.248|10126|wf5342|225866 -110.40.82.248|10127|pk6252|767436 -110.40.82.248|10128|kg4699|665633 -110.40.82.248|10129|rr4552|433777 -110.40.82.248|10130|bb4524|465625 -110.40.82.248|10131|tj6876|789928 -110.40.82.248|10132|je6786|579265 -110.40.82.248|10133|jd2567|679592 -110.40.82.248|10134|ay5885|592344 -110.40.82.248|10135|xt3862|866283 -110.40.82.248|10136|nb7497|683947 -110.40.82.248|10137|nx2353|256249 -110.40.82.248|10138|qv7433|664945 -110.40.82.248|10139|py2642|833672 -110.40.82.248|10140|ap2489|568855 -110.40.82.248|10141|td8773|266242 -110.40.82.248|10142|xw2452|593488 -110.40.82.248|10143|ff5337|954543 -110.40.82.248|10144|tz9987|963433 -110.40.82.248|10145|fb8376|985273 -110.40.82.248|10146|su2894|323982 -110.40.82.248|10147|nb7495|823237 -110.40.82.248|10148|yg2564|592488 -110.40.82.248|10149|kn9899|227429 -110.40.82.248|10150|cg4848|684686 -110.40.82.248|10151|tn2256|249727 -110.40.82.248|10152|ej3365|335369 -110.40.82.248|10153|gx4888|279465 -110.40.82.248|10154|hx7765|876632 -110.40.82.248|10155|fm7674|254868 -110.40.82.248|10156|cv7899|724934 -110.40.82.248|10157|za7794|492886 -110.40.82.248|10158|es6893|452285 -110.40.82.248|10159|wt6853|675724 -110.40.82.248|10160|av6876|758346 -110.40.82.248|10161|mx7959|885764 -110.40.82.248|10162|dy6887|388742 -110.40.82.248|10163|nj8722|754387 -110.40.82.248|10164|hc9946|863228 -110.40.82.248|10165|qz9557|235287 -110.40.82.248|10166|ge3847|927394 -110.40.82.248|10167|cy8372|767252 -110.40.82.248|10168|jj7654|982787 -110.40.82.248|10169|zk8335|959346 -110.40.82.248|10170|xn5586|639796 -110.40.82.248|10171|ad6755|374686 -110.40.82.248|10172|ks4839|489756 -110.40.82.248|10173|yc9737|546796 -110.40.82.248|10174|aq2328|853237 -110.40.82.248|10175|wg7776|358652 -110.40.82.248|10176|px4656|596576 -110.40.82.248|10177|xs2728|453736 -110.40.82.248|10178|gy4535|876755 -110.40.82.248|10179|gb5937|723928 -110.40.82.248|10180|pr2285|748893 -110.40.82.248|10181|xd9847|336452 -110.40.82.248|10182|td9655|785479 -110.40.82.248|10183|rd4335|634744 -110.40.82.248|10184|zx5458|674622 -110.40.82.248|10185|xq8773|253948 -110.40.82.248|10186|cs2696|496264 -110.40.82.248|10187|at6665|653586 -110.40.82.248|10188|eq7974|549797 -110.40.82.248|10189|ty9272|772364 -110.40.82.248|10190|tc2559|569529 -110.40.82.248|10191|vq7798|855826 -110.40.82.248|10192|xa4844|942872 -110.40.82.248|10193|gy5679|996892 -110.40.82.248|10194|xx7573|242397 -110.40.82.248|10195|sg5662|545365 -110.40.82.248|10196|be3787|924628 -110.40.82.248|10197|pz6235|278446 -110.40.82.248|10198|rh9632|349377 -110.40.82.248|10199|xr2236|446398 -110.40.82.248|10200|gf7455|288766 -110.40.82.248|10201|yy5269|687478 -110.40.82.248|10202|am7328|282833 -110.40.82.248|10203|nh5229|759947 -110.40.82.248|10204|hm5592|674869 -110.40.82.248|10205|zj5449|622724 -110.40.82.248|10206|uv8246|773676 -110.40.82.248|10207|yv4955|253927 -110.40.82.248|10208|er6533|932487 -110.40.82.248|10209|ab8686|938948 -110.40.82.248|10210|cu8395|495276 -110.40.82.248|10211|nx8453|822793 -110.40.82.248|10212|xv3389|885536 -110.40.82.248|10213|yj9724|798479 -110.40.82.248|10214|uz7896|435885 -110.40.82.248|10215|hm9372|243792 -110.40.82.248|10216|he7489|387683 -110.40.82.248|10217|aw8368|956565 -110.40.82.248|10218|cf4883|976237 -110.40.82.248|10219|ur6422|388325 \ No newline at end of file diff --git a/scripts/speed-tool/speed.sh b/scripts/speed-tool/speed.sh deleted file mode 100644 index 9c46d64..0000000 --- a/scripts/speed-tool/speed.sh +++ /dev/null @@ -1,172 +0,0 @@ -#!/bin/bash - -# 检查是否提供了URL参数 -if [ $# -eq 0 ]; then - echo "使用方法: $0 <要测试的URL>" - exit 1 -fi - -TARGET_URL="$1" -LINKS_FILE="$(dirname "$0")/links.txt" -HIGH_LATENCY_THRESHOLD=400 # 高延迟阈值,修改为400毫秒 -TIMEOUT=10 # curl 超时时间,单位秒 -MAX_RETRIES=1 # 失败重试次数 - -# 检查links.txt文件是否存在 -if [ ! -f "$LINKS_FILE" ]; then - echo "错误: $LINKS_FILE 文件不存在" - exit 1 -fi - -echo "开始测试代理速度,目标URL: $TARGET_URL" -echo "--------------------------------------" - -# 初始化变量 -total_latency=0 -count=0 -success_count=0 -fail_count=0 -retry_success_count=0 -high_latency_proxies="" -failed_proxies="" - -# 读取并测试每个代理 -while IFS='|' read -r ip port username password || [ -n "$ip" ]; do - # 跳过空行和注释行 - [[ -z "$ip" || "$ip" =~ ^# ]] && continue - - # 去除可能的空白字符 - ip=$(echo "$ip" | tr -d '[:space:]') - port=$(echo "$port" | tr -d '[:space:]') - username=$(echo "$username" | tr -d '[:space:]') - password=$(echo "$password" | tr -d '[:space:]') - - proxy_url="http://$username:$password@$ip:$port" - echo -n "测试代理: $ip:$port ... " - - # 测试逻辑封装成函数以便重试 - test_proxy() { - local start_time=$(date +%s%N) - local response=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout $TIMEOUT --max-time $TIMEOUT -x "$proxy_url" "$TARGET_URL" 2>/dev/null) - local end_time=$(date +%s%N) - local latency=0 - - if [ "$response" = "200" ]; then - latency=$(( (end_time - start_time) / 1000000 )) - echo "$response $latency" - else - echo "$response 0" - fi - } - - # 第一次尝试 - count=$((count + 1)) - result=$(test_proxy) - response=$(echo $result | cut -d ' ' -f 1) - latency=$(echo $result | cut -d ' ' -f 2) - - # 判断是否需要重试 - if [ "$response" != "200" ]; then - echo -n "失败 - HTTP状态码: $response,正在重试... " - - # 重试 - result=$(test_proxy) - response=$(echo $result | cut -d ' ' -f 1) - latency=$(echo $result | cut -d ' ' -f 2) - - if [ "$response" = "200" ]; then - retry_success_count=$((retry_success_count + 1)) - fi - fi - - # 处理最终结果 - if [ "$response" = "200" ]; then - echo "成功 - 延迟: ${latency}ms" - - # 累加总延迟 - total_latency=$((total_latency + latency)) - success_count=$((success_count + 1)) - - # 检查是否为高延迟代理 - if [ $latency -gt $HIGH_LATENCY_THRESHOLD ]; then - high_latency_proxies="${high_latency_proxies}$ip:$port (${latency}ms)\n" - fi - else - echo "最终失败 - HTTP状态码: $response" - fail_count=$((fail_count + 1)) - failed_proxies="${failed_proxies}$ip:$port (状态码: $response)\n" - fi -done < "$LINKS_FILE" - -echo "--------------------------------------" - -# 输出统计结果 -echo "测试结果汇总:" -echo "总测试代理数量: $count" -echo "成功代理数量: $success_count (含重试成功: $retry_success_count)" -echo "失败代理数量: $fail_count" -echo "成功率: $(( success_count * 100 / count ))%" - -if [ $success_count -gt 0 ]; then - average_latency=$(( total_latency / success_count )) - echo "平均延迟: ${average_latency}ms" - - if [ -n "$high_latency_proxies" ]; then - echo -e "\n高延迟代理 (>${HIGH_LATENCY_THRESHOLD}ms):" - echo -e "$high_latency_proxies" - else - echo -e "\n没有发现高延迟代理。" - fi -fi - -if [ -n "$failed_proxies" ]; then - echo -e "\n连接失败的代理:" - echo -e "$failed_proxies" -fi - -# 输出延迟分布情况 -if [ $success_count -gt 0 ]; then - echo -e "\n延迟分布统计:" - # 重新统计以生成延迟分布 - low_latency=0 # <100ms - medium_latency=0 # 100-200ms - high_latency=0 # 200-400ms - very_high_latency=0 # >400ms - - while IFS='|' read -r ip port username password || [ -n "$ip" ]; do - # 跳过空行和注释行 - [[ -z "$ip" || "$ip" =~ ^# ]] && continue - - # 去除可能的空白字符 - ip=$(echo "$ip" | tr -d '[:space:]') - port=$(echo "$port" | tr -d '[:space:]') - username=$(echo "$username" | tr -d '[:space:]') - password=$(echo "$password" | tr -d '[:space:]') - - proxy_url="http://$username:$password@$ip:$port" - - # 只测量一次以获取延迟数据,不进行重试统计 - start_time=$(date +%s%N) - response=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout $TIMEOUT --max-time $TIMEOUT -x "$proxy_url" "$TARGET_URL" 2>/dev/null) - end_time=$(date +%s%N) - - if [ "$response" = "200" ]; then - latency=$(( (end_time - start_time) / 1000000 )) - - if [ $latency -lt 100 ]; then - low_latency=$((low_latency + 1)) - elif [ $latency -lt 200 ]; then - medium_latency=$((medium_latency + 1)) - elif [ $latency -lt 400 ]; then - high_latency=$((high_latency + 1)) - else - very_high_latency=$((very_high_latency + 1)) - fi - fi - done < "$LINKS_FILE" - - echo " < 100ms: $low_latency ($(( low_latency * 100 / success_count ))%)" - echo "100-200ms: $medium_latency ($(( medium_latency * 100 / success_count ))%)" - echo "200-400ms: $high_latency ($(( high_latency * 100 / success_count ))%)" - echo " > 400ms: $very_high_latency ($(( very_high_latency * 100 / success_count ))%)" -fi diff --git a/scripts/sql/init.sql b/scripts/sql/init.sql deleted file mode 100644 index 0e49b4d..0000000 --- a/scripts/sql/init.sql +++ /dev/null @@ -1,860 +0,0 @@ --- 清空数据表 -do -$$ - declare - r record; - begin - for r in ( - select - tablename - from - pg_tables - where - schemaname = 'public' - ) loop - execute 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; - end loop; - end -$$; - --- ==================== --- region 管理员信息 --- ==================== - --- admin -drop table if exists admin cascade; -create table admin ( - id serial primary key, - username varchar(255) not null unique, - password varchar(255) not null, - name varchar(255), - avatar varchar(255), - phone varchar(255), - email varchar(255), - status int not null default 1, - last_login timestamp, - last_login_host varchar(45), - last_login_agent varchar(255), - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index admin_status_index on admin (status); -create index admin_deleted_at_index on admin (deleted_at); - --- admin表字段注释 -comment on table admin is '管理员表'; -comment on column admin.id is '管理员ID'; -comment on column admin.username is '用户名'; -comment on column admin.password is '密码'; -comment on column admin.name is '真实姓名'; -comment on column admin.avatar is '头像URL'; -comment on column admin.phone is '手机号码'; -comment on column admin.email is '邮箱'; -comment on column admin.status is '状态:1-正常,0-禁用'; -comment on column admin.last_login is '最后登录时间'; -comment on column admin.last_login_host is '最后登录地址'; -comment on column admin.last_login_agent is '最后登录代理'; -comment on column admin.created_at is '创建时间'; -comment on column admin.updated_at is '更新时间'; -comment on column admin.deleted_at is '删除时间'; - --- admin_role -drop table if exists admin_role cascade; -create table admin_role ( - id serial primary key, - name varchar(255) not null unique, - description varchar(255), - active bool default true, - sort int default 0, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index admin_role_deleted_at_index on admin_role (deleted_at); - --- admin_role表字段注释 -comment on table admin_role is '管理员角色关联表'; -comment on column admin_role.id is '管理员角色ID'; -comment on column admin_role.name is '角色名称'; -comment on column admin_role.description is '角色描述'; -comment on column admin_role.active is '是否激活'; -comment on column admin_role.sort is '排序'; -comment on column admin_role.created_at is '创建时间'; -comment on column admin_role.updated_at is '更新时间'; -comment on column admin_role.deleted_at is '删除时间'; - --- endregion - --- ==================== --- region 用户信息 --- ==================== - --- user -drop table if exists "user" cascade; -create table "user" ( - id serial primary key, - admin_id int references admin (id) -- - on update cascade -- - on delete set null, - phone varchar(255) not null unique, - username varchar(255), - email varchar(255), - password varchar(255), - name varchar(255), - avatar varchar(255), - status int not null default 1, - balance decimal(12, 2) not null default 0, - id_type int not null default 0, - id_no varchar(255), - id_token varchar(255), - contact_qq varchar(255), - contact_wechat varchar(255), - last_login timestamp, - last_login_host varchar(45), - last_login_agent varchar(255), - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index user_admin_id_index on "user" (admin_id); -create index user_username_index on "user" (username); -create index user_email_index on "user" (email); -create index user_status_index on "user" (status); -create index user_deleted_at_index on "user" (deleted_at); - --- user表字段注释 -comment on table "user" is '用户表'; -comment on column "user".id is '用户ID'; -comment on column "user".admin_id is '管理员ID'; -comment on column "user".password is '用户密码'; -comment on column "user".username is '用户名'; -comment on column "user".phone is '手机号码'; -comment on column "user".name is '真实姓名'; -comment on column "user".avatar is '头像URL'; -comment on column "user".status is '用户状态:1-正常,0-禁用'; -comment on column "user".balance is '账户余额'; -comment on column "user".id_type is '认证类型:0-未认证,1-个人认证,2-企业认证'; -comment on column "user".id_no is '身份证号或营业执照号'; -comment on column "user".id_token is '身份验证标识'; -comment on column "user".contact_qq is 'QQ联系方式'; -comment on column "user".contact_wechat is '微信联系方式'; -comment on column "user".last_login is '最后登录时间'; -comment on column "user".last_login_host is '最后登录地址'; -comment on column "user".last_login_agent is '最后登录代理'; -comment on column "user".created_at is '创建时间'; -comment on column "user".updated_at is '更新时间'; -comment on column "user".deleted_at is '删除时间'; - --- user_role -drop table if exists user_role cascade; -create table user_role ( - id serial primary key, - name varchar(255) not null unique, - description varchar(255), - active bool default true, - sort int default 0, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index user_role_deleted_at_index on user_role (deleted_at); - --- user_role表字段注释 -comment on table user_role is '用户角色表'; -comment on column user_role.id is '角色ID'; -comment on column user_role.name is '角色名称'; -comment on column user_role.description is '角色描述'; -comment on column user_role.active is '是否激活'; -comment on column user_role.sort is '排序'; -comment on column user_role.created_at is '创建时间'; -comment on column user_role.updated_at is '更新时间'; -comment on column user_role.deleted_at is '删除时间'; - --- endregion - --- ==================== --- region 客户端信息 --- ==================== - -drop table if exists client cascade; -create table client ( - id serial primary key, - client_id varchar(255) not null unique, - client_secret varchar(255) not null, - redirect_uri varchar(255), - grant_code bool not null default false, - grant_client bool not null default false, - grant_refresh bool not null default false, - grant_password bool not null default false, - spec int not null, - name varchar(255) not null, - icon varchar(255), - status int not null default 1, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); - -create index client_client_id_index on client (client_id); -create index client_name_index on client (name); -create index client_status_index on client (status); -create index client_deleted_at_index on client (deleted_at); - --- client表字段注释 -comment on table client is '客户端表'; -comment on column client.id is '客户端ID'; -comment on column client.client_id is 'OAuth2客户端标识符'; -comment on column client.client_secret is 'OAuth2客户端密钥'; -comment on column client.redirect_uri is 'OAuth2 重定向URI'; -comment on column client.grant_code is '允许授权码授予'; -comment on column client.grant_client is '允许客户端凭证授予'; -comment on column client.grant_refresh is '允许刷新令牌授予'; -comment on column client.grant_password is '允许密码授予'; -comment on column client.spec is '安全规范:0-web,1-native,2-browser'; -comment on column client.name is '名称'; -comment on column client.icon is '图标URL'; -comment on column client.status is '状态:1-正常,0-禁用'; -comment on column client.created_at is '创建时间'; -comment on column client.updated_at is '更新时间'; -comment on column client.deleted_at is '删除时间'; - --- endregion - --- ==================== --- region 权限信息 --- ==================== - --- permission -drop table if exists permission cascade; -create table permission ( - id serial primary key, - parent_id int references permission (id) - on update cascade - on delete cascade, - name varchar(255) not null unique, - description varchar(255), - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index permission_parent_id_index on permission (parent_id); -create index permission_name_index on permission (name); -create index permission_deleted_at_index on permission (deleted_at); - --- permission表字段注释 -comment on table permission is '权限表'; -comment on column permission.id is '权限ID'; -comment on column permission.parent_id is '父权限ID'; -comment on column permission.name is '权限名称'; -comment on column permission.description is '权限描述'; -comment on column permission.created_at is '创建时间'; -comment on column permission.updated_at is '更新时间'; -comment on column permission.deleted_at is '删除时间'; - --- user_role_link -drop table if exists user_role_link cascade; -create table user_role_link ( - id serial primary key, - user_id int not null references "user" (id) - on update cascade - on delete cascade, - role_id int not null references user_role (id) - on update cascade - on delete cascade, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index user_role_link_user_id_index on user_role_link (user_id); -create index user_role_link_role_id_index on user_role_link (role_id); -create index user_role_link_deleted_at_index on user_role_link (deleted_at); - --- user_role_link表字段注释 -comment on table user_role_link is '用户角色关联表'; -comment on column user_role_link.id is '关联ID'; -comment on column user_role_link.user_id is '用户ID'; -comment on column user_role_link.role_id is '角色ID'; -comment on column user_role_link.created_at is '创建时间'; -comment on column user_role_link.updated_at is '更新时间'; -comment on column user_role_link.deleted_at is '删除时间'; - --- admin_role_link -drop table if exists admin_role_link cascade; -create table admin_role_link ( - id serial primary key, - admin_id int not null references admin (id) - on update cascade - on delete cascade, - role_id int not null references admin_role (id) - on update cascade - on delete cascade, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index admin_role_link_admin_id_index on admin_role_link (admin_id); -create index admin_role_link_role_id_index on admin_role_link (role_id); -create index admin_role_link_deleted_at_index on admin_role_link (deleted_at); - --- admin_role_link表字段注释 -comment on table admin_role_link is '管理员角色关联表'; -comment on column admin_role_link.id is '关联ID'; -comment on column admin_role_link.admin_id is '管理员ID'; -comment on column admin_role_link.role_id is '角色ID'; -comment on column admin_role_link.created_at is '创建时间'; -comment on column admin_role_link.updated_at is '更新时间'; -comment on column admin_role_link.deleted_at is '删除时间'; - --- user_role_permission_link -drop table if exists user_role_permission_link cascade; -create table user_role_permission_link ( - id serial primary key, - role_id int not null references user_role (id) - on update cascade - on delete cascade, - permission_id int not null references permission (id) - on update cascade - on delete cascade, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index user_role_permission_link_role_id_index on user_role_permission_link (role_id); -create index user_role_permission_link_permission_id_index on user_role_permission_link (permission_id); -create index user_role_permission_link_deleted_at_index on user_role_permission_link (deleted_at); - --- user_role_permission_link表字段注释 -comment on table user_role_permission_link is '用户角色权限关联表'; -comment on column user_role_permission_link.id is '关联ID'; -comment on column user_role_permission_link.role_id is '角色ID'; -comment on column user_role_permission_link.permission_id is '权限ID'; -comment on column user_role_permission_link.created_at is '创建时间'; -comment on column user_role_permission_link.updated_at is '更新时间'; -comment on column user_role_permission_link.deleted_at is '删除时间'; - --- admin_role_permission_link -drop table if exists admin_role_permission_link cascade; -create table admin_role_permission_link ( - id serial primary key, - role_id int not null references admin_role (id) - on update cascade - on delete cascade, - permission_id int not null references permission (id) - on update cascade - on delete cascade, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index admin_role_permission_link_role_id_index on admin_role_permission_link (role_id); -create index admin_role_permission_link_permission_id_index on admin_role_permission_link (permission_id); -create index admin_role_permission_link_deleted_at_index on admin_role_permission_link (deleted_at); - --- admin_role_permission_link表字段注释 -comment on table admin_role_permission_link is '管理员角色权限关联表'; -comment on column admin_role_permission_link.id is '关联ID'; -comment on column admin_role_permission_link.role_id is '角色ID'; -comment on column admin_role_permission_link.permission_id is '权限ID'; -comment on column admin_role_permission_link.created_at is '创建时间'; -comment on column admin_role_permission_link.updated_at is '更新时间'; -comment on column admin_role_permission_link.deleted_at is '删除时间'; - --- client_permission_link -drop table if exists client_permission_link cascade; -create table client_permission_link ( - id serial primary key, - client_id int not null references client (id) - on update cascade - on delete cascade, - permission_id int not null references permission (id) - on update cascade - on delete cascade, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index client_permission_link_client_id_index on client_permission_link (client_id); -create index client_permission_link_permission_id_index on client_permission_link (permission_id); -create index client_permission_link_deleted_at_index on client_permission_link (deleted_at); - --- client_permission_link表字段注释 -comment on table client_permission_link is '客户端权限关联表'; -comment on column client_permission_link.id is '关联ID'; -comment on column client_permission_link.client_id is '客户端ID'; -comment on column client_permission_link.permission_id is '权限ID'; -comment on column client_permission_link.created_at is '创建时间'; -comment on column client_permission_link.updated_at is '更新时间'; -comment on column client_permission_link.deleted_at is '删除时间'; - --- endregion - --- ==================== --- region 节点信息 --- ==================== - --- proxy -drop table if exists proxy cascade; -create table proxy ( - id serial primary key, - version int not null, - name varchar(255) not null unique, - host varchar(255) not null, - type int not null default 0, - secret varchar(255), - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index proxy_name_index on proxy (name); -create index proxy_host_index on proxy (host); -create index proxy_deleted_at_index on proxy (deleted_at); - --- proxy表字段注释 -comment on table proxy is '代理服务表'; -comment on column proxy.id is '代理服务ID'; -comment on column proxy.version is '代理服务版本'; -comment on column proxy.name is '代理服务名称'; -comment on column proxy.host is '代理服务地址'; -comment on column proxy.type is '代理服务类型:0-自有,1-三方'; -comment on column proxy.secret is '代理服务密钥'; -comment on column proxy.created_at is '创建时间'; -comment on column proxy.updated_at is '更新时间'; -comment on column proxy.deleted_at is '删除时间'; - --- node -drop table if exists node cascade; -create table node ( - id serial primary key, - proxy_id int references proxy (id) - on update cascade - on delete cascade, - version int not null, - name varchar(255) not null unique, - host varchar(255) not null, - isp int not null, - prov varchar(255) not null, - city varchar(255) not null, - proxy_port int, - status int not null default 0, - rtt int default 0, - loss int default 0, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index node_isp_index on node (isp); -create index node_prov_index on node (prov); -create index node_city_index on node (city); -create index node_proxy_id_index on node (proxy_id); -create index node_deleted_at_index on node (deleted_at); - --- node表字段注释 -comment on table node is '节点表'; -comment on column node.id is '节点ID'; -comment on column node.version is '节点版本'; -comment on column node.name is '节点名称'; -comment on column node.host is '节点地址'; -comment on column node.isp is '运营商:0-其他,1-电信,2-联通,3-移动'; -comment on column node.prov is '省份'; -comment on column node.city is '城市'; -comment on column node.proxy_id is '代理ID'; -comment on column node.proxy_port is '代理端口'; -comment on column node.status is '节点状态:0-离线,1-正常'; -comment on column node.rtt is '延迟'; -comment on column node.loss is '丢包率'; -comment on column node.created_at is '创建时间'; -comment on column node.updated_at is '更新时间'; -comment on column node.deleted_at is '删除时间'; - --- whitelist -drop table if exists whitelist cascade; -create table whitelist ( - id serial primary key, - user_id int not null references "user" (id) - on update cascade - on delete cascade, - host varchar(45) not null, - remark varchar(255), - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index whitelist_user_id_index on whitelist (user_id); -create index whitelist_host_index on whitelist (host); -create index whitelist_deleted_at_index on whitelist (deleted_at); - --- whitelist表字段注释 -comment on table whitelist is '白名单表'; -comment on column whitelist.id is '白名单ID'; -comment on column whitelist.user_id is '用户ID'; -comment on column whitelist.host is 'IP地址'; -comment on column whitelist.remark is '备注'; -comment on column whitelist.created_at is '创建时间'; -comment on column whitelist.updated_at is '更新时间'; -comment on column whitelist.deleted_at is '删除时间'; - --- channel -drop table if exists channel cascade; -create table channel ( - id serial primary key, - user_id int not null references "user" (id) - on update cascade - on delete cascade, - proxy_id int not null references proxy (id) -- - on update cascade -- - on delete set null, - node_id int references node (id) -- - on update cascade -- - on delete set null, - proxy_host varchar(255) not null default '', - proxy_port int not null, - node_host varchar(255), - protocol int, - auth_ip bool not null default false, - user_host varchar(255), - auth_pass bool not null default false, - username varchar(255), - password varchar(255), - expiration timestamp not null, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index channel_user_id_index on channel (user_id); -create index channel_proxy_id_index on channel (proxy_id); -create index channel_node_id_index on channel (node_id); -create index channel_proxy_host_index on channel (proxy_host); -create index channel_proxy_port_index on channel (proxy_port); -create index channel_node_host_index on channel (node_host); -create index channel_auth_ip_index on channel (auth_ip); -create index channel_user_host_index on channel (user_host); -create index channel_auth_pass_index on channel (auth_pass); -create index channel_username_index on channel (username); -create index channel_expiration_index on channel (expiration); -create index channel_deleted_at_index on channel (deleted_at); - --- channel表字段注释 -comment on table channel is '通道表'; -comment on column channel.id is '通道ID'; -comment on column channel.user_id is '用户ID'; -comment on column channel.proxy_id is '代理ID'; -comment on column channel.node_id is '节点ID'; -comment on column channel.user_host is '用户地址'; -comment on column channel.proxy_port is '转发端口'; -comment on column channel.node_host is '节点地址'; -comment on column channel.auth_ip is 'IP认证'; -comment on column channel.auth_pass is '密码认证'; -comment on column channel.protocol is '协议类型:1-http,2-https,3-socks5'; -comment on column channel.username is '用户名'; -comment on column channel.password is '密码'; -comment on column channel.expiration is '过期时间'; -comment on column channel.created_at is '创建时间'; -comment on column channel.updated_at is '更新时间'; -comment on column channel.deleted_at is '删除时间'; - --- endregion - --- ==================== --- region 产品信息 --- ==================== - --- product -drop table if exists product cascade; -create table product ( - id serial primary key, - code varchar(255) not null unique, - name varchar(255) not null, - description varchar(255), - sort int not null default 0, - status int not null default 1, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index product_deleted_at_index on product (deleted_at); - --- product表字段注释 -comment on table product is '产品表'; -comment on column product.id is '产品ID'; -comment on column product.code is '产品代码'; -comment on column product.name is '产品名称'; -comment on column product.description is '产品描述'; -comment on column product.sort is '排序'; -comment on column product.status is '产品状态:1-正常,0-禁用'; -comment on column product.created_at is '创建时间'; -comment on column product.updated_at is '更新时间'; -comment on column product.deleted_at is '删除时间'; - --- resource -drop table if exists resource cascade; -create table resource ( - id serial primary key, - user_id int not null references "user" (id) - on update cascade - on delete cascade, - resource_no varchar(255) unique, - active bool not null default true, - type int not null, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index resource_user_id_index on resource (user_id); -create index resource_resource_no_index on resource (resource_no); -create index resource_active_index on resource (active); -create index resource_type_index on resource (type); -create index resource_deleted_at_index on resource (deleted_at); - --- resource表字段注释 -comment on table resource is '套餐表'; -comment on column resource.id is '套餐ID'; -comment on column resource.user_id is '用户ID'; -comment on column resource.resource_no is '套餐编号'; -comment on column resource.active is '套餐状态'; -comment on column resource.type is '套餐类型:1-动态,2-隧道,3-独享'; -comment on column resource.created_at is '创建时间'; -comment on column resource.updated_at is '更新时间'; -comment on column resource.deleted_at is '删除时间'; - --- resource_pss -drop table if exists resource_pss cascade; -create table resource_pss ( - id serial primary key, - resource_id int not null references resource (id) - on update cascade - on delete cascade, - type int, - live int, - expire timestamp, - quota int, - used int not null default 0, - daily_limit int not null default 0, - daily_used int not null default 0, - daily_last timestamp -); -create index resource_pss_resource_id_index on resource_pss (resource_id); - --- resource_pss表字段注释 -comment on table resource_pss is '动态代理套餐表'; -comment on column resource_pss.id is 'ID'; -comment on column resource_pss.resource_id is '套餐ID'; -comment on column resource_pss.type is '套餐类型:1-包时,2-包量'; -comment on column resource_pss.live is '可用时长(秒)'; -comment on column resource_pss.quota is '配额数量'; -comment on column resource_pss.used is '已用数量'; -comment on column resource_pss.expire is '过期时间'; -comment on column resource_pss.daily_limit is '每日限制'; -comment on column resource_pss.daily_used is '今日已用数量'; -comment on column resource_pss.daily_last is '今日最后使用时间'; - --- resource_psr -drop table if exists resource_psr cascade; -create table resource_psr ( - id serial primary key, - resource_id int not null references resource (id) - on update cascade - on delete cascade, - live int, - conn int, - expire timestamp, - used bool -); -create index resource_psr_resource_id_index on resource_psr (resource_id); - --- resource_psr表字段注释 -comment on table resource_psr is '隧道代理套餐表'; -comment on column resource_psr.id is 'ID'; -comment on column resource_psr.resource_id is '套餐ID'; -comment on column resource_psr.live is '轮换周期(秒)'; -comment on column resource_psr.conn is '最大连接数'; -comment on column resource_psr.expire is '过期时间'; -comment on column resource_psr.used is '是否已使用'; - --- resource_pps -drop table if exists resource_pps cascade; -create table resource_pps ( - id serial primary key, - resource_id int not null references resource (id) - on update cascade - on delete cascade -); -create index resource_pps_resource_id_index on resource_pps (resource_id); - --- resource_pps表字段注释 -comment on table resource_pps is '独享代理套餐表'; -comment on column resource_pps.id is 'ID'; -comment on column resource_pps.resource_id is '套餐ID'; - --- endregion - --- ==================== --- region 订单信息 --- ==================== - --- trade -drop table if exists trade cascade; -create table trade ( - id serial primary key, - user_id int not null references "user" (id) - on update cascade - on delete cascade, - inner_no varchar(255) not null unique, - outer_no varchar(255), - type int not null, - subject varchar(255) not null, - remark varchar(255), - amount decimal(12, 2) not null default 0, - payment decimal(12, 2) not null default 0, - method int not null, - status int not null default 0, - pay_url text, - paid_at timestamp, - cancel_at timestamp, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index trade_user_id_index on trade (user_id); -create index trade_outer_no_index on trade (outer_no); -create index trade_type_index on trade (type); -create index trade_status_index on trade (status); -create index trade_deleted_at_index on trade (deleted_at); - --- trade表字段注释 -comment on table trade is '订单表'; -comment on column trade.id is '订单ID'; -comment on column trade.user_id is '用户ID'; -comment on column trade.inner_no is '内部订单号'; -comment on column trade.outer_no is '外部订单号'; -comment on column trade.type is '订单类型:0-充值余额,1-购买产品'; -comment on column trade.subject is '订单主题'; -comment on column trade.remark is '订单备注'; -comment on column trade.amount is '订单总金额'; -comment on column trade.payment is '支付金额'; -comment on column trade.method is '支付方式:1-支付宝,2-微信'; -comment on column trade.status is '订单状态:0-待支付,1-已支付,2-已取消,3-已退款'; -comment on column trade.pay_url is '支付链接'; -comment on column trade.paid_at is '支付时间'; -comment on column trade.cancel_at is '取消时间'; -comment on column trade.created_at is '创建时间'; -comment on column trade.updated_at is '更新时间'; -comment on column trade.deleted_at is '删除时间'; - --- refund -drop table if exists refund cascade; -create table refund ( - id serial primary key, - trade_id int not null references trade (id) - on update cascade - on delete cascade, - product_id int references product (id) -- - on update cascade -- - on delete set null, - amount decimal(12, 2) not null default 0, - reason varchar(255), - status int not null default 0, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index refund_trade_id_index on refund (trade_id); -create index refund_product_id_index on refund (product_id); -create index refund_deleted_at_index on refund (deleted_at); - --- refund表字段注释 -comment on table refund is '退款记录表'; -comment on column refund.id is '退款ID'; -comment on column refund.trade_id is '订单ID'; -comment on column refund.product_id is '产品ID'; -comment on column refund.amount is '退款金额'; -comment on column refund.reason is '退款原因'; -comment on column refund.status is '退款状态:0-待处理,1-已退款,2-已拒绝'; -comment on column refund.created_at is '创建时间'; -comment on column refund.updated_at is '更新时间'; -comment on column refund.deleted_at is '删除时间'; - --- bill -drop table if exists bill cascade; -create table bill ( - id serial primary key, - user_id int not null references "user" (id) - on update cascade - on delete cascade, - trade_id int references trade (id) -- - on update cascade -- - on delete set null, - resource_id int references resource (id) -- - on update cascade -- - on delete set null, - refund_id int references refund (id) -- - on update cascade -- - on delete set null, - bill_no varchar(255) not null unique, - info varchar(255), - type int not null, - amount decimal(12, 2) not null default 0, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index bill_user_id_index on bill (user_id); -create index bill_trade_id_index on bill (trade_id); -create index bill_resource_id_index on bill (resource_id); -create index bill_refund_id_index on bill (refund_id); -create index bill_bill_no_index on bill (bill_no); -create index bill_type_index on bill (type); -create index bill_deleted_at_index on bill (deleted_at); - --- bill表字段注释 -comment on table bill is '账单表'; -comment on column bill.id is '账单ID'; -comment on column bill.user_id is '用户ID'; -comment on column bill.trade_id is '订单ID'; -comment on column bill.resource_id is '套餐ID'; -comment on column bill.refund_id is '退款ID'; -comment on column bill.bill_no is '易读账单号'; -comment on column bill.info is '产品可读信息'; -comment on column bill.type is '账单类型:0-充值,1-消费,2-退款'; -comment on column bill.amount is '账单金额'; -comment on column bill.created_at is '创建时间'; -comment on column bill.updated_at is '更新时间'; -comment on column bill.deleted_at is '删除时间'; - --- coupon 优惠券 -drop table if exists coupon cascade; -create table coupon ( - id serial primary key, - user_id int references "user" (id) - on update cascade - on delete cascade, - code varchar(255) not null unique, - remark varchar(255), - amount decimal(12, 2) not null default 0, - min_amount decimal(12, 2) not null default 0, - status int not null default 0, - expire_at timestamp, - created_at timestamp default current_timestamp, - updated_at timestamp default current_timestamp, - deleted_at timestamp -); -create index coupon_user_id_index on coupon (user_id); -create index coupon_code_index on coupon (code); -create index coupon_status_index on coupon (status); -create index coupon_deleted_at_index on coupon (deleted_at); - --- coupon表字段注释 -comment on table coupon is '优惠券表'; -comment on column coupon.id is '优惠券ID'; -comment on column coupon.user_id is '用户ID'; -comment on column coupon.code is '优惠券代码'; -comment on column coupon.remark is '优惠券备注'; -comment on column coupon.amount is '优惠券金额'; -comment on column coupon.min_amount is '最低消费金额'; -comment on column coupon.status is '优惠券状态:0-未使用,1-已使用,2-已过期'; -comment on column coupon.expire_at is '过期时间'; -comment on column coupon.created_at is '创建时间'; -comment on column coupon.updated_at is '更新时间'; -comment on column coupon.deleted_at is '删除时间'; - --- endregion \ No newline at end of file diff --git a/web/auth/auth.go b/web/auth/auth.go index 7770d5a..2a1c996 100644 --- a/web/auth/auth.go +++ b/web/auth/auth.go @@ -111,18 +111,24 @@ func Protect(c *fiber.Ctx, types []services.PayloadType, permissions []string) ( var auth *services.AuthContext var err error switch split[0] { + case "Bearer": auth, err = authBearer(c.Context(), token) + if err != nil { + return nil, fiber.NewError(fiber.StatusUnauthorized, "没有权限") + } + case "Basic": if !slices.Contains(types, services.PayloadClientConfidential) { return nil, fiber.NewError(fiber.StatusForbidden, "没有权限") } auth, err = authBasic(c.Context(), token) + if err != nil { + return nil, fiber.NewError(fiber.StatusUnauthorized, "没有权限") + } + default: - return nil, fiber.NewError(fiber.StatusUnauthorized, "没有权限") - } - if err != nil { - return nil, fiber.NewError(fiber.StatusUnauthorized, "没有权限") + return nil, fiber.NewError(fiber.StatusForbidden, "没有权限") } // 检查权限 diff --git a/web/common/errors.go b/web/common/errors.go index 6bd3752..ae89428 100644 --- a/web/common/errors.go +++ b/web/common/errors.go @@ -11,3 +11,9 @@ type AuthForbiddenErr string func (e AuthForbiddenErr) Error() string { return string(e) } + +type DataErr string + +func (e DataErr) Error() string { + return string(e) +} diff --git a/web/handlers/auth.go b/web/handlers/auth.go index b7e23be..9851105 100644 --- a/web/handlers/auth.go +++ b/web/handlers/auth.go @@ -268,7 +268,7 @@ type RevokeReq struct { } func Revoke(c *fiber.Ctx) error { - _, err := auth.Protect(c, []s.PayloadType{s.PayloadUser}, []string{}) + _, err := auth.Protect(c, []s.PayloadType{s.PayloadClientConfidential}, []string{}) if err != nil { // 用户未登录 return nil @@ -290,3 +290,30 @@ func Revoke(c *fiber.Ctx) error { } // endregion + +// region /profile + +type IntrospectResp struct { + m.User +} + +func Introspect(c *fiber.Ctx) error { + // 验证权限 + authCtx, err := auth.Protect(c, []s.PayloadType{s.PayloadUser}, []string{}) + if err != nil { + return err + } + + // 获取用户信息 + profile, err := q.User. + Where(q.User.ID.Eq(authCtx.Payload.Id)). + Omit(q.User.Password, q.User.DeletedAt). + Take() + if err != nil { + return err + } + + return c.JSON(IntrospectResp{*profile}) +} + +// endregion diff --git a/web/handlers/user.go b/web/handlers/user.go index 87609f9..66472ea 100644 --- a/web/handlers/user.go +++ b/web/handlers/user.go @@ -1,7 +1,6 @@ package handlers import ( - "errors" "platform/web/auth" q "platform/web/queries" s "platform/web/services" @@ -9,48 +8,8 @@ import ( "time" "github.com/gofiber/fiber/v2" - "gorm.io/gorm" ) -// region GetUserByToken - -type GetUserByTokenReq struct { - Token string `json:"token" validate:"required"` -} - -// GetUserByToken 通过token获取用户信息 -func GetUserByToken(c *fiber.Ctx) error { - - // 解析请求参数 - req := new(GetUserByTokenReq) - if err := c.BodyParser(req); err != nil { - return err - } - - // 查询会话信息 - session, err := s.Session.Find(c.Context(), req.Token) - if err != nil { - return err - } - - // 查询用户信息 - user, err := q.User.Debug(). - Omit(q.User.Password, q.User.DeletedAt). - Where(q.User.ID.Eq(session.Payload.Id)). - Take() - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return fiber.NewError(fiber.StatusNotFound, "用户不存在") - } - return err - } - - // 返回用户信息 - return c.JSON(user) -} - -// endregion - // region recharge type RechargePrepareReq struct { diff --git a/web/router.go b/web/router.go index 07ff5c2..321df4e 100644 --- a/web/router.go +++ b/web/router.go @@ -14,8 +14,18 @@ func ApplyRouters(app *fiber.App) { auth := api.Group("/auth") auth.Post("/token", handlers.Token) auth.Post("/revoke", handlers.Revoke) + auth.Post("/introspect", handlers.Introspect) auth.Post("/verify/sms", handlers.SmsCode) + // 用户 + user := api.Group("/user") + user.Post("/identify", handlers.Identify) + user.Post("/identify/callback", handlers.IdentifyCallback) + user.Post("/recharge/prepare/alipay", handlers.RechargePrepareAlipay) + user.Post("/recharge/confirm/alipay", handlers.RechargeConfirmAlipay) + user.Post("/recharge/prepare/wechat", handlers.RechargePrepareWechat) + user.Post("/recharge/confirm/wechat", handlers.RechargeConfirmWechat) + // 通道 channel := api.Group("/channel") channel.Post("/create", handlers.CreateChannel) @@ -38,16 +48,6 @@ func ApplyRouters(app *fiber.App) { resource.Post("/prepare/wechat", handlers.PrepareResourceByWechat) resource.Post("/create/wechat", handlers.CreateResourceByWechat) - // 用户 - user := api.Group("/user") - user.Post("/get/token", handlers.GetUserByToken) - user.Post("/identify", handlers.Identify) - user.Post("/identify/callback", handlers.IdentifyCallback) - user.Post("/recharge/prepare/alipay", handlers.RechargePrepareAlipay) - user.Post("/recharge/confirm/alipay", handlers.RechargeConfirmAlipay) - user.Post("/recharge/prepare/wechat", handlers.RechargePrepareWechat) - user.Post("/recharge/confirm/wechat", handlers.RechargeConfirmWechat) - // 账单 bill := api.Group("/bill") bill.Post("/list", handlers.ListBill) diff --git a/web/services/session.go b/web/services/session.go index 166167b..3c6bda0 100644 --- a/web/services/session.go +++ b/web/services/session.go @@ -134,11 +134,6 @@ func (s *sessionService) Refresh(ctx context.Context, refreshToken string, confi return err } - // 删除旧的令牌 - pipeline := tx.Pipeline() - pipeline.Del(ctx, accessKey(refreshData.AccessToken)) - pipeline.Del(ctx, refreshKey(refreshToken)) - // 生成新的令牌 newAccessToken := genToken() newRefreshToken := genToken() @@ -155,9 +150,16 @@ func (s *sessionService) Refresh(ctx context.Context, refreshToken string, confi return err } + pipeline := tx.Pipeline() + + // 保存新的令牌 pipeline.Set(ctx, accessKey(newAccessToken), authData, cfg.AccessTokenDuration) pipeline.Set(ctx, refreshKey(newRefreshToken), newRefreshData, cfg.RefreshTokenDuration) + // 删除旧的令牌 + pipeline.Del(ctx, accessKey(refreshData.AccessToken)) + pipeline.Del(ctx, refreshKey(refreshToken)) + _, err = pipeline.Exec(ctx) if err != nil { return err