[#148] Make secret optional when files are attached (#150)

This commit is contained in:
Knut Ahlers 2023-11-20 15:52:06 +01:00 committed by GitHub
parent 62d2897e44
commit 8d29e5f6ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 26 deletions

View File

@ -1,6 +1,7 @@
package main
import (
"bytes"
"fmt"
"io"
"mime"
@ -37,6 +38,7 @@ func init() {
createCmd.Flags().StringSliceP("header", "H", nil, "Headers to include in the request (i.e. 'Authorization: Token ...')")
createCmd.Flags().String("instance", "https://ots.fyi/", "Instance to create the secret with")
createCmd.Flags().StringSliceP("file", "f", nil, "File(s) to attach to the secret")
createCmd.Flags().Bool("no-text", false, "Disable secret read (create a secret with only files)")
createCmd.Flags().String("secret-from", "-", `File to read the secret content from ("-" for STDIN)`)
createCmd.Flags().StringP("user", "u", "", "Username / Password for basic auth, specified as 'user:pass'")
rootCmd.AddCommand(createCmd)
@ -51,29 +53,10 @@ func createRunE(cmd *cobra.Command, _ []string) (err error) {
// Read the secret content
logrus.Info("reading secret content...")
secretSourceName, err := cmd.Flags().GetString("secret-from")
if err != nil {
return fmt.Errorf("getting secret-from flag: %w", err)
if secret.Secret, err = getSecretContent(cmd); err != nil {
return fmt.Errorf("getting secret content: %w", err)
}
var secretSource io.Reader
if secretSourceName == "-" {
secretSource = os.Stdin
} else {
f, err := os.Open(secretSourceName) //#nosec:G304 // Opening user specified file is intended
if err != nil {
return fmt.Errorf("opening secret-from file: %w", err)
}
defer f.Close() //nolint:errcheck // The file will be force-closed by program exit
secretSource = f
}
secretContent, err := io.ReadAll(secretSource)
if err != nil {
return fmt.Errorf("reading secret content: %w", err)
}
secret.Secret = string(secretContent)
// Attach any file given
files, err := cmd.Flags().GetStringSlice("file")
if err != nil {
@ -93,6 +76,10 @@ func createRunE(cmd *cobra.Command, _ []string) (err error) {
})
}
if secret.Secret == "" && secret.Attachments == nil {
return fmt.Errorf("secret has no content and no attachments")
}
// Get flags for creation
logrus.Info("creating the secret...")
instanceURL, err := cmd.Flags().GetString("instance")
@ -158,6 +145,42 @@ func constructHTTPClient(cmd *cobra.Command) (*http.Client, error) {
return &http.Client{Transport: t}, nil
}
func getSecretContent(cmd *cobra.Command) (string, error) {
secretSourceName, err := cmd.Flags().GetString("secret-from")
if err != nil {
return "", fmt.Errorf("getting secret-from flag: %w", err)
}
noSecret, err := cmd.Flags().GetBool("no-text")
if err != nil {
return "", fmt.Errorf("getting no-text flag: %w", err)
}
var secretSource io.Reader
switch {
case noSecret:
secretSource = bytes.NewReader(nil)
case secretSourceName == "-":
secretSource = os.Stdin
default:
f, err := os.Open(secretSourceName) //#nosec:G304 // Opening user specified file is intended
if err != nil {
return "", fmt.Errorf("opening secret-from file: %w", err)
}
defer f.Close() //nolint:errcheck // The file will be force-closed by program exit
secretSource = f
}
secretContent, err := io.ReadAll(secretSource)
if err != nil {
return "", fmt.Errorf("reading secret content: %w", err)
}
return strings.TrimSpace(string(secretContent)), nil
}
func (a authRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
if a.user != "" {
r.SetBasicAuth(a.user, a.pass)

View File

@ -72,7 +72,7 @@
<button
type="submit"
class="btn btn-success"
:disabled="secret.trim().length < 1 || maxFileSizeExceeded || invalidFilesSelected || createRunning"
:disabled="!canCreate"
>
<template v-if="!createRunning">
{{ $t('btn-create-secret') }}
@ -148,6 +148,10 @@ const passwordLength = 20
export default {
computed: {
canCreate() {
return (this.secret.trim().length > 0 || this.selectedFileMeta.length > 0) && !this.maxFileSizeExceeded && !this.invalidFilesSelected
},
expiryChoices() {
const choices = [{ text: this.$t('expire-default'), value: null }]
for (const choice of this.$root.customize.expiryChoices || defaultExpiryChoices) {
@ -243,7 +247,7 @@ export default {
// createSecret executes the secret creation after encrypting the secret
createSecret() {
if (this.secret.trim().length < 1 || this.maxFileSizeExceeded || this.invalidFilesSelected) {
if (!this.canCreate) {
return false
}

View File

@ -6,7 +6,7 @@
v-html="$t('title-reading-secret')"
/>
<div class="card-body">
<template v-if="!secret">
<template v-if="!secret && files.length === 0">
<p v-html="$t('text-pre-reveal-hint')" />
<button
class="btn btn-success"
@ -23,7 +23,10 @@
</button>
</template>
<template v-else>
<div class="input-group mb-3">
<div
v-if="secret"
class="input-group mb-3"
>
<textarea
class="form-control"
readonly
@ -47,7 +50,6 @@
</div>
</div>
</div>
<p v-html="$t('text-hint-burned')" />
<template v-if="files.length > 0">
<p v-html="$t('text-attached-files')" />
<ul>
@ -64,6 +66,7 @@
</li>
</ul>
</template>
<p v-html="$t('text-hint-burned')" />
</template>
</div>
</div>