liuyuqi-dellpc 2 months ago
parent
commit
ae24102b22

+ 27 - 0
.dockerignore

@@ -0,0 +1,27 @@
+**/__pycache__
+**/.venv
+**/.classpath
+**/.dockerignore
+**/.env
+**/.git
+**/.gitignore
+**/.project
+**/.settings
+**/.toolstarget
+**/.vs
+**/.vscode
+**/*.*proj.user
+**/*.dbmdl
+**/*.jfm
+**/bin
+**/charts
+**/docker-compose*
+**/compose*
+**/Dockerfile*
+**/node_modules
+**/npm-debug.log
+**/obj
+**/secrets.dev.yaml
+**/values.dev.yaml
+LICENSE
+README.md

+ 19 - 0
.vscode/launch.json

@@ -0,0 +1,19 @@
+{
+    "configurations": [
+        {
+            "name": "Docker: Python - Flask",
+            "type": "docker",
+            "request": "launch",
+            "preLaunchTask": "docker-run: debug",
+            "python": {
+                "pathMappings": [
+                    {
+                        "localRoot": "${workspaceFolder}",
+                        "remoteRoot": "/app"
+                    }
+                ],
+                "projectType": "flask"
+            }
+        }
+    ]
+}

+ 40 - 0
.vscode/tasks.json

@@ -0,0 +1,40 @@
+{
+	"version": "2.0.0",
+	"tasks": [
+		{
+			"type": "docker-build",
+			"label": "docker-build",
+			"platform": "python",
+			"dockerBuild": {
+				"tag": "setgithubsecret:latest",
+				"dockerfile": "${workspaceFolder}/Dockerfile",
+				"context": "${workspaceFolder}",
+				"pull": true
+			}
+		},
+		{
+			"type": "docker-run",
+			"label": "docker-run: debug",
+			"dependsOn": [
+				"docker-build"
+			],
+			"dockerRun": {
+				"env": {
+					"FLASK_APP": "web\\app.py"
+				}
+			},
+			"python": {
+				"args": [
+					"run",
+					"--no-debugger",
+					"--no-reload",
+					"--host",
+					"0.0.0.0",
+					"--port",
+					"5002"
+				],
+				"module": "flask"
+			}
+		}
+	]
+}

BIN
favicon.ico


+ 14 - 0
gui/main.py

@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+"""
+@Contact :   liuyuqi.gov@msn.cn
+@Time    :   2024/07/26
+@License :   Copyright © 2017-2022 liuyuqi. All Rights Reserved.
+@Desc    :   enter point
+"""
+
+import os,sys,logging
+
+
+if __name__=='__main__':
+    pass

+ 36 - 0
setup.py

@@ -0,0 +1,36 @@
+from setuptools import setup, find_packages
+import os, codecs
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+with codecs.open(os.path.join(here, "README.md"), encoding="utf-8") as f:
+    long_description = "\n" + f.read()
+with open("requirements.txt") as f:
+    install_requires = f.read().splitlines()
+
+version = ""
+
+setup(
+    name="set_github_secret",
+    version="1.0.1",
+    author="liuyuqi.gov@msn.cn",
+    description="set github secret",
+    long_description=long_description,
+    long_description_content_type="text/markdown",
+    packages=find_packages(),
+    package_data={"data": ["*.txt", "*.rst", "*.md"]},
+    include_package_data=True,
+    install_requires=install_requires,
+    zip_safe=False,
+    entry_points={
+        "console_scripts": ["run=apps:run"],
+    },
+    url="",
+    project_urls={},
+    keywords=[
+        "flask",
+    ],
+    classifiers=[
+        "Development Status :: 1 - Planning",
+    ],
+)

+ 27 - 0
web/.env

