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