github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/tequilapi/endpoints/ui.go (about) 1 /* 2 * Copyright (C) 2021 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package endpoints 19 20 import ( 21 "fmt" 22 "net/http" 23 "strconv" 24 25 "github.com/gin-gonic/gin" 26 "github.com/mysteriumnetwork/go-rest/apierror" 27 "github.com/mysteriumnetwork/node/tequilapi/contract" 28 "github.com/mysteriumnetwork/node/ui/versionmanager" 29 ) 30 31 // NodeUIEndpoints node ui version management endpoints 32 type NodeUIEndpoints struct { 33 versionManager *versionmanager.VersionManager 34 } 35 36 // NewNodeUIEndpoints constructor 37 func NewNodeUIEndpoints(versionManager *versionmanager.VersionManager) *NodeUIEndpoints { 38 return &NodeUIEndpoints{ 39 versionManager: versionManager, 40 } 41 } 42 43 // RemoteVersions list node UI releases from repo 44 // swagger:operation GET /ui/remote-versions UI uiRemoteVersions 45 // 46 // --- 47 // summary: List local 48 // description: provides a list of node UI releases from github repository 49 // responses: 50 // 200: 51 // description: Remote version list 52 // schema: 53 // "$ref": "#/definitions/RemoteVersionsResponse" 54 // 500: 55 // description: Internal server error 56 // schema: 57 // "$ref": "#/definitions/APIError" 58 func (n *NodeUIEndpoints) RemoteVersions(c *gin.Context) { 59 r := versionmanager.RemoteVersionRequest{ 60 PerPage: 50, 61 } 62 63 if b, err := strconv.ParseBool(c.Query("flush_cache")); err == nil { 64 r.FlushCache = b 65 } 66 67 if pp, err := strconv.ParseInt(c.Query("per_page"), 10, 32); err == nil { 68 r.PerPage = int(pp) 69 } 70 71 if p, err := strconv.ParseInt(c.Query("page"), 10, 32); err == nil { 72 r.Page = int(p) 73 } 74 75 versions, err := n.versionManager.ListRemoteVersions(r) 76 if err != nil { 77 c.Error(err) 78 return 79 } 80 c.JSON(http.StatusOK, contract.RemoteVersionsResponse{Versions: versions}) 81 } 82 83 // LocalVersions locally available node UI versions 84 // swagger:operation GET /ui/local-versions UI uiLocalVersions 85 // 86 // --- 87 // summary: List remote 88 // description: provides a list of node UI releases that have been downloaded or bundled with node 89 // responses: 90 // 200: 91 // description: Local version list 92 // schema: 93 // "$ref": "#/definitions/LocalVersionsResponse" 94 // 500: 95 // description: Internal server error 96 // schema: 97 // "$ref": "#/definitions/APIError" 98 func (n *NodeUIEndpoints) LocalVersions(c *gin.Context) { 99 versions, err := n.versionManager.ListLocalVersions() 100 if err != nil { 101 c.Error(apierror.Internal("Could not list local versions: "+err.Error(), contract.ErrCodeUILocalVersions)) 102 return 103 } 104 c.JSON(http.StatusOK, contract.LocalVersionsResponse{Versions: versions}) 105 } 106 107 // SwitchVersion switches node UI version to locally available one 108 // swagger:operation POST /ui/switch-version UI uiSwitchVersion 109 // 110 // --- 111 // summary: Switch Version 112 // description: switch node UI version to locally available one 113 // responses: 114 // 200: 115 // description: version switched 116 // 400: 117 // description: Failed to parse or request validation failed 118 // schema: 119 // "$ref": "#/definitions/APIError" 120 // 422: 121 // description: Unable to process the request at this point 122 // schema: 123 // "$ref": "#/definitions/APIError" 124 // 500: 125 // description: Internal server error 126 // schema: 127 // "$ref": "#/definitions/APIError" 128 func (n *NodeUIEndpoints) SwitchVersion(c *gin.Context) { 129 var req contract.SwitchNodeUIRequest 130 if err := c.ShouldBindJSON(&req); err != nil { 131 c.Error(apierror.ParseFailed()) 132 return 133 } 134 135 if err := req.Valid(); err != nil { 136 c.Error(err) 137 return 138 } 139 140 if err := n.versionManager.SwitchTo(req.Version); err != nil { 141 c.Error(apierror.Unprocessable(fmt.Sprintf("Could not switch to node UI version: %s", req.Version), contract.ErrCodeUISwitchVersion)) 142 return 143 } 144 145 c.AbortWithStatus(http.StatusOK) 146 } 147 148 // Download download a remote node UI release 149 // swagger:operation POST /ui/download-version UI uiDownload 150 // 151 // --- 152 // summary: Download 153 // description: download a remote node UI release 154 // responses: 155 // 200: 156 // description: Download in progress 157 // 400: 158 // description: Failed to parse or request validation failed 159 // schema: 160 // "$ref": "#/definitions/APIError" 161 // 500: 162 // description: Internal server error 163 // schema: 164 // "$ref": "#/definitions/APIError" 165 func (n *NodeUIEndpoints) Download(c *gin.Context) { 166 var req contract.DownloadNodeUIRequest 167 if err := c.ShouldBindJSON(&req); err != nil { 168 c.Error(apierror.ParseFailed()) 169 return 170 } 171 172 if err := req.Valid(); err != nil { 173 c.Error(err) 174 return 175 } 176 177 if err := n.versionManager.Download(req.Version); err != nil { 178 c.Error(apierror.Internal(fmt.Sprintf("Could not download node UI version: %s", req.Version), contract.ErrCodeUIDownload)) 179 return 180 } 181 182 c.AbortWithStatus(http.StatusOK) 183 } 184 185 // DownloadStatus returns download status 186 // swagger:operation GET /ui/download-status UI uiDownloadStatus 187 // 188 // --- 189 // summary: Download status 190 // description: DownloadStatus can download one remote release at a time. This endpoint provides status of the download. 191 // responses: 192 // 200: 193 // description: download status 194 // schema: 195 // "$ref": "#/definitions/DownloadStatus" 196 // 500: 197 // description: Internal server error 198 // schema: 199 // "$ref": "#/definitions/APIError" 200 func (n *NodeUIEndpoints) DownloadStatus(c *gin.Context) { 201 c.JSON(http.StatusOK, n.versionManager.DownloadStatus()) 202 } 203 204 // UI returns download status 205 // swagger:operation GET /ui/info UI ui 206 // 207 // --- 208 // summary: Node UI information 209 // description: Node UI information 210 // responses: 211 // 200: 212 // description: Node UI information 213 // schema: 214 // "$ref": "#/definitions/UI" 215 // 500: 216 // description: Internal server error 217 // schema: 218 // "$ref": "#/definitions/APIError" 219 func (n *NodeUIEndpoints) UI(c *gin.Context) { 220 bundled, err := n.versionManager.BundledVersion() 221 if err != nil { 222 c.Error(apierror.Internal("Could not resolve bundled version: "+err.Error(), contract.ErrCodeUIBundledVersion)) 223 return 224 } 225 226 used, err := n.versionManager.UsedVersion() 227 if err != nil { 228 c.Error(apierror.Internal("Could not resolve used version: "+err.Error(), contract.ErrCodeUIUsedVersion)) 229 return 230 } 231 c.JSON(http.StatusOK, contract.UI{ 232 BundledVersion: bundled.Name, 233 UsedVersion: used.Name, 234 }) 235 } 236 237 // AddRoutesForNodeUI provides controls for nodeUI management via tequilapi 238 func AddRoutesForNodeUI(versionManager *versionmanager.VersionManager) func(*gin.Engine) error { 239 endpoints := NewNodeUIEndpoints(versionManager) 240 241 return func(e *gin.Engine) error { 242 v1Group := e.Group("/ui") 243 { 244 v1Group.GET("/info", endpoints.UI) 245 v1Group.GET("/local-versions", endpoints.LocalVersions) 246 v1Group.GET("/remote-versions", endpoints.RemoteVersions) 247 v1Group.POST("/switch-version", endpoints.SwitchVersion) 248 v1Group.POST("/download-version", endpoints.Download) 249 v1Group.GET("/download-status", endpoints.DownloadStatus) 250 } 251 return nil 252 } 253 }