Browse Source

feat: store created_by and updated_by for apps, modelconfigs, and sites (#7613)

kurokobo 7 months ago
parent
commit
bc3a8e0ca2

+ 2 - 0
api/controllers/console/app/model_config.py

@@ -32,6 +32,8 @@ class ModelConfigResource(Resource):
 
         new_app_model_config = AppModelConfig(
             app_id=app_model.id,
+            created_by=current_user.id,
+            updated_by=current_user.id,
         )
         new_app_model_config = new_app_model_config.from_model_config_dict(model_configuration)
 

+ 6 - 0
api/controllers/console/app/site.py

@@ -1,3 +1,5 @@
+from datetime import datetime, timezone
+
 from flask_login import current_user
 from flask_restful import Resource, marshal_with, reqparse
 from werkzeug.exceptions import Forbidden, NotFound
@@ -71,6 +73,8 @@ class AppSite(Resource):
             if value is not None:
                 setattr(site, attr_name, value)
 
+        site.updated_by = current_user.id
+        site.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
         db.session.commit()
 
         return site
@@ -93,6 +97,8 @@ class AppSiteAccessTokenReset(Resource):
             raise NotFound
 
         site.code = Site.generate_code(16)
+        site.updated_by = current_user.id
+        site.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
         db.session.commit()
 
         return site

+ 2 - 0
api/events/event_handlers/create_site_record_when_app_created.py

@@ -17,6 +17,8 @@ def handle(sender, **kwargs):
         default_language=account.interface_language,
         customize_token_strategy="not_allow",
         code=Site.generate_code(16),
+        created_by=app.created_by,
+        updated_by=app.updated_by,
     )
 
     db.session.add(site)

+ 24 - 0
api/fields/app_fields.py

@@ -1,5 +1,6 @@
 from flask_restful import fields
 
