buttercup-pw/buttercup-core

View on GitHub
source/io/formatA/commands.ts

Summary

Maintainability
D
2 days
Test Coverage
import {
    findEntryByID,
    findGroupByID,
    findGroupContainingEntryID,
    findGroupContainingGroupID,
    generateEntryLegacyHistoryItem
} from "./tools.js";
import {
    EntryID,
    EntryPropertyType,
    FormatAEntry,
    FormatAGroup,
    FormatAVault,
    GroupID,
    VaultID
} from "../../types.js";

export function executeArchiveID(vault: FormatAVault, opts: any, id: VaultID) {
    if (opts.shareID) {
        // Don't set vault ID from a share
        return;
    }
    if (vault.id) {
        // ID already set
        throw new Error("Vault ID already set");
    }
    vault.id = id;
}

export function executeComment() {
    // Comment has no action
}

export function executeCreateEntry(
    archive: FormatAVault,
    opts: any,
    groupID: GroupID,
    entryID: EntryID
) {
    archive.groups = archive.groups || [];
    const entry: FormatAEntry = {
        id: entryID,
        properties: {},
        shareID: opts.shareID,
        parentID: groupID
    };
    if (opts.permissions) {
        entry.permissions = opts.permissions;
    }
    const group = findGroupByID(archive.groups, groupID);
    if (!group) {
        throw new Error(`Invalid group ID: ${groupID}`);
    }
    group.entries = group.entries || [];
    group.entries.push(entry);
}

export function executeCreateGroup(
    archive: FormatAVault,
    opts: any,
    parentID: GroupID | VaultID,
    newID: GroupID
) {
    archive.groups = archive.groups || [];
    const group: FormatAGroup = {
        id: newID,
        title: "New group",
        shareID: opts.shareID,
        parentID
    };
    if (opts.permissions) {
        group.permissions = opts.permissions;
    }
    if (parentID === "0") {
        archive.groups.push(group);
    } else {
        const parentGroup = findGroupByID(archive.groups, parentID);
        if (!parentGroup) {
            throw new Error(`Invalid parent group ID: ${parentID}`);
        }
        parentGroup.groups = parentGroup.groups || [];
        parentGroup.groups.push(group);
    }
}

export function executeDeleteArchiveAttribute(archive: FormatAVault, opts: any, attribute: string) {
    const attributes = archive.attributes || {};
    if (attributes.hasOwnProperty(attribute) !== true) {
        throw new Error(`Vault contains no such attribute: ${attribute}`);
    }
    const deleted = delete attributes[attribute];
    if (!deleted) {
        throw new Error(`Failed deleting attribute: ${attribute}`);
    }
}

export function executeDeleteEntry(archive: FormatAVault, opts: any, entryID: EntryID) {
    archive.groups = archive.groups || [];
    const { group, index } = findGroupContainingEntryID(archive.groups, entryID);
    if (!group) {
        throw new Error(`Failed deleting entry: Invalid entry ID: ${entryID}`);
    }
    group.entries.splice(index, 1);
}

export function executeDeleteEntryAttribute(
    archive: FormatAVault,
    opts: any,
    entryID: EntryID,
    attribute: string
) {
    archive.groups = archive.groups || [];
    const entry = findEntryByID(archive.groups, entryID);
    if (!entry) {
        throw new Error("Entry not found for ID");
    }
    entry.attributes = entry.attributes || {};
    const value = entry.attributes[attribute];
    const deleted = delete entry.attributes[attribute];
    if (!deleted) {
        throw new Error("Failed deleting attribute");
    }
    entry.history = entry.history || [];
    entry.history.push(
        generateEntryLegacyHistoryItem(attribute, EntryPropertyType.Attribute, value, null)
    );
}

export function executeDeleteEntryProperty(
    archive: FormatAVault,
    opts: any,
    entryID: EntryID,
    property: string
) {
    archive.groups = archive.groups || [];
    const entry = findEntryByID(archive.groups, entryID);
    if (!entry) {
        throw new Error(`Entry not found for ID: ${entryID}`);
    }
    entry.properties = entry.properties || {};
    const value = entry.properties[property];
    const deleted = delete entry.properties[property];
    if (!deleted) {
        throw new Error(`Failed deleting property: ${property}`);
    }
    entry.history = entry.history || [];
    entry.history.push(
        generateEntryLegacyHistoryItem(property, EntryPropertyType.Property, value, null)
    );
}

export function executeDeleteGroup(archive: FormatAVault, opts: any, groupID: GroupID) {
    archive.groups = archive.groups || [];
    const { group, index } = findGroupContainingGroupID(archive, groupID);
    if (!group) {
        throw new Error(`Invalid group ID: ${groupID}`);
    }
    group.groups.splice(index, 1);
}

