github.com/pelicanplatform/pelican@v1.0.5/namespace_registry/registry_ui.go (about) 1 /*************************************************************** 2 * 3 * Copyright (C) 2023, Pelican Project, Morgridge Institute for Research 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); you 6 * may not use this file except in compliance with the License. You may 7 * obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ***************************************************************/ 18 19 package nsregistry 20 21 import ( 22 "encoding/json" 23 "fmt" 24 "net/http" 25 "strconv" 26 27 "github.com/gin-gonic/gin" 28 ) 29 30 type listNamespaceRequest struct { 31 ServerType string `form:"server_type"` 32 } 33 34 // Exclude pubkey field from marshalling into json 35 func excludePubKey(nss []*Namespace) (nssNew []NamespaceWOPubkey) { 36 nssNew = make([]NamespaceWOPubkey, 0) 37 for _, ns := range nss { 38 nsNew := NamespaceWOPubkey{ 39 ID: ns.ID, 40 Prefix: ns.Prefix, 41 Pubkey: ns.Pubkey, 42 AdminMetadata: ns.AdminMetadata, 43 Identity: ns.Identity, 44 } 45 nssNew = append(nssNew, nsNew) 46 } 47 48 return 49 } 50 51 func listNamespaces(ctx *gin.Context) { 52 queryParams := listNamespaceRequest{} 53 if ctx.ShouldBindQuery(&queryParams) != nil { 54 ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid query parameters"}) 55 return 56 } 57 58 if queryParams.ServerType != "" { 59 if queryParams.ServerType != string(OriginType) && queryParams.ServerType != string(CacheType) { 60 ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server type"}) 61 return 62 } 63 namespaces, err := getNamespacesByServerType(ServerType(queryParams.ServerType)) 64 if err != nil { 65 ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Server encountered an error trying to list namespaces"}) 66 return 67 } 68 nssWOPubkey := excludePubKey(namespaces) 69 ctx.JSON(http.StatusOK, nssWOPubkey) 70 71 } else { 72 namespaces, err := getAllNamespaces() 73 if err != nil { 74 ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Server encountered an error trying to list namespaces"}) 75 return 76 } 77 nssWOPubkey := excludePubKey(namespaces) 78 ctx.JSON(http.StatusOK, nssWOPubkey) 79 } 80 } 81 82 func getNamespaceJWKS(ctx *gin.Context) { 83 idStr := ctx.Param("id") 84 id, err := strconv.Atoi(idStr) 85 if err != nil || id <= 0 { 86 // Handle the error if id is not a valid integer 87 ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID format. ID must a non-zero integer"}) 88 return 89 } 90 found, err := namespaceExistsById(id) 91 if err != nil { 92 ctx.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprint("Error checking id:", err)}) 93 return 94 } 95 if !found { 96 ctx.JSON(http.StatusNotFound, gin.H{"error": "Namespace not found"}) 97 return 98 } 99 jwks, err := getPrefixJwksById(id) 100 if err != nil { 101 ctx.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprint("Error getting jwks by id:", err)}) 102 return 103 } 104 jsonData, err := json.MarshalIndent(jwks, "", " ") 105 if err != nil { 106 ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to marshal JWKS"}) 107 return 108 } 109 // Append a new line to the JSON data 110 jsonData = append(jsonData, '\n') 111 ctx.Header("Content-Disposition", fmt.Sprintf("attachment; filename=public-key-server-%v.jwks", id)) 112 ctx.Data(200, "application/json", jsonData) 113 } 114 115 func RegisterNamespacesRegistryWebAPI(router *gin.RouterGroup) { 116 registryWebAPI := router.Group("/api/v1.0/registry_ui") 117 // Follow RESTful schema 118 { 119 registryWebAPI.GET("/namespaces", listNamespaces) 120 registryWebAPI.GET("/namespaces/:id/pubkey", getNamespaceJWKS) 121 } 122 }