diff --git a/deployment/options.nix b/deployment/options.nix index df04b994..27d38bce 100644 --- a/deployment/options.nix +++ b/deployment/options.nix @@ -2,7 +2,7 @@ Deployment options as to be presented in the front end. These are converted to JSON schema in order to generate front-end forms etc. - For this to work, options must not have types `functionTo` or `package` (or `submodule` until [submodule introspection](https://github.com/NixOS/nixpkgs/pull/391544) is merged), and must not access `config` for their default values. + For this to work, options must not have types `functionTo` or `package`, and must not access `config` for their default values. */ { lib, @@ -34,22 +34,30 @@ in mastodon = { enable = lib.mkEnableOption "Mastodon"; }; - initialUser = { - displayName = mkOption { - type = types.str; - description = "Display name of the user"; - }; - username = mkOption { - type = types.str; - description = "Username for login"; - }; - email = mkOption { - type = types.str; - description = "User's email address"; - }; - password = mkOption { - type = types.str; - description = "Password for login"; + initialUser = mkOption { + description = '' + Some services require an initial user to access them. + This option sets the credentials for such an initial user. + ''; + type = types.submodule { + options = { + displayName = mkOption { + type = types.str; + description = "Display name of the user"; + }; + username = mkOption { + type = types.str; + description = "Username for login"; + }; + email = mkOption { + type = types.str; + description = "User's email address"; + }; + password = mkOption { + type = types.str; + description = "Password for login"; + }; + }; }; }; }; diff --git a/panel/src/panel/templates/partials/deployment_result.html b/panel/src/panel/templates/partials/deployment_result.html index d342ad18..353d93c7 100644 --- a/panel/src/panel/templates/partials/deployment_result.html +++ b/panel/src/panel/templates/partials/deployment_result.html @@ -5,7 +5,7 @@ {% for service_name, service_meta in services.items %} {% if service_meta.enable %}
  • - ✓ {{ service_name }} + ✓ {{ service_name }}
  • {% endif %} {% endfor %} diff --git a/panel/src/panel/views.py b/panel/src/panel/views.py index 29eb31d9..1eb48c6f 100644 --- a/panel/src/panel/views.py +++ b/panel/src/panel/views.py @@ -14,6 +14,8 @@ from rest_framework.renderers import TemplateHTMLRenderer from rest_framework.response import Response from rest_framework.views import APIView +from pydantic import BaseModel + from panel import models, settings from panel.configuration import schema @@ -39,7 +41,6 @@ class ConfigurationForm(LoginRequiredMixin, APIView): success_url = reverse_lazy('configuration_form') def get_object(self): - """Get or create the configuration object for the current user""" obj, created = models.Configuration.objects.get_or_create( operator=self.request.user, ) @@ -67,37 +68,33 @@ class ConfigurationForm(LoginRequiredMixin, APIView): config.save() return redirect(self.success_url) +# TODO(@fricklerhandwerk): +# this is broken after changing the form view. +# but if there's no test for it, how do we know it ever worked in the first place? class DeploymentStatus(ConfigurationForm): - def form_valid(self, form): - obj = self.get_object() - obj.value = form.to_python().model_dump_json() - obj.save() - # Check for deploy button - if "deploy" in self.request.POST.keys(): - deployment_result, deployment_params = self.deployment(obj) - deployment_succeeded = deployment_result.returncode == 0 + def post(self, request): + config = self.get_object() + serializer = schema.Model.drf_serializer( + instance=config.parsed_value, + data=request.data + ) + + if not serializer.is_valid(): + return Response({'serializer': serializer}) + + config.value = json.dumps(serializer.validated_data) + config.save() + + deployment_result, deployment_params = self.deployment(config.parsed_value) + deployment_succeeded = deployment_result.returncode == 0 return render(self.request, "partials/deployment_result.html", { "deployment_succeeded": deployment_succeeded, - "services": { - "peertube": { - "enable": deployment_params['peertube']['enable'], - "url": f"https://peertube.{deployment_params['domain']}", - }, - "pixelfed":{ - "enable": deployment_params['pixelfed']['enable'], - "url": f"https://pixelfed.{deployment_params['domain']}", - }, - "mastodon": { - "enable": deployment_params['mastodon']['enable'], - "url": f"https://mastodon.{deployment_params['domain']}", - }, - }, - }) + "services": deployment_params.json(), + }) - def deployment(self, obj): - submission = obj.parsed_value.model_dump_json() + def deployment(self, config: BaseModel): # FIXME: let the user specify these from the form (#190) dummy_user = { "initialUser": { @@ -107,12 +104,10 @@ class DeploymentStatus(ConfigurationForm): "email": "test@test.com", }, } - # serialize back and forth now we still need to manually inject the dummy user - deployment_params = json.dumps(dummy_user | json.loads(submission)) env = { "PATH": settings.bin_path, # pass in form info to our deployment - "DEPLOYMENT": deployment_params, + "DEPLOYMENT": config.json() } cmd = [ "nix", @@ -129,4 +124,4 @@ class DeploymentStatus(ConfigurationForm): cwd=settings.repo_dir, env=env, ) - return deployment_result, json.loads(deployment_params) + return deployment_result, config