예제 #1
0
    def add_key(self, import_file):
        """Add a key to the keyring.

        :param file-object import_file: File object containing the key data.

        :return: True if the key is successfully added.
        :rtype: bool

        :Example:

        >>> from pathlib import Path
        >>> my_key_file = Path("pharmaship.pub").open()
        >>> km = KeyManager()
        >>> km.add_key(my_key_file)
        True

        """
        key_data = import_file.read()
        r = self.gpg.import_keys(key_data)

        for item in r.results:
            if 'ok' not in item.keys():
                log.error("Signature error: %s", item["text"])
                self.status = _('Something went wrong! See detailed logs.')
                return False

        if r.imported == 0:
            log.info("Key already added.")
            self.status = _('Key already added')
        else:
            key = self.get_key(r.fingerprints[0])
            item = {"name": key['uids'][0], "fingerprint": key['fingerprint']}
            log.debug(item)
            self.status = _('Key successfully added')
        return True
예제 #2
0
    def on_language(self, action, param):
        log.info("Lang changed: %s", param)
        action.set_state(param)
        self.params.application.lang = param.get_string()
        self.params.save()

        set_langage(self.params.application.lang)

        # Get window parameters
        window_size = self.window.get_size()
        # Position is not reliable on Wayland
        window_position = self.window.get_position()
        log.debug(window_position)
        mode = self.window.mode

        self.window.destroy()
        self.window = AppWindow(application=self,
                                params=self.params,
                                actions=self)
        self.window.set_size_request(800, 600)

        self.set_mode(mode)
        self.window.set_default_size(*window_size)

        self.window.move(x=window_position[0], y=window_position[1])

        self.window.show_all()
예제 #3
0
    def create_main_layout(self):
        box = self.builder.get_object("main-box")
        # self.scrolled.add(box)
        self.window.layout.pack_start(box, True, True, 0)

        self.window.layout.show_all()

        # Get setting
        self.setting = self.params.setting

        if self.setting.first_aid_kit == 0:
            return

        first_aid_kits = models.FirstAidKit.objects.order_by("id").prefetch_related("items").all()[:self.params.setting.first_aid_kit]

        # Create the missing first aid kits
        count = first_aid_kits.count()
        missing = self.setting.first_aid_kit - count

        if missing > 0:
            log.info("Missing some first aid kit instances. Creating...")
            for i in range(missing):
                models.FirstAidKit.objects.create(
                    name="First Aid Kit {0}".format(count + i),
                    location_id=0
                    )
            first_aid_kits = None

        self.build_kits(first_aid_kits)
예제 #4
0
    def on_dashboard(self, action, param):
        log.info("Dashboard!")
        self.window.mode = "dashboard"
        self.window.mode_button.set_label(_("Dashboard"))

        self.clear_layout()

        view = views.dashboard.View(self.window)
        view.create_main_layout()
예제 #5
0
    def do_activate(self):
        # We only allow a single window and raise any existing ones
        if not self.window:
            # Windows are associated with the application
            # when the last one is closed the application shuts down
            self.window = AppWindow(application=self,
                                    params=self.params,
                                    actions=self)
            self.window.set_size_request(800, 600)

        self.on_dashboard(None, None)
        self.window.show_all()

        query_count_all()
        log.info("Initialization completed!")
예제 #6
0
    def create_rescue_bags(total):
        current = RescueBag.objects.count()
        missing = total - current
        if missing < 1:
            # Nothing to do
            log.debug("Number of RescueBag in database higher than needed")
            return True

        log.info("Missing some rescue bag instances. Creating...")
        for i in range(missing):
            location = Location.objects.create(name="Rescue Bag {0}".format(i),
                                               parent_id=0,
                                               is_rescue_bag=True)

            RescueBag.objects.create(name="Rescue Bag {0}".format(i),
                                     location_id=location.id)

            return True
예제 #7
0
    def deploy(self):
        """Propagate the import to concerned modules.

        For each module listed in the configuration, the import class
        ``update()`` method is called.

        :return: ``True`` if all updates are applied correctly, ``False``\
        otherwise
        :rtype: bool
        """
        for module in self.modules:
            import_class = load_module(module)
            if not import_class:
                self.status = _("Module import error. See detailed log.")
                return False

            data_import = import_class(tar=self.archive,
                                       conf=self.conf,
                                       key=self.km.key)

            if not (hasattr(data_import, "update")
                    and callable(data_import.update)):
                log.error("Module %s has no DataImport.update method.", module)
                self.status = _(
                    "Target module has no update method. See detailed log.")
                return False

            step_result = data_import.update()
            if not step_result:
                msg = _("Import of module {0} failed. See detailed logs."
                        ).format(module)
                log.error(msg)
            else:
                msg = _("Import of module {0} succeeded.").format(module)
                log.info(msg)

            self.import_log.append({'name': module, 'value': msg})

        self.status = _("Import success.")

        return True
