@strapi/admin 5.0.0-rc.9 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/{AdminSeatInfo-j58AKYvZ.js → AdminSeatInfo-8vtNB3ck.js} +3 -3
- package/dist/admin/{AdminSeatInfo-j58AKYvZ.js.map → AdminSeatInfo-8vtNB3ck.js.map} +1 -1
- package/dist/admin/{AdminSeatInfo-qGNvhfii.mjs → AdminSeatInfo-qIgh5-QA.mjs} +4 -4
- package/dist/admin/{AdminSeatInfo-qGNvhfii.mjs.map → AdminSeatInfo-qIgh5-QA.mjs.map} +1 -1
- package/dist/admin/{ApplicationInfoPage-ahnTcFV1.mjs → ApplicationInfoPage-AAIv_ZkF.mjs} +5 -5
- package/dist/admin/{ApplicationInfoPage-ahnTcFV1.mjs.map → ApplicationInfoPage-AAIv_ZkF.mjs.map} +1 -1
- package/dist/admin/{ApplicationInfoPage-JfdJ0U4H.js → ApplicationInfoPage-bkWa99An.js} +5 -5
- package/dist/admin/{ApplicationInfoPage-JfdJ0U4H.js.map → ApplicationInfoPage-bkWa99An.js.map} +1 -1
- package/dist/admin/{AuthResponse-J8A48xdo.mjs → AuthResponse-HYXVuTDF.mjs} +2 -2
- package/dist/admin/{AuthResponse-J8A48xdo.mjs.map → AuthResponse-HYXVuTDF.mjs.map} +1 -1
- package/dist/admin/{AuthResponse-KlTDmm2i.js → AuthResponse-R8kR_yqS.js} +2 -2
- package/dist/admin/{AuthResponse-KlTDmm2i.js.map → AuthResponse-R8kR_yqS.js.map} +1 -1
- package/dist/admin/{AuthenticatedLayout-06fn7qrH.mjs → AuthenticatedLayout-J22BBdYe.mjs} +31 -39
- package/dist/admin/AuthenticatedLayout-J22BBdYe.mjs.map +1 -0
- package/dist/admin/{AuthenticatedLayout-eKDwvUFO.js → AuthenticatedLayout-ZAXB7o93.js} +30 -38
- package/dist/admin/AuthenticatedLayout-ZAXB7o93.js.map +1 -0
- package/dist/admin/{CreateActionEE-Yfp4hs7a.mjs → CreateActionEE-X2nnG2dm.mjs} +2 -2
- package/dist/admin/{CreateActionEE-Yfp4hs7a.mjs.map → CreateActionEE-X2nnG2dm.mjs.map} +1 -1
- package/dist/admin/{CreatePage-68skzZjY.js → CreatePage-3V_sa8A4.js} +3 -3
- package/dist/admin/{CreatePage-68skzZjY.js.map → CreatePage-3V_sa8A4.js.map} +1 -1
- package/dist/admin/{CreatePage-bdWb1wg4.mjs → CreatePage-5WzWwepG.mjs} +7 -7
- package/dist/admin/CreatePage-5WzWwepG.mjs.map +1 -0
- package/dist/admin/{CreatePage-Yd5JyWS5.mjs → CreatePage-hEdR3uWK.mjs} +3 -3
- package/dist/admin/{CreatePage-Yd5JyWS5.mjs.map → CreatePage-hEdR3uWK.mjs.map} +1 -1
- package/dist/admin/{CreatePage-t5HQUOqJ.js → CreatePage-zzbF8IhD.js} +6 -6
- package/dist/admin/CreatePage-zzbF8IhD.js.map +1 -0
- package/dist/admin/{CreateView-yv51Pyvw.js → CreateView-5EC5Yv96.js} +3 -3
- package/dist/admin/{CreateView-yv51Pyvw.js.map → CreateView-5EC5Yv96.js.map} +1 -1
- package/dist/admin/{CreateView-ZZaA8hbe.mjs → CreateView-OjaERndy.mjs} +3 -3
- package/dist/admin/{CreateView-ZZaA8hbe.mjs.map → CreateView-OjaERndy.mjs.map} +1 -1
- package/dist/admin/{CreateView-V0v5CK8t.mjs → CreateView-S8gDQUCt.mjs} +3 -3
- package/dist/admin/{CreateView-V0v5CK8t.mjs.map → CreateView-S8gDQUCt.mjs.map} +1 -1
- package/dist/admin/{CreateView-nzILLv0g.js → CreateView-ZQEmP8-n.js} +3 -3
- package/dist/admin/{CreateView-nzILLv0g.js.map → CreateView-ZQEmP8-n.js.map} +1 -1
- package/dist/admin/{EditPage-cWJ8V1BK.mjs → EditPage-493L2-vV.mjs} +27 -23
- package/dist/admin/EditPage-493L2-vV.mjs.map +1 -0
- package/dist/admin/{EditPage-A7-BewPd.mjs → EditPage-7fMqo-c-.mjs} +7 -7
- package/dist/admin/EditPage-7fMqo-c-.mjs.map +1 -0
- package/dist/admin/{EditPage-pTQCDncU.js → EditPage-8T9gBnnc.js} +25 -21
- package/dist/admin/EditPage-8T9gBnnc.js.map +1 -0
- package/dist/admin/{EditPage-Lw36XG9G.js → EditPage-OFlfNGv0.js} +6 -6
- package/dist/admin/EditPage-OFlfNGv0.js.map +1 -0
- package/dist/admin/{EditPage-2cMhX4F_.mjs → EditPage-akxbKeqK.mjs} +8 -8
- package/dist/admin/{EditPage-2cMhX4F_.mjs.map → EditPage-akxbKeqK.mjs.map} +1 -1
- package/dist/admin/{EditPage-LoESB5pq.js → EditPage-gJJgatNc.js} +7 -7
- package/dist/admin/{EditPage-LoESB5pq.js.map → EditPage-gJJgatNc.js.map} +1 -1
- package/dist/admin/{EditView-KzdDTSO-.js → EditView-ZJPPeal2.js} +5 -6
- package/dist/admin/EditView-ZJPPeal2.js.map +1 -0
- package/dist/admin/{EditView-HygMdUSf.mjs → EditView-_QID3gT5.mjs} +7 -8
- package/dist/admin/EditView-_QID3gT5.mjs.map +1 -0
- package/dist/admin/{EditViewPage-FgsrW_wV.js → EditViewPage-_wx5u6QJ.js} +5 -5
- package/dist/admin/{EditViewPage-FgsrW_wV.js.map → EditViewPage-_wx5u6QJ.js.map} +1 -1
- package/dist/admin/{EditViewPage-47F2xHBt.mjs → EditViewPage-zkNmb1zg.mjs} +6 -6
- package/dist/admin/{EditViewPage-47F2xHBt.mjs.map → EditViewPage-zkNmb1zg.mjs.map} +1 -1
- package/dist/admin/{EventsTable--XlOTHxM.js → EventsTable-31485Cwq.js} +2 -2
- package/dist/admin/{EventsTable--XlOTHxM.js.map → EventsTable-31485Cwq.js.map} +1 -1
- package/dist/admin/{EventsTable-mgIyB8DL.mjs → EventsTable-_BT8dIHY.mjs} +2 -2
- package/dist/admin/{EventsTable-mgIyB8DL.mjs.map → EventsTable-_BT8dIHY.mjs.map} +1 -1
- package/dist/admin/{HomePage-dyDldozB.mjs → HomePage-LenrY0bj.mjs} +7 -10
- package/dist/admin/HomePage-LenrY0bj.mjs.map +1 -0
- package/dist/admin/{HomePage-H77dsrr1.mjs → HomePage-NdId9gqT.mjs} +3 -3
- package/dist/admin/{HomePage-H77dsrr1.mjs.map → HomePage-NdId9gqT.mjs.map} +1 -1
- package/dist/admin/{HomePage-ywYHZHMa.js → HomePage-T2yVEfC3.js} +15 -18
- package/dist/admin/HomePage-T2yVEfC3.js.map +1 -0
- package/dist/admin/{HomePage-uVwht52t.js → HomePage-yyizKL39.js} +3 -3
- package/dist/admin/{HomePage-uVwht52t.js.map → HomePage-yyizKL39.js.map} +1 -1
- package/dist/admin/{InstalledPluginsPage-3OSkplVn.mjs → InstalledPlugins-Z_uS95dC.mjs} +9 -11
- package/dist/admin/InstalledPlugins-Z_uS95dC.mjs.map +1 -0
- package/dist/admin/{InstalledPluginsPage-JkruwT2d.js → InstalledPlugins-spdwM8ub.js} +9 -11
- package/dist/admin/InstalledPlugins-spdwM8ub.js.map +1 -0
- package/dist/admin/{Layout-8Ds_z3XN.mjs → Layout-5lg6USuO.mjs} +5 -5
- package/dist/admin/{Layout-8Ds_z3XN.mjs.map → Layout-5lg6USuO.mjs.map} +1 -1
- package/dist/admin/{Layout-pVTNV6PU.js → Layout-B3TQMQxb.js} +5 -5
- package/dist/admin/{Layout-pVTNV6PU.js.map → Layout-B3TQMQxb.js.map} +1 -1
- package/dist/admin/{ListPage-semY3kTl.mjs → ListPage--B6TB-mt.mjs} +4 -4
- package/dist/admin/{ListPage-semY3kTl.mjs.map → ListPage--B6TB-mt.mjs.map} +1 -1
- package/dist/admin/{ListPage-DHUp0PDw.js → ListPage-GRLtmRuy.js} +8 -8
- package/dist/admin/ListPage-GRLtmRuy.js.map +1 -0
- package/dist/admin/{ListPage-NtjeF8R2.mjs → ListPage-Ggd99FLO.mjs} +4 -4
- package/dist/admin/{ListPage-NtjeF8R2.mjs.map → ListPage-Ggd99FLO.mjs.map} +1 -1
- package/dist/admin/{ListPage-OIdhjljI.js → ListPage-Hc3VZ9O3.js} +6 -6
- package/dist/admin/{ListPage-OIdhjljI.js.map → ListPage-Hc3VZ9O3.js.map} +1 -1
- package/dist/admin/{ListPage-LokTy34i.mjs → ListPage-LIn0aEKt.mjs} +3 -3
- package/dist/admin/{ListPage-LokTy34i.mjs.map → ListPage-LIn0aEKt.mjs.map} +1 -1
- package/dist/admin/{ListPage-15KiUCLt.js → ListPage-UEsKYDPH.js} +3 -3
- package/dist/admin/{ListPage-15KiUCLt.js.map → ListPage-UEsKYDPH.js.map} +1 -1
- package/dist/admin/{ListPage-dApwERT6.js → ListPage-Vf4xtn8w.js} +5 -5
- package/dist/admin/{ListPage-dApwERT6.js.map → ListPage-Vf4xtn8w.js.map} +1 -1
- package/dist/admin/{ListPage-8M-bmv0a.mjs → ListPage-rCkaHmeP.mjs} +6 -6
- package/dist/admin/{ListPage-8M-bmv0a.mjs.map → ListPage-rCkaHmeP.mjs.map} +1 -1
- package/dist/admin/{ListPage-hNIbvh17.mjs → ListPage-vJik-wkj.mjs} +10 -10
- package/dist/admin/ListPage-vJik-wkj.mjs.map +1 -0
- package/dist/admin/{ListPage-jTpJnTuQ.js → ListPage-y3rcDJX1.js} +3 -3
- package/dist/admin/{ListPage-jTpJnTuQ.js.map → ListPage-y3rcDJX1.js.map} +1 -1
- package/dist/admin/{ListView-ZSEn2tK5.js → ListView-8pEtfLsu.js} +5 -5
- package/dist/admin/{ListView-ZSEn2tK5.js.map → ListView-8pEtfLsu.js.map} +1 -1
- package/dist/admin/{ListView-tCCo7pVS.mjs → ListView-iCqFRGiO.mjs} +5 -5
- package/dist/admin/{ListView-tCCo7pVS.mjs.map → ListView-iCqFRGiO.mjs.map} +1 -1
- package/dist/admin/{ListView-kEuSmXPm.mjs → ListView-jrsV1wF_.mjs} +5 -5
- package/dist/admin/{ListView-kEuSmXPm.mjs.map → ListView-jrsV1wF_.mjs.map} +1 -1
- package/dist/admin/{ListView-MA83TDJF.js → ListView-noYLY_DM.js} +4 -4
- package/dist/admin/{ListView-MA83TDJF.js.map → ListView-noYLY_DM.js.map} +1 -1
- package/dist/admin/{Login-GLcLgHUd.mjs → Login--GgWQano.mjs} +3 -3
- package/dist/admin/{Login-GLcLgHUd.mjs.map → Login--GgWQano.mjs.map} +1 -1
- package/dist/admin/{Login-RrWZQA_X.js → Login-qr72UXGp.js} +3 -3
- package/dist/admin/{Login-RrWZQA_X.js.map → Login-qr72UXGp.js.map} +1 -1
- package/dist/admin/{MagicLinkEE-u0n-nwtv.js → MagicLinkEE-uTufI4yx.js} +3 -3
- package/dist/admin/{MagicLinkEE-u0n-nwtv.js.map → MagicLinkEE-uTufI4yx.js.map} +1 -1
- package/dist/admin/{MagicLinkEE-_qltdLkk.mjs → MagicLinkEE-vQcgXndx.mjs} +3 -3
- package/dist/admin/{MagicLinkEE-_qltdLkk.mjs.map → MagicLinkEE-vQcgXndx.mjs.map} +1 -1
- package/dist/admin/{MarketplacePage-41CstG0b.mjs → MarketplacePage-LRlL_4ys.mjs} +64 -63
- package/dist/admin/MarketplacePage-LRlL_4ys.mjs.map +1 -0
- package/dist/admin/{MarketplacePage-uyOTT12t.js → MarketplacePage-yRWZ54oN.js} +65 -64
- package/dist/admin/MarketplacePage-yRWZ54oN.js.map +1 -0
- package/dist/admin/{Permissions-J2jRpCh_.mjs → Permissions-aSGK8VGG.mjs} +2 -2
- package/dist/admin/{Permissions-J2jRpCh_.mjs.map → Permissions-aSGK8VGG.mjs.map} +1 -1
- package/dist/admin/{Permissions-LMVH6wf4.js → Permissions-bmMBmcv7.js} +2 -2
- package/dist/admin/{Permissions-LMVH6wf4.js.map → Permissions-bmMBmcv7.js.map} +1 -1
- package/dist/admin/{PrivateRoute-ndqg7K6H.js → PrivateRoute-LO9G_pCJ.js} +2 -2
- package/dist/admin/{PrivateRoute-ndqg7K6H.js.map → PrivateRoute-LO9G_pCJ.js.map} +1 -1
- package/dist/admin/{PrivateRoute-4oRTB_tX.mjs → PrivateRoute-S4Lol0B9.mjs} +2 -2
- package/dist/admin/{PrivateRoute-4oRTB_tX.mjs.map → PrivateRoute-S4Lol0B9.mjs.map} +1 -1
- package/dist/admin/{ProfilePage-wxZFen3W.js → ProfilePage-Mte9RhXw.js} +5 -5
- package/dist/admin/ProfilePage-Mte9RhXw.js.map +1 -0
- package/dist/admin/{ProfilePage-zwG0fq_e.mjs → ProfilePage-voofTYei.mjs} +6 -6
- package/dist/admin/ProfilePage-voofTYei.mjs.map +1 -0
- package/dist/admin/{PurchaseAuditLogs-FDPV-ZqU.mjs → PurchaseAuditLogs-8wmVhLCb.mjs} +2 -2
- package/dist/admin/{PurchaseAuditLogs-FDPV-ZqU.mjs.map → PurchaseAuditLogs-8wmVhLCb.mjs.map} +1 -1
- package/dist/admin/{PurchaseAuditLogs-f6iczpRi.js → PurchaseAuditLogs-qxVh-U_P.js} +2 -2
- package/dist/admin/{PurchaseAuditLogs-f6iczpRi.js.map → PurchaseAuditLogs-qxVh-U_P.js.map} +1 -1
- package/dist/admin/{PurchaseSingleSignOn-S0B2HM4d.mjs → PurchaseSingleSignOn-kgjD8gsd.mjs} +2 -2
- package/dist/admin/{PurchaseSingleSignOn-S0B2HM4d.mjs.map → PurchaseSingleSignOn-kgjD8gsd.mjs.map} +1 -1
- package/dist/admin/{PurchaseSingleSignOn-0wXAjOLm.js → PurchaseSingleSignOn-ovEsG_Ud.js} +2 -2
- package/dist/admin/{PurchaseSingleSignOn-0wXAjOLm.js.map → PurchaseSingleSignOn-ovEsG_Ud.js.map} +1 -1
- package/dist/admin/{SelectRoles-h_1srnVz.mjs → SelectRoles-Kzqv2-TI.mjs} +6 -6
- package/dist/admin/SelectRoles-Kzqv2-TI.mjs.map +1 -0
- package/dist/admin/{SelectRoles-MoDtdDcM.js → SelectRoles-pjJ11lBU.js} +7 -7
- package/dist/admin/SelectRoles-pjJ11lBU.js.map +1 -0
- package/dist/admin/{SingleSignOnPage-5CdOsumW.js → SingleSignOnPage-WjL8NvC5.js} +4 -4
- package/dist/admin/{SingleSignOnPage-5CdOsumW.js.map → SingleSignOnPage-WjL8NvC5.js.map} +1 -1
- package/dist/admin/{SingleSignOnPage-AZVczKwR.mjs → SingleSignOnPage-p1fTOytT.mjs} +5 -5
- package/dist/admin/{SingleSignOnPage-AZVczKwR.mjs.map → SingleSignOnPage-p1fTOytT.mjs.map} +1 -1
- package/dist/admin/{Table-EPKfcF5-.mjs → Table-ARSVxoYe.mjs} +12 -19
- package/dist/admin/Table-ARSVxoYe.mjs.map +1 -0
- package/dist/admin/{Table-CpbvaRQh.js → Table-QAvKSSis.js} +12 -19
- package/dist/admin/Table-QAvKSSis.js.map +1 -0
- package/dist/admin/{Theme-PrUuuGtN.mjs → Theme-frC82ceE.mjs} +221 -20
- package/dist/admin/Theme-frC82ceE.mjs.map +1 -0
- package/dist/admin/{Theme-7W0we6BI.js → Theme-y_rWTknM.js} +225 -19
- package/dist/admin/Theme-y_rWTknM.js.map +1 -0
- package/dist/admin/{TokenTypeSelect-yRV19q7R.js → TokenTypeSelect-biZzRJv2.js} +4 -5
- package/dist/admin/{TokenTypeSelect-yRV19q7R.js.map → TokenTypeSelect-biZzRJv2.js.map} +1 -1
- package/dist/admin/{TokenTypeSelect-7Ki5z_3z.mjs → TokenTypeSelect-j-b_9iB9.mjs} +4 -5
- package/dist/admin/{TokenTypeSelect-7Ki5z_3z.mjs.map → TokenTypeSelect-j-b_9iB9.mjs.map} +1 -1
- package/dist/admin/{UseCasePage-as6-3qKD.mjs → UseCasePage-b2VozaZB.mjs} +4 -4
- package/dist/admin/{UseCasePage-as6-3qKD.mjs.map → UseCasePage-b2VozaZB.mjs.map} +1 -1
- package/dist/admin/{UseCasePage-l9OmQYhK.js → UseCasePage-hJH0orUl.js} +4 -4
- package/dist/admin/{UseCasePage-l9OmQYhK.js.map → UseCasePage-hJH0orUl.js.map} +1 -1
- package/dist/admin/{admin-B6AW0Kov.mjs → admin-GZ-AP2T0.mjs} +2 -2
- package/dist/admin/{admin-B6AW0Kov.mjs.map → admin-GZ-AP2T0.mjs.map} +1 -1
- package/dist/admin/{apiTokens-YMUmHnrH.mjs → apiTokens-GQe-GqwZ.mjs} +2 -2
- package/dist/admin/{apiTokens-YMUmHnrH.mjs.map → apiTokens-GQe-GqwZ.mjs.map} +1 -1
- package/dist/admin/{constants-X2uDAtEA.js → constants-bgMqSKBQ.js} +3 -3
- package/dist/admin/{constants-X2uDAtEA.js.map → constants-bgMqSKBQ.js.map} +1 -1
- package/dist/admin/{constants-AYR471DB.mjs → constants-jKuNcrQj.mjs} +3 -3
- package/dist/admin/{constants-AYR471DB.mjs.map → constants-jKuNcrQj.mjs.map} +1 -1
- package/dist/admin/ee.mjs +1 -1
- package/dist/admin/{en-TbnMBjZf.js → en-_1-Nn7iH.js} +3 -2
- package/dist/admin/{en-TbnMBjZf.js.map → en-_1-Nn7iH.js.map} +1 -1
- package/dist/admin/{en-0Ld-ipyI.mjs → en-lDO5lPD0.mjs} +3 -2
- package/dist/admin/{en-0Ld-ipyI.mjs.map → en-lDO5lPD0.mjs.map} +1 -1
- package/dist/admin/{index-Fu3hPmaj.mjs → index-hoTsgrwy.mjs} +136 -279
- package/dist/admin/index-hoTsgrwy.mjs.map +1 -0
- package/dist/admin/{index-w33_0vI-.js → index-we0DbzVF.js} +140 -286
- package/dist/admin/index-we0DbzVF.js.map +1 -0
- package/dist/admin/index.js +5 -4
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +3 -3
- package/dist/admin/{selectors-ZpHhvPK4.mjs → selectors--muHmKGe.mjs} +2 -2
- package/dist/admin/{selectors-ZpHhvPK4.mjs.map → selectors--muHmKGe.mjs.map} +1 -1
- package/dist/admin/{selectors-zQKcCNuz.js → selectors-1ySxKbos.js} +2 -2
- package/dist/admin/{selectors-zQKcCNuz.js.map → selectors-1ySxKbos.js.map} +1 -1
- package/dist/admin/src/StrapiApp.d.ts +8 -6
- package/dist/admin/src/components/Form.d.ts +3 -1
- package/dist/admin/src/components/GuidedTour/Provider.d.ts +0 -4
- package/dist/admin/src/constants.d.ts +10 -0
- package/dist/admin/src/features/Auth.d.ts +1 -1
- package/dist/admin/src/hooks/useRBAC.d.ts +1 -1
- package/dist/admin/src/index.d.ts +3 -0
- package/dist/admin/src/layouts/UnauthenticatedLayout.d.ts +1 -1
- package/dist/admin/src/pages/Marketplace/hooks/useMarketplaceData.d.ts +2 -1
- package/dist/admin/src/pages/Settings/pages/InstalledPlugins.d.ts +3 -0
- package/dist/admin/src/pages/Settings/pages/Roles/components/CollapseLabel.d.ts +1 -1
- package/dist/admin/src/types/permissions.d.ts +3 -1
- package/dist/admin/test.js +3 -3
- package/dist/admin/test.js.map +1 -1
- package/dist/admin/test.mjs +4 -4
- package/dist/admin/test.mjs.map +1 -1
- package/dist/admin/{transferTokens-CNI0TFdA.mjs → transferTokens-v8tNpI_l.mjs} +2 -2
- package/dist/admin/{transferTokens-CNI0TFdA.mjs.map → transferTokens-v8tNpI_l.mjs.map} +1 -1
- package/dist/admin/{useAdminRoles-w6h8NFK5.js → useAdminRoles-0gM7o3f2.js} +2 -2
- package/dist/admin/{useAdminRoles-w6h8NFK5.js.map → useAdminRoles-0gM7o3f2.js.map} +1 -1
- package/dist/admin/{useAdminRoles-lDesL4gN.mjs → useAdminRoles-uRNvxyDX.mjs} +2 -2
- package/dist/admin/{useAdminRoles-lDesL4gN.mjs.map → useAdminRoles-uRNvxyDX.mjs.map} +1 -1
- package/dist/admin/{useLicenseLimitNotification-PaR7jmqd.mjs → useLicenseLimitNotification-Qx_rSpUQ.mjs} +3 -3
- package/dist/admin/{useLicenseLimitNotification-PaR7jmqd.mjs.map → useLicenseLimitNotification-Qx_rSpUQ.mjs.map} +1 -1
- package/dist/admin/{useLicenseLimitNotification-g1vq6nzk.js → useLicenseLimitNotification-eau4ja6h.js} +2 -2
- package/dist/admin/{useLicenseLimitNotification-g1vq6nzk.js.map → useLicenseLimitNotification-eau4ja6h.js.map} +1 -1
- package/dist/admin/{useLicenseLimits-Jy6E6qc2.mjs → useLicenseLimits-j5znikzW.mjs} +2 -2
- package/dist/admin/{useLicenseLimits-Jy6E6qc2.mjs.map → useLicenseLimits-j5znikzW.mjs.map} +1 -1
- package/dist/admin/{useWebhooks-7thg-d57.mjs → useWebhooks-upF7mgdZ.mjs} +2 -2
- package/dist/admin/{useWebhooks-7thg-d57.mjs.map → useWebhooks-upF7mgdZ.mjs.map} +1 -1
- package/dist/admin/{validation-IcNGA_ef.mjs → validation-OR7t0a-C.mjs} +4 -4
- package/dist/admin/validation-OR7t0a-C.mjs.map +1 -0
- package/dist/admin/{validation-4SWh9S5z.js → validation-VuxEFW4W.js} +4 -4
- package/dist/admin/validation-VuxEFW4W.js.map +1 -0
- package/dist/ee/server/src/audit-logs/content-types/audit-log.d.ts +41 -0
- package/dist/ee/server/src/audit-logs/content-types/audit-log.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/controllers/audit-logs.d.ts +7 -0
- package/dist/ee/server/src/audit-logs/controllers/audit-logs.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/routes/audit-logs.d.ts +19 -0
- package/dist/ee/server/src/audit-logs/routes/audit-logs.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/services/audit-logs.d.ts +27 -0
- package/dist/ee/server/src/audit-logs/services/audit-logs.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts +12 -0
- package/dist/ee/server/src/audit-logs/services/lifecycles.d.ts.map +1 -0
- package/dist/ee/server/src/audit-logs/validation/audit-logs.d.ts +6 -0
- package/dist/ee/server/src/audit-logs/validation/audit-logs.d.ts.map +1 -0
- package/dist/ee/server/src/bootstrap.d.ts +3 -0
- package/dist/ee/server/src/bootstrap.d.ts.map +1 -0
- package/dist/ee/server/src/config/admin-actions.d.ts +20 -0
- package/dist/ee/server/src/config/admin-actions.d.ts.map +1 -0
- package/dist/ee/server/src/content-types/index.d.ts +3 -0
- package/dist/ee/server/src/content-types/index.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/admin.d.ts +29 -0
- package/dist/ee/server/src/controllers/admin.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/authentication-utils/constants.d.ts +10 -0
- package/dist/ee/server/src/controllers/authentication-utils/constants.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/authentication-utils/index.d.ts +5 -0
- package/dist/ee/server/src/controllers/authentication-utils/index.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts +9 -0
- package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/authentication-utils/utils.d.ts +55 -0
- package/dist/ee/server/src/controllers/authentication-utils/utils.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/authentication.d.ts +9 -0
- package/dist/ee/server/src/controllers/authentication.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/index.d.ts +48 -0
- package/dist/ee/server/src/controllers/index.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/role.d.ts +20 -0
- package/dist/ee/server/src/controllers/role.d.ts.map +1 -0
- package/dist/ee/server/src/controllers/user.d.ts +8 -0
- package/dist/ee/server/src/controllers/user.d.ts.map +1 -0
- package/dist/ee/server/src/destroy.d.ts +6 -0
- package/dist/ee/server/src/destroy.d.ts.map +1 -0
- package/dist/ee/server/src/index.d.ts +380 -0
- package/dist/ee/server/src/index.d.ts.map +1 -0
- package/dist/ee/server/src/register.d.ts +6 -0
- package/dist/ee/server/src/register.d.ts.map +1 -0
- package/dist/ee/server/src/routes/index.d.ts +47 -0
- package/dist/ee/server/src/routes/index.d.ts.map +1 -0
- package/dist/ee/server/src/routes/license-limit.d.ts +18 -0
- package/dist/ee/server/src/routes/license-limit.d.ts.map +1 -0
- package/dist/ee/server/src/routes/sso.d.ts +29 -0
- package/dist/ee/server/src/routes/sso.d.ts.map +1 -0
- package/dist/ee/server/src/routes/utils.d.ts +3 -0
- package/dist/ee/server/src/routes/utils.d.ts.map +1 -0
- package/dist/ee/server/src/services/auth.d.ts +6 -0
- package/dist/ee/server/src/services/auth.d.ts.map +1 -0
- package/dist/ee/server/src/services/index.d.ts +39 -0
- package/dist/ee/server/src/services/index.d.ts.map +1 -0
- package/dist/ee/server/src/services/metrics.d.ts +8 -0
- package/dist/ee/server/src/services/metrics.d.ts.map +1 -0
- package/dist/ee/server/src/services/passport/provider-registry.d.ts +4 -0
- package/dist/ee/server/src/services/passport/provider-registry.d.ts.map +1 -0
- package/dist/ee/server/src/services/passport/sso.d.ts +19 -0
- package/dist/ee/server/src/services/passport/sso.d.ts.map +1 -0
- package/dist/ee/server/src/services/passport.d.ts +13 -0
- package/dist/ee/server/src/services/passport.d.ts.map +1 -0
- package/dist/ee/server/src/services/role.d.ts +5 -0
- package/dist/ee/server/src/services/role.d.ts.map +1 -0
- package/dist/ee/server/src/services/seat-enforcement.d.ts +6 -0
- package/dist/ee/server/src/services/seat-enforcement.d.ts.map +1 -0
- package/dist/ee/server/src/services/user.d.ts +10 -0
- package/dist/ee/server/src/services/user.d.ts.map +1 -0
- package/dist/ee/server/src/utils/index.d.ts +11 -0
- package/dist/ee/server/src/utils/index.d.ts.map +1 -0
- package/dist/ee/server/src/utils/persisted-tables.d.ts +42 -0
- package/dist/ee/server/src/utils/persisted-tables.d.ts.map +1 -0
- package/dist/ee/server/src/utils/sso-lock.d.ts +6 -0
- package/dist/ee/server/src/utils/sso-lock.d.ts.map +1 -0
- package/dist/ee/server/src/validation/authentication.d.ts +15 -0
- package/dist/ee/server/src/validation/authentication.d.ts.map +1 -0
- package/dist/ee/server/src/validation/role.d.ts +21 -0
- package/dist/ee/server/src/validation/role.d.ts.map +1 -0
- package/dist/ee/server/src/validation/user.d.ts +19 -0
- package/dist/ee/server/src/validation/user.d.ts.map +1 -0
- package/dist/package.json.d.ts +10 -9
- package/dist/server/index.js +1891 -538
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +1687 -333
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/src/domain/action/provider.d.ts +1 -1
- package/dist/server/src/domain/condition/provider.d.ts +3 -1
- package/dist/server/src/domain/condition/provider.d.ts.map +1 -1
- package/dist/server/src/index.d.ts +738 -10
- package/dist/server/src/index.d.ts.map +1 -1
- package/dist/server/src/services/permission.d.ts +4 -2
- package/dist/server/src/services/permission.d.ts.map +1 -1
- package/dist/shared/contracts/admin.d.ts +1 -0
- package/dist/shared/contracts/admin.d.ts.map +1 -1
- package/dist/shared/contracts/user.d.ts +1 -1
- package/dist/shared/contracts/user.d.ts.map +1 -1
- package/package.json +17 -16
- package/dist/admin/AuthenticatedLayout-06fn7qrH.mjs.map +0 -1
- package/dist/admin/AuthenticatedLayout-eKDwvUFO.js.map +0 -1
- package/dist/admin/ContentBox-3MRTNw0X.js +0 -43
- package/dist/admin/ContentBox-3MRTNw0X.js.map +0 -1
- package/dist/admin/ContentBox-9LBDzws0.mjs +0 -41
- package/dist/admin/ContentBox-9LBDzws0.mjs.map +0 -1
- package/dist/admin/CreatePage-bdWb1wg4.mjs.map +0 -1
- package/dist/admin/CreatePage-t5HQUOqJ.js.map +0 -1
- package/dist/admin/EditPage-A7-BewPd.mjs.map +0 -1
- package/dist/admin/EditPage-Lw36XG9G.js.map +0 -1
- package/dist/admin/EditPage-cWJ8V1BK.mjs.map +0 -1
- package/dist/admin/EditPage-pTQCDncU.js.map +0 -1
- package/dist/admin/EditView-HygMdUSf.mjs.map +0 -1
- package/dist/admin/EditView-KzdDTSO-.js.map +0 -1
- package/dist/admin/HomePage-dyDldozB.mjs.map +0 -1
- package/dist/admin/HomePage-ywYHZHMa.js.map +0 -1
- package/dist/admin/InstalledPluginsPage-3OSkplVn.mjs.map +0 -1
- package/dist/admin/InstalledPluginsPage-JkruwT2d.js.map +0 -1
- package/dist/admin/ListPage-DHUp0PDw.js.map +0 -1
- package/dist/admin/ListPage-hNIbvh17.mjs.map +0 -1
- package/dist/admin/MarketplacePage-41CstG0b.mjs.map +0 -1
- package/dist/admin/MarketplacePage-uyOTT12t.js.map +0 -1
- package/dist/admin/ProfilePage-wxZFen3W.js.map +0 -1
- package/dist/admin/ProfilePage-zwG0fq_e.mjs.map +0 -1
- package/dist/admin/SelectRoles-MoDtdDcM.js.map +0 -1
- package/dist/admin/SelectRoles-h_1srnVz.mjs.map +0 -1
- package/dist/admin/Table-CpbvaRQh.js.map +0 -1
- package/dist/admin/Table-EPKfcF5-.mjs.map +0 -1
- package/dist/admin/Theme-7W0we6BI.js.map +0 -1
- package/dist/admin/Theme-PrUuuGtN.mjs.map +0 -1
- package/dist/admin/index-Fu3hPmaj.mjs.map +0 -1
- package/dist/admin/index-w33_0vI-.js.map +0 -1
- package/dist/admin/src/pages/InstalledPluginsPage.d.ts +0 -3
- package/dist/admin/validation-4SWh9S5z.js.map +0 -1
- package/dist/admin/validation-IcNGA_ef.mjs.map +0 -1
- package/dist/ee/server/index.js +0 -2193
- package/dist/ee/server/index.js.map +0 -1
- package/dist/ee/server/index.mjs +0 -2188
- package/dist/ee/server/index.mjs.map +0 -1
- package/strapi-server.js +0 -18
package/dist/ee/server/index.mjs
DELETED
|
@@ -1,2188 +0,0 @@
|
|
|
1
|
-
import { resolve, basename, join, extname } from "path";
|
|
2
|
-
import fse from "fs-extra";
|
|
3
|
-
import koaStatic from "koa-static";
|
|
4
|
-
import { isNil, castArray, merge, map, uniq, difference, differenceWith, isEqual, isEmpty, toLower, isFunction, toString, pipe, toNumber, assign, reverse, take, prop, drop, pick, mapValues, curry, includes, isArray, set, omit, has, isUndefined } from "lodash/fp";
|
|
5
|
-
import { differenceInHours, parseISO } from "date-fns";
|
|
6
|
-
import { errors, async, arrays, yup, validateYupSchema, env } from "@strapi/utils";
|
|
7
|
-
import "@strapi/types";
|
|
8
|
-
import _ from "lodash";
|
|
9
|
-
import { Strategy } from "passport-local";
|
|
10
|
-
import passport$2 from "koa-passport";
|
|
11
|
-
import compose from "koa-compose";
|
|
12
|
-
import { scheduleJob } from "node-schedule";
|
|
13
|
-
const registerAdminPanelRoute = ({ strapi: strapi2 }) => {
|
|
14
|
-
let buildDir = resolve(strapi2.dirs.dist.root, "build");
|
|
15
|
-
if (!fse.pathExistsSync(buildDir)) {
|
|
16
|
-
buildDir = resolve(__dirname, "../../build");
|
|
17
|
-
}
|
|
18
|
-
const serveAdminMiddleware = async (ctx, next) => {
|
|
19
|
-
await next();
|
|
20
|
-
if (ctx.method !== "HEAD" && ctx.method !== "GET") {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
if (ctx.body != null || ctx.status !== 404) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
ctx.type = "html";
|
|
27
|
-
ctx.body = fse.createReadStream(join(buildDir, "index.html"));
|
|
28
|
-
};
|
|
29
|
-
strapi2.server.routes([
|
|
30
|
-
{
|
|
31
|
-
method: "GET",
|
|
32
|
-
path: `${strapi2.config.admin.path}/:path*`,
|
|
33
|
-
handler: [
|
|
34
|
-
serveAdminMiddleware,
|
|
35
|
-
serveStatic(buildDir, {
|
|
36
|
-
maxage: 31536e3,
|
|
37
|
-
defer: false,
|
|
38
|
-
index: "index.html",
|
|
39
|
-
setHeaders(res, path) {
|
|
40
|
-
const ext = extname(path);
|
|
41
|
-
if (ext !== ".html") {
|
|
42
|
-
res.setHeader("cache-control", "public, max-age=31536000, immutable");
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
],
|
|
47
|
-
config: { auth: false }
|
|
48
|
-
}
|
|
49
|
-
]);
|
|
50
|
-
};
|
|
51
|
-
const serveStatic = (filesDir, koaStaticOptions = {}) => {
|
|
52
|
-
const serve = koaStatic(filesDir, koaStaticOptions);
|
|
53
|
-
return async (ctx, next) => {
|
|
54
|
-
const prev = ctx.path;
|
|
55
|
-
const newPath = basename(ctx.path);
|
|
56
|
-
ctx.path = newPath;
|
|
57
|
-
await serve(ctx, async () => {
|
|
58
|
-
ctx.path = prev;
|
|
59
|
-
await next();
|
|
60
|
-
ctx.path = newPath;
|
|
61
|
-
});
|
|
62
|
-
ctx.path = prev;
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
|
-
const getService$1 = (name2) => {
|
|
66
|
-
return strapi.service(`admin::${name2}`);
|
|
67
|
-
};
|
|
68
|
-
const authenticate$2 = async (ctx) => {
|
|
69
|
-
const { authorization } = ctx.request.header;
|
|
70
|
-
if (!authorization) {
|
|
71
|
-
return { authenticated: false };
|
|
72
|
-
}
|
|
73
|
-
const parts = authorization.split(/\s+/);
|
|
74
|
-
if (parts[0].toLowerCase() !== "bearer" || parts.length !== 2) {
|
|
75
|
-
return { authenticated: false };
|
|
76
|
-
}
|
|
77
|
-
const token = parts[1];
|
|
78
|
-
const { payload, isValid } = getService$1("token").decodeJwtToken(token);
|
|
79
|
-
if (!isValid) {
|
|
80
|
-
return { authenticated: false };
|
|
81
|
-
}
|
|
82
|
-
const user2 = await strapi.db.query("admin::user").findOne({ where: { id: payload.id }, populate: ["roles"] });
|
|
83
|
-
if (!user2 || !(user2.isActive === true)) {
|
|
84
|
-
return { authenticated: false };
|
|
85
|
-
}
|
|
86
|
-
const userAbility = await getService$1("permission").engine.generateUserAbility(user2);
|
|
87
|
-
ctx.state.userAbility = userAbility;
|
|
88
|
-
ctx.state.user = user2;
|
|
89
|
-
return {
|
|
90
|
-
authenticated: true,
|
|
91
|
-
credentials: user2,
|
|
92
|
-
ability: userAbility
|
|
93
|
-
};
|
|
94
|
-
};
|
|
95
|
-
const name = "admin";
|
|
96
|
-
const adminAuthStrategy = {
|
|
97
|
-
name,
|
|
98
|
-
authenticate: authenticate$2
|
|
99
|
-
};
|
|
100
|
-
const DAY_IN_MS = 24 * 60 * 60 * 1e3;
|
|
101
|
-
const constants = {
|
|
102
|
-
CONTENT_TYPE_SECTION: "contentTypes",
|
|
103
|
-
SUPER_ADMIN_CODE: "strapi-super-admin",
|
|
104
|
-
EDITOR_CODE: "strapi-editor",
|
|
105
|
-
AUTHOR_CODE: "strapi-author",
|
|
106
|
-
READ_ACTION: "plugin::content-manager.explorer.read",
|
|
107
|
-
CREATE_ACTION: "plugin::content-manager.explorer.create",
|
|
108
|
-
UPDATE_ACTION: "plugin::content-manager.explorer.update",
|
|
109
|
-
DELETE_ACTION: "plugin::content-manager.explorer.delete",
|
|
110
|
-
PUBLISH_ACTION: "plugin::content-manager.explorer.publish",
|
|
111
|
-
API_TOKEN_TYPE: {
|
|
112
|
-
READ_ONLY: "read-only",
|
|
113
|
-
FULL_ACCESS: "full-access",
|
|
114
|
-
CUSTOM: "custom"
|
|
115
|
-
},
|
|
116
|
-
// The front-end only displays these values
|
|
117
|
-
API_TOKEN_LIFESPANS: {
|
|
118
|
-
UNLIMITED: null,
|
|
119
|
-
DAYS_7: 7 * DAY_IN_MS,
|
|
120
|
-
DAYS_30: 30 * DAY_IN_MS,
|
|
121
|
-
DAYS_90: 90 * DAY_IN_MS
|
|
122
|
-
},
|
|
123
|
-
TRANSFER_TOKEN_TYPE: {
|
|
124
|
-
PUSH: "push",
|
|
125
|
-
PULL: "pull"
|
|
126
|
-
},
|
|
127
|
-
TRANSFER_TOKEN_LIFESPANS: {
|
|
128
|
-
UNLIMITED: null,
|
|
129
|
-
DAYS_7: 7 * DAY_IN_MS,
|
|
130
|
-
DAYS_30: 30 * DAY_IN_MS,
|
|
131
|
-
DAYS_90: 90 * DAY_IN_MS
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
const { UnauthorizedError: UnauthorizedError$1, ForbiddenError: ForbiddenError$1 } = errors;
|
|
135
|
-
const isReadScope = (scope) => scope.endsWith("find") || scope.endsWith("findOne");
|
|
136
|
-
const extractToken = (ctx) => {
|
|
137
|
-
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
|
|
138
|
-
const parts = ctx.request.header.authorization.split(/\s+/);
|
|
139
|
-
if (parts[0].toLowerCase() !== "bearer" || parts.length !== 2) {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
return parts[1];
|
|
143
|
-
}
|
|
144
|
-
return null;
|
|
145
|
-
};
|
|
146
|
-
const authenticate$1 = async (ctx) => {
|
|
147
|
-
const apiTokenService = getService$1("api-token");
|
|
148
|
-
const token = extractToken(ctx);
|
|
149
|
-
if (!token) {
|
|
150
|
-
return { authenticated: false };
|
|
151
|
-
}
|
|
152
|
-
const apiToken = await apiTokenService.getBy({
|
|
153
|
-
accessKey: apiTokenService.hash(token)
|
|
154
|
-
});
|
|
155
|
-
if (!apiToken) {
|
|
156
|
-
return { authenticated: false };
|
|
157
|
-
}
|
|
158
|
-
const currentDate = /* @__PURE__ */ new Date();
|
|
159
|
-
if (!isNil(apiToken.expiresAt)) {
|
|
160
|
-
const expirationDate = new Date(apiToken.expiresAt);
|
|
161
|
-
if (expirationDate < currentDate) {
|
|
162
|
-
return { authenticated: false, error: new UnauthorizedError$1("Token expired") };
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
const hoursSinceLastUsed = differenceInHours(currentDate, parseISO(apiToken.lastUsedAt));
|
|
166
|
-
if (hoursSinceLastUsed >= 1) {
|
|
167
|
-
await strapi.db.query("admin::api-token").update({
|
|
168
|
-
where: { id: apiToken.id },
|
|
169
|
-
data: { lastUsedAt: currentDate }
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
if (apiToken.type === constants.API_TOKEN_TYPE.CUSTOM) {
|
|
173
|
-
const ability = await strapi.contentAPI.permissions.engine.generateAbility(
|
|
174
|
-
apiToken.permissions.map((action) => ({ action }))
|
|
175
|
-
);
|
|
176
|
-
return { authenticated: true, ability, credentials: apiToken };
|
|
177
|
-
}
|
|
178
|
-
return { authenticated: true, credentials: apiToken };
|
|
179
|
-
};
|
|
180
|
-
const verify = (auth2, config) => {
|
|
181
|
-
const { credentials: apiToken, ability } = auth2;
|
|
182
|
-
if (!apiToken) {
|
|
183
|
-
throw new UnauthorizedError$1("Token not found");
|
|
184
|
-
}
|
|
185
|
-
const currentDate = /* @__PURE__ */ new Date();
|
|
186
|
-
if (!isNil(apiToken.expiresAt)) {
|
|
187
|
-
const expirationDate = new Date(apiToken.expiresAt);
|
|
188
|
-
if (expirationDate < currentDate) {
|
|
189
|
-
throw new UnauthorizedError$1("Token expired");
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
if (apiToken.type === constants.API_TOKEN_TYPE.FULL_ACCESS) {
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
if (apiToken.type === constants.API_TOKEN_TYPE.READ_ONLY) {
|
|
196
|
-
const scopes = castArray(config.scope);
|
|
197
|
-
if (config.scope && scopes.every(isReadScope)) {
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
} else if (apiToken.type === constants.API_TOKEN_TYPE.CUSTOM) {
|
|
201
|
-
if (!ability) {
|
|
202
|
-
throw new ForbiddenError$1();
|
|
203
|
-
}
|
|
204
|
-
const scopes = castArray(config.scope);
|
|
205
|
-
const isAllowed = scopes.every((scope) => ability.can(scope));
|
|
206
|
-
if (isAllowed) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
throw new ForbiddenError$1();
|
|
211
|
-
};
|
|
212
|
-
const apiTokenAuthStrategy = {
|
|
213
|
-
name: "api-token",
|
|
214
|
-
authenticate: authenticate$1,
|
|
215
|
-
verify
|
|
216
|
-
};
|
|
217
|
-
const executeCERegister = ({ strapi: strapi2 }) => {
|
|
218
|
-
const passportMiddleware = strapi2.service("admin::passport").init();
|
|
219
|
-
strapi2.server.api("admin").use(passportMiddleware);
|
|
220
|
-
strapi2.get("auth").register("admin", adminAuthStrategy);
|
|
221
|
-
strapi2.get("auth").register("content-api", apiTokenAuthStrategy);
|
|
222
|
-
if (strapi2.config.get("admin.serveAdminPanel")) {
|
|
223
|
-
registerAdminPanelRoute({ strapi: strapi2 });
|
|
224
|
-
}
|
|
225
|
-
};
|
|
226
|
-
const register = async ({ strapi: strapi2 }) => {
|
|
227
|
-
await executeCERegister({ strapi: strapi2 });
|
|
228
|
-
};
|
|
229
|
-
const actions$1 = [
|
|
230
|
-
{
|
|
231
|
-
uid: "marketplace.read",
|
|
232
|
-
displayName: "Access the marketplace",
|
|
233
|
-
pluginName: "admin",
|
|
234
|
-
section: "settings",
|
|
235
|
-
category: "plugins and marketplace",
|
|
236
|
-
subCategory: "marketplace"
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
uid: "webhooks.create",
|
|
240
|
-
displayName: "Create",
|
|
241
|
-
pluginName: "admin",
|
|
242
|
-
section: "settings",
|
|
243
|
-
category: "webhooks"
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
uid: "webhooks.read",
|
|
247
|
-
displayName: "Read",
|
|
248
|
-
pluginName: "admin",
|
|
249
|
-
section: "settings",
|
|
250
|
-
category: "webhooks"
|
|
251
|
-
},
|
|
252
|
-
{
|
|
253
|
-
uid: "webhooks.update",
|
|
254
|
-
displayName: "Update",
|
|
255
|
-
pluginName: "admin",
|
|
256
|
-
section: "settings",
|
|
257
|
-
category: "webhooks"
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
uid: "webhooks.delete",
|
|
261
|
-
displayName: "Delete",
|
|
262
|
-
pluginName: "admin",
|
|
263
|
-
section: "settings",
|
|
264
|
-
category: "webhooks"
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
uid: "users.create",
|
|
268
|
-
displayName: "Create (invite)",
|
|
269
|
-
pluginName: "admin",
|
|
270
|
-
section: "settings",
|
|
271
|
-
category: "users and roles",
|
|
272
|
-
subCategory: "users"
|
|
273
|
-
},
|
|
274
|
-
{
|
|
275
|
-
uid: "users.read",
|
|
276
|
-
displayName: "Read",
|
|
277
|
-
pluginName: "admin",
|
|
278
|
-
section: "settings",
|
|
279
|
-
category: "users and roles",
|
|
280
|
-
subCategory: "users",
|
|
281
|
-
aliases: [
|
|
282
|
-
{
|
|
283
|
-
actionId: "plugin::content-manager.explorer.read",
|
|
284
|
-
subjects: ["admin::user"]
|
|
285
|
-
}
|
|
286
|
-
]
|
|
287
|
-
},
|
|
288
|
-
{
|
|
289
|
-
uid: "users.update",
|
|
290
|
-
displayName: "Update",
|
|
291
|
-
pluginName: "admin",
|
|
292
|
-
section: "settings",
|
|
293
|
-
category: "users and roles",
|
|
294
|
-
subCategory: "users"
|
|
295
|
-
},
|
|
296
|
-
{
|
|
297
|
-
uid: "users.delete",
|
|
298
|
-
displayName: "Delete",
|
|
299
|
-
pluginName: "admin",
|
|
300
|
-
section: "settings",
|
|
301
|
-
category: "users and roles",
|
|
302
|
-
subCategory: "users"
|
|
303
|
-
},
|
|
304
|
-
{
|
|
305
|
-
uid: "roles.create",
|
|
306
|
-
displayName: "Create",
|
|
307
|
-
pluginName: "admin",
|
|
308
|
-
section: "settings",
|
|
309
|
-
category: "users and roles",
|
|
310
|
-
subCategory: "roles"
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
uid: "roles.read",
|
|
314
|
-
displayName: "Read",
|
|
315
|
-
pluginName: "admin",
|
|
316
|
-
section: "settings",
|
|
317
|
-
category: "users and roles",
|
|
318
|
-
subCategory: "roles",
|
|
319
|
-
aliases: [
|
|
320
|
-
{
|
|
321
|
-
actionId: "plugin::content-manager.explorer.read",
|
|
322
|
-
subjects: ["admin::role"]
|
|
323
|
-
}
|
|
324
|
-
]
|
|
325
|
-
},
|
|
326
|
-
{
|
|
327
|
-
uid: "roles.update",
|
|
328
|
-
displayName: "Update",
|
|
329
|
-
pluginName: "admin",
|
|
330
|
-
section: "settings",
|
|
331
|
-
category: "users and roles",
|
|
332
|
-
subCategory: "roles"
|
|
333
|
-
},
|
|
334
|
-
{
|
|
335
|
-
uid: "roles.delete",
|
|
336
|
-
displayName: "Delete",
|
|
337
|
-
pluginName: "admin",
|
|
338
|
-
section: "settings",
|
|
339
|
-
category: "users and roles",
|
|
340
|
-
subCategory: "roles"
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
uid: "api-tokens.access",
|
|
344
|
-
displayName: "Access the API tokens settings page",
|
|
345
|
-
pluginName: "admin",
|
|
346
|
-
section: "settings",
|
|
347
|
-
category: "api tokens",
|
|
348
|
-
subCategory: "api Tokens"
|
|
349
|
-
},
|
|
350
|
-
{
|
|
351
|
-
uid: "api-tokens.create",
|
|
352
|
-
displayName: "Create (generate)",
|
|
353
|
-
pluginName: "admin",
|
|
354
|
-
section: "settings",
|
|
355
|
-
category: "api tokens",
|
|
356
|
-
subCategory: "general"
|
|
357
|
-
},
|
|
358
|
-
{
|
|
359
|
-
uid: "api-tokens.read",
|
|
360
|
-
displayName: "Read",
|
|
361
|
-
pluginName: "admin",
|
|
362
|
-
section: "settings",
|
|
363
|
-
category: "api tokens",
|
|
364
|
-
subCategory: "general"
|
|
365
|
-
},
|
|
366
|
-
{
|
|
367
|
-
uid: "api-tokens.update",
|
|
368
|
-
displayName: "Update",
|
|
369
|
-
pluginName: "admin",
|
|
370
|
-
section: "settings",
|
|
371
|
-
category: "api tokens",
|
|
372
|
-
subCategory: "general"
|
|
373
|
-
},
|
|
374
|
-
{
|
|
375
|
-
uid: "api-tokens.regenerate",
|
|
376
|
-
displayName: "Regenerate",
|
|
377
|
-
pluginName: "admin",
|
|
378
|
-
section: "settings",
|
|
379
|
-
category: "api tokens",
|
|
380
|
-
subCategory: "general"
|
|
381
|
-
},
|
|
382
|
-
{
|
|
383
|
-
uid: "api-tokens.delete",
|
|
384
|
-
displayName: "Delete (revoke)",
|
|
385
|
-
pluginName: "admin",
|
|
386
|
-
section: "settings",
|
|
387
|
-
category: "api tokens",
|
|
388
|
-
subCategory: "general"
|
|
389
|
-
},
|
|
390
|
-
{
|
|
391
|
-
uid: "project-settings.update",
|
|
392
|
-
displayName: "Update the project level settings",
|
|
393
|
-
pluginName: "admin",
|
|
394
|
-
section: "settings",
|
|
395
|
-
category: "project"
|
|
396
|
-
},
|
|
397
|
-
{
|
|
398
|
-
uid: "project-settings.read",
|
|
399
|
-
displayName: "Read the project level settings",
|
|
400
|
-
pluginName: "admin",
|
|
401
|
-
section: "settings",
|
|
402
|
-
category: "project"
|
|
403
|
-
},
|
|
404
|
-
{
|
|
405
|
-
uid: "transfer.tokens.access",
|
|
406
|
-
displayName: "Access the transfer tokens settings page",
|
|
407
|
-
pluginName: "admin",
|
|
408
|
-
section: "settings",
|
|
409
|
-
category: "transfer tokens",
|
|
410
|
-
subCategory: "transfer tokens"
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
uid: "transfer.tokens.create",
|
|
414
|
-
displayName: "Create (generate)",
|
|
415
|
-
pluginName: "admin",
|
|
416
|
-
section: "settings",
|
|
417
|
-
category: "transfer tokens",
|
|
418
|
-
subCategory: "general"
|
|
419
|
-
},
|
|
420
|
-
{
|
|
421
|
-
uid: "transfer.tokens.read",
|
|
422
|
-
displayName: "Read",
|
|
423
|
-
pluginName: "admin",
|
|
424
|
-
section: "settings",
|
|
425
|
-
category: "transfer tokens",
|
|
426
|
-
subCategory: "general"
|
|
427
|
-
},
|
|
428
|
-
{
|
|
429
|
-
uid: "transfer.tokens.update",
|
|
430
|
-
displayName: "Update",
|
|
431
|
-
pluginName: "admin",
|
|
432
|
-
section: "settings",
|
|
433
|
-
category: "transfer tokens",
|
|
434
|
-
subCategory: "general"
|
|
435
|
-
},
|
|
436
|
-
{
|
|
437
|
-
uid: "transfer.tokens.regenerate",
|
|
438
|
-
displayName: "Regenerate",
|
|
439
|
-
pluginName: "admin",
|
|
440
|
-
section: "settings",
|
|
441
|
-
category: "transfer tokens",
|
|
442
|
-
subCategory: "general"
|
|
443
|
-
},
|
|
444
|
-
{
|
|
445
|
-
uid: "transfer.tokens.delete",
|
|
446
|
-
displayName: "Delete (revoke)",
|
|
447
|
-
pluginName: "admin",
|
|
448
|
-
section: "settings",
|
|
449
|
-
category: "transfer tokens",
|
|
450
|
-
subCategory: "general"
|
|
451
|
-
}
|
|
452
|
-
];
|
|
453
|
-
const adminActions = {
|
|
454
|
-
actions: actions$1
|
|
455
|
-
};
|
|
456
|
-
const conditions = [
|
|
457
|
-
{
|
|
458
|
-
displayName: "Is creator",
|
|
459
|
-
name: "is-creator",
|
|
460
|
-
plugin: "admin",
|
|
461
|
-
handler: (user2) => ({ "createdBy.id": user2.id })
|
|
462
|
-
},
|
|
463
|
-
{
|
|
464
|
-
displayName: "Has same role as creator",
|
|
465
|
-
name: "has-same-role-as-creator",
|
|
466
|
-
plugin: "admin",
|
|
467
|
-
handler: (user2) => ({
|
|
468
|
-
"createdBy.roles": {
|
|
469
|
-
$elemMatch: {
|
|
470
|
-
id: {
|
|
471
|
-
$in: user2.roles.map((r) => r.id)
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
})
|
|
476
|
-
}
|
|
477
|
-
];
|
|
478
|
-
const adminConditions = {
|
|
479
|
-
conditions
|
|
480
|
-
};
|
|
481
|
-
const defaultAdminAuthSettings = {
|
|
482
|
-
providers: {
|
|
483
|
-
autoRegister: false,
|
|
484
|
-
defaultRole: null,
|
|
485
|
-
ssoLockedRoles: null
|
|
486
|
-
}
|
|
487
|
-
};
|
|
488
|
-
const registerPermissionActions = async () => {
|
|
489
|
-
await getService$1("permission").actionProvider.registerMany(adminActions.actions);
|
|
490
|
-
};
|
|
491
|
-
const registerAdminConditions = async () => {
|
|
492
|
-
await getService$1("permission").conditionProvider.registerMany(adminConditions.conditions);
|
|
493
|
-
};
|
|
494
|
-
const registerModelHooks = () => {
|
|
495
|
-
const { sendDidChangeInterfaceLanguage } = getService$1("metrics");
|
|
496
|
-
strapi.db.lifecycles.subscribe({
|
|
497
|
-
models: ["admin::user"],
|
|
498
|
-
afterCreate: sendDidChangeInterfaceLanguage,
|
|
499
|
-
afterDelete: sendDidChangeInterfaceLanguage,
|
|
500
|
-
afterUpdate({ params }) {
|
|
501
|
-
if (params.data.preferedLanguage) {
|
|
502
|
-
sendDidChangeInterfaceLanguage();
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
});
|
|
506
|
-
};
|
|
507
|
-
const syncAuthSettings = async () => {
|
|
508
|
-
const adminStore = await strapi.store({ type: "core", name: "admin" });
|
|
509
|
-
const adminAuthSettings = await adminStore.get({ key: "auth" });
|
|
510
|
-
const newAuthSettings = merge(defaultAdminAuthSettings, adminAuthSettings);
|
|
511
|
-
const roleExists = await getService$1("role").exists({
|
|
512
|
-
id: newAuthSettings.providers.defaultRole
|
|
513
|
-
});
|
|
514
|
-
if (!roleExists) {
|
|
515
|
-
newAuthSettings.providers.defaultRole = null;
|
|
516
|
-
}
|
|
517
|
-
await adminStore.set({ key: "auth", value: newAuthSettings });
|
|
518
|
-
};
|
|
519
|
-
const syncAPITokensPermissions = async () => {
|
|
520
|
-
const validPermissions = strapi.contentAPI.permissions.providers.action.keys();
|
|
521
|
-
const permissionsInDB = await async.pipe(
|
|
522
|
-
strapi.db.query("admin::api-token-permission").findMany,
|
|
523
|
-
map("action")
|
|
524
|
-
)();
|
|
525
|
-
const unknownPermissions = uniq(difference(permissionsInDB, validPermissions));
|
|
526
|
-
if (unknownPermissions.length > 0) {
|
|
527
|
-
await strapi.db.query("admin::api-token-permission").deleteMany({ where: { action: { $in: unknownPermissions } } });
|
|
528
|
-
}
|
|
529
|
-
};
|
|
530
|
-
const executeCEBootstrap = async ({ strapi: strapi2 }) => {
|
|
531
|
-
await registerAdminConditions();
|
|
532
|
-
await registerPermissionActions();
|
|
533
|
-
registerModelHooks();
|
|
534
|
-
const permissionService = getService$1("permission");
|
|
535
|
-
const userService = getService$1("user");
|
|
536
|
-
const roleService = getService$1("role");
|
|
537
|
-
const apiTokenService = getService$1("api-token");
|
|
538
|
-
const transferService = getService$1("transfer");
|
|
539
|
-
const tokenService = getService$1("token");
|
|
540
|
-
await roleService.createRolesIfNoneExist();
|
|
541
|
-
await roleService.resetSuperAdminPermissions();
|
|
542
|
-
await roleService.displayWarningIfNoSuperAdmin();
|
|
543
|
-
await permissionService.cleanPermissionsInDatabase();
|
|
544
|
-
await userService.displayWarningIfUsersDontHaveRole();
|
|
545
|
-
await syncAuthSettings();
|
|
546
|
-
await syncAPITokensPermissions();
|
|
547
|
-
await getService$1("metrics").sendUpdateProjectInformation(strapi2);
|
|
548
|
-
getService$1("metrics").startCron(strapi2);
|
|
549
|
-
apiTokenService.checkSaltIsDefined();
|
|
550
|
-
transferService.token.checkSaltIsDefined();
|
|
551
|
-
tokenService.checkSecretIsDefined();
|
|
552
|
-
};
|
|
553
|
-
const getService = (name2, { strapi: strapi2 } = { strapi: global.strapi }) => {
|
|
554
|
-
return strapi2.service(`admin::${name2}`);
|
|
555
|
-
};
|
|
556
|
-
const actions = {
|
|
557
|
-
sso: [
|
|
558
|
-
{
|
|
559
|
-
uid: "provider-login.read",
|
|
560
|
-
displayName: "Read",
|
|
561
|
-
pluginName: "admin",
|
|
562
|
-
section: "settings",
|
|
563
|
-
category: "single sign on",
|
|
564
|
-
subCategory: "options"
|
|
565
|
-
},
|
|
566
|
-
{
|
|
567
|
-
uid: "provider-login.update",
|
|
568
|
-
displayName: "Update",
|
|
569
|
-
pluginName: "admin",
|
|
570
|
-
section: "settings",
|
|
571
|
-
category: "single sign on",
|
|
572
|
-
subCategory: "options"
|
|
573
|
-
}
|
|
574
|
-
],
|
|
575
|
-
auditLogs: [
|
|
576
|
-
{
|
|
577
|
-
uid: "audit-logs.read",
|
|
578
|
-
displayName: "Read",
|
|
579
|
-
pluginName: "admin",
|
|
580
|
-
section: "settings",
|
|
581
|
-
category: "audit logs",
|
|
582
|
-
subCategory: "options"
|
|
583
|
-
}
|
|
584
|
-
]
|
|
585
|
-
};
|
|
586
|
-
const transformTableName = (table) => {
|
|
587
|
-
if (typeof table === "string") {
|
|
588
|
-
return { name: table };
|
|
589
|
-
}
|
|
590
|
-
return table;
|
|
591
|
-
};
|
|
592
|
-
async function findTables({ strapi: strapi2 }, regex) {
|
|
593
|
-
const tables = await strapi2.db.dialect.schemaInspector.getTables();
|
|
594
|
-
return tables.filter((tableName) => regex.test(tableName));
|
|
595
|
-
}
|
|
596
|
-
async function addPersistTables({ strapi: strapi2 }, tableNames) {
|
|
597
|
-
const persistedTables = await getPersistedTables({ strapi: strapi2 });
|
|
598
|
-
const tables = tableNames.map(transformTableName);
|
|
599
|
-
const notPersistedTableNames = differenceWith(isEqual, tables, persistedTables);
|
|
600
|
-
const tablesToPersist = differenceWith(
|
|
601
|
-
(t1, t2) => t1.name === t2.name,
|
|
602
|
-
persistedTables,
|
|
603
|
-
notPersistedTableNames
|
|
604
|
-
);
|
|
605
|
-
if (!notPersistedTableNames.length) {
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
608
|
-
tablesToPersist.push(...notPersistedTableNames);
|
|
609
|
-
await strapi2.store.set({
|
|
610
|
-
type: "core",
|
|
611
|
-
key: "persisted_tables",
|
|
612
|
-
value: tablesToPersist
|
|
613
|
-
});
|
|
614
|
-
}
|
|
615
|
-
async function getPersistedTables({ strapi: strapi2 }) {
|
|
616
|
-
const persistedTables = await strapi2.store.get({
|
|
617
|
-
type: "core",
|
|
618
|
-
key: "persisted_tables"
|
|
619
|
-
});
|
|
620
|
-
return (persistedTables || []).map(transformTableName);
|
|
621
|
-
}
|
|
622
|
-
const persistTablesWithPrefix = async (tableNamePrefix) => {
|
|
623
|
-
const tableNameRegex = new RegExp(`^${tableNamePrefix}.*`);
|
|
624
|
-
const tableNames = await findTables({ strapi }, tableNameRegex);
|
|
625
|
-
await addPersistTables({ strapi }, tableNames);
|
|
626
|
-
};
|
|
627
|
-
const bootstrap = async (args) => {
|
|
628
|
-
const { actionProvider } = getService("permission");
|
|
629
|
-
if (strapi.ee.features.isEnabled("sso")) {
|
|
630
|
-
await actionProvider.registerMany(actions.sso);
|
|
631
|
-
}
|
|
632
|
-
if (strapi.ee.features.isEnabled("audit-logs")) {
|
|
633
|
-
await persistTablesWithPrefix("strapi_audit_logs");
|
|
634
|
-
await actionProvider.registerMany(actions.auditLogs);
|
|
635
|
-
}
|
|
636
|
-
await getService("seat-enforcement").seatEnforcementWorkflow();
|
|
637
|
-
await executeCEBootstrap(args);
|
|
638
|
-
};
|
|
639
|
-
const executeCEDestroy = async () => {
|
|
640
|
-
const { conditionProvider, actionProvider } = getService$1("permission");
|
|
641
|
-
await conditionProvider.clear();
|
|
642
|
-
await actionProvider.clear();
|
|
643
|
-
};
|
|
644
|
-
const destroy = async ({ strapi: strapi2 }) => {
|
|
645
|
-
await executeCEDestroy();
|
|
646
|
-
};
|
|
647
|
-
const adminContentTypes = {};
|
|
648
|
-
const isSsoLocked = async (user2) => {
|
|
649
|
-
if (!strapi.ee.features.isEnabled("sso")) {
|
|
650
|
-
return false;
|
|
651
|
-
}
|
|
652
|
-
if (!user2) {
|
|
653
|
-
throw new Error("Missing user object");
|
|
654
|
-
}
|
|
655
|
-
const adminStore = await strapi.store({ type: "core", name: "admin" });
|
|
656
|
-
const { providers } = await adminStore.get({ key: "auth" });
|
|
657
|
-
const lockedRoles = providers.ssoLockedRoles ?? [];
|
|
658
|
-
if (isEmpty(lockedRoles)) {
|
|
659
|
-
return false;
|
|
660
|
-
}
|
|
661
|
-
const roles2 = (
|
|
662
|
-
// If the roles are pre-loaded for the given user, then use them
|
|
663
|
-
user2.roles ?? // Otherwise, try to load the role based on the given user ID
|
|
664
|
-
await strapi.db.query("admin::user").load(user2, "roles", { roles: { fields: ["id"] } }) ?? // If the query fails somehow, default to an empty array
|
|
665
|
-
[]
|
|
666
|
-
);
|
|
667
|
-
const isLocked = lockedRoles.some(
|
|
668
|
-
(lockedId) => (
|
|
669
|
-
// lockedRoles will be a string to avoid issues with frontend and bigints
|
|
670
|
-
roles2.some((role2) => lockedId === role2.id.toString())
|
|
671
|
-
)
|
|
672
|
-
);
|
|
673
|
-
return isLocked;
|
|
674
|
-
};
|
|
675
|
-
const { ApplicationError: ApplicationError$2 } = errors;
|
|
676
|
-
const forgotPassword = async ({ email: email2 } = {}) => {
|
|
677
|
-
const user2 = await strapi.db.query("admin::user").findOne({ where: { email: email2, isActive: true } });
|
|
678
|
-
if (!user2 || await isSsoLocked(user2)) {
|
|
679
|
-
return;
|
|
680
|
-
}
|
|
681
|
-
const resetPasswordToken = getService("token").createToken();
|
|
682
|
-
await getService("user").updateById(user2.id, { resetPasswordToken });
|
|
683
|
-
const url = `${strapi.config.get(
|
|
684
|
-
"admin.absoluteUrl"
|
|
685
|
-
)}/auth/reset-password?code=${resetPasswordToken}`;
|
|
686
|
-
return strapi.plugin("email").service("email").sendTemplatedEmail(
|
|
687
|
-
{
|
|
688
|
-
to: user2.email,
|
|
689
|
-
from: strapi.config.get("admin.forgotPassword.from"),
|
|
690
|
-
replyTo: strapi.config.get("admin.forgotPassword.replyTo")
|
|
691
|
-
},
|
|
692
|
-
strapi.config.get("admin.forgotPassword.emailTemplate"),
|
|
693
|
-
{
|
|
694
|
-
url,
|
|
695
|
-
user: _.pick(user2, ["email", "firstname", "lastname", "username"])
|
|
696
|
-
}
|
|
697
|
-
).catch((err) => {
|
|
698
|
-
strapi.log.error(err);
|
|
699
|
-
});
|
|
700
|
-
};
|
|
701
|
-
const resetPassword = async ({ resetPasswordToken, password: password2 } = {}) => {
|
|
702
|
-
const matchingUser = await strapi.db.query("admin::user").findOne({ where: { resetPasswordToken, isActive: true } });
|
|
703
|
-
if (!matchingUser || await isSsoLocked(matchingUser)) {
|
|
704
|
-
throw new ApplicationError$2();
|
|
705
|
-
}
|
|
706
|
-
return getService("user").updateById(matchingUser.id, {
|
|
707
|
-
password: password2,
|
|
708
|
-
resetPasswordToken: null
|
|
709
|
-
});
|
|
710
|
-
};
|
|
711
|
-
const auth = {
|
|
712
|
-
forgotPassword,
|
|
713
|
-
resetPassword
|
|
714
|
-
};
|
|
715
|
-
const createLocalStrategy = (strapi2, middleware) => {
|
|
716
|
-
return new Strategy(
|
|
717
|
-
{
|
|
718
|
-
usernameField: "email",
|
|
719
|
-
passwordField: "password",
|
|
720
|
-
session: false
|
|
721
|
-
},
|
|
722
|
-
(email2, password2, done) => {
|
|
723
|
-
return getService$1("auth").checkCredentials({ email: toLower(email2), password: password2 }).then(async ([error, user2, message]) => {
|
|
724
|
-
if (middleware) {
|
|
725
|
-
return middleware([error, user2, message], done);
|
|
726
|
-
}
|
|
727
|
-
return done(error, user2, message);
|
|
728
|
-
}).catch((error) => done(error));
|
|
729
|
-
}
|
|
730
|
-
);
|
|
731
|
-
};
|
|
732
|
-
const authEventsMapper = {
|
|
733
|
-
onConnectionSuccess: "admin.auth.success",
|
|
734
|
-
onConnectionError: "admin.auth.error"
|
|
735
|
-
};
|
|
736
|
-
const valueIsFunctionType = ([, value]) => isFunction(value);
|
|
737
|
-
const keyIsValidEventName = ([key]) => {
|
|
738
|
-
return Object.keys(strapi.service("admin::passport").authEventsMapper).includes(key);
|
|
739
|
-
};
|
|
740
|
-
const getPassportStrategies$1 = () => [createLocalStrategy(strapi)];
|
|
741
|
-
const registerAuthEvents = () => {
|
|
742
|
-
const { events = {} } = strapi.config.get("admin.auth", {});
|
|
743
|
-
const { authEventsMapper: authEventsMapper2 } = strapi.service("admin::passport");
|
|
744
|
-
const eventList = Object.entries(events).filter(keyIsValidEventName).filter(valueIsFunctionType);
|
|
745
|
-
for (const [eventName, handler] of eventList) {
|
|
746
|
-
strapi.eventHub.on(authEventsMapper2[eventName], handler);
|
|
747
|
-
}
|
|
748
|
-
};
|
|
749
|
-
const init = () => {
|
|
750
|
-
strapi.service("admin::passport").getPassportStrategies().forEach((strategy) => passport$2.use(strategy));
|
|
751
|
-
registerAuthEvents();
|
|
752
|
-
return passport$2.initialize();
|
|
753
|
-
};
|
|
754
|
-
const passport$1 = { init, getPassportStrategies: getPassportStrategies$1, authEventsMapper };
|
|
755
|
-
const createProviderRegistry = () => {
|
|
756
|
-
const registry = /* @__PURE__ */ new Map();
|
|
757
|
-
Object.assign(registry, {
|
|
758
|
-
register(provider) {
|
|
759
|
-
if (strapi.isLoaded) {
|
|
760
|
-
throw new Error(`You can't register new provider after the bootstrap`);
|
|
761
|
-
}
|
|
762
|
-
this.set(provider.uid, provider);
|
|
763
|
-
},
|
|
764
|
-
registerMany(providers) {
|
|
765
|
-
providers.forEach((provider) => {
|
|
766
|
-
this.register(provider);
|
|
767
|
-
});
|
|
768
|
-
},
|
|
769
|
-
getAll() {
|
|
770
|
-
return Array.from(this.values());
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
return registry;
|
|
774
|
-
};
|
|
775
|
-
const providerRegistry = createProviderRegistry();
|
|
776
|
-
const errorMessage = "SSO is disabled. Its functionnalities cannot be accessed.";
|
|
777
|
-
const getStrategyCallbackURL = (providerName) => {
|
|
778
|
-
if (!strapi.ee.features.isEnabled("sso")) {
|
|
779
|
-
throw new Error(errorMessage);
|
|
780
|
-
}
|
|
781
|
-
return `/admin/connect/${providerName}`;
|
|
782
|
-
};
|
|
783
|
-
const syncProviderRegistryWithConfig = () => {
|
|
784
|
-
if (!strapi.ee.features.isEnabled("sso")) {
|
|
785
|
-
throw new Error(errorMessage);
|
|
786
|
-
}
|
|
787
|
-
const { providers = [] } = strapi.config.get("admin.auth", {});
|
|
788
|
-
providerRegistry.registerMany(providers);
|
|
789
|
-
};
|
|
790
|
-
const SSOAuthEventsMapper = {
|
|
791
|
-
onSSOAutoRegistration: "admin.auth.autoRegistration"
|
|
792
|
-
};
|
|
793
|
-
const sso$1 = {
|
|
794
|
-
providerRegistry,
|
|
795
|
-
getStrategyCallbackURL,
|
|
796
|
-
syncProviderRegistryWithConfig,
|
|
797
|
-
authEventsMapper: { ...passport$1.authEventsMapper, ...SSOAuthEventsMapper }
|
|
798
|
-
};
|
|
799
|
-
const { UnauthorizedError } = errors;
|
|
800
|
-
const localStrategyMiddleware = async ([error, user2, message], done) => {
|
|
801
|
-
if (user2 && !error && await isSsoLocked(user2)) {
|
|
802
|
-
return done(
|
|
803
|
-
new UnauthorizedError("Login not allowed, please contact your administrator", {
|
|
804
|
-
code: "LOGIN_NOT_ALLOWED"
|
|
805
|
-
}),
|
|
806
|
-
user2,
|
|
807
|
-
message
|
|
808
|
-
);
|
|
809
|
-
}
|
|
810
|
-
return done(error, user2, message);
|
|
811
|
-
};
|
|
812
|
-
const getPassportStrategies = () => {
|
|
813
|
-
if (!strapi.ee.features.isEnabled("sso")) {
|
|
814
|
-
return [createLocalStrategy(strapi)];
|
|
815
|
-
}
|
|
816
|
-
const localStrategy = createLocalStrategy(strapi, localStrategyMiddleware);
|
|
817
|
-
if (!strapi.isLoaded) {
|
|
818
|
-
sso$1.syncProviderRegistryWithConfig();
|
|
819
|
-
}
|
|
820
|
-
const providers = sso$1.providerRegistry.getAll();
|
|
821
|
-
const strategies = providers.map((provider) => provider.createStrategy(strapi));
|
|
822
|
-
return [localStrategy, ...strategies];
|
|
823
|
-
};
|
|
824
|
-
const passport = {
|
|
825
|
-
getPassportStrategies,
|
|
826
|
-
...sso$1
|
|
827
|
-
};
|
|
828
|
-
const { ApplicationError: ApplicationError$1 } = errors;
|
|
829
|
-
const ssoCheckRolesIdForDeletion = async (ids) => {
|
|
830
|
-
const adminStore = await strapi.store({ type: "core", name: "admin" });
|
|
831
|
-
const {
|
|
832
|
-
providers: { defaultRole }
|
|
833
|
-
} = await adminStore.get({ key: "auth" });
|
|
834
|
-
for (const roleId of ids) {
|
|
835
|
-
if (defaultRole && toString(defaultRole) === toString(roleId)) {
|
|
836
|
-
throw new ApplicationError$1(
|
|
837
|
-
"This role is used as the default SSO role. Make sure to change this configuration before deleting the role"
|
|
838
|
-
);
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
};
|
|
842
|
-
const role$1 = {
|
|
843
|
-
ssoCheckRolesIdForDeletion
|
|
844
|
-
};
|
|
845
|
-
const { SUPER_ADMIN_CODE: SUPER_ADMIN_CODE$2 } = constants;
|
|
846
|
-
const hasSuperAdminRole = (user2) => {
|
|
847
|
-
return user2.roles.filter((role2) => role2.code === SUPER_ADMIN_CODE$2).length > 0;
|
|
848
|
-
};
|
|
849
|
-
const { ValidationError: ValidationError$1 } = errors;
|
|
850
|
-
const { SUPER_ADMIN_CODE: SUPER_ADMIN_CODE$1 } = constants;
|
|
851
|
-
const updateEEDisabledUsersList = async (id, input) => {
|
|
852
|
-
const disabledUsers = await getService("seat-enforcement").getDisabledUserList();
|
|
853
|
-
if (!disabledUsers) {
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
856
|
-
const user2 = disabledUsers.find((user22) => user22.id === Number(id));
|
|
857
|
-
if (!user2) {
|
|
858
|
-
return;
|
|
859
|
-
}
|
|
860
|
-
if (user2.isActive !== input.isActive) {
|
|
861
|
-
const newDisabledUsersList = disabledUsers.filter((user22) => user22.id !== Number(id));
|
|
862
|
-
await strapi.store.set({
|
|
863
|
-
type: "ee",
|
|
864
|
-
key: "disabled_users",
|
|
865
|
-
value: newDisabledUsersList
|
|
866
|
-
});
|
|
867
|
-
}
|
|
868
|
-
};
|
|
869
|
-
const castNumberArray = pipe(castArray, map(toNumber));
|
|
870
|
-
const removeFromEEDisabledUsersList = async (ids) => {
|
|
871
|
-
let idsToCheck;
|
|
872
|
-
if (typeof ids === "object") {
|
|
873
|
-
idsToCheck = castNumberArray(ids);
|
|
874
|
-
} else {
|
|
875
|
-
idsToCheck = [Number(ids)];
|
|
876
|
-
}
|
|
877
|
-
const disabledUsers = await getService("seat-enforcement").getDisabledUserList();
|
|
878
|
-
if (!disabledUsers) {
|
|
879
|
-
return;
|
|
880
|
-
}
|
|
881
|
-
const newDisabledUsersList = disabledUsers.filter((user2) => !idsToCheck.includes(user2.id));
|
|
882
|
-
await strapi.store.set({
|
|
883
|
-
type: "ee",
|
|
884
|
-
key: "disabled_users",
|
|
885
|
-
value: newDisabledUsersList
|
|
886
|
-
});
|
|
887
|
-
};
|
|
888
|
-
const updateById = async (id, attributes) => {
|
|
889
|
-
if (_.has(attributes, "roles")) {
|
|
890
|
-
const lastAdminUser = await isLastSuperAdminUser(id);
|
|
891
|
-
const superAdminRole = await getService("role").getSuperAdminWithUsersCount();
|
|
892
|
-
const willRemoveSuperAdminRole = !arrays.includesString(attributes.roles, superAdminRole.id);
|
|
893
|
-
if (lastAdminUser && willRemoveSuperAdminRole) {
|
|
894
|
-
throw new ValidationError$1("You must have at least one user with super admin role.");
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
if (attributes.isActive === false) {
|
|
898
|
-
const lastAdminUser = await isLastSuperAdminUser(id);
|
|
899
|
-
if (lastAdminUser) {
|
|
900
|
-
throw new ValidationError$1("You must have at least one user with super admin role.");
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
if (_.has(attributes, "password")) {
|
|
904
|
-
const hashedPassword = await getService("auth").hashPassword(attributes.password);
|
|
905
|
-
const updatedUser2 = await strapi.db.query("admin::user").update({
|
|
906
|
-
where: { id },
|
|
907
|
-
data: {
|
|
908
|
-
...attributes,
|
|
909
|
-
password: hashedPassword
|
|
910
|
-
},
|
|
911
|
-
populate: ["roles"]
|
|
912
|
-
});
|
|
913
|
-
strapi.eventHub.emit("user.update", { user: sanitizeUser(updatedUser2) });
|
|
914
|
-
return updatedUser2;
|
|
915
|
-
}
|
|
916
|
-
const updatedUser = await strapi.db.query("admin::user").update({
|
|
917
|
-
where: { id },
|
|
918
|
-
data: attributes,
|
|
919
|
-
populate: ["roles"]
|
|
920
|
-
});
|
|
921
|
-
await updateEEDisabledUsersList(id, attributes);
|
|
922
|
-
if (updatedUser) {
|
|
923
|
-
strapi.eventHub.emit("user.update", { user: sanitizeUser(updatedUser) });
|
|
924
|
-
}
|
|
925
|
-
return updatedUser;
|
|
926
|
-
};
|
|
927
|
-
const deleteById = async (id) => {
|
|
928
|
-
const userToDelete = await strapi.db.query("admin::user").findOne({
|
|
929
|
-
where: { id },
|
|
930
|
-
populate: ["roles"]
|
|
931
|
-
});
|
|
932
|
-
if (!userToDelete) {
|
|
933
|
-
return null;
|
|
934
|
-
}
|
|
935
|
-
if (userToDelete) {
|
|
936
|
-
if (userToDelete.roles.some((r) => r.code === SUPER_ADMIN_CODE$1)) {
|
|
937
|
-
const superAdminRole = await getService("role").getSuperAdminWithUsersCount();
|
|
938
|
-
if (superAdminRole.usersCount === 1) {
|
|
939
|
-
throw new ValidationError$1("You must have at least one user with super admin role.");
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
const deletedUser = await strapi.db.query("admin::user").delete({ where: { id }, populate: ["roles"] });
|
|
944
|
-
await removeFromEEDisabledUsersList(id);
|
|
945
|
-
strapi.eventHub.emit("user.delete", { user: sanitizeUser(deletedUser) });
|
|
946
|
-
return deletedUser;
|
|
947
|
-
};
|
|
948
|
-
const deleteByIds = async (ids) => {
|
|
949
|
-
const superAdminRole = await getService("role").getSuperAdminWithUsersCount();
|
|
950
|
-
const nbOfSuperAdminToDelete = await strapi.db.query("admin::user").count({
|
|
951
|
-
where: {
|
|
952
|
-
id: ids,
|
|
953
|
-
roles: { id: superAdminRole.id }
|
|
954
|
-
}
|
|
955
|
-
});
|
|
956
|
-
if (superAdminRole.usersCount === nbOfSuperAdminToDelete) {
|
|
957
|
-
throw new ValidationError$1("You must have at least one user with super admin role.");
|
|
958
|
-
}
|
|
959
|
-
const deletedUsers = [];
|
|
960
|
-
for (const id of ids) {
|
|
961
|
-
const deletedUser = await strapi.db.query("admin::user").delete({
|
|
962
|
-
where: { id },
|
|
963
|
-
populate: ["roles"]
|
|
964
|
-
});
|
|
965
|
-
deletedUsers.push(deletedUser);
|
|
966
|
-
}
|
|
967
|
-
await removeFromEEDisabledUsersList(ids);
|
|
968
|
-
strapi.eventHub.emit("user.delete", {
|
|
969
|
-
users: deletedUsers.map((deletedUser) => sanitizeUser(deletedUser))
|
|
970
|
-
});
|
|
971
|
-
return deletedUsers;
|
|
972
|
-
};
|
|
973
|
-
const sanitizeUserRoles = (role2) => _.pick(role2, ["id", "name", "description", "code"]);
|
|
974
|
-
const isLastSuperAdminUser = async (userId) => {
|
|
975
|
-
const user2 = await findOne(userId);
|
|
976
|
-
const superAdminRole = await getService("role").getSuperAdminWithUsersCount();
|
|
977
|
-
return superAdminRole.usersCount === 1 && hasSuperAdminRole(user2);
|
|
978
|
-
};
|
|
979
|
-
const sanitizeUser = (user2) => {
|
|
980
|
-
return {
|
|
981
|
-
..._.omit(user2, ["password", "resetPasswordToken", "registrationToken", "roles"]),
|
|
982
|
-
roles: user2.roles && user2.roles.map(sanitizeUserRoles)
|
|
983
|
-
};
|
|
984
|
-
};
|
|
985
|
-
const findOne = async (id, populate = ["roles"]) => {
|
|
986
|
-
return strapi.db.query("admin::user").findOne({ where: { id }, populate });
|
|
987
|
-
};
|
|
988
|
-
const getCurrentActiveUserCount = async () => {
|
|
989
|
-
return strapi.db.query("admin::user").count({ where: { isActive: true } });
|
|
990
|
-
};
|
|
991
|
-
const user$1 = {
|
|
992
|
-
updateEEDisabledUsersList,
|
|
993
|
-
removeFromEEDisabledUsersList,
|
|
994
|
-
getCurrentActiveUserCount,
|
|
995
|
-
deleteByIds,
|
|
996
|
-
deleteById,
|
|
997
|
-
updateById
|
|
998
|
-
};
|
|
999
|
-
const getSSOProvidersList = async () => {
|
|
1000
|
-
const { providerRegistry: providerRegistry2 } = strapi.service("admin::passport");
|
|
1001
|
-
return providerRegistry2.getAll().map(({ uid }) => uid);
|
|
1002
|
-
};
|
|
1003
|
-
const sendUpdateProjectInformation = async (strapi2) => {
|
|
1004
|
-
let groupProperties = {};
|
|
1005
|
-
const numberOfActiveAdminUsers = await getService("user").count({ isActive: true });
|
|
1006
|
-
const numberOfAdminUsers = await getService("user").count();
|
|
1007
|
-
if (strapi2.ee.features.isEnabled("sso")) {
|
|
1008
|
-
const SSOProviders = await getSSOProvidersList();
|
|
1009
|
-
groupProperties = assign(groupProperties, {
|
|
1010
|
-
SSOProviders,
|
|
1011
|
-
isSSOConfigured: SSOProviders.length !== 0
|
|
1012
|
-
});
|
|
1013
|
-
}
|
|
1014
|
-
if (strapi2.ee.features.isEnabled("cms-content-releases")) {
|
|
1015
|
-
const numberOfContentReleases = await strapi2.db.query("plugin::content-releases.release").count();
|
|
1016
|
-
const numberOfPublishedContentReleases = await strapi2.db.query("plugin::content-releases.release").count({
|
|
1017
|
-
filters: { releasedAt: { $notNull: true } }
|
|
1018
|
-
});
|
|
1019
|
-
groupProperties = assign(groupProperties, {
|
|
1020
|
-
numberOfContentReleases,
|
|
1021
|
-
numberOfPublishedContentReleases
|
|
1022
|
-
});
|
|
1023
|
-
}
|
|
1024
|
-
groupProperties = assign(groupProperties, { numberOfActiveAdminUsers, numberOfAdminUsers });
|
|
1025
|
-
strapi2.telemetry.send("didUpdateProjectInformation", {
|
|
1026
|
-
groupProperties
|
|
1027
|
-
});
|
|
1028
|
-
};
|
|
1029
|
-
const startCron = (strapi2) => {
|
|
1030
|
-
strapi2.cron.add({
|
|
1031
|
-
"0 0 0 * * *": () => sendUpdateProjectInformation(strapi2)
|
|
1032
|
-
});
|
|
1033
|
-
};
|
|
1034
|
-
const metrics = { startCron, getSSOProvidersList, sendUpdateProjectInformation };
|
|
1035
|
-
const { SUPER_ADMIN_CODE } = constants;
|
|
1036
|
-
const getDisabledUserList = async () => {
|
|
1037
|
-
return strapi.store.get({ type: "ee", key: "disabled_users" });
|
|
1038
|
-
};
|
|
1039
|
-
const enableMaximumUserCount = async (numberOfUsersToEnable) => {
|
|
1040
|
-
const disabledUsers = await getDisabledUserList();
|
|
1041
|
-
const orderedDisabledUsers = reverse(disabledUsers);
|
|
1042
|
-
const usersToEnable = take(numberOfUsersToEnable, orderedDisabledUsers);
|
|
1043
|
-
await strapi.db.query("admin::user").updateMany({
|
|
1044
|
-
where: { id: map(prop("id"), usersToEnable) },
|
|
1045
|
-
data: { isActive: true }
|
|
1046
|
-
});
|
|
1047
|
-
const remainingDisabledUsers = drop(numberOfUsersToEnable, orderedDisabledUsers);
|
|
1048
|
-
await strapi.store.set({
|
|
1049
|
-
type: "ee",
|
|
1050
|
-
key: "disabled_users",
|
|
1051
|
-
value: remainingDisabledUsers
|
|
1052
|
-
});
|
|
1053
|
-
};
|
|
1054
|
-
const disableUsersAboveLicenseLimit = async (numberOfUsersToDisable) => {
|
|
1055
|
-
const currentlyDisabledUsers = await getDisabledUserList() ?? [];
|
|
1056
|
-
const usersToDisable = [];
|
|
1057
|
-
const nonSuperAdminUsersToDisable = await strapi.db.query("admin::user").findMany({
|
|
1058
|
-
where: {
|
|
1059
|
-
isActive: true,
|
|
1060
|
-
roles: {
|
|
1061
|
-
code: { $ne: SUPER_ADMIN_CODE }
|
|
1062
|
-
}
|
|
1063
|
-
},
|
|
1064
|
-
orderBy: { createdAt: "DESC" },
|
|
1065
|
-
limit: numberOfUsersToDisable
|
|
1066
|
-
});
|
|
1067
|
-
usersToDisable.push(...nonSuperAdminUsersToDisable);
|
|
1068
|
-
if (nonSuperAdminUsersToDisable.length < numberOfUsersToDisable) {
|
|
1069
|
-
const superAdminUsersToDisable = await strapi.db.query("admin::user").findMany({
|
|
1070
|
-
where: {
|
|
1071
|
-
isActive: true,
|
|
1072
|
-
roles: { code: SUPER_ADMIN_CODE }
|
|
1073
|
-
},
|
|
1074
|
-
orderBy: { createdAt: "DESC" },
|
|
1075
|
-
limit: numberOfUsersToDisable - nonSuperAdminUsersToDisable.length
|
|
1076
|
-
});
|
|
1077
|
-
usersToDisable.push(...superAdminUsersToDisable);
|
|
1078
|
-
}
|
|
1079
|
-
await strapi.db.query("admin::user").updateMany({
|
|
1080
|
-
where: { id: map(prop("id"), usersToDisable) },
|
|
1081
|
-
data: { isActive: false }
|
|
1082
|
-
});
|
|
1083
|
-
await strapi.store.set({
|
|
1084
|
-
type: "ee",
|
|
1085
|
-
key: "disabled_users",
|
|
1086
|
-
value: currentlyDisabledUsers.concat(map(pick(["id", "isActive"]), usersToDisable))
|
|
1087
|
-
});
|
|
1088
|
-
};
|
|
1089
|
-
const syncDisabledUserRecords = async () => {
|
|
1090
|
-
const disabledUsers = await strapi.store.get({ type: "ee", key: "disabled_users" });
|
|
1091
|
-
if (!disabledUsers) {
|
|
1092
|
-
return;
|
|
1093
|
-
}
|
|
1094
|
-
await strapi.db.query("admin::user").updateMany({
|
|
1095
|
-
where: { id: map(prop("id"), disabledUsers) },
|
|
1096
|
-
data: { isActive: false }
|
|
1097
|
-
});
|
|
1098
|
-
};
|
|
1099
|
-
const seatEnforcementWorkflow = async () => {
|
|
1100
|
-
const adminSeats = strapi.ee.seats;
|
|
1101
|
-
if (isNil(adminSeats)) {
|
|
1102
|
-
return;
|
|
1103
|
-
}
|
|
1104
|
-
await syncDisabledUserRecords();
|
|
1105
|
-
const currentActiveUserCount = await getService("user").getCurrentActiveUserCount();
|
|
1106
|
-
const adminSeatsLeft = adminSeats - currentActiveUserCount;
|
|
1107
|
-
if (adminSeatsLeft > 0) {
|
|
1108
|
-
await enableMaximumUserCount(adminSeatsLeft);
|
|
1109
|
-
} else if (adminSeatsLeft < 0) {
|
|
1110
|
-
await disableUsersAboveLicenseLimit(-adminSeatsLeft);
|
|
1111
|
-
}
|
|
1112
|
-
};
|
|
1113
|
-
const seatEnforcement = {
|
|
1114
|
-
seatEnforcementWorkflow,
|
|
1115
|
-
getDisabledUserList
|
|
1116
|
-
};
|
|
1117
|
-
const services = {
|
|
1118
|
-
auth,
|
|
1119
|
-
passport,
|
|
1120
|
-
role: role$1,
|
|
1121
|
-
user: user$1,
|
|
1122
|
-
metrics,
|
|
1123
|
-
"seat-enforcement": seatEnforcement
|
|
1124
|
-
};
|
|
1125
|
-
const providerOptionsUpdateSchema = yup.object().shape({
|
|
1126
|
-
autoRegister: yup.boolean().required(),
|
|
1127
|
-
defaultRole: yup.strapiID().when("autoRegister", (value, initSchema) => {
|
|
1128
|
-
return value ? initSchema.required() : initSchema.nullable();
|
|
1129
|
-
}).test("is-valid-role", "You must submit a valid default role", (roleId) => {
|
|
1130
|
-
if (roleId === null) {
|
|
1131
|
-
return true;
|
|
1132
|
-
}
|
|
1133
|
-
return strapi.service("admin::role").exists({ id: roleId });
|
|
1134
|
-
}),
|
|
1135
|
-
ssoLockedRoles: yup.array().nullable().of(
|
|
1136
|
-
yup.strapiID().test(
|
|
1137
|
-
"is-valid-role",
|
|
1138
|
-
"You must submit a valid role for the SSO Locked roles",
|
|
1139
|
-
(roleId) => {
|
|
1140
|
-
return strapi.service("admin::role").exists({ id: roleId });
|
|
1141
|
-
}
|
|
1142
|
-
)
|
|
1143
|
-
)
|
|
1144
|
-
});
|
|
1145
|
-
const validateProviderOptionsUpdate = validateYupSchema(providerOptionsUpdateSchema);
|
|
1146
|
-
const PROVIDER_REDIRECT_BASE = "/auth/login";
|
|
1147
|
-
const PROVIDER_REDIRECT_SUCCESS = `${PROVIDER_REDIRECT_BASE}/success`;
|
|
1148
|
-
const PROVIDER_REDIRECT_ERROR = `${PROVIDER_REDIRECT_BASE}/error`;
|
|
1149
|
-
const PROVIDER_URLS_MAP = {
|
|
1150
|
-
success: PROVIDER_REDIRECT_SUCCESS,
|
|
1151
|
-
error: PROVIDER_REDIRECT_ERROR
|
|
1152
|
-
};
|
|
1153
|
-
const getAdminStore = async () => strapi.store({ type: "core", name: "admin" });
|
|
1154
|
-
const getPrefixedRedirectUrls = () => {
|
|
1155
|
-
const { url: adminUrl } = strapi.config.get("admin");
|
|
1156
|
-
const prefixUrl = (url) => `${adminUrl || "/admin"}${url}`;
|
|
1157
|
-
return mapValues(prefixUrl, PROVIDER_URLS_MAP);
|
|
1158
|
-
};
|
|
1159
|
-
const utils = {
|
|
1160
|
-
getAdminStore,
|
|
1161
|
-
getPrefixedRedirectUrls
|
|
1162
|
-
};
|
|
1163
|
-
const defaultConnectionError = () => new Error("Invalid connection payload");
|
|
1164
|
-
const authenticate = async (ctx, next) => {
|
|
1165
|
-
const {
|
|
1166
|
-
params: { provider }
|
|
1167
|
-
} = ctx;
|
|
1168
|
-
const redirectUrls = utils.getPrefixedRedirectUrls();
|
|
1169
|
-
return passport$2.authenticate(provider, null, async (error, profile) => {
|
|
1170
|
-
if (error || !profile || !profile.email) {
|
|
1171
|
-
if (error) {
|
|
1172
|
-
strapi.log.error(error);
|
|
1173
|
-
}
|
|
1174
|
-
strapi.eventHub.emit("admin.auth.error", {
|
|
1175
|
-
error: error || defaultConnectionError(),
|
|
1176
|
-
provider
|
|
1177
|
-
});
|
|
1178
|
-
return ctx.redirect(redirectUrls.error);
|
|
1179
|
-
}
|
|
1180
|
-
const user2 = await getService("user").findOneByEmail(profile.email);
|
|
1181
|
-
const scenario = user2 ? existingUserScenario : nonExistingUserScenario;
|
|
1182
|
-
return scenario(ctx, next)(user2 || profile, provider);
|
|
1183
|
-
})(ctx, next);
|
|
1184
|
-
};
|
|
1185
|
-
const existingUserScenario = (ctx, next) => async (user2, provider) => {
|
|
1186
|
-
const redirectUrls = utils.getPrefixedRedirectUrls();
|
|
1187
|
-
if (!user2.isActive) {
|
|
1188
|
-
strapi.eventHub.emit("admin.auth.error", {
|
|
1189
|
-
error: new Error(`Deactivated user tried to login (${user2.id})`),
|
|
1190
|
-
provider
|
|
1191
|
-
});
|
|
1192
|
-
return ctx.redirect(redirectUrls.error);
|
|
1193
|
-
}
|
|
1194
|
-
ctx.state.user = user2;
|
|
1195
|
-
return next();
|
|
1196
|
-
};
|
|
1197
|
-
const nonExistingUserScenario = (ctx, next) => async (profile, provider) => {
|
|
1198
|
-
const { email: email2, firstname: firstname2, lastname: lastname2, username: username2 } = profile;
|
|
1199
|
-
const redirectUrls = utils.getPrefixedRedirectUrls();
|
|
1200
|
-
const adminStore = await utils.getAdminStore();
|
|
1201
|
-
const { providers } = await adminStore.get({ key: "auth" });
|
|
1202
|
-
const isMissingRegisterFields = !username2 && (!firstname2 || !lastname2);
|
|
1203
|
-
if (!providers.autoRegister || !providers.defaultRole || isMissingRegisterFields) {
|
|
1204
|
-
strapi.eventHub.emit("admin.auth.error", { error: defaultConnectionError(), provider });
|
|
1205
|
-
return ctx.redirect(redirectUrls.error);
|
|
1206
|
-
}
|
|
1207
|
-
const defaultRole = await getService("role").findOne({ id: providers.defaultRole });
|
|
1208
|
-
if (!defaultRole) {
|
|
1209
|
-
strapi.eventHub.emit("admin.auth.error", { error: defaultConnectionError(), provider });
|
|
1210
|
-
return ctx.redirect(redirectUrls.error);
|
|
1211
|
-
}
|
|
1212
|
-
ctx.state.user = await getService("user").create({
|
|
1213
|
-
email: email2,
|
|
1214
|
-
username: username2,
|
|
1215
|
-
firstname: firstname2,
|
|
1216
|
-
lastname: lastname2,
|
|
1217
|
-
roles: [defaultRole.id],
|
|
1218
|
-
isActive: true,
|
|
1219
|
-
registrationToken: null
|
|
1220
|
-
});
|
|
1221
|
-
strapi.eventHub.emit("admin.auth.autoRegistration", {
|
|
1222
|
-
user: ctx.state.user,
|
|
1223
|
-
provider
|
|
1224
|
-
});
|
|
1225
|
-
return next();
|
|
1226
|
-
};
|
|
1227
|
-
const redirectWithAuth = (ctx) => {
|
|
1228
|
-
const {
|
|
1229
|
-
params: { provider }
|
|
1230
|
-
} = ctx;
|
|
1231
|
-
const redirectUrls = utils.getPrefixedRedirectUrls();
|
|
1232
|
-
const domain = strapi.config.get("admin.auth.domain");
|
|
1233
|
-
const { user: user2 } = ctx.state;
|
|
1234
|
-
const jwt = getService("token").createJwtToken(user2);
|
|
1235
|
-
const isProduction = strapi.config.get("environment") === "production";
|
|
1236
|
-
const cookiesOptions = { httpOnly: false, secure: isProduction, overwrite: true, domain };
|
|
1237
|
-
const sanitizedUser = getService("user").sanitizeUser(user2);
|
|
1238
|
-
strapi.eventHub.emit("admin.auth.success", { user: sanitizedUser, provider });
|
|
1239
|
-
ctx.cookies.set("jwtToken", jwt, cookiesOptions);
|
|
1240
|
-
ctx.redirect(redirectUrls.success);
|
|
1241
|
-
};
|
|
1242
|
-
const middlewares = {
|
|
1243
|
-
authenticate,
|
|
1244
|
-
redirectWithAuth
|
|
1245
|
-
};
|
|
1246
|
-
const toProviderDTO = pick(["uid", "displayName", "icon"]);
|
|
1247
|
-
const toProviderLoginOptionsDTO = pick(["autoRegister", "defaultRole", "ssoLockedRoles"]);
|
|
1248
|
-
const { ValidationError } = errors;
|
|
1249
|
-
const providerAuthenticationFlow = compose([
|
|
1250
|
-
middlewares.authenticate,
|
|
1251
|
-
middlewares.redirectWithAuth
|
|
1252
|
-
]);
|
|
1253
|
-
const authentication = {
|
|
1254
|
-
async getProviders(ctx) {
|
|
1255
|
-
const { providerRegistry: providerRegistry2 } = strapi.service("admin::passport");
|
|
1256
|
-
ctx.body = providerRegistry2.getAll().map(toProviderDTO);
|
|
1257
|
-
},
|
|
1258
|
-
async getProviderLoginOptions(ctx) {
|
|
1259
|
-
const adminStore = await utils.getAdminStore();
|
|
1260
|
-
const { providers: providersOptions } = await adminStore.get({ key: "auth" });
|
|
1261
|
-
ctx.body = {
|
|
1262
|
-
data: toProviderLoginOptionsDTO(providersOptions)
|
|
1263
|
-
};
|
|
1264
|
-
},
|
|
1265
|
-
async updateProviderLoginOptions(ctx) {
|
|
1266
|
-
const {
|
|
1267
|
-
request: { body }
|
|
1268
|
-
} = ctx;
|
|
1269
|
-
await validateProviderOptionsUpdate(body);
|
|
1270
|
-
const adminStore = await utils.getAdminStore();
|
|
1271
|
-
const currentAuthOptions = await adminStore.get({ key: "auth" });
|
|
1272
|
-
const newAuthOptions = { ...currentAuthOptions, providers: body };
|
|
1273
|
-
await adminStore.set({ key: "auth", value: newAuthOptions });
|
|
1274
|
-
strapi.telemetry.send("didUpdateSSOSettings");
|
|
1275
|
-
ctx.body = {
|
|
1276
|
-
data: toProviderLoginOptionsDTO(newAuthOptions.providers)
|
|
1277
|
-
};
|
|
1278
|
-
},
|
|
1279
|
-
providerLogin(ctx, next) {
|
|
1280
|
-
const {
|
|
1281
|
-
params: { provider: providerName }
|
|
1282
|
-
} = ctx;
|
|
1283
|
-
const { providerRegistry: providerRegistry2 } = strapi.service("admin::passport");
|
|
1284
|
-
if (!providerRegistry2.has(providerName)) {
|
|
1285
|
-
throw new ValidationError(`Invalid provider supplied: ${providerName}`);
|
|
1286
|
-
}
|
|
1287
|
-
return providerAuthenticationFlow(ctx, next);
|
|
1288
|
-
}
|
|
1289
|
-
};
|
|
1290
|
-
const roleCreateSchema = yup.object().shape({
|
|
1291
|
-
name: yup.string().min(1).required(),
|
|
1292
|
-
description: yup.string().nullable()
|
|
1293
|
-
}).noUnknown();
|
|
1294
|
-
const rolesDeleteSchema = yup.object().shape({
|
|
1295
|
-
ids: yup.array().of(yup.strapiID()).min(1).required().test(
|
|
1296
|
-
"roles-deletion-checks",
|
|
1297
|
-
"Roles deletion checks have failed",
|
|
1298
|
-
async function rolesDeletionChecks(ids) {
|
|
1299
|
-
try {
|
|
1300
|
-
await strapi.service("admin::role").checkRolesIdForDeletion(ids);
|
|
1301
|
-
if (strapi.ee.features.isEnabled("sso")) {
|
|
1302
|
-
await strapi.service("admin::role").ssoCheckRolesIdForDeletion(ids);
|
|
1303
|
-
}
|
|
1304
|
-
} catch (e) {
|
|
1305
|
-
return this.createError({ path: "ids", message: e.message });
|
|
1306
|
-
}
|
|
1307
|
-
return true;
|
|
1308
|
-
}
|
|
1309
|
-
)
|
|
1310
|
-
}).noUnknown();
|
|
1311
|
-
const roleDeleteSchema = yup.strapiID().required().test(
|
|
1312
|
-
"no-admin-single-delete",
|
|
1313
|
-
"Role deletion checks have failed",
|
|
1314
|
-
async function noAdminSingleDelete(id) {
|
|
1315
|
-
try {
|
|
1316
|
-
await strapi.service("admin::role").checkRolesIdForDeletion([id]);
|
|
1317
|
-
if (strapi.ee.features.isEnabled("sso")) {
|
|
1318
|
-
await strapi.service("admin::role").ssoCheckRolesIdForDeletion([id]);
|
|
1319
|
-
}
|
|
1320
|
-
} catch (e) {
|
|
1321
|
-
return this.createError({ path: "id", message: e.message });
|
|
1322
|
-
}
|
|
1323
|
-
return true;
|
|
1324
|
-
}
|
|
1325
|
-
);
|
|
1326
|
-
const validateRoleCreateInput = validateYupSchema(roleCreateSchema);
|
|
1327
|
-
const validateRolesDeleteInput = validateYupSchema(rolesDeleteSchema);
|
|
1328
|
-
const validateRoleDeleteInput = validateYupSchema(roleDeleteSchema);
|
|
1329
|
-
const role = {
|
|
1330
|
-
/**
|
|
1331
|
-
* Create a new role
|
|
1332
|
-
* @param {KoaContext} ctx - koa context
|
|
1333
|
-
*/
|
|
1334
|
-
async create(ctx) {
|
|
1335
|
-
await validateRoleCreateInput(ctx.request.body);
|
|
1336
|
-
const roleService = getService("role");
|
|
1337
|
-
const role2 = await roleService.create(ctx.request.body);
|
|
1338
|
-
const sanitizedRole = roleService.sanitizeRole(role2);
|
|
1339
|
-
ctx.created({ data: sanitizedRole });
|
|
1340
|
-
},
|
|
1341
|
-
/**
|
|
1342
|
-
* Delete a role
|
|
1343
|
-
* @param {KoaContext} ctx - koa context
|
|
1344
|
-
*/
|
|
1345
|
-
async deleteOne(ctx) {
|
|
1346
|
-
const { id } = ctx.params;
|
|
1347
|
-
await validateRoleDeleteInput(id);
|
|
1348
|
-
const roleService = getService("role");
|
|
1349
|
-
const roles2 = await roleService.deleteByIds([id]);
|
|
1350
|
-
const sanitizedRole = roles2.map((role2) => roleService.sanitizeRole(role2))[0] || null;
|
|
1351
|
-
return ctx.deleted({
|
|
1352
|
-
data: sanitizedRole
|
|
1353
|
-
});
|
|
1354
|
-
},
|
|
1355
|
-
/**
|
|
1356
|
-
* delete several roles
|
|
1357
|
-
* @param {KoaContext} ctx - koa context
|
|
1358
|
-
*/
|
|
1359
|
-
async deleteMany(ctx) {
|
|
1360
|
-
const { body } = ctx.request;
|
|
1361
|
-
await validateRolesDeleteInput(body);
|
|
1362
|
-
const roleService = getService("role");
|
|
1363
|
-
const roles2 = await roleService.deleteByIds(body.ids);
|
|
1364
|
-
const sanitizedRoles = roles2.map(roleService.sanitizeRole);
|
|
1365
|
-
return ctx.deleted({
|
|
1366
|
-
data: sanitizedRoles
|
|
1367
|
-
});
|
|
1368
|
-
}
|
|
1369
|
-
};
|
|
1370
|
-
const getDefaultActionAttributes = () => ({
|
|
1371
|
-
options: {
|
|
1372
|
-
applyToProperties: null
|
|
1373
|
-
}
|
|
1374
|
-
});
|
|
1375
|
-
const actionFields = [
|
|
1376
|
-
"section",
|
|
1377
|
-
"displayName",
|
|
1378
|
-
"category",
|
|
1379
|
-
"subCategory",
|
|
1380
|
-
"pluginName",
|
|
1381
|
-
"subjects",
|
|
1382
|
-
"options",
|
|
1383
|
-
"actionId",
|
|
1384
|
-
"aliases"
|
|
1385
|
-
];
|
|
1386
|
-
const sanitizeActionAttributes = pick(actionFields);
|
|
1387
|
-
const computeActionId = (attributes) => {
|
|
1388
|
-
const { pluginName, uid } = attributes;
|
|
1389
|
-
if (!pluginName) {
|
|
1390
|
-
return `api::${uid}`;
|
|
1391
|
-
}
|
|
1392
|
-
if (pluginName === "admin") {
|
|
1393
|
-
return `admin::${uid}`;
|
|
1394
|
-
}
|
|
1395
|
-
return `plugin::${pluginName}.${uid}`;
|
|
1396
|
-
};
|
|
1397
|
-
const assignActionId = (attrs) => set("actionId", computeActionId(attrs), attrs);
|
|
1398
|
-
const assignOrOmitSubCategory = (action) => {
|
|
1399
|
-
const shouldHaveSubCategory = ["settings", "plugins"].includes(action.section);
|
|
1400
|
-
return shouldHaveSubCategory ? set("subCategory", action.subCategory || "general", action) : omit("subCategory", action);
|
|
1401
|
-
};
|
|
1402
|
-
const appliesToProperty = curry((property, action) => {
|
|
1403
|
-
return pipe(prop("options.applyToProperties"), includes(property))(action);
|
|
1404
|
-
});
|
|
1405
|
-
const appliesToSubject = curry((subject, action) => {
|
|
1406
|
-
return isArray(action.subjects) && includes(subject, action.subjects);
|
|
1407
|
-
});
|
|
1408
|
-
const create = pipe(
|
|
1409
|
-
// Create and assign an action identifier to the action
|
|
1410
|
-
// (need to be done before the sanitizeActionAttributes since we need the uid here)
|
|
1411
|
-
assignActionId,
|
|
1412
|
-
// Add or remove the sub category field based on the pluginName attribute
|
|
1413
|
-
assignOrOmitSubCategory,
|
|
1414
|
-
// Remove unwanted attributes from the payload
|
|
1415
|
-
sanitizeActionAttributes,
|
|
1416
|
-
// Complete the action creation by adding default values for some attributes
|
|
1417
|
-
merge(getDefaultActionAttributes())
|
|
1418
|
-
);
|
|
1419
|
-
const actionDomain = {
|
|
1420
|
-
actionFields,
|
|
1421
|
-
appliesToProperty,
|
|
1422
|
-
appliesToSubject,
|
|
1423
|
-
assignActionId,
|
|
1424
|
-
assignOrOmitSubCategory,
|
|
1425
|
-
create,
|
|
1426
|
-
computeActionId,
|
|
1427
|
-
getDefaultActionAttributes,
|
|
1428
|
-
sanitizeActionAttributes
|
|
1429
|
-
};
|
|
1430
|
-
const checkFieldsAreCorrectlyNested = (fields) => {
|
|
1431
|
-
if (_.isNil(fields)) {
|
|
1432
|
-
return true;
|
|
1433
|
-
}
|
|
1434
|
-
if (!Array.isArray(fields)) {
|
|
1435
|
-
return false;
|
|
1436
|
-
}
|
|
1437
|
-
let failed = false;
|
|
1438
|
-
for (let indexA = 0; indexA < fields.length; indexA += 1) {
|
|
1439
|
-
failed = fields.slice(indexA + 1).some(
|
|
1440
|
-
(fieldB) => fieldB.startsWith(`${fields[indexA]}.`) || fields[indexA].startsWith(`${fieldB}.`)
|
|
1441
|
-
);
|
|
1442
|
-
if (failed)
|
|
1443
|
-
break;
|
|
1444
|
-
}
|
|
1445
|
-
return !failed;
|
|
1446
|
-
};
|
|
1447
|
-
const checkFieldsDontHaveDuplicates = (fields) => {
|
|
1448
|
-
if (_.isNil(fields)) {
|
|
1449
|
-
return true;
|
|
1450
|
-
}
|
|
1451
|
-
if (!Array.isArray(fields)) {
|
|
1452
|
-
return false;
|
|
1453
|
-
}
|
|
1454
|
-
return _.uniq(fields).length === fields.length;
|
|
1455
|
-
};
|
|
1456
|
-
const getActionFromProvider = (actionId) => {
|
|
1457
|
-
return getService$1("permission").actionProvider.get(actionId);
|
|
1458
|
-
};
|
|
1459
|
-
const email = yup.string().email().lowercase();
|
|
1460
|
-
const firstname = yup.string().trim().min(1);
|
|
1461
|
-
const lastname = yup.string();
|
|
1462
|
-
const username = yup.string().min(1);
|
|
1463
|
-
const password = yup.string().min(8).matches(/[a-z]/, "${path} must contain at least one lowercase character").matches(/[A-Z]/, "${path} must contain at least one uppercase character").matches(/\d/, "${path} must contain at least one number");
|
|
1464
|
-
const roles = yup.array(yup.strapiID()).min(1);
|
|
1465
|
-
const isAPluginName = yup.string().test("is-a-plugin-name", "is not a plugin name", function(value) {
|
|
1466
|
-
return [void 0, "admin", ...Object.keys(strapi.plugins)].includes(value) ? true : this.createError({ path: this.path, message: `${this.path} is not an existing plugin` });
|
|
1467
|
-
});
|
|
1468
|
-
const arrayOfConditionNames = yup.array().of(yup.string()).test("is-an-array-of-conditions", "is not a plugin name", function(value) {
|
|
1469
|
-
const ids = strapi.service("admin::permission").conditionProvider.keys();
|
|
1470
|
-
return _.isUndefined(value) || _.difference(value, ids).length === 0 ? true : this.createError({ path: this.path, message: `contains conditions that don't exist` });
|
|
1471
|
-
});
|
|
1472
|
-
const permissionsAreEquals = (a, b) => a.action === b.action && (a.subject === b.subject || _.isNil(a.subject) && _.isNil(b.subject));
|
|
1473
|
-
const checkNoDuplicatedPermissions = (permissions) => !Array.isArray(permissions) || permissions.every(
|
|
1474
|
-
(permA, i) => permissions.slice(i + 1).every((permB) => !permissionsAreEquals(permA, permB))
|
|
1475
|
-
);
|
|
1476
|
-
const checkNilFields = (action) => function(fields) {
|
|
1477
|
-
if (isNil(action)) {
|
|
1478
|
-
return true;
|
|
1479
|
-
}
|
|
1480
|
-
return actionDomain.appliesToProperty("fields", action) || isNil(fields);
|
|
1481
|
-
};
|
|
1482
|
-
const fieldsPropertyValidation = (action) => yup.array().of(yup.string()).nullable().test(
|
|
1483
|
-
"field-nested",
|
|
1484
|
-
"Fields format are incorrect (bad nesting).",
|
|
1485
|
-
checkFieldsAreCorrectlyNested
|
|
1486
|
-
).test(
|
|
1487
|
-
"field-nested",
|
|
1488
|
-
"Fields format are incorrect (duplicates).",
|
|
1489
|
-
checkFieldsDontHaveDuplicates
|
|
1490
|
-
).test(
|
|
1491
|
-
"fields-restriction",
|
|
1492
|
-
"The permission at ${path} must have fields set to null or undefined",
|
|
1493
|
-
// @ts-expect-error yup types
|
|
1494
|
-
checkNilFields(action)
|
|
1495
|
-
);
|
|
1496
|
-
const permission = yup.object().shape({
|
|
1497
|
-
action: yup.string().required().test("action-validity", "action is not an existing permission action", function(actionId) {
|
|
1498
|
-
if (isNil(actionId)) {
|
|
1499
|
-
return true;
|
|
1500
|
-
}
|
|
1501
|
-
return !!getActionFromProvider(actionId);
|
|
1502
|
-
}),
|
|
1503
|
-
actionParameters: yup.object().nullable(),
|
|
1504
|
-
subject: yup.string().nullable().test("subject-validity", "Invalid subject submitted", function(subject) {
|
|
1505
|
-
const action = getActionFromProvider(this.options.parent.action);
|
|
1506
|
-
if (!action) {
|
|
1507
|
-
return true;
|
|
1508
|
-
}
|
|
1509
|
-
if (isNil(action.subjects)) {
|
|
1510
|
-
return isNil(subject);
|
|
1511
|
-
}
|
|
1512
|
-
if (isArray(action.subjects) && !isNil(subject)) {
|
|
1513
|
-
return action.subjects.includes(subject);
|
|
1514
|
-
}
|
|
1515
|
-
return false;
|
|
1516
|
-
}),
|
|
1517
|
-
properties: yup.object().test("properties-structure", "Invalid property set at ${path}", function(properties) {
|
|
1518
|
-
const action = getActionFromProvider(this.options.parent.action);
|
|
1519
|
-
const hasNoProperties = isEmpty(properties) || isNil(properties);
|
|
1520
|
-
if (!has("options.applyToProperties", action)) {
|
|
1521
|
-
return hasNoProperties;
|
|
1522
|
-
}
|
|
1523
|
-
if (hasNoProperties) {
|
|
1524
|
-
return true;
|
|
1525
|
-
}
|
|
1526
|
-
const { applyToProperties } = action.options;
|
|
1527
|
-
if (!isArray(applyToProperties)) {
|
|
1528
|
-
return false;
|
|
1529
|
-
}
|
|
1530
|
-
return Object.keys(properties).every((property) => applyToProperties.includes(property));
|
|
1531
|
-
}).test(
|
|
1532
|
-
"fields-property",
|
|
1533
|
-
"Invalid fields property at ${path}",
|
|
1534
|
-
async function(properties = {}) {
|
|
1535
|
-
const action = getActionFromProvider(this.options.parent.action);
|
|
1536
|
-
if (!action || !properties) {
|
|
1537
|
-
return true;
|
|
1538
|
-
}
|
|
1539
|
-
if (!actionDomain.appliesToProperty("fields", action)) {
|
|
1540
|
-
return true;
|
|
1541
|
-
}
|
|
1542
|
-
try {
|
|
1543
|
-
await fieldsPropertyValidation(action).validate(properties.fields, {
|
|
1544
|
-
strict: true,
|
|
1545
|
-
abortEarly: false
|
|
1546
|
-
});
|
|
1547
|
-
return true;
|
|
1548
|
-
} catch (e) {
|
|
1549
|
-
throw this.createError({
|
|
1550
|
-
message: e.message,
|
|
1551
|
-
path: `${this.path}.fields`
|
|
1552
|
-
});
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
),
|
|
1556
|
-
conditions: yup.array().of(yup.string())
|
|
1557
|
-
}).noUnknown();
|
|
1558
|
-
const updatePermissions = yup.object().shape({
|
|
1559
|
-
permissions: yup.array().required().of(permission).test(
|
|
1560
|
-
"duplicated-permissions",
|
|
1561
|
-
"Some permissions are duplicated (same action and subject)",
|
|
1562
|
-
checkNoDuplicatedPermissions
|
|
1563
|
-
)
|
|
1564
|
-
}).required().noUnknown();
|
|
1565
|
-
const validators = {
|
|
1566
|
-
email,
|
|
1567
|
-
firstname,
|
|
1568
|
-
lastname,
|
|
1569
|
-
username,
|
|
1570
|
-
password,
|
|
1571
|
-
roles,
|
|
1572
|
-
isAPluginName,
|
|
1573
|
-
arrayOfConditionNames,
|
|
1574
|
-
permission,
|
|
1575
|
-
updatePermissions
|
|
1576
|
-
};
|
|
1577
|
-
const userCreationSchema = yup.object().shape({
|
|
1578
|
-
email: validators.email.required(),
|
|
1579
|
-
firstname: validators.firstname.required(),
|
|
1580
|
-
lastname: validators.lastname,
|
|
1581
|
-
roles: validators.roles.min(1),
|
|
1582
|
-
preferedLanguage: yup.string().nullable()
|
|
1583
|
-
}).noUnknown();
|
|
1584
|
-
const profileUpdateSchema = yup.object().shape({
|
|
1585
|
-
email: validators.email.notNull(),
|
|
1586
|
-
firstname: validators.firstname.notNull(),
|
|
1587
|
-
lastname: validators.lastname.nullable(),
|
|
1588
|
-
username: validators.username.nullable(),
|
|
1589
|
-
password: validators.password.notNull(),
|
|
1590
|
-
currentPassword: yup.string().when(
|
|
1591
|
-
"password",
|
|
1592
|
-
(password2, schema) => !isUndefined(password2) ? schema.required() : schema
|
|
1593
|
-
).notNull(),
|
|
1594
|
-
preferedLanguage: yup.string().nullable()
|
|
1595
|
-
}).noUnknown();
|
|
1596
|
-
const userUpdateSchema = yup.object().shape({
|
|
1597
|
-
email: validators.email.notNull(),
|
|
1598
|
-
firstname: validators.firstname.notNull(),
|
|
1599
|
-
lastname: validators.lastname.nullable(),
|
|
1600
|
-
username: validators.username.nullable(),
|
|
1601
|
-
password: validators.password.notNull(),
|
|
1602
|
-
isActive: yup.bool().notNull(),
|
|
1603
|
-
roles: validators.roles.min(1).notNull()
|
|
1604
|
-
}).noUnknown();
|
|
1605
|
-
const usersDeleteSchema = yup.object().shape({
|
|
1606
|
-
ids: yup.array().of(yup.strapiID()).min(1).required()
|
|
1607
|
-
}).noUnknown();
|
|
1608
|
-
validateYupSchema(userCreationSchema);
|
|
1609
|
-
validateYupSchema(profileUpdateSchema);
|
|
1610
|
-
const validateUserUpdateInput = validateYupSchema(userUpdateSchema);
|
|
1611
|
-
validateYupSchema(usersDeleteSchema);
|
|
1612
|
-
const schemas = {
|
|
1613
|
-
userCreationSchema,
|
|
1614
|
-
usersDeleteSchema,
|
|
1615
|
-
userUpdateSchema
|
|
1616
|
-
};
|
|
1617
|
-
const ssoUserCreationInputExtension = yup.object().shape({
|
|
1618
|
-
useSSORegistration: yup.boolean()
|
|
1619
|
-
}).noUnknown();
|
|
1620
|
-
const validateUserCreationInput = (data) => {
|
|
1621
|
-
let schema = schemas.userCreationSchema;
|
|
1622
|
-
if (strapi.ee.features.isEnabled("sso")) {
|
|
1623
|
-
schema = schema.concat(ssoUserCreationInputExtension);
|
|
1624
|
-
}
|
|
1625
|
-
return validateYupSchema(schema)(data);
|
|
1626
|
-
};
|
|
1627
|
-
const { ApplicationError, ForbiddenError } = errors;
|
|
1628
|
-
const pickUserCreationAttributes = pick(["firstname", "lastname", "email", "roles"]);
|
|
1629
|
-
const hasAdminSeatsAvaialble = async () => {
|
|
1630
|
-
if (!strapi.EE) {
|
|
1631
|
-
return true;
|
|
1632
|
-
}
|
|
1633
|
-
const permittedSeats = strapi.ee.seats;
|
|
1634
|
-
if (isNil(permittedSeats)) {
|
|
1635
|
-
return true;
|
|
1636
|
-
}
|
|
1637
|
-
const userCount = await strapi.service("admin::user").getCurrentActiveUserCount();
|
|
1638
|
-
if (userCount < permittedSeats) {
|
|
1639
|
-
return true;
|
|
1640
|
-
}
|
|
1641
|
-
};
|
|
1642
|
-
const user = {
|
|
1643
|
-
async create(ctx) {
|
|
1644
|
-
if (!await hasAdminSeatsAvaialble()) {
|
|
1645
|
-
throw new ForbiddenError("License seat limit reached. You cannot create a new user");
|
|
1646
|
-
}
|
|
1647
|
-
const { body } = ctx.request;
|
|
1648
|
-
const cleanData = { ...body, email: _.get(body, `email`, ``).toLowerCase() };
|
|
1649
|
-
await validateUserCreationInput(cleanData);
|
|
1650
|
-
const attributes = pickUserCreationAttributes(cleanData);
|
|
1651
|
-
const { useSSORegistration } = cleanData;
|
|
1652
|
-
const userAlreadyExists = await getService("user").exists({ email: attributes.email });
|
|
1653
|
-
if (userAlreadyExists) {
|
|
1654
|
-
throw new ApplicationError("Email already taken");
|
|
1655
|
-
}
|
|
1656
|
-
if (useSSORegistration) {
|
|
1657
|
-
Object.assign(attributes, { registrationToken: null, isActive: true });
|
|
1658
|
-
}
|
|
1659
|
-
const createdUser = await getService("user").create(attributes);
|
|
1660
|
-
const userInfo = getService("user").sanitizeUser(createdUser);
|
|
1661
|
-
Object.assign(userInfo, { registrationToken: createdUser.registrationToken });
|
|
1662
|
-
ctx.created({ data: userInfo });
|
|
1663
|
-
},
|
|
1664
|
-
async update(ctx) {
|
|
1665
|
-
const { id } = ctx.params;
|
|
1666
|
-
const { body: input } = ctx.request;
|
|
1667
|
-
await validateUserUpdateInput(input);
|
|
1668
|
-
if (_.has(input, "email")) {
|
|
1669
|
-
const uniqueEmailCheck = await getService("user").exists({
|
|
1670
|
-
id: { $ne: id },
|
|
1671
|
-
email: input.email
|
|
1672
|
-
});
|
|
1673
|
-
if (uniqueEmailCheck) {
|
|
1674
|
-
throw new ApplicationError("A user with this email address already exists");
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
const user2 = await getService("user").findOne(id, null);
|
|
1678
|
-
if (!await hasAdminSeatsAvaialble() && !user2.isActive && input.isActive) {
|
|
1679
|
-
throw new ForbiddenError("License seat limit reached. You cannot active this user");
|
|
1680
|
-
}
|
|
1681
|
-
const updatedUser = await getService("user").updateById(id, input);
|
|
1682
|
-
if (!updatedUser) {
|
|
1683
|
-
return ctx.notFound("User does not exist");
|
|
1684
|
-
}
|
|
1685
|
-
ctx.body = {
|
|
1686
|
-
data: getService("user").sanitizeUser(updatedUser)
|
|
1687
|
-
};
|
|
1688
|
-
},
|
|
1689
|
-
async isSSOLocked(ctx) {
|
|
1690
|
-
const { user: user2 } = ctx.state;
|
|
1691
|
-
const isSSOLocked = await isSsoLocked(user2);
|
|
1692
|
-
ctx.body = {
|
|
1693
|
-
data: {
|
|
1694
|
-
isSSOLocked
|
|
1695
|
-
}
|
|
1696
|
-
};
|
|
1697
|
-
}
|
|
1698
|
-
};
|
|
1699
|
-
const admin = {
|
|
1700
|
-
// NOTE: Overrides CE admin controller
|
|
1701
|
-
async getProjectType() {
|
|
1702
|
-
const flags = strapi.config.get("admin.flags", {});
|
|
1703
|
-
try {
|
|
1704
|
-
return { data: { isEE: strapi.EE, features: strapi.ee.features.list(), flags } };
|
|
1705
|
-
} catch (err) {
|
|
1706
|
-
return { data: { isEE: false, features: [], flags } };
|
|
1707
|
-
}
|
|
1708
|
-
},
|
|
1709
|
-
async licenseLimitInformation() {
|
|
1710
|
-
const permittedSeats = strapi.ee.seats;
|
|
1711
|
-
let shouldNotify = false;
|
|
1712
|
-
let licenseLimitStatus = null;
|
|
1713
|
-
let enforcementUserCount;
|
|
1714
|
-
const currentActiveUserCount = await getService("user").getCurrentActiveUserCount();
|
|
1715
|
-
const eeDisabledUsers = await getService("seat-enforcement").getDisabledUserList();
|
|
1716
|
-
if (eeDisabledUsers) {
|
|
1717
|
-
enforcementUserCount = currentActiveUserCount + eeDisabledUsers.length;
|
|
1718
|
-
} else {
|
|
1719
|
-
enforcementUserCount = currentActiveUserCount;
|
|
1720
|
-
}
|
|
1721
|
-
if (!isNil(permittedSeats) && enforcementUserCount > permittedSeats) {
|
|
1722
|
-
shouldNotify = true;
|
|
1723
|
-
licenseLimitStatus = "OVER_LIMIT";
|
|
1724
|
-
}
|
|
1725
|
-
if (!isNil(permittedSeats) && enforcementUserCount === permittedSeats) {
|
|
1726
|
-
shouldNotify = true;
|
|
1727
|
-
licenseLimitStatus = "AT_LIMIT";
|
|
1728
|
-
}
|
|
1729
|
-
const data = {
|
|
1730
|
-
enforcementUserCount,
|
|
1731
|
-
currentActiveUserCount,
|
|
1732
|
-
permittedSeats,
|
|
1733
|
-
shouldNotify,
|
|
1734
|
-
shouldStopCreate: isNil(permittedSeats) ? false : currentActiveUserCount >= permittedSeats,
|
|
1735
|
-
licenseLimitStatus,
|
|
1736
|
-
isHostedOnStrapiCloud: env("STRAPI_HOSTING", null) === "strapi.cloud",
|
|
1737
|
-
features: strapi.ee.features.list() ?? []
|
|
1738
|
-
};
|
|
1739
|
-
return { data };
|
|
1740
|
-
}
|
|
1741
|
-
};
|
|
1742
|
-
const controllers = {
|
|
1743
|
-
authentication,
|
|
1744
|
-
role,
|
|
1745
|
-
user,
|
|
1746
|
-
admin
|
|
1747
|
-
};
|
|
1748
|
-
const enableFeatureMiddleware = (featureName) => (ctx, next) => {
|
|
1749
|
-
if (strapi.ee.features.isEnabled(featureName)) {
|
|
1750
|
-
return next();
|
|
1751
|
-
}
|
|
1752
|
-
ctx.status = 404;
|
|
1753
|
-
};
|
|
1754
|
-
const sso = {
|
|
1755
|
-
type: "admin",
|
|
1756
|
-
routes: [
|
|
1757
|
-
{
|
|
1758
|
-
method: "GET",
|
|
1759
|
-
path: "/providers",
|
|
1760
|
-
handler: "authentication.getProviders",
|
|
1761
|
-
config: {
|
|
1762
|
-
middlewares: [enableFeatureMiddleware("sso")],
|
|
1763
|
-
auth: false
|
|
1764
|
-
}
|
|
1765
|
-
},
|
|
1766
|
-
{
|
|
1767
|
-
method: "GET",
|
|
1768
|
-
path: "/connect/:provider",
|
|
1769
|
-
handler: "authentication.providerLogin",
|
|
1770
|
-
config: {
|
|
1771
|
-
middlewares: [enableFeatureMiddleware("sso")],
|
|
1772
|
-
auth: false
|
|
1773
|
-
}
|
|
1774
|
-
},
|
|
1775
|
-
{
|
|
1776
|
-
method: "POST",
|
|
1777
|
-
path: "/connect/:provider",
|
|
1778
|
-
handler: "authentication.providerLogin",
|
|
1779
|
-
config: {
|
|
1780
|
-
middlewares: [enableFeatureMiddleware("sso")],
|
|
1781
|
-
auth: false
|
|
1782
|
-
}
|
|
1783
|
-
},
|
|
1784
|
-
{
|
|
1785
|
-
method: "GET",
|
|
1786
|
-
path: "/providers/options",
|
|
1787
|
-
handler: "authentication.getProviderLoginOptions",
|
|
1788
|
-
config: {
|
|
1789
|
-
middlewares: [enableFeatureMiddleware("sso")],
|
|
1790
|
-
policies: [
|
|
1791
|
-
"admin::isAuthenticatedAdmin",
|
|
1792
|
-
{ name: "admin::hasPermissions", config: { actions: ["admin::provider-login.read"] } }
|
|
1793
|
-
]
|
|
1794
|
-
}
|
|
1795
|
-
},
|
|
1796
|
-
{
|
|
1797
|
-
method: "PUT",
|
|
1798
|
-
path: "/providers/options",
|
|
1799
|
-
handler: "authentication.updateProviderLoginOptions",
|
|
1800
|
-
config: {
|
|
1801
|
-
middlewares: [enableFeatureMiddleware("sso")],
|
|
1802
|
-
policies: [
|
|
1803
|
-
"admin::isAuthenticatedAdmin",
|
|
1804
|
-
{ name: "admin::hasPermissions", config: { actions: ["admin::provider-login.update"] } }
|
|
1805
|
-
]
|
|
1806
|
-
}
|
|
1807
|
-
},
|
|
1808
|
-
{
|
|
1809
|
-
method: "GET",
|
|
1810
|
-
path: "/providers/isSSOLocked",
|
|
1811
|
-
handler: "user.isSSOLocked",
|
|
1812
|
-
config: {
|
|
1813
|
-
middlewares: [enableFeatureMiddleware("sso")],
|
|
1814
|
-
policies: ["admin::isAuthenticatedAdmin"]
|
|
1815
|
-
}
|
|
1816
|
-
}
|
|
1817
|
-
]
|
|
1818
|
-
};
|
|
1819
|
-
const licenseLimit = {
|
|
1820
|
-
type: "admin",
|
|
1821
|
-
routes: [
|
|
1822
|
-
// License limit infos
|
|
1823
|
-
{
|
|
1824
|
-
method: "GET",
|
|
1825
|
-
path: "/license-limit-information",
|
|
1826
|
-
handler: "admin.licenseLimitInformation",
|
|
1827
|
-
config: {
|
|
1828
|
-
policies: [
|
|
1829
|
-
"admin::isAuthenticatedAdmin",
|
|
1830
|
-
{
|
|
1831
|
-
name: "admin::hasPermissions",
|
|
1832
|
-
config: {
|
|
1833
|
-
actions: [
|
|
1834
|
-
"admin::users.create",
|
|
1835
|
-
"admin::users.read",
|
|
1836
|
-
"admin::users.update",
|
|
1837
|
-
"admin::users.delete"
|
|
1838
|
-
]
|
|
1839
|
-
}
|
|
1840
|
-
}
|
|
1841
|
-
]
|
|
1842
|
-
}
|
|
1843
|
-
}
|
|
1844
|
-
]
|
|
1845
|
-
};
|
|
1846
|
-
const routes = {
|
|
1847
|
-
sso,
|
|
1848
|
-
"license-limit": licenseLimit
|
|
1849
|
-
};
|
|
1850
|
-
const auditLogsRoutes = {
|
|
1851
|
-
type: "admin",
|
|
1852
|
-
routes: [
|
|
1853
|
-
{
|
|
1854
|
-
method: "GET",
|
|
1855
|
-
path: "/audit-logs",
|
|
1856
|
-
handler: "audit-logs.findMany",
|
|
1857
|
-
config: {
|
|
1858
|
-
middlewares: [enableFeatureMiddleware("audit-logs")],
|
|
1859
|
-
policies: [
|
|
1860
|
-
"admin::isAuthenticatedAdmin",
|
|
1861
|
-
{
|
|
1862
|
-
name: "admin::hasPermissions",
|
|
1863
|
-
config: {
|
|
1864
|
-
actions: ["admin::audit-logs.read"]
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1867
|
-
]
|
|
1868
|
-
}
|
|
1869
|
-
},
|
|
1870
|
-
{
|
|
1871
|
-
method: "GET",
|
|
1872
|
-
path: "/audit-logs/:id",
|
|
1873
|
-
handler: "audit-logs.findOne",
|
|
1874
|
-
config: {
|
|
1875
|
-
middlewares: [enableFeatureMiddleware("audit-logs")],
|
|
1876
|
-
policies: [
|
|
1877
|
-
"admin::isAuthenticatedAdmin",
|
|
1878
|
-
{
|
|
1879
|
-
name: "admin::hasPermissions",
|
|
1880
|
-
config: {
|
|
1881
|
-
actions: ["admin::audit-logs.read"]
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
]
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
]
|
|
1888
|
-
};
|
|
1889
|
-
const ALLOWED_SORT_STRINGS = ["action:ASC", "action:DESC", "date:ASC", "date:DESC"];
|
|
1890
|
-
const validateFindManySchema = yup.object().shape({
|
|
1891
|
-
page: yup.number().integer().min(1),
|
|
1892
|
-
pageSize: yup.number().integer().min(1).max(100),
|
|
1893
|
-
sort: yup.mixed().oneOf(ALLOWED_SORT_STRINGS)
|
|
1894
|
-
}).required();
|
|
1895
|
-
const validateFindMany = validateYupSchema(validateFindManySchema, { strict: false });
|
|
1896
|
-
const auditLogsController = {
|
|
1897
|
-
async findMany(ctx) {
|
|
1898
|
-
const { query } = ctx.request;
|
|
1899
|
-
await validateFindMany(query);
|
|
1900
|
-
const auditLogs = strapi.get("audit-logs");
|
|
1901
|
-
const body = await auditLogs.findMany(query);
|
|
1902
|
-
ctx.body = body;
|
|
1903
|
-
},
|
|
1904
|
-
async findOne(ctx) {
|
|
1905
|
-
const { id } = ctx.params;
|
|
1906
|
-
const auditLogs = strapi.get("audit-logs");
|
|
1907
|
-
const body = await auditLogs.findOne(id);
|
|
1908
|
-
ctx.body = body;
|
|
1909
|
-
strapi.telemetry.send("didWatchAnAuditLog");
|
|
1910
|
-
}
|
|
1911
|
-
};
|
|
1912
|
-
const getSanitizedUser = (user2) => {
|
|
1913
|
-
let displayName = user2.email;
|
|
1914
|
-
if (user2.username) {
|
|
1915
|
-
displayName = user2.username;
|
|
1916
|
-
} else if (user2.firstname && user2.lastname) {
|
|
1917
|
-
displayName = `${user2.firstname} ${user2.lastname}`;
|
|
1918
|
-
}
|
|
1919
|
-
return {
|
|
1920
|
-
id: user2.id,
|
|
1921
|
-
email: user2.email,
|
|
1922
|
-
displayName
|
|
1923
|
-
};
|
|
1924
|
-
};
|
|
1925
|
-
const createAuditLogsService = (strapi2) => {
|
|
1926
|
-
return {
|
|
1927
|
-
async saveEvent(event) {
|
|
1928
|
-
const { userId, ...rest } = event;
|
|
1929
|
-
const auditLog2 = { ...rest, user: userId };
|
|
1930
|
-
await strapi2.db?.query("admin::audit-log").create({ data: auditLog2 });
|
|
1931
|
-
return this;
|
|
1932
|
-
},
|
|
1933
|
-
async findMany(query) {
|
|
1934
|
-
const { results, pagination } = await strapi2.db?.query("admin::audit-log").findPage({
|
|
1935
|
-
populate: ["user"],
|
|
1936
|
-
select: ["action", "date", "payload"],
|
|
1937
|
-
...strapi2.get("query-params").transform("admin::audit-log", query)
|
|
1938
|
-
});
|
|
1939
|
-
const sanitizedResults = results.map((result) => {
|
|
1940
|
-
const { user: user2, ...rest } = result;
|
|
1941
|
-
return {
|
|
1942
|
-
...rest,
|
|
1943
|
-
user: user2 ? getSanitizedUser(user2) : null
|
|
1944
|
-
};
|
|
1945
|
-
});
|
|
1946
|
-
return {
|
|
1947
|
-
results: sanitizedResults,
|
|
1948
|
-
pagination
|
|
1949
|
-
};
|
|
1950
|
-
},
|
|
1951
|
-
async findOne(id) {
|
|
1952
|
-
const result = await strapi2.db?.query("admin::audit-log").findOne({
|
|
1953
|
-
where: { id },
|
|
1954
|
-
populate: ["user"],
|
|
1955
|
-
select: ["action", "date", "payload"]
|
|
1956
|
-
});
|
|
1957
|
-
if (!result) {
|
|
1958
|
-
return null;
|
|
1959
|
-
}
|
|
1960
|
-
const { user: user2, ...rest } = result;
|
|
1961
|
-
return {
|
|
1962
|
-
...rest,
|
|
1963
|
-
user: user2 ? getSanitizedUser(user2) : null
|
|
1964
|
-
};
|
|
1965
|
-
},
|
|
1966
|
-
deleteExpiredEvents(expirationDate) {
|
|
1967
|
-
return strapi2.db?.query("admin::audit-log").deleteMany({
|
|
1968
|
-
where: {
|
|
1969
|
-
date: {
|
|
1970
|
-
$lt: expirationDate.toISOString()
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
1973
|
-
});
|
|
1974
|
-
}
|
|
1975
|
-
};
|
|
1976
|
-
};
|
|
1977
|
-
const DEFAULT_RETENTION_DAYS = 90;
|
|
1978
|
-
const defaultEvents = [
|
|
1979
|
-
"entry.create",
|
|
1980
|
-
"entry.update",
|
|
1981
|
-
"entry.delete",
|
|
1982
|
-
"entry.publish",
|
|
1983
|
-
"entry.unpublish",
|
|
1984
|
-
"media.create",
|
|
1985
|
-
"media.update",
|
|
1986
|
-
"media.delete",
|
|
1987
|
-
"media-folder.create",
|
|
1988
|
-
"media-folder.update",
|
|
1989
|
-
"media-folder.delete",
|
|
1990
|
-
"user.create",
|
|
1991
|
-
"user.update",
|
|
1992
|
-
"user.delete",
|
|
1993
|
-
"admin.auth.success",
|
|
1994
|
-
"admin.logout",
|
|
1995
|
-
"content-type.create",
|
|
1996
|
-
"content-type.update",
|
|
1997
|
-
"content-type.delete",
|
|
1998
|
-
"component.create",
|
|
1999
|
-
"component.update",
|
|
2000
|
-
"component.delete",
|
|
2001
|
-
"role.create",
|
|
2002
|
-
"role.update",
|
|
2003
|
-
"role.delete",
|
|
2004
|
-
"permission.create",
|
|
2005
|
-
"permission.update",
|
|
2006
|
-
"permission.delete"
|
|
2007
|
-
];
|
|
2008
|
-
const getEventMap = (defaultEvents2) => {
|
|
2009
|
-
const getDefaultPayload = (...args) => args[0];
|
|
2010
|
-
return defaultEvents2.reduce((acc, event) => {
|
|
2011
|
-
acc[event] = getDefaultPayload;
|
|
2012
|
-
return acc;
|
|
2013
|
-
}, {});
|
|
2014
|
-
};
|
|
2015
|
-
const getRetentionDays = (strapi2) => {
|
|
2016
|
-
const featureConfig = strapi2.ee.features.get("audit-logs");
|
|
2017
|
-
const licenseRetentionDays = typeof featureConfig === "object" && featureConfig?.options.retentionDays;
|
|
2018
|
-
const userRetentionDays = strapi2.config.get("admin.auditLogs.retentionDays");
|
|
2019
|
-
if (licenseRetentionDays == null) {
|
|
2020
|
-
return userRetentionDays ?? DEFAULT_RETENTION_DAYS;
|
|
2021
|
-
}
|
|
2022
|
-
if (userRetentionDays && userRetentionDays < licenseRetentionDays) {
|
|
2023
|
-
return userRetentionDays;
|
|
2024
|
-
}
|
|
2025
|
-
return licenseRetentionDays;
|
|
2026
|
-
};
|
|
2027
|
-
const createAuditLogsLifecycleService = (strapi2) => {
|
|
2028
|
-
const state = {};
|
|
2029
|
-
const auditLogsService = strapi2.get("audit-logs");
|
|
2030
|
-
const eventMap = getEventMap(defaultEvents);
|
|
2031
|
-
const processEvent = (name2, ...args) => {
|
|
2032
|
-
const requestState = strapi2.requestContext.get()?.state;
|
|
2033
|
-
const isUsingAdminAuth = requestState?.route.info.type === "admin";
|
|
2034
|
-
const user2 = requestState?.user;
|
|
2035
|
-
if (!isUsingAdminAuth || !user2) {
|
|
2036
|
-
return null;
|
|
2037
|
-
}
|
|
2038
|
-
const getPayload = eventMap[name2];
|
|
2039
|
-
if (!getPayload) {
|
|
2040
|
-
return null;
|
|
2041
|
-
}
|
|
2042
|
-
const ignoredUids = ["plugin::upload.file", "plugin::upload.folder"];
|
|
2043
|
-
if (ignoredUids.includes(args[0]?.uid)) {
|
|
2044
|
-
return null;
|
|
2045
|
-
}
|
|
2046
|
-
return {
|
|
2047
|
-
action: name2,
|
|
2048
|
-
date: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2049
|
-
payload: getPayload(...args) || {},
|
|
2050
|
-
userId: user2.id
|
|
2051
|
-
};
|
|
2052
|
-
};
|
|
2053
|
-
const handleEvent = async (name2, ...args) => {
|
|
2054
|
-
const processedEvent = processEvent(name2, ...args);
|
|
2055
|
-
if (processedEvent) {
|
|
2056
|
-
await auditLogsService.saveEvent(processedEvent);
|
|
2057
|
-
}
|
|
2058
|
-
};
|
|
2059
|
-
return {
|
|
2060
|
-
async register() {
|
|
2061
|
-
if (!state.eeEnableUnsubscribe) {
|
|
2062
|
-
state.eeEnableUnsubscribe = strapi2.eventHub.on("ee.enable", () => {
|
|
2063
|
-
this.destroy();
|
|
2064
|
-
this.register();
|
|
2065
|
-
});
|
|
2066
|
-
}
|
|
2067
|
-
if (!state.eeUpdateUnsubscribe) {
|
|
2068
|
-
state.eeUpdateUnsubscribe = strapi2.eventHub.on("ee.update", () => {
|
|
2069
|
-
this.destroy();
|
|
2070
|
-
this.register();
|
|
2071
|
-
});
|
|
2072
|
-
}
|
|
2073
|
-
state.eeDisableUnsubscribe = strapi2.eventHub.on("ee.disable", () => {
|
|
2074
|
-
this.destroy();
|
|
2075
|
-
});
|
|
2076
|
-
if (!strapi2.ee.features.isEnabled("audit-logs")) {
|
|
2077
|
-
return this;
|
|
2078
|
-
}
|
|
2079
|
-
state.eventHubUnsubscribe = strapi2.eventHub.subscribe(handleEvent);
|
|
2080
|
-
const retentionDays = getRetentionDays(strapi2);
|
|
2081
|
-
state.deleteExpiredJob = scheduleJob("0 0 * * *", () => {
|
|
2082
|
-
const expirationDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1e3);
|
|
2083
|
-
auditLogsService.deleteExpiredEvents(expirationDate);
|
|
2084
|
-
});
|
|
2085
|
-
return this;
|
|
2086
|
-
},
|
|
2087
|
-
unsubscribe() {
|
|
2088
|
-
if (state.eeDisableUnsubscribe) {
|
|
2089
|
-
state.eeDisableUnsubscribe();
|
|
2090
|
-
}
|
|
2091
|
-
if (state.eventHubUnsubscribe) {
|
|
2092
|
-
state.eventHubUnsubscribe();
|
|
2093
|
-
}
|
|
2094
|
-
if (state.deleteExpiredJob) {
|
|
2095
|
-
state.deleteExpiredJob.cancel();
|
|
2096
|
-
}
|
|
2097
|
-
return this;
|
|
2098
|
-
},
|
|
2099
|
-
destroy() {
|
|
2100
|
-
return this.unsubscribe();
|
|
2101
|
-
}
|
|
2102
|
-
};
|
|
2103
|
-
};
|
|
2104
|
-
const auditLog = {
|
|
2105
|
-
schema: {
|
|
2106
|
-
kind: "collectionType",
|
|
2107
|
-
collectionName: "strapi_audit_logs",
|
|
2108
|
-
info: {
|
|
2109
|
-
singularName: "audit-log",
|
|
2110
|
-
pluralName: "audit-logs",
|
|
2111
|
-
displayName: "Audit Log"
|
|
2112
|
-
},
|
|
2113
|
-
options: {
|
|
2114
|
-
timestamps: false
|
|
2115
|
-
},
|
|
2116
|
-
pluginOptions: {
|
|
2117
|
-
"content-manager": {
|
|
2118
|
-
visible: false
|
|
2119
|
-
},
|
|
2120
|
-
"content-type-builder": {
|
|
2121
|
-
visible: false
|
|
2122
|
-
}
|
|
2123
|
-
},
|
|
2124
|
-
attributes: {
|
|
2125
|
-
action: {
|
|
2126
|
-
type: "string",
|
|
2127
|
-
required: true
|
|
2128
|
-
},
|
|
2129
|
-
date: {
|
|
2130
|
-
type: "datetime",
|
|
2131
|
-
required: true
|
|
2132
|
-
},
|
|
2133
|
-
user: {
|
|
2134
|
-
type: "relation",
|
|
2135
|
-
relation: "oneToOne",
|
|
2136
|
-
target: "admin::user"
|
|
2137
|
-
},
|
|
2138
|
-
payload: {
|
|
2139
|
-
type: "json"
|
|
2140
|
-
}
|
|
2141
|
-
}
|
|
2142
|
-
}
|
|
2143
|
-
};
|
|
2144
|
-
const getAdminEE = () => {
|
|
2145
|
-
const eeAdmin = {
|
|
2146
|
-
register,
|
|
2147
|
-
bootstrap,
|
|
2148
|
-
destroy,
|
|
2149
|
-
contentTypes: {
|
|
2150
|
-
// Always register the audit-log content type to prevent data loss
|
|
2151
|
-
"audit-log": auditLog,
|
|
2152
|
-
...adminContentTypes
|
|
2153
|
-
},
|
|
2154
|
-
services,
|
|
2155
|
-
controllers,
|
|
2156
|
-
routes
|
|
2157
|
-
};
|
|
2158
|
-
if (strapi.config.get("admin.auditLogs.enabled", true) && strapi.ee.features.isEnabled("audit-logs")) {
|
|
2159
|
-
return {
|
|
2160
|
-
...eeAdmin,
|
|
2161
|
-
controllers: {
|
|
2162
|
-
...eeAdmin.controllers,
|
|
2163
|
-
"audit-logs": auditLogsController
|
|
2164
|
-
},
|
|
2165
|
-
routes: {
|
|
2166
|
-
...eeAdmin.routes,
|
|
2167
|
-
"audit-logs": auditLogsRoutes
|
|
2168
|
-
},
|
|
2169
|
-
async register({ strapi: strapi2 }) {
|
|
2170
|
-
await eeAdmin.register({ strapi: strapi2 });
|
|
2171
|
-
strapi2.add("audit-logs", createAuditLogsService(strapi2));
|
|
2172
|
-
const auditLogsLifecycle = createAuditLogsLifecycleService(strapi2);
|
|
2173
|
-
strapi2.add("audit-logs-lifecycle", auditLogsLifecycle);
|
|
2174
|
-
await auditLogsLifecycle.register();
|
|
2175
|
-
},
|
|
2176
|
-
async destroy({ strapi: strapi2 }) {
|
|
2177
|
-
strapi2.get("audit-logs-lifecycle").destroy();
|
|
2178
|
-
await eeAdmin.destroy({ strapi: strapi2 });
|
|
2179
|
-
}
|
|
2180
|
-
};
|
|
2181
|
-
}
|
|
2182
|
-
return eeAdmin;
|
|
2183
|
-
};
|
|
2184
|
-
const index = getAdminEE();
|
|
2185
|
-
export {
|
|
2186
|
-
index as default
|
|
2187
|
-
};
|
|
2188
|
-
//# sourceMappingURL=index.mjs.map
|