@strapi/admin 5.43.0 → 5.45.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.
Files changed (384) hide show
  1. package/dist/admin/admin/src/StrapiApp.js +17 -4
  2. package/dist/admin/admin/src/StrapiApp.js.map +1 -1
  3. package/dist/admin/admin/src/StrapiApp.mjs +18 -5
  4. package/dist/admin/admin/src/StrapiApp.mjs.map +1 -1
  5. package/dist/admin/admin/src/components/Form.js +18 -8
  6. package/dist/admin/admin/src/components/Form.js.map +1 -1
  7. package/dist/admin/admin/src/components/Form.mjs +18 -8
  8. package/dist/admin/admin/src/components/Form.mjs.map +1 -1
  9. package/dist/admin/admin/src/components/Layouts/Layout.js +1 -0
  10. package/dist/admin/admin/src/components/Layouts/Layout.js.map +1 -1
  11. package/dist/admin/admin/src/components/Layouts/Layout.mjs +1 -0
  12. package/dist/admin/admin/src/components/Layouts/Layout.mjs.map +1 -1
  13. package/dist/admin/admin/src/components/Table.js.map +1 -1
  14. package/dist/admin/admin/src/components/Table.mjs.map +1 -1
  15. package/dist/admin/admin/src/components/Widgets.js +52 -0
  16. package/dist/admin/admin/src/components/Widgets.js.map +1 -1
  17. package/dist/admin/admin/src/components/Widgets.mjs +54 -3
  18. package/dist/admin/admin/src/components/Widgets.mjs.map +1 -1
  19. package/dist/admin/admin/src/constants.js +49 -0
  20. package/dist/admin/admin/src/constants.js.map +1 -1
  21. package/dist/admin/admin/src/constants.mjs +49 -0
  22. package/dist/admin/admin/src/constants.mjs.map +1 -1
  23. package/dist/admin/admin/src/core/apis/router.js +4 -4
  24. package/dist/admin/admin/src/core/apis/router.js.map +1 -1
  25. package/dist/admin/admin/src/core/apis/router.mjs +4 -4
  26. package/dist/admin/admin/src/core/apis/router.mjs.map +1 -1
  27. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  28. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  29. package/dist/admin/admin/src/pages/Settings/{pages/ApiTokens/EditView/components → components/Tokens}/FormApiTokenContainer.js +48 -11
  30. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormApiTokenContainer.js.map +1 -0
  31. package/dist/admin/admin/src/pages/Settings/{pages/ApiTokens/EditView/components → components/Tokens}/FormApiTokenContainer.mjs +49 -12
  32. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormApiTokenContainer.mjs.map +1 -0
  33. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js +1 -1
  34. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.js.map +1 -1
  35. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs +1 -1
  36. package/dist/admin/admin/src/pages/Settings/components/Tokens/FormHead.mjs.map +1 -1
  37. package/dist/admin/admin/src/pages/Settings/components/Tokens/LifeSpanInput.js +1 -1
  38. package/dist/admin/admin/src/pages/Settings/components/Tokens/LifeSpanInput.js.map +1 -1
  39. package/dist/admin/admin/src/pages/Settings/components/Tokens/LifeSpanInput.mjs +1 -1
  40. package/dist/admin/admin/src/pages/Settings/components/Tokens/LifeSpanInput.mjs.map +1 -1
  41. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.js +21 -1
  42. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.js.map +1 -1
  43. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.mjs +21 -1
  44. package/dist/admin/admin/src/pages/Settings/components/Tokens/Table.mjs.map +1 -1
  45. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js +1 -1
  46. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.js.map +1 -1
  47. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs +1 -1
  48. package/dist/admin/admin/src/pages/Settings/components/Tokens/TokenBox.mjs.map +1 -1
  49. package/dist/admin/admin/src/pages/Settings/components/Tokens/constants.js +33 -0
  50. package/dist/admin/admin/src/pages/Settings/components/Tokens/constants.js.map +1 -1
  51. package/dist/admin/admin/src/pages/Settings/components/Tokens/constants.mjs +14 -1
  52. package/dist/admin/admin/src/pages/Settings/components/Tokens/constants.mjs.map +1 -1
  53. package/dist/admin/admin/src/pages/Settings/{pages/ApiTokens/EditView → components/Tokens}/utils/getDateOfExpiration.js +1 -1
  54. package/dist/admin/admin/src/pages/Settings/components/Tokens/utils/getDateOfExpiration.js.map +1 -0
  55. package/dist/admin/admin/src/pages/Settings/{pages/ApiTokens/EditView → components/Tokens}/utils/getDateOfExpiration.mjs +1 -1
  56. package/dist/admin/admin/src/pages/Settings/components/Tokens/utils/getDateOfExpiration.mjs.map +1 -0
  57. package/dist/admin/admin/src/pages/Settings/constants.js +182 -151
  58. package/dist/admin/admin/src/pages/Settings/constants.js.map +1 -1
  59. package/dist/admin/admin/src/pages/Settings/constants.mjs +182 -151
  60. package/dist/admin/admin/src/pages/Settings/constants.mjs.map +1 -1
  61. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/CreateView.js +17 -0
  62. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/CreateView.js.map +1 -0
  63. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/CreateView.mjs +15 -0
  64. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/CreateView.mjs.map +1 -0
  65. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/EditView/EditViewPage.js +314 -0
  66. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/EditView/EditViewPage.js.map +1 -0
  67. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/EditView/EditViewPage.mjs +292 -0
  68. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/EditView/EditViewPage.mjs.map +1 -0
  69. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/EditView/components/AdminPermissions.js +70 -0
  70. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/EditView/components/AdminPermissions.js.map +1 -0
  71. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/EditView/components/AdminPermissions.mjs +49 -0
  72. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/EditView/components/AdminPermissions.mjs.map +1 -0
  73. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/ListView.js +254 -0
  74. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/ListView.js.map +1 -0
  75. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/ListView.mjs +231 -0
  76. package/dist/admin/admin/src/pages/Settings/pages/AdminTokens/ListView.mjs.map +1 -0
  77. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js +42 -33
  78. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.js.map +1 -1
  79. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs +43 -34
  80. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/EditViewPage.mjs.map +1 -1
  81. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js +3 -2
  82. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.js.map +1 -1
  83. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs +3 -2
  84. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/ListView.mjs.map +1 -1
  85. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/CollapsePropertyMatrix.js +23 -12
  86. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/CollapsePropertyMatrix.js.map +1 -1
  87. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/CollapsePropertyMatrix.mjs +23 -12
  88. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/CollapsePropertyMatrix.mjs.map +1 -1
  89. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ConditionsModal.js +124 -35
  90. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ConditionsModal.js.map +1 -1
  91. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ConditionsModal.mjs +126 -37
  92. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ConditionsModal.mjs.map +1 -1
  93. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ContentTypeCollapses.js +24 -9
  94. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ContentTypeCollapses.js.map +1 -1
  95. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ContentTypeCollapses.mjs +24 -9
  96. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/ContentTypeCollapses.mjs.map +1 -1
  97. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/GlobalActions.js +5 -3
  98. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/GlobalActions.js.map +1 -1
  99. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/GlobalActions.mjs +5 -3
  100. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/GlobalActions.mjs.map +1 -1
  101. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/Permissions.js +171 -36
  102. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/Permissions.js.map +1 -1
  103. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/Permissions.mjs +172 -37
  104. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/Permissions.mjs.map +1 -1
  105. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.js +5 -3
  106. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.js.map +1 -1
  107. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.mjs +5 -3
  108. package/dist/admin/admin/src/pages/Settings/pages/Roles/components/PluginsAndSettings.mjs.map +1 -1
  109. package/dist/admin/admin/src/pages/Settings/pages/Roles/hooks/usePermissionsDataManager.js +59 -1
  110. package/dist/admin/admin/src/pages/Settings/pages/Roles/hooks/usePermissionsDataManager.js.map +1 -1
  111. package/dist/admin/admin/src/pages/Settings/pages/Roles/hooks/usePermissionsDataManager.mjs +40 -1
  112. package/dist/admin/admin/src/pages/Settings/pages/Roles/hooks/usePermissionsDataManager.mjs.map +1 -1
  113. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/createPermissionChecker.js +89 -0
  114. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/createPermissionChecker.js.map +1 -0
  115. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/createPermissionChecker.mjs +86 -0
  116. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/createPermissionChecker.mjs.map +1 -0
  117. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/updateValues.js +35 -9
  118. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/updateValues.js.map +1 -1
  119. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/updateValues.mjs +35 -10
  120. package/dist/admin/admin/src/pages/Settings/pages/Roles/utils/updateValues.mjs.map +1 -1
  121. package/dist/admin/admin/src/render.js +6 -3
  122. package/dist/admin/admin/src/render.js.map +1 -1
  123. package/dist/admin/admin/src/render.mjs +6 -3
  124. package/dist/admin/admin/src/render.mjs.map +1 -1
  125. package/dist/admin/admin/src/router.js +4 -4
  126. package/dist/admin/admin/src/router.js.map +1 -1
  127. package/dist/admin/admin/src/router.mjs +1 -1
  128. package/dist/admin/admin/src/router.mjs.map +1 -1
  129. package/dist/admin/admin/src/services/apiTokens.js +85 -2
  130. package/dist/admin/admin/src/services/apiTokens.js.map +1 -1
  131. package/dist/admin/admin/src/services/apiTokens.mjs +80 -3
  132. package/dist/admin/admin/src/services/apiTokens.mjs.map +1 -1
  133. package/dist/admin/admin/src/translations/ar.json.js +4 -1
  134. package/dist/admin/admin/src/translations/ar.json.js.map +1 -1
  135. package/dist/admin/admin/src/translations/ar.json.mjs +4 -1
  136. package/dist/admin/admin/src/translations/ar.json.mjs.map +1 -1
  137. package/dist/admin/admin/src/translations/cs.json.js +736 -13
  138. package/dist/admin/admin/src/translations/cs.json.js.map +1 -1
  139. package/dist/admin/admin/src/translations/cs.json.mjs +728 -14
  140. package/dist/admin/admin/src/translations/cs.json.mjs.map +1 -1
  141. package/dist/admin/admin/src/translations/de.json.js +4 -1
  142. package/dist/admin/admin/src/translations/de.json.js.map +1 -1
  143. package/dist/admin/admin/src/translations/de.json.mjs +4 -1
  144. package/dist/admin/admin/src/translations/de.json.mjs.map +1 -1
  145. package/dist/admin/admin/src/translations/en.json.js +20 -2
  146. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  147. package/dist/admin/admin/src/translations/en.json.mjs +20 -2
  148. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  149. package/dist/admin/admin/src/translations/es.json.js +4 -1
  150. package/dist/admin/admin/src/translations/es.json.js.map +1 -1
  151. package/dist/admin/admin/src/translations/es.json.mjs +4 -1
  152. package/dist/admin/admin/src/translations/es.json.mjs.map +1 -1
  153. package/dist/admin/admin/src/translations/fr.json.js +4 -1
  154. package/dist/admin/admin/src/translations/fr.json.js.map +1 -1
  155. package/dist/admin/admin/src/translations/fr.json.mjs +4 -1
  156. package/dist/admin/admin/src/translations/fr.json.mjs.map +1 -1
  157. package/dist/admin/admin/src/translations/it.json.js +4 -1
  158. package/dist/admin/admin/src/translations/it.json.js.map +1 -1
  159. package/dist/admin/admin/src/translations/it.json.mjs +4 -1
  160. package/dist/admin/admin/src/translations/it.json.mjs.map +1 -1
  161. package/dist/admin/admin/src/translations/ru.json.js +32 -19
  162. package/dist/admin/admin/src/translations/ru.json.js.map +1 -1
  163. package/dist/admin/admin/src/translations/ru.json.mjs +32 -19
  164. package/dist/admin/admin/src/translations/ru.json.mjs.map +1 -1
  165. package/dist/admin/admin/src/translations/zh-Hans.json.js +4 -1
  166. package/dist/admin/admin/src/translations/zh-Hans.json.js.map +1 -1
  167. package/dist/admin/admin/src/translations/zh-Hans.json.mjs +4 -1
  168. package/dist/admin/admin/src/translations/zh-Hans.json.mjs.map +1 -1
  169. package/dist/admin/admin/src/utils/getFetchClient.js +33 -4
  170. package/dist/admin/admin/src/utils/getFetchClient.js.map +1 -1
  171. package/dist/admin/admin/src/utils/getFetchClient.mjs +33 -4
  172. package/dist/admin/admin/src/utils/getFetchClient.mjs.map +1 -1
  173. package/dist/admin/admin/tests/server.js +99 -21
  174. package/dist/admin/admin/tests/server.js.map +1 -1
  175. package/dist/admin/admin/tests/server.mjs +99 -21
  176. package/dist/admin/admin/tests/server.mjs.map +1 -1
  177. package/dist/admin/src/components/Widgets.d.ts +2 -1
  178. package/dist/admin/src/constants.d.ts +26 -0
  179. package/dist/admin/src/core/apis/router.d.ts +1 -1
  180. package/dist/admin/src/features/Tracking.d.ts +2 -1
  181. package/dist/admin/src/pages/Settings/components/Tokens/FormApiTokenContainer.d.ts +24 -0
  182. package/dist/admin/src/pages/Settings/components/Tokens/Table.d.ts +2 -1
  183. package/dist/admin/src/pages/Settings/components/Tokens/constants.d.ts +17 -0
  184. package/dist/admin/src/pages/Settings/constants.d.ts +1 -1
  185. package/dist/admin/src/pages/Settings/pages/AdminTokens/CreateView.d.ts +1 -0
  186. package/dist/admin/src/pages/Settings/pages/AdminTokens/EditView/EditViewPage.d.ts +2 -0
  187. package/dist/admin/src/pages/Settings/pages/AdminTokens/EditView/components/AdminPermissions.d.ts +13 -0
  188. package/dist/admin/src/pages/Settings/pages/AdminTokens/ListView.d.ts +2 -0
  189. package/dist/admin/src/pages/Settings/pages/Roles/components/CollapsePropertyMatrix.d.ts +4 -3
  190. package/dist/admin/src/pages/Settings/pages/Roles/components/ConditionsModal.d.ts +3 -1
  191. package/dist/admin/src/pages/Settings/pages/Roles/components/ContentTypeCollapses.d.ts +1 -0
  192. package/dist/admin/src/pages/Settings/pages/Roles/components/Permissions.d.ts +5 -0
  193. package/dist/admin/src/pages/Settings/pages/Roles/hooks/usePermissionsDataManager.d.ts +8 -7
  194. package/dist/admin/src/pages/Settings/pages/Roles/utils/createPermissionChecker.d.ts +27 -0
  195. package/dist/admin/src/pages/Settings/pages/Roles/utils/updateValues.d.ts +8 -2
  196. package/dist/admin/src/services/apiTokens.d.ts +5 -2
  197. package/dist/admin/src/types/permissions.d.ts +1 -1
  198. package/dist/admin/src/utils/getFetchClient.d.ts +14 -1
  199. package/dist/server/server/src/bootstrap.js +37 -5
  200. package/dist/server/server/src/bootstrap.js.map +1 -1
  201. package/dist/server/server/src/bootstrap.mjs +37 -5
  202. package/dist/server/server/src/bootstrap.mjs.map +1 -1
  203. package/dist/server/server/src/config/admin-actions.js +48 -0
  204. package/dist/server/server/src/config/admin-actions.js.map +1 -1
  205. package/dist/server/server/src/config/admin-actions.mjs +48 -0
  206. package/dist/server/server/src/config/admin-actions.mjs.map +1 -1
  207. package/dist/server/server/src/content-types/Permission.js +10 -1
  208. package/dist/server/server/src/content-types/Permission.js.map +1 -1
  209. package/dist/server/server/src/content-types/Permission.mjs +10 -1
  210. package/dist/server/server/src/content-types/Permission.mjs.map +1 -1
  211. package/dist/server/server/src/content-types/User.js +8 -0
  212. package/dist/server/server/src/content-types/User.js.map +1 -1
  213. package/dist/server/server/src/content-types/User.mjs +8 -0
  214. package/dist/server/server/src/content-types/User.mjs.map +1 -1
  215. package/dist/server/server/src/content-types/api-token.js +27 -1
  216. package/dist/server/server/src/content-types/api-token.js.map +1 -1
  217. package/dist/server/server/src/content-types/api-token.mjs +27 -1
  218. package/dist/server/server/src/content-types/api-token.mjs.map +1 -1
  219. package/dist/server/server/src/controllers/admin-token.js +194 -0
  220. package/dist/server/server/src/controllers/admin-token.js.map +1 -0
  221. package/dist/server/server/src/controllers/admin-token.mjs +192 -0
  222. package/dist/server/server/src/controllers/admin-token.mjs.map +1 -0
  223. package/dist/server/server/src/controllers/api-token.js +48 -47
  224. package/dist/server/server/src/controllers/api-token.js.map +1 -1
  225. package/dist/server/server/src/controllers/api-token.mjs +48 -47
  226. package/dist/server/server/src/controllers/api-token.mjs.map +1 -1
  227. package/dist/server/server/src/controllers/index.js +2 -0
  228. package/dist/server/server/src/controllers/index.js.map +1 -1
  229. package/dist/server/server/src/controllers/index.mjs +2 -0
  230. package/dist/server/server/src/controllers/index.mjs.map +1 -1
  231. package/dist/server/server/src/domain/permission/index.js +2 -1
  232. package/dist/server/server/src/domain/permission/index.js.map +1 -1
  233. package/dist/server/server/src/domain/permission/index.mjs +2 -1
  234. package/dist/server/server/src/domain/permission/index.mjs.map +1 -1
  235. package/dist/server/server/src/policies/index.js +2 -0
  236. package/dist/server/server/src/policies/index.js.map +1 -1
  237. package/dist/server/server/src/policies/index.mjs +2 -0
  238. package/dist/server/server/src/policies/index.mjs.map +1 -1
  239. package/dist/server/server/src/policies/isAdminTokensEnabled.js +16 -0
  240. package/dist/server/server/src/policies/isAdminTokensEnabled.js.map +1 -0
  241. package/dist/server/server/src/policies/isAdminTokensEnabled.mjs +14 -0
  242. package/dist/server/server/src/policies/isAdminTokensEnabled.mjs.map +1 -0
  243. package/dist/server/server/src/register.js +4 -2
  244. package/dist/server/server/src/register.js.map +1 -1
  245. package/dist/server/server/src/register.mjs +4 -2
  246. package/dist/server/server/src/register.mjs.map +1 -1
  247. package/dist/server/server/src/routes/admin-tokens.js +140 -0
  248. package/dist/server/server/src/routes/admin-tokens.js.map +1 -0
  249. package/dist/server/server/src/routes/admin-tokens.mjs +138 -0
  250. package/dist/server/server/src/routes/admin-tokens.mjs.map +1 -0
  251. package/dist/server/server/src/routes/index.js +2 -0
  252. package/dist/server/server/src/routes/index.js.map +1 -1
  253. package/dist/server/server/src/routes/index.mjs +2 -0
  254. package/dist/server/server/src/routes/index.mjs.map +1 -1
  255. package/dist/server/server/src/services/api-token.js +805 -101
  256. package/dist/server/server/src/services/api-token.js.map +1 -1
  257. package/dist/server/server/src/services/api-token.mjs +800 -101
  258. package/dist/server/server/src/services/api-token.mjs.map +1 -1
  259. package/dist/server/server/src/services/constants.js +2 -0
  260. package/dist/server/server/src/services/constants.js.map +1 -1
  261. package/dist/server/server/src/services/constants.mjs +2 -0
  262. package/dist/server/server/src/services/constants.mjs.map +1 -1
  263. package/dist/server/server/src/services/homepage.js +1 -1
  264. package/dist/server/server/src/services/homepage.js.map +1 -1
  265. package/dist/server/server/src/services/homepage.mjs +1 -1
  266. package/dist/server/server/src/services/homepage.mjs.map +1 -1
  267. package/dist/server/server/src/services/index.js +2 -1
  268. package/dist/server/server/src/services/index.js.map +1 -1
  269. package/dist/server/server/src/services/index.mjs +3 -2
  270. package/dist/server/server/src/services/index.mjs.map +1 -1
  271. package/dist/server/server/src/services/permission/engine.js +6 -0
  272. package/dist/server/server/src/services/permission/engine.js.map +1 -1
  273. package/dist/server/server/src/services/permission/engine.mjs +6 -0
  274. package/dist/server/server/src/services/permission/engine.mjs.map +1 -1
  275. package/dist/server/server/src/services/permission/queries.js +11 -2
  276. package/dist/server/server/src/services/permission/queries.js.map +1 -1
  277. package/dist/server/server/src/services/permission/queries.mjs +12 -3
  278. package/dist/server/server/src/services/permission/queries.mjs.map +1 -1
  279. package/dist/server/server/src/services/role.js +3 -0
  280. package/dist/server/server/src/services/role.js.map +1 -1
  281. package/dist/server/server/src/services/role.mjs +3 -0
  282. package/dist/server/server/src/services/role.mjs.map +1 -1
  283. package/dist/server/server/src/strategies/admin-token.js +110 -0
  284. package/dist/server/server/src/strategies/admin-token.js.map +1 -0
  285. package/dist/server/server/src/strategies/admin-token.mjs +104 -0
  286. package/dist/server/server/src/strategies/admin-token.mjs.map +1 -0
  287. package/dist/server/server/src/strategies/api-token-utils.js +56 -0
  288. package/dist/server/server/src/strategies/api-token-utils.js.map +1 -0
  289. package/dist/server/server/src/strategies/api-token-utils.mjs +52 -0
  290. package/dist/server/server/src/strategies/api-token-utils.mjs.map +1 -0
  291. package/dist/server/server/src/strategies/content-api-token.js +104 -0
  292. package/dist/server/server/src/strategies/content-api-token.js.map +1 -0
  293. package/dist/server/server/src/strategies/content-api-token.mjs +98 -0
  294. package/dist/server/server/src/strategies/content-api-token.mjs.map +1 -0
  295. package/dist/server/server/src/validation/admin-tokens.js +28 -0
  296. package/dist/server/server/src/validation/admin-tokens.js.map +1 -0
  297. package/dist/server/server/src/validation/admin-tokens.mjs +25 -0
  298. package/dist/server/server/src/validation/admin-tokens.mjs.map +1 -0
  299. package/dist/server/server/src/validation/api-tokens.js +5 -2
  300. package/dist/server/server/src/validation/api-tokens.js.map +1 -1
  301. package/dist/server/server/src/validation/api-tokens.mjs +5 -2
  302. package/dist/server/server/src/validation/api-tokens.mjs.map +1 -1
  303. package/dist/server/server/src/validation/project-settings.js +15 -16
  304. package/dist/server/server/src/validation/project-settings.js.map +1 -1
  305. package/dist/server/server/src/validation/project-settings.mjs +4 -5
  306. package/dist/server/server/src/validation/project-settings.mjs.map +1 -1
  307. package/dist/server/src/bootstrap.d.ts.map +1 -1
  308. package/dist/server/src/config/admin-actions.d.ts.map +1 -1
  309. package/dist/server/src/content-types/Permission.d.ts +9 -0
  310. package/dist/server/src/content-types/Permission.d.ts.map +1 -1
  311. package/dist/server/src/content-types/User.d.ts +8 -0
  312. package/dist/server/src/content-types/User.d.ts.map +1 -1
  313. package/dist/server/src/content-types/api-token.d.ts +23 -0
  314. package/dist/server/src/content-types/api-token.d.ts.map +1 -1
  315. package/dist/server/src/content-types/index.d.ts +40 -0
  316. package/dist/server/src/content-types/index.d.ts.map +1 -1
  317. package/dist/server/src/controllers/admin-token.d.ts +12 -0
  318. package/dist/server/src/controllers/admin-token.d.ts.map +1 -0
  319. package/dist/server/src/controllers/api-token.d.ts +0 -1
  320. package/dist/server/src/controllers/api-token.d.ts.map +1 -1
  321. package/dist/server/src/controllers/index.d.ts +9 -1
  322. package/dist/server/src/controllers/index.d.ts.map +1 -1
  323. package/dist/server/src/domain/permission/index.d.ts.map +1 -1
  324. package/dist/server/src/index.d.ts +56 -2
  325. package/dist/server/src/index.d.ts.map +1 -1
  326. package/dist/server/src/policies/index.d.ts +5 -0
  327. package/dist/server/src/policies/index.d.ts.map +1 -1
  328. package/dist/server/src/policies/isAdminTokensEnabled.d.ts +7 -0
  329. package/dist/server/src/policies/isAdminTokensEnabled.d.ts.map +1 -0
  330. package/dist/server/src/register.d.ts.map +1 -1
  331. package/dist/server/src/routes/admin-tokens.d.ts +15 -0
  332. package/dist/server/src/routes/admin-tokens.d.ts.map +1 -0
  333. package/dist/server/src/routes/index.d.ts.map +1 -1
  334. package/dist/server/src/services/api-token.d.ts +136 -12
  335. package/dist/server/src/services/api-token.d.ts.map +1 -1
  336. package/dist/server/src/services/constants.d.ts +13 -11
  337. package/dist/server/src/services/constants.d.ts.map +1 -1
  338. package/dist/server/src/services/index.d.ts +2 -2
  339. package/dist/server/src/services/index.d.ts.map +1 -1
  340. package/dist/server/src/services/permission/engine.d.ts +5 -0
  341. package/dist/server/src/services/permission/engine.d.ts.map +1 -1
  342. package/dist/server/src/services/permission/queries.d.ts.map +1 -1
  343. package/dist/server/src/services/permission.d.ts +1 -0
  344. package/dist/server/src/services/permission.d.ts.map +1 -1
  345. package/dist/server/src/services/role.d.ts.map +1 -1
  346. package/dist/server/src/strategies/admin-token.d.ts +51 -0
  347. package/dist/server/src/strategies/admin-token.d.ts.map +1 -0
  348. package/dist/server/src/strategies/api-token-utils.d.ts +13 -0
  349. package/dist/server/src/strategies/api-token-utils.d.ts.map +1 -0
  350. package/dist/server/src/strategies/{api-token.d.ts → content-api-token.d.ts} +10 -11
  351. package/dist/server/src/strategies/content-api-token.d.ts.map +1 -0
  352. package/dist/server/src/strategies/index.d.ts +2 -1
  353. package/dist/server/src/strategies/index.d.ts.map +1 -1
  354. package/dist/server/src/validation/admin-tokens.d.ts +75 -0
  355. package/dist/server/src/validation/admin-tokens.d.ts.map +1 -0
  356. package/dist/server/src/validation/api-tokens.d.ts +4 -2
  357. package/dist/server/src/validation/api-tokens.d.ts.map +1 -1
  358. package/dist/server/src/validation/project-settings.d.ts +10 -10
  359. package/dist/server/src/validation/project-settings.d.ts.map +1 -1
  360. package/dist/shared/contracts/admin-token.d.ts +122 -0
  361. package/dist/shared/contracts/admin-token.d.ts.map +1 -0
  362. package/dist/shared/contracts/api-token.d.ts +6 -95
  363. package/dist/shared/contracts/api-token.d.ts.map +1 -1
  364. package/dist/shared/contracts/content-api-token.d.ts +97 -0
  365. package/dist/shared/contracts/content-api-token.d.ts.map +1 -0
  366. package/dist/shared/contracts/shared.d.ts +1 -0
  367. package/dist/shared/contracts/shared.d.ts.map +1 -1
  368. package/package.json +10 -10
  369. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/FormApiTokenContainer.js.map +0 -1
  370. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/components/FormApiTokenContainer.mjs.map +0 -1
  371. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/constants.js +0 -37
  372. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/constants.js.map +0 -1
  373. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/constants.mjs +0 -16
  374. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/constants.mjs.map +0 -1
  375. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/utils/getDateOfExpiration.js.map +0 -1
  376. package/dist/admin/admin/src/pages/Settings/pages/ApiTokens/EditView/utils/getDateOfExpiration.mjs.map +0 -1
  377. package/dist/admin/src/pages/Settings/pages/ApiTokens/EditView/components/FormApiTokenContainer.d.ts +0 -20
  378. package/dist/admin/src/pages/Settings/pages/ApiTokens/EditView/constants.d.ts +0 -17
  379. package/dist/server/server/src/strategies/api-token.js +0 -144
  380. package/dist/server/server/src/strategies/api-token.js.map +0 -1
  381. package/dist/server/server/src/strategies/api-token.mjs +0 -138
  382. package/dist/server/server/src/strategies/api-token.mjs.map +0 -1
  383. package/dist/server/src/strategies/api-token.d.ts.map +0 -1
  384. /package/dist/admin/src/pages/Settings/{pages/ApiTokens/EditView → components/Tokens}/utils/getDateOfExpiration.d.ts +0 -0
