github.com/xzl8028/xenia-server@v0.0.0-20190809101854-18450a97da63/api4/plugin.go (about)

     1  // Copyright (c) 2017-present Xenia, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  // EXPERIMENTAL - SUBJECT TO CHANGE
     5  
     6  package api4
     7  
     8  import (
     9  	"net/http"
    10  	"net/url"
    11  
    12  	"github.com/xzl8028/xenia-server/mlog"
    13  	"github.com/xzl8028/xenia-server/model"
    14  )
    15  
    16  const (
    17  	MAXIMUM_PLUGIN_FILE_SIZE = 50 * 1024 * 1024
    18  )
    19  
    20  func (api *API) InitPlugin() {
    21  	mlog.Debug("EXPERIMENTAL: Initializing plugin api")
    22  
    23  	api.BaseRoutes.Plugins.Handle("", api.ApiSessionRequired(uploadPlugin)).Methods("POST")
    24  	api.BaseRoutes.Plugins.Handle("", api.ApiSessionRequired(getPlugins)).Methods("GET")
    25  	api.BaseRoutes.Plugin.Handle("", api.ApiSessionRequired(removePlugin)).Methods("DELETE")
    26  	api.BaseRoutes.Plugins.Handle("/install_from_url", api.ApiSessionRequired(installPluginFromUrl)).Methods("POST")
    27  
    28  	api.BaseRoutes.Plugins.Handle("/statuses", api.ApiSessionRequired(getPluginStatuses)).Methods("GET")
    29  	api.BaseRoutes.Plugin.Handle("/enable", api.ApiSessionRequired(enablePlugin)).Methods("POST")
    30  	api.BaseRoutes.Plugin.Handle("/disable", api.ApiSessionRequired(disablePlugin)).Methods("POST")
    31  
    32  	api.BaseRoutes.Plugins.Handle("/webapp", api.ApiHandler(getWebappPlugins)).Methods("GET")
    33  }
    34  
    35  func uploadPlugin(c *Context, w http.ResponseWriter, r *http.Request) {
    36  	if !*c.App.Config().PluginSettings.Enable || !*c.App.Config().PluginSettings.EnableUploads {
    37  		c.Err = model.NewAppError("uploadPlugin", "app.plugin.upload_disabled.app_error", nil, "", http.StatusNotImplemented)
    38  		return
    39  	}
    40  
    41  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
    42  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
    43  		return
    44  	}
    45  
    46  	if err := r.ParseMultipartForm(MAXIMUM_PLUGIN_FILE_SIZE); err != nil {
    47  		http.Error(w, err.Error(), http.StatusBadRequest)
    48  		return
    49  	}
    50  
    51  	m := r.MultipartForm
    52  
    53  	pluginArray, ok := m.File["plugin"]
    54  	if !ok {
    55  		c.Err = model.NewAppError("uploadPlugin", "api.plugin.upload.no_file.app_error", nil, "", http.StatusBadRequest)
    56  		return
    57  	}
    58  
    59  	if len(pluginArray) <= 0 {
    60  		c.Err = model.NewAppError("uploadPlugin", "api.plugin.upload.array.app_error", nil, "", http.StatusBadRequest)
    61  		return
    62  	}
    63  
    64  	file, err := pluginArray[0].Open()
    65  	if err != nil {
    66  		c.Err = model.NewAppError("uploadPlugin", "api.plugin.upload.file.app_error", nil, "", http.StatusBadRequest)
    67  		return
    68  	}
    69  	defer file.Close()
    70  
    71  	force := false
    72  	if len(m.Value["force"]) > 0 && m.Value["force"][0] == "true" {
    73  		force = true
    74  	}
    75  	manifest, unpackErr := c.App.InstallPlugin(file, force)
    76  
    77  	if unpackErr != nil {
    78  		c.Err = unpackErr
    79  		return
    80  	}
    81  
    82  	w.WriteHeader(http.StatusCreated)
    83  	w.Write([]byte(manifest.ToJson()))
    84  }
    85  
    86  func installPluginFromUrl(c *Context, w http.ResponseWriter, r *http.Request) {
    87  	if !*c.App.Config().PluginSettings.Enable {
    88  		c.Err = model.NewAppError("installPluginFromUrl", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
    89  		return
    90  	}
    91  
    92  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
    93  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
    94  		return
    95  	}
    96  
    97  	downloadUrl := r.URL.Query().Get("plugin_download_url")
    98  
    99  	if !model.IsValidHttpUrl(downloadUrl) {
   100  		c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.invalid_url.app_error", nil, "", http.StatusBadRequest)
   101  		return
   102  	}
   103  
   104  	u, err := url.ParseRequestURI(downloadUrl)
   105  	if err != nil {
   106  		c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.invalid_url.app_error", nil, "", http.StatusBadRequest)
   107  		return
   108  	}
   109  
   110  	if !*c.App.Config().PluginSettings.AllowInsecureDownloadUrl && u.Scheme != "https" {
   111  		c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.insecure_url.app_error", nil, "", http.StatusBadRequest)
   112  		return
   113  	}
   114  
   115  	client := c.App.HTTPService.MakeClient(true)
   116  	resp, err := client.Get(downloadUrl)
   117  	if err != nil {
   118  		c.Err = model.NewAppError("installPluginFromUrl", "api.plugin.install.download_failed.app_error", nil, err.Error(), http.StatusBadRequest)
   119  		return
   120  	}
   121  	defer resp.Body.Close()
   122  
   123  	force := false
   124  	if r.URL.Query().Get("force") == "true" {
   125  		force = true
   126  	}
   127  	manifest, unpackErr := c.App.InstallPlugin(resp.Body, force)
   128  
   129  	if unpackErr != nil {
   130  		c.Err = unpackErr
   131  		return
   132  	}
   133  
   134  	w.WriteHeader(http.StatusCreated)
   135  	w.Write([]byte(manifest.ToJson()))
   136  }
   137  
   138  func getPlugins(c *Context, w http.ResponseWriter, r *http.Request) {
   139  	if !*c.App.Config().PluginSettings.Enable {
   140  		c.Err = model.NewAppError("getPlugins", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
   141  		return
   142  	}
   143  
   144  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   145  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   146  		return
   147  	}
   148  
   149  	response, err := c.App.GetPlugins()
   150  	if err != nil {
   151  		c.Err = err
   152  		return
   153  	}
   154  
   155  	w.Write([]byte(response.ToJson()))
   156  }
   157  
   158  func getPluginStatuses(c *Context, w http.ResponseWriter, r *http.Request) {
   159  	if !*c.App.Config().PluginSettings.Enable {
   160  		c.Err = model.NewAppError("getPluginStatuses", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
   161  		return
   162  	}
   163  
   164  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   165  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   166  		return
   167  	}
   168  
   169  	response, err := c.App.GetClusterPluginStatuses()
   170  	if err != nil {
   171  		c.Err = err
   172  		return
   173  	}
   174  
   175  	w.Write([]byte(response.ToJson()))
   176  }
   177  
   178  func removePlugin(c *Context, w http.ResponseWriter, r *http.Request) {
   179  	c.RequirePluginId()
   180  	if c.Err != nil {
   181  		return
   182  	}
   183  
   184  	if !*c.App.Config().PluginSettings.Enable {
   185  		c.Err = model.NewAppError("removePlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
   186  		return
   187  	}
   188  
   189  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   190  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   191  		return
   192  	}
   193  
   194  	err := c.App.RemovePlugin(c.Params.PluginId)
   195  	if err != nil {
   196  		c.Err = err
   197  		return
   198  	}
   199  
   200  	ReturnStatusOK(w)
   201  }
   202  
   203  func getWebappPlugins(c *Context, w http.ResponseWriter, r *http.Request) {
   204  	if !*c.App.Config().PluginSettings.Enable {
   205  		c.Err = model.NewAppError("getWebappPlugins", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
   206  		return
   207  	}
   208  
   209  	manifests, err := c.App.GetActivePluginManifests()
   210  	if err != nil {
   211  		c.Err = err
   212  		return
   213  	}
   214  
   215  	clientManifests := []*model.Manifest{}
   216  	for _, m := range manifests {
   217  		if m.HasClient() {
   218  			manifest := m.ClientManifest()
   219  
   220  			// There is no reason to expose the SettingsSchema in this API call; it's not used in the webapp.
   221  			manifest.SettingsSchema = nil
   222  			clientManifests = append(clientManifests, manifest)
   223  		}
   224  	}
   225  
   226  	w.Write([]byte(model.ManifestListToJson(clientManifests)))
   227  }
   228  
   229  func enablePlugin(c *Context, w http.ResponseWriter, r *http.Request) {
   230  	c.RequirePluginId()
   231  	if c.Err != nil {
   232  		return
   233  	}
   234  
   235  	if !*c.App.Config().PluginSettings.Enable {
   236  		c.Err = model.NewAppError("activatePlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
   237  		return
   238  	}
   239  
   240  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   241  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   242  		return
   243  	}
   244  
   245  	if err := c.App.EnablePlugin(c.Params.PluginId); err != nil {
   246  		c.Err = err
   247  		return
   248  	}
   249  
   250  	ReturnStatusOK(w)
   251  }
   252  
   253  func disablePlugin(c *Context, w http.ResponseWriter, r *http.Request) {
   254  	c.RequirePluginId()
   255  	if c.Err != nil {
   256  		return
   257  	}
   258  
   259  	if !*c.App.Config().PluginSettings.Enable {
   260  		c.Err = model.NewAppError("deactivatePlugin", "app.plugin.disabled.app_error", nil, "", http.StatusNotImplemented)
   261  		return
   262  	}
   263  
   264  	if !c.App.SessionHasPermissionTo(c.App.Session, model.PERMISSION_MANAGE_SYSTEM) {
   265  		c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
   266  		return
   267  	}
   268  
   269  	if err := c.App.DisablePlugin(c.Params.PluginId); err != nil {
   270  		c.Err = err
   271  		return
   272  	}
   273  
   274  	ReturnStatusOK(w)
   275  }