From 40e17ef4b8094b54a8ea72b53b8c8750c1adcf91 Mon Sep 17 00:00:00 2001
From: lijianguo <lijianguo1991@outlook.com>
Date: Tue, 3 Sep 2024 16:46:27 +0800
Subject: [PATCH 1/2] chore(controller): services protocol default is TCP

---
 rootfs/api/serializers/__init__.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/rootfs/api/serializers/__init__.py b/rootfs/api/serializers/__init__.py
index b4662024f..796e1657a 100644
--- a/rootfs/api/serializers/__init__.py
+++ b/rootfs/api/serializers/__init__.py
@@ -492,7 +492,9 @@ def validate_port(value):
 
     @staticmethod
     def validate_protocol(value):
-        if not re.match(SERVICE_PROTOCOL_MATCH, value):
+        if value is None or value == "":
+            value = "TCP"
+        elif not re.match(SERVICE_PROTOCOL_MATCH, value):
             raise serializers.ValidationError(SERVICE_PROTOCOL_MISMATCH_MSG)
         return value
 

From 10d3067ecebf657250bf28d22a8345413959dae8 Mon Sep 17 00:00:00 2001
From: lijianguo <lijianguo1991@outlook.com>
Date: Wed, 4 Sep 2024 16:20:17 +0800
Subject: [PATCH 2/2] chore(controller): owner or admin operate perms

---
 rootfs/api/views.py | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/rootfs/api/views.py b/rootfs/api/views.py
index a9c024a41..b3f4c42b2 100644
--- a/rootfs/api/views.py
+++ b/rootfs/api/views.py
@@ -23,6 +23,7 @@
 from rest_framework.response import Response
 from rest_framework.viewsets import GenericViewSet
 from rest_framework.parsers import MultiPartParser
+from rest_framework.exceptions import PermissionDenied
 
 from api import monitor, models, permissions, serializers, viewsets, authentication
 from api.tasks import scale_app, restart_app, mount_app, downstream_model_owner, \
@@ -392,20 +393,19 @@ class ConfigViewSet(ReleasableViewSet):
     serializer_class = serializers.ConfigSerializer
 
     def post_save(self, config):
-        if not config.app.appsettings_set.latest().autodeploy:
-            return
         latest_release = config.app.release_set.filter(failed=False).latest()
         try:
             release = latest_release.new(
                 self.request.user, config=config, build=latest_release.build)
-            ptypes = set()
-            for field, diff in config.diff().items():
-                if field in config.ptype_fields:
-                    for value in diff.values():
-                        ptypes.update(value.keys())
-            # allof_fields changed, deploy all.
-            ptypes = list(ptypes) if ptypes else None
-            release.deploy(ptypes, False)
+            if config.app.appsettings_set.latest().autodeploy:
+                ptypes = set()
+                for field, diff in config.diff().items():
+                    if field in config.ptype_fields:
+                        for value in diff.values():
+                            ptypes.update(value.keys())
+                # allof_fields changed, deploy all.
+                ptypes = list(ptypes) if ptypes else None
+                release.deploy(ptypes, False)
         except BaseException as e:
             config.delete()
             if isinstance(e, AlreadyExists):
@@ -774,8 +774,15 @@ def create(self, request, *args, **kwargs):
 class AppPermViewSet(AppResourceViewSet):
     """RESTful views for sharing apps with collaborators."""
 
+    def get_app(self, request):
+        app = get_object_or_404(models.app.App, id=self.kwargs['id'])
+        if not permissions.IsOwnerOrAdmin().has_object_permission(request, self, app):
+            raise PermissionDenied()
+        self.check_object_permissions(self.request, app)
+        return app
+
     def list(self, request, **kwargs):
-        app = self.get_app()
+        app = self.get_app(request)
         results = [
             {
                 "app": app.id,
@@ -792,7 +799,7 @@ def list(self, request, **kwargs):
         return Response(data=pagination)
 
     def create(self, request, **kwargs):
-        app = self.get_app()
+        app = self.get_app(request)
         username = request.data.get('username')
         shortnames = set([perm for perm in request.data.get("permissions", "").split(",") if perm])
         all_shortnames = models.app.app_permission_registry.shortnames
@@ -810,7 +817,7 @@ def create(self, request, **kwargs):
         return Response(status=status.HTTP_201_CREATED)
 
     def update(self, request, **kwargs):
-        app = self.get_app()
+        app = self.get_app(request)
         user = get_object_or_404(User, username=kwargs['username'])
         shortnames = set([perm for perm in request.data.get("permissions", "").split(",") if perm])
         all_shortnames = models.app.app_permission_registry.shortnames
@@ -832,7 +839,7 @@ def update(self, request, **kwargs):
         return Response(status=status.HTTP_204_NO_CONTENT)
 
     def destroy(self, request, **kwargs):
-        app = self.get_app()
+        app = self.get_app(request)
         username = kwargs['username']
         user = get_object_or_404(User, username=username)
         for codename in get_user_perms(user, app):
