setup_endpoint.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. package service
  2. import (
  3. "fmt"
  4. "github.com/langgenius/dify-plugin-daemon/internal/core/dify_invocation"
  5. "github.com/langgenius/dify-plugin-daemon/internal/core/plugin_manager"
  6. "github.com/langgenius/dify-plugin-daemon/internal/db"
  7. "github.com/langgenius/dify-plugin-daemon/internal/service/install_service"
  8. "github.com/langgenius/dify-plugin-daemon/internal/types/entities"
  9. "github.com/langgenius/dify-plugin-daemon/internal/types/entities/plugin_entities"
  10. "github.com/langgenius/dify-plugin-daemon/internal/types/models"
  11. "github.com/langgenius/dify-plugin-daemon/internal/utils/cache/helper"
  12. "github.com/langgenius/dify-plugin-daemon/internal/utils/encryption"
  13. )
  14. func SetupEndpoint(
  15. tenant_id string,
  16. user_id string,
  17. plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
  18. name string,
  19. settings map[string]any,
  20. ) *entities.Response {
  21. // try find plugin installation
  22. installation, err := db.GetOne[models.PluginInstallation](
  23. db.Equal("tenant_id", tenant_id),
  24. db.Equal("plugin_unique_identifier", plugin_unique_identifier.String()),
  25. )
  26. if err != nil {
  27. return entities.NewErrorResponse(-404, fmt.Sprintf("failed to find plugin installation: %v", err))
  28. }
  29. // try get plugin
  30. plugin_declaration, err := helper.CombinedGetPluginDeclaration(plugin_unique_identifier)
  31. if err != nil {
  32. return entities.NewErrorResponse(-404, fmt.Sprintf("failed to find plugin: %v", err))
  33. }
  34. if !plugin_declaration.Resource.Permission.AllowRegisterEndpoint() {
  35. return entities.NewErrorResponse(-403, "permission denied")
  36. }
  37. if plugin_declaration.Endpoint == nil {
  38. return entities.NewErrorResponse(-404, "plugin does not have an endpoint")
  39. }
  40. // check settings
  41. if err := plugin_entities.ValidateProviderConfigs(settings, plugin_declaration.Endpoint.Settings); err != nil {
  42. return entities.NewErrorResponse(-400, fmt.Sprintf("failed to validate settings: %v", err))
  43. }
  44. endpoint, err := install_service.InstallEndpoint(
  45. plugin_unique_identifier,
  46. installation.ID,
  47. tenant_id,
  48. user_id,
  49. name,
  50. map[string]any{},
  51. )
  52. if err != nil {
  53. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to setup endpoint: %v", err))
  54. }
  55. manager := plugin_manager.Manager()
  56. if manager == nil {
  57. return entities.NewErrorResponse(-500, "failed to get plugin manager")
  58. }
  59. // encrypt settings
  60. encrypted_settings, err := manager.BackwardsInvocation().InvokeEncrypt(
  61. &dify_invocation.InvokeEncryptRequest{
  62. BaseInvokeDifyRequest: dify_invocation.BaseInvokeDifyRequest{
  63. TenantId: tenant_id,
  64. UserId: user_id,
  65. Type: dify_invocation.INVOKE_TYPE_ENCRYPT,
  66. },
  67. InvokeEncryptSchema: dify_invocation.InvokeEncryptSchema{
  68. Opt: dify_invocation.ENCRYPT_OPT_ENCRYPT,
  69. Namespace: dify_invocation.ENCRYPT_NAMESPACE_ENDPOINT,
  70. Identity: endpoint.ID,
  71. Data: settings,
  72. Config: plugin_declaration.Endpoint.Settings,
  73. },
  74. },
  75. )
  76. if err != nil {
  77. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to encrypt settings: %v", err))
  78. }
  79. if err := install_service.UpdateEndpoint(endpoint, name, encrypted_settings); err != nil {
  80. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to update endpoint: %v", err))
  81. }
  82. return entities.NewSuccessResponse(true)
  83. }
  84. func RemoveEndpoint(endpoint_id string, tenant_id string) *entities.Response {
  85. endpoint, err := db.GetOne[models.Endpoint](
  86. db.Equal("id", endpoint_id),
  87. db.Equal("tenant_id", tenant_id),
  88. )
  89. if err != nil {
  90. return entities.NewErrorResponse(-404, fmt.Sprintf("failed to find endpoint: %v", err))
  91. }
  92. err = install_service.UninstallEndpoint(&endpoint)
  93. if err != nil {
  94. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to remove endpoint: %v", err))
  95. }
  96. manager := plugin_manager.Manager()
  97. if manager == nil {
  98. return entities.NewErrorResponse(-500, "failed to get plugin manager")
  99. }
  100. // clear credentials cache
  101. if _, err := manager.BackwardsInvocation().InvokeEncrypt(&dify_invocation.InvokeEncryptRequest{
  102. BaseInvokeDifyRequest: dify_invocation.BaseInvokeDifyRequest{
  103. TenantId: tenant_id,
  104. UserId: "",
  105. Type: dify_invocation.INVOKE_TYPE_ENCRYPT,
  106. },
  107. InvokeEncryptSchema: dify_invocation.InvokeEncryptSchema{
  108. Opt: dify_invocation.ENCRYPT_OPT_CLEAR,
  109. Namespace: dify_invocation.ENCRYPT_NAMESPACE_ENDPOINT,
  110. Identity: endpoint.ID,
  111. },
  112. }); err != nil {
  113. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to clear credentials cache: %v", err))
  114. }
  115. return entities.NewSuccessResponse(true)
  116. }
  117. func UpdateEndpoint(endpoint_id string, tenant_id string, user_id string, name string, settings map[string]any) *entities.Response {
  118. // get endpoint
  119. endpoint, err := db.GetOne[models.Endpoint](
  120. db.Equal("id", endpoint_id),
  121. db.Equal("tenant_id", tenant_id),
  122. )
  123. if err != nil {
  124. return entities.NewErrorResponse(-404, fmt.Sprintf("failed to find endpoint: %v", err))
  125. }
  126. // get plugin installation
  127. installation, err := db.GetOne[models.PluginInstallation](
  128. db.Equal("plugin_id", endpoint.PluginID),
  129. db.Equal("tenant_id", tenant_id),
  130. )
  131. if err != nil {
  132. return entities.NewErrorResponse(-404, fmt.Sprintf("failed to find plugin installation: %v", err))
  133. }
  134. plugin_unique_identifier, err := plugin_entities.NewPluginUniqueIdentifier(
  135. installation.PluginUniqueIdentifier,
  136. )
  137. if err != nil {
  138. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to parse plugin unique identifier: %v", err))
  139. }
  140. // get plugin
  141. plugin_declaration, err := helper.CombinedGetPluginDeclaration(plugin_unique_identifier)
  142. if err != nil {
  143. return entities.NewErrorResponse(-404, fmt.Sprintf("failed to find plugin: %v", err))
  144. }
  145. if plugin_declaration.Endpoint == nil {
  146. return entities.NewErrorResponse(-404, "plugin does not have an endpoint")
  147. }
  148. // decrypt original settings
  149. manager := plugin_manager.Manager()
  150. if manager == nil {
  151. return entities.NewErrorResponse(-500, "failed to get plugin manager")
  152. }
  153. original_settings, err := manager.BackwardsInvocation().InvokeEncrypt(
  154. &dify_invocation.InvokeEncryptRequest{
  155. BaseInvokeDifyRequest: dify_invocation.BaseInvokeDifyRequest{
  156. TenantId: tenant_id,
  157. UserId: user_id,
  158. Type: dify_invocation.INVOKE_TYPE_ENCRYPT,
  159. },
  160. InvokeEncryptSchema: dify_invocation.InvokeEncryptSchema{
  161. Opt: dify_invocation.ENCRYPT_OPT_DECRYPT,
  162. Namespace: dify_invocation.ENCRYPT_NAMESPACE_ENDPOINT,
  163. Identity: endpoint.ID,
  164. Data: endpoint.Settings,
  165. Config: plugin_declaration.Endpoint.Settings,
  166. },
  167. },
  168. )
  169. if err != nil {
  170. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to decrypt settings: %v", err))
  171. }
  172. masked_settings := encryption.MaskConfigCredentials(original_settings, plugin_declaration.Endpoint.Settings)
  173. // check if settings is changed, replace the value is the same as masked_settings
  174. for setting_name, value := range settings {
  175. if masked_settings[setting_name] == value {
  176. settings[setting_name] = original_settings[setting_name]
  177. }
  178. }
  179. // check settings
  180. if err := plugin_entities.ValidateProviderConfigs(settings, plugin_declaration.Endpoint.Settings); err != nil {
  181. return entities.NewErrorResponse(-400, fmt.Sprintf("failed to validate settings: %v", err))
  182. }
  183. // encrypt settings
  184. encrypted_settings, err := manager.BackwardsInvocation().InvokeEncrypt(
  185. &dify_invocation.InvokeEncryptRequest{
  186. BaseInvokeDifyRequest: dify_invocation.BaseInvokeDifyRequest{
  187. TenantId: tenant_id,
  188. UserId: user_id,
  189. Type: dify_invocation.INVOKE_TYPE_ENCRYPT,
  190. },
  191. InvokeEncryptSchema: dify_invocation.InvokeEncryptSchema{
  192. Opt: dify_invocation.ENCRYPT_OPT_ENCRYPT,
  193. Namespace: dify_invocation.ENCRYPT_NAMESPACE_ENDPOINT,
  194. Identity: endpoint.ID,
  195. Data: settings,
  196. Config: plugin_declaration.Endpoint.Settings,
  197. },
  198. },
  199. )
  200. if err != nil {
  201. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to encrypt settings: %v", err))
  202. }
  203. // update endpoint
  204. if err := install_service.UpdateEndpoint(&endpoint, name, encrypted_settings); err != nil {
  205. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to update endpoint: %v", err))
  206. }
  207. // clear credentials cache
  208. if _, err := manager.BackwardsInvocation().InvokeEncrypt(&dify_invocation.InvokeEncryptRequest{
  209. BaseInvokeDifyRequest: dify_invocation.BaseInvokeDifyRequest{
  210. TenantId: tenant_id,
  211. UserId: user_id,
  212. Type: dify_invocation.INVOKE_TYPE_ENCRYPT,
  213. },
  214. InvokeEncryptSchema: dify_invocation.InvokeEncryptSchema{
  215. Opt: dify_invocation.ENCRYPT_OPT_CLEAR,
  216. Namespace: dify_invocation.ENCRYPT_NAMESPACE_ENDPOINT,
  217. Identity: endpoint.ID,
  218. Data: settings,
  219. Config: plugin_declaration.Endpoint.Settings,
  220. },
  221. }); err != nil {
  222. return entities.NewErrorResponse(-500, fmt.Sprintf("failed to clear credentials cache: %v", err))
  223. }
  224. return entities.NewSuccessResponse(true)
  225. }