blueprints: Fix handling of invalid blueprint names in the API code
Empty names are not allowed, and blueprint names should only contain characters matching: ^[a-zA-Z0-9._-]+$ This also adds tests for the various places where the blueprint name could potentially be wrong.
This commit is contained in:
parent
56ae3d33c8
commit
369312989f
4 changed files with 392 additions and 24 deletions
|
|
@ -63,6 +63,42 @@ func TestPostEmptyTOMLBlueprintV0(t *testing.T) {
|
|||
require.False(t, resp.Status, "did not return an error")
|
||||
}
|
||||
|
||||
// POST a TOML blueprint with an empty name
|
||||
func TestPostEmptyNameTOMLBlueprintV0(t *testing.T) {
|
||||
// Use a blueprint with an empty Name
|
||||
bp := `
|
||||
name=""
|
||||
version="0.0.1"
|
||||
[package]
|
||||
name="bash"
|
||||
version="*"
|
||||
`
|
||||
resp, err := PostTOMLBlueprintV0(testState.socket, bp)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// POST a TOML blueprint with an invalid name chars
|
||||
func TestPostInvalidNameTOMLBlueprintV0(t *testing.T) {
|
||||
// Use a blueprint with invalid Name
|
||||
bp := `
|
||||
name="I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜"
|
||||
version="0.0.1"
|
||||
[package]
|
||||
name="bash"
|
||||
version="*"
|
||||
`
|
||||
resp, err := PostTOMLBlueprintV0(testState.socket, bp)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// POST a new JSON blueprint
|
||||
func TestPostJSONBlueprintV0(t *testing.T) {
|
||||
bp := `{
|
||||
|
|
@ -100,6 +136,40 @@ func TestPostEmptyJSONBlueprintV0(t *testing.T) {
|
|||
require.False(t, resp.Status, "did not return an error")
|
||||
}
|
||||
|
||||
// POST a JSON blueprint with an empty name
|
||||
func TestPostEmptyNameJSONBlueprintV0(t *testing.T) {
|
||||
// Use a blueprint with an empty Name
|
||||
bp := `{
|
||||
"name": "",
|
||||
"version": "0.0.1",
|
||||
"modules": [{"name": "util-linux", "version": "*"}]
|
||||
}`
|
||||
|
||||
resp, err := PostJSONBlueprintV0(testState.socket, bp)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// POST a JSON blueprint with invalid name chars
|
||||
func TestPostInvalidNameJSONBlueprintV0(t *testing.T) {
|
||||
// Use a blueprint with an empty Name
|
||||
bp := `{
|
||||
"name": "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜",
|
||||
"version": "0.0.1",
|
||||
"modules": [{"name": "util-linux", "version": "*"}]
|
||||
}`
|
||||
|
||||
resp, err := PostJSONBlueprintV0(testState.socket, bp)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// POST a blueprint to the workspace as TOML
|
||||
func TestPostTOMLWorkspaceV0(t *testing.T) {
|
||||
bp := `
|
||||
|
|
@ -145,6 +215,42 @@ func TestPostEmptyTOMLWorkspaceV0(t *testing.T) {
|
|||
require.False(t, resp.Status, "did not return an error")
|
||||
}
|
||||
|
||||
// POST a TOML blueprint with an empty name to the workspace
|
||||
func TestPostEmptyNameTOMLWorkspaceV0(t *testing.T) {
|
||||
// Use a blueprint with an empty Name
|
||||
bp := `
|
||||
name=""
|
||||
version="0.0.1"
|
||||
[package]
|
||||
name="bash"
|
||||
version="*"
|
||||
`
|
||||
resp, err := PostTOMLWorkspaceV0(testState.socket, bp)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// POST a TOML blueprint with an invalid name chars to the workspace
|
||||
func TestPostInvalidNameTOMLWorkspaceV0(t *testing.T) {
|
||||
// Use a blueprint with invalid Name
|
||||
bp := `
|
||||
name="I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜"
|
||||
version="0.0.1"
|
||||
[package]
|
||||
name="bash"
|
||||
version="*"
|
||||
`
|
||||
resp, err := PostTOMLWorkspaceV0(testState.socket, bp)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// POST a blueprint to the workspace as JSON
|
||||
func TestPostJSONWorkspaceV0(t *testing.T) {
|
||||
bp := `{
|
||||
|
|
@ -182,6 +288,40 @@ func TestPostEmptyJSONWorkspaceV0(t *testing.T) {
|
|||
require.False(t, resp.Status, "did not return an error")
|
||||
}
|
||||
|
||||
// POST a JSON blueprint with an empty name to the workspace
|
||||
func TestPostEmptyNameJSONWorkspaceV0(t *testing.T) {
|
||||
// Use a blueprint with an empty Name
|
||||
bp := `{
|
||||
"name": "",
|
||||
"version": "0.0.1",
|
||||
"modules": [{"name": "util-linux", "version": "*"}]
|
||||
}`
|
||||
|
||||
resp, err := PostJSONWorkspaceV0(testState.socket, bp)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// POST a JSON blueprint with invalid name chars to the workspace
|
||||
func TestPostInvalidNameJSONWorkspaceV0(t *testing.T) {
|
||||
// Use a blueprint with an empty Name
|
||||
bp := `{
|
||||
"name": "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜",
|
||||
"version": "0.0.1",
|
||||
"modules": [{"name": "util-linux", "version": "*"}]
|
||||
}`
|
||||
|
||||
resp, err := PostJSONWorkspaceV0(testState.socket, bp)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// delete a blueprint
|
||||
func TestDeleteBlueprintV0(t *testing.T) {
|
||||
// POST a blueprint to delete
|
||||
|
|
@ -211,6 +351,16 @@ func TestDeleteNonBlueprint0(t *testing.T) {
|
|||
require.False(t, resp.Status, "did not return an error")
|
||||
}
|
||||
|
||||
// delete a blueprint with invalid name characters
|
||||
func TestDeleteInvalidBlueprintV0(t *testing.T) {
|
||||
resp, err := DeleteBlueprintV0(testState.socket, "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// delete a new blueprint from the workspace
|
||||
func TestDeleteNewWorkspaceV0(t *testing.T) {
|
||||
// POST a blueprint to delete
|
||||
|
|
@ -291,6 +441,23 @@ func TestDeleteChangesWorkspaceV0(t *testing.T) {
|
|||
require.Equal(t, "deleteBlueprintChangesWSV0", info.Blueprints[0].Description, "original blueprint not returned")
|
||||
}
|
||||
|
||||
// delete a non-existent blueprint workspace
|
||||
func TestDeleteNonWorkspace0(t *testing.T) {
|
||||
resp, err := DeleteWorkspaceV0(testState.socket, "test-delete-non-blueprint-ws-v0")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.False(t, resp.Status, "did not return an error")
|
||||
}
|
||||
|
||||
// delete a blueprint with invalid name characters
|
||||
func TestDeleteInvalidWorkspaceV0(t *testing.T) {
|
||||
resp, err := DeleteWorkspaceV0(testState.socket, "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// list blueprints
|
||||
func TestListBlueprintsV0(t *testing.T) {
|
||||
// Post a couple of blueprints
|
||||
|
|
@ -361,6 +528,16 @@ func TestGetNonTOMLBlueprintV0(t *testing.T) {
|
|||
require.False(t, api.Status, "wrong Status (true)")
|
||||
}
|
||||
|
||||
// get blueprint with invalid name characters
|
||||
func TestGetInvalidTOMLBlueprintV0(t *testing.T) {
|
||||
_, api, err := GetBlueprintInfoTOMLV0(testState.socket, "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, api, "did not return an error")
|
||||
require.False(t, api.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", api.Errors[0].ID)
|
||||
require.Contains(t, api.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// get blueprint contents as JSON
|
||||
func TestGetJSONBlueprintV0(t *testing.T) {
|
||||
bp := `{
|
||||
|
|
@ -490,6 +667,16 @@ func TestBlueprintNonChangesV0(t *testing.T) {
|
|||
require.Greater(t, len(resp.Errors), 0, "failed with no error: %#v", resp)
|
||||
}
|
||||
|
||||
// get changes with invalid name characters
|
||||
func TestInvalidBlueprintChangesV0(t *testing.T) {
|
||||
_, api, err := GetBlueprintsChangesV0(testState.socket, []string{"I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜"})
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, api, "did not return an error")
|
||||
require.False(t, api.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", api.Errors[0].ID)
|
||||
require.Contains(t, api.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// Undo blueprint changes
|
||||
func TestUndoBlueprintV0(t *testing.T) {
|
||||
bps := []string{`{
|
||||
|
|
@ -589,6 +776,26 @@ func TestUndoNonBlueprintV0(t *testing.T) {
|
|||
require.False(t, resp.Status, "did not return an error")
|
||||
}
|
||||
|
||||
// undo a blueprint with invalid name characters
|
||||
func TestUndoInvalidBlueprintV0(t *testing.T) {
|
||||
resp, err := UndoBlueprintChangeV0(testState.socket, "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜", "FFFF")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// undo a blueprint with invalid commit characters
|
||||
func TestUndoInvalidBlueprintCommitV0(t *testing.T) {
|
||||
resp, err := UndoBlueprintChangeV0(testState.socket, "test-undo-non-blueprint-v0", "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// Tag a blueprint with a new revision
|
||||
// The blueprint revision tag cannot be reset, it always increments by one, and cannot be deleted.
|
||||
// So to test tagging we tag two blueprint changes and make sure the second is first +1
|
||||
|
|
@ -660,6 +867,16 @@ func TestNonBlueprintTagV0(t *testing.T) {
|
|||
require.False(t, tagResp.Status, "did not return an error")
|
||||
}
|
||||
|
||||
// tag a blueprint with invalid name characters
|
||||
func TestTagInvalidBlueprintV0(t *testing.T) {
|
||||
resp, err := TagBlueprintV0(testState.socket, "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp, "did not return an error")
|
||||
require.False(t, resp.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// depsolve a blueprint with packages and modules
|
||||
func TestBlueprintDepsolveV0(t *testing.T) {
|
||||
bp := `{
|
||||
|
|
@ -695,6 +912,16 @@ func TestNonBlueprintDepsolveV0(t *testing.T) {
|
|||
require.Greater(t, len(resp.Errors), 0, "failed with no error: %#v", resp)
|
||||
}
|
||||
|
||||
// depsolve a blueprint with invalid name characters
|
||||
func TestDepsolveInvalidBlueprintV0(t *testing.T) {
|
||||
_, api, err := DepsolveBlueprintV0(testState.socket, "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, api, "did not return an error")
|
||||
require.False(t, api.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", api.Errors[0].ID)
|
||||
require.Contains(t, api.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// freeze a blueprint
|
||||
func TestBlueprintFreezeV0(t *testing.T) {
|
||||
if testState.unitTest {
|
||||
|
|
@ -758,4 +985,14 @@ func TestNonBlueprintFreezeV0(t *testing.T) {
|
|||
require.Greater(t, len(resp.Errors), 0, "failed with no error: %#v", resp)
|
||||
}
|
||||
|
||||
// freeze a blueprint with invalid name characters
|
||||
func TestFreezeInvalidBlueprintV0(t *testing.T) {
|
||||
_, api, err := FreezeBlueprintV0(testState.socket, "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, api, "did not return an error")
|
||||
require.False(t, api.Status, "wrong Status (true)")
|
||||
require.Equal(t, "InvalidChars", api.Errors[0].ID)
|
||||
require.Contains(t, api.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// TODO diff of blueprint changes
|
||||
|
|
|
|||
|
|
@ -89,6 +89,36 @@ func TestComposeInvalidBlueprintV0(t *testing.T) {
|
|||
require.Contains(t, resp.Errors[0].Msg, "test-invalid-bp-compose-v0")
|
||||
}
|
||||
|
||||
// Test compose for empty blueprint fails
|
||||
func TestComposeEmptyBlueprintV0(t *testing.T) {
|
||||
compose := `{
|
||||
"blueprint_name": "",
|
||||
"compose_type": "qcow2",
|
||||
"branch": "master"
|
||||
}`
|
||||
resp, err := PostComposeV0(testState.socket, compose)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp)
|
||||
require.False(t, resp.Status, "POST did not fail")
|
||||
require.Equal(t, len(resp.Errors), 1)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// Test compose for blueprint with invalid characters fails
|
||||
func TestComposeInvalidCharsBlueprintV0(t *testing.T) {
|
||||
compose := `{
|
||||
"blueprint_name": "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜",
|
||||
"compose_type": "qcow2",
|
||||
"branch": "master"
|
||||
}`
|
||||
resp, err := PostComposeV0(testState.socket, compose)
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp)
|
||||
require.False(t, resp.Status, "POST did not fail")
|
||||
require.Equal(t, len(resp.Errors), 1)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
}
|
||||
|
||||
// Test compose cancel for unknown uuid fails
|
||||
// Is cancel implemented at all?
|
||||
|
||||
|
|
@ -162,6 +192,24 @@ func TestComposeInvalidStatusV0(t *testing.T) {
|
|||
require.Equal(t, 0, len(status))
|
||||
}
|
||||
|
||||
// Test status filter for unknown blueprint
|
||||
func TestComposeUnknownBlueprintStatusV0(t *testing.T) {
|
||||
status, resp, err := GetComposeStatusV0(testState.socket, "*", "unknown-blueprint-test", "", "")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.Nil(t, resp)
|
||||
require.Equal(t, 0, len(status))
|
||||
}
|
||||
|
||||
// Test status filter for blueprint with invalid characters
|
||||
func TestComposeInvalidBlueprintStatusV0(t *testing.T) {
|
||||
status, resp, err := GetComposeStatusV0(testState.socket, "*", "I w𝒊ll 𝟉ο𝘁 𝛠a𝔰ꜱ 𝘁𝒉𝝸𝚜", "", "")
|
||||
require.NoError(t, err, "failed with a client error")
|
||||
require.NotNil(t, resp)
|
||||
require.Equal(t, "InvalidChars", resp.Errors[0].ID)
|
||||
require.Contains(t, resp.Errors[0].Msg, "Invalid characters in API path")
|
||||
require.Equal(t, 0, len(status))
|
||||
}
|
||||
|
||||
// Helper for searching compose results for a UUID
|
||||
func UUIDInComposeResults(buildID uuid.UUID, results []weldr.ComposeEntryV0) bool {
|
||||
for idx := range results {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -43,6 +44,8 @@ type API struct {
|
|||
router *httprouter.Router
|
||||
}
|
||||
|
||||
var ValidBlueprintName = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`)
|
||||
|
||||
func New(rpmmd rpmmd.RPMMD, arch distro.Arch, distro distro.Distro, repos []rpmmd.RepoConfig, logger *log.Logger, store *store.Store, workers *worker.Server) *API {
|
||||
api := &API{
|
||||
store: store,
|
||||
|
|
@ -232,6 +235,24 @@ type responseError struct {
|
|||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// verifyStringsWithRegex checks a slive of strings against a regex of allowed characters
|
||||
// it writes the InvalidChars error to the writer and returns false if any of them fail the check
|
||||
// It will also return an error if the string is empty
|
||||
func verifyStringsWithRegex(writer http.ResponseWriter, strings []string, re *regexp.Regexp) bool {
|
||||
for _, s := range strings {
|
||||
if len(s) > 0 && re.MatchString(s) {
|
||||
continue
|
||||
}
|
||||
errors := responseError{
|
||||
ID: "InvalidChars",
|
||||
Msg: "Invalid characters in API path",
|
||||
}
|
||||
statusResponseError(writer, http.StatusBadRequest, errors)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func statusResponseError(writer http.ResponseWriter, code int, errors ...responseError) {
|
||||
type reply struct {
|
||||
Status bool `json:"status"`
|
||||
|
|
@ -807,6 +828,13 @@ func (api *API) blueprintsInfoHandler(writer http.ResponseWriter, request *http.
|
|||
return
|
||||
}
|
||||
|
||||
// Remove the leading / from the first entry (check above ensures it is not just a /
|
||||
names[0] = names[0][1:]
|
||||
|
||||
if !verifyStringsWithRegex(writer, names, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
query, err := url.ParseQuery(request.URL.RawQuery)
|
||||
if err != nil {
|
||||
errors := responseError{
|
||||
|
|
@ -821,12 +849,7 @@ func (api *API) blueprintsInfoHandler(writer http.ResponseWriter, request *http.
|
|||
changes := []change{}
|
||||
blueprintErrors := []responseError{}
|
||||
|
||||
for i, name := range names {
|
||||
// remove leading / from first name
|
||||
if i == 0 {
|
||||
name = name[1:]
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
blueprint, changed := api.store.GetBlueprint(name)
|
||||
if blueprint == nil {
|
||||
blueprintErrors = append(blueprintErrors, responseError{
|
||||
|
|
@ -902,13 +925,16 @@ func (api *API) blueprintsDepsolveHandler(writer http.ResponseWriter, request *h
|
|||
return
|
||||
}
|
||||
|
||||
// Remove the leading / from the first entry (check above ensures it is not just a /
|
||||
names[0] = names[0][1:]
|
||||
|
||||
if !verifyStringsWithRegex(writer, names, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
blueprints := []entry{}
|
||||
blueprintsErrors := []responseError{}
|
||||
for i, name := range names {
|
||||
// remove leading / from first name
|
||||
if i == 0 {
|
||||
name = name[1:]
|
||||
}
|
||||
for _, name := range names {
|
||||
blueprint, _ := api.store.GetBlueprint(name)
|
||||
if blueprint == nil {
|
||||
blueprintsErrors = append(blueprintsErrors, responseError{
|
||||
|
|
@ -987,13 +1013,16 @@ func (api *API) blueprintsFreezeHandler(writer http.ResponseWriter, request *htt
|
|||
return
|
||||
}
|
||||
|
||||
// Remove the leading / from the first entry (check above ensures it is not just a /
|
||||
names[0] = names[0][1:]
|
||||
|
||||
if !verifyStringsWithRegex(writer, names, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
blueprints := []blueprintFrozen{}
|
||||
errors := []responseError{}
|
||||
for i, name := range names {
|
||||
// remove leading / from first name
|
||||
if i == 0 {
|
||||
name = name[1:]
|
||||
}
|
||||
for _, name := range names {
|
||||
bp, _ := api.store.GetBlueprint(name)
|
||||
if bp == nil {
|
||||
rerr := responseError{
|
||||
|
|
@ -1076,8 +1105,19 @@ func (api *API) blueprintsDiffHandler(writer http.ResponseWriter, request *http.
|
|||
}
|
||||
|
||||
name := params.ByName("blueprint")
|
||||
if !verifyStringsWithRegex(writer, []string{name}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
fromCommit := params.ByName("from")
|
||||
if !verifyStringsWithRegex(writer, []string{fromCommit}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
toCommit := params.ByName("to")
|
||||
if !verifyStringsWithRegex(writer, []string{toCommit}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
if len(name) == 0 || len(fromCommit) == 0 || len(toCommit) == 0 {
|
||||
errors := responseError{
|
||||
|
|
@ -1178,6 +1218,13 @@ func (api *API) blueprintsChangesHandler(writer http.ResponseWriter, request *ht
|
|||
return
|
||||
}
|
||||
|
||||
// Remove the leading / from the first entry (check above ensures it is not just a /
|
||||
names[0] = names[0][1:]
|
||||
|
||||
if !verifyStringsWithRegex(writer, names, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
offset, limit, err := parseOffsetAndLimit(request.URL.Query())
|
||||
if err != nil {
|
||||
errors := responseError{
|
||||
|
|
@ -1190,11 +1237,7 @@ func (api *API) blueprintsChangesHandler(writer http.ResponseWriter, request *ht
|
|||
|
||||
allChanges := []change{}
|
||||
errors := []responseError{}
|
||||
for i, name := range names {
|
||||
// remove leading / from first name
|
||||
if i == 0 {
|
||||
name = name[1:]
|
||||
}
|
||||
for _, name := range names {
|
||||
bpChanges := api.store.GetBlueprintChanges(name)
|
||||
// Reverse the changes, newest first
|
||||
reversed := make([]blueprint.Change, 0, len(bpChanges))
|
||||
|
|
@ -1269,6 +1312,10 @@ func (api *API) blueprintsNewHandler(writer http.ResponseWriter, request *http.R
|
|||
return
|
||||
}
|
||||
|
||||
if !verifyStringsWithRegex(writer, []string{blueprint.Name}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
commitMsg := "Recipe " + blueprint.Name + ", version " + blueprint.Version + " saved."
|
||||
err = api.store.PushBlueprint(blueprint, commitMsg)
|
||||
if err != nil {
|
||||
|
|
@ -1326,6 +1373,10 @@ func (api *API) blueprintsWorkspaceHandler(writer http.ResponseWriter, request *
|
|||
return
|
||||
}
|
||||
|
||||
if !verifyStringsWithRegex(writer, []string{blueprint.Name}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
err = api.store.PushBlueprintToWorkspace(blueprint)
|
||||
if err != nil {
|
||||
errors := responseError{
|
||||
|
|
@ -1345,7 +1396,15 @@ func (api *API) blueprintUndoHandler(writer http.ResponseWriter, request *http.R
|
|||
}
|
||||
|
||||
name := params.ByName("blueprint")
|
||||
if !verifyStringsWithRegex(writer, []string{name}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
commit := params.ByName("commit")
|
||||
if !verifyStringsWithRegex(writer, []string{commit}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
bpChange, err := api.store.GetBlueprintChange(name, commit)
|
||||
if err != nil {
|
||||
errors := responseError{
|
||||
|
|
@ -1375,7 +1434,12 @@ func (api *API) blueprintDeleteHandler(writer http.ResponseWriter, request *http
|
|||
return
|
||||
}
|
||||
|
||||
if err := api.store.DeleteBlueprint(params.ByName("blueprint")); err != nil {
|
||||
name := params.ByName("blueprint")
|
||||
if !verifyStringsWithRegex(writer, []string{name}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := api.store.DeleteBlueprint(name); err != nil {
|
||||
errors := responseError{
|
||||
ID: "BlueprintsError",
|
||||
Msg: err.Error(),
|
||||
|
|
@ -1391,7 +1455,12 @@ func (api *API) blueprintDeleteWorkspaceHandler(writer http.ResponseWriter, requ
|
|||
return
|
||||
}
|
||||
|
||||
if err := api.store.DeleteBlueprintFromWorkspace(params.ByName("blueprint")); err != nil {
|
||||
name := params.ByName("blueprint")
|
||||
if !verifyStringsWithRegex(writer, []string{name}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := api.store.DeleteBlueprintFromWorkspace(name); err != nil {
|
||||
errors := responseError{
|
||||
ID: "BlueprintsError",
|
||||
Msg: err.Error(),
|
||||
|
|
@ -1408,7 +1477,12 @@ func (api *API) blueprintsTagHandler(writer http.ResponseWriter, request *http.R
|
|||
return
|
||||
}
|
||||
|
||||
err := api.store.TagBlueprint(params.ByName("blueprint"))
|
||||
name := params.ByName("blueprint")
|
||||
if !verifyStringsWithRegex(writer, []string{name}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
err := api.store.TagBlueprint(name)
|
||||
if err != nil {
|
||||
errors := responseError{
|
||||
ID: "BlueprintsError",
|
||||
|
|
@ -1472,6 +1546,10 @@ func (api *API) composeHandler(writer http.ResponseWriter, request *http.Request
|
|||
return
|
||||
}
|
||||
|
||||
if !verifyStringsWithRegex(writer, []string{cr.BlueprintName}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
composeID := uuid.New()
|
||||
|
||||
var targets []*target.Target
|
||||
|
|
@ -1727,6 +1805,10 @@ func (api *API) composeStatusHandler(writer http.ResponseWriter, request *http.R
|
|||
}
|
||||
|
||||
filterBlueprint := q.Get("blueprint")
|
||||
if len(filterBlueprint) > 0 && !verifyStringsWithRegex(writer, []string{filterBlueprint}, ValidBlueprintName) {
|
||||
return
|
||||
}
|
||||
|
||||
filterStatus := q.Get("status")
|
||||
filterImageType, filterImageTypeExists := common.ImageTypeFromCompatString(q.Get("type"))
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ func TestBlueprintsNew(t *testing.T) {
|
|||
{"POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages":[],"version":""}`, http.StatusOK, `{"status":true}`},
|
||||
{"POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages":[{"name":"httpd","version":"2.4.*"}],"version":"0.0.0"}`, http.StatusOK, `{"status":true}`},
|
||||
{"POST", "/api/v0/blueprints/new", `{"name":"test","description":"Test","packages:}`, http.StatusBadRequest, `{"status":false,"errors":[{"id":"BlueprintsError","msg":"400 Bad Request: The browser (or proxy) sent a request that this server could not understand: unexpected EOF"}]}`},
|
||||
{"POST", "/api/v0/blueprints/new", `{"name":"","description":"Test","packages":[{"name":"httpd","version":"2.4.*"}],"version":"0.0.0"}`, http.StatusBadRequest, `{"status":false,"errors":[{"id":"InvalidChars","msg":"Invalid characters in API path"}]}`},
|
||||
{"POST", "/api/v0/blueprints/new", ``, http.StatusBadRequest, `{"status":false,"errors":[{"id":"BlueprintsError","msg":"Missing blueprint"}]}`},
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue