зеркало из https://github.com/mozilla/mig.git
[minor] add loader search to console
This commit is contained in:
Родитель
81fa03c320
Коммит
da8bbb2ee5
|
@ -407,12 +407,18 @@ func (cli Client) GetManifestLoaders(mid float64) (ldrs []mig.LoaderEntry, err e
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if resource.Collection.Items[0].Data[0].Name != "loaders" {
|
for _, item := range resource.Collection.Items {
|
||||||
panic("API returned something that is not a loader list... something's wrong.")
|
for _, data := range item.Data {
|
||||||
}
|
if data.Name != "loader" {
|
||||||
ldrs, err = ValueToLoaderEntries(resource.Collection.Items[0].Data[0].Value)
|
continue
|
||||||
if err != nil {
|
}
|
||||||
panic(err)
|
ldr, err := ValueToLoaderEntry(data.Value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
ldrs = append(ldrs, ldr)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -600,7 +606,7 @@ func ValueToAction(v interface{}) (a mig.Action, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValueToLoaderEntries(v interface{}) (l []mig.LoaderEntry, err error) {
|
func ValueToLoaderEntry(v interface{}) (l mig.LoaderEntry, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("ValueToLoaderEntries() -> %v", e)
|
err = fmt.Errorf("ValueToLoaderEntries() -> %v", e)
|
||||||
|
|
|
@ -88,7 +88,7 @@ func main() {
|
||||||
// completion
|
// completion
|
||||||
var symbols = []string{"action", "agent", "create", "command", "help", "history",
|
var symbols = []string{"action", "agent", "create", "command", "help", "history",
|
||||||
"exit", "manifest", "showcfg", "status", "investigator", "search", "query",
|
"exit", "manifest", "showcfg", "status", "investigator", "search", "query",
|
||||||
"where", "and"}
|
"where", "and", "loader"}
|
||||||
readline.Completer = func(query, ctx string) []string {
|
readline.Completer = func(query, ctx string) []string {
|
||||||
var res []string
|
var res []string
|
||||||
for _, sym := range symbols {
|
for _, sym := range symbols {
|
||||||
|
|
|
@ -29,10 +29,10 @@ func search(input string, cli client.Client) (err error) {
|
||||||
}
|
}
|
||||||
sType := ""
|
sType := ""
|
||||||
switch orders[1] {
|
switch orders[1] {
|
||||||
case "action", "agent", "command", "investigator", "manifest":
|
case "action", "agent", "command", "investigator", "manifest", "loader":
|
||||||
sType = orders[1]
|
sType = orders[1]
|
||||||
case "", "help":
|
case "", "help":
|
||||||
fmt.Printf(`usage: search <action|agent|command|investigator|manifest> where <key>=<value> [and <key>=<value>...]
|
fmt.Printf(`usage: search <action|agent|command|investigator|loader|manifest> where <key>=<value> [and <key>=<value>...]
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
mig> search command where agentname=%%khazad%% and investigatorname=%%vehent%% and actionname=%%memory%% and after=2015-09-09T17:00:00Z
|
mig> search command where agentname=%%khazad%% and investigatorname=%%vehent%% and actionname=%%memory%% and after=2015-09-09T17:00:00Z
|
||||||
|
@ -91,6 +91,11 @@ The following search parameters are available, per search type:
|
||||||
- manifestname=<str> search manifests by name
|
- manifestname=<str> search manifests by name
|
||||||
- status=<str> search manifests by status amongst: active, staged, disabled
|
- status=<str> search manifests by status amongst: active, staged, disabled
|
||||||
|
|
||||||
|
* loader:
|
||||||
|
- loaderid=<id> search loaders by id
|
||||||
|
- loadername=<str> search loaders by loader name
|
||||||
|
- agentname=<str> search loaders for associated agent names
|
||||||
|
|
||||||
All searches accept the 'limit=<num>' parameter to limits the number of results returned by a search, defaults to 100
|
All searches accept the 'limit=<num>' parameter to limits the number of results returned by a search, defaults to 100
|
||||||
Parameters that accept a <str> can use wildcards * and % (ex: name=jul%veh% ).
|
Parameters that accept a <str> can use wildcards * and % (ex: name=jul%veh% ).
|
||||||
No spaces are permitted within parameters. Spaces are used to separate search parameters.
|
No spaces are permitted within parameters. Spaces are used to separate search parameters.
|
||||||
|
@ -123,6 +128,8 @@ No spaces are permitted within parameters. Spaces are used to separate search pa
|
||||||
fmt.Println("- ID - + ---- Name ---- + --- Status ---")
|
fmt.Println("- ID - + ---- Name ---- + --- Status ---")
|
||||||
case "manifest":
|
case "manifest":
|
||||||
fmt.Println("- ID - + ---- Name ---- + -- Status -- + -------------- Target -------- + ---- Timestamp ---")
|
fmt.Println("- ID - + ---- Name ---- + -- Status -- + -------------- Target -------- + ---- Timestamp ---")
|
||||||
|
case "loader":
|
||||||
|
fmt.Println("- ID - + ---- Name ---- + ---- Agent Name ---- + -- Last Used ---")
|
||||||
}
|
}
|
||||||
for _, item := range resources.Collection.Items {
|
for _, item := range resources.Collection.Items {
|
||||||
for _, data := range item.Data {
|
for _, data := range item.Data {
|
||||||
|
@ -228,6 +235,32 @@ No spaces are permitted within parameters. Spaces are used to separate search pa
|
||||||
}
|
}
|
||||||
fmt.Printf("%6.0f %s %s %s %s\n", mr.ID, name,
|
fmt.Printf("%6.0f %s %s %s %s\n", mr.ID, name,
|
||||||
status, target, mr.Timestamp)
|
status, target, mr.Timestamp)
|
||||||
|
case "loader":
|
||||||
|
le, err := client.ValueToLoaderEntry(data.Value)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
loadername := le.Name
|
||||||
|
if len(loadername) < 24 {
|
||||||
|
for i := len(loadername); i < 24; i++ {
|
||||||
|
loadername += " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(loadername) > 24 {
|
||||||
|
loadername = loadername[0:21] + "..."
|
||||||
|
}
|
||||||
|
agtname := le.AgentName
|
||||||
|
if len(agtname) < 24 {
|
||||||
|
for i := len(agtname); i < 24; i++ {
|
||||||
|
agtname += " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(agtname) > 24 {
|
||||||
|
agtname = agtname[0:21] + "..."
|
||||||
|
}
|
||||||
|
fmt.Printf("%6.0f %s %s %s\n", le.ID, loadername,
|
||||||
|
agtname,
|
||||||
|
le.LastUsed.UTC().Format(time.RFC3339))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,6 +326,10 @@ func parseSearchQuery(orders []string) (p migdbsearch.Parameters, err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("invalid limit parameter")
|
panic("invalid limit parameter")
|
||||||
}
|
}
|
||||||
|
case "loadername":
|
||||||
|
p.LoaderName = value
|
||||||
|
case "loaderid":
|
||||||
|
p.LoaderID = value
|
||||||
case "manifestname":
|
case "manifestname":
|
||||||
p.ManifestName = value
|
p.ManifestName = value
|
||||||
case "manifestid":
|
case "manifestid":
|
||||||
|
|
|
@ -51,7 +51,9 @@ func (db *DB) UpdateLoaderEntry(lid float64, agt mig.Agent) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = db.c.Exec(`UPDATE loaders
|
_, err = db.c.Exec(`UPDATE loaders
|
||||||
SET name=$1, env=$2, tags=$3 WHERE id=$4`,
|
SET name=$1, env=$2, tags=$3,
|
||||||
|
lastused=now()
|
||||||
|
WHERE id=$4`,
|
||||||
agt.Name, jEnv, jTags, lid)
|
agt.Name, jEnv, jTags, lid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -103,7 +105,7 @@ func (db *DB) AllLoadersFromManifestID(mid float64) (ret []mig.LoaderEntry, err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
qs := fmt.Sprintf("SELECT id, loadername, name FROM loaders WHERE %v", mtarg)
|
qs := fmt.Sprintf("SELECT id, loadername, name, lastused FROM loaders WHERE %v", mtarg)
|
||||||
rows, err := db.c.Query(qs)
|
rows, err := db.c.Query(qs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -113,7 +115,7 @@ func (db *DB) AllLoadersFromManifestID(mid float64) (ret []mig.LoaderEntry, err
|
||||||
}
|
}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
nle := mig.LoaderEntry{}
|
nle := mig.LoaderEntry{}
|
||||||
err = rows.Scan(&nle.ID, &nle.Name, &nle.AgentName)
|
err = rows.Scan(&nle.ID, &nle.Name, &nle.AgentName, &nle.LastUsed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,12 +131,13 @@ CREATE UNIQUE INDEX manifestsig_manifestid_investigatorid_idx ON manifestsig USI
|
||||||
|
|
||||||
CREATE SEQUENCE loaders_id_seq START 1;
|
CREATE SEQUENCE loaders_id_seq START 1;
|
||||||
CREATE TABLE loaders (
|
CREATE TABLE loaders (
|
||||||
id numeric NOT NULL DEFAULT nextval('loaders_id_seq'),
|
id numeric NOT NULL DEFAULT nextval('loaders_id_seq'),
|
||||||
loadername character varying(256) NOT NULL,
|
loadername character varying(256) NOT NULL,
|
||||||
loaderkey character varying(64) NOT NULL,
|
loaderkey character varying(64) NOT NULL,
|
||||||
name character varying(2048),
|
name character varying(2048),
|
||||||
env json,
|
env json,
|
||||||
tags json
|
tags json,
|
||||||
|
lastused timestamp with time zone NOT NULL
|
||||||
);
|
);
|
||||||
ALTER TABLE ONLY loaders
|
ALTER TABLE ONLY loaders
|
||||||
ADD CONSTRAINT loaders_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT loaders_pkey PRIMARY KEY (id);
|
||||||
|
@ -202,7 +203,7 @@ GRANT INSERT ON actions, signatures, manifests, manifestsig TO migapi;
|
||||||
GRANT DELETE ON manifestsig TO migapi;
|
GRANT DELETE ON manifestsig TO migapi;
|
||||||
GRANT INSERT (name, pgpfingerprint, publickey, status, createdat, lastmodified) ON investigators TO migapi;
|
GRANT INSERT (name, pgpfingerprint, publickey, status, createdat, lastmodified) ON investigators TO migapi;
|
||||||
GRANT UPDATE (status, lastmodified) ON investigators TO migapi;
|
GRANT UPDATE (status, lastmodified) ON investigators TO migapi;
|
||||||
GRANT UPDATE (name, env, tags) ON loaders TO migapi;
|
GRANT UPDATE (name, env, tags, lastused) ON loaders TO migapi;
|
||||||
GRANT UPDATE (status) ON manifests TO migapi;
|
GRANT UPDATE (status) ON manifests TO migapi;
|
||||||
GRANT USAGE ON SEQUENCE investigators_id_seq TO migapi;
|
GRANT USAGE ON SEQUENCE investigators_id_seq TO migapi;
|
||||||
GRANT USAGE ON SEQUENCE loaders_id_seq TO migapi;
|
GRANT USAGE ON SEQUENCE loaders_id_seq TO migapi;
|
||||||
|
|
|
@ -26,6 +26,8 @@ type Parameters struct {
|
||||||
InvestigatorID string `json:"investigatorid"`
|
InvestigatorID string `json:"investigatorid"`
|
||||||
InvestigatorName string `json:"investigatorname"`
|
InvestigatorName string `json:"investigatorname"`
|
||||||
Limit float64 `json:"limit"`
|
Limit float64 `json:"limit"`
|
||||||
|
LoaderID string `json:"loaderid"`
|
||||||
|
LoaderName string `json:"loadername"`
|
||||||
ManifestID string `json:"manifestid"`
|
ManifestID string `json:"manifestid"`
|
||||||
ManifestName string `json:"manifestname"`
|
ManifestName string `json:"manifestname"`
|
||||||
Offset float64 `json:"offset"`
|
Offset float64 `json:"offset"`
|
||||||
|
@ -52,6 +54,8 @@ func NewParameters() (p Parameters) {
|
||||||
p.InvestigatorID = "∞"
|
p.InvestigatorID = "∞"
|
||||||
p.InvestigatorName = "%"
|
p.InvestigatorName = "%"
|
||||||
p.Limit = 100
|
p.Limit = 100
|
||||||
|
p.LoaderID = "∞"
|
||||||
|
p.LoaderName = "%"
|
||||||
p.ManifestID = "∞"
|
p.ManifestID = "∞"
|
||||||
p.ManifestName = "%"
|
p.ManifestName = "%"
|
||||||
p.Offset = 0
|
p.Offset = 0
|
||||||
|
@ -88,6 +92,12 @@ func (p Parameters) String() (query string) {
|
||||||
if p.InvestigatorName != "%" {
|
if p.InvestigatorName != "%" {
|
||||||
query += fmt.Sprintf("&investigatorname=%s", p.InvestigatorName)
|
query += fmt.Sprintf("&investigatorname=%s", p.InvestigatorName)
|
||||||
}
|
}
|
||||||
|
if p.LoaderID != "∞" {
|
||||||
|
query += fmt.Sprintf("&loaderid=%s", p.LoaderID)
|
||||||
|
}
|
||||||
|
if p.LoaderName != "%" {
|
||||||
|
query += fmt.Sprintf("&loadername=%s", p.LoaderName)
|
||||||
|
}
|
||||||
if p.ManifestName != "%" {
|
if p.ManifestName != "%" {
|
||||||
query += fmt.Sprintf("&manifestname=%s", p.ManifestName)
|
query += fmt.Sprintf("&manifestname=%s", p.ManifestName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -916,3 +916,84 @@ func (db *DB) SearchManifests(p search.Parameters) (mrecords []mig.ManifestRecor
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *DB) SearchLoaders(p search.Parameters) (lrecords []mig.LoaderEntry, err error) {
|
||||||
|
var rows *sql.Rows
|
||||||
|
ids, err := makeIDsFromParams(p)
|
||||||
|
columns := `loaders.id, loaders.loadername, loaders.name, loaders.lastused`
|
||||||
|
where := ""
|
||||||
|
vals := []interface{}{}
|
||||||
|
valctr := 0
|
||||||
|
if p.Before.Before(time.Now().Add(search.DefaultWindow - time.Hour)) {
|
||||||
|
where += fmt.Sprintf(`loaders.lastused <= $%d `, valctr+1)
|
||||||
|
vals = append(vals, p.Before)
|
||||||
|
valctr += 1
|
||||||
|
}
|
||||||
|
if p.After.After(time.Now().Add(-(search.DefaultWindow - time.Hour))) {
|
||||||
|
if valctr > 0 {
|
||||||
|
where += " AND "
|
||||||
|
}
|
||||||
|
where += fmt.Sprintf(`loaders.lastused >= $%d `, valctr+1)
|
||||||
|
vals = append(vals, p.After)
|
||||||
|
valctr += 1
|
||||||
|
}
|
||||||
|
if p.LoaderName != "%" {
|
||||||
|
if valctr > 0 {
|
||||||
|
where += " AND "
|
||||||
|
}
|
||||||
|
where += fmt.Sprintf(`loaders.loadername ILIKE $%d`, valctr+1)
|
||||||
|
vals = append(vals, p.LoaderName)
|
||||||
|
valctr += 1
|
||||||
|
}
|
||||||
|
if p.AgentName != "%" {
|
||||||
|
if valctr > 0 {
|
||||||
|
where += " AND "
|
||||||
|
}
|
||||||
|
where += fmt.Sprintf(`loaders.name ILIKE $%d`, valctr+1)
|
||||||
|
vals = append(vals, p.AgentName)
|
||||||
|
valctr += 1
|
||||||
|
}
|
||||||
|
if p.LoaderID != "∞" {
|
||||||
|
if valctr > 0 {
|
||||||
|
where += " AND "
|
||||||
|
}
|
||||||
|
where += fmt.Sprintf(`loaders.id >= $%d AND loaders.id <= $%d`,
|
||||||
|
valctr+1, valctr+2)
|
||||||
|
vals = append(vals, ids.minManID, ids.maxManID)
|
||||||
|
valctr += 2
|
||||||
|
}
|
||||||
|
query := fmt.Sprintf(`SELECT %s FROM loaders WHERE %s ORDER BY loadername;`, columns, where)
|
||||||
|
stmt, err := db.c.Prepare(query)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Error while preparing search statement: '%v' in '%s'", err, query)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if stmt != nil {
|
||||||
|
defer stmt.Close()
|
||||||
|
}
|
||||||
|
rows, err = stmt.Query(vals...)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Error while finding loaders: '%v'", err)
|
||||||
|
}
|
||||||
|
if rows != nil {
|
||||||
|
defer rows.Close()
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
var le mig.LoaderEntry
|
||||||
|
var agtnameNull sql.NullString
|
||||||
|
err = rows.Scan(&le.ID, &le.Name, &agtnameNull, &le.LastUsed)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Failed to retrieve loader data: '%v'", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
le.AgentName = "unset"
|
||||||
|
if agtnameNull.Valid {
|
||||||
|
le.AgentName = agtnameNull.String
|
||||||
|
}
|
||||||
|
lrecords = append(lrecords, le)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
err = fmt.Errorf("Failed to complete database query: '%v'", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
11
loader.go
11
loader.go
|
@ -6,9 +6,14 @@
|
||||||
|
|
||||||
package mig /* import "mig.ninja/mig" */
|
package mig /* import "mig.ninja/mig" */
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// Describes a loader entry stored in the database
|
// Describes a loader entry stored in the database
|
||||||
type LoaderEntry struct {
|
type LoaderEntry struct {
|
||||||
ID float64 // Loader ID
|
ID float64 // Loader ID
|
||||||
Name string // Loader name
|
Name string // Loader name
|
||||||
AgentName string // Loader environment, agent name
|
AgentName string // Loader environment, agent name
|
||||||
|
LastUsed time.Time // Last time loader was used
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,11 +273,13 @@ func manifestLoaders(respWriter http.ResponseWriter, request *http.Request) {
|
||||||
respond(404, resource, respWriter, request)
|
respond(404, resource, respWriter, request)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
li, err := loaderEntrysToItem(ldrs, mid, ctx)
|
for _, ldr := range ldrs {
|
||||||
if err != nil {
|
item, err := loaderEntryToItem(ldr, mid, ctx)
|
||||||
panic(err)
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
resource.AddItem(item)
|
||||||
}
|
}
|
||||||
resource.AddItem(li)
|
|
||||||
respond(200, resource, respWriter, request)
|
respond(200, resource, respWriter, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,10 +428,11 @@ func manifestRecordToItem(mr mig.ManifestRecord, ctx Context) (item cljs.Item, e
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func loaderEntrysToItem(ldrs []mig.LoaderEntry, mid float64, ctx Context) (item cljs.Item, err error) {
|
func loaderEntryToItem(ldr mig.LoaderEntry, mid float64, ctx Context) (item cljs.Item, err error) {
|
||||||
|
// XXX This Href doesn't properly represent the item and needs to be fixed
|
||||||
item.Href = fmt.Sprintf("%s/manifest/loaders?manifestid=%.0f", ctx.Server.BaseURL, mid)
|
item.Href = fmt.Sprintf("%s/manifest/loaders?manifestid=%.0f", ctx.Server.BaseURL, mid)
|
||||||
item.Data = []cljs.Data{
|
item.Data = []cljs.Data{
|
||||||
{Name: "loaders", Value: ldrs},
|
{Name: "loader", Value: ldr},
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,8 @@ func search(respWriter http.ResponseWriter, request *http.Request) {
|
||||||
results, err = ctx.DB.SearchInvestigators(p)
|
results, err = ctx.DB.SearchInvestigators(p)
|
||||||
case "manifest":
|
case "manifest":
|
||||||
results, err = ctx.DB.SearchManifests(p)
|
results, err = ctx.DB.SearchManifests(p)
|
||||||
|
case "loader":
|
||||||
|
results, err = ctx.DB.SearchLoaders(p)
|
||||||
default:
|
default:
|
||||||
panic("search type is invalid")
|
panic("search type is invalid")
|
||||||
}
|
}
|
||||||
|
@ -218,6 +220,25 @@ func search(respWriter http.ResponseWriter, request *http.Request) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "loader":
|
||||||
|
ctx.Channels.Log <- mig.Log{OpID: opid, Desc: fmt.Sprintf("returning search results with %d loaders", len(results.([]mig.LoaderEntry)))}
|
||||||
|
if len(results.([]mig.LoaderEntry)) == 0 {
|
||||||
|
panic("no results found")
|
||||||
|
}
|
||||||
|
for i, r := range results.([]mig.LoaderEntry) {
|
||||||
|
err = resource.AddItem(cljs.Item{
|
||||||
|
// XXX This should be an Href to fetch the entry
|
||||||
|
Href: fmt.Sprintf("%s%s", ctx.Server.Host,
|
||||||
|
ctx.Server.BaseRoute),
|
||||||
|
Data: []cljs.Data{{Name: p.Type, Value: r}},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if float64(i) > p.Limit {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if needed, add pagination info
|
// if needed, add pagination info
|
||||||
|
@ -304,6 +325,10 @@ func parseSearchParameters(qp url.Values) (p migdbsearch.Parameters, filterFound
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("invalid limit parameter")
|
panic("invalid limit parameter")
|
||||||
}
|
}
|
||||||
|
case "loadername":
|
||||||
|
p.LoaderName = qp["loadername"][0]
|
||||||
|
case "loaderid":
|
||||||
|
p.LoaderID = qp["loaderid"][0]
|
||||||
case "manifestname":
|
case "manifestname":
|
||||||
p.ManifestName = qp["manifestname"][0]
|
p.ManifestName = qp["manifestname"][0]
|
||||||
case "manifestid":
|
case "manifestid":
|
||||||
|
|
Загрузка…
Ссылка в новой задаче