├── .github ├── pull_request_template.md └── workflows │ ├── deploy-documentation.yml │ └── php.yml ├── .gitignore ├── .phpcs.xml ├── ActionScripts ├── ActionZabbix │ ├── ActionZabbix.json │ ├── ActionZabbix.php │ ├── composer.json │ └── composer.lock ├── NotificationDiscord │ ├── NotificationDiscord.json │ ├── NotificationDiscord.php │ ├── composer.json │ └── composer.lock ├── NotificationMail │ ├── NotificationMail.json │ ├── NotificationMail.php │ ├── README.md │ ├── composer.json │ ├── composer.lock │ └── templates │ │ ├── information.html │ │ └── newItemITSM.html └── autoload.php ├── LICENSE ├── Makefile ├── README.md ├── SPECS ├── ITIL4.md └── specs.md ├── bin └── cli ├── composer.json ├── composer.lock ├── config └── current │ └── .gitkeep ├── db └── migrations │ ├── 20200719120001_changes.php │ ├── 20200719130001_menus.php │ ├── 20200719140001_menuitems.php │ ├── 20200719150001_menuitemcustoms.php │ ├── 20200719160001_typepanels.php │ ├── 20200719170001_typepanelitems.php │ ├── 20200720091602_properties.php │ ├── 20200720091613_types.php │ ├── 20200720091620_property_type.php │ ├── 20200720091657_propertylists.php │ ├── 20200720091660_propertytypelinks.php │ ├── 20200720091661_propertyitemlinks.php │ ├── 20200720091683_propertyallowedtypes.php │ ├── 20200720120829_items.php │ ├── 20200720120838_itemstatus.php │ ├── 20200720133434_item_property.php │ ├── 20200725083703_relationshiptype.php │ ├── 20200725083720_item_item.php │ ├── 20200803061448_fusioninventory_item.php │ ├── 20200803061453_fusioninventory_property.php │ ├── 20200913080339_rules_creation.php │ ├── 20220812125817_permissiondataproperty.php │ ├── 20220812130039_permissiondata.php │ ├── 20220812130052_permissionstructure.php │ ├── 20220812130059_permissionstructurecustom.php │ ├── 20220812130109_item_role.php │ ├── 20220812130116_roles.php │ ├── 20220903062128_fusioninventory_data_model.php │ ├── 20220904071848_fill_userparams.php │ ├── 20220905112557_fill_roles.php │ └── 20220918075728_audit.php ├── devtools ├── README.md ├── _generateFileStructureTestSchemaRESTAPI.php ├── apidoc │ ├── apidoc.json │ ├── package.json │ └── yarn.lock ├── generate_apidoc.sh └── template │ ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ ├── glyphicons-halflings-regular.woff2 │ ├── oxygen-v15-latin-300.eot │ ├── oxygen-v15-latin-300.svg │ ├── oxygen-v15-latin-300.ttf │ ├── oxygen-v15-latin-300.woff │ ├── oxygen-v15-latin-300.woff2 │ ├── oxygen-v15-latin-700.eot │ ├── oxygen-v15-latin-700.svg │ ├── oxygen-v15-latin-700.ttf │ ├── oxygen-v15-latin-700.woff │ ├── oxygen-v15-latin-700.woff2 │ ├── oxygen-v15-latin-regular.eot │ ├── oxygen-v15-latin-regular.svg │ ├── oxygen-v15-latin-regular.ttf │ ├── oxygen-v15-latin-regular.woff │ ├── oxygen-v15-latin-regular.woff2 │ ├── roboto-v30-latin-300.eot │ ├── roboto-v30-latin-300.svg │ ├── roboto-v30-latin-300.ttf │ ├── roboto-v30-latin-300.woff │ ├── roboto-v30-latin-300.woff2 │ ├── roboto-v30-latin-500.eot │ ├── roboto-v30-latin-500.svg │ ├── roboto-v30-latin-500.ttf │ ├── roboto-v30-latin-500.woff │ ├── roboto-v30-latin-500.woff2 │ ├── roboto-v30-latin-700.eot │ ├── roboto-v30-latin-700.svg │ ├── roboto-v30-latin-700.ttf │ ├── roboto-v30-latin-700.woff │ ├── roboto-v30-latin-700.woff2 │ ├── roboto-v30-latin-regular.eot │ ├── roboto-v30-latin-regular.svg │ ├── roboto-v30-latin-regular.ttf │ ├── roboto-v30-latin-regular.woff │ ├── roboto-v30-latin-regular.woff2 │ ├── source-code-pro-v21-latin-300.eot │ ├── source-code-pro-v21-latin-300.svg │ ├── source-code-pro-v21-latin-300.ttf │ ├── source-code-pro-v21-latin-300.woff │ ├── source-code-pro-v21-latin-300.woff2 │ ├── source-code-pro-v21-latin-600.eot │ ├── source-code-pro-v21-latin-600.svg │ ├── source-code-pro-v21-latin-600.ttf │ ├── source-code-pro-v21-latin-600.woff │ ├── source-code-pro-v21-latin-600.woff2 │ ├── source-code-pro-v21-latin-700.eot │ ├── source-code-pro-v21-latin-700.svg │ ├── source-code-pro-v21-latin-700.ttf │ ├── source-code-pro-v21-latin-700.woff │ ├── source-code-pro-v21-latin-700.woff2 │ ├── source-code-pro-v21-latin-regular.eot │ ├── source-code-pro-v21-latin-regular.svg │ ├── source-code-pro-v21-latin-regular.ttf │ ├── source-code-pro-v21-latin-regular.woff │ └── source-code-pro-v21-latin-regular.woff2 │ ├── img │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── favicon.ico │ └── logo.png │ ├── index.html │ └── src │ ├── css │ └── main.css │ ├── diff_match_patch.mjs │ ├── hb_helpers.js │ ├── jsonifier.mjs │ ├── main.js │ ├── sampreq_url_processor.mjs │ ├── send_sample_request.js │ └── webpack.config.js ├── docker ├── Dockerfile ├── bin │ ├── cli │ ├── composer │ ├── mariadb │ └── php ├── docker-compose.yml ├── install-composer.sh └── nginx.conf ├── phpstan.neon ├── public └── index.php ├── src ├── Route.php ├── config.php ├── constant.php └── v1 │ ├── Common.php │ ├── Controllers │ ├── Cli │ │ ├── Common.php │ │ ├── EnvironmentCreate.php │ │ ├── EnvironmentList.php │ │ ├── EnvironmentSwitch.php │ │ ├── Install.php │ │ └── Reset.php │ ├── Config │ │ ├── Permissiondata.php │ │ ├── Permissiondataproperty.php │ │ ├── Permissionstructure.php │ │ ├── Permissionstructurecustom.php │ │ ├── Property.php │ │ ├── Role.php │ │ └── Type.php │ ├── Display │ │ ├── Menu │ │ │ ├── Menu.php │ │ │ ├── Menuitem.php │ │ │ └── Menuitemcustom.php │ │ └── Type │ │ │ ├── Typepanel.php │ │ │ └── Typepanelitem.php │ ├── Fusioninventory.php │ ├── Item.php │ ├── Log │ │ ├── Audit.php │ │ └── Change.php │ ├── Ping.php │ ├── Rule.php │ ├── Rules │ │ ├── ActionScript.php │ │ ├── GetType.php │ │ └── SearchItem.php │ ├── Status.php │ ├── Token.php │ └── User.php │ ├── Models │ ├── Common.php │ ├── Config │ │ ├── Permissiondata.php │ │ ├── Permissiondataproperty.php │ │ ├── Permissionstructure.php │ │ ├── Permissionstructurecustom.php │ │ ├── Property.php │ │ ├── Propertyallowedtype.php │ │ ├── Propertyitemlink.php │ │ ├── Propertylist.php │ │ ├── Propertytypelink.php │ │ ├── Relationshiptype.php │ │ ├── Role.php │ │ └── Type.php │ ├── Display │ │ ├── Menu │ │ │ ├── Menu.php │ │ │ ├── Menuitem.php │ │ │ └── Menuitemcustom.php │ │ └── Type │ │ │ ├── Typepanel.php │ │ │ ├── Typepanelcustom.php │ │ │ └── Typepanelitem.php │ ├── Fusioninventoryitem.php │ ├── Fusioninventoryproperty.php │ ├── Item.php │ ├── ItemProperty.php │ ├── ItemState.php │ ├── Log │ │ ├── Audit.php │ │ └── Change.php │ ├── Rule.php │ ├── Ruleaction.php │ ├── Rulecriterium.php │ └── Useraudit.php │ ├── Permission.php │ ├── Post.php │ ├── Query.php │ ├── Read.php │ ├── Templates │ ├── Incident_management.json │ ├── Knowledge_management.json │ ├── incident_contracts.json │ └── tmp_computer.json │ └── Validator │ ├── Dateformat.php │ ├── Datetimeformat.php │ ├── Maxchars.php │ ├── Minchars.php │ ├── Timeformat.php │ └── Type.php └── tests ├── RESTAPI ├── .eslintrc.json ├── 00_status.js ├── 00_token.js ├── 01_type │ ├── 0_type-GET.js │ ├── 1_type-POST.js │ ├── 2_type-id-PATCH.js │ └── 3_type-id-DELETE.js ├── 02_items │ ├── 0_create_type.js │ ├── 1_type-items-POST.js │ ├── 2_type-items-GET.js │ ├── 3_item-id-PATCH.js │ ├── 4_type-items-POST.js │ ├── 6_items-PATCH-property.js │ ├── 8_item-id-DELETE.js │ └── 9_delete_types.js ├── 03_itemsHeaders │ ├── 1_create_15_items.js │ ├── 2_type-items-GET.js │ └── 8_item-id-DELETE.js ├── 04_itemProperties │ ├── boolean │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValueTrue.js │ ├── common.js │ ├── commonCreateItem.js │ ├── date │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueCurrentdate.js │ │ ├── 6_workingDefaultValueDate.js │ │ └── 7_workingDefaultValueNull.js │ ├── datetime │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueCurrentdatetime.js │ │ ├── 6_workingDefaultValueDatetime.js │ │ └── 7_workingDefaultValueNull.js │ ├── decimal │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueDecimal.js │ │ └── 6_workingDefaultValueNull.js │ ├── integer │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueInteger.js │ │ └── 6_workingDefaultValueNull.js │ ├── itemlink │ │ ├── 0_dataproviders.js │ │ ├── 1_create_items.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueItemlink.js │ │ ├── 6_workingDefaultValueNull.js │ │ ├── 7_allowedtypes.js │ │ └── 8_delete_items.js │ ├── itemlinks │ │ ├── 1_create_items.js │ │ ├── 2_dataproviders.js │ │ ├── 3_badDefaultValue.js │ │ ├── 4_badValue.js │ │ ├── 5_workingDefaultValueItemlinks.js │ │ ├── 6_workingDefaultValueNull.js │ │ ├── 7_allowedtypes.js │ │ └── 8_delete_items.js │ ├── list │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueList.js │ │ ├── 6_workingDefaultValueNull.js │ │ └── 7_add_delete_listvalues.js │ ├── number │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValueNumber.js │ ├── password │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValuePassword.js │ ├── passwordhash │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValuePassword.js │ ├── propertylink │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValuePropertylink.js │ ├── string │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValueString.js │ ├── text │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValueText.js │ ├── time │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_workingDefaultValueCurrentime.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValueTime.js │ ├── typelink │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValueTypelink.js │ └── typelinks │ │ ├── 1_dataproviders.js │ │ ├── 2_badDefaultValue.js │ │ ├── 3_badValue.js │ │ ├── 4_canbenullNo.js │ │ ├── 5_workingDefaultValueNull.js │ │ └── 6_workingDefaultValueTypelinks.js ├── 05_itemsTree │ ├── 1_createType.js │ ├── 2_createRootItem.js │ ├── 3_createSub1Item.js │ ├── 4_createItemInErrors.js │ ├── 5_deleteSub1Item.js │ ├── 6_deleteRootItem.js │ └── 7_deleteType.js ├── 06_itemsTreeMultipleRoots │ ├── 1_createType.js │ ├── 2_createRootItem.js │ ├── 3_createSub1Item.js │ ├── 4_createSecondRootItem.js │ ├── 5_createItemInErrors.js │ ├── 6_deleteSub1Item.js │ ├── 7_deleteRootItem.js │ └── 8_deleteType.js ├── 07_protectedSystem │ ├── 1_type-delete-error-system.js │ ├── 2_property-delete-error-system.js │ └── 3_item-delete-error-system.js ├── 08_roles │ ├── 1_none │ │ ├── 1_create-role.js │ │ ├── 2_attach-role-user.js │ │ ├── 3_connect-user-check-permissions.js │ │ └── 8_delete-role.js │ ├── 2_grant │ │ ├── 1_create-role.js │ │ ├── 2_attach-role-user.js │ │ ├── 3_connect-user-check-permissions.js │ │ ├── 7_delete-laptop.js │ │ └── 8_delete-role.js │ └── 3_custom │ │ ├── data │ │ ├── 01_create-role.js │ │ ├── 02_attach-role-user.js │ │ ├── 03_laptop-create.js │ │ ├── 04_laptop-update.js │ │ ├── 05_laptop-view.js │ │ ├── 06_laptop-softdelete.js │ │ ├── 07_laptop-delete.js │ │ ├── 30_delete-laptop.js │ │ └── 31_delete-role.js │ │ ├── data_property │ │ ├── 01_create-role.js │ │ ├── 02_attach-role-user.js │ │ ├── 03_laptop-create.js │ │ ├── 04_laptop-view-property.js │ │ ├── 05_laptop-update-property.js │ │ ├── 30_delete-laptop.js │ │ └── 31_delete-role.js │ │ ├── structure │ │ ├── property │ │ │ ├── 01_create-role.js │ │ │ ├── 02_attach-role-user.js │ │ │ ├── 03_get_properties.js │ │ │ ├── 04_create_properties.js │ │ │ ├── 05_update_properties.js │ │ │ ├── 06_softdelete_properties.js │ │ │ ├── 07_delete_properties.js │ │ │ └── 31_delete-role.js │ │ ├── role │ │ │ ├── 01_create-role.js │ │ │ ├── 02_attach-role-user.js │ │ │ ├── 03_get_roles.js │ │ │ ├── 04_create_role.js │ │ │ ├── 05_update_roles.js │ │ │ ├── 06_softdelete_roles.js │ │ │ ├── 07_delete_roles.js │ │ │ └── 31_delete-role.js │ │ └── type │ │ │ ├── 01_create-role.js │ │ │ ├── 02_attach-role-user.js │ │ │ ├── 03_get_types.js │ │ │ ├── 04_create_type.js │ │ │ ├── 05_update_types.js │ │ │ ├── 06_softdelete_types.js │ │ │ ├── 07_delete_types.js │ │ │ └── 31_delete-role.js │ │ └── structure_custom │ │ ├── property │ │ ├── 01_create-role.js │ │ ├── 02_attach-role-user.js │ │ ├── 03_create_property.js │ │ ├── 04_get_properties.js │ │ ├── 05_update_properties.js │ │ ├── 06_softdelete_properties.js │ │ ├── 07_delete_properties.js │ │ └── 31_delete-role.js │ │ ├── role │ │ ├── 01_create-role.js │ │ ├── 02_attach-role-user.js │ │ ├── 03_create_role.js │ │ ├── 04_get_roles.js │ │ ├── 05_update_roles.js │ │ ├── 06_softdelete_roles.js │ │ ├── 07_delete_roles.js │ │ └── 31_delete-role.js │ │ └── type │ │ ├── 01_create-role.js │ │ ├── 02_attach-role-user.js │ │ ├── 03_create_type.js │ │ ├── 04_get_types.js │ │ ├── 05_update_types.js │ │ ├── 06_softdelete_types.js │ │ ├── 07_delete_types.js │ │ └── 31_delete-role.js ├── 09_organizations │ ├── items │ │ ├── 00_createType.js │ │ ├── 01_create-organization-POST.js │ │ ├── 02_create-users-POST.js │ │ ├── 03_token-users.js │ │ ├── 04_create-items-POST.js │ │ ├── 05_get_all_items_rootorg.js │ │ ├── 06_get_all_items_sub1org.js │ │ ├── 07_get_all_items_sub2org.js │ │ ├── 08_get_each_items_ok_notok.js │ │ ├── 09_items-DELETE.js │ │ ├── 10_delete-types.js │ │ ├── 11_delete-users.js │ │ └── 12_delete-organizations.js │ ├── properties │ │ ├── 01_create-organization-POST.js │ │ ├── 02_create-users-POST.js │ │ ├── 03_token-users.js │ │ ├── 04_create-properties-POST.js │ │ ├── 05_create-types-POST.js │ │ ├── 06_attach_properties_to_type1_byadmin.js │ │ ├── 07_attach_properties_to_typesub1_byadmin.js │ │ ├── 08_attach_properties_to_type2_byadmin.js │ │ ├── 09_detach_properties_to_type2_byadmin.js │ │ ├── 10_attach_properties_to_type1_byuser1.js │ │ ├── 11_attach_properties_to_type2_byuser1.js │ │ ├── 12_detach_properties_to_type2_byadmin.js │ │ ├── 13_attach_properties_to_type1_byuser1.js │ │ ├── 14_attach_properties_to_type2_byuser1.js │ │ ├── 30_delete-types.js │ │ ├── 31_properties-DELETE.js │ │ ├── 32_delete-users.js │ │ └── 33_delete-organizations.js │ └── types │ │ ├── 01_create-organization-POST.js │ │ ├── 02_create-users-POST.js │ │ ├── 03_token-users.js │ │ ├── 04_create-types-POST.js │ │ ├── 05_get_all_types_user_admin.js │ │ ├── 06_get_all_types_user_user1.js │ │ ├── 07_get_all_types_user_user2.js │ │ ├── 21_types-DELETE.js │ │ ├── 22_delete-users.js │ │ └── 23_delete-organizations.js ├── 10_usereventTimestamp │ ├── 01_create-users-POST.js │ ├── 02_token-users.js │ ├── 03_create-property.js │ ├── 04_create-type.js │ ├── 05_create-item.js │ ├── 06_update-property.js │ ├── 07_update-type.js │ ├── 08_update-item.js │ ├── 09_softdelete-property.js │ ├── 10_softdelete-item.js │ ├── 11_softdelete-type.js │ ├── 12_restore-property.js │ ├── 13_restore-type.js │ ├── 14_restore-item.js │ ├── 15_attach-property-to-type.js │ ├── 16_update-property-value-of-item.js │ ├── 31_delete-users.js │ ├── 32_check-item.js │ ├── 33_check-type.js │ ├── 34_check-property.js │ ├── 35_delete-item.js │ ├── 36_delete-type.js │ ├── 37_delete-property.js │ └── README.md ├── 15_userparams │ └── 0_type-GET.js ├── 16_actionscripts │ ├── actionZabbix │ │ ├── 1_configutationRule.js │ │ ├── 2_createItem.js │ │ └── 2_deleteRule.js │ └── notificationMail │ │ ├── 1_configutationRule.js │ │ ├── 2_createItem.js │ │ └── 2_deleteRule.js ├── 17_logAudit │ ├── 1_connection.js │ ├── 2_property.js │ ├── 3_type.js │ └── 4_item.js ├── 18_items_unique_name │ ├── with_unique_name.js │ └── without_unique_name.js ├── 19_refreshToken │ ├── 01_create-users-POST.js │ ├── 02_token-users.js │ └── 05_delete-users.js ├── 20_getToken │ ├── 01_create-users-POST.js │ ├── 02_token-users.js │ └── 05_delete-users.js ├── 21_itemPropertyWhenAddDeletePropertyToType │ ├── 1_createType.js │ ├── 2_createItem.js │ ├── 3_addNewPropertyToType.js │ ├── 4_deletePropertyToType.js │ ├── 5_addNewPropertyToTypeByTemplate.js │ ├── 6_deleteItem.js │ └── 7_deleteType.js ├── 22_changeslogs │ ├── 1_properties │ │ ├── 1_create_property.js │ │ ├── 2_getall_properties.js │ │ ├── 3_update_property.js │ │ ├── 4_softdelete_property.js │ │ └── 9_delete_property.js │ ├── 2_type │ │ ├── 1_create_type.js │ │ ├── 2_getall_types.js │ │ ├── 3_update_type.js │ │ ├── 4_softdelete_property.js │ │ └── 9_delete_type.js │ └── 3_item │ │ ├── 01_prepare_type.js │ │ ├── 02_create_item.js │ │ ├── 03_getall_item.js │ │ ├── 04_update_item.js │ │ ├── 05_softdelete_item.js │ │ ├── 10_update_item_property_boolean.js │ │ ├── 11_update_item_property_date.js │ │ ├── 12_update_item_property_datetime.js │ │ ├── 13_update_item_property_decimal.js │ │ ├── 14_update_item_property_integer.js │ │ ├── 15_update_item_property_itemlink.js │ │ ├── 16_update_item_property_itemlinks.js │ │ ├── 17_update_item_property_list.js │ │ ├── 18_update_item_property_number.js │ │ ├── 19_update_item_property_propertylink.js │ │ ├── 20_update_item_property_string.js │ │ ├── 21_update_item_property_text.js │ │ ├── 22_update_item_property_time.js │ │ ├── 23_update_item_property_typelink.js │ │ ├── 24_update_item_property_typelinks.js │ │ ├── 51_delete_item.js │ │ └── 52_delete_type_properties.js ├── 23_display │ ├── 1_menus │ │ ├── 1_menu-POST.js │ │ ├── 2_menu-GET.js │ │ ├── 3_menu-id-PATCH.js │ │ ├── 4_menu-id-DELETE.js │ │ └── 5_menu-positions.js │ ├── 2_menuitems │ │ ├── 0_dataproviders.js │ │ ├── 1_menuitem-POST.js │ │ ├── 2_menuitem-GET.js │ │ ├── 3_menuitem-DELETE-type.js │ │ ├── 4_menuitem-id-PATCH.js │ │ ├── 5_menuitem-id-DELETE.js │ │ └── 6_menuitem-positions.js │ ├── 3_menuitemcustoms │ │ ├── 1_prepare-POST.js │ │ ├── 2_menuitemcustom-POST.js │ │ ├── 3_menuitemcustom-GET.js │ │ ├── 5_menuitemcustom-DELETE.js │ │ └── 9_finish.js │ ├── 4_typepanel │ │ ├── 1_type-autoadd.js │ │ ├── 2_type-add-panel.js │ │ ├── 3_type-transfert-properties.js │ │ ├── 4_special-case-default-panel.js │ │ ├── 5_special-case-icons.js │ │ └── 9_finish.js │ └── 5_typepanelitem │ │ ├── 1_type-autoadd.js │ │ ├── 2_GET-panelitems.js │ │ ├── 3_PATCH-panelitems.js │ │ └── 9_finish.js ├── 25_itemSearch │ ├── 000_dataproviders.js │ ├── 001_prepare-type.js │ ├── 002_prepare-add-data.js │ ├── 003_search-name.js │ ├── 004_search-prop-boolean.js │ ├── 005_search-prop-date.js │ ├── 006_search-prop-datetime.js │ ├── 007_search-prop-decimal.js │ ├── 008_search-prop-integer.js │ ├── 009_search-prop-itemlink.js │ ├── 010_search-prop-itemlinks.js │ ├── 011_search-prop-list.js │ ├── 012_search-prop-number.js │ ├── 013_search-prop-propertylink.js │ ├── 014_search-prop-string.js │ ├── 015_search-prop-text.js │ ├── 016_search-prop-time.js │ ├── 017_search-prop-typelink.js │ ├── 018_search-prop-typelinks.js │ ├── 103_search-name-notok.js │ ├── 104_search-prop-boolean-notok.js │ ├── 105_search-prop-date-notok.js │ ├── 106_search-prop-datetime-notok.js │ ├── 107_search-prop-decimal-notok.js │ ├── 108_search-prop-integer-notok.js │ ├── 109_search-prop-itemlink-notok.js │ ├── 110_search-prop-itemlinks-notok.js │ ├── 111_search-prop-list-notok.js │ ├── 112_search-prop-number-notok.js │ ├── 113_search-prop-propertylink-notok.js │ ├── 114_search-prop-string.js │ ├── 115_search-prop-text.js │ ├── 116_search-prop-time-notok.js │ ├── 117_search-prop-typelink-notok.js │ ├── 118_search-prop-typelinks-notok.js │ └── 999_clean-data.js ├── 26_items_users_properties_hidden │ ├── 1_type-items-POST.js │ ├── 2_type-items-GET.js │ ├── 3_item-id-PATCH.js │ └── 8_item-id-DELETE.js ├── 27_passwordUserLogin │ ├── 01_create-users-with-passwordPOST.js │ ├── 02_token-users.js │ ├── 03_update_password_to_default.js │ ├── 04_update_password.js │ └── 05_delete-users.js ├── README.md ├── fusionsuite.conf ├── mountebank │ ├── imposters.ejs │ └── imposters │ │ ├── smtp.ejs │ │ └── zabbix.ejs ├── package.json ├── schemaValidation │ ├── .old │ ├── commonSchema.js │ ├── ping │ │ └── get │ │ │ ├── schema.json │ │ │ └── schema.json.old │ └── v1 │ │ ├── items │ │ ├── post │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ ├── type │ │ │ └── {typeid} │ │ │ │ └── get │ │ │ │ ├── schema.json │ │ │ │ └── schema.json.old │ │ └── {id} │ │ │ ├── delete │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ │ ├── get │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ │ ├── patch │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ │ └── property │ │ │ └── {propertyid} │ │ │ ├── patch │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ │ └── typelinks │ │ │ ├── post │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ │ └── {typelinkid} │ │ │ └── delete │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ ├── rules │ │ ├── {id} │ │ │ └── delete │ │ │ │ ├── schema.json │ │ │ │ └── schema.json.old │ │ └── {type} │ │ │ ├── get │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ │ ├── post │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ │ └── {id} │ │ │ ├── action │ │ │ └── post │ │ │ │ ├── schema.json │ │ │ │ └── schema.json.old │ │ │ ├── criteria │ │ │ └── post │ │ │ │ ├── schema.json │ │ │ │ └── schema.json.old │ │ │ └── get │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ ├── status │ │ └── get │ │ │ ├── schema.json │ │ │ ├── schema.json.old │ │ │ └── test.js │ │ ├── token │ │ └── post │ │ │ ├── schema.json │ │ │ └── schema.json.old │ │ └── userparams │ │ └── get │ │ ├── schema.json │ │ └── schema.json.old ├── testDatabaseAccess.php ├── yarn-error.log └── yarn.lock ├── performances ├── README.md ├── itemsUniqueId.js └── test.js └── units └── v1 └── Controllers └── Cli ├── EnvironmentCreateTest.php └── EnvironmentSwitchTest.php /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Changes proposed in this pull request: 2 | 3 | - 4 | - 5 | - 6 | 7 | How to test the feature manually: 8 | 9 | 1. 10 | 2. 11 | 3. 12 | 13 | Pull request checklist: 14 | 15 | - [ ] code is manually tested 16 | - [ ] tests are updated 17 | - [ ] commit messages are relevant 18 | - [ ] documentation is updated (including code comments, commit messages…) 19 | 20 | _If you think one of the item isn’t applicable to the PR, please check it 21 | anyway and precise `N/A` next to it._ 22 | 23 | Related to # 24 | -------------------------------------------------------------------------------- /.github/workflows/deploy-documentation.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | 6 | env: 7 | NODE_VERSION: '16.x' 8 | 9 | jobs: 10 | buildAndDeploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Set up Node.js 16 | uses: actions/setup-node@v2 17 | with: 18 | node-version: ${{ env.NODE_VERSION }} 19 | cache: 'yarn' 20 | cache-dependency-path: devtools/apidoc/yarn.lock 21 | 22 | - name: yarn install 23 | run: | 24 | cd devtools/apidoc/ 25 | yarn install 26 | 27 | - name: generate the documentation 28 | run: | 29 | cd devtools/ 30 | ./generate_apidoc.sh 31 | 32 | - name: Deploy with rsync 33 | uses: "Pendect/action-rsyncer@v1.1.0" 34 | env: 35 | DEPLOY_KEY: ${{ secrets.SSH_DOCUMENTATION_KEY }} 36 | with: 37 | flags: '-avzr --delete' 38 | options: '' 39 | ssh_options: '' 40 | src: 'documentation/' 41 | dest: '${{ secrets.SSH_DOCUMENTATION_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DOCUMENTATION_RESTAPI_PATH }}' 42 | 43 | - name: Display status from deploy 44 | run: echo "${{ steps.deploy.outputs.status }}" 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | **/vendor 3 | /documentation 4 | /devtools/apidoc/node_modules 5 | /tests/RESTAPI/node_modules 6 | tests/RESTAPI/mb* 7 | config 8 | devtools/apidoc/logfile.log 9 | -------------------------------------------------------------------------------- /.phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ActionScripts/*/vendor/* 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /ActionScripts/ActionZabbix/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "minimum-stability": "dev", 3 | "require": { 4 | "intellitrend/zabbixapi": "dev-master" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ActionScripts/NotificationDiscord/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "woeler/phpdiscord": "4.*" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /ActionScripts/NotificationMail/README.md: -------------------------------------------------------------------------------- 1 | # Creation steps for templates 2 | For create template: 3 | 4 | 1/ use https://mosaico.io 5 | 2/ update code to use mustache variables: http://mustache.github.io/#demo 6 | 7 | # Useful links 8 | 9 | https://github.com/tijsverkoyen/CssToInlineStyles 10 | https://www.lafabriquedunet.fr/email-marketing/guide/coder-email-html-css/ 11 | https://stackoverflow.com/questions/2229822/best-practices-considerations-when-writing-html-emails 12 | https://www.codeur.com/blog/email-builder-gratuit-sans-coder/ 13 | -------------------------------------------------------------------------------- /ActionScripts/NotificationMail/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "phpmailer/phpmailer": "6.*", 4 | "mustache/mustache": "2.14.*", 5 | "html2text/html2text": "^4.3" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /ActionScripts/NotificationMail/templates/newItemITSM.html: -------------------------------------------------------------------------------- 1 |