@@ -0,0 +1,27 @@
+DEBUG=True
+HOST = 0.0.0.0
+PORT = 8080
+
+# Flask ENV
+FLASK_APP=app.py
+FLASK_CONFIG=development
+# If not provided, a random one is generated 
+# 密钥配置
+SECRET_KEY='一定要修改!!!'
+
+# Used for CDN (in production)
+ASSETS_ROOT=/static/assets
+
+# If DEBUG=True sqlite, else mysql
+DB_ENGINE=sqlite
+DB_NAME=appseed_db
+DB_HOST=localhost
+DB_PORT=3306
+DB_USERNAME=appseed_db_usr
+DB_PASS=<STRONG_PASS>
+
+# 邮箱配置
+MAIL_SERVER='smtp.qq.com'
+MAIL_USERNAME='123@qq.com'
+MAIL_PASSWORD='XXXXX' # 生成的授权码
+MAIL_PORT=465

+ 25 - 0
web/Dockerfile

@@ -0,0 +1,25 @@
+# For more information, please refer to https://aka.ms/vscode-docker-python
+FROM python:3-slim
+
+EXPOSE 5002
+
+# Keeps Python from generating .pyc files in the container
+ENV PYTHONDONTWRITEBYTECODE=1
+
+# Turns off buffering for easier container logging
+ENV PYTHONUNBUFFERED=1
+
+# Install pip requirements
+COPY requirements.txt .
+RUN python -m pip install -r requirements.txt
+
+WORKDIR /app
+COPY . /app
+
+# Creates a non-root user with an explicit UID and adds permission to access the /app folder
+# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
+RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
+USER appuser
+
+# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
+CMD ["gunicorn", "--bind", "0.0.0.0:5002", "web.app:app"]

+ 25 - 0
web/app.py

@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+"""
+@Contact :   liuyuqi.gov@msn.cn
+@Time    :   2024/07/26
+@License :   Copyright © 2017-2022 liuyuqi. All Rights Reserved.
+@Desc    :   enter point
+"""
+
+if __name__=='__main__':
+    from dotenv import load_dotenv
+    import os
+
+    if os.path.exists('.env'):
+        load_dotenv('.env')
+    _host = os.getenv("HOST")  if os.getenv("HOST") is not None else "0.0.0.0"
+    _port =os.getenv("PORT") if os.getenv("PORT") is not None else "8080"
+    _debug=os.getenv("DEBUG") if os.getenv("DEBUG") is not None else True
+    if _debug:
+        app.run(host=_host, port=_port, debug=_debug)
+    else :
+        import uvicorn
+        from asgiref.wsgi import WsgiToAsgi
+        asgi_app = WsgiToAsgi(app)
+        uvicorn.run(asgi_app, host=_host, port=_port,)

+ 105 - 0
web/apps/__init__.py

@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+"""
+@Contact :   liuyuqi.gov@msn.cn
+@Time    :   2023/10/04 11:09:00
+@License :   Copyright © 2017-2022 liuyuqi. All Rights Reserved.
+@Desc    :   None
+"""
+
+from flask import Flask, render_template
+from flask_cors import CORS
+from apps.config import config
+from .extensions import init_extensions, init_docs
+from .script import init_script
+from .views import init_blueprints
+import os
+
+
+def create_app(config_name="default") -> Flask:
+    """ 创建 flask app
+    :param config_name: 配置名称, 可选值: development, production, default
+    :return: flask app
+    """
+    # banner()
+    config_name = os.getenv("FLASK_CONFIG") or config_name
+    app = Flask(config[config_name].BASE_DIR)
+    CORS(app, supports_credentials=True, resources={r"/api/*": {"origins": "*"}})
+
+    app.config.from_object(config[config_name])  # 读取配置
+    config[config_name].init_app(app)
+
+    init_extensions(app)
+
+    init_blueprints(app)
+    
+    init_hook(app)
+
+    configure_error_handlers(app)
+
+    init_script(app)
+
+    # pirnt all route
+    # with app.test_request_context():
+    #     for rule in app.url_map.iter_rules():
+    #         print(rule, "---------------")
+
+    return app
+
+
+def configure_error_handlers(app: Flask):
+    @app.errorhandler(403)
+    def forbidden_page(error):
+        # return "Oops! You don't have permission to access this page.", 403
+        return render_template("errors/403.html"), 403
+
+    @app.errorhandler(404)
+    def page_not_found(error):
+        # return jsonify({
+        #     'code': 404,
+        #     'msg': 'Oops! Page Not Found'
+        # }), 404
+        return render_template("errors/404.html"), 404
+
+    @app.errorhandler(500)
+    def server_error_page(error):
+        # return "Oops! Internal server error. Please try after sometime.", 500
+        return render_template("errors/500.html"), 500
+
+        # @app.context_processor
+        # def context_processor():
+        """ 上下文处理 """
+        # if hasattr(g,"  user"):
+        #     return {"user": g.user}
+        # else:
+        #     return {"user": None}
+        # pass
+
+
+def init_hook(app: Flask):
+    @app.after_request
+    def after_request(response):
+        return response
+
+    @app.before_request
+    def before_request():
+        # user_id = session.get("user_id")
+        # if user_id:
+        #     try:
+        #         user = Users.query.get(user_id)
+        #         g.user = user
+        #     except Exception as e:
+        #         print(e)
+        #         g.user = None
+        pass
+
+
+def banner():
+    Version = "V 1.0\n"
+    info = "\t\t\t\t\t\t\t 阿sir,我真的是卧底 | By liuyuqi.gov@msn.cn | {}".format(Version)
+    banner1 = """
+                4444444444444444444
+    {}""".format(
+        info
+    )
+    print(banner1)

