Skip to content

Commit

Permalink
Share: New feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
Theotime Leveque committed Mar 20, 2017
1 parent 76d6e5d commit b99c13a
Show file tree
Hide file tree
Showing 3 changed files with 278 additions and 2 deletions.
107 changes: 107 additions & 0 deletions backend/share/share.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package share

import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
)

// Upload to transfer.sh
func Upload(filename string, targetURL string, key string) (string, error) {
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)

fileWriter, err := bodyWriter.CreateFormFile("uploadfile", filename)
if err != nil {
fmt.Println("error writing to buffer")
return "", err
}

var fh io.Reader
if key == "" {
fh, err = os.Open(filename)
if err != nil {
fmt.Println("error opening file")
return "", err
}
} else {
fh = EncryptFile(filename, []byte(key))
}

// iocopy
_, err = io.Copy(fileWriter, fh)
if err != nil {
return "", err
}

contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()

resp, err := http.Post(targetURL, contentType, bodyBuf)
if err != nil {
return "", err
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
fmt.Println(resp.Status)
return string(respBody), nil
}

// ZipConfigFiles produces a Zip archive
func ZipConfigFiles(filename string) {

}

// EncryptFile encrypt and return a file
func EncryptFile(filename string, key []byte) io.Reader {
fileContent, err := ioutil.ReadFile(filename)

block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}

// The IV needs to be unique, but not secure. Therefore it's common to
// include it at the beginning of the ciphertext.
ciphertext := make([]byte, aes.BlockSize+len(fileContent))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}

stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[aes.BlockSize:], fileContent)
return bytes.NewReader(ciphertext)
}

// GetshareSetFromLinkCmdUsageTemplate returns shareSetFromLinkCmd usage template
func GetshareSetFromLinkCmdUsageTemplate() string {
return `Usage:{{if .Runnable}}
{{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "<url> <conf_file> [flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
{{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}
Aliases:
{{.NameAndAliases}}
{{end}}{{if .HasExample}}
Examples:
{{ .Example }}{{end}}{{if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasAvailableInheritedFlags}}
Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}
Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
{{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
}
10 changes: 8 additions & 2 deletions cmd/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,10 @@ func setProjectCmd() *cobra.Command {
return &cobra.Command{
Use: "set",
Short: "Define a subcommand",
Long: `Define a subcommand.`,
Long: `Define a subcommand.
Usage:
ian project set <description> <command>`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
fmt.Fprint(os.Stderr, "Not enough argument.\n\n")
Expand Down Expand Up @@ -262,7 +265,10 @@ func unsetProjectCmd() *cobra.Command {
return &cobra.Command{
Use: "unset",
Short: "Remove a subcommand",
Long: `Remove a subcommand.`,
Long: `Remove a subcommand.
Usage:
ian project remove <command>`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Fprint(os.Stderr, "Not enough argument.\n\n")
Expand Down
163 changes: 163 additions & 0 deletions cmd/share.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// Copyright © 2016 Theotime LEVEQUE [email protected]
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"strings"

"github.com/spf13/cobra"
"github.com/thylong/ian/backend/config"
"github.com/thylong/ian/backend/share"
)

var key = ""

var encryptShareCmdParam bool

// var shortLinkShareCmdParam bool

func init() {
RootCmd.AddCommand(shareCmd)

shareCmd.PersistentFlags().BoolVarP(&encryptShareCmdParam, "encrypt", "s", false, "Encrypt with private key before uploading")
// shareCmd.PersistentFlags().BoolVarP(&shortLinkShareCmdParam, "bitlink", "b", false, "Get a Bit.ly shorten URL")

shareSetFromLinkCmd.SetUsageTemplate(share.GetshareSetFromLinkCmdUsageTemplate())

shareCmd.AddCommand(
shareConfigCmd,
shareProjectsCmd,
shareEnvCmd,
shareSetFromLinkCmd,
// shareAllCmd,
)
}

// shareCmd represents the env command
var shareCmd = &cobra.Command{
Use: "share",
Short: "Share ian configuration",
Long: `Share a public link to a single (or multiple) ian configuration file.`,
}

var shareConfigCmd = &cobra.Command{
Use: "config",
Short: "Share a public link to ian config.yml file",
Long: `Share a public link to ian config.yml file.`,
Run: func(cmd *cobra.Command, args []string) {
if encryptShareCmdParam {
key = config.GetUserInput("Enter a secret key: ")
}
link, err := share.Upload(config.ConfigFilesPathes[cmd.Use], "https://transfer.sh/", key)
if err != nil {
fmt.Fprint(os.Stderr, "Sorry, it looks like I cannot upload configuration file... :(")
return
}
fmt.Println(link)
},
}

var shareProjectsCmd = &cobra.Command{
Use: "projects",
Short: "Share a public link to ian projects.yml file",
Long: `Share a public link to ian projects.yml file.`,
Run: func(cmd *cobra.Command, args []string) {
if encryptShareCmdParam {
key = config.GetUserInput("Enter a secret key: ")
}
link, err := share.Upload(config.ConfigFilesPathes[cmd.Use], "https://transfer.sh/", key)
if err != nil {
fmt.Fprint(os.Stderr, "Sorry, it looks like I cannot upload configuration file... :(")
return
}
fmt.Println(link)
},
}

var shareEnvCmd = &cobra.Command{
Use: "env",
Short: "Share a public link to ian env.yml file",
Long: `Share a public link to ian env.yml file.`,
Run: func(cmd *cobra.Command, args []string) {
if encryptShareCmdParam {
key = config.GetUserInput("Enter a secret key: ")
}
link, err := share.Upload(config.ConfigFilesPathes[cmd.Use], "https://transfer.sh/", key)
if err != nil {
fmt.Fprint(os.Stderr, "Sorry, it looks like I cannot upload configuration file... :(")
return
}
fmt.Println(link)
},
}

var shareSetFromLinkCmd = &cobra.Command{
Use: "set",
Short: "Set config from config file link",
Long: `Set config from config file link.`,
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
fmt.Fprint(os.Stderr, "Not enough argument.\n\n")
cmd.Usage()
os.Exit(1)
}

_, err := url.ParseRequestURI(args[0])
if err != nil {
fmt.Fprint(os.Stderr, "Sorry, it looks like the link you provided is invalid.")
}

resp, err := http.Get(args[0])
if err != nil {
fmt.Fprint(os.Stderr, "Sorry, the link is unreachable.")
}
defer resp.Body.Close()

if strings.HasSuffix(string(strings.TrimSuffix(args[0], "/")), "_e") {
// DecryptFile
}

confFileName := strings.TrimSuffix(args[1], ".yml")
fmt.Print(confFileName)
if confFilePath, ok := config.ConfigFilesPathes[confFileName]; ok {
f, err := os.OpenFile(confFilePath, os.O_TRUNC|os.O_WRONLY, 0600)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer f.Close()

if _, err := io.Copy(f, resp.Body); err != nil {
fmt.Fprintf(os.Stderr, "Error: %s", err.Error())
os.Exit(1)
}
return
}
fmt.Fprint(os.Stderr, "Sorry, something went wrong.")
},
}

var shareAllCmd = &cobra.Command{
Use: "all",
Short: "Share a public link to ian a zip containing all files",
Long: `Share a public link to ian env.yml file.`,
Run: func(cmd *cobra.Command, args []string) {
},
}

0 comments on commit b99c13a

Please sign in to comment.