setup_endpoint.go 8.5 KB

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