+ 0 - 0
web/apps/common/__init__.py


+ 199 - 0
web/apps/config.py

@@ -0,0 +1,199 @@
+import os
+import random
+import string
+import logging
+from datetime import timedelta
+from dotenv import load_dotenv
+
+
+if os.path.exists(".env"):
+    load_dotenv(".env", verbose=True)
+
+class BaseConfig:
+    """基础配置"""
+
+    # persist_directory = os.environ.get('PERSIST_DIRECTORY')
+    # CG_TOKEN = os.getenv("CHATGPT_TOKEN", "your-chatgpt-token")
+    SUPERADMIN = "admin"
+    SYSTEM_NAME = "Pear Admin"
+    # 主题面板的链接列表配置
+    SYSTEM_PANEL_LINKS = [
+        {
+            "icon": "layui-icon layui-icon-auz",
+            "title": "官方网站",
+            "href": "http://www.pearadmin.com",
+        },
+        {
+            "icon": "layui-icon layui-icon-auz",
+            "title": "开发文档",
+            "href": "http://www.pearadmin.com",
+        },
+        {
+            "icon": "layui-icon layui-icon-auz",
+            "title": "开源地址",
+            "href": "https://gitee.com/Jmysy/Pear-Admin-Layui",
+        },
+    ]
+    ASSETS_ROOT = os.getenv("ASSETS_ROOT", "/static/assets")
+    STATIC_URL = "/static/"
+    SECRET_KEY = os.getenv("SECRET_KEY", None)
+    if not SECRET_KEY:
+        SECRET_KEY = "".join(random.choice(string.ascii_lowercase) for i in range(32))
+
+    # base
+    PROJECT_NAME = "flask_blog"
+    # 当前 config.py 文件目录
+    DEBUG = False
+    # 当前文件所在目录的绝对路径 /apps
+    BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
+    BASE_URL = "http://"
+    ADMIN_EMAILS = ""
+
+    # 分页
+    POST_PER_PAGE = 8  # 每页文章数
+    COMMENT_PER_PAGE = 10  # 每页评论数
+
+    LANGUAGE_CODE = "zh-hans"
+    TIME_ZONE = "PRC"
+
+    UP_DIR = os.path.join(
+        os.path.abspath(os.path.dirname(__file__)), "app/static/uploads/"
+    )  # 文件上传路径
+    FC_DIR = os.path.join(
+        os.path.abspath(os.path.dirname(__file__)), "app/static/uploads/users/"
+    )  # 用户头像上传路径
+    UPLOADED_PHOTOS_DEST = "static/upload"
+    UPLOADED_FILES_ALLOW = ["gif", "jpg"]
+    UPLOADS_AUTOSERVE = True
+    JSON_AS_ASCII = False
+
+    # db
+    SQLALCHEMY_TRACK_MODIFICATIONS = False
+    DB_ENGINE = os.getenv("DB_ENGINE", None)
+    DB_USERNAME = os.getenv("DB_USERNAME", None)
+    DB_PASS = os.getenv("DB_PASS", None)
+    DB_HOST = os.getenv("DB_HOST", None)
+    DB_PORT = os.getenv("DB_PORT", None)
+    DB_NAME = os.getenv("DB_NAME", None)
+    USE_SQLITE = True
+
+    # MSSQL:    f"mssql+pymssql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=cp936"
+    # MySQL:    f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
+    # Oracle:   f"oracle+cx_oracle://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}"
+    # SQLite    "sqlite:/// database.db"
+    # Postgres f"postgresql+psycopg2://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}"
+    # Oracle的第二种连接方式
+    # dsnStr = cx_Oracle.makedsn({HOSTNAME}, 1521, service_name='orcl')
+    # connect_str = "oracle://%s:%s@%s" % ('{USERNAME}', ' {PASSWORD}', dsnStr)
+
+    #  在SQLALCHEMY_BINDS 中设置:'{数据库连接别名}': '{连接串}'
+    # 最后在models的数据模型class中,在__tablename__前设置        __bind_key__ = '{数据库连接别名}'  即可,表示该数据模型不使用默认的数据库连接,改用“SQLALCHEMY_BINDS”中设置的其他数据库连接
+    #  SQLALCHEMY_BINDS = {
+    #    'testMySQL': 'mysql+pymysql://test:123456@192.168.1.1:3306/test?charset=utf8',
+    #    'testMsSQL': 'mssql+pymssql://test:123456@192.168.1.1:1433/test?charset=cp936',
+    #    'testOracle': 'oracle+cx_oracle://test:123456@192.168.1.1:1521/test',
+    #    'testSQLite': 'sqlite:///database.db
+    # }
+    # if DB_ENGINE and DB_NAME and DB_USERNAME:
+    #     try:
+    #         # Relational DBMS: PSQL, MySql
+    #         SQLALCHEMY_DATABASE_URI = '{}://{}:{}@{}:{}/{}'.format(
+    #             DB_ENGINE,
+    #             DB_USERNAME,
+    #             DB_PASS,
+    #             DB_HOST,
+    #             DB_PORT,
+    #             DB_NAME
+    #         )
+    #         USE_SQLITE  = False
+    #     except Exception as e:
+    #         print('> Error: DBMS Exception: ' + str(e) )
+    #         print('> Fallback to SQLite ')
+    # if USE_SQLITE:
+    #     # This will create a file in <app> FOLDER
+    #     SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'db.sqlite3')
+
+    # redis
+    REDIS_HOST = os.getenv("REDIS_HOST", "localhost")
+    REDIS_PORT = os.getenv("REDIS_PORT", 6379)
+    REDIS_DB = os.getenv("REDIS_DB", 0)
+    REDIS_PASSWORD = os.getenv("REDIS_PASSWORD", None)
+    CELERY_BROKER_URL = "redis://{}:{}/{}".format(REDIS_HOST, REDIS_PORT, REDIS_DB)
+
+    # mail
+    MAIL_SERVER = os.getenv("MAIL_SERVER", "smtp.qq.com")
+    MAIL_PORT = os.getenv("MAIL_PORT", 465)
+    MAIL_USE_TLS = False
+    MAIL_USE_SSL = True
+    MAIL_DEBUG = True
+    MAIL_USERNAME = os.getenv("MAIL_USERNAME", None)
+    MAIL_PASSWORD = os.getenv("MAIL_PASSWORD", None)  # 生成的授权码
+    MAIL_DEFAULT_SENDER = MAIL_USERNAME
+
+    # token配置
+    TIMEOUT_TOKEN = 10 * 24 * 60 * 60
+    TIMEOUT_EMAIL = 10 * 60
+
+    PERMANENT_SESSION_LIFETIME = timedelta(hours=2)
+
+    # log
+    LOG_LEVEL = logging.WARN
+
+    # 插件配置,填写插件的文件名名称,默认不启用插件。
+    PLUGIN_ENABLE_FOLDERS = []
+
+    # 七牛云
+    QINIU_ACCESS_KEY = os.getenv("QINIU_ACCESS_KEY", None)
+    QINIU_SECRET_KEY = os.getenv("QINIU_SECRET_KEY", None)
+    QINIU_BUCKET_NAME = os.getenv("QINIU_BUCKET_NAME", None)
+
+    # github
+    GITHUB_CLIENT_ID = os.getenv("GITHUB_CLIENT_ID", None)
+    GITHUB_CLIENT_SECRET = os.getenv("GITHUB_CLIENT_SECRET", None)
+    if GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET:
+        SOCIAL_AUTH_GITHUB = True
+
+    @staticmethod
+    def init_app(app):
+        pass
+
+
+class DevelopmentConfig(BaseConfig):
+    """开发环境配置, 开启调试模式, 使用 sqlite"""
+
+    DEBUG = True
+    SQLALCHEMY_TRACK_MODIFICATIONS = True
+    # SQLALCHEMY_ECHO = True
+    # SQLALCHEMY_COMMIT_ON_TEARDOWN = True
+    SQLALCHEMY_DATABASE_URI = "sqlite:///../flask-note.sqlite3.db"
+
+
+class TestingConfig(BaseConfig):
+    DEBUG = True
+
+
+class ProductionConfig(BaseConfig):
+    DEBUG = False
+    SQLALCHEMY_DATABASE_URI = (
+        "mysql+pymysql://lyq:123456@ok.yoqi.me:13306/travel?charset=utf8"
+    )
+
+    # DB_ENGINE   = os.getenv('DB_ENGINE'   , None)
+    # DB_USERNAME = os.getenv('DB_USERNAME' , None)
+    # DB_PASS     = os.getenv('DB_PASS'     , None)
+    # DB_HOST     = os.getenv('DB_HOST'     , None)
+    # DB_PORT     = os.getenv('DB_PORT'     , None)
+    # DB_NAME     = os.getenv('DB_NAME'     , None)
+
+    # Security
+    SESSION_COOKIE_HTTPONLY = True
+    REMEMBER_COOKIE_HTTPONLY = True
+    REMEMBER_COOKIE_DURATION = 3600
+
+
+config = {
+    "default": DevelopmentConfig,
+    "development": DevelopmentConfig,  # 开发环境配置, 开启调试模式, 使用 sqlite
+    # "testing": TestingConfig,
+    "production": ProductionConfig,
+}