export function executeDeleteGroupAttribute(
    archive: FormatAVault,
    opts: any,
    groupID: GroupID,
    attribute: string
) {
    archive.groups = archive.groups || [];
    const group = findGroupByID(archive.groups, groupID);
    if (!group) {
        throw new Error(`Group not found for ID: ${groupID}`);
    }
    group.attributes = group.attributes || {};
    const deleted = delete group.attributes[attribute];
    if (!deleted) {
        throw new Error(`Failed deleting attribute: ${attribute}`);
    }
}

export function executeFormat(archive: FormatAVault, opts: any, format: string) {
    if (opts.shareID) {
        // Don't set archive format from a share
        return;
    }
    if (archive.format) {
        throw new Error("Format already set");
    }
    archive.format = format;
}

export function executeMoveEntry(
    archive: FormatAVault,
    opts: any,
    entryID: EntryID,
    groupID: GroupID
) {
    archive.groups = archive.groups || [];
    const { group: originGroup, index: originIndex } = findGroupContainingEntryID(
        archive.groups,
        entryID
    );
    if (!originGroup) {
        throw new Error(`Invalid entry ID: ${entryID}`);
    }
    const targetGroup = findGroupByID(archive.groups, groupID);
    if (!targetGroup) {
        throw new Error("Invalid group ID");
    }
    const [movedEntry] = originGroup.entries.splice(originIndex, 1);
    targetGroup.entries = targetGroup.entries || [];
    targetGroup.entries.push(movedEntry);
    movedEntry.parentID = groupID;
}

export function executeMoveGroup(
    archive: FormatAVault,
    opts: any,
    groupID: GroupID,
    targetGroupID: GroupID
) {
    archive.groups = archive.groups || [];
    const { group: originGroup, index: originIndex } = findGroupContainingGroupID(archive, groupID);
    if (!originGroup) {
        throw new Error(`Invalid group ID: ${groupID}`);
    }
    const targetGroup =
        targetGroupID.length === 1 && parseInt(targetGroupID, 10) === 0
            ? archive
            : findGroupByID(archive.groups, targetGroupID);
    if (!targetGroup) {
        throw new Error(`Invalid target group ID: ${targetGroupID}`);
    }
    const [movedGroup] = originGroup.groups.splice(originIndex, 1);
    targetGroup.groups = targetGroup.groups || [];
    targetGroup.groups.push(movedGroup);
    movedGroup.parentID = targetGroupID;
}

export function executePad() {
    // Comment has no action
}

export function executeSetArchiveAttribute(
    archive: FormatAVault,
    opts: any,
    attribute: string,
    value: string
) {
    archive.attributes = archive.attributes || {};
    archive.attributes[attribute] = value;
}

export function executeSetEntryAttribute(
    archive: FormatAVault,
    opts: any,
    entryID: EntryID,
    attribute: string,
    value: string
) {
    archive.groups = archive.groups || [];
    const entry = findEntryByID(archive.groups, entryID);
    if (!entry) {
        throw new Error(`Entry not found for ID: ${entryID}`);
    }
    entry.attributes = entry.attributes || {};
    const previousValue =
        typeof entry.attributes[attribute] === "string" ? entry.attributes[attribute] : null;
    entry.attributes[attribute] = value;
    entry.history = entry.history || [];
    entry.history.push(
        generateEntryLegacyHistoryItem(attribute, EntryPropertyType.Attribute, previousValue, value)
    );
}

export function executeSetEntryProperty(
    archive: FormatAVault,
    opts: any,
    entryID: EntryID,
    property: string,
    value: string
) {
    archive.groups = archive.groups || [];
    const entry = findEntryByID(archive.groups, entryID);
    if (!entry) {
        throw new Error(`Entry not found for ID: ${entryID}`);
    }
    entry.properties = entry.properties || {};
    const previousValue =
        typeof entry.properties[property] === "string" ? entry.properties[property] : null;
    entry.properties[property] = value;
    entry.history = entry.history || [];
    entry.history.push(
        generateEntryLegacyHistoryItem(property, EntryPropertyType.Property, previousValue, value)
    );
}

export function executeSetGroupAttribute(
    archive: FormatAVault,
    opts: any,
    groupID: GroupID,
    attribute: string,
    value: string
) {
    archive.groups = archive.groups || [];
    const group = findGroupByID(archive.groups, groupID);
    if (!group) {
        throw new Error(`Group not found for ID: ${groupID}`);
    }
    group.attributes = group.attributes || {};
    group.attributes[attribute] = value;
}

export function executeTitleGroup(
    archive: FormatAVault,
    opts: any,
    groupID: GroupID,
    title: string
) {
    archive.groups = archive.groups || [];
    const group = findGroupByID(archive.groups, groupID);
    if (!group) {
        throw new Error(`Group not found for ID: ${groupID}`);
    }
    group.title = title;
}