{{title}}

2 | 3 | Welcome {{firstname}} 4 | -------------------------------------------------------------------------------- /ActionScripts/autoload.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | $baseFolder = __DIR__; 22 | $folders = scandir($baseFolder); 23 | foreach ($folders as $folder) 24 | { 25 | if ($folder == '.' || $folder == '..') 26 | { 27 | continue; 28 | } 29 | if (is_dir(__DIR__ . '/' . $folder)) 30 | { 31 | require_once __DIR__ . '/' . $folder . '/vendor/autoload.php'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FusionSuite::Backend 2 | 3 | ## Introduction 4 | 5 | It's the backend for the IT Service Management. 6 | 7 | It will offer REST API of data. 8 | 9 | 10 | ## Technologies 11 | 12 | It's written in PHP and use: 13 | 14 | * slim (microframework) 15 | * eloquent (database queries) 16 | * phinx (database migrations) 17 | 18 | ## Install 19 | 20 | Here are the steps to install the backend: 21 | 22 | * install dependencies `composer install` 23 | * configure into phinx.php the database information 24 | * run command `./vendor/bin/phinx migrate` 25 | 26 | 27 | -------------------------------------------------------------------------------- /bin/cli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | . 19 | */ 20 | 21 | require __DIR__ . '/../vendor/autoload.php'; 22 | 23 | use App\v1\Controllers\Cli\Common; 24 | use Ahc\Cli\Output\Cursor; 25 | 26 | $cursor = new Cursor; 27 | echo $cursor->clear(); 28 | 29 | $cliCommon = new Common; 30 | $cliCommon->displayLogo(); 31 | 32 | $version = '1.0.0'; 33 | $app = new Ahc\Cli\Application('cli', $version); 34 | 35 | $app->add(new \App\v1\Controllers\Cli\EnvironmentCreate); 36 | $app->add(new \App\v1\Controllers\Cli\EnvironmentList); 37 | $app->add(new \App\v1\Controllers\Cli\EnvironmentSwitch); 38 | $app->add(new \App\v1\Controllers\Cli\Install); 39 | $app->add(new \App\v1\Controllers\Cli\Reset); 40 | 41 | $app->handle($_SERVER['argv']); 42 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fusionsuite/backend", 3 | "description": "It's the backend part of FusionSuite project", 4 | "type": "project", 5 | "homepage": "https://fusionsuite.org/", 6 | "license": [ 7 | "AGPL-3.0-or-later" 8 | ], 9 | "require": { 10 | "php": "^8.1|^8.2|^8.3", 11 | "slim/slim": "4.*", 12 | "slim/psr7": "1.*", 13 | "robmorgan/phinx": "0.15.*", 14 | "illuminate/database": "10.*", 15 | "tuupola/slim-jwt-auth": "3.*", 16 | "tuupola/base62": "2.*", 17 | "spatie/array-to-xml": "3.2.*", 18 | "hoa/ruler": "^2.17.05.16", 19 | "illuminate/events": "10.*", 20 | "rakit/validation": "^1.4", 21 | "adhocore/cli": "1.6.*", 22 | "genealabs/laravel-pivot-events": "10.*", 23 | "symfony/error-handler": "6.*" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "App\\": "src", 28 | "ActionScripts\\": "ActionScripts" 29 | } 30 | }, 31 | "require-dev": { 32 | "phpstan/phpstan": "1.*", 33 | "squizlabs/php_codesniffer": "3.*", 34 | "phpunit/phpunit": "10.*", 35 | "bmitch/churn-php": "^1.7" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /config/current/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/config/current/.gitkeep -------------------------------------------------------------------------------- /db/migrations/20200720120838_itemstatus.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | declare(strict_types=1); 20 | 21 | use Phinx\Migration\AbstractMigration; 22 | 23 | final class Itemstatus extends AbstractMigration 24 | { 25 | /** 26 | * Change Method. 27 | * 28 | * Write your reversible migrations using this method. 29 | * 30 | * More information on writing migrations is available here: 31 | * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method 32 | * 33 | * Remember to call "create()" or "update()" and NOT "save()" when working 34 | * with the Table class. 35 | */ 36 | public function change(): void 37 | { 38 | // create the table 39 | $table = $this->table('itemstates'); 40 | $table->addColumn('name', 'string') 41 | ->addColumn('created_at', 'datetime') 42 | ->addColumn('updated_at', 'datetime', ['null' => true]) 43 | ->addColumn('deleted_at', 'datetime', ['null' => true]) 44 | ->create(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /db/migrations/20200725083703_relationshiptype.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | declare(strict_types=1); 20 | 21 | use Phinx\Migration\AbstractMigration; 22 | 23 | final class Relationshiptype extends AbstractMigration 24 | { 25 | /** 26 | * Change Method. 27 | * 28 | * Write your reversible migrations using this method. 29 | * 30 | * More information on writing migrations is available here: 31 | * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method 32 | * 33 | * Remember to call "create()" or "update()" and NOT "save()" when working 34 | * with the Table class. 35 | */ 36 | public function change(): void 37 | { 38 | // create the table 39 | $table = $this->table('relationshiptypes'); 40 | $table->addColumn('name', 'string') 41 | ->addColumn('created_at', 'datetime') 42 | ->addColumn('updated_at', 'datetime', ['null' => true]) 43 | ->addColumn('deleted_at', 'datetime', ['null' => true]) 44 | ->create(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /db/migrations/20220905112557_fill_roles.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | declare(strict_types=1); 22 | 23 | use Phinx\Migration\AbstractMigration; 24 | 25 | final class FillRoles extends AbstractMigration 26 | { 27 | /** 28 | * Change Method. 29 | * 30 | * Write your reversible migrations using this method. 31 | * 32 | * More information on writing migrations is available here: 33 | * https://book.cakephp.org/phinx/0/en/migrations.html#the-change-method 34 | * 35 | * Remember to call "create()" or "update()" and NOT "save()" when working 36 | * with the Table class. 37 | */ 38 | public function change(): void 39 | { 40 | // ***** Create admin role ***** // 41 | $role = new \App\v1\Models\Config\Role(); 42 | $role->name = 'admin'; 43 | $role->permissionstructure = 'grant'; 44 | $role->permissiondata = 'grant'; 45 | $role->save(); 46 | 47 | // Attach the default user to the admin role 48 | $role->users()->attach($GLOBALS['user_id']); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /devtools/README.md: -------------------------------------------------------------------------------- 1 | # Template apidoc 2 | 3 | The template is based on the works of https://github.com/ahmed-dinar/apidoc-template 4 | 5 | 6 | -------------------------------------------------------------------------------- /devtools/apidoc/apidoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "REST API FusionSuite backend documentation", 3 | "version": "1.0.0-draft", 4 | "description": "The documentation of REST API (backend FusionSuite)", 5 | "title": "REST API FusionSuite backend documentation", 6 | "order": [ 7 | "Ping", 8 | "Status", 9 | "Authentication", 10 | "GetConfigProperties", 11 | "GetConfigProperty", 12 | "PostConfigProperties", 13 | "PatchConfigProperties", 14 | "GetConfigPropertygroups", 15 | "GetConfigTypes", 16 | "GetConfigType", 17 | "PostConfigTypes", 18 | "PatchConfigTypes", 19 | "DeletConfigTypes", 20 | "PostConfigTypesProperty", 21 | "DeleteConfigTypesProperty", 22 | "PostConfigTypesTemplate" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /devtools/apidoc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "apidoc": "0.51.1", 4 | "apidoc-swagger-3": "^1.0.6", 5 | "apidoc-swagger-converter": "^1.0.9", 6 | "esbuild-loader": "^2.19.0", 7 | "install": "^0.13.0", 8 | "webpack": "^5.66.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /devtools/generate_apidoc.sh: -------------------------------------------------------------------------------- 1 | # Compile by default 2 | rm -fr ../documentation/* 3 | rm ../tests/RESTAPI/schemaValidation/swagger.json 4 | cd apidoc 5 | ./node_modules/.bin/apidoc -i ../../src -o ../../documentation/ -c apidoc.json 6 | # Compile second time with own template (needed because some files not generated only with own like 'main.bundle.js' file 7 | ./node_modules/.bin/apidoc -i ../../src -o ../../documentation/ -c apidoc.json -t ../template/ 8 | # Generate schema json for schema tests from apidoc 9 | ./node_modules/.bin/apidoc-swagger-3 -i ../../src/ -o ../../tests/RESTAPI/schemaValidation/ 10 | cd .. 11 | php _generateFileStructureTestSchemaRESTAPI.php 12 | -------------------------------------------------------------------------------- /devtools/template/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /devtools/template/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /devtools/template/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-300.eot -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-300.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-300.woff -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-300.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-700.eot -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-700.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-700.woff -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-700.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-regular.eot -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-regular.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-regular.woff -------------------------------------------------------------------------------- /devtools/template/fonts/oxygen-v15-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/oxygen-v15-latin-regular.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-300.eot -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-300.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-300.woff -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-300.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-500.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-500.eot -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-500.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-500.woff -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-500.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-700.eot -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-700.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-700.woff -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-700.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-regular.eot -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-regular.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-regular.woff -------------------------------------------------------------------------------- /devtools/template/fonts/roboto-v30-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/roboto-v30-latin-regular.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-300.eot -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-300.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-300.woff -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-300.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-600.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-600.eot -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-600.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-600.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-600.woff -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-600.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-700.eot -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-700.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-700.woff -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-700.woff2 -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-regular.eot -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-regular.ttf -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-regular.woff -------------------------------------------------------------------------------- /devtools/template/fonts/source-code-pro-v21-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/fonts/source-code-pro-v21-latin-regular.woff2 -------------------------------------------------------------------------------- /devtools/template/img/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/img/android-chrome-192x192.png -------------------------------------------------------------------------------- /devtools/template/img/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/img/android-chrome-512x512.png -------------------------------------------------------------------------------- /devtools/template/img/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/img/apple-touch-icon.png -------------------------------------------------------------------------------- /devtools/template/img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/img/favicon-16x16.png -------------------------------------------------------------------------------- /devtools/template/img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/img/favicon-32x32.png -------------------------------------------------------------------------------- /devtools/template/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/img/favicon.ico -------------------------------------------------------------------------------- /devtools/template/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fusionSuite/backend/10729781f13210eaf424781d6d90e1bae02704b3/devtools/template/img/logo.png -------------------------------------------------------------------------------- /devtools/template/src/diff_match_patch.mjs: -------------------------------------------------------------------------------- 1 | import _DiffMatchPatch from 'diff-match-patch'; 2 | 3 | export default class DiffMatchPatch extends _DiffMatchPatch { 4 | constructor (testMode) { 5 | super(); 6 | this.testMode = testMode; 7 | } 8 | 9 | diffMain (text1, text2, optChecklines, optDeadline) { 10 | return super.diff_main(this._stripHtml(text1), this._stripHtml(text2), optChecklines, optDeadline); 11 | } 12 | 13 | diffPrettyHtml (diffs) { 14 | const html = []; 15 | const patternAmp = /&/g; 16 | const patternLt = //g; 18 | const patternPara = /\n/g; 19 | for (let x = 0; x < diffs.length; x++) { 20 | const op = diffs[x][0]; // Operation (insert, delete, equal) 21 | const data = diffs[x][1]; // Text of change. 22 | const text = data.replace(patternAmp, '&').replace(patternLt, '<') 23 | .replace(patternGt, '>').replace(patternPara, '¶
'); 24 | switch (op) { 25 | case _DiffMatchPatch.DIFF_INSERT: 26 | html[x] = '' + text + ''; 27 | break; 28 | case _DiffMatchPatch.DIFF_DELETE: 29 | html[x] = '' + text + ''; 30 | break; 31 | case _DiffMatchPatch.DIFF_EQUAL: 32 | html[x] = '' + text + ''; 33 | break; 34 | } 35 | } 36 | return html.join(''); 37 | } 38 | 39 | diffCleanupSemantic (diffs) { 40 | return this.diff_cleanupSemantic(diffs); 41 | } 42 | 43 | _stripHtml (html) { 44 | // no document object with CLI when running tests 45 | if (this.testMode) { return html; } 46 | const div = document.createElement('div'); 47 | div.innerHTML = html; 48 | return div.textContent || div.innerText || ''; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /devtools/template/src/jsonifier.mjs: -------------------------------------------------------------------------------- 1 | /* 2 | * apidoc 3 | * https://apidocjs.com 4 | * 5 | * Authors: 6 | * Peter Rottmann 7 | * Nicolas CARPi @ Deltablot 8 | * Copyright (c) 2013 inveris OHG 9 | * Licensed under the MIT license. 10 | */ 11 | import pkg from 'lodash'; 12 | const { defaultsDeep } = pkg; 13 | 14 | const setValueToField = (fields, value) => { 15 | const reducer = (acc, item, index, arr) => ({ [item]: index + 1 < arr.length ? acc : value }); 16 | return fields.reduceRight(reducer, {}); 17 | }; 18 | 19 | const fieldsToJson = fields => { 20 | let obj = {}; 21 | fields.forEach(field => { 22 | const line = setValueToField(field[0].split('.'), field[1]); 23 | obj = defaultsDeep(obj, line); 24 | }); 25 | return beautify(obj); 26 | }; 27 | 28 | /** 29 | * Stringify an obj to JSON with spaces 30 | */ 31 | export function beautify (obj) { 32 | return JSON.stringify(obj, null, 4); 33 | } 34 | 35 | export function body2json (context) { 36 | // build an array of fields with their type 37 | const fields = []; 38 | context.forEach(entry => { 39 | let val; 40 | switch (entry.type.toLowerCase()) { 41 | case 'string': 42 | val = entry.defaultValue || ''; 43 | break; 44 | case 'boolean': 45 | val = Boolean(entry.defaultValue) || false; 46 | break; 47 | case 'number': 48 | val = parseInt(entry.defaultValue || 0, 10); 49 | break; 50 | case 'date': 51 | // date field will have default value or formatted date of today in current locale 52 | val = entry.defaultValue || new Date().toLocaleDateString(window.navigator.language); 53 | break; 54 | } 55 | fields.push([entry.field, val]); 56 | }); 57 | return fieldsToJson(fields); 58 | } 59 | -------------------------------------------------------------------------------- /devtools/template/src/sampreq_url_processor.mjs: -------------------------------------------------------------------------------- 1 | /* 2 | * apidoc 3 | * https://apidocjs.com 4 | * 5 | * Authors: 6 | * Peter Rottmann 7 | * Nicolas CARPi @ Deltablot 8 | * Copyright (c) 2013 inveris OHG 9 | * Licensed under the MIT license. 10 | */ 11 | export default class UrlProcessor { 12 | // Replace parameters from url (:id) by the parameters from input values 13 | hydrate (url, queryParameters) { 14 | // The dummy URL base is only used for parses of relative URLs in Node.js. 15 | const parsedUrl = new URL(url, typeof window === 'undefined' ? 'https://dummy.base' : window.location.origin); 16 | const queryParametersChangedInPathname = {}; 17 | 18 | // For API parameters in the URL parts delimited by `/` (e.g. `/:foo/:bar`). 19 | parsedUrl.pathname.split('/').forEach((pathnamePart, i) => { 20 | if (pathnamePart.charAt(0) === ':') { 21 | const realPathnamePart = pathnamePart.slice(1); 22 | 23 | if (typeof queryParameters[realPathnamePart] !== 'undefined') { 24 | parsedUrl.pathname = parsedUrl.pathname.replace(pathnamePart, encodeURIComponent(queryParameters[realPathnamePart])); 25 | queryParametersChangedInPathname[realPathnamePart] = queryParameters[realPathnamePart]; 26 | } 27 | } 28 | }); 29 | 30 | // For API parameters in the URL query string (e.g. `?foo=:foo&bar=:bar`). 31 | for (const key in queryParameters) { 32 | if ( 33 | typeof queryParametersChangedInPathname[key] === 'undefined' || // Avoid adding query parameter if it has already been changed in pathname. 34 | parsedUrl.searchParams.has(key) 35 | ) { 36 | parsedUrl.searchParams.set(key, queryParameters[key]); 37 | } 38 | } 39 | 40 | return parsedUrl.toString(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /devtools/template/src/webpack.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * apidoc 3 | * https://apidocjs.com 4 | * 5 | * Authors: 6 | * Peter Rottmann 7 | * Nicolas CARPi @ Deltablot 8 | * Copyright (c) 2013 inveris OHG 9 | * Licensed under the MIT license. 10 | */ 11 | 12 | /* webpack js bundler config file */ 13 | const path = require('path'); 14 | const { ESBuildMinifyPlugin } = require('esbuild-loader'); 15 | 16 | module.exports = { 17 | entry: path.resolve(__dirname, 'main.js'), 18 | // mode is set at runtime 19 | resolve: { 20 | alias: { 21 | handlebars: 'handlebars/dist/handlebars.min.js', 22 | // use src jquery, not the minified version or it won't be found 23 | jquery: 'jquery/src/jquery', 24 | }, 25 | extensions: ['.js', '.mjs'], 26 | }, 27 | module: { 28 | rules: [ 29 | // expose jquery globally 30 | { 31 | test: require.resolve('jquery'), 32 | loader: 'expose-loader', 33 | options: { 34 | exposes: ['$', 'jQuery'], 35 | }, 36 | }, 37 | ], 38 | }, 39 | output: { 40 | filename: 'main.bundle.js', 41 | // path is set at runtime 42 | }, 43 | optimization: { 44 | minimizer: [ 45 | new ESBuildMinifyPlugin({ 46 | target: 'es2015', 47 | }), 48 | ], 49 | }, 50 | }; 51 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.0-fpm 2 | 3 | ENV COMPOSER_HOME /tmp 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | git \ 7 | libzip-dev \ 8 | unzip \ 9 | && pecl install xdebug \ 10 | && docker-php-ext-install -j$(nproc) zip pdo pdo_mysql \ 11 | && docker-php-ext-enable xdebug \ 12 | && echo "xdebug.mode=coverage" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini; 13 | 14 | COPY install-composer.sh . 15 | RUN sh ./install-composer.sh && rm ./install-composer.sh 16 | -------------------------------------------------------------------------------- /docker/bin/cli: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_PATH=$(dirname $(realpath -s $0)) 4 | export COMPOSE_PROJECT_NAME=fusionsuite-backend 5 | export COMPOSE_FILE=$SCRIPT_PATH/../docker-compose.yml 6 | export USER=$(id -u):$(id -g) 7 | 8 | if [ -z `docker-compose ps -q php` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q php)` ]; then 9 | docker-compose run -T --rm --no-deps php ./bin/cli "$@" 10 | else 11 | docker-compose exec -T php ./bin/cli "$@" 12 | fi 13 | -------------------------------------------------------------------------------- /docker/bin/composer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_PATH=$(dirname $(realpath -s $0)) 4 | export COMPOSE_PROJECT_NAME=fusionsuite-backend 5 | export COMPOSE_FILE=$SCRIPT_PATH/../docker-compose.yml 6 | export USER=$(id -u):$(id -g) 7 | 8 | if [ -z `docker-compose ps -q php` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q php)` ]; then 9 | docker-compose run -T --rm --no-deps php composer "$@" 10 | else 11 | docker-compose exec -T php composer "$@" 12 | fi 13 | -------------------------------------------------------------------------------- /docker/bin/mariadb: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_PATH=$(dirname $(realpath -s $0)) 4 | export COMPOSE_PROJECT_NAME=fusionsuite-backend 5 | export COMPOSE_FILE=$SCRIPT_PATH/../docker-compose.yml 6 | export USER=$(id -u):$(id -g) 7 | 8 | if [ -z `docker-compose ps -q database` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q database)` ]; then 9 | docker-compose run --rm --no-deps database mariadb -u fusionsuite --password=fusionsuite fusionsuite_development "$@" 10 | else 11 | docker-compose exec database mariadb -u fusionsuite --password=fusionsuite fusionsuite_development "$@" 12 | fi 13 | -------------------------------------------------------------------------------- /docker/bin/php: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_PATH=$(dirname $(realpath -s $0)) 4 | export COMPOSE_PROJECT_NAME=fusionsuite-backend 5 | export COMPOSE_FILE=$SCRIPT_PATH/../docker-compose.yml 6 | export USER=$(id -u):$(id -g) 7 | 8 | if [ -z `docker-compose ps -q php` ] || [ -z `docker ps -q --no-trunc | grep $(docker-compose ps -q php)` ]; then 9 | docker-compose run -T --rm --no-deps php php "$@" 10 | else 11 | docker-compose exec -T php php "$@" 12 | fi 13 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | php: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | restart: unless-stopped 9 | ports: 10 | - "9000:9000" 11 | volumes: 12 | - ..:/var/www/html:z 13 | - composer:/tmp 14 | user: $USER 15 | links: 16 | - database 17 | 18 | nginx: 19 | image: nginx:alpine 20 | restart: unless-stopped 21 | ports: 22 | - "8000:8000" 23 | volumes: 24 | - ..:/var/www/html:z 25 | - ./nginx.conf:/etc/nginx/conf.d/default.conf:z 26 | links: 27 | - php 28 | 29 | database: 30 | image: mariadb:10.7 31 | restart: unless-stopped 32 | environment: 33 | - MARIADB_ROOT_PASSWORD=fusionsuite 34 | - MARIADB_USER=fusionsuite 35 | - MARIADB_PASSWORD=fusionsuite 36 | - MARIADB_DATABASE=fusionsuite_development 37 | 38 | volumes: 39 | composer: {} 40 | 41 | networks: 42 | default: 43 | name: fusionsuite-network 44 | -------------------------------------------------------------------------------- /docker/install-composer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Code from https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md 4 | 5 | EXPECTED_CHECKSUM="$(curl https://composer.github.io/installer.sig)" 6 | php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 7 | ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" 8 | 9 | if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ] 10 | then 11 | >&2 echo 'ERROR: Invalid installer checksum' 12 | rm composer-setup.php 13 | exit 1 14 | fi 15 | 16 | php composer-setup.php --install-dir=/usr/local/bin --filename=composer 17 | RESULT=$? 18 | chmod +x /usr/local/bin/composer 19 | rm composer-setup.php 20 | exit $RESULT 21 | -------------------------------------------------------------------------------- /docker/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8000; 3 | server_name localhost; 4 | 5 | root /var/www/html/public; 6 | index index.html index.php; 7 | 8 | error_log /var/log/nginx/error.log; 9 | access_log /var/log/nginx/access.log; 10 | 11 | location / { 12 | fastcgi_pass php:9000; 13 | 14 | fastcgi_param SCRIPT_FILENAME $document_root/index.php$fastcgi_script_name; 15 | include fastcgi_params; 16 | 17 | add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; 18 | add_header X-Frame-Options "SAMEORIGIN" always; 19 | add_header Access-Control-Allow-Origin * always; 20 | add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE' always; 21 | add_header Access-Control-Allow-Credentials true always; 22 | add_header Access-Control-Allow-Headers 'Origin,Content-Type,Accept,Authorization,Cache-Control,Pragma,Expires' always; 23 | add_header Access-Control-Expose-Headers 'X-Total-Count,Content-Range,Link' always; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 0 3 | bootstrapFiles: 4 | - vendor/autoload.php 5 | - ActionScripts/autoload.php 6 | excludePaths: 7 | analyseAndScan: 8 | - ActionScripts/*/vendor/* 9 | -------------------------------------------------------------------------------- /src/config.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | if (!isset($phinxConfig)) 22 | { 23 | $phinxConfig = include(__DIR__ . '/../config/current/database.php'); 24 | } 25 | $environment = $phinxConfig['environments']['default_environment']; 26 | $phinxDatabase = $phinxConfig['environments'][$environment]; 27 | 28 | return [ 29 | 'determineRouteBeforeAppMiddleware' => false, 30 | 'outputBuffering' => false, 31 | 'displayErrorDetails' => true, 32 | 'db' => [ 33 | 'driver' => $phinxDatabase['adapter'], 34 | 'host' => $phinxDatabase['host'], 35 | 'port' => $phinxDatabase['port'], 36 | 'database' => $phinxDatabase['name'], 37 | 'username' => $phinxDatabase['user'], 38 | 'password' => $phinxDatabase['pass'], 39 | 'charset' => $phinxDatabase['charset'], 40 | 'collation' => 'utf8_unicode_ci', 41 | ] 42 | ]; 43 | -------------------------------------------------------------------------------- /src/constant.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | define('TYPE_ORGANIZATION_ID', 1); 22 | define('TYPE_USER_ID', 2); 23 | -------------------------------------------------------------------------------- /src/v1/Controllers/Ping.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Controllers; 22 | 23 | use Psr\Http\Message\ResponseInterface as Response; 24 | use Psr\Http\Message\ServerRequestInterface as Request; 25 | 26 | final class Ping 27 | { 28 | /** 29 | * @api {get} /ping Check if backend answer 30 | * @apiName GetPing 31 | * @apiGroup Ping 32 | * @apiVersion 1.0.0-draft 33 | * 34 | * @apiSuccessExample {text} Success-Response: 35 | * HTTP/1.1 200 OK 36 | * pong 37 | * 38 | */ 39 | public function getPing(Request $request, Response $response, $args): Response 40 | { 41 | $response->getBody()->write('pong'); 42 | return $response; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/v1/Models/Config/Propertyallowedtype.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Config; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Propertyallowedtype extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | 'type_id', 31 | 'property_id', 32 | 'created_at', 33 | 'updated_at' 34 | ]; 35 | } 36 | -------------------------------------------------------------------------------- /src/v1/Models/Config/Propertyitemlink.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Config; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Propertyitemlink extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | 'item_id', 31 | 'property_id', 32 | 'created_at', 33 | 'updated_at' 34 | ]; 35 | } 36 | -------------------------------------------------------------------------------- /src/v1/Models/Config/Propertylist.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Config; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Propertylist extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | // 'property_id', 31 | 'value', 32 | // 'created_at', 33 | // 'updated_at' 34 | ]; 35 | protected $hidden = [ 36 | 'is_type', 37 | ]; 38 | } 39 | -------------------------------------------------------------------------------- /src/v1/Models/Config/Propertytypelink.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Config; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Propertytypelink extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | 'type_id', 31 | 'property_id', 32 | 'created_at', 33 | 'updated_at' 34 | ]; 35 | } 36 | -------------------------------------------------------------------------------- /src/v1/Models/Config/Relationshiptype.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Config; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Relationshiptype extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | 'name', 31 | 'created_at', 32 | 'updated_at' 33 | ]; 34 | protected $hidden = []; 35 | } 36 | -------------------------------------------------------------------------------- /src/v1/Models/Display/Menu/Menu.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Display\Menu; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Menu extends Model 26 | { 27 | protected $appends = [ 28 | 'items' 29 | ]; 30 | protected $visible = [ 31 | 'id', 32 | 'name', 33 | 'icon', 34 | 'position', 35 | 'items', 36 | 'created_at', 37 | 'updated_at', 38 | ]; 39 | 40 | /** 41 | * The attributes that should be cast. 42 | * 43 | * @var array 44 | */ 45 | protected $casts = [ 46 | 'name' => 'string', 47 | 'icon' => 'string', 48 | 'position' => 'integer' 49 | ]; 50 | 51 | public function getItemsAttribute() 52 | { 53 | return []; 54 | } 55 | 56 | public function items() 57 | { 58 | return $this->hasMany('\App\v1\Models\Display\Menu\Menuitem')->orderBy('position'); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/v1/Models/Display/Menu/Menuitem.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Display\Menu; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | use Illuminate\Database\Eloquent\SoftDeletes; 25 | use Illuminate\Database\Capsule\Manager as DB; 26 | 27 | class Menuitem extends Model 28 | { 29 | protected $appends = [ 30 | 'type', 31 | ]; 32 | protected $visible = [ 33 | 'id', 34 | 'name', 35 | 'icon', 36 | 'type', 37 | 'position', 38 | 'menu_id', 39 | 'created_at', 40 | 'updated_at', 41 | ]; 42 | 43 | /** 44 | * The attributes that should be cast. 45 | * 46 | * @var array 47 | */ 48 | protected $casts = [ 49 | 'name' => 'string', 50 | 'icon' => 'string', 51 | 'position' => 'integer' 52 | ]; 53 | 54 | public function getTypeAttribute() 55 | { 56 | $type = \App\v1\Models\Config\Type::find($this->attributes['type_id']); 57 | return $type; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/v1/Models/Display/Menu/Menuitemcustom.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Display\Menu; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | use Illuminate\Database\Eloquent\SoftDeletes; 25 | use Illuminate\Database\Capsule\Manager as DB; 26 | 27 | class Menuitemcustom extends Model 28 | { 29 | protected $appends = [ 30 | 'menuitem', 31 | ]; 32 | protected $visible = [ 33 | 'id', 34 | 'menuitem', 35 | 'position', 36 | 'user_id', 37 | 'created_at', 38 | 'updated_at', 39 | ]; 40 | 41 | protected $hidden = [ 42 | 'user_id' 43 | ]; 44 | 45 | /** 46 | * The attributes that should be cast. 47 | * 48 | * @var array 49 | */ 50 | protected $casts = [ 51 | 'position' => 'integer' 52 | ]; 53 | 54 | public function getMenuitemAttribute() 55 | { 56 | $type = \App\v1\Models\Display\Menu\Menuitem::find($this->attributes['menuitem_id']); 57 | return $type; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/v1/Models/Display/Type/Typepanel.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Display\Type; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | use Illuminate\Database\Eloquent\SoftDeletes; 25 | use Illuminate\Database\Capsule\Manager as DB; 26 | 27 | class Typepanel extends Model 28 | { 29 | protected $appends = [ 30 | ]; 31 | protected $visible = [ 32 | 'id', 33 | 'name', 34 | 'icon', 35 | 'position', 36 | 'displaytype', 37 | 'type_id', 38 | 'items' 39 | ]; 40 | 41 | /** 42 | * The attributes that should be cast. 43 | * 44 | * @var array 45 | */ 46 | protected $casts = [ 47 | 'name' => 'string', 48 | 'icon' => 'string', 49 | 'position' => 'integer' 50 | ]; 51 | 52 | public function getItemsAttribute() 53 | { 54 | return []; 55 | } 56 | 57 | public function items() 58 | { 59 | return $this->hasMany('\App\v1\Models\Display\Type\Typepanelitem')->orderBy('position'); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/v1/Models/Display/Type/Typepanelcustom.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Display\Type; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | use Illuminate\Database\Eloquent\SoftDeletes; 25 | use Illuminate\Database\Capsule\Manager as DB; 26 | 27 | class Typepanelcustom extends Model 28 | { 29 | protected $appends = [ 30 | ]; 31 | protected $visible = [ 32 | 'id', 33 | 'user_id', 34 | 'type_id', 35 | 'panelspositions' 36 | ]; 37 | 38 | /** 39 | * The attributes that should be cast. 40 | * 41 | * @var array 42 | */ 43 | protected $casts = [ 44 | ]; 45 | } 46 | -------------------------------------------------------------------------------- /src/v1/Models/Display/Type/Typepanelitem.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models\Display\Type; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | use Illuminate\Database\Eloquent\SoftDeletes; 25 | use Illuminate\Database\Capsule\Manager as DB; 26 | 27 | class Typepanelitem extends Model 28 | { 29 | protected $appends = [ 30 | ]; 31 | protected $visible = [ 32 | 'id', 33 | 'position', 34 | 'property_id', 35 | 'typepanel_id', 36 | 'timeline_message', 37 | 'timeline_options', 38 | ]; 39 | 40 | /** 41 | * The attributes that should be cast. 42 | * 43 | * @var array 44 | */ 45 | protected $casts = [ 46 | 'position' => 'integer' 47 | ]; 48 | } 49 | -------------------------------------------------------------------------------- /src/v1/Models/Fusioninventoryitem.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Fusioninventoryitem extends Model 26 | { 27 | protected $appends = [ 28 | 'properties' 29 | ]; 30 | protected $visible = [ 31 | 'id', 32 | 'querytype', 33 | 'markup', 34 | 'markup_name', 35 | 'type_id', 36 | 'fusioninventoryitem_id', 37 | 'properties', 38 | 'created_at', 39 | 'updated_at' 40 | ]; 41 | protected $hidden = []; 42 | 43 | public function getPropertiesAttribute() 44 | { 45 | return $this->properties()->get(); 46 | } 47 | 48 | public function properties() 49 | { 50 | return $this->hasMany('App\v1\Models\Fusioninventoryproperty'); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/v1/Models/Fusioninventoryproperty.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Fusioninventoryproperty extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | 'markup', 31 | 'fusioninventoryitem_id', 32 | 'property_id', 33 | 'created_at', 34 | 'updated_at' 35 | ]; 36 | protected $hidden = []; 37 | } 38 | -------------------------------------------------------------------------------- /src/v1/Models/ItemProperty.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models; 22 | 23 | use Illuminate\Database\Eloquent\Relations\Pivot; 24 | 25 | class ItemProperty extends Pivot 26 | { 27 | } 28 | -------------------------------------------------------------------------------- /src/v1/Models/ItemState.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class ItemState extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | 'name', 31 | 'created_at', 32 | 'updated_at' 33 | ]; 34 | protected $hidden = []; 35 | } 36 | -------------------------------------------------------------------------------- /src/v1/Models/Rule.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | use Illuminate\Database\Eloquent\SoftDeletes; 25 | 26 | class Rule extends Model 27 | { 28 | use SoftDeletes; 29 | 30 | protected $appends = [ 31 | 'criteria', 32 | 'actions' 33 | ]; 34 | protected $visible = [ 35 | 'id', 36 | 'name', 37 | 'type', 38 | 'serialized', 39 | 'comment', 40 | 'criteria', 41 | 'actions' 42 | ]; 43 | 44 | protected $hidden = [ 45 | 'serialized' 46 | ]; 47 | 48 | public function getCriteriaAttribute() 49 | { 50 | return $this->criteria()->get(); 51 | } 52 | 53 | public function getActionsAttribute() 54 | { 55 | return $this->actions()->get(); 56 | } 57 | 58 | public function criteria() 59 | { 60 | return $this->hasMany('App\v1\Models\Rulecriterium'); 61 | } 62 | 63 | public function actions() 64 | { 65 | return $this->hasMany('App\v1\Models\Ruleaction'); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/v1/Models/Ruleaction.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Ruleaction extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | 'name', 31 | 'field', 32 | 'type', 33 | 'values', 34 | 'res_in_property_id', 35 | 'comment', 36 | 'created_at', 37 | 'updated_at' 38 | ]; 39 | protected $hidden = []; 40 | } 41 | -------------------------------------------------------------------------------- /src/v1/Models/Rulecriterium.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Models; 22 | 23 | use Illuminate\Database\Eloquent\Model as Model; 24 | 25 | class Rulecriterium extends Model 26 | { 27 | protected $appends = []; 28 | protected $visible = [ 29 | 'id', 30 | 'name', 31 | 'field', 32 | 'comparator', 33 | 'values', 34 | 'comment', 35 | 'created_at', 36 | 'updated_at' 37 | ]; 38 | protected $hidden = []; 39 | } 40 | -------------------------------------------------------------------------------- /src/v1/Post.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1; 22 | 23 | final class Post 24 | { 25 | public static function postHasProperties($obj, $properties) 26 | { 27 | foreach ($properties as $property) 28 | { 29 | if ( 30 | is_null($obj) 31 | || property_exists($obj, $property) === false 32 | ) 33 | { 34 | return false; 35 | } 36 | } 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/v1/Templates/Knowledge_management.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "itemName": "Knowledge base", 4 | "internalname": "knowledgebase", 5 | "panels": [ 6 | { 7 | "name": "Classification", 8 | "properties": [ 9 | { 10 | "name": "Knowledge type", 11 | "internalname": "knowledgetype", 12 | "valuetype": "list", 13 | "regexformat": "", 14 | "listvalues": ["Known solution", "Known workaround", "Known error"], 15 | "unit": "", 16 | "default": "", 17 | "description": "" 18 | }, 19 | { 20 | "name": "Description", 21 | "internalname": "description", 22 | "valuetype": "string", 23 | "regexformat": "", 24 | "listvalues": [], 25 | "unit": "", 26 | "default": "", 27 | "description": "" 28 | } 29 | ] 30 | }, 31 | { 32 | "name": "Knowledge", 33 | "properties": [ 34 | { 35 | "name": "Knowledge", 36 | "internalname": "knowledge", 37 | "valuetype": "text", 38 | "regexformat": "", 39 | "listvalues": [], 40 | "unit": "", 41 | "default": "", 42 | "description": "" 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | ] 49 | -------------------------------------------------------------------------------- /src/v1/Validator/Dateformat.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Validator; 22 | 23 | use Rakit\Validation\Rule; 24 | 25 | class Dateformat extends Rule 26 | { 27 | protected $message = "The :attribute is not valid date"; 28 | 29 | protected $fillableParams = ['dateformat']; 30 | 31 | public function check($value): bool 32 | { 33 | // true for valid, false for invalid 34 | if ($value == '') 35 | { 36 | return true; 37 | } 38 | $date = date_create_from_format('Y-m-d', $value); 39 | if (!$date || date_format($date, 'Y-m-d') != $value) 40 | { 41 | return false; 42 | } 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/v1/Validator/Datetimeformat.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Validator; 22 | 23 | use Rakit\Validation\Rule; 24 | 25 | class Datetimeformat extends Rule 26 | { 27 | protected $message = "The :attribute is not valid datetime"; 28 | 29 | protected $fillableParams = ['datetimeformat']; 30 | 31 | public function check($value): bool 32 | { 33 | // true for valid, false for invalid 34 | if ($value == '') 35 | { 36 | return true; 37 | } 38 | $date = date_create_from_format('Y-m-d H:i:s', $value); 39 | if (!$date || date_format($date, 'Y-m-d H:i:s') != $value) 40 | { 41 | return false; 42 | } 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/v1/Validator/Maxchars.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Validator; 22 | 23 | use Rakit\Validation\Rule; 24 | 25 | class Maxchars extends Rule 26 | { 27 | protected $message = "The :attribute property has too many characters"; 28 | 29 | protected $fillableParams = ['maxchars']; 30 | 31 | public function check($value): bool 32 | { 33 | // make sure required parameters exists 34 | $this->requireParameters(['maxchars']); 35 | 36 | // getting parameters 37 | $maxchars = $this->parameter('maxchars'); 38 | 39 | if (!is_null($value)) 40 | { 41 | return strlen($value) <= $maxchars; 42 | } 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/v1/Validator/Minchars.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Validator; 22 | 23 | use Rakit\Validation\Rule; 24 | 25 | class Minchars extends Rule 26 | { 27 | protected $message = "The :attribute property has not enough characters"; 28 | 29 | protected $fillableParams = ['minchars']; 30 | 31 | public function check($value): bool 32 | { 33 | // make sure required parameters exists 34 | $this->requireParameters(['minchars']); 35 | 36 | // getting parameters 37 | $minchars = $this->parameter('minchars'); 38 | 39 | if (!is_null($value)) 40 | { 41 | return strlen($value) >= $minchars; 42 | } 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/v1/Validator/Timeformat.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Validator; 22 | 23 | use Rakit\Validation\Rule; 24 | 25 | class Timeformat extends Rule 26 | { 27 | protected $message = "The :attribute is not valid time"; 28 | 29 | protected $fillableParams = ['timeformat']; 30 | 31 | public function check($value): bool 32 | { 33 | // true for valid, false for invalid 34 | if ($value == '') 35 | { 36 | return true; 37 | } 38 | $date = date_create_from_format('H:i:s', $value); 39 | if (!$date || date_format($date, 'H:i:s') != $value) 40 | { 41 | return false; 42 | } 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/v1/Validator/Type.php: -------------------------------------------------------------------------------- 1 | . 19 | */ 20 | 21 | namespace App\v1\Validator; 22 | 23 | use Rakit\Validation\Rule; 24 | 25 | class Type extends Rule 26 | { 27 | protected $message = "The :attribute is not valid type"; 28 | 29 | protected $fillableParams = ['type']; 30 | 31 | public function check($value): bool 32 | { 33 | // make sure required parameters exists 34 | $this->requireParameters(['type']); 35 | 36 | // getting parameters 37 | $type = $this->parameter('type'); 38 | 39 | // true for valid, false for invalid 40 | return gettype($value) === $type; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/RESTAPI/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "standard", 8 | "plugin:mocha/recommended" 9 | ], 10 | "globals": { 11 | "$localize": "readonly", 12 | "before": "readonly", 13 | "cy": "readonly", 14 | "Cypress": "readonly" 15 | }, 16 | "parserOptions": { 17 | "ecmaVersion": "latest" 18 | }, 19 | "plugins": [ 20 | "mocha" 21 | ], 22 | "rules": { 23 | "comma-dangle": ["error", "always-multiline"], 24 | "no-useless-constructor": "off", 25 | "semi": ["error", "always"], 26 | "template-tag-spacing": ["error", "always"], 27 | "mocha/no-skipped-tests": "warn", 28 | "mocha/no-empty-description": "error" 29 | }, 30 | "ignorePatterns": ["schemaValidation/**/*.js"] 31 | } 32 | -------------------------------------------------------------------------------- /tests/RESTAPI/00_status.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('Endpoint /v1/status', function () { 6 | it('respond with json containing the status of the backend', function (done) { 7 | request 8 | .get('/v1/status') 9 | .set('Accept', 'application/json') 10 | .expect('Content-Type', /json/) 11 | .expect(200) 12 | .end(function (err, response) { 13 | if (err) { 14 | return done(err + ' | Response: ' + response.text); 15 | } 16 | return done(); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /tests/RESTAPI/00_token.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | describe('Endpoint /v1/token', function () { 9 | it('respond with json containing the JWT token with login & password', function (done) { 10 | request 11 | .post('/v1/token') 12 | .send({ login: 'admin', password: 'admin' }) 13 | .set('Accept', 'application/json') 14 | .expect(200) 15 | .expect('Content-Type', /json/) 16 | .expect(function (response) { 17 | assert(is.propertyCount(response.body, 3)); 18 | 19 | assert(validator.isJWT(response.body.token)); 20 | assert(validator.matches(response.body.refreshtoken, /^\w+$/)); 21 | 22 | assert(is.integer(response.body.expires)); 23 | assert(validator.matches('' + response.body.expires, /^\d{10}$/)); 24 | global.token = response.body.token; 25 | }) 26 | .end(function (err, response) { 27 | if (err) { 28 | return done(err + ' | Response: ' + response.text); 29 | } 30 | return done(); 31 | }); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /tests/RESTAPI/01_type/0_type-GET.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | describe('type | Endpoint /v1/config/types', function () { 9 | it('respond with json containing the list of types', function (done) { 10 | request 11 | .get('/v1/config/types') 12 | .set('Accept', 'application/json') 13 | .set('Authorization', 'Bearer ' + global.token) 14 | .expect(200) 15 | .expect('Content-Type', /json/) 16 | .expect(function (response) { 17 | const laptopType = response.body[2]; // laptops 18 | assert(is.propertyCount(laptopType, 16)); 19 | assert(is.number(laptopType.id)); 20 | assert(is.string(laptopType.name)); 21 | assert(is.string(laptopType.internalname)); 22 | assert(is.string(laptopType.modeling)); 23 | assert(is.boolean(laptopType.tree)); 24 | assert(is.boolean(laptopType.allowtreemultipleroots)); 25 | assert(validator.isISO8601(laptopType.created_at)); 26 | assert(validator.isISO8601(laptopType.updated_at)); 27 | assert(is.array(laptopType.properties)); 28 | 29 | assert(validator.equals('' + laptopType.id, '3')); 30 | assert(validator.equals(laptopType.name, 'Laptop')); 31 | assert(validator.equals(laptopType.modeling, 'physical')); 32 | }) 33 | .end(function (err, response) { 34 | if (err) { 35 | return done(err + ' | Response: ' + response.text); 36 | } 37 | return done(); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /tests/RESTAPI/01_type/3_type-id-DELETE.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('type | Delete /v1/config/types/:id', function () { 6 | it('soft delete the Firewall type', function (done) { 7 | request 8 | .delete('/v1/config/types/' + global.id) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('permanently delete the Firewall type', function (done) { 22 | request 23 | .delete('/v1/config/types/' + global.id) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/02_items/8_item-id-DELETE.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('items | delete /v1/items/:id', function () { 6 | it('soft delete the item', function (done) { 7 | request 8 | .delete('/v1/items/' + global.id) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('permanently delete the item', function (done) { 22 | request 23 | .delete('/v1/items/' + global.id) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/02_items/9_delete_types.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 3 | 4 | describe('items | Endpoint /v1/items | delete type', function () { 5 | it('soft delete a type', function (done) { 6 | request 7 | .delete('/v1/config/types/' + global.mytypeId) 8 | .set('Accept', 'application/json') 9 | .set('Authorization', 'Bearer ' + global.token) 10 | .expect(200) 11 | .expect('Content-Type', /json/) 12 | .end(function (err, response) { 13 | if (err) { 14 | return done(err + ' | Response: ' + response.text); 15 | } 16 | return done(); 17 | }); 18 | }); 19 | 20 | it('hard delete a type', function (done) { 21 | request 22 | .delete('/v1/config/types/' + global.mytypeId) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect(200) 26 | .expect('Content-Type', /json/) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/RESTAPI/03_itemsHeaders/1_create_15_items.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | describe('itemsHeaders | Endpoint /v1/items', function () { 9 | for (let step = 1; step <= 15; step++) { 10 | it('create a new item ' + step, function (done) { 11 | request 12 | .post('/v1/items') 13 | .send({ name: 'Laptop' + step, type_id: 3 }) 14 | .set('Accept', 'application/json') 15 | .set('Authorization', 'Bearer ' + global.token) 16 | .expect(200) 17 | .expect('Content-Type', /json/) 18 | .expect(function (response) { 19 | assert(is.propertyCount(response.body, 2)); 20 | assert(is.integer(response.body.id)); 21 | assert(is.integer(response.body.id_bytype)); 22 | assert(validator.matches('' + response.body.id, /^\d+$/)); 23 | }) 24 | .end(function (err, response) { 25 | if (err) { 26 | return done(err + ' | Response: ' + response.text); 27 | } 28 | return done(); 29 | }); 30 | }); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /tests/RESTAPI/03_itemsHeaders/8_item-id-DELETE.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemsHeaders | Delete all items', function () { 6 | it('soft delete the item', function (done) { 7 | for (const id of global.itemsId) { 8 | request 9 | .delete('/v1/items/' + id) 10 | .set('Accept', 'application/json') 11 | .set('Authorization', 'Bearer ' + global.token) 12 | .expect('Content-Type', /json/) 13 | .expect(200) 14 | .end(function (err, response) { 15 | if (err) { 16 | return done(err + ' | Response: ' + response.text); 17 | } 18 | }); 19 | } 20 | return done(); 21 | }); 22 | 23 | it('permanently delete the item', function (done) { 24 | for (const id of global.itemsId) { 25 | request 26 | .delete('/v1/items/' + id) 27 | .set('Accept', 'application/json') 28 | .set('Authorization', 'Bearer ' + global.token) 29 | .expect('Content-Type', /json/) 30 | .expect(200) 31 | .end(function (err, response) { 32 | if (err) { 33 | return done(err + ' | Response: ' + response.text); 34 | } 35 | }); 36 | } 37 | return done(); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/boolean/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'boolean in string', 4 | value: 'false', 5 | errorMessage: 'The Default is not valid type', 6 | }, 7 | { 8 | description: 'set 0 (integer) instead false', 9 | value: 0, 10 | errorMessage: 'The Default is not valid type', 11 | }, 12 | { 13 | description: 'set 0 (string) instead false', 14 | value: '0', 15 | errorMessage: 'The Default is not valid type', 16 | }, 17 | ]; 18 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/boolean/3_badValue.js: -------------------------------------------------------------------------------- 1 | const common = require('../common.js'); 2 | 3 | describe('itemProperties | boolean type | bad values | create items', function () { 4 | describe('prepare', function () { 5 | it('define the type boolean', function (done) { 6 | common.defineValuetype(done, 'boolean'); 7 | }); 8 | 9 | it('create a new type', function (done) { 10 | common.createType(done, 'boolean'); 11 | }); 12 | 13 | it('create the property ', function (done) { 14 | common.createProperty(done, true); 15 | }); 16 | 17 | it('Get the property to check value is good', function (done) { 18 | common.checkProperty(done, true); 19 | }); 20 | 21 | it('Attach a property to the type', function (done) { 22 | common.attachPropertyToType(done); 23 | }); 24 | }); 25 | 26 | describe('item, create: multiple bad values', function () { 27 | // eslint-disable-next-line mocha/no-setup-in-describe 28 | global.dataProvider.forEach(function ({ description, value, errorMessage }) { 29 | errorMessage = errorMessage.replace(' Default ', ' Value '); 30 | it('try create a new item but return error (' + description + ') => error', function (done) { 31 | common.createItemWithError(done, value, errorMessage); 32 | }); 33 | }); 34 | }); 35 | 36 | describe('clean', function () { 37 | it('Soft delete the type: test boolean', function (done) { 38 | common.deleteType(done); 39 | }); 40 | 41 | it('Hard delete the type: test boolean', function (done) { 42 | common.deleteType(done); 43 | }); 44 | 45 | it('Soft delete the property', function (done) { 46 | common.deleteProperty(done); 47 | }); 48 | 49 | it('Hard delete the property', function (done) { 50 | common.deleteProperty(done); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/date/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'date inversed', 4 | value: '06-05-2022', 5 | errorMessage: 'The Default is not valid date', 6 | }, 7 | { 8 | description: 'integer', 9 | value: 2022, 10 | errorMessage: 'The Default is not valid type, The Value is not valid date', 11 | }, 12 | { 13 | description: 'wrong month', 14 | value: '2022-15-13', 15 | errorMessage: 'The Default is not valid date', 16 | }, 17 | { 18 | description: 'miss the 0 in month number', 19 | value: '2022-5-13', 20 | errorMessage: 'The Default is not valid date', 21 | }, 22 | { 23 | description: 'text string', 24 | value: 'sometext', 25 | errorMessage: 'The Default is not valid date', 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/date/3_badValue.js: -------------------------------------------------------------------------------- 1 | const common = require('../common.js'); 2 | 3 | describe('itemProperties | date type | bad values | create items', function () { 4 | describe('prepare', function () { 5 | it('define the type date', function (done) { 6 | common.defineValuetype(done, 'date'); 7 | }); 8 | 9 | it('create a new type date', function (done) { 10 | common.createType(done, 'date'); 11 | }); 12 | 13 | it('create the property', function (done) { 14 | common.createProperty(done, '2022-04-25'); 15 | }); 16 | 17 | it('Get the property to check value is good', function (done) { 18 | common.checkProperty(done, '2022-04-25'); 19 | }); 20 | 21 | it('Attach a property to the type date', function (done) { 22 | common.attachPropertyToType(done); 23 | }); 24 | }); 25 | 26 | describe('item, create: multiple bad values', function () { 27 | // eslint-disable-next-line mocha/no-setup-in-describe 28 | global.dataProvider.forEach(({ description, value, errorMessage }) => { 29 | errorMessage = errorMessage.replace(' Default ', ' Value '); 30 | it('try create a new item but return error (' + description + ')', function (done) { 31 | common.createItemWithError(done, value, errorMessage); 32 | }); 33 | }); 34 | }); 35 | 36 | describe('clean', function () { 37 | it('Soft delete the type: test date', function (done) { 38 | common.deleteType(done); 39 | }); 40 | 41 | it('Hard delete the type: test date', function (done) { 42 | common.deleteType(done); 43 | }); 44 | 45 | it('Soft delete the property', function (done) { 46 | common.deleteProperty(done); 47 | }); 48 | 49 | it('Hard delete the property', function (done) { 50 | common.deleteProperty(done); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/datetime/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'bad datetime format', 4 | value: '2022-05-06 13:54', 5 | errorMessage: 'The Default is not valid datetime', 6 | }, 7 | { 8 | description: 'integer', 9 | value: 2022, 10 | errorMessage: 'The Default is not valid type, The Value is not valid datetime', 11 | }, 12 | { 13 | description: 'boolean instead string', 14 | value: true, 15 | errorMessage: 'The Default is not valid type, The Value is not valid datetime', 16 | }, 17 | { 18 | description: 'miss the 0 in the hour', 19 | value: '2022-05-06 3:64:05', 20 | errorMessage: 'The Default is not valid datetime', 21 | }, 22 | { 23 | description: 'bad minute', 24 | value: '2022-05-06 13:64:05', 25 | errorMessage: 'The Default is not valid datetime', 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/decimal/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'integer', 4 | value: 10, 5 | errorMessage: 'The Value is not valid type', 6 | }, 7 | { 8 | description: 'string', 9 | value: '3.1416', 10 | errorMessage: 'The Value is not valid type', 11 | }, 12 | ]; 13 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/decimal/3_badValue.js: -------------------------------------------------------------------------------- 1 | const common = require('../common.js'); 2 | 3 | describe('itemProperties | decimal type | bad values | create items', function () { 4 | describe('prepare', function () { 5 | it('define the type decimal', function (done) { 6 | common.defineValuetype(done, 'decimal'); 7 | }); 8 | 9 | it('create a new type decimal', function (done) { 10 | common.createType(done, 'decimal'); 11 | }); 12 | 13 | it('create the property', function (done) { 14 | common.createProperty(done, 3.1416); 15 | }); 16 | 17 | it('Get the property to check value is good', function (done) { 18 | common.checkProperty(done, 3.1416); 19 | }); 20 | 21 | it('Attach a property to the type decimal', function (done) { 22 | common.attachPropertyToType(done); 23 | }); 24 | }); 25 | 26 | describe('item, create: multiple bad values', function () { 27 | // eslint-disable-next-line mocha/no-setup-in-describe 28 | global.dataProvider.forEach(({ description, value, errorMessage }) => { 29 | it('try create a new item but return error (' + description + ')', function (done) { 30 | common.createItemWithError(done, value, errorMessage); 31 | }); 32 | }); 33 | }); 34 | 35 | describe('clean', function () { 36 | it('Soft delete the type: test decimal', function (done) { 37 | common.deleteType(done); 38 | }); 39 | 40 | it('Hard delete the type: test decimal', function (done) { 41 | common.deleteType(done); 42 | }); 43 | 44 | it('Soft delete the property', function (done) { 45 | common.deleteProperty(done); 46 | }); 47 | 48 | it('Hard delete the property', function (done) { 49 | common.deleteProperty(done); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/integer/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'integer into string', 4 | value: '10', 5 | errorMessage: 'The Default is not valid type', 6 | }, 7 | { 8 | description: 'float', 9 | value: 10.1, 10 | errorMessage: 'The Default is not valid type, The Value must be integer', 11 | }, 12 | { 13 | description: 'boolean', 14 | value: true, 15 | errorMessage: 'The Default is not valid type', 16 | }, 17 | ]; 18 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/itemlink/0_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'item id in string', 4 | value: '123', 5 | errorMessage: 'The Default is not valid type', 6 | }, 7 | { 8 | description: 'boolean', 9 | value: true, 10 | errorMessage: 'The Default is not valid type', 11 | }, 12 | { 13 | description: 'item id not exists', 14 | value: 47586, 15 | errorMessage: 'The Default is an id than does not exist', 16 | }, 17 | { 18 | description: 'wrong item id (negative integer)', 19 | value: -1, 20 | errorMessage: 'The Default is not valid format', 21 | }, 22 | { 23 | description: 'wrong item id: 0', 24 | value: 0, 25 | errorMessage: 'The Default is an id than does not exist', 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/itemlink/1_create_items.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | global.itemId1 = 0; 9 | global.itemId2 = 0; 10 | global.itemId3 = 0; 11 | global.itemId4 = 0; 12 | global.itemId5 = 0; 13 | global.itemId6 = 0; 14 | 15 | describe('itemProperties: itemlink type | create items', function () { 16 | for (let i = 1; i < 7; i++) { 17 | it('create an item ' + i, function (done) { 18 | request 19 | .post('/v1/items') 20 | .send({ 21 | name: 'my item ' + i, 22 | type_id: 3, 23 | }) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect(200) 27 | .expect('Content-Type', /json/) 28 | .expect(function (response) { 29 | assert(is.propertyCount(response.body, 2)); 30 | assert(is.integer(response.body.id)); 31 | assert(is.integer(response.body.id_bytype)); 32 | assert(validator.matches('' + response.body.id, /^\d+$/)); 33 | global['itemId' + i] = response.body.id; 34 | }) 35 | .end(function (err, response) { 36 | if (err) { 37 | return done(err + ' | Response: ' + response.text); 38 | } 39 | return done(); 40 | }); 41 | }); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/itemlink/8_delete_items.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 3 | 4 | describe('itemProperties: itemlink type | delete item', function () { 5 | for (let i = 1; i < 7; i++) { 6 | it('Soft delete the item ' + i, function (done) { 7 | request 8 | .delete('/v1/items/' + global['itemId' + i].toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the item ' + i, function (done) { 21 | request 22 | .delete('/v1/items/' + global['itemId' + i].toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/itemlinks/1_create_items.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | global.itemId1 = 0; 9 | global.itemId2 = 0; 10 | global.itemId3 = 0; 11 | global.itemId4 = 0; 12 | global.itemId5 = 0; 13 | global.itemId6 = 0; 14 | 15 | describe('itemProperties: itemlinks type | create items', function () { 16 | for (let i = 1; i < 7; i++) { 17 | it('create an item ' + i, function (done) { 18 | request 19 | .post('/v1/items') 20 | .send({ 21 | name: 'my item ' + i, 22 | type_id: 3, 23 | }) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect(200) 27 | .expect('Content-Type', /json/) 28 | .expect(function (response) { 29 | assert(is.propertyCount(response.body, 2)); 30 | assert(is.integer(response.body.id)); 31 | assert(is.integer(response.body.id_bytype)); 32 | assert(validator.matches('' + response.body.id, /^\d+$/)); 33 | global['itemId' + i] = response.body.id; 34 | }) 35 | .end(function (err, response) { 36 | if (err) { 37 | return done(err + ' | Response: ' + response.text); 38 | } 39 | return done(); 40 | }); 41 | }); 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/itemlinks/8_delete_items.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 3 | 4 | describe('itemProperties: itemlinks type | delete items', function () { 5 | for (let i = 1; i < 7; i++) { 6 | it('Soft delete the item ' + i, function (done) { 7 | request 8 | .delete('/v1/items/' + global['itemId' + i].toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the item ' + i, function (done) { 21 | request 22 | .delete('/v1/items/' + global['itemId' + i].toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/list/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'integer 432', 4 | value: 432, 5 | errorMessageDefault: 'The Default is not valid type', 6 | errorMessage: 'The Value is an id than does not exist (property Test for list - ', 7 | }, 8 | { 9 | description: 'unknown list value: list3', 10 | value: 'list3', 11 | errorMessageDefault: 'The Default property does not exist in listvalues', 12 | errorMessage: 'The Value is not valid type (property Test for list - ', 13 | }, 14 | { 15 | description: 'array with good value', 16 | value: ['list3'], 17 | errorMessageDefault: 'The Default is not valid type', 18 | errorMessage: 'The Value is not valid type (property Test for list - ', 19 | }, 20 | ]; 21 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/number/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'string 5', 4 | value: '5', 5 | errorMessage: 'The Default is not valid type', 6 | }, 7 | { 8 | description: 'negative integer -4', 9 | value: -4, 10 | errorMessage: 'The Default is not valid format', 11 | }, 12 | ]; 13 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/number/3_badValue.js: -------------------------------------------------------------------------------- 1 | const common = require('../common.js'); 2 | 3 | describe('itemProperties | number type | bad values | create items', function () { 4 | describe('prepare', function () { 5 | it('define the type number', function (done) { 6 | common.defineValuetype(done, 'number'); 7 | }); 8 | 9 | it('create a new type number', function (done) { 10 | common.createType(done, 'number'); 11 | }); 12 | 13 | it('create the property', function (done) { 14 | common.createProperty(done, 5); 15 | }); 16 | 17 | it('Get the property to check value is good', function (done) { 18 | common.checkProperty(done, 5); 19 | }); 20 | 21 | it('Attach a property to the type number', function (done) { 22 | common.attachPropertyToType(done); 23 | }); 24 | }); 25 | 26 | describe('item, create: wrong values => error', function () { 27 | // eslint-disable-next-line mocha/no-setup-in-describe 28 | global.dataProvider.forEach(({ description, value, errorMessage }) => { 29 | errorMessage = errorMessage.replace(' Default ', ' Value '); 30 | it('try create a new item but return error (' + description + ')', function (done) { 31 | common.createItemWithError(done, value, errorMessage); 32 | }); 33 | }); 34 | }); 35 | 36 | describe('clean', function () { 37 | it('Soft delete the type: test number', function (done) { 38 | common.deleteType(done); 39 | }); 40 | 41 | it('Hard delete the type: test number', function (done) { 42 | common.deleteType(done); 43 | }); 44 | 45 | it('Soft delete the property', function (done) { 46 | common.deleteProperty(done); 47 | }); 48 | 49 | it('Hard delete the property', function (done) { 50 | common.deleteProperty(done); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/password/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'boolean', 4 | value: true, 5 | errorMessage: 'The Value is not valid type', 6 | }, 7 | { 8 | description: 'integer', 9 | value: 2, 10 | errorMessage: 'The Value is not valid type', 11 | }, 12 | ]; 13 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/passwordhash/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'boolean', 4 | value: true, 5 | errorMessage: 'The Value is not valid type', 6 | }, 7 | { 8 | description: 'integer', 9 | value: 2, 10 | errorMessage: 'The Value is not valid type', 11 | }, 12 | ]; 13 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/propertylink/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'string test1', 4 | value: 'test1', 5 | errorMessage: 'The Default is not valid type', 6 | }, 7 | { 8 | description: 'not existant id 548774', 9 | value: 548774, 10 | errorMessage: 'The Default property id does not exist', 11 | }, 12 | { 13 | description: 'negative integer', 14 | value: -40, 15 | errorMessage: 'The Default is not valid format', 16 | }, 17 | { 18 | description: 'id 0', 19 | value: 0, 20 | errorMessage: 'The Default property id does not exist', 21 | }, 22 | { 23 | description: 'property id is a string', 24 | value: '1', 25 | errorMessage: 'The Default is not valid type', 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/string/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'number', 4 | value: 42, 5 | errorMessage: 'The Default is not valid type', 6 | }, 7 | { 8 | description: 'too long string', 9 | value: 'Lorem ipsum dolor sit amet. Est porro eius sed dolorum consequatur et ducimus distinctio qui eius porro. Cum facilis quaerat ut excepturi animi qui vero voluptatum et cupiditate fuga et autem neque qui consectetur vitae qui delectus neque? Aut soluta ratione ad cupiditate maiores et modi rerum ad dignissimos nisi aut debi', 10 | errorMessage: 'The Default property has too many characters', 11 | }, 12 | { 13 | description: 'boolean', 14 | value: true, 15 | errorMessage: 'The Default is not valid type', 16 | }, 17 | ]; 18 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/text/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'integer', 4 | value: 10, 5 | errorMessage: 'The Default is not valid type', 6 | }, 7 | { 8 | description: 'boolean', 9 | value: true, 10 | errorMessage: 'The Default is not valid type', 11 | }, 12 | ]; 13 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/time/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'text not time', 4 | value: 'lala la', 5 | errorMessage: 'The Default is not valid time', 6 | }, 7 | { 8 | description: 'bad time format', 9 | value: '23:62:04', 10 | errorMessage: 'The Default is not valid time', 11 | }, 12 | { 13 | description: 'miss a 0 in the time', 14 | value: '3:42:04', 15 | errorMessage: 'The Default is not valid time', 16 | }, 17 | ]; 18 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/time/3_badValue.js: -------------------------------------------------------------------------------- 1 | const common = require('../common.js'); 2 | 3 | describe('itemProperties | time type | bad values | create items', function () { 4 | describe('prepare', function () { 5 | it('define the type time', function (done) { 6 | common.defineValuetype(done, 'time'); 7 | }); 8 | 9 | it('create a new type time', function (done) { 10 | common.createType(done, 'time'); 11 | }); 12 | 13 | it('create the property', function (done) { 14 | common.createProperty(done, '07:04:21'); 15 | }); 16 | 17 | it('Get the property to check value is good', function (done) { 18 | common.checkProperty(done, '07:04:21'); 19 | }); 20 | 21 | it('Attach a property to the type time', function (done) { 22 | common.attachPropertyToType(done); 23 | }); 24 | }); 25 | 26 | describe('item, create: wrong values => error', function () { 27 | // eslint-disable-next-line mocha/no-setup-in-describe 28 | global.dataProvider.forEach(({ description, value, errorMessage }) => { 29 | errorMessage = errorMessage.replace(' Default ', ' Value '); 30 | it('try create a new item but return error (' + description + ')', function (done) { 31 | common.createItemWithError(done, value, errorMessage); 32 | }); 33 | }); 34 | }); 35 | 36 | describe('clean', function () { 37 | it('Soft delete the type: test time', function (done) { 38 | common.deleteType(done); 39 | }); 40 | 41 | it('Hard delete the type: test time', function (done) { 42 | common.deleteType(done); 43 | }); 44 | 45 | it('Soft delete the property', function (done) { 46 | common.deleteProperty(done); 47 | }); 48 | 49 | it('Hard delete the property', function (done) { 50 | common.deleteProperty(done); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/typelink/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'type id in string', 4 | value: '2', 5 | errorMessage: 'The Default is not valid type', 6 | }, 7 | { 8 | description: 'boolean', 9 | value: true, 10 | errorMessage: 'The Default is not valid type', 11 | }, 12 | { 13 | description: 'type id not exists', 14 | value: 47586, 15 | errorMessage: 'The Default type does not exist', 16 | }, 17 | { 18 | description: 'wrong type id (negative integer)', 19 | value: -1, 20 | errorMessage: 'The Default is not valid format', 21 | }, 22 | { 23 | description: 'wrong type id (0 value)', 24 | value: 0, 25 | errorMessage: 'The Default type does not exist', 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /tests/RESTAPI/04_itemProperties/typelinks/1_dataproviders.js: -------------------------------------------------------------------------------- 1 | global.dataProvider = [ 2 | { 3 | description: 'type id not in array', 4 | value: 2, 5 | errorMessage: 'The Default must be array', 6 | }, 7 | { 8 | description: 'type id in string', 9 | value: '2', 10 | errorMessage: 'The Default must be array', 11 | }, 12 | { 13 | description: 'types id (style array) in string', 14 | value: '[2,3]', 15 | errorMessage: 'The Default must be array', 16 | }, 17 | { 18 | description: 'type id not exists', 19 | value: [267584], 20 | errorMessage: 'The Default is an id than does not exist', 21 | }, 22 | { 23 | description: 'types id with 1 of the 2 not exists', 24 | value: [3, 267584], 25 | errorMessage: 'The Default is an id than does not exist', 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /tests/RESTAPI/05_itemsTree/5_deleteSub1Item.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemsTree | delete root item', function () { 6 | it('Soft delete the sub1 item', function (done) { 7 | request 8 | .delete('/v1/items/' + global.itemLevel2Id.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the sub1 item', function (done) { 21 | request 22 | .delete('/v1/items/' + global.itemLevel2Id.toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/RESTAPI/05_itemsTree/6_deleteRootItem.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemsTree | delete root item', function () { 6 | it('Soft delete the root item', function (done) { 7 | request 8 | .delete('/v1/items/' + global.itemLevel1Id.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the root item', function (done) { 21 | request 22 | .delete('/v1/items/' + global.itemLevel1Id.toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/RESTAPI/05_itemsTree/7_deleteType.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemsTree | delete type', function () { 6 | it('Soft delete the type', function (done) { 7 | request 8 | .delete('/v1/config/types/' + global.typeId.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the type', function (done) { 21 | request 22 | .delete('/v1/config/types/' + global.typeId.toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/RESTAPI/06_itemsTreeMultipleRoots/6_deleteSub1Item.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemsTreeMultipleRoots | delete root item', function () { 6 | it('Soft delete the sub1 item', function (done) { 7 | request 8 | .delete('/v1/items/' + global.itemLevel2Id.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the sub1 item', function (done) { 21 | request 22 | .delete('/v1/items/' + global.itemLevel2Id.toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/RESTAPI/06_itemsTreeMultipleRoots/7_deleteRootItem.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemsTreeMultipleRoots | delete root item', function () { 6 | it('Soft delete the root item', function (done) { 7 | request 8 | .delete('/v1/items/' + global.itemLevel1Id.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the root item', function (done) { 21 | request 22 | .delete('/v1/items/' + global.itemLevel1Id.toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/RESTAPI/06_itemsTreeMultipleRoots/8_deleteType.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemsTreeMultipleRoots | delete type', function () { 6 | it('Soft delete the type', function (done) { 7 | request 8 | .delete('/v1/config/types/' + global.typeId.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the type', function (done) { 21 | request 22 | .delete('/v1/config/types/' + global.typeId.toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/RESTAPI/08_roles/2_grant/7_delete-laptop.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('roles | grant | delete laptops', function () { 6 | it('soft delete the laptop', function (done) { 7 | request 8 | .delete('/v1/items/' + global.item1Id) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('permanently delete the laptop', function (done) { 22 | request 23 | .delete('/v1/items/' + global.item1Id) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/08_roles/3_custom/data/30_delete-laptop.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('roles | custom > data | delete laptops', function () { 6 | it('soft delete the laptop', function (done) { 7 | request 8 | .delete('/v1/items/' + global.item1Id) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | // disable expect, because can be deleted or not, so need to be sure it's deleted 13 | // .expect(200) 14 | .end(function (err, response) { 15 | if (err) { 16 | return done(err + ' | Response: ' + response.text); 17 | } 18 | return done(); 19 | }); 20 | }); 21 | 22 | it('permanently delete the laptop', function (done) { 23 | request 24 | .delete('/v1/items/' + global.item1Id) 25 | .set('Accept', 'application/json') 26 | .set('Authorization', 'Bearer ' + global.token) 27 | .expect('Content-Type', /json/) 28 | // disable expect, because can be deleted or not, so need to be sure it's deleted 29 | // .expect(200) 30 | .end(function (err, response) { 31 | if (err) { 32 | return done(err + ' | Response: ' + response.text); 33 | } 34 | return done(); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /tests/RESTAPI/08_roles/3_custom/data_property/30_delete-laptop.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('roles | custom > data > properties | delete laptops', function () { 6 | it('soft delete the laptop', function (done) { 7 | request 8 | .delete('/v1/items/' + global.item1Id) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('permanently delete the laptop', function (done) { 22 | request 23 | .delete('/v1/items/' + global.item1Id) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/09_organizations/items/05_get_all_items_rootorg.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('organizations | items | get items with admin', function () { 8 | it('get all items in top level of oganization', function (done) { 9 | request 10 | .get('/v1/items/type/' + global.typeId) 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.token) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.not.empty(response.body), 'response body must not be empty'); 17 | assert(is.array(response.body), 'response body must be an array'); 18 | assert(is.propertyCount(response.body, 4), 'must have the 4 items'); 19 | // check the organization field in items 20 | const firstItem = response.body[0]; 21 | assert(is.object(firstItem.organization)); 22 | assert(is.equal(2, Object.keys(firstItem.organization).length), 'organization must have only 2 attributes'); 23 | assert(is.equal(1, firstItem.organization.id), 'organization id must be 1'); 24 | assert(is.equal('My organization', firstItem.organization.name), 'organization name must be `My organization`'); 25 | }) 26 | .end(function (err, response) { 27 | if (err) { 28 | return done(err + ' | Response: ' + response.text); 29 | } 30 | return done(); 31 | }); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /tests/RESTAPI/09_organizations/items/06_get_all_items_sub1org.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('organizations | items | get items with user1', function () { 8 | it('get all items in sub1 level of oganization', function (done) { 9 | request 10 | .get('/v1/items/type/' + global.typeId) 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.tokenUser1) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.not.empty(response.body), 'response body must not be empty'); 17 | assert(is.array(response.body), 'response body must be an array'); 18 | assert(is.propertyCount(response.body, 3), 'must have the 3 items'); 19 | assert(is.equal(response.body[0].id, global.myitemSub1), 'must have the id of the myitemSub1'); 20 | assert(is.equal(response.body[1].id, global.myitem2), 'must have the id of the myitem2'); 21 | assert(is.equal(response.body[2].id, global.myitem3), 'must have the id of the myitem3'); 22 | }) 23 | .end(function (err, response) { 24 | if (err) { 25 | return done(err + ' | Response: ' + response.text); 26 | } 27 | return done(); 28 | }); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /tests/RESTAPI/09_organizations/items/07_get_all_items_sub2org.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('organizations | items | get items with user2', function () { 8 | it('get all items in sub1 level of oganization', function (done) { 9 | request 10 | .get('/v1/items/type/' + global.typeId) 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.tokenUser2) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.not.empty(response.body), 'response body must not be empty'); 17 | assert(is.array(response.body), 'response body must be an array'); 18 | assert(is.propertyCount(response.body, 2), 'must have the third item'); 19 | assert(is.equal(response.body[0].id, global.myitemSub1), 'must have the id of the myitemSub1'); 20 | assert(is.equal(response.body[1].id, global.myitem3), 'must have the id of the myitem3'); 21 | }) 22 | .end(function (err, response) { 23 | if (err) { 24 | return done(err + ' | Response: ' + response.text); 25 | } 26 | return done(); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /tests/RESTAPI/09_organizations/items/10_delete-types.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('organizations | items | delete type', function () { 6 | it('Soft delete the type', function (done) { 7 | request 8 | .delete('/v1/config/types/' + global.typeId.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | it('Hard delete the type', function (done) { 21 | request 22 | .delete('/v1/config/types/' + global.typeId.toString()) 23 | .set('Accept', 'application/json') 24 | .set('Authorization', 'Bearer ' + global.token) 25 | .expect('Content-Type', /json/) 26 | .expect(200) 27 | .end(function (err, response) { 28 | if (err) { 29 | return done(err + ' | Response: ' + response.text); 30 | } 31 | return done(); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /tests/RESTAPI/09_organizations/properties/09_detach_properties_to_type2_byadmin.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('organizations | properties | attach properties to type2 by admin', function () { 8 | it('detach mypropSub1', function (done) { 9 | request 10 | .delete('/v1/config/types/' + global.mytype2 + '/property/' + global.mypropSub1) 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.token) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.propertyCount(response.body, 0)); 17 | }) 18 | .end(function (err, response) { 19 | if (err) { 20 | return done(err + ' | Response: ' + response.text); 21 | } 22 | return done(); 23 | }); 24 | }); 25 | 26 | it('detach prop2', function (done) { 27 | request 28 | .delete('/v1/config/types/' + global.mytype2 + '/property/' + global.myprop2) 29 | .set('Accept', 'application/json') 30 | .set('Authorization', 'Bearer ' + global.token) 31 | .expect(200) 32 | .expect('Content-Type', /json/) 33 | .expect(function (response) { 34 | assert(is.propertyCount(response.body, 0)); 35 | }) 36 | .end(function (err, response) { 37 | if (err) { 38 | return done(err + ' | Response: ' + response.text); 39 | } 40 | return done(); 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /tests/RESTAPI/09_organizations/properties/12_detach_properties_to_type2_byadmin.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('organizations | properties | attach properties to type2 by admin', function () { 8 | it('detach mypropSub1', function (done) { 9 | request 10 | .delete('/v1/config/types/' + global.mytype2 + '/property/' + global.mypropSub1) 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.token) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.propertyCount(response.body, 0)); 17 | }) 18 | .end(function (err, response) { 19 | if (err) { 20 | return done(err + ' | Response: ' + response.text); 21 | } 22 | return done(); 23 | }); 24 | }); 25 | 26 | it('detach prop2', function (done) { 27 | request 28 | .delete('/v1/config/types/' + global.mytype2 + '/property/' + global.myprop2) 29 | .set('Accept', 'application/json') 30 | .set('Authorization', 'Bearer ' + global.token) 31 | .expect(200) 32 | .expect('Content-Type', /json/) 33 | .expect(function (response) { 34 | assert(is.propertyCount(response.body, 0)); 35 | }) 36 | .end(function (err, response) { 37 | if (err) { 38 | return done(err + ' | Response: ' + response.text); 39 | } 40 | return done(); 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /tests/RESTAPI/10_usereventTimestamp/35_delete-item.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('usereventTimestamp | delete item', function () { 6 | it('soft delete the item', function (done) { 7 | request 8 | .delete('/v1/items/' + global.itemId) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect(200) 12 | .expect('Content-Type', /json/) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('hard delete the item', function (done) { 22 | request 23 | .delete('/v1/items/' + global.itemId) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect(200) 27 | .expect('Content-Type', /json/) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/10_usereventTimestamp/36_delete-type.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('usereventTimestamp | delete type', function () { 6 | it('soft delete the type', function (done) { 7 | request 8 | .delete('/v1/config/types/' + global.typeId) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect(200) 12 | .expect('Content-Type', /json/) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('hard delete the type', function (done) { 22 | request 23 | .delete('/v1/config/types/' + global.typeId) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect(200) 27 | .expect('Content-Type', /json/) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/10_usereventTimestamp/37_delete-property.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('usereventTimestamp | delete property', function () { 6 | it('soft delete the property', function (done) { 7 | request 8 | .delete('/v1/config/properties/' + global.propertyId) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect(200) 12 | .expect('Content-Type', /json/) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('hard delete the property', function (done) { 22 | request 23 | .delete('/v1/config/properties/' + global.propertyId) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect(200) 27 | .expect('Content-Type', /json/) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/10_usereventTimestamp/README.md: -------------------------------------------------------------------------------- 1 | # User event and timestamp 2 | 3 | These tests will test for: 4 | 5 | * config/properties 6 | * config/types 7 | * items 8 | 9 | The following: 10 | 11 | * creating 12 | * fill *created_at* with datetime 13 | * fill *updated_at* with datetime 14 | * fill *created_by* with user id 15 | * updating 16 | * update *updated_at* with datetime 17 | * fill *updated_by* with user id 18 | * soft deleting 19 | * fill *deleted_at* with datetime 20 | * fill *deleted_by* with user id 21 | * restoring from soft delete 22 | * fill *deleted_at* to null 23 | * fill *deleted_by* to null 24 | * update *updated_at* with datetime 25 | * update *updated_by* with user id 26 | 27 | -------------------------------------------------------------------------------- /tests/RESTAPI/16_actionscripts/actionZabbix/2_deleteRule.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('actionscripts/ActionZabbix - Delete the rule', function () { 6 | it('it delete a rule', function (done) { 7 | request 8 | .delete('/v1/rules/actionscript/' + global.ruleId) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect(200) 12 | .end(function (err, response) { 13 | if (err) { 14 | return done(err + ' | Response: ' + response.text); 15 | } 16 | return done(); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /tests/RESTAPI/16_actionscripts/notificationMail/2_deleteRule.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('Delete the rule', function () { 6 | it('it delete a rule', function (done) { 7 | request 8 | .delete('/v1/rules/actionscript/' + global.ruleId) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect(200) 12 | .end(function (err, response) { 13 | if (err) { 14 | return done(err + ' | Response: ' + response.text); 15 | } 16 | return done(); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /tests/RESTAPI/19_refreshToken/05_delete-users.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('refresh token | delete users', function () { 6 | it('Soft delete the user1', function (done) { 7 | request 8 | .delete('/v1/items/' + global.user1.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('Hard delete the user1', function (done) { 22 | request 23 | .delete('/v1/items/' + global.user1.toString()) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/20_getToken/05_delete-users.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('get token | delete users', function () { 6 | it('Soft delete the user1', function (done) { 7 | request 8 | .delete('/v1/items/' + global.user1.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('Hard delete the user1', function (done) { 22 | request 23 | .delete('/v1/items/' + global.user1.toString()) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/21_itemPropertyWhenAddDeletePropertyToType/1_createType.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | describe('itemPropertyWhenAddPropertyToType | create type', function () { 9 | it('create a new type', function (done) { 10 | request 11 | .post('/v1/config/types') 12 | .send({ 13 | name: 'testType', 14 | internalname: 'testtype', 15 | }) 16 | .set('Accept', 'application/json') 17 | .set('Authorization', 'Bearer ' + global.token) 18 | .expect(200) 19 | .expect('Content-Type', /json/) 20 | .expect(function (response) { 21 | assert(is.propertyCount(response.body, 1)); 22 | assert(is.integer(response.body.id)); 23 | assert(validator.matches('' + response.body.id, /^\d+$/)); 24 | global.typeId = response.body.id; 25 | }) 26 | .end(function (err, response) { 27 | if (err) { 28 | return done(err + ' | Response: ' + response.text); 29 | } 30 | return done(); 31 | }); 32 | }); 33 | 34 | it('Attach a property to the type', function (done) { 35 | request 36 | .post('/v1/config/types/' + global.typeId.toString() + '/property/6') 37 | .send() 38 | .set('Accept', 'application/json') 39 | .set('Authorization', 'Bearer ' + global.token) 40 | .expect(200) 41 | .expect('Content-Type', /json/) 42 | .end(function (err, response) { 43 | if (err) { 44 | return done(err + ' | Response: ' + response.text); 45 | } 46 | return done(); 47 | }); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /tests/RESTAPI/21_itemPropertyWhenAddDeletePropertyToType/2_createItem.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | describe('itemPropertyWhenAddPropertyToType | create item', function () { 9 | it('create an item', function (done) { 10 | request 11 | .post('/v1/items') 12 | .send({ 13 | name: 'an item of the type', 14 | type_id: global.typeId, 15 | }) 16 | .set('Accept', 'application/json') 17 | .set('Authorization', 'Bearer ' + global.token) 18 | .expect(200) 19 | .expect('Content-Type', /json/) 20 | .expect(function (response) { 21 | assert(is.propertyCount(response.body, 2)); 22 | assert(is.integer(response.body.id)); 23 | assert(is.integer(response.body.id_bytype)); 24 | assert(validator.matches('' + response.body.id, /^\d+$/)); 25 | assert(is.equal(1, response.body.id_bytype)); 26 | global.itemId = response.body.id; 27 | }) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/21_itemPropertyWhenAddDeletePropertyToType/3_addNewPropertyToType.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('itemPropertyWhenAddPropertyToType | add new property to type', function () { 8 | it('Attach a property to the type', function (done) { 9 | request 10 | .post('/v1/config/types/' + global.typeId.toString() + '/property/7') 11 | .send() 12 | .set('Accept', 'application/json') 13 | .set('Authorization', 'Bearer ' + global.token) 14 | .expect(200) 15 | .expect('Content-Type', /json/) 16 | .end(function (err, response) { 17 | if (err) { 18 | return done(err + ' | Response: ' + response.text); 19 | } 20 | return done(); 21 | }); 22 | }); 23 | 24 | it('verify the item have right the property 7', function (done) { 25 | request 26 | .get('/v1/items/' + global.itemId) 27 | .set('Accept', 'application/json') 28 | .set('Authorization', 'Bearer ' + global.token) 29 | .expect(200) 30 | .expect('Content-Type', /json/) 31 | .expect(function (response) { 32 | assert(is.not.empty(response.body), 'The body must contain something'); 33 | assert(is.object(response.body), 'the body response must be an object'); 34 | assert(is.equal(2, response.body.properties.length), 'must have 2 properties'); 35 | assert(is.equal(7, response.body.properties[1].id), 'the second property id must be 7'); 36 | }) 37 | .end(function (err, response) { 38 | if (err) { 39 | return done(err + ' | Response: ' + response.text); 40 | } 41 | return done(); 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /tests/RESTAPI/21_itemPropertyWhenAddDeletePropertyToType/4_deletePropertyToType.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('itemPropertyWhenAddPropertyToType | delete property to type', function () { 8 | it('Attach a property to the type', function (done) { 9 | request 10 | .delete('/v1/config/types/' + global.typeId.toString() + '/property/7') 11 | .send() 12 | .set('Accept', 'application/json') 13 | .set('Authorization', 'Bearer ' + global.token) 14 | .expect(200) 15 | .expect('Content-Type', /json/) 16 | .end(function (err, response) { 17 | if (err) { 18 | return done(err + ' | Response: ' + response.text); 19 | } 20 | return done(); 21 | }); 22 | }); 23 | 24 | it('verify the item not have right the property 7', function (done) { 25 | request 26 | .get('/v1/items/' + global.itemId) 27 | .set('Accept', 'application/json') 28 | .set('Authorization', 'Bearer ' + global.token) 29 | .expect(200) 30 | .expect('Content-Type', /json/) 31 | .expect(function (response) { 32 | assert(is.not.empty(response.body), 'The body must contain something'); 33 | assert(is.object(response.body), 'the body response must be an object'); 34 | assert(is.equal(1, response.body.properties.length), 'must have 1 property'); 35 | assert(is.equal(6, response.body.properties[0].id), 'the id of the unique property must be 6'); 36 | }) 37 | .end(function (err, response) { 38 | if (err) { 39 | return done(err + ' | Response: ' + response.text); 40 | } 41 | return done(); 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /tests/RESTAPI/21_itemPropertyWhenAddDeletePropertyToType/6_deleteItem.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemPropertyWhenAddPropertyToType | delete item', function () { 6 | it('Soft delete the item', function (done) { 7 | request 8 | .delete('/v1/items/' + global.itemId.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('Hard delete the item', function (done) { 22 | request 23 | .delete('/v1/items/' + global.itemId.toString()) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/21_itemPropertyWhenAddDeletePropertyToType/7_deleteType.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemPropertyWhenAddPropertyToType | delete type', function () { 6 | it('Soft delete the type', function (done) { 7 | request 8 | .delete('/v1/config/types/' + global.typeId.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('Hard delete the type', function (done) { 22 | request 23 | .delete('/v1/config/types/' + global.typeId.toString()) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/22_changeslogs/1_properties/2_getall_properties.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('changes | properties | get all properties', function () { 8 | it('get all properties and check changes key not exists', function (done) { 9 | request 10 | .get('/v1/config/properties') 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.token) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.array(response.body)); 17 | assert(is.above(response.body.length, 2)); 18 | 19 | const firstProperty = response.body[0]; 20 | assert(is.not.propertyDefined(firstProperty, 'changes')); 21 | }) 22 | .end(function (err, response) { 23 | if (err) { 24 | return done(err + ' | Response: ' + response.text); 25 | } 26 | return done(); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /tests/RESTAPI/22_changeslogs/2_type/2_getall_types.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('changes | types | get all types', function () { 8 | it('get all types and check changes key not exists', function (done) { 9 | request 10 | .get('/v1/config/types') 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.token) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.array(response.body)); 17 | assert(is.above(response.body.length, 2)); 18 | 19 | const firstType = response.body[0]; 20 | assert(is.not.propertyDefined(firstType, 'changes')); 21 | }) 22 | .end(function (err, response) { 23 | if (err) { 24 | return done(err + ' | Response: ' + response.text); 25 | } 26 | return done(); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /tests/RESTAPI/22_changeslogs/3_item/03_getall_item.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('changes | items | get all items', function () { 8 | it('get all items and check changes key not exists', function (done) { 9 | request 10 | .get('/v1/items/type/' + global.typeId) 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.token) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.array(response.body)); 17 | assert(is.above(response.body.length, 0)); 18 | 19 | const firstItem = response.body[0]; 20 | assert(is.not.propertyDefined(firstItem, 'changes')); 21 | }) 22 | .end(function (err, response) { 23 | if (err) { 24 | return done(err + ' | Response: ' + response.text); 25 | } 26 | return done(); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /tests/RESTAPI/23_display/1_menus/2_menu-GET.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | describe('Display menu | Get menu', function () { 9 | it('respond with json containing the list of menus', function (done) { 10 | request 11 | .get('/v1/display/menu') 12 | .set('Accept', 'application/json') 13 | .set('Authorization', 'Bearer ' + global.token) 14 | .expect(200) 15 | .expect('Content-Type', /json/) 16 | .expect(function (response) { 17 | const menu = response.body[0]; // assets menu 18 | assert(is.propertyCount(menu, 7)); 19 | assert(is.number(menu.id)); 20 | assert(is.string(menu.name)); 21 | assert(is.null(menu.icon)); 22 | assert(is.number(menu.position)); 23 | assert(validator.isISO8601(menu.created_at)); 24 | assert(validator.isISO8601(menu.updated_at)); 25 | assert(is.array(menu.items)); 26 | 27 | assert(is.equal(menu.id, global.id)); 28 | assert(validator.equals(menu.name, 'Assets')); 29 | }) 30 | .end(function (err, response) { 31 | if (err) { 32 | return done(err + ' | Response: ' + response.text); 33 | } 34 | return done(); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /tests/RESTAPI/23_display/1_menus/4_menu-id-DELETE.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('Display menu | Delete menu', function () { 6 | it('delete the Assets menu', function (done) { 7 | request 8 | .delete('/v1/display/menu/' + global.id) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/RESTAPI/23_display/2_menuitems/2_menuitem-GET.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const validator = require('validator'); 3 | const assert = require('assert'); 4 | const is = require('is_js'); 5 | 6 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 7 | 8 | describe('Display menuitem | Get menuitem', function () { 9 | it('respond with json containing the list of menus', function (done) { 10 | request 11 | .get('/v1/display/menu/item') 12 | .set('Accept', 'application/json') 13 | .set('Authorization', 'Bearer ' + global.token) 14 | .expect(200) 15 | .expect('Content-Type', /json/) 16 | .expect(function (response) { 17 | assert(is.equal(2, response.body.length), 'must have 2 items in this menu'); 18 | const menu = response.body[0]; 19 | assert(is.propertyCount(menu, 8)); 20 | assert(is.number(menu.id)); 21 | assert(is.string(menu.name)); 22 | assert(is.null(menu.icon)); 23 | assert(is.object(menu.type)); 24 | assert(is.number(menu.type.id)); 25 | assert(is.number(menu.position)); 26 | assert(is.number(menu.menu_id)); 27 | assert(validator.isISO8601(menu.created_at)); 28 | assert(validator.isISO8601(menu.updated_at)); 29 | 30 | assert(is.equal(menu.id, global.id)); 31 | assert(validator.equals(menu.name, 'Laptop')); 32 | }) 33 | .end(function (err, response) { 34 | if (err) { 35 | return done(err + ' | Response: ' + response.text); 36 | } 37 | return done(); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /tests/RESTAPI/23_display/2_menuitems/5_menuitem-id-DELETE.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('Display menuitem | Delete menuitem', function () { 6 | it('delete the menu item', function (done) { 7 | request 8 | .delete('/v1/display/menu/item/' + global.id) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/RESTAPI/23_display/3_menuitemcustoms/9_finish.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('Display menuitemcustom | delete all', function () { 6 | it('delete a menu', function (done) { 7 | request 8 | .delete('/v1/display/menu/' + global.menu01id) 9 | .send({ name: 'Assets 01' }) 10 | .set('Accept', 'application/json') 11 | .set('Authorization', 'Bearer ' + global.token) 12 | .expect(200) 13 | .expect('Content-Type', /json/) 14 | .end(function (err, response) { 15 | if (err) { 16 | return done(err + ' | Response: ' + response.text); 17 | } 18 | return done(); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /tests/RESTAPI/23_display/5_typepanelitem/9_finish.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('Display typepanelitem | Delete types to finish', function () { 6 | it('soft delete the type', function (done) { 7 | request 8 | .delete('/v1/config/types/' + global.typeId) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('permanently delete the type', function (done) { 22 | request 23 | .delete('/v1/config/types/' + global.typeId) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/25_itemSearch/002_prepare-add-data.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('itemSearch | prepare data', function () { 6 | // eslint-disable-next-line mocha/no-setup-in-describe 7 | global.dataProvider.forEach((data) => { 8 | it('create an item: ' + data.name, function (done) { 9 | const itemData = { 10 | name: data.name, 11 | type_id: global.typeId, 12 | properties: [ 13 | ], 14 | }; 15 | for (let [valuetype, value] of Object.entries(data.properties)) { 16 | if (valuetype === 'list' && value !== null) { 17 | value = global.listvalues[value]; 18 | } 19 | if (valuetype === 'itemlink' && value !== null) { 20 | value = global[value]; 21 | } 22 | if (valuetype === 'itemlinks' && value !== null) { 23 | const values = []; 24 | for (const val of value) { 25 | values.push(global[val]); 26 | } 27 | value = values; 28 | } 29 | 30 | itemData.properties.push( 31 | { 32 | property_id: global.properties[valuetype], 33 | value, 34 | }, 35 | ); 36 | } 37 | request 38 | .post('/v1/items') 39 | .send(itemData) 40 | .set('Accept', 'application/json') 41 | .set('Authorization', 'Bearer ' + global.token) 42 | .expect(200) 43 | .expect('Content-Type', /json/) 44 | .expect(function (response) { 45 | }) 46 | .end(function (err, response) { 47 | if (err) { 48 | return done(err + ' | Response: ' + response.text); 49 | } 50 | return done(); 51 | }); 52 | }); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /tests/RESTAPI/26_items_users_properties_hidden/2_type-items-GET.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const assert = require('assert'); 3 | const is = require('is_js'); 4 | 5 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 6 | 7 | describe('items_users_properties_hidden | Endpoint /v1/items/type/ users (GET all)', function () { 8 | it('Get the items of the type users', function (done) { 9 | request 10 | .get('/v1/items/type/2') 11 | .set('Accept', 'application/json') 12 | .set('Authorization', 'Bearer ' + global.token) 13 | .expect(200) 14 | .expect('Content-Type', /json/) 15 | .expect(function (response) { 16 | assert(is.not.empty(response.body), 'response body must not be empty'); 17 | assert(is.array(response.body), 'response body must be an array'); 18 | const firstElement = response.body[0]; 19 | assert(is.array(firstElement.properties), 'the item properties must be an array'); 20 | 21 | const propertiesIds = []; 22 | let password = null; 23 | for (const property of firstElement.properties) { 24 | propertiesIds.push(property.id); 25 | if (property.id === 5) { 26 | password = property.value; 27 | } 28 | } 29 | 30 | assert.deepEqual(propertiesIds, [1, 2, 5, 6], 'We must have only first name, last name, empty password and activated properties'); 31 | assert(is.null(password), 'the password must be always null value when get, defined or not in the database'); 32 | }) 33 | .end(function (err, response) { 34 | if (err) { 35 | return done(err + ' | Response: ' + response.text); 36 | } 37 | return done(); 38 | }); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /tests/RESTAPI/27_passwordUserLogin/05_delete-users.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | 3 | const request = supertest('http://127.0.0.1/fusionsuite/backend'); 4 | 5 | describe('password user login | delete users', function () { 6 | it('Soft delete the user1', function (done) { 7 | request 8 | .delete('/v1/items/' + global.user1.toString()) 9 | .set('Accept', 'application/json') 10 | .set('Authorization', 'Bearer ' + global.token) 11 | .expect('Content-Type', /json/) 12 | .expect(200) 13 | .end(function (err, response) { 14 | if (err) { 15 | return done(err + ' | Response: ' + response.text); 16 | } 17 | return done(); 18 | }); 19 | }); 20 | 21 | it('Hard delete the user1', function (done) { 22 | request 23 | .delete('/v1/items/' + global.user1.toString()) 24 | .set('Accept', 'application/json') 25 | .set('Authorization', 'Bearer ' + global.token) 26 | .expect('Content-Type', /json/) 27 | .expect(200) 28 | .end(function (err, response) { 29 | if (err) { 30 | return done(err + ' | Response: ' + response.text); 31 | } 32 | return done(); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /tests/RESTAPI/README.md: -------------------------------------------------------------------------------- 1 | # Run REST API tests 2 | 3 | Need run mountebank fake server (HTTP, SMTP): 4 | 5 | ``` 6 | ./node_modules/.bin/mb --configfile mountebank/imposters.ejs 7 | ``` 8 | 9 | Need run too php script to do actions on the database 10 | 11 | ``` 12 | php -S 127.0.0.1:8012 testDatabaseAccess.php 13 | ``` 14 | 15 | Then run the tests: 16 | 17 | ``` 18 | ./node_modules/.bin/mocha --ignore "./node_modules/**/*.js" --ignore "./schemaValidation/**/*.js" "./**/*.js" 19 | ``` 20 | 21 | 22 | -------------------------------------------------------------------------------- /tests/RESTAPI/fusionsuite.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen [::]:80 default_server; 4 | 5 | root /var/www/public; 6 | index index.php index.html; 7 | server_name _; 8 | add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; 9 | add_header X-Frame-Options "SAMEORIGIN"; 10 | add_header Access-Control-Allow-Origin *; 11 | add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS, PUT, DELETE'; 12 | add_header Access-Control-Allow-Credentials true; 13 | add_header Access-Control-Allow-Headers 'Origin,Content-Type,Accept,Authorization,Cache-Control,Pragma,Expires'; 14 | add_header Access-Control-Expose-Headers 'X-Total-Count,Content-Range,Link'; 15 | 16 | location /fusionsuite/backend/ { 17 | allow 127.0.0.1; 18 | fastcgi_split_path_info ^/fusionsuite/backend(.+)()$; 19 | fastcgi_param SCRIPT_FILENAME $document_root/index.php$fastcgi_script_name; 20 | include fastcgi_params; 21 | fastcgi_pass unix:/run/php/php8.0-fpm.sock; 22 | fastcgi_param PATH_INFO $fastcgi_path_info; 23 | } 24 | } -------------------------------------------------------------------------------- /tests/RESTAPI/mountebank/imposters.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "imposters": [ 3 | <% include imposters/smtp.ejs %>, 4 | <% include imposters/zabbix.ejs %> 5 | ] 6 | } -------------------------------------------------------------------------------- /tests/RESTAPI/mountebank/imposters/smtp.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "port": 10025, 3 | "protocol": "smtp", 4 | "name": "smtp server not secured", 5 | "recordRequests": true, 6 | "requests": [ 7 | { 8 | "requestFrom": "127.0.0.1", 9 | "ip": "127.0.0.1" 10 | } 11 | ], 12 | "stubs": [] 13 | } -------------------------------------------------------------------------------- /tests/RESTAPI/mountebank/imposters/zabbix.ejs: -------------------------------------------------------------------------------- 1 | { 2 | "port": 10800, 3 | "protocol": "http", 4 | "name": "Zabbix API", 5 | "recordRequests": true, 6 | "requests": [ 7 | { 8 | "requestFrom": "127.0.0.1", 9 | "ip": "127.0.0.1" 10 | } 11 | ], 12 | "stubs": [ 13 | { 14 | "predicates": [{ 15 | "contains": { 16 | "body": "user.login" 17 | } 18 | }], 19 | "responses": [ 20 | { 21 | "is": { 22 | "body": { 23 | "jsonrpc": "2.0", 24 | "result": "0424bd59b807674191e7d77572075f33", 25 | "id": 1 26 | } 27 | } 28 | } 29 | ] 30 | }, 31 | { 32 | "predicates": [{ 33 | "contains": { 34 | "body": "apiinfo.version" 35 | } 36 | }], 37 | "responses": [ 38 | { 39 | "is": { 40 | "body": { 41 | "jsonrpc": "2.0", 42 | "result": "5.4.2", 43 | "id": 1 44 | } 45 | } 46 | } 47 | ] 48 | }, 49 | { 50 | "predicates": [{ 51 | "contains": { 52 | "body": "host.create" 53 | } 54 | }], 55 | "responses": [ 56 | { 57 | "is": { 58 | "body": { 59 | "jsonrpc": "2.0", 60 | "result": { 61 | "hostids": [ 62 | "107819" 63 | ] 64 | }, 65 | "id": "1" 66 | } 67 | } 68 | } 69 | ] 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /tests/RESTAPI/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@faker-js/faker": "^8.3.1", 4 | "assert": "^2.1.0", 5 | "is_js": "^0.9.0", 6 | "mocha": "^10.2.0", 7 | "mountebank": "^2.9.1", 8 | "nock": "^13.4.0", 9 | "supertest": "^6.3.3", 10 | "validator": "^13.11.0" 11 | }, 12 | "devDependencies": { 13 | "eslint": "^8.56.0", 14 | "eslint-config-standard": "^17.1.0", 15 | "eslint-plugin-import": "^2.29.1", 16 | "eslint-plugin-mocha": "^10.2.0", 17 | "eslint-plugin-n": "^16.5.0", 18 | "eslint-plugin-promise": "^6.1.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/ping", 3 | "method": "get", 4 | "parameters": [], 5 | "responses": [] 6 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/ping/get/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/ping", 3 | "method": "get", 4 | "parameters": [ 5 | { 6 | "in": "body", 7 | "schema": { 8 | "properties": [], 9 | "type": "object", 10 | "required": [] 11 | } 12 | } 13 | ], 14 | "responses": [] 15 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/ping/get/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/ping", 3 | "method": "get", 4 | "parameters": [], 5 | "responses": [] 6 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/post/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "$schema": "http:\/\/json-schema.org\/draft-04\/schema#", 16 | "title": "Request-Example:", 17 | "type": "object", 18 | "properties": [] 19 | }, 20 | "description": "Request-Example:" 21 | } 22 | ], 23 | "responses": { 24 | "id": { 25 | "type": "number", 26 | "description": "The id of the item." 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/post/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "query", 8 | "name": "name", 9 | "description": "The name of the item.", 10 | "required": true 11 | }, 12 | { 13 | "type": "number", 14 | "in": "query", 15 | "name": "type_id", 16 | "description": "The id of the type of the item.", 17 | "required": true 18 | }, 19 | { 20 | "type": "object[]", 21 | "in": "query", 22 | "name": "properties", 23 | "description": "List of properties", 24 | "required": true 25 | }, 26 | { 27 | "type": "number", 28 | "in": "query", 29 | "name": "properties.property_id", 30 | "description": "The id of the property.", 31 | "required": true 32 | }, 33 | { 34 | "type": "string[]", 35 | "in": "query", 36 | "name": "properties.value", 37 | "description": "The value of the property for the item.", 38 | "required": true 39 | }, 40 | { 41 | "type": "string", 42 | "in": "header", 43 | "name": "Authorization", 44 | "description": "The JWT token.", 45 | "required": true 46 | } 47 | ], 48 | "responses": { 49 | "id": { 50 | "type": "number", 51 | "description": "The id of the item." 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/delete/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}", 3 | "method": "delete", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "properties": { 16 | "id": { 17 | "type": "number", 18 | "description": "Unique ID of the item." 19 | } 20 | }, 21 | "type": "object", 22 | "required": [ 23 | "id" 24 | ] 25 | } 26 | } 27 | ], 28 | "responses": [] 29 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/delete/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}", 3 | "method": "delete", 4 | "parameters": [ 5 | { 6 | "type": "number", 7 | "in": "path", 8 | "name": "id", 9 | "description": "Unique ID of the item.", 10 | "required": true 11 | }, 12 | { 13 | "type": "string", 14 | "in": "header", 15 | "name": "Authorization", 16 | "description": "The JWT token.", 17 | "required": true 18 | } 19 | ], 20 | "responses": [] 21 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/patch/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}", 3 | "method": "patch", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "$schema": "http:\/\/json-schema.org\/draft-04\/schema#", 16 | "title": "Request-Example:", 17 | "type": "object", 18 | "properties": { 19 | "id": { 20 | "type": "number", 21 | "description": "Unique ID of the item." 22 | } 23 | }, 24 | "required": [ 25 | "id" 26 | ] 27 | }, 28 | "description": "Request-Example:" 29 | } 30 | ], 31 | "responses": [] 32 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/patch/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}", 3 | "method": "patch", 4 | "parameters": [ 5 | { 6 | "type": "number", 7 | "in": "path", 8 | "name": "id", 9 | "description": "Unique ID of the item.", 10 | "required": true 11 | }, 12 | { 13 | "type": "string", 14 | "in": "header", 15 | "name": "Authorization", 16 | "description": "The JWT token.", 17 | "required": true 18 | } 19 | ], 20 | "responses": { 21 | "name": { 22 | "type": "string", 23 | "description": "Name of the type." 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/property/{propertyid}/patch/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}\/property\/{propertyid}", 3 | "method": "patch", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "$schema": "http:\/\/json-schema.org\/draft-04\/schema#", 16 | "title": "Request-Example:", 17 | "type": "object", 18 | "properties": { 19 | "value": { 20 | "type": "null" 21 | }, 22 | "reset_to_default": { 23 | "type": "boolean" 24 | }, 25 | "id": { 26 | "type": "number", 27 | "description": "Unique ID of the item." 28 | }, 29 | "propertyid": { 30 | "type": "number", 31 | "description": "Unique ID of the property." 32 | } 33 | }, 34 | "required": [ 35 | "id", 36 | "propertyid" 37 | ] 38 | }, 39 | "description": "Request-Example:" 40 | } 41 | ], 42 | "responses": [] 43 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/property/{propertyid}/patch/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}\/property\/{propertyid}", 3 | "method": "patch", 4 | "parameters": [ 5 | { 6 | "type": "number", 7 | "in": "path", 8 | "name": "id", 9 | "description": "Unique ID of the item.", 10 | "required": true 11 | }, 12 | { 13 | "type": "number", 14 | "in": "path", 15 | "name": "propertyid", 16 | "description": "Unique ID of the property.", 17 | "required": true 18 | }, 19 | { 20 | "type": "string", 21 | "in": "header", 22 | "name": "Authorization", 23 | "description": "The JWT token.", 24 | "required": true 25 | } 26 | ], 27 | "responses": { 28 | "value": { 29 | "type": "string", 30 | "description": "Value of the property to update." 31 | }, 32 | "reset_to_default": { 33 | "type": "boolean", 34 | "description": "To update with default value of property.", 35 | "default": "false" 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/property/{propertyid}/typelinks/post/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}\/property\/{propertyid}\/typelinks", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "$schema": "http:\/\/json-schema.org\/draft-04\/schema#", 16 | "title": "Request-Example:", 17 | "type": "object", 18 | "properties": { 19 | "value": { 20 | "type": "number" 21 | }, 22 | "id": { 23 | "type": "number", 24 | "description": "Unique ID of the item." 25 | }, 26 | "propertyid": { 27 | "type": "number", 28 | "description": "Unique ID of the property." 29 | } 30 | }, 31 | "required": [ 32 | "id", 33 | "propertyid" 34 | ] 35 | }, 36 | "description": "Request-Example:" 37 | } 38 | ], 39 | "responses": { 40 | "value": { 41 | "type": "number", 42 | "description": "Unique ID of the type." 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/property/{propertyid}/typelinks/post/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}\/property\/{propertyid}\/typelinks", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "number", 7 | "in": "path", 8 | "name": "id", 9 | "description": "Unique ID of the item.", 10 | "required": true 11 | }, 12 | { 13 | "type": "number", 14 | "in": "path", 15 | "name": "propertyid", 16 | "description": "Unique ID of the property.", 17 | "required": true 18 | }, 19 | { 20 | "type": "string", 21 | "in": "header", 22 | "name": "Authorization", 23 | "description": "The JWT token.", 24 | "required": true 25 | } 26 | ], 27 | "responses": { 28 | "value": { 29 | "type": "number", 30 | "description": "Unique ID of the type." 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/property/{propertyid}/typelinks/{typelinkid}/delete/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}\/property\/{propertyid}\/typelinks\/{typelinkid}", 3 | "method": "delete", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "properties": { 16 | "id": { 17 | "type": "number", 18 | "description": "Unique ID of the item." 19 | }, 20 | "propertyid": { 21 | "type": "number", 22 | "description": "Unique ID of the property." 23 | }, 24 | "typelinkid": { 25 | "type": "number", 26 | "description": "Unique ID of the typelink." 27 | } 28 | }, 29 | "type": "object", 30 | "required": [ 31 | "id", 32 | "propertyid", 33 | "typelinkid" 34 | ] 35 | } 36 | } 37 | ], 38 | "responses": [] 39 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/items/{id}/property/{propertyid}/typelinks/{typelinkid}/delete/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/items\/{id}\/property\/{propertyid}\/typelinks\/{typelinkid}", 3 | "method": "delete", 4 | "parameters": [ 5 | { 6 | "type": "number", 7 | "in": "path", 8 | "name": "id", 9 | "description": "Unique ID of the item.", 10 | "required": true 11 | }, 12 | { 13 | "type": "number", 14 | "in": "path", 15 | "name": "propertyid", 16 | "description": "Unique ID of the property.", 17 | "required": true 18 | }, 19 | { 20 | "type": "number", 21 | "in": "path", 22 | "name": "typelinkid", 23 | "description": "Unique ID of the typelink.", 24 | "required": true 25 | }, 26 | { 27 | "type": "string", 28 | "in": "header", 29 | "name": "Authorization", 30 | "description": "The JWT token.", 31 | "required": true 32 | } 33 | ], 34 | "responses": [] 35 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{id}/delete/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{id}", 3 | "method": "delete", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "properties": { 16 | "id": { 17 | "type": "number", 18 | "description": "Unique ID of the item." 19 | } 20 | }, 21 | "type": "object", 22 | "required": [ 23 | "id" 24 | ] 25 | } 26 | } 27 | ], 28 | "responses": [] 29 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{id}/delete/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{id}", 3 | "method": "delete", 4 | "parameters": [ 5 | { 6 | "type": "number", 7 | "in": "path", 8 | "name": "id", 9 | "description": "Unique ID of the item.", 10 | "required": true 11 | }, 12 | { 13 | "type": "string", 14 | "in": "header", 15 | "name": "Authorization", 16 | "description": "The JWT token.", 17 | "required": true 18 | } 19 | ], 20 | "responses": [] 21 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{type}/get/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{type}", 3 | "method": "get", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "query", 8 | "name": "type", 9 | "description": "The type of the rules.", 10 | "required": true 11 | }, 12 | { 13 | "type": "string", 14 | "in": "header", 15 | "name": "Authorization", 16 | "description": "The JWT token.", 17 | "required": true 18 | }, 19 | { 20 | "in": "body", 21 | "schema": { 22 | "properties": [], 23 | "type": "object", 24 | "required": [] 25 | } 26 | } 27 | ], 28 | "responses": { 29 | "id": { 30 | "type": "integer", 31 | "description": "The id of the item." 32 | }, 33 | "name": { 34 | "type": "string", 35 | "description": "The name of the item." 36 | }, 37 | "comment": { 38 | "type": "string", 39 | "description": "The comment of the item." 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{type}/get/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{type}", 3 | "method": "get", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "path", 8 | "name": "type", 9 | "description": "The type of the rules.", 10 | "required": true 11 | }, 12 | { 13 | "type": "string", 14 | "in": "header", 15 | "name": "Authorization", 16 | "description": "The JWT token.", 17 | "required": true 18 | } 19 | ], 20 | "responses": { 21 | "id": { 22 | "type": "integer", 23 | "description": "The id of the item." 24 | }, 25 | "name": { 26 | "type": "string", 27 | "description": "The name of the item." 28 | }, 29 | "comment": { 30 | "type": "string", 31 | "description": "The comment of the item." 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{type}/post/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{type}", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "properties": { 16 | "type": { 17 | "type": "number", 18 | "description": "Id of the type." 19 | } 20 | }, 21 | "type": "object", 22 | "required": [ 23 | "type" 24 | ] 25 | } 26 | } 27 | ], 28 | "responses": [] 29 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{type}/post/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{type}", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "query", 8 | "name": "name", 9 | "description": "Name of the rule.", 10 | "required": true 11 | }, 12 | { 13 | "type": "string", 14 | "in": "query", 15 | "name": "comment", 16 | "description": "Comment of the rule.", 17 | "required": true 18 | }, 19 | { 20 | "type": "string", 21 | "in": "header", 22 | "name": "Authorization", 23 | "description": "The JWT token.", 24 | "required": true 25 | } 26 | ], 27 | "responses": [] 28 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{type}/{id}/action/post/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{type}\/{id}\/action", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "properties": { 16 | "name": { 17 | "type": "string", 18 | "description": "Name of the rule." 19 | }, 20 | "comment": { 21 | "type": "string", 22 | "description": "Comment of the rule." 23 | } 24 | }, 25 | "type": "object", 26 | "required": [ 27 | "name", 28 | "comment" 29 | ] 30 | } 31 | } 32 | ], 33 | "responses": [] 34 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{type}/{id}/action/post/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{type}\/{id}\/action", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "query", 8 | "name": "name", 9 | "description": "Name of the rule.", 10 | "required": true 11 | }, 12 | { 13 | "type": "string", 14 | "in": "query", 15 | "name": "comment", 16 | "description": "Comment of the rule.", 17 | "required": true 18 | }, 19 | { 20 | "type": "string", 21 | "in": "header", 22 | "name": "Authorization", 23 | "description": "The JWT token.", 24 | "required": true 25 | } 26 | ], 27 | "responses": [] 28 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{type}/{id}/criteria/post/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{type}\/{id}\/criteria", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "header", 8 | "name": "Authorization", 9 | "description": "The JWT token.", 10 | "required": true 11 | }, 12 | { 13 | "in": "body", 14 | "schema": { 15 | "properties": { 16 | "name": { 17 | "type": "string", 18 | "description": "Name of the rule." 19 | }, 20 | "comment": { 21 | "type": "string", 22 | "description": "Comment of the rule." 23 | } 24 | }, 25 | "type": "object", 26 | "required": [ 27 | "name", 28 | "comment" 29 | ] 30 | } 31 | } 32 | ], 33 | "responses": [] 34 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/rules/{type}/{id}/criteria/post/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/rules\/{type}\/{id}\/criteria", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "type": "string", 7 | "in": "query", 8 | "name": "name", 9 | "description": "Name of the rule.", 10 | "required": true 11 | }, 12 | { 13 | "type": "string", 14 | "in": "query", 15 | "name": "comment", 16 | "description": "Comment of the rule.", 17 | "required": true 18 | }, 19 | { 20 | "type": "string", 21 | "in": "header", 22 | "name": "Authorization", 23 | "description": "The JWT token.", 24 | "required": true 25 | } 26 | ], 27 | "responses": [] 28 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/status/get/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/status", 3 | "method": "get", 4 | "parameters": [ 5 | { 6 | "in": "body", 7 | "schema": { 8 | "properties": [], 9 | "type": "object", 10 | "required": [] 11 | } 12 | } 13 | ], 14 | "responses": { 15 | "connections": { 16 | "type": "object", 17 | "properties": { 18 | "database": { 19 | "type": "boolean", 20 | "description": "true if the connection to the database is OK" 21 | } 22 | }, 23 | "required": [ 24 | "database" 25 | ] 26 | }, 27 | "crontasks": { 28 | "type": "array", 29 | "description": "The status of the crontasks." 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/status/get/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/status", 3 | "method": "get", 4 | "parameters": [], 5 | "responses": { 6 | "connections": { 7 | "type": "object", 8 | "properties": { 9 | "database": { 10 | "type": "boolean", 11 | "description": "true if the connection to the database is OK" 12 | } 13 | }, 14 | "required": [ 15 | "database" 16 | ] 17 | }, 18 | "crontasks": { 19 | "type": "array", 20 | "description": "The status of the crontasks." 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/status/get/test.js: -------------------------------------------------------------------------------- 1 | const commonSchema = require('../../../commonSchema.js'); 2 | 3 | const fs = require('fs'); 4 | const json = JSON.parse(fs.readFileSync('schemaValidation/v1/status/get/schema.json', 'utf-8')); 5 | const path = json.path; 6 | const method = json.method; 7 | 8 | describe('Schema REST API | ' + path + ' | ' + method, function () { 9 | describe('test the get status', function () { 10 | it('generate the headers', function (done) { 11 | commonSchema.generateHeaders(done, json.parameters); 12 | }); 13 | 14 | it('generate the data', function (done) { 15 | commonSchema.generateData(done, json.parameters, {}); 16 | }); 17 | 18 | it('generate the path: ' + path, function (done) { 19 | commonSchema.generatePath(done, path, {}); 20 | }); 21 | 22 | it('check the endpoint and the response', function (done) { 23 | commonSchema.executeRequest(done, json.method, json.responses); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/token/post/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/token", 3 | "method": "post", 4 | "parameters": [ 5 | { 6 | "in": "body", 7 | "schema": { 8 | "$schema": "http:\/\/json-schema.org\/draft-04\/schema#", 9 | "title": "Request-Example:", 10 | "type": "object", 11 | "properties": { 12 | "login": { 13 | "type": "string" 14 | }, 15 | "password": { 16 | "type": "string" 17 | } 18 | } 19 | }, 20 | "description": "Request-Example:" 21 | } 22 | ], 23 | "responses": { 24 | "token": { 25 | "type": "string", 26 | "description": "The token string." 27 | }, 28 | "refreshtoken": { 29 | "type": "string", 30 | "description": "The token string can be used to refresh \/ regenerate a new token when this token expire." 31 | }, 32 | "expires": { 33 | "type": "integer", 34 | "description": "The expiration timestamp." 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /tests/RESTAPI/schemaValidation/v1/token/post/schema.json.old: -------------------------------------------------------------------------------- 1 | { 2 | "path": "\/v1\/token", 3 | "method": "post", 4 | "parameters": [], 5 | "responses": { 6 | "token": { 7 | "type": "string", 8 | "description": "The token string." 9 | }, 10 | "refreshtoken": { 11 | "type": "string", 12 | "description": "The token string can be used to refresh \/ regenerate a new token when this token expire." 13 | }, 14 | "expires": { 15 | "type": "integer", 16 | "description": "The expiration timestamp." 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /tests/performances/README.md: -------------------------------------------------------------------------------- 1 | # Performances tests 2 | 3 | In this folder, there are scripts for use with k6 (https://k6.io/). 4 | 5 | The goal is to have scripts testing the performances of the backend in queries charge. 6 | Needs too test with many data in the backend. 7 | 8 | # Run 9 | 10 | The command to run the script is: 11 | 12 | ``` 13 | k6 run --vus 10 --duration 30s file.js 14 | ``` 15 | 16 | -------------------------------------------------------------------------------- /tests/performances/itemsUniqueId.js: -------------------------------------------------------------------------------- 1 | // Check if no collisions when generate internal id incremented by 1 and based on type_id 2 | 3 | import http from 'k6/http'; 4 | 5 | import { sleep } from 'k6'; 6 | 7 | export const options = { 8 | 9 | thresholds: { 10 | http_req_failed: ['rate<0.01'], // http errors should be less than 1% 11 | http_req_duration: ['p(95)<200'], // 95% of requests should be below 200ms 12 | }, 13 | }; 14 | 15 | export function setup() { 16 | const url = 'http://127.0.0.1/fusionsuite/backend/v1/token'; 17 | 18 | const params = { 19 | headers: { 20 | 'Content-Type': 'application/json' 21 | }, 22 | }; 23 | 24 | const payload = JSON.stringify({ 25 | login: 'admin', 26 | password: 'admin', 27 | }); 28 | 29 | const res = http.post(url, payload, params); 30 | return res.json(); 31 | } 32 | 33 | export default function (data) { 34 | 35 | const url = 'http://127.0.0.1/fusionsuite/backend/v1/items'; 36 | 37 | const params = { 38 | headers: { 39 | 'Content-Type': 'application/json', 40 | 'Authorization': 'Bearer '+data.token 41 | }, 42 | }; 43 | 44 | const payload = JSON.stringify({ 45 | name: 'test', 46 | type_id: 3, 47 | }); 48 | 49 | http.post(url, payload, params); 50 | 51 | sleep(1); 52 | } 53 | -------------------------------------------------------------------------------- /tests/performances/test.js: -------------------------------------------------------------------------------- 1 | import http from 'k6/http'; 2 | 3 | import { sleep } from 'k6'; 4 | 5 | export const options = { 6 | 7 | thresholds: { 8 | http_req_failed: ['rate<0.01'], // http errors should be less than 1% 9 | http_req_duration: ['p(95)<200'], // 95% of requests should be below 200ms 10 | }, 11 | }; 12 | 13 | export function setup() { 14 | const url = 'http://127.0.0.1/fusionsuite/backend/v1/token'; 15 | 16 | const params = { 17 | headers: { 18 | 'Content-Type': 'application/json' 19 | }, 20 | }; 21 | 22 | const payload = JSON.stringify({ 23 | login: 'admin', 24 | password: 'admin', 25 | }); 26 | 27 | const res = http.post(url, payload, params); 28 | return res.json(); 29 | } 30 | 31 | export default function (data) { 32 | 33 | const url = 'http://127.0.0.1/fusionsuite/backend/v1/config/types/3'; 34 | 35 | const params = { 36 | headers: { 37 | 'Content-Type': 'application/json', 38 | 'Authorization': 'Bearer '+data.token 39 | }, 40 | }; 41 | 42 | http.get(url, params); 43 | 44 | sleep(1); 45 | } --------------------------------------------------------------------------------