+ 0 - 0
web/apps/extensions/__init__.py


+ 0 - 0
web/apps/models/__init__.py


+ 0 - 0
web/apps/script/__init__.py


+ 0 - 0
web/apps/utils/__init__.py


+ 0 - 0
web/apps/views/__init__.py


+ 19 - 0
web/docker-compose.debug.yml

@@ -0,0 +1,19 @@
+version: '3.4'
+
+services:
+  setgithubsecret:
+    image: jianboy/setgithubsecret:latest
+    build:
+      context: .
+      dockerfile: ./Dockerfile
+    command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 -m flask run --no-debugger --no-reload --host 0.0.0.0 --port 5002"]
+    ports:
+      - 5002:5002
+    environment:
+      - FLASK_APP=web\app.py
+      - FLASK_DEBUG=1
+    volumes:
+      - .:/app
+
+networks:
+  default:

+ 18 - 0
web/docker-compose.yml

@@ -0,0 +1,18 @@
+version: '3.4'
+
+services:
+  setgithubsecret:
+    container_name: setgithubsecret
+    image: jianboy/setgithubsecret:latest
+    ports:
+      - 5002:5002
+    volumes:
+      - .:/app
+    environment:
+      - APP_ID
+      - APP_SECRET
+    
+networks:
+  default:
+
+    

+ 12 - 0
web/requirements.txt

@@ -0,0 +1,12 @@
+flask==2.3.2
+#Flask[async]
+APScheduler==3.10.1
+Flask-APScheduler==1.12.4
+Flask_Reuploaded==1.3.0
+
+SQLAlchemy==2.0.19
+Flask-SQLAlchemy==3.1.1
+flask-marshmallow==0.15.0
+marshmallow-sqlalchemy==0.29.0
+marshmallow==3.20.1
+#PyMySQL==1.1.0