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 }