Beispiel #1
0
Datei: app.go Projekt: zqzca/back
// Run the application, start http and scp server.
func Run(appConfig Config) {
	config = appConfig

	// Connect to DB
	db, err := lib.Connect()
	if err != nil {
		fmt.Printf("Failed to connect to db")
		return
	}

	// Logging
	log := logrus.New()
	log.Level = logrus.DebugLevel
	log.Out = os.Stdout
	log.Formatter = &logrus.TextFormatter{}

	// Websockets
	ws := ws.NewServer()

	// Shared dependencies between all controller
	deps := dependencies.Dependencies{
		Fs:     afero.NewOsFs(),
		Logger: log,
		DB:     db,
		WS:     ws,
	}

	ws.Dependencies = &deps
	go ws.Start()

	// // Start SCP
	// scp := scp.Server{}
	// scp.DB = deps.DB
	// scp.Logger = deps.Logger
	// scp.CertPath = "certs/scp.rsa"
	// scp.BindAddr = config.SCPBindAddr
	// go scp.ListenAndServe()

	if config.Secure {
		c := autocert.DirCache("certs")
		m := autocert.Manager{
			Cache:      c,
			Prompt:     autocert.AcceptTOS,
			HostPolicy: autocert.HostWhitelist("x.zqz.ca"),
		}

		s := &http.Server{
			Addr:      config.HTTPBindAddr,
			TLSConfig: &tls.Config{GetCertificate: m.GetCertificate},
		}

		deps.Info("Listening for HTTP1.1 Connections", "addr", ":3001")
		deps.Info("Listening for HTTP2 Connections", "addr", config.HTTPBindAddr)
		go http.ListenAndServe(":3001", secureRedirect())
		s.ListenAndServeTLS("", "")
	} else {
		deps.Info("Listening for HTTP1.1 Connections", "addr", config.HTTPBindAddr)
		http.ListenAndServe(config.HTTPBindAddr, Routes(deps))
	}
}
Beispiel #2
0
// BuildFile builds a file from chunks.
func BuildFile(deps dependencies.Dependencies, f *models.File) (io.ReadSeeker, error) {
	chunks, err := models.Chunks(
		deps.DB,
		qm.Where("file_id=$1", f.ID),
		qm.OrderBy("position asc"),
	).All()

	var hashes []string
	for _, c := range chunks {
		hashes = append(hashes, c.Hash)
	}

	if ok, err := chunksExist(hashes); !ok {
		deps.Error("Missing chunks!", "id", f.ID, "name", f.Name)
		return nil, err
	}

	if err != nil {
		fmt.Println("Failed to find chunks for file:", f.ID)
		return nil, err
	}

	fs := deps.Fs
	fullFilePath := filepath.Join("files", f.Hash)
	fullFile, err := fs.Create(fullFilePath)
	if err != nil {
		fmt.Println("Failed because", err)
		return nil, err
	}
	defer fullFile.Close()
	fullFileBuffer := &bytes.Buffer{}

	mw := io.MultiWriter(fullFile, fullFileBuffer)

	for _, c := range chunks {
		fmt.Println("pos:", c.Position)
		path := filepath.Join("files", "chunks", c.Hash)
		chunkData, err := fs.Open(path)

		if err != nil {
			fmt.Println("chunk Failed because", err)
			return nil, err
		}
		_, err = io.Copy(mw, chunkData)
		chunkData.Close()

		if err != nil {
			fmt.Println("Failed to copy chunk to full file")
		}
	}

	fmt.Println("Finished building file")

	// for _, c := range chunks {
	// 	path := filepath.Join("files", "chunks", c.Hash)
	// 	if err != nil {
	// 		fmt.Println("Failed to delete chunk entry:", c.ID)
	// 	}
	// 	fs.Remove(path)
	// }

	bs := bytes.NewReader(fullFileBuffer.Bytes())

	return bs, nil
}
Beispiel #3
0
// CompleteFile builds the file from chunks and then generates thumbnails
func CompleteFile(deps dependencies.Dependencies, f *models.File) error {
	deps.Info("Processing File", "name", f.Name, "id", f.ID)

	tx, err := deps.DB.Begin()
	if err != nil {
		deps.Error("Failed to create transaction")
		return err
	}

	if err = f.Reload(tx); err != nil {
		tx.Rollback()
		return errors.Wrap(err, "Failed to reload the file")
	}

	if f.State == lib.FileProcessing {
		tx.Rollback()
		return errors.Wrap(err, "This file is already being processed")
	}

	// Delete all thumbnails
	err = models.Thumbnails(tx, qm.Where("file_id=?", f.ID)).DeleteAll()
	if err != nil {
		deps.Info("No previous thumnails")
	}

	f.State = lib.FileProcessing
	if err = f.Update(tx, "state"); err != nil {
		tx.Rollback()
		return errors.Wrap(err, "Failed to update state")
	}

	reader, err := BuildFile(deps, f)
	if err != nil {
		tx.Rollback()
		return errors.Wrap(err, "Failed to complete building file")
	}

	thumbHash, thumbSize, err := CreateThumbnail(deps, reader)
	if err != nil {
		tx.Rollback()
		return errors.Wrap(err, "Failed to create thumbnail")
	}

	if len(thumbHash) == 0 {
		tx.Rollback()
		return errors.Wrap(err, "No thumbnail created")
	}

	t := models.Thumbnail{
		Hash:   thumbHash,
		Size:   thumbSize,
		FileID: f.ID,
	}

	if err = t.Insert(tx); err != nil {
		tx.Rollback()
		return errors.Wrap(err, "Failed to insert Thumbnail")
	}

	f.State = lib.FileFinished
	if err = f.Update(tx, "state"); err != nil {
		tx.Rollback()
		return errors.Wrap(err, "Failed to set state")
	}

	if err = tx.Commit(); err != nil {
		return errors.Wrap(err, "Failed to commit transaction")
	}

	if err = Cleanup(deps, f); err != nil {
		return errors.Wrap(err, "Failed to cleanup file")
	}

	deps.Info("Processed File", "name", f.Name, "id", f.ID)
	return nil
}
Beispiel #4
0
// CreateThumnail builds a JPG thumbnail and can rotate if an exif bit is set.
func CreateThumbnail(deps dependencies.Dependencies, r io.ReadSeeker) (string, int, error) {
	raw, format, err := image.Decode(r)

	if format == "" {
		return "", 0, nil
	}

	if format == "jpeg" || format == "jpg" {
		deps.Debug("Received JPG")
		orientation, err := readOrientation(r)

		if err == nil {
			deps.Debug("Rotating JPG", "orientation", orientation)
			raw = rotate(raw, orientation)
		}
	}

	deps.Debug("Thumbnail format", "fmt", format)

	if err != nil {
		deps.Error("Failed to decode image")
		return "", 0, err
	}

	fs := deps.Fs
	tmpFilePath := lib.TempFilePath("thumbnail")
	tmpFile, err := fs.Create(tmpFilePath)
	if err != nil {
		deps.Error("Failed to create temp file", "path", tmpFilePath)
		return "", 0, err
	}

	// Make sure we close.
	closeTmpFile := func() {
		if tmpFile != nil {
			tmpFile.Close()
			tmpFile = nil
		}
	}

	defer closeTmpFile()

	h := sha1.New()
	var wc writeCounter
	mw := io.MultiWriter(tmpFile, h, wc)

	// Generate Thumbnail image data
	dst := imaging.Fill(raw, 200, 200, imaging.Center, imaging.Lanczos)
	// Write it
	err = imaging.Encode(mw, dst, imaging.JPEG)
	if err != nil {
		deps.Error("Failed to encode data")
		return "", 0, err
	}

	hash := fmt.Sprintf("%x", h.Sum(nil))
	deps.Debug("Thumbnail hash", "hash:", hash)
	newPath := lib.LocalPath(hash)

	// Move temp thumbnail to final destination.
	err = os.Rename(tmpFilePath, newPath)
	if err != nil {
		deps.Error("Failed to rename file")

		// Todo delete file
		return hash, int(wc), err
	}

	// Set permissons
	err = fs.Chmod(newPath, 0644)
	if err != nil {
		deps.Error("Failed to set permissions", "path", newPath)
		// Todo delete file
		return hash, int(wc), err
	}

	return hash, int(wc), nil
}