예제 #8
0
    def create_main_layout(self):
        box = self.builder.get_object("main-box")
        # self.scrolled.add(box)
        self.window.layout.pack_start(box, True, True, 0)

        self.window.layout.show_all()

        # Get setting
        self.setting = self.params.setting

        if self.setting.rescue_bag == 0:
            return

        rescue_bags = RescueBag.objects.all().order_by(
            "name").prefetch_related("location")

        # Create the missing first aid kits
        count = rescue_bags.count()
        missing = self.setting.rescue_bag - count

        if missing > 0:
            log.info("Missing some rescue bag instances. Creating...")
            for i in range(missing):
                location = Location.objects.create(
                    name="Rescue Bag {0}".format(count + i),
                    parent_id=0,
                    is_rescue_bag=True)

                RescueBag.objects.create(name="Rescue Bag {0}".format(count +
                                                                      i),
                                         location_id=location.id)

            rescue_bags = RescueBag.objects.all().order_by(
                "name").prefetch_related("location")

        data = parser(self.params)
        # Create the all bags page
        self.build_full_list(data)

        self.build_bags(data, rescue_bags)
예제 #9
0
 def list_allowance(self, args):
     """List `Allowance` objects in database."""
     log.info("Allowances in database:")
     log.info("[ID]  NAME (VERSION)")
     for item in models.Allowance.objects.all().order_by("id"):
         log.info("[{0:02d}]  {1} ({2})".format(item.id, item.name,
                                                item.version))
예제 #10
0
    def check_signature(self, signed_data):
        """Check signed data has a valid known signature.

        :param str signed_data: GPG signed content to verify (armored).

        :return: validated data if the signature is valide, False otherwise.
        :rtype: bytes or False.
        """
        # Verifying the signature
        verified = self.gpg.verify(signed_data)

        # Check first is the signature is valid
        if not verified:
            self.status = _("No signature found.")
            return False

        # Then check that it is in the keyring
        self.key = None
        for k in self.gpg.list_keys():
            if k['keyid'] == verified.key_id:
                self.key = k
                break

            # Also check in the subkeys
            for sk in k['subkeys']:
                if sk[0] == verified.key_id:
                    self.key = k
                    break

        if not self.key:
            self.status = _("Signature not in the keyring.")
            return False

        # Decrypt the file
        log.info("Package signature correct and verified (%s, %s)",
                 verified.username, verified.key_id[-8:])
        return self.gpg.decrypt(signed_data).data
예제 #11
0
def update_allowance(allowance, key):
    """Update or create an allowance instance from serialized allowance data.

    :param models.Allowance allowance: Up-to-date Allowance instance.
    :param str key: GPG key ID used for signing the package archive.

    :return: the updated (or create) allowance instance
    :rtype: models.Allowance
    """
    log.debug("Allowance name: %s", allowance.name)

    allowance_dict = allowance.__dict__
    allowance_dict.pop('id', None)
    allowance_dict.pop('_state', None)
    allowance_dict['signature'] = key
    # Unique: (name, )
    obj, created = models.Allowance.objects.update_or_create(
        name=allowance.name, defaults=allowance_dict)
    if not created:
        log.info("Allowance `%s` already exists, updated.", allowance.name)
    else:
        log.info("Allowance `%s` create.", allowance.name)

    return obj
