diff --git a/notehub/app.go b/notehub/app.go index 8bdd76d..554d95b 100644 --- a/notehub/app.go +++ b/notehub/app.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/blues/note-cli/lib" + "github.com/blues/note-go/note" notegoapi "github.com/blues/note-go/notehub/api" ) @@ -300,6 +301,58 @@ func addScope(scope string, appMetadata *AppMetadata, scopeDevices *[]string, sc } +// ProjectInfo represents a project with its products +type ProjectInfo struct { + Name string `json:"name,omitempty"` + UID string `json:"uid,omitempty"` + Products []Metadata `json:"products,omitempty"` +} + +// List all projects accessible to the authenticated user +func appListProjects(flagVerbose bool) (projects []ProjectInfo, err error) { + rsp, err := reqHubV1JSON(flagVerbose, lib.ConfigAPIHub(), "GET", "/v1/projects", nil) + if err != nil { + return + } + var parsed map[string]interface{} + err = note.JSONUnmarshal(rsp, &parsed) + if err != nil { + return + } + items, _ := parsed["projects"].([]interface{}) + for _, v := range items { + p, ok := v.(map[string]interface{}) + if !ok { + continue + } + uid, _ := p["uid"].(string) + label, _ := p["label"].(string) + info := ProjectInfo{Name: label, UID: uid} + + // Fetch products for this project + productsRsp := map[string]interface{}{} + err = reqHubV1(flagVerbose, lib.ConfigAPIHub(), "GET", "/v1/projects/"+uid+"/products", nil, &productsRsp) + if err == nil { + pi, exists := productsRsp["products"].([]interface{}) + if exists { + for _, pv := range pi { + pp, ok := pv.(map[string]interface{}) + if ok { + info.Products = append(info.Products, Metadata{ + Name: pp["label"].(string), + UID: pp["uid"].(string), + }) + } + } + } + } + err = nil // don't fail the whole listing if one project's products can't be fetched + + projects = append(projects, info) + } + return +} + // Sort and remove duplicates in a string slice func sortAndRemoveDuplicates(strings []string) []string { diff --git a/notehub/main.go b/notehub/main.go index 9ef6101..886d44e 100644 --- a/notehub/main.go +++ b/notehub/main.go @@ -43,6 +43,7 @@ func getFlagGroups() []lib.FlagGroup { Name: "scope", Description: "Project & Device Scope", Flags: []*flag.Flag{ + lib.GetFlagByName("projects"), lib.GetFlagByName("project"), lib.GetFlagByName("provision"), lib.GetFlagByName("product"), @@ -168,6 +169,8 @@ func main() { flag.StringVar(&flagSn, "sn", "", "serial number") var flagProvision bool flag.BoolVar(&flagProvision, "provision", false, "provision devices") + var flagProjects bool + flag.BoolVar(&flagProjects, "projects", false, "list all projects") // Parse these flags and also the note tool config flags err := lib.FlagParse(false, true) @@ -271,6 +274,27 @@ func main() { fmt.Printf("Notehub CLI Version: %s\n", version) } + if err == nil && flagProjects { + didSomething = true + err = withCreds(credentials, func() (err error) { + projects, err := appListProjects(flagVerbose) + if err != nil { + return err + } + var projectsJSON []byte + if flagPretty { + projectsJSON, err = note.JSONMarshalIndent(projects, "", " ") + } else { + projectsJSON, err = note.JSONMarshal(projects) + } + if err != nil { + return err + } + fmt.Printf("%s\n", projectsJSON) + return nil + }) + } + if flagReq != "" || flagUpload != "" { didSomething = true err = withCreds(credentials, func() (err error) {