AdminRepository.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. const axios = require('axios');
  2. const qs = require('qs');
  3. const {
  4. KEYCLOAK_REALM,
  5. KEYCLOAK_ADMIN_URL,
  6. CLIENT_ID,
  7. CLIENT_SECRET
  8. } = require('../../../config/keycloak.js');
  9. const HttpException = require('../../utils/HttpException.js');
  10. const bcrypt = require('bcrypt');
  11. const prisma = require('../../prisma/PrismaClient.js');
  12. const getAdminToken = async () => {
  13. const tokenParams = qs.stringify({
  14. grant_type: 'client_credentials',
  15. client_id: CLIENT_ID,
  16. client_secret: CLIENT_SECRET
  17. });
  18. const { data } = await axios.post(
  19. `${KEYCLOAK_ADMIN_URL}/realms/${KEYCLOAK_REALM}/protocol/openid-connect/token`,
  20. tokenParams,
  21. {
  22. headers: {
  23. 'Content-Type': 'application/x-www-form-urlencoded'
  24. }
  25. }
  26. );
  27. return data.access_token;
  28. };
  29. const KeycloakRepository = {
  30. createUser: async (userData) => {
  31. const token = await getAdminToken();
  32. // Cek apakah username sudah terpakai
  33. const { data: usersByUsername } = await axios.get(
  34. `${KEYCLOAK_ADMIN_URL}/admin/realms/${KEYCLOAK_REALM}/users?username=${encodeURIComponent(userData.username)}`,
  35. { headers: { Authorization: `Bearer ${token}` } }
  36. );
  37. if (usersByUsername.length > 0) {
  38. throw new HttpException('Username already exists in Keycloak', 409);
  39. }
  40. // Cek apakah email sudah terpakai
  41. const { data: usersByEmail } = await axios.get(
  42. `${KEYCLOAK_ADMIN_URL}/admin/realms/${KEYCLOAK_REALM}/users?email=${encodeURIComponent(userData.email)}`,
  43. { headers: { Authorization: `Bearer ${token}` } }
  44. );
  45. if (usersByEmail.length > 0) {
  46. throw new HttpException('Email already exists in Keycloak', 409);
  47. }
  48. const response = await axios.post(
  49. `${KEYCLOAK_ADMIN_URL}/admin/realms/${KEYCLOAK_REALM}/users`,
  50. {
  51. username: userData.username,
  52. email: userData.email,
  53. firstName: userData.firstname,
  54. lastName: userData.lastname,
  55. enabled: true,
  56. credentials: [{
  57. type: "password",
  58. value: userData.password,
  59. temporary: false
  60. }]
  61. },
  62. { headers: { Authorization: `Bearer ${token}` } }
  63. );
  64. return response.headers.location.split('/').pop();
  65. },
  66. assignAdminRole: async (userId) => {
  67. const token = await getAdminToken();
  68. // Get role sales
  69. const { data: roles } = await axios.get(
  70. `${KEYCLOAK_ADMIN_URL}/admin/realms/${KEYCLOAK_REALM}/roles`,
  71. { headers: { Authorization: `Bearer ${token}` } }
  72. );
  73. const adminRole = roles.find(role => role.name === 'admin');
  74. if (!adminRole) throw new HttpException('Admin role not found in Keycloak', 500);
  75. // Assign role to user
  76. await axios.post(
  77. `${KEYCLOAK_ADMIN_URL}/admin/realms/${KEYCLOAK_REALM}/users/${userId}/role-mappings/realm`,
  78. [adminRole],
  79. { headers: { Authorization: `Bearer ${token}` } }
  80. );
  81. },
  82. updateUser: async (userId, updatedData) => {
  83. const token = await getAdminToken();
  84. await axios.put(
  85. `${KEYCLOAK_ADMIN_URL}/admin/realms/${KEYCLOAK_REALM}/users/${userId}`,
  86. {
  87. firstName: updatedData.firstname,
  88. lastName: updatedData.lastname,
  89. email: updatedData.email,
  90. credentials: updatedData.password ? [{
  91. type: 'password',
  92. value: updatedData.password,
  93. temporary: false
  94. }] : undefined
  95. },
  96. { headers: { Authorization: `Bearer ${token}` } }
  97. );
  98. },
  99. deleteUser: async (userId) => {
  100. const token = await getAdminToken();
  101. await axios.delete(
  102. `${KEYCLOAK_ADMIN_URL}/admin/realms/${KEYCLOAK_REALM}/users/${userId}`,
  103. { headers: { Authorization: `Bearer ${token}` } }
  104. );
  105. }
  106. };
  107. const AdminRepository = {
  108. createUser: async (userId, userData) => {
  109. const hashedPassword = await bcrypt.hash(userData.password, 10);
  110. return prisma.user.create({
  111. data: {
  112. id: userId,
  113. username: userData.username,
  114. email: userData.email,
  115. firstname: userData.firstname,
  116. lastname: userData.lastname,
  117. password: hashedPassword,
  118. role: 'admin'
  119. }
  120. });
  121. },
  122. findAll: async ({ skip, take, where, orderBy }) => {
  123. return prisma.user.findMany({
  124. where: {
  125. ...where,
  126. role: 'admin'
  127. },
  128. skip,
  129. take,
  130. orderBy,
  131. select: {
  132. id: true,
  133. username: true,
  134. email: true,
  135. firstname: true,
  136. lastname: true,
  137. role: true,
  138. createdAt: true,
  139. updatedAt: true,
  140. },
  141. });
  142. },
  143. countAll: async (where) => {
  144. return prisma.user.count({
  145. where: {
  146. ...where,
  147. role: 'admin'
  148. }
  149. });
  150. },
  151. findById: async (id) => {
  152. return prisma.user.findFirst({
  153. where: {
  154. id,
  155. deletedAt: null
  156. },
  157. select: {
  158. id: true,
  159. username: true,
  160. email: true,
  161. firstname: true,
  162. lastname: true,
  163. createdAt: true,
  164. updatedAt: true,
  165. }
  166. });
  167. },
  168. updateUser: async (id, updatedData) => {
  169. const updatePayload = {
  170. email: updatedData.email,
  171. firstname: updatedData.firstname,
  172. lastname: updatedData.lastname
  173. };
  174. if (updatedData.password) {
  175. updatePayload.password = await bcrypt.hash(updatedData.password, 10);
  176. }
  177. return prisma.user.update({
  178. where: { id },
  179. data: updatePayload
  180. });
  181. },
  182. deleteUser: async (id) => {
  183. return prisma.user.update({
  184. where: { id },
  185. data: {
  186. deletedAt: new Date()
  187. }
  188. });
  189. }
  190. };
  191. module.exports = { KeycloakRepository, AdminRepository };