delete_groups_nextcloud_scope.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import dotenv from 'dotenv';
  2. import axios from 'axios';
  3. // Load environment variables
  4. dotenv.config();
  5. console.log('Environment variables loaded.');
  6. // Configuration constants
  7. const KEYCLOAK_URL = process.env.KEYCLOAK_URL || 'https://auth.mrx8086.com';
  8. const ADMIN_USERNAME = process.env.KEYCLOAK_ADMIN_USER;
  9. const ADMIN_PASSWORD = process.env.KEYCLOAK_ADMIN_PASSWORD;
  10. const REALM_NAME = 'office-automation';
  11. console.log('Configuration constants set:', { KEYCLOAK_URL, ADMIN_USERNAME, REALM_NAME });
  12. // Helper function for API error handling
  13. const handleAxiosError = (error, operation, config, response) => {
  14. console.error(`Error during ${operation}:`);
  15. if (config) {
  16. console.error('Request:', {
  17. method: config.method,
  18. url: config.url,
  19. headers: config.headers,
  20. data: config.data,
  21. });
  22. }
  23. if (error.response) {
  24. console.error('Response:', {
  25. status: error.response.status,
  26. data: error.response.data
  27. });
  28. } else {
  29. console.error('Error Message:', error.message);
  30. }
  31. throw error;
  32. };
  33. // Get Admin Token
  34. async function getAdminToken() {
  35. console.log('Getting admin token...');
  36. try {
  37. const response = await axios.post(
  38. `${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token`,
  39. new URLSearchParams({
  40. 'client_id': 'admin-cli',
  41. 'username': ADMIN_USERNAME,
  42. 'password': ADMIN_PASSWORD,
  43. 'grant_type': 'password'
  44. }),
  45. {
  46. headers: {
  47. 'Content-Type': 'application/x-www-form-urlencoded'
  48. }
  49. }
  50. );
  51. console.log('Admin token received.');
  52. return response.data.access_token;
  53. } catch (error) {
  54. handleAxiosError(error, 'getting admin token');
  55. }
  56. }
  57. async function getClientScope(token, scopeName) {
  58. console.log(`Getting client scope ${scopeName}...`);
  59. try {
  60. const response = await axios.get(
  61. `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/client-scopes`,
  62. {
  63. headers: {
  64. 'Authorization': `Bearer ${token}`
  65. },
  66. params: {
  67. name: scopeName
  68. }
  69. }
  70. );
  71. if (response.data.length === 0) {
  72. console.log(`Client Scope ${scopeName} not found`);
  73. return null;
  74. }
  75. console.log(`Client scope ${scopeName} found.`);
  76. return response.data[0]
  77. } catch (error) {
  78. handleAxiosError(error, `getting client scope ${scopeName}`, error.config, error.response);
  79. return null;
  80. }
  81. }
  82. async function deleteClientScope(token, scopeId) {
  83. console.log(`Deleting client scope with ID ${scopeId}...`);
  84. try {
  85. await axios.delete(
  86. `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/client-scopes/${scopeId}`,
  87. {
  88. headers: {
  89. 'Authorization': `Bearer ${token}`
  90. }
  91. }
  92. );
  93. console.log(`Client scope with ID ${scopeId} deleted successfully.`);
  94. } catch (error) {
  95. handleAxiosError(error, `deleting client scope with ID ${scopeId}`);
  96. }
  97. }
  98. async function deleteMapper(token, scopeId, mapperId) {
  99. console.log(`Deleting mapper ${mapperId} of client scope with ID ${scopeId}`);
  100. try {
  101. await axios.delete(
  102. `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/client-scopes/${scopeId}/protocol-mappers/models/${mapperId}`,
  103. {
  104. headers: {
  105. 'Authorization': `Bearer ${token}`
  106. }
  107. }
  108. );
  109. console.log(`Mapper with ID ${mapperId} deleted successfully.`);
  110. } catch (error) {
  111. handleAxiosError(error, `deleting mapper ${mapperId} for client scope with ID ${scopeId}`);
  112. }
  113. }
  114. async function getClientScopeMappers(token, scopeId) {
  115. console.log(`Getting mappers for client scope with ID ${scopeId}...`);
  116. try {
  117. const response = await axios.get(
  118. `${KEYCLOAK_URL}/admin/realms/${REALM_NAME}/client-scopes/${scopeId}/protocol-mappers/models`,
  119. {
  120. headers: {
  121. 'Authorization': `Bearer ${token}`
  122. }
  123. }
  124. );
  125. console.log(`Mappers for client scope with ID ${scopeId} retrieved.`);
  126. return response.data
  127. } catch (error) {
  128. handleAxiosError(error, `getting mappers for client scope with ID ${scopeId}`);
  129. return [];
  130. }
  131. }
  132. async function deleteGroupsNextcloudScope() {
  133. try {
  134. console.log('Starting deletion of groups-nextcloud scope and its mapper...');
  135. const token = await getAdminToken();
  136. const clientScope = await getClientScope(token, "groups-nextcloud");
  137. if (!clientScope) {
  138. console.log("Client scope groups-nextcloud not found, nothing to delete.")
  139. return;
  140. }
  141. const mappers = await getClientScopeMappers(token, clientScope.id)
  142. const groupsMapper = mappers.find(m => m.name === "groups-mapper");
  143. if (groupsMapper)
  144. await deleteMapper(token, clientScope.id, groupsMapper.id)
  145. await deleteClientScope(token, clientScope.id);
  146. console.log('Deletion of groups-nextcloud scope and its mapper completed successfully.');
  147. } catch (error) {
  148. console.error('Deletion failed:', error);
  149. process.exit(1);
  150. }
  151. }
  152. // Execute the deletion
  153. deleteGroupsNextcloudScope();