예제 #12
0
    def update(self):
        """Launch the importation.

        Import first the :class:`pharmaship.inventory.models.Allowance`.
        Then, import all :class:`pharmaship.inventory.models.Molecule` and
        :class:`pharmaship.inventory.models.Equipment` objects (update or
        create them).

        When this is done, parse each JSON file for required quantities:

        * :class:`pharmaship.inventory.models.MoleculeReqQty`
        * :class:`pharmaship.inventory.models.EquipmentReqQty`
        * :class:`pharmaship.inventory.models.RescueBagReqQty`
        * :class:`pharmaship.inventory.models.FirstAidKitReqQty`
        * :class:`pharmaship.inventory.models.LaboratoryReqQty`
        * :class:`pharmaship.inventory.models.TelemedicalReqQty`

        :class:`pharmaship.inventory.models.Molecule` and
        :class:`pharmaship.inventory.models.Equipment` objects without
        required quantity after import are affected to the default
        :class:`pharmaship.inventory.models.Allowance` (``id=0``) with a
        required quantity of 0.

        :return: ``True`` if import successful, ``False`` otherwise.
        :rtype: bool
        """
        log.info("Inventory import...")

        # Detecting objects without allowance (orphan)
        self.no_allowance = models.Allowance.objects.get(pk=0)
        query_count_all()

        allowance = self.import_allowance()
        if not allowance:
            return False
        query_count_all()

        if not self.import_molecule():
            return False
        query_count_all()

        if not self.import_equipment():
            return False
        query_count_all()

        # Required Quantities
        required = [
            {
                "filename": "inventory/molecule_reqqty.json",
                "model": models.MoleculeReqQty,
                # "serializer": serializers.MoleculeReqQtySerializer
            },
            {
                "filename": "inventory/equipment_reqqty.json",
                "model": models.EquipmentReqQty,
                # "serializer": serializers.EquipmentReqQtySerializer
            },
            {
                "filename": "inventory/telemedical_reqqty.json",
                "model": models.TelemedicalReqQty,
                # "serializer": serializers.TelemedicalReqQtySerializer
            },
            {
                "filename": "inventory/laboratory_reqqty.json",
                "model": models.LaboratoryReqQty,
                # "serializer": serializers.LaboratoryReqQtySerializer
            },
            {
                "filename": "inventory/rescue_bag_reqqty.json",
                "model": models.RescueBagReqQty,
                # "serializer": serializers.RescueBagReqQtySerializer
            },
            {
                "filename": "inventory/first_aid_kit_reqqty.json",
                "model": models.FirstAidKitReqQty,
                # "serializer": serializers.FirstAidKitReqQtySerializer
            },
        ]

        query_count_all()

        for item in required:
            res = required_quantity(item, self.tar, allowance)
            if not res:
                return False

        # Listing molecules with no reqqty
        molecule_orphan_after = models.Molecule.objects.filter(allowances=None)
        equipment_orphan_after = models.Equipment.objects.filter(
            allowances=None)

        log.info("Orphan Molecules: %s", len(molecule_orphan_after))
        log.info("Orphan Equipments: %s", len(equipment_orphan_after))

        # Creating reqqty with special allowance (id=1)
        for molecule in molecule_orphan_after:
            models.MoleculeReqQty.objects.create(base=molecule,
                                                 allowance=self.no_allowance,
                                                 required_quantity=0)

        for equipment in equipment_orphan_after:
            models.EquipmentReqQty.objects.create(base=equipment,
                                                  allowance=self.no_allowance,
                                                  required_quantity=0)

        # Copying pictures
        self.tar.extractall(members=pictures_files(self.tar),
                            path=str(settings.PICTURES_FOLDER))

        # Set allowance active as everything went well
        allowance.active = True
        allowance.save()

        return True
예제 #13
0
    def handle(self, *args, **options):  # noqa: D102
        try:
            settings.PHARMASHIP_CONF.touch()
            log.info("Copy default configuration")
            default_config = settings.PHARMASHIP_DATA / "config_default.yaml"
            data = default_config.read_text()
            settings.PHARMASHIP_CONF.write_text(data)
        except FileExistsError:
            pass

        log.info("Load Equipment Groups")
        load_data("EquipmentGroup.yaml")
        log.info("Load Molecule Groups")
        load_data("MoleculeGroup.yaml")
        log.info("Load default Locations")
        load_data("Location.yaml")
        log.info("Load default Allowance")
        load_data("Allowance.yaml")

        log.info("Load Pharmaship public key")
        key_path = settings.PHARMASHIP_DATA / "pharmaship.pub"
        log.debug(key_path)
        call_command("key_management", "add", key_path)
예제 #14
0
    def get(self, args):
        log.info("Getting keys")

        km = KeyManager()
        res = km.get_key(args["fingerprint"])
        log.info(res)
예제 #15
0
    def delete(self, args):
        log.info("Deleting keys")

        km = KeyManager()
        res = km.delete_key(args["fingerprint"])
        log.info(res)
예제 #16
0
    def add(self, args):
        log.info("Adding key from file.")

        km = KeyManager()
        res = km.add_key(args["file"])
        log.info(res)
예제 #17
0
    def list(self, args):
        log.info("Listing keys")
        km = KeyManager()
        res = km.key_list()

        log.info(res)
예제 #18
0
 def handle(self, *args, **options):  # noqa: D102
     log.info(args)
     if "func" in options:
         options['func'](options)