@@ -1,12 +1,58 @@
1
1
  import crypto from 'crypto';
2
- import { omit, uniq, map, difference, isEmpty, isArray, isNumber, isNil } from 'lodash/fp';
2
+ import { pick, uniq, differenceWith, prop, omit, map, difference, isEqual, isEmpty, isArray, isNumber, isNil } from 'lodash/fp';
3
3
  import { errors } from '@strapi/utils';
4
4
  import constants from './constants.mjs';
5
5
  import { getService } from '../utils/index.mjs';
6
+ import permissionDomain from '../domain/permission/index.mjs';
7
+ import { validatePermissionsExist } from '../validation/permission.mjs';
6
8
 
9
+ const { SUPER_ADMIN_CODE } = constants;
7
10
  const { ValidationError, NotFoundError } = errors;
11
+ const assertOwnerMatchesCallingUser = async (adminUserOwner, callingUser)=>{
12
+ if (callingUser === undefined || callingUser === null) {
13
+ throw new ValidationError('adminUserOwner requires an authenticated admin user');
14
+ }
15
+ const ownerId = String(adminUserOwner);
16
+ const callingUserId = String(callingUser.id);
17
+ if (ownerId !== callingUserId) {
18
+ throw new ValidationError('adminUserOwner must match the authenticated admin user');
19
+ }
20
+ const existingUser = await strapi.db.query('admin::user').findOne({
21
+ select: [
22
+ 'id'
23
+ ],
24
+ where: {
25
+ id: callingUser.id
26
+ }
27
+ });
28
+ if (existingUser === null || existingUser === undefined) {
29
+ throw new ValidationError('adminUserOwner must reference an existing admin user');
30
+ }
31
+ };
32
+ const isSuperAdmin = (user)=>user?.roles?.some((r)=>r.code === SUPER_ADMIN_CODE) === true;
33
+ const getOwnerId = (token)=>{
34
+ const owner = token.adminUserOwner;
35
+ return String(typeof owner === 'object' ? owner.id : owner);
36
+ };
37
+ const toAdminTokenOwner = (owner)=>{
38
+ if (owner === null || owner === undefined) {
39
+ throw new Error('adminUserOwner is required');
40
+ }
41
+ // Bare id
42
+ if (typeof owner === 'number' || typeof owner === 'string') {
43
+ return owner;
44
+ }
45
+ return {
46
+ id: owner.id,
47
+ firstname: owner.firstname,
48
+ lastname: owner.lastname,
49
+ username: owner.username,
50
+ email: owner.email
51
+ };
52
+ };
8
53
  const SELECT_FIELDS = [
9
54
  'id',
55
+ 'kind',
10
56
  'name',
11
57
  'description',
12
58
  'lastUsedAt',
@@ -17,7 +63,9 @@ const SELECT_FIELDS = [
17
63
  'updatedAt'
18
64
  ];
19
65
  const POPULATE_FIELDS = [
20
- 'permissions'
66
+ 'permissions',
67
+ 'adminPermissions',
68
+ 'adminUserOwner'
21
69
  ];
22
70
  // TODO: we need to ensure the permissions are actually valid registered permissions!
23
71
  /**
@@ -60,42 +108,381 @@ const POPULATE_FIELDS = [
60
108
  }
61
109
  };
62
110
  /**
63
- * Flatten a token's database permissions objects to an array of strings
64
- */ const flattenTokenPermissions = (token)=>{
65
- if (!token) {
66
- return token;
111
+ * Assert that a legacy-kind token body does not carry admin-only fields
112
+ */ const assertLegacyKindFields = (attributes)=>{
113
+ const raw = attributes;
114
+ if (raw.adminPermissions !== undefined && raw.adminPermissions !== null) {
115
+ throw new ValidationError('Legacy tokens cannot carry admin permissions');
116
+ }
117
+ if (raw.adminUserOwner !== undefined && raw.adminUserOwner !== null) {
118
+ throw new ValidationError('Legacy tokens cannot have an admin user owner');
119
+ }
120
+ };
121
+ /**
122
+ * Assert that an admin-kind token body does not carry legacy-only fields
123
+ */ const assertAdminKindFields = (attributes)=>{
124
+ const raw = attributes;
125
+ if (raw.type !== undefined && raw.type !== null) {
126
+ throw new ValidationError('Admin tokens cannot carry a legacy type (custom/read-only/full-access)');
127
+ }
128
+ if (raw.permissions !== undefined && raw.permissions !== null) {
129
+ throw new ValidationError('Admin tokens cannot carry legacy content-API permissions');
130
+ }
131
+ };
132
+ /**
133
+ * Assert that admin permissions are valid
134
+ */ const assertAdminPermissionsValidity = async (adminPermissions)=>{
135
+ if (!adminPermissions || adminPermissions.length === 0) {
136
+ return;
137
+ }
138
+ // Validate that all actions exist in the admin action provider
139
+ const validActions = getService('permission').actionProvider.keys();
140
+ for (const perm of adminPermissions){
141
+ if (!validActions.includes(perm.action)) {
142
+ throw new ValidationError(`Unknown admin action: ${perm.action}`);
143
+ }
144
+ }
145
+ // Use existing permission validation
146
+ await validatePermissionsExist(adminPermissions);
147
+ };
148
+ /**
149
+ * Enforce that every requested admin permission stays within the calling
150
+ * user's own permission ceiling, then return the clamped permissions.
151
+ *
152
+ * Super-admins bypass this (they hold every permission).
153
+ * When admin permissions are requested, an authenticated user is required (no bypass when user is missing).
154
+ *
155
+ * For each requested permission:
156
+ * - action + subject must match at least one user permission
157
+ * - properties.fields must be ⊆ user's properties.fields
158
+ * (if the user's permission defines no fields, all fields are allowed)
159
+ * - conditions are inherited from the user's matching permission(s);
160
+ * the caller cannot configure conditions on their own tokens
161
+ *
162
+ * Returns the permissions with conditions enforced from the user's role.
163
+ * Throws ValidationError if any permission exceeds the user's ceiling.
164
+ *
165
+ * Guaranteed postcondition: all returned permissions have conditions filtered to
166
+ * registered conditions only, regardless of the user type.
167
+ */ const enforceAdminPermissionsCeiling = async (user, requestedPermissions)=>{
168
+ if (!requestedPermissions || requestedPermissions.length === 0) {
169
+ return requestedPermissions || [];
170
+ }
171
+ if (user === undefined || user === null) {
172
+ throw new ValidationError('Admin permission ceiling cannot be enforced without an authenticated user');
173
+ }
174
+ if (isSuperAdmin(user)) {
175
+ // Sanitize conditions even for super-admins so this function is a complete boundary.
176
+ // createApiTokenAdminPermissions also sanitizes, but relying on that downstream
177
+ // is fragile — any future call path that skips it would store invalid conditions.
178
+ const { conditionProvider } = getService('permission');
179
+ const sanitize = permissionDomain.sanitizeConditions(conditionProvider);
180
+ return requestedPermissions.map((perm)=>{
181
+ const sanitized = sanitize({
182
+ ...perm,
183
+ actionParameters: {}
184
+ });
185
+ return {
186
+ ...perm,
187
+ conditions: sanitized.conditions
188
+ };
189
+ });
190
+ }
191
+ const userPermissions = await getService('permission').findUserPermissions(user);
192
+ const exceeding = [];
193
+ const clamped = requestedPermissions.map((requested)=>{
194
+ const requestedSubject = requested.subject || null;
195
+ // Find all user permissions matching action + subject
196
+ const matchingUserPerms = userPermissions.filter((userPerm)=>{
197
+ if (userPerm.action !== requested.action) return false;
198
+ const userSubject = userPerm.subject || null;
199
+ return requestedSubject === userSubject;
200
+ });
201
+ const label = requestedSubject !== null ? `${requested.action} on ${requestedSubject}` : requested.action;
202
+ if (matchingUserPerms.length === 0) {
203
+ exceeding.push(label);
204
+ return requested;
205
+ }
206
+ // --- Field-level ceiling ---
207
+ // If any matching user perm has no fields defined → all fields are allowed.
208
+ // Otherwise, effective user fields = union of all matching perms' fields.
209
+ const anyUserPermHasAllFields = matchingUserPerms.some((p)=>!p.properties?.fields || p.properties.fields.length === 0);
210
+ const requestedFields = requested.properties?.fields;
211
+ if (!anyUserPermHasAllFields) {
212
+ const effectiveUserFields = uniq(matchingUserPerms.flatMap((p)=>p.properties?.fields || []));
213
+ // When the owner is field-restricted, omitting fields would widen access to all fields.
214
+ // Force explicit field selection so token scope can't exceed the owner's ceiling.
215
+ if (requestedFields === undefined || requestedFields === null) {
216
+ exceeding.push(`${label} (fields are required due to owner field restrictions)`);
217
+ return requested;
218
+ }
219
+ if (requestedFields.length > 0) {
220
+ const exceedingFields = requestedFields.filter((f)=>!effectiveUserFields.includes(f));
221
+ if (exceedingFields.length > 0) {
222
+ exceeding.push(`${label} (fields: ${exceedingFields.join(', ')})`);
223
+ return requested;
224
+ }
225
+ }
226
+ }
227
+ // --- Condition-level ceiling ---
228
+ // Conditions are always inherited from the user's matching permission(s).
229
+ // If any matching user perm is unconditional → token gets no conditions.
230
+ // Otherwise → union of conditions across matching perms.
231
+ const anyUserPermIsUnconditional = matchingUserPerms.some((p)=>!p.conditions || p.conditions.length === 0);
232
+ const enforcedConditions = anyUserPermIsUnconditional ? [] : uniq(matchingUserPerms.flatMap((p)=>p.conditions || []));
233
+ return {
234
+ ...requested,
235
+ conditions: enforcedConditions
236
+ };
237
+ });
238
+ if (exceeding.length > 0) {
239
+ throw new ValidationError(`Cannot assign admin permissions that exceed your own. ` + `Exceeding: ${exceeding.join(', ')}`);
240
+ }
241
+ return clamped;
242
+ };
243
+ /**
244
+ * Create admin permissions for an API token
245
+ */ const createApiTokenAdminPermissions = async (tokenId, permissions)=>{
246
+ const { conditionProvider } = getService('permission');
247
+ const sanitizeConditions = permissionDomain.sanitizeConditions(conditionProvider);
248
+ const permissionsWithToken = permissions.map((perm)=>{
249
+ const permAsPermission = {
250
+ ...perm,
251
+ actionParameters: {}
252
+ };
253
+ const sanitized = sanitizeConditions(permAsPermission);
254
+ return permissionDomain.create({
255
+ ...sanitized,
256
+ apiToken: tokenId,
257
+ role: null
258
+ });
259
+ });
260
+ const createdPermissions = await getService('permission').createMany(permissionsWithToken);
261
+ return createdPermissions;
262
+ };
263
+ /**
264
+ * Fields to compare when checking if two permissions are equal
265
+ */ const COMPARABLE_FIELDS = [
266
+ 'conditions',
267
+ 'properties',
268
+ 'subject',
269
+ 'action',
270
+ 'actionParameters'
271
+ ];
272
+ const pickComparableFields = pick(COMPARABLE_FIELDS);
273
+ /**
274
+ * Helper to clean JSON (remove undefined values)
275
+ */ const jsonClean = (data)=>JSON.parse(JSON.stringify(data));
276
+ /**
277
+ * Compare two permissions for equality
278
+ */ const arePermissionsEqual = (p1, p2)=>{
279
+ if (p1.action === p2.action) {
280
+ return isEqual(jsonClean(pickComparableFields(p1)), jsonClean(pickComparableFields(p2)));
67
281
  }
282
+ return false;
283
+ };
284
+ /**
285
+ * Assign admin permissions to an API token (similar to role permission assignment).
286
+ * ceilingUser is the user whose permissions act as the ceiling — always the token owner,
287
+ * regardless of who is making the request.
288
+ */ const assignAdminPermissionsToToken = async (tokenId, permissions, ceilingUser)=>{
289
+ await validatePermissionsExist(permissions);
290
+ const clampedPermissions = await enforceAdminPermissionsCeiling(ceilingUser, permissions);
291
+ const permissionsWithToken = clampedPermissions.map((perm)=>permissionDomain.create({
292
+ ...perm,
293
+ apiToken: tokenId,
294
+ role: null
295
+ }));
296
+ const existingPermissions = await getService('permission').findMany({
297
+ where: {
298
+ apiToken: {
299
+ id: tokenId
300
+ }
301
+ }
302
+ });
303
+ const permissionsToAdd = differenceWith(arePermissionsEqual, permissionsWithToken, existingPermissions);
304
+ const permissionsToDelete = differenceWith(arePermissionsEqual, existingPermissions, permissionsWithToken);
305
+ if (permissionsToDelete.length > 0) {
306
+ await getService('permission').deleteByIds(permissionsToDelete.map(prop('id')));
307
+ }
308
+ if (permissionsToAdd.length > 0) {
309
+ await createApiTokenAdminPermissions(tokenId, permissionsToAdd);
310
+ }
311
+ // Return all current permissions
312
+ const allCurrentPermissions = await getService('permission').findMany({
313
+ where: {
314
+ apiToken: {
315
+ id: tokenId
316
+ }
317
+ }
318
+ });
319
+ return allCurrentPermissions;
320
+ };
321
+ /**
322
+ * Reconcile a token's admin permissions against the owner's current effective ceiling.
323
+ *
324
+ * Pure / sync — no DB calls. Returns two buckets:
325
+ * toDelete – permissions that are no longer within the user's scope (action/subject missing
326
+ * or requested fields exceed the allowed set)
327
+ * toUpdate – permissions that are still in scope but whose conditions must be re-clamped
328
+ * to the current union of the matching user permissions' conditions
329
+ */ const reconcileTokenPermissionsToUserCeiling = (userPermissions, tokenPermissions)=>{
330
+ const toDelete = [];
331
+ const toUpdate = [];
332
+ tokenPermissions.forEach((tokenPerm)=>{
333
+ const tokenSubject = tokenPerm.subject || null;
334
+ const matchingUserPerms = userPermissions.filter((userPerm)=>userPerm.action === tokenPerm.action && (userPerm.subject || null) === tokenSubject);
335
+ if (matchingUserPerms.length === 0) {
336
+ toDelete.push(tokenPerm);
337
+ return;
338
+ }
339
+ // Field-level ceiling check (mirrors enforceAdminPermissionsCeiling)
340
+ const anyUserPermHasAllFields = matchingUserPerms.some((p)=>!p.properties?.fields || p.properties.fields.length === 0);
341
+ const tokenFields = tokenPerm.properties?.fields;
342
+ const fieldCeilingExceeded = !anyUserPermHasAllFields && tokenFields !== undefined && tokenFields !== null && tokenFields.length > 0 && (()=>{
343
+ const effectiveUserFields = uniq(matchingUserPerms.flatMap((p)=>p.properties?.fields || []));
344
+ return tokenFields.some((f)=>!effectiveUserFields.includes(f));
345
+ })();
346
+ if (fieldCeilingExceeded) {
347
+ toDelete.push(tokenPerm);
348
+ return;
349
+ }
350
+ // Condition: force conditions to be the ones of the user permission(s)
351
+ const anyUserPermIsUnconditional = matchingUserPerms.some((p)=>!p.conditions || p.conditions.length === 0);
352
+ const enforcedConditions = anyUserPermIsUnconditional ? [] : uniq(matchingUserPerms.flatMap((p)=>p.conditions || []));
353
+ const currentConditions = tokenPerm.conditions || [];
354
+ const conditionsChanged = enforcedConditions.length !== currentConditions.length || enforcedConditions.some((c)=>!currentConditions.includes(c));
355
+ if (conditionsChanged) {
356
+ toUpdate.push({
357
+ id: tokenPerm.id,
358
+ conditions: enforcedConditions
359
+ });
360
+ }
361
+ });
68
362
  return {
69
- ...token,
70
- permissions: isArray(token.permissions) ? map('action', token.permissions) : token.permissions
363
+ toDelete,
364
+ toUpdate
71
365
  };
72
366
  };
73
367
  /**
74
- * Get a token
75
- */ const getBy = async (whereParams = {})=>{
368
+ * Re-sync all admin token permissions for a given user against their current effective ceiling.
369
+ *
370
+ * Skips super-admins (no ceiling). For each admin token owned by the user:
371
+ * - Deletes permissions that are no longer within the user's scope
372
+ * - Updates conditions on permissions whose conditions have drifted from the role's current set
373
+ */ const syncApiTokenPermissionsForUser = async (userId)=>{
374
+ const user = await strapi.db.query('admin::user').findOne({
375
+ where: {
376
+ id: userId
377
+ },
378
+ populate: [
379
+ 'roles'
380
+ ]
381
+ });
382
+ if (user === null || user === undefined) return;
383
+ if (isSuperAdmin(user)) return;
384
+ const userEffectivePermissions = await getService('permission').findUserPermissions(user);
385
+ const tokens = await strapi.db.query('admin::api-token').findMany({
386
+ where: {
387
+ kind: 'admin',
388
+ adminUserOwner: {
389
+ id: userId
390
+ }
391
+ },
392
+ populate: [
393
+ 'adminPermissions'
394
+ ]
395
+ });
396
+ const tokensWithPermissions = tokens.filter((token)=>Array.isArray(token.adminPermissions) && token.adminPermissions.length > 0);
397
+ for (const token of tokensWithPermissions){
398
+ const tokenPermissions = token.adminPermissions;
399
+ const { toDelete, toUpdate } = reconcileTokenPermissionsToUserCeiling(userEffectivePermissions, tokenPermissions);
400
+ if (toDelete.length > 0) {
401
+ await getService('permission').deleteByIds(toDelete.map((p)=>p.id));
402
+ }
403
+ for (const { id, conditions } of toUpdate){
404
+ await strapi.db.query('admin::permission').update({
405
+ where: {
406
+ id
407
+ },
408
+ data: {
409
+ conditions
410
+ }
411
+ });
412
+ }
413
+ }
414
+ };
415
+ /**
416
+ * Re-sync admin token permissions for all admin users who hold a given role.
417
+ * Called after role permissions are updated.
418
+ */ const syncApiTokenPermissionsForRole = async (roleId)=>{
419
+ const users = await strapi.db.query('admin::user').findMany({
420
+ where: {
421
+ roles: {
422
+ id: roleId
423
+ }
424
+ },
425
+ populate: [
426
+ 'roles'
427
+ ]
428
+ });
429
+ await Promise.allSettled(users.map((user)=>syncApiTokenPermissionsForUser(user.id)));
430
+ };
431
+ /**
432
+ * Flatten a token's database permissions objects to an array of strings
433
+ */ const flattenTokenPermissions = (permissions)=>{
434
+ return isArray(permissions) ? map('action', permissions) : [];
435
+ };
436
+ /**
437
+ * Get a token.
438
+ * By default the plaintext accessKey is NOT included.
439
+ * Pass { includeDecryptedKey: true } to decrypt and return it (owner-only paths).
440
+ */ const getBy = async (whereParams = {}, options = {})=>{
76
441
  if (Object.keys(whereParams).length === 0) {
77
442
  return null;
78
443
  }
444
+ const { includeDecryptedKey = false } = options;
445
+ const selectFields = includeDecryptedKey ? [
446
+ ...SELECT_FIELDS,
447
+ 'encryptedKey'
448
+ ] : SELECT_FIELDS;
79
449
  const token = await strapi.db.query('admin::api-token').findOne({
80
- select: [
81
- ...SELECT_FIELDS,
82
- 'encryptedKey'
83
- ],
450
+ select: selectFields,
84
451
  populate: POPULATE_FIELDS,
85
452
  where: whereParams
86
453
  });
87
454
  if (!token) {
88
455
  return token;
89
456
  }
90
- const { encryptedKey, ...rest } = token;
91
- if (!encryptedKey) {
92
- return flattenTokenPermissions(rest);
457
+ // Tokens created before kind introduction case: force kind to be content-api
458
+ const computedKind = token.kind ?? 'content-api';
459
+ const result = omit([
460
+ 'accessKey',
461
+ 'encryptedKey',
462
+ 'type',
463
+ 'permissions',
464
+ 'adminPermissions',
465
+ 'adminUserOwner'
466
+ ], token);
467
+ if (computedKind === 'content-api') {
468
+ Object.assign(result, {
469
+ kind: 'content-api',
470
+ type: token.type,
471
+ permissions: flattenTokenPermissions(token.permissions)
472
+ });
473
+ } else if (computedKind === 'admin') {
474
+ Object.assign(result, {
475
+ kind: 'admin',
476
+ adminPermissions: token.adminPermissions,
477
+ adminUserOwner: toAdminTokenOwner(token.adminUserOwner)
478
+ });
93
479
  }
94
- const accessKey = getService('encryption').decrypt(encryptedKey);
95
- return flattenTokenPermissions({
96
- ...rest,
97
- accessKey
98
- });
480
+ if (includeDecryptedKey && token.encryptedKey) {
481
+ Object.assign(result, {
482
+ accessKey: getService('encryption').decrypt(token.encryptedKey)
483
+ });
484
+ }
485
+ return result;
99
486
  };
100
487
  /**
101
488
  * Check if token exists
@@ -117,54 +504,116 @@ const getExpirationFields = (lifespan)=>{
117
504
  throw new ValidationError('lifespan must be a positive number or null');
118
505
  }
119
506
  return {
120
- lifespan: lifespan || null,
507
+ lifespan: lifespan ?? null,
121
508
  expiresAt: lifespan ? Date.now() + lifespan : null
122
509
  };
123
510
  };
124
511
  /**
125
512
  * Create a token and its permissions
126
- */ const create = async (attributes)=>{
513
+ */ const create = async (attributes, callingUser)=>{
127
514
  const encryptionService = getService('encryption');
128
515
  const accessKey = crypto.randomBytes(128).toString('hex');
129
516
  const encryptedKey = encryptionService.encrypt(accessKey);
130
- assertCustomTokenPermissionsValidity(attributes.type, attributes.permissions);
131
517
  assertValidLifespan(attributes.lifespan);
132
- // Create the token
518
+ if (attributes.kind === 'content-api') {
519
+ const castedContentApiApiTokenBody = attributes;
520
+ assertLegacyKindFields(castedContentApiApiTokenBody);
521
+ assertCustomTokenPermissionsValidity(castedContentApiApiTokenBody.type, castedContentApiApiTokenBody.permissions);
522
+ // content api tokens have no owner
523
+ const apiToken = await strapi.db.query('admin::api-token').create({
524
+ select: SELECT_FIELDS,
525
+ populate: POPULATE_FIELDS,
526
+ data: {
527
+ ...omit([
528
+ 'permissions',
529
+ 'adminPermissions',
530
+ 'adminUserOwner'
531
+ ], attributes),
532
+ accessKey: hash(accessKey),
533
+ encryptedKey,
534
+ adminUserOwner: null,
535
+ ...getExpirationFields(castedContentApiApiTokenBody.lifespan ?? null)
536
+ }
537
+ });
538
+ const result = {
539
+ ...apiToken,
540
+ accessKey
541
+ };
542
+ // If this is a custom type token, create the related content-API permissions
543
+ if (castedContentApiApiTokenBody.type === constants.API_TOKEN_TYPE.CUSTOM) {
544
+ // TODO: createMany doesn't seem to create relation properly, implement a better way rather than a ton of queries
545
+ await Promise.all(uniq(castedContentApiApiTokenBody.permissions).map((action)=>strapi.db.query('admin::api-token-permission').create({
546
+ data: {
547
+ action,
548
+ token: apiToken
549
+ }
550
+ })));
551
+ const currentPermissions = await strapi.db.query('admin::api-token').load(apiToken, 'permissions');
552
+ if (currentPermissions) {
553
+ Object.assign(result, {
554
+ permissions: flattenTokenPermissions(currentPermissions)
555
+ });
556
+ }
557
+ }
558
+ // Casted to any to avoid complex type duplication
559
+ return omit([
560
+ 'adminPermissions',
561
+ 'adminUserOwner'
562
+ ], result);
563
+ }
564
+ // kind === 'admin'
565
+ assertAdminKindFields(attributes);
566
+ const castedAdminTokenBody = attributes;
567
+ await assertAdminPermissionsValidity(castedAdminTokenBody.adminPermissions);
568
+ const clampedAdminPermissions = await enforceAdminPermissionsCeiling(callingUser, castedAdminTokenBody.adminPermissions);
569
+ // Owner: when explicitly provided, it must match the caller.
570
+ // When omitted, always defaults to the calling user (including super admins).
571
+ let ownerId;
572
+ if (castedAdminTokenBody.adminUserOwner !== undefined && castedAdminTokenBody.adminUserOwner !== null) {
573
+ await assertOwnerMatchesCallingUser(castedAdminTokenBody.adminUserOwner, callingUser);
574
+ ownerId = castedAdminTokenBody.adminUserOwner;
575
+ } else {
576
+ if (callingUser === undefined || callingUser === null) {
577
+ throw new ValidationError('Creating an admin token requires an authenticated admin user');
578
+ }
579
+ ownerId = callingUser.id;
580
+ }
133
581
  const apiToken = await strapi.db.query('admin::api-token').create({
134
582
  select: SELECT_FIELDS,
135
583
  populate: POPULATE_FIELDS,
136
584
  data: {
137
- ...omit('permissions', attributes),
585
+ ...omit([
586
+ 'permissions',
587
+ 'adminPermissions',
588
+ 'adminUserOwner'
589
+ ], attributes),
138
590
  accessKey: hash(accessKey),
139
591
  encryptedKey,
140
- ...getExpirationFields(attributes.lifespan)
592
+ adminUserOwner: ownerId,
593
+ ...getExpirationFields(castedAdminTokenBody.lifespan ?? null)
141
594
  }
142
595
  });
143
596
  const result = {
144
597
  ...apiToken,
145
598
  accessKey
146
599
  };
147
- // If this is a custom type token, create and the related permissions
148
- if (attributes.type === constants.API_TOKEN_TYPE.CUSTOM) {
149
- // TODO: createMany doesn't seem to create relation properly, implement a better way rather than a ton of queries
150
- // const permissionsCount = await strapi.db.query('admin::api-token-permission').createMany({
151
- // populate: POPULATE_FIELDS,
152
- // data: attributes.permissions.map(action => ({ action, token: apiToken })),
153
- // });
154
- await Promise.all(uniq(attributes.permissions).map((action)=>strapi.db.query('admin::api-token-permission').create({
155
- data: {
156
- action,
157
- token: apiToken
158
- }
159
- })));
160
- const currentPermissions = await strapi.db.query('admin::api-token').load(apiToken, 'permissions');
161
- if (currentPermissions) {
600
+ // Handle admin permissions (using ceiling-clamped permissions with inherited conditions)
601
+ if (clampedAdminPermissions.length > 0) {
602
+ await createApiTokenAdminPermissions(apiToken.id, clampedAdminPermissions);
603
+ const currentAdminPermissions = await strapi.db.query('admin::api-token').load(apiToken, 'adminPermissions');
604
+ if (currentAdminPermissions) {
162
605
  Object.assign(result, {
163
- permissions: map('action', currentPermissions)
606
+ adminPermissions: currentAdminPermissions
164
607
  });
165
608
  }
166
609
  }
167
- return result;
610
+ // Casted to any to avoid complex type duplication
611
+ return {
612
+ ...omit([
613
+ 'permissions'
614
+ ], result),
615
+ adminUserOwner: toAdminTokenOwner(result.adminUserOwner)
616
+ };
168
617
  };
169
618
  const regenerate = async (id)=>{
170
619
  const accessKey = crypto.randomBytes(128).toString('hex');
@@ -206,50 +655,114 @@ For security reasons, prefer storing the secret in an environment variable and r
206
655
  }
207
656
  };
208
657
  /**
209
- * Return a list of all tokens and their permissions
210
- */ const list = async ()=>{
658
+ * Return a list of tokens visible to the calling user.
659
+ * Super-admins see all tokens; regular admins see only ownerless tokens and their own.
660
+ */ const list = async (callingUser, { filter } = {})=>{
661
+ const ownershipWhere = isSuperAdmin(callingUser) ? {} : {
662
+ $or: [
663
+ {
664
+ adminUserOwner: null
665
+ },
666
+ {
667
+ adminUserOwner: {
668
+ id: callingUser.id
669
+ }
670
+ }
671
+ ]
672
+ };
673
+ // Tokens without a persisted kind are content-api tokens (pre-migration rows).
674
+ let kindWhere = {};
675
+ if (filter?.kind === 'content-api') {
676
+ kindWhere = {
677
+ $or: [
678
+ {
679
+ kind: 'content-api'
680
+ },
681
+ {
682
+ kind: {
683
+ $null: true
684
+ }
685
+ }
686
+ ]
687
+ };
688
+ } else if (filter?.kind !== undefined) {
689
+ kindWhere = {
690
+ kind: filter.kind
691
+ };
692
+ }
693
+ const where = {
694
+ ...ownershipWhere,
695
+ ...kindWhere
696
+ };
211
697
  const tokens = await strapi.db.query('admin::api-token').findMany({
212
698
  select: SELECT_FIELDS,
213
699
  populate: POPULATE_FIELDS,
214
700
  orderBy: {
215
701
  name: 'ASC'
216
- }
702
+ },
703
+ where
217
704
  });
218
705
  if (!tokens) {
219
706
  return tokens;
220
707
  }
221
- return tokens.map((token)=>flattenTokenPermissions(token));
708
+ return tokens.map((token)=>token.kind === null || token.kind === 'content-api' ? omit([
709
+ 'adminPermissions',
710
+ 'adminUserOwner'
711
+ ], {
712
+ ...token,
713
+ // Tokens created before kind introduction case: force kind to be content-api
714
+ kind: 'content-api',
715
+ permissions: flattenTokenPermissions(token.permissions)
716
+ }) : {
717
+ ...omit([
718
+ 'permissions'
719
+ ], token),
720
+ adminUserOwner: toAdminTokenOwner(token.adminUserOwner)
721
+ });
222
722
  };
223
723
  /**
224
724
  * Revoke (delete) a token
225
725
  */ const revoke = async (id)=>{
226
- return strapi.db.query('admin::api-token').delete({
726
+ const token = await strapi.db.query('admin::api-token').findOne({
727
+ where: {
728
+ id
729
+ },
730
+ select: [
731
+ 'id'
732
+ ],
733
+ populate: [
734
+ 'adminPermissions'
735
+ ]
736
+ });
737
+ if (token !== null && token !== undefined) {
738
+ const permissionIds = (token.adminPermissions ?? []).map((p)=>p.id).filter((permId)=>permId !== null && permId !== undefined);
739
+ if (permissionIds.length > 0) {
740
+ await getService('permission').deleteByIds(permissionIds);
741
+ }
742
+ }
743
+ const deletedToken = await strapi.db.query('admin::api-token').delete({
227
744
  select: SELECT_FIELDS,
228
745
  populate: POPULATE_FIELDS,
229
746
  where: {
230
747
  id
231
748
  }
232
749
  });
233
- };
234
- /**
235
- * Retrieve a token by id
236
- */ const getById = async (id)=>{
237
- return getBy({
238
- id
239
- });
240
- };
241
- /**
242
- * Retrieve a token by name
243
- */ const getByName = async (name)=>{
244
- return getBy({
245
- name
246
- });
750
+ if (deletedToken === null || deletedToken === undefined || deletedToken.kind !== 'admin') {
751
+ return deletedToken;
752
+ }
753
+ return {
754
+ ...deletedToken,
755
+ adminUserOwner: toAdminTokenOwner(deletedToken.adminUserOwner)
756
+ };
247
757
  };
248
758
  /**
249
759
  * Update a token and its permissions
250
760
  */ const update = async (id, attributes)=>{
251
- // retrieve token without permissions
252
761
  const originalToken = await strapi.db.query('admin::api-token').findOne({
762
+ select: SELECT_FIELDS,
763
+ populate: [
764
+ 'adminUserOwner'
765
+ ],
253
766
  where: {
254
767
  id
255
768
  }
@@ -257,55 +770,112 @@ For security reasons, prefer storing the secret in an environment variable and r
257
770
  if (!originalToken) {
258
771
  throw new NotFoundError('Token not found');
259
772
  }
260
- const changingTypeToCustom = attributes.type === constants.API_TOKEN_TYPE.CUSTOM && originalToken.type !== constants.API_TOKEN_TYPE.CUSTOM;
261
- // if we're updating the permissions on any token type, or changing from non-custom to custom, ensure they're still valid
262
- // if neither type nor permissions are changing, we don't need to validate again or else we can't allow partial update
263
- if (attributes.permissions || changingTypeToCustom) {
264
- assertCustomTokenPermissionsValidity(attributes.type || originalToken.type, attributes.permissions || originalToken.permissions);
773
+ const raw = attributes;
774
+ // kind is immutable after creation
775
+ if (raw.kind !== undefined && raw.kind !== null && raw.kind !== originalToken.kind) {
776
+ throw new ValidationError('kind is immutable after creation');
265
777
  }
266
778
  assertValidLifespan(attributes.lifespan);
779
+ let clampedAdminPermissions;
780
+ let tokenOwnerUser;
781
+ if (originalToken.kind === 'content-api') {
782
+ assertLegacyKindFields(attributes);
783
+ const incomingType = raw.type;
784
+ const incomingPermissions = raw.permissions;
785
+ const resolvedType = incomingType ?? originalToken.type;
786
+ const changingTypeToCustom = incomingType === constants.API_TOKEN_TYPE.CUSTOM && originalToken.type !== constants.API_TOKEN_TYPE.CUSTOM;
787
+ // Only re-validate if permissions or type are being changed
788
+ if (incomingPermissions !== undefined || changingTypeToCustom) {
789
+ assertCustomTokenPermissionsValidity(resolvedType, incomingPermissions ?? originalToken.permissions);
790
+ }
791
+ } else if (originalToken.kind === 'admin') {
792
+ assertAdminKindFields(attributes);
793
+ const incomingAdminPermissions = raw.adminPermissions;
794
+ if (incomingAdminPermissions !== undefined) {
795
+ await assertAdminPermissionsValidity(incomingAdminPermissions);
796
+ // Ceiling is always the owner's permissions, not the calling user's.
797
+ // A super admin editing another user's token must not overflow that user's scope.
798
+ const ownerId = getOwnerId(originalToken);
799
+ const resolvedOwner = await getService('user').findOne(ownerId);
800
+ if (resolvedOwner === null || resolvedOwner === undefined) {
801
+ throw new ValidationError('Token owner no longer exists');
802
+ }
803
+ tokenOwnerUser = resolvedOwner;
804
+ clampedAdminPermissions = await enforceAdminPermissionsCeiling(tokenOwnerUser, incomingAdminPermissions);
805
+ }
806
+ const incomingAdminUserOwner = raw.adminUserOwner;
807
+ if (incomingAdminUserOwner !== undefined) {
808
+ // Owner is immutable; the provided value must match the existing one
809
+ const existingOwner = originalToken.adminUserOwner;
810
+ const existingOwnerId = existingOwner === null || existingOwner === undefined ? null : String(typeof existingOwner === 'object' ? existingOwner.id : existingOwner);
811
+ const requestedOwnerId = incomingAdminUserOwner === null ? null : String(incomingAdminUserOwner);
812
+ if (requestedOwnerId !== existingOwnerId) {
813
+ throw new ValidationError('adminUserOwner cannot be changed on update');
814
+ }
815
+ }
816
+ }
267
817
  const updatedToken = await strapi.db.query('admin::api-token').update({
268
818
  select: SELECT_FIELDS,
269
819
  where: {
270
820
  id
271
821
  },
272
- data: omit('permissions', attributes)
822
+ // kind is immutable — strip it along with relation fields so the DB write is clean
823
+ data: omit([
824
+ 'kind',
825
+ 'permissions',
826
+ 'adminPermissions',
827
+ 'adminUserOwner'
828
+ ], attributes)
273
829
  });
274
- // custom tokens need to have their permissions updated as well
275
- if (updatedToken.type === constants.API_TOKEN_TYPE.CUSTOM && attributes.permissions) {
276
- const currentPermissionsResult = await strapi.db.query('admin::api-token').load(updatedToken, 'permissions');
277
- const currentPermissions = map('action', currentPermissionsResult || []);
278
- const newPermissions = uniq(attributes.permissions);
279
- const actionsToDelete = difference(currentPermissions, newPermissions);
280
- const actionsToAdd = difference(newPermissions, currentPermissions);
281
- // TODO: improve efficiency here
282
- // method using a loop -- works but very inefficient
283
- await Promise.all(actionsToDelete.map((action)=>strapi.db.query('admin::api-token-permission').delete({
830
+ if (originalToken.kind === 'content-api') {
831
+ const incomingPermissions = raw.permissions;
832
+ // custom tokens need to have their permissions updated as well
833
+ if (updatedToken.type === constants.API_TOKEN_TYPE.CUSTOM && incomingPermissions !== undefined) {
834
+ const currentPermissionsResult = await strapi.db.query('admin::api-token').load(updatedToken, 'permissions');
835
+ const currentPermissions = map('action', currentPermissionsResult || []);
836
+ const newPermissions = uniq(incomingPermissions || []);
837
+ const actionsToDelete = difference(currentPermissions, newPermissions);
838
+ const actionsToAdd = difference(newPermissions, currentPermissions);
839
+ // TODO: improve efficiency here
840
+ await Promise.all(actionsToDelete.map((action)=>strapi.db.query('admin::api-token-permission').delete({
841
+ where: {
842
+ action,
843
+ token: id
844
+ }
845
+ })));
846
+ // TODO: improve efficiency here
847
+ await Promise.all(actionsToAdd.map((action)=>strapi.db.query('admin::api-token-permission').create({
848
+ data: {
849
+ action,
850
+ token: id
851
+ }
852
+ })));
853
+ } else if (updatedToken.type !== constants.API_TOKEN_TYPE.CUSTOM) {
854
+ await strapi.db.query('admin::api-token-permission').delete({
284
855
  where: {
285
- action,
286
856
  token: id
287
857
  }
288
- })));
289
- // TODO: improve efficiency here
290
- // using a loop -- works but very inefficient
291
- await Promise.all(actionsToAdd.map((action)=>strapi.db.query('admin::api-token-permission').create({
292
- data: {
293
- action,
294
- token: id
295
- }
296
- })));
297
- } else if (updatedToken.type !== constants.API_TOKEN_TYPE.CUSTOM) {
298
- await strapi.db.query('admin::api-token-permission').delete({
299
- where: {
300
- token: id
301
- }
302
- });
858
+ });
859
+ }
860
+ const permissionsFromDb = await strapi.db.query('admin::api-token').load(updatedToken, 'permissions');
861
+ return {
862
+ ...updatedToken,
863
+ permissions: permissionsFromDb ? permissionsFromDb.map((p)=>p.action) : undefined
864
+ };
865
+ }
866
+ // kind === 'admin'
867
+ if (clampedAdminPermissions !== undefined) {
868
+ if (tokenOwnerUser === undefined) {
869
+ throw new ValidationError('Updating admin permissions requires a resolved token owner');
870
+ }
871
+ await assignAdminPermissionsToToken(id, clampedAdminPermissions, tokenOwnerUser);
303
872
  }
304
- // retrieve permissions
305
- const permissionsFromDb = await strapi.db.query('admin::api-token').load(updatedToken, 'permissions');
873
+ const adminPermissionsFromDb = await strapi.db.query('admin::api-token').load(updatedToken, 'adminPermissions');
874
+ const adminUserOwnerFromDb = await strapi.db.query('admin::api-token').load(updatedToken, 'adminUserOwner');
306
875
  return {
307
876
  ...updatedToken,
308
- permissions: permissionsFromDb ? permissionsFromDb.map((p)=>p.action) : undefined
877
+ adminPermissions: adminPermissionsFromDb || [],
878
+ adminUserOwner: toAdminTokenOwner(adminUserOwnerFromDb)
309
879
  };
310
880
  };
311
881
  const count = async (where = {})=>{
@@ -313,6 +883,135 @@ const count = async (where = {})=>{
313
883
  where
314
884
  });
315
885
  };
886
+ /**
887
+ * Delete all admin API tokens owned by the given user, including their associated admin permissions.
888
+ * Called when the owner user is deleted so tokens don't linger with a dangling owner FK.
889
+ */ const deleteAdminTokensForUser = async (userId)=>{
890
+ const tokens = await strapi.db.query('admin::api-token').findMany({
891
+ where: {
892
+ kind: 'admin',
893
+ adminUserOwner: {
894
+ id: userId
895
+ }
896
+ },
897
+ select: [
898
+ 'id'
899
+ ],
900
+ populate: [
901
+ 'adminPermissions'
902
+ ]
903
+ });
904
+ for (const token of tokens){
905
+ const permissionIds = (token.adminPermissions ?? []).map((p)=>p.id).filter((id)=>id !== null && id !== undefined);
906
+ if (permissionIds.length > 0) {
907
+ await getService('permission').deleteByIds(permissionIds);
908
+ }
909
+ await strapi.db.query('admin::api-token').delete({
910
+ where: {
911
+ id: token.id
912
+ }
913
+ });
914
+ }
915
+ };
916
+ function createTokenService(kind) {
917
+ const shared = {
918
+ hash,
919
+ checkSaltIsDefined,
920
+ getByAccessKey: (accessKeyHash, options)=>getBy({
921
+ accessKey: accessKeyHash
922
+ }, options),
923
+ countAll: count,
924
+ reconcileTokenPermissionsToUserCeiling
925
+ };
926
+ if (kind === 'content-api') {
927
+ const svc = {
928
+ ...shared,
929
+ create: (attributes, callingUser)=>create({
930
+ ...attributes,
931
+ kind: 'content-api'
932
+ }, callingUser),
933
+ list: (callingUser)=>list(callingUser, {
934
+ filter: {
935
+ kind: 'content-api'
936
+ }
937
+ }),
938
+ getById: (id, options)=>getBy({
939
+ $and: [
940
+ {
941
+ id
942
+ },
943
+ {
944
+ $or: [
945
+ {
946
+ kind: 'content-api'
947
+ },
948
+ {
949
+ kind: {
950
+ $null: true
951
+ }
952
+ }
953
+ ]
954
+ }
955
+ ]
956
+ }, options),
957
+ getByName: (name, options)=>getBy({
958
+ $and: [
959
+ {
960
+ name
961
+ },
962
+ {
963
+ $or: [
964
+ {
965
+ kind: 'content-api'
966
+ },
967
+ {
968
+ kind: {
969
+ $null: true
970
+ }
971
+ }
972
+ ]
973
+ }
974
+ ]
975
+ }, options),
976
+ update: (id, attributes)=>update(id, attributes),
977
+ revoke: (id)=>revoke(id),
978
+ regenerate: (id)=>regenerate(id),
979
+ exists,
980
+ count
981
+ };
982
+ return svc;
983
+ }
984
+ const svc = {
985
+ ...shared,
986
+ create: (attributes, callingUser)=>create({
987
+ ...attributes,
988
+ kind: 'admin'
989
+ }, callingUser),
990
+ list: (callingUser)=>list(callingUser, {
991
+ filter: {
992
+ kind: 'admin'
993
+ }
994
+ }),
995
+ getById: (id, options)=>getBy({
996
+ id,
997
+ kind: 'admin'
998
+ }, options),
999
+ getByName: (name, options)=>getBy({
1000
+ name,
1001
+ kind: 'admin'
1002
+ }, options),
1003
+ update: (id, attributes)=>update(id, attributes),
1004
+ revoke: (id)=>revoke(id),
1005
+ regenerate: (id)=>regenerate(id),
1006
+ exists,
1007
+ count,
1008
+ assignAdminPermissionsToToken,
1009
+ syncPermissionsForUser: syncApiTokenPermissionsForUser,
1010
+ syncPermissionsForRole: syncApiTokenPermissionsForRole,
1011
+ deleteTokensForUser: deleteAdminTokensForUser
1012
+ };
1013
+ return svc;
1014
+ }
316
1015
 
317
- export { checkSaltIsDefined, count, create, exists, getBy, getById, getByName, hash, list, regenerate, revoke, update };
1016
+ export { assignAdminPermissionsToToken, checkSaltIsDefined, count, create, createTokenService, deleteAdminTokensForUser, enforceAdminPermissionsCeiling, exists, getBy, hash, list, reconcileTokenPermissionsToUserCeiling, regenerate, revoke, syncApiTokenPermissionsForRole, syncApiTokenPermissionsForUser, update };
318
1017
  //# sourceMappingURL=api-token.mjs.map