parent
							
								
									50bfb2f2f8
								
							
						
					
					
						commit
						2f5740a2b9
					
				@ -801,7 +801,7 @@ in
 | 
			
		||||
  mopidy = handleTest ./mopidy.nix { };
 | 
			
		||||
  morph-browser = runTest ./morph-browser.nix;
 | 
			
		||||
  morty = handleTest ./morty.nix { };
 | 
			
		||||
  mosquitto = handleTest ./mosquitto.nix { };
 | 
			
		||||
  mosquitto = runTest ./mosquitto.nix;
 | 
			
		||||
  moosefs = handleTest ./moosefs.nix { };
 | 
			
		||||
  movim = discoverTests (import ./web-apps/movim { inherit handleTestOn; });
 | 
			
		||||
  mpd = handleTest ./mpd.nix { };
 | 
			
		||||
 | 
			
		||||
@ -1,229 +1,227 @@
 | 
			
		||||
import ./make-test-python.nix (
 | 
			
		||||
  { pkgs, lib, ... }:
 | 
			
		||||
{ pkgs, ... }:
 | 
			
		||||
 | 
			
		||||
  let
 | 
			
		||||
    port = 1888;
 | 
			
		||||
    tlsPort = 1889;
 | 
			
		||||
    anonPort = 1890;
 | 
			
		||||
    password = "VERY_secret";
 | 
			
		||||
    hashedPassword = "$7$101$/WJc4Mp+I+uYE9sR$o7z9rD1EYXHPwEP5GqQj6A7k4W1yVbePlb8TqNcuOLV9WNCiDgwHOB0JHC1WCtdkssqTBduBNUnUGd6kmZvDSw==";
 | 
			
		||||
    topic = "test/foo";
 | 
			
		||||
let
 | 
			
		||||
  port = 1888;
 | 
			
		||||
  tlsPort = 1889;
 | 
			
		||||
  anonPort = 1890;
 | 
			
		||||
  password = "VERY_secret";
 | 
			
		||||
  hashedPassword = "$7$101$/WJc4Mp+I+uYE9sR$o7z9rD1EYXHPwEP5GqQj6A7k4W1yVbePlb8TqNcuOLV9WNCiDgwHOB0JHC1WCtdkssqTBduBNUnUGd6kmZvDSw==";
 | 
			
		||||
  topic = "test/foo";
 | 
			
		||||
 | 
			
		||||
    snakeOil =
 | 
			
		||||
      pkgs.runCommand "snakeoil-certs"
 | 
			
		||||
        {
 | 
			
		||||
          buildInputs = [ pkgs.gnutls.bin ];
 | 
			
		||||
          caTemplate = pkgs.writeText "snakeoil-ca.template" ''
 | 
			
		||||
            cn = server
 | 
			
		||||
            expiration_days = -1
 | 
			
		||||
            cert_signing_key
 | 
			
		||||
            ca
 | 
			
		||||
          '';
 | 
			
		||||
          certTemplate = pkgs.writeText "snakeoil-cert.template" ''
 | 
			
		||||
            cn = server
 | 
			
		||||
            expiration_days = -1
 | 
			
		||||
            tls_www_server
 | 
			
		||||
            encryption_key
 | 
			
		||||
            signing_key
 | 
			
		||||
          '';
 | 
			
		||||
          userCertTemplate = pkgs.writeText "snakeoil-user-cert.template" ''
 | 
			
		||||
            organization = snakeoil
 | 
			
		||||
            cn = client1
 | 
			
		||||
            expiration_days = -1
 | 
			
		||||
            tls_www_client
 | 
			
		||||
            encryption_key
 | 
			
		||||
            signing_key
 | 
			
		||||
          '';
 | 
			
		||||
        }
 | 
			
		||||
        ''
 | 
			
		||||
          mkdir "$out"
 | 
			
		||||
 | 
			
		||||
          certtool -p --bits 2048 --outfile "$out/ca.key"
 | 
			
		||||
          certtool -s --template "$caTemplate" --load-privkey "$out/ca.key" \
 | 
			
		||||
                      --outfile "$out/ca.crt"
 | 
			
		||||
          certtool -p --bits 2048 --outfile "$out/server.key"
 | 
			
		||||
          certtool -c --template "$certTemplate" \
 | 
			
		||||
                      --load-ca-privkey "$out/ca.key" \
 | 
			
		||||
                      --load-ca-certificate "$out/ca.crt" \
 | 
			
		||||
                      --load-privkey "$out/server.key" \
 | 
			
		||||
                      --outfile "$out/server.crt"
 | 
			
		||||
 | 
			
		||||
          certtool -p --bits 2048 --outfile "$out/client1.key"
 | 
			
		||||
          certtool -c --template "$userCertTemplate" \
 | 
			
		||||
                      --load-privkey "$out/client1.key" \
 | 
			
		||||
                      --load-ca-privkey "$out/ca.key" \
 | 
			
		||||
                      --load-ca-certificate "$out/ca.crt" \
 | 
			
		||||
                      --outfile "$out/client1.crt"
 | 
			
		||||
  snakeOil =
 | 
			
		||||
    pkgs.runCommand "snakeoil-certs"
 | 
			
		||||
      {
 | 
			
		||||
        buildInputs = [ pkgs.gnutls.bin ];
 | 
			
		||||
        caTemplate = pkgs.writeText "snakeoil-ca.template" ''
 | 
			
		||||
          cn = server
 | 
			
		||||
          expiration_days = -1
 | 
			
		||||
          cert_signing_key
 | 
			
		||||
          ca
 | 
			
		||||
        '';
 | 
			
		||||
        certTemplate = pkgs.writeText "snakeoil-cert.template" ''
 | 
			
		||||
          cn = server
 | 
			
		||||
          expiration_days = -1
 | 
			
		||||
          tls_www_server
 | 
			
		||||
          encryption_key
 | 
			
		||||
          signing_key
 | 
			
		||||
        '';
 | 
			
		||||
        userCertTemplate = pkgs.writeText "snakeoil-user-cert.template" ''
 | 
			
		||||
          organization = snakeoil
 | 
			
		||||
          cn = client1
 | 
			
		||||
          expiration_days = -1
 | 
			
		||||
          tls_www_client
 | 
			
		||||
          encryption_key
 | 
			
		||||
          signing_key
 | 
			
		||||
        '';
 | 
			
		||||
      }
 | 
			
		||||
      ''
 | 
			
		||||
        mkdir "$out"
 | 
			
		||||
 | 
			
		||||
  in
 | 
			
		||||
  {
 | 
			
		||||
    name = "mosquitto";
 | 
			
		||||
    meta = with pkgs.lib; {
 | 
			
		||||
      maintainers = with maintainers; [ peterhoeg ];
 | 
			
		||||
        certtool -p --bits 2048 --outfile "$out/ca.key"
 | 
			
		||||
        certtool -s --template "$caTemplate" --load-privkey "$out/ca.key" \
 | 
			
		||||
                    --outfile "$out/ca.crt"
 | 
			
		||||
        certtool -p --bits 2048 --outfile "$out/server.key"
 | 
			
		||||
        certtool -c --template "$certTemplate" \
 | 
			
		||||
                    --load-ca-privkey "$out/ca.key" \
 | 
			
		||||
                    --load-ca-certificate "$out/ca.crt" \
 | 
			
		||||
                    --load-privkey "$out/server.key" \
 | 
			
		||||
                    --outfile "$out/server.crt"
 | 
			
		||||
 | 
			
		||||
        certtool -p --bits 2048 --outfile "$out/client1.key"
 | 
			
		||||
        certtool -c --template "$userCertTemplate" \
 | 
			
		||||
                    --load-privkey "$out/client1.key" \
 | 
			
		||||
                    --load-ca-privkey "$out/ca.key" \
 | 
			
		||||
                    --load-ca-certificate "$out/ca.crt" \
 | 
			
		||||
                    --outfile "$out/client1.crt"
 | 
			
		||||
      '';
 | 
			
		||||
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  name = "mosquitto";
 | 
			
		||||
  meta = with pkgs.lib; {
 | 
			
		||||
    maintainers = with maintainers; [ peterhoeg ];
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  nodes =
 | 
			
		||||
    let
 | 
			
		||||
      client =
 | 
			
		||||
        { pkgs, ... }:
 | 
			
		||||
        {
 | 
			
		||||
          environment.systemPackages = with pkgs; [ mosquitto ];
 | 
			
		||||
        };
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
      server =
 | 
			
		||||
        { pkgs, ... }:
 | 
			
		||||
        {
 | 
			
		||||
          networking.firewall.allowedTCPPorts = [
 | 
			
		||||
            port
 | 
			
		||||
            tlsPort
 | 
			
		||||
            anonPort
 | 
			
		||||
          ];
 | 
			
		||||
          networking.useNetworkd = true;
 | 
			
		||||
          services.mosquitto = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            settings = {
 | 
			
		||||
              sys_interval = 1;
 | 
			
		||||
            };
 | 
			
		||||
            listeners = [
 | 
			
		||||
              {
 | 
			
		||||
                inherit port;
 | 
			
		||||
                users = {
 | 
			
		||||
                  password_store = {
 | 
			
		||||
                    inherit password;
 | 
			
		||||
                  };
 | 
			
		||||
                  password_file = {
 | 
			
		||||
                    passwordFile = pkgs.writeText "mqtt-password" password;
 | 
			
		||||
                  };
 | 
			
		||||
                  hashed_store = {
 | 
			
		||||
                    inherit hashedPassword;
 | 
			
		||||
                  };
 | 
			
		||||
                  hashed_file = {
 | 
			
		||||
                    hashedPasswordFile = pkgs.writeText "mqtt-hashed-password" hashedPassword;
 | 
			
		||||
                  };
 | 
			
		||||
 | 
			
		||||
                  reader = {
 | 
			
		||||
                    inherit password;
 | 
			
		||||
                    acl = [
 | 
			
		||||
                      "read ${topic}"
 | 
			
		||||
                      "read $SYS/#" # so we always have something to read
 | 
			
		||||
                    ];
 | 
			
		||||
                  };
 | 
			
		||||
                  writer = {
 | 
			
		||||
                    inherit password;
 | 
			
		||||
                    acl = [ "write ${topic}" ];
 | 
			
		||||
                  };
 | 
			
		||||
                };
 | 
			
		||||
              }
 | 
			
		||||
              {
 | 
			
		||||
                port = tlsPort;
 | 
			
		||||
                users.client1 = {
 | 
			
		||||
                  acl = [ "read $SYS/#" ];
 | 
			
		||||
                };
 | 
			
		||||
                settings = {
 | 
			
		||||
                  cafile = "${snakeOil}/ca.crt";
 | 
			
		||||
                  certfile = "${snakeOil}/server.crt";
 | 
			
		||||
                  keyfile = "${snakeOil}/server.key";
 | 
			
		||||
                  require_certificate = true;
 | 
			
		||||
                  use_identity_as_username = true;
 | 
			
		||||
                };
 | 
			
		||||
              }
 | 
			
		||||
              {
 | 
			
		||||
                port = anonPort;
 | 
			
		||||
                omitPasswordAuth = true;
 | 
			
		||||
                settings.allow_anonymous = true;
 | 
			
		||||
                acl = [ "pattern read #" ];
 | 
			
		||||
                users = {
 | 
			
		||||
                  anonWriter = {
 | 
			
		||||
                    password = "<ignored>" + password;
 | 
			
		||||
                    acl = [ "write ${topic}" ];
 | 
			
		||||
                  };
 | 
			
		||||
                };
 | 
			
		||||
              }
 | 
			
		||||
            ];
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
      client1 = client;
 | 
			
		||||
      client2 = client;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    nodes =
 | 
			
		||||
      let
 | 
			
		||||
        client =
 | 
			
		||||
          { pkgs, ... }:
 | 
			
		||||
          {
 | 
			
		||||
            environment.systemPackages = with pkgs; [ mosquitto ];
 | 
			
		||||
          };
 | 
			
		||||
      in
 | 
			
		||||
      {
 | 
			
		||||
        server =
 | 
			
		||||
          { pkgs, ... }:
 | 
			
		||||
          {
 | 
			
		||||
            networking.firewall.allowedTCPPorts = [
 | 
			
		||||
              port
 | 
			
		||||
              tlsPort
 | 
			
		||||
              anonPort
 | 
			
		||||
            ];
 | 
			
		||||
            networking.useNetworkd = true;
 | 
			
		||||
            services.mosquitto = {
 | 
			
		||||
              enable = true;
 | 
			
		||||
              settings = {
 | 
			
		||||
                sys_interval = 1;
 | 
			
		||||
              };
 | 
			
		||||
              listeners = [
 | 
			
		||||
                {
 | 
			
		||||
                  inherit port;
 | 
			
		||||
                  users = {
 | 
			
		||||
                    password_store = {
 | 
			
		||||
                      inherit password;
 | 
			
		||||
                    };
 | 
			
		||||
                    password_file = {
 | 
			
		||||
                      passwordFile = pkgs.writeText "mqtt-password" password;
 | 
			
		||||
                    };
 | 
			
		||||
                    hashed_store = {
 | 
			
		||||
                      inherit hashedPassword;
 | 
			
		||||
                    };
 | 
			
		||||
                    hashed_file = {
 | 
			
		||||
                      hashedPasswordFile = pkgs.writeText "mqtt-hashed-password" hashedPassword;
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    reader = {
 | 
			
		||||
                      inherit password;
 | 
			
		||||
                      acl = [
 | 
			
		||||
                        "read ${topic}"
 | 
			
		||||
                        "read $SYS/#" # so we always have something to read
 | 
			
		||||
                      ];
 | 
			
		||||
                    };
 | 
			
		||||
                    writer = {
 | 
			
		||||
                      inherit password;
 | 
			
		||||
                      acl = [ "write ${topic}" ];
 | 
			
		||||
                    };
 | 
			
		||||
                  };
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                  port = tlsPort;
 | 
			
		||||
                  users.client1 = {
 | 
			
		||||
                    acl = [ "read $SYS/#" ];
 | 
			
		||||
                  };
 | 
			
		||||
                  settings = {
 | 
			
		||||
                    cafile = "${snakeOil}/ca.crt";
 | 
			
		||||
                    certfile = "${snakeOil}/server.crt";
 | 
			
		||||
                    keyfile = "${snakeOil}/server.key";
 | 
			
		||||
                    require_certificate = true;
 | 
			
		||||
                    use_identity_as_username = true;
 | 
			
		||||
                  };
 | 
			
		||||
                }
 | 
			
		||||
                {
 | 
			
		||||
                  port = anonPort;
 | 
			
		||||
                  omitPasswordAuth = true;
 | 
			
		||||
                  settings.allow_anonymous = true;
 | 
			
		||||
                  acl = [ "pattern read #" ];
 | 
			
		||||
                  users = {
 | 
			
		||||
                    anonWriter = {
 | 
			
		||||
                      password = "<ignored>" + password;
 | 
			
		||||
                      acl = [ "write ${topic}" ];
 | 
			
		||||
                    };
 | 
			
		||||
                  };
 | 
			
		||||
                }
 | 
			
		||||
              ];
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
        client1 = client;
 | 
			
		||||
        client2 = client;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
    testScript = ''
 | 
			
		||||
      def mosquitto_cmd(binary, user, topic, port):
 | 
			
		||||
          return (
 | 
			
		||||
              "mosquitto_{} "
 | 
			
		||||
              "-V mqttv311 "
 | 
			
		||||
              "-h server "
 | 
			
		||||
              "-p {} "
 | 
			
		||||
              "-u {} "
 | 
			
		||||
              "-P '${password}' "
 | 
			
		||||
              "-t '{}'"
 | 
			
		||||
          ).format(binary, port, user, topic)
 | 
			
		||||
  testScript = ''
 | 
			
		||||
    def mosquitto_cmd(binary, user, topic, port):
 | 
			
		||||
        return (
 | 
			
		||||
            "mosquitto_{} "
 | 
			
		||||
            "-V mqttv311 "
 | 
			
		||||
            "-h server "
 | 
			
		||||
            "-p {} "
 | 
			
		||||
            "-u {} "
 | 
			
		||||
            "-P '${password}' "
 | 
			
		||||
            "-t '{}'"
 | 
			
		||||
        ).format(binary, port, user, topic)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      def publish(args, user, topic="${topic}", port=${toString port}):
 | 
			
		||||
          return "{} {}".format(mosquitto_cmd("pub", user, topic, port), args)
 | 
			
		||||
    def publish(args, user, topic="${topic}", port=${toString port}):
 | 
			
		||||
        return "{} {}".format(mosquitto_cmd("pub", user, topic, port), args)
 | 
			
		||||
 | 
			
		||||
      def subscribe(args, user, topic="${topic}", port=${toString port}):
 | 
			
		||||
          return "{} -W 5 -C 1 {}".format(mosquitto_cmd("sub", user, topic, port), args)
 | 
			
		||||
    def subscribe(args, user, topic="${topic}", port=${toString port}):
 | 
			
		||||
        return "{} -W 5 -C 1 {}".format(mosquitto_cmd("sub", user, topic, port), args)
 | 
			
		||||
 | 
			
		||||
      def parallel(*fns):
 | 
			
		||||
          from threading import Thread
 | 
			
		||||
          threads = [ Thread(target=fn) for fn in fns ]
 | 
			
		||||
          for t in threads: t.start()
 | 
			
		||||
          for t in threads: t.join()
 | 
			
		||||
    def parallel(*fns):
 | 
			
		||||
        from threading import Thread
 | 
			
		||||
        threads = [ Thread(target=fn) for fn in fns ]
 | 
			
		||||
        for t in threads: t.start()
 | 
			
		||||
        for t in threads: t.join()
 | 
			
		||||
 | 
			
		||||
      def wait_uuid(uuid):
 | 
			
		||||
          server.wait_for_console_text(uuid)
 | 
			
		||||
          return None
 | 
			
		||||
    def wait_uuid(uuid):
 | 
			
		||||
        server.wait_for_console_text(uuid)
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      start_all()
 | 
			
		||||
      server.wait_for_unit("mosquitto.service")
 | 
			
		||||
    start_all()
 | 
			
		||||
    server.wait_for_unit("mosquitto.service")
 | 
			
		||||
 | 
			
		||||
      with subtest("check passwords"):
 | 
			
		||||
          client1.succeed(publish("-m test", "password_store"))
 | 
			
		||||
          client1.succeed(publish("-m test", "password_file"))
 | 
			
		||||
          client1.succeed(publish("-m test", "hashed_store"))
 | 
			
		||||
          client1.succeed(publish("-m test", "hashed_file"))
 | 
			
		||||
    with subtest("check passwords"):
 | 
			
		||||
        client1.succeed(publish("-m test", "password_store"))
 | 
			
		||||
        client1.succeed(publish("-m test", "password_file"))
 | 
			
		||||
        client1.succeed(publish("-m test", "hashed_store"))
 | 
			
		||||
        client1.succeed(publish("-m test", "hashed_file"))
 | 
			
		||||
 | 
			
		||||
      with subtest("check acl"):
 | 
			
		||||
          client1.succeed(subscribe("", "reader", topic="$SYS/#"))
 | 
			
		||||
          client1.fail(subscribe("", "writer", topic="$SYS/#"))
 | 
			
		||||
    with subtest("check acl"):
 | 
			
		||||
        client1.succeed(subscribe("", "reader", topic="$SYS/#"))
 | 
			
		||||
        client1.fail(subscribe("", "writer", topic="$SYS/#"))
 | 
			
		||||
 | 
			
		||||
          parallel(
 | 
			
		||||
              lambda: client1.succeed(subscribe("-i 3688cdd7-aa07-42a4-be22-cb9352917e40", "reader")),
 | 
			
		||||
              lambda: [
 | 
			
		||||
                  wait_uuid("3688cdd7-aa07-42a4-be22-cb9352917e40"),
 | 
			
		||||
                  client2.succeed(publish("-m test", "writer"))
 | 
			
		||||
              ])
 | 
			
		||||
        parallel(
 | 
			
		||||
            lambda: client1.succeed(subscribe("-i 3688cdd7-aa07-42a4-be22-cb9352917e40", "reader")),
 | 
			
		||||
            lambda: [
 | 
			
		||||
                wait_uuid("3688cdd7-aa07-42a4-be22-cb9352917e40"),
 | 
			
		||||
                client2.succeed(publish("-m test", "writer"))
 | 
			
		||||
            ])
 | 
			
		||||
 | 
			
		||||
          parallel(
 | 
			
		||||
              lambda: client1.fail(subscribe("-i 24ff16a2-ae33-4a51-9098-1b417153c712", "reader")),
 | 
			
		||||
              lambda: [
 | 
			
		||||
                  wait_uuid("24ff16a2-ae33-4a51-9098-1b417153c712"),
 | 
			
		||||
                  client2.succeed(publish("-m test", "reader"))
 | 
			
		||||
              ])
 | 
			
		||||
        parallel(
 | 
			
		||||
            lambda: client1.fail(subscribe("-i 24ff16a2-ae33-4a51-9098-1b417153c712", "reader")),
 | 
			
		||||
            lambda: [
 | 
			
		||||
                wait_uuid("24ff16a2-ae33-4a51-9098-1b417153c712"),
 | 
			
		||||
                client2.succeed(publish("-m test", "reader"))
 | 
			
		||||
            ])
 | 
			
		||||
 | 
			
		||||
      with subtest("check tls"):
 | 
			
		||||
          client1.succeed(
 | 
			
		||||
              subscribe(
 | 
			
		||||
                  "--cafile ${snakeOil}/ca.crt "
 | 
			
		||||
                  "--cert ${snakeOil}/client1.crt "
 | 
			
		||||
                  "--key ${snakeOil}/client1.key",
 | 
			
		||||
                  topic="$SYS/#",
 | 
			
		||||
                  port=${toString tlsPort},
 | 
			
		||||
                  user="no_such_user"))
 | 
			
		||||
    with subtest("check tls"):
 | 
			
		||||
        client1.succeed(
 | 
			
		||||
            subscribe(
 | 
			
		||||
                "--cafile ${snakeOil}/ca.crt "
 | 
			
		||||
                "--cert ${snakeOil}/client1.crt "
 | 
			
		||||
                "--key ${snakeOil}/client1.key",
 | 
			
		||||
                topic="$SYS/#",
 | 
			
		||||
                port=${toString tlsPort},
 | 
			
		||||
                user="no_such_user"))
 | 
			
		||||
 | 
			
		||||
      with subtest("check omitPasswordAuth"):
 | 
			
		||||
          parallel(
 | 
			
		||||
              lambda: client1.succeed(subscribe("-i fd56032c-d9cb-4813-a3b4-6be0e04c8fc3",
 | 
			
		||||
                  "anonReader", port=${toString anonPort})),
 | 
			
		||||
              lambda: [
 | 
			
		||||
                  wait_uuid("fd56032c-d9cb-4813-a3b4-6be0e04c8fc3"),
 | 
			
		||||
                  client2.succeed(publish("-m test", "anonWriter", port=${toString anonPort}))
 | 
			
		||||
              ])
 | 
			
		||||
    '';
 | 
			
		||||
  }
 | 
			
		||||
)
 | 
			
		||||
    with subtest("check omitPasswordAuth"):
 | 
			
		||||
        parallel(
 | 
			
		||||
            lambda: client1.succeed(subscribe("-i fd56032c-d9cb-4813-a3b4-6be0e04c8fc3",
 | 
			
		||||
                "anonReader", port=${toString anonPort})),
 | 
			
		||||
            lambda: [
 | 
			
		||||
                wait_uuid("fd56032c-d9cb-4813-a3b4-6be0e04c8fc3"),
 | 
			
		||||
                client2.succeed(publish("-m test", "anonWriter", port=${toString anonPort}))
 | 
			
		||||
            ])
 | 
			
		||||
  '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user