+from fields.workflow_fields import workflow_partial_fields
 from libs.helper import AppIconUrlField, TimestampField
 
 app_detail_kernel_fields = {
@@ -39,7 +40,10 @@ model_config_fields = {
     "completion_prompt_config": fields.Raw(attribute="completion_prompt_config_dict"),
     "dataset_configs": fields.Raw(attribute="dataset_configs_dict"),
     "file_upload": fields.Raw(attribute="file_upload_dict"),
+    "created_by": fields.String,
     "created_at": TimestampField,
+    "updated_by": fields.String,
+    "updated_at": TimestampField,
 }
 
 app_detail_fields = {
@@ -52,8 +56,12 @@ app_detail_fields = {
     "enable_site": fields.Boolean,
     "enable_api": fields.Boolean,
     "model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True),
+    "workflow": fields.Nested(workflow_partial_fields, allow_null=True),
     "tracing": fields.Raw,
+    "created_by": fields.String,
     "created_at": TimestampField,
+    "updated_by": fields.String,
+    "updated_at": TimestampField,
 }
 
 prompt_config_fields = {
@@ -63,6 +71,10 @@ prompt_config_fields = {
 model_config_partial_fields = {
     "model": fields.Raw(attribute="model_dict"),
     "pre_prompt": fields.String,
+    "created_by": fields.String,
+    "created_at": TimestampField,
+    "updated_by": fields.String,
+    "updated_at": TimestampField,
 }
 
 tag_fields = {"id": fields.String, "name": fields.String, "type": fields.String}
@@ -78,7 +90,11 @@ app_partial_fields = {
     "icon_background": fields.String,
     "icon_url": AppIconUrlField,
     "model_config": fields.Nested(model_config_partial_fields, attribute="app_model_config", allow_null=True),
+    "workflow": fields.Nested(workflow_partial_fields, allow_null=True),
+    "created_by": fields.String,
     "created_at": TimestampField,
+    "updated_by": fields.String,
+    "updated_at": TimestampField,
     "tags": fields.List(fields.Nested(tag_fields)),
 }
 
@@ -124,6 +140,10 @@ site_fields = {
     "prompt_public": fields.Boolean,
     "app_base_url": fields.String,
     "show_workflow_steps": fields.Boolean,
+    "created_by": fields.String,
+    "created_at": TimestampField,
+    "updated_by": fields.String,
+    "updated_at": TimestampField,
 }
 
 app_detail_fields_with_site = {
@@ -138,9 +158,13 @@ app_detail_fields_with_site = {
     "enable_site": fields.Boolean,
     "enable_api": fields.Boolean,
     "model_config": fields.Nested(model_config_fields, attribute="app_model_config", allow_null=True),
+    "workflow": fields.Nested(workflow_partial_fields, allow_null=True),
     "site": fields.Nested(site_fields),
     "api_base_url": fields.String,
+    "created_by": fields.String,
     "created_at": TimestampField,
+    "updated_by": fields.String,
+    "updated_at": TimestampField,
     "deleted_tools": fields.List(fields.String),
 }
 

+ 8 - 0
api/fields/workflow_fields.py

@@ -53,3 +53,11 @@ workflow_fields = {
     "environment_variables": fields.List(EnvironmentVariableField()),
     "conversation_variables": fields.List(fields.Nested(conversation_variable_fields)),
 }
+
+workflow_partial_fields = {
+    "id": fields.String,
+    "created_by": fields.String,
+    "created_at": TimestampField,
+    "updated_by": fields.String,
+    "updated_at": TimestampField,
+}

+ 52 - 0
api/migrations/versions/2024_08_25_0441-d0187d6a88dd_add_created_by_and_updated_by_to_app_.py

@@ -0,0 +1,52 @@
+"""add created_by and updated_by to app, modelconfig, and site
+
+Revision ID: d0187d6a88dd
+Revises: 2dbe42621d96
+Create Date: 2024-08-25 04:41:18.157397
+
+"""
+
+import sqlalchemy as sa
+from alembic import op
+
+import models as models
+
+# revision identifiers, used by Alembic.
+revision = "d0187d6a88dd"
+down_revision = "2dbe42621d96"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    with op.batch_alter_table("app_model_configs", schema=None) as batch_op:
+        batch_op.add_column(sa.Column("created_by", models.types.StringUUID(), nullable=True))
+        batch_op.add_column(sa.Column("updated_by", models.types.StringUUID(), nullable=True))
+
+    with op.batch_alter_table("apps", schema=None) as batch_op:
+        batch_op.add_column(sa.Column("created_by", models.types.StringUUID(), nullable=True))
+        batch_op.add_column(sa.Column("updated_by", models.types.StringUUID(), nullable=True))
+
+    with op.batch_alter_table("sites", schema=None) as batch_op:
+        batch_op.add_column(sa.Column("created_by", models.types.StringUUID(), nullable=True))
+        batch_op.add_column(sa.Column("updated_by", models.types.StringUUID(), nullable=True))
+
+    # ### end Alembic commands ###
+
+
+def downgrade():
+    # ### commands auto generated by Alembic - please adjust! ###
+    with op.batch_alter_table("sites", schema=None) as batch_op:
+        batch_op.drop_column("updated_by")
+        batch_op.drop_column("created_by")
+
+    with op.batch_alter_table("apps", schema=None) as batch_op:
+        batch_op.drop_column("updated_by")
+        batch_op.drop_column("created_by")
+
+    with op.batch_alter_table("app_model_configs", schema=None) as batch_op:
+        batch_op.drop_column("updated_by")
+        batch_op.drop_column("created_by")
+
+    # ### end Alembic commands ###

+ 6 - 0
api/models/model.py

@@ -82,7 +82,9 @@ class App(db.Model):
     is_universal = db.Column(db.Boolean, nullable=False, server_default=db.text('false'))
     tracing = db.Column(db.Text, nullable=True)
     max_active_requests = db.Column(db.Integer, nullable=True)
+    created_by = db.Column(StringUUID, nullable=True)
     created_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
+    updated_by = db.Column(StringUUID, nullable=True)
     updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
 
     @property
@@ -221,7 +223,9 @@ class AppModelConfig(db.Model):
     provider = db.Column(db.String(255), nullable=True)
     model_id = db.Column(db.String(255), nullable=True)
     configs = db.Column(db.JSON, nullable=True)
+    created_by = db.Column(StringUUID, nullable=True)
     created_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
+    updated_by = db.Column(StringUUID, nullable=True)
     updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
     opening_statement = db.Column(db.Text)
     suggested_questions = db.Column(db.Text)
@@ -1115,7 +1119,9 @@ class Site(db.Model):
     customize_token_strategy = db.Column(db.String(255), nullable=False)
     prompt_public = db.Column(db.Boolean, nullable=False, server_default=db.text('false'))
     status = db.Column(db.String(255), nullable=False, server_default=db.text("'normal'::character varying"))
+    created_by = db.Column(StringUUID, nullable=True)
     created_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
+    updated_by = db.Column(StringUUID, nullable=True)
     updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text('CURRENT_TIMESTAMP(0)'))
     code = db.Column(db.String(255))
 

+ 4 - 0
api/services/app_dsl_service.py

@@ -346,6 +346,8 @@ class AppDslService:
         app_model_config = AppModelConfig()
         app_model_config = app_model_config.from_model_config_dict(model_config_data)
         app_model_config.app_id = app.id
+        app_model_config.created_by = account.id
+        app_model_config.updated_by = account.id
 
         db.session.add(app_model_config)
         db.session.commit()
@@ -390,6 +392,8 @@ class AppDslService:
             icon_background=icon_background,
             enable_site=True,
             enable_api=True,
+            created_by=account.id,
+            updated_by=account.id,
         )
 
         db.session.add(app)

+ 9 - 0
api/services/app_service.py

@@ -127,6 +127,8 @@ class AppService:
         app.tenant_id = tenant_id
         app.api_rph = args.get("api_rph", 0)
         app.api_rpm = args.get("api_rpm", 0)
+        app.created_by = account.id
+        app.updated_by = account.id
 
         db.session.add(app)
         db.session.flush()
@@ -134,6 +136,8 @@ class AppService:
         if default_model_config:
             app_model_config = AppModelConfig(**default_model_config)
             app_model_config.app_id = app.id
+            app_model_config.created_by = account.id
+            app_model_config.updated_by = account.id
             db.session.add(app_model_config)
             db.session.flush()
 
@@ -217,6 +221,7 @@ class AppService:
         app.icon_type = args.get("icon_type", "emoji")
         app.icon = args.get("icon")
         app.icon_background = args.get("icon_background")
+        app.updated_by = current_user.id
         app.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
         db.session.commit()
 
@@ -233,6 +238,7 @@ class AppService:
         :return: App instance
         """
         app.name = name
+        app.updated_by = current_user.id
         app.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
         db.session.commit()
 
@@ -248,6 +254,7 @@ class AppService:
         """
         app.icon = icon
         app.icon_background = icon_background
+        app.updated_by = current_user.id
         app.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
         db.session.commit()
 
@@ -264,6 +271,7 @@ class AppService:
             return app
 
         app.enable_site = enable_site
+        app.updated_by = current_user.id
         app.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
         db.session.commit()
 
@@ -280,6 +288,7 @@ class AppService:
             return app
 
         app.enable_api = enable_api
+        app.updated_by = current_user.id
         app.updated_at = datetime.now(timezone.utc).replace(tzinfo=None)
         db.session.commit()
 

+ 2 - 0
api/services/workflow/workflow_converter.py

@@ -74,6 +74,8 @@ class WorkflowConverter:
         new_app.api_rph = app_model.api_rph
         new_app.is_demo = False
         new_app.is_public = app_model.is_public
+        new_app.created_by = account.id
+        new_app.updated_by = account.id
         db.session.add(new_app)
         db.session.flush()
         db.session.commit()