Validate portable workspace identifiers
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/config"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/pathsafe"
|
||||
)
|
||||
|
||||
// SessionPaths contains canonical local paths for one session work directory.
|
||||
@@ -63,11 +64,15 @@ func SessionPreviousArtifactsDirForCampaign(rootDir, campaign, sessionID string)
|
||||
return filepath.Join(SessionPreviousDirForCampaign(rootDir, campaign, sessionID), config.PathArtifactsDirSegment)
|
||||
}
|
||||
|
||||
// SessionPreviousArtifactPathForCampaign returns a path under previous/artifacts for one artifact.
|
||||
func SessionPreviousArtifactPathForCampaign(rootDir, campaign, sessionID, artifactRelativePath string) string {
|
||||
return filepath.Join(
|
||||
// SessionPreviousArtifactPathForCampaign returns a confined path under
|
||||
// previous/artifacts for one artifact.
|
||||
func SessionPreviousArtifactPathForCampaign(rootDir, campaign, sessionID, artifactRelativePath string) (string, error) {
|
||||
if err := ValidateSessionIdentity(campaign, sessionID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return pathsafe.JoinSlashRelativeUnderRoot(
|
||||
SessionPreviousArtifactsDirForCampaign(rootDir, campaign, sessionID),
|
||||
filepath.FromSlash(previousArtifactCacheRelativePath(artifactRelativePath)),
|
||||
previousArtifactCacheRelativePath(artifactRelativePath),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -190,9 +195,34 @@ func SessionPreviousArtifactsDir(paths SessionPaths) string {
|
||||
return paths.PreviousArtifactsDir
|
||||
}
|
||||
|
||||
// SessionPreviousArtifactPath returns a path under previous/artifacts for already-resolved session paths.
|
||||
func SessionPreviousArtifactPath(paths SessionPaths, artifactRelativePath string) string {
|
||||
return filepath.Join(paths.PreviousArtifactsDir, filepath.FromSlash(previousArtifactCacheRelativePath(artifactRelativePath)))
|
||||
// SessionPreviousArtifactPath returns a confined path under previous/artifacts
|
||||
// for already-resolved session paths.
|
||||
func SessionPreviousArtifactPath(paths SessionPaths, artifactRelativePath string) (string, error) {
|
||||
if err := ValidateSessionIdentity(paths.CampaignID, paths.SessionID); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return pathsafe.JoinSlashRelativeUnderRoot(paths.PreviousArtifactsDir, previousArtifactCacheRelativePath(artifactRelativePath))
|
||||
}
|
||||
|
||||
// ValidateSessionIdentity validates the opaque components used in workspace
|
||||
// and object-store session paths.
|
||||
func ValidateSessionIdentity(campaign, sessionID string) error {
|
||||
if err := pathsafe.ValidateOpaqueSegment(campaign); err != nil {
|
||||
return fmt.Errorf("campaign identity: %w", err)
|
||||
}
|
||||
if err := pathsafe.ValidateOpaqueSegment(sessionID); err != nil {
|
||||
return fmt.Errorf("session identity: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateRunIdentity validates the opaque component used below a session's
|
||||
// run directory and object-store prefix.
|
||||
func ValidateRunIdentity(runID string) error {
|
||||
if err := pathsafe.ValidateOpaqueSegment(runID); err != nil {
|
||||
return fmt.Errorf("run identity: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func previousArtifactCacheRelativePath(artifactRelativePath string) string {
|
||||
|
||||
Reference in New Issue
Block a user