install_plugin.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. package service
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "mime/multipart"
  7. "github.com/gin-gonic/gin"
  8. "github.com/langgenius/dify-plugin-daemon/internal/core/plugin_packager/decoder"
  9. "github.com/langgenius/dify-plugin-daemon/internal/core/plugin_packager/verifier"
  10. "github.com/langgenius/dify-plugin-daemon/internal/db"
  11. "github.com/langgenius/dify-plugin-daemon/internal/types/app"
  12. "github.com/langgenius/dify-plugin-daemon/internal/types/entities"
  13. "github.com/langgenius/dify-plugin-daemon/internal/types/entities/plugin_entities"
  14. "github.com/langgenius/dify-plugin-daemon/internal/types/models"
  15. "github.com/langgenius/dify-plugin-daemon/internal/types/models/curd"
  16. )
  17. func UploadPluginFromPkg(
  18. config *app.Config,
  19. c *gin.Context,
  20. tenant_id string,
  21. dify_pkg_file multipart.File,
  22. verify_signature bool,
  23. ) *entities.Response {
  24. plugin_file, err := io.ReadAll(dify_pkg_file)
  25. if err != nil {
  26. return entities.NewErrorResponse(-500, err.Error())
  27. }
  28. decoder, err := decoder.NewZipPluginDecoder(plugin_file)
  29. if err != nil {
  30. return entities.NewErrorResponse(-500, err.Error())
  31. }
  32. if config.ForceVerifyingSignature || verify_signature {
  33. err := verifier.VerifyPlugin(decoder)
  34. if err != nil {
  35. return entities.NewErrorResponse(-500, errors.Join(err, errors.New(
  36. "plugin verification has been enabled, and the plugin you want to install has a bad signature",
  37. )).Error())
  38. }
  39. }
  40. manifest, err := decoder.Manifest()
  41. if err != nil {
  42. return entities.NewErrorResponse(-500, err.Error())
  43. }
  44. return entities.NewSuccessResponse(manifest.Identity())
  45. }
  46. func InstallPluginFromIdentifiers(
  47. tenant_id string,
  48. plugin_unique_identifiers []plugin_entities.PluginUniqueIdentifier,
  49. source string,
  50. meta map[string]any,
  51. ) *entities.Response {
  52. // TODO: create installation task and dispatch to workers
  53. for _, plugin_unique_identifier := range plugin_unique_identifiers {
  54. if err := InstallPluginFromIdentifier(tenant_id, plugin_unique_identifier, source, meta); err != nil {
  55. return entities.NewErrorResponse(-500, err.Error())
  56. }
  57. }
  58. return entities.NewSuccessResponse(true)
  59. }
  60. func FetchPluginInstallationTasks(
  61. tenant_id string,
  62. page int,
  63. page_size int,
  64. ) *entities.Response {
  65. return nil
  66. }
  67. func FetchPluginInstallationTask(
  68. tenant_id string,
  69. task_id string,
  70. ) *entities.Response {
  71. return nil
  72. }
  73. func FetchPluginManifest(
  74. tenant_id string,
  75. plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
  76. ) *entities.Response {
  77. return nil
  78. }
  79. func InstallPluginFromIdentifier(
  80. tenant_id string,
  81. plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
  82. source string,
  83. meta map[string]any,
  84. ) error {
  85. // TODO: refactor
  86. // check if identifier exists
  87. plugin, err := db.GetOne[models.Plugin](
  88. db.Equal("plugin_unique_identifier", plugin_unique_identifier.String()),
  89. )
  90. if err == db.ErrDatabaseNotFound {
  91. return errors.New("plugin not found")
  92. }
  93. if err != nil {
  94. return err
  95. }
  96. if plugin.InstallType == plugin_entities.PLUGIN_RUNTIME_TYPE_REMOTE {
  97. return errors.New("remote plugin not supported")
  98. }
  99. declaration := plugin.Declaration
  100. // install to this workspace
  101. if _, _, err := curd.InstallPlugin(tenant_id, plugin_unique_identifier, plugin.InstallType, &declaration, source, meta); err != nil {
  102. return err
  103. }
  104. return nil
  105. }
  106. func FetchPluginFromIdentifier(
  107. plugin_unique_identifier plugin_entities.PluginUniqueIdentifier,
  108. ) *entities.Response {
  109. _, err := db.GetOne[models.Plugin](
  110. db.Equal("plugin_unique_identifier", plugin_unique_identifier.String()),
  111. )
  112. if err == db.ErrDatabaseNotFound {
  113. return entities.NewSuccessResponse(false)
  114. }
  115. if err != nil {
  116. return entities.NewErrorResponse(-500, err.Error())
  117. }
  118. return entities.NewSuccessResponse(true)
  119. }
  120. func UninstallPlugin(
  121. tenant_id string,
  122. plugin_installation_id string,
  123. ) *entities.Response {
  124. // Check if the plugin exists for the tenant
  125. installation, err := db.GetOne[models.PluginInstallation](
  126. db.Equal("tenant_id", tenant_id),
  127. db.Equal("id", plugin_installation_id),
  128. )
  129. if err == db.ErrDatabaseNotFound {
  130. return entities.NewErrorResponse(-404, "Plugin installation not found for this tenant")
  131. }
  132. if err != nil {
  133. return entities.NewErrorResponse(-500, err.Error())
  134. }
  135. // Uninstall the plugin
  136. _, err = curd.UninstallPlugin(
  137. tenant_id,
  138. plugin_entities.PluginUniqueIdentifier(installation.PluginUniqueIdentifier),
  139. installation.ID,
  140. )
  141. if err != nil {
  142. return entities.NewErrorResponse(-500, fmt.Sprintf("Failed to uninstall plugin: %s", err.Error()))
  143. }
  144. return entities.NewSuccessResponse(true)
  145. }