// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package pathperms provides a library to assist servers implementing
// GetPermissions/SetPermissions functions and authorizers where there are
// path-specific Permissions stored individually in files.
// TODO(rjkroege): Add unit tests.
package pathperms

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"

	"v.io/v23/context"
	"v.io/v23/security"
	"v.io/v23/security/access"
	"v.io/v23/verror"
	"v.io/x/lib/vlog"
	"v.io/x/ref/lib/security/serialization"
)

const (
	pkgPath   = "v.io/x/ref/services/internal/pathperms"
	sigName   = "signature"
	permsName = "data"
)

var (
	ErrOperationFailed = verror.Register(pkgPath+".OperationFailed", verror.NoRetry, "{1:}{2:} operation failed{:_}")
)

// PathStore manages storage of a set of Permissions in the filesystem where each
// path identifies a specific Permissions in the set. PathStore synchronizes
// access to its member Permissions.
type PathStore struct {
	// TODO(rjkroege): Garbage collect the locks map.
	pthlks    map[string]*sync.Mutex
	lk        sync.Mutex
	principal security.Principal
}

// NewPathStore creates a new instance of the lock map that uses
// principal to sign stored Permissions files.
func NewPathStore(principal security.Principal) *PathStore {
	return &PathStore{pthlks: make(map[string]*sync.Mutex), principal: principal}
}

// Get returns the Permissions from the data file in dir.
func (store PathStore) Get(dir string) (access.Permissions, string, error) {
	permspath := filepath.Join(dir, permsName)
	sigpath := filepath.Join(dir, sigName)
	defer store.lockPath(dir)()
	return getCore(store.principal, permspath, sigpath)
}

// TODO(rjkroege): Improve lock handling.
func (store PathStore) lockPath(dir string) func() {
	store.lk.Lock()
	lck, contains := store.pthlks[dir]
	if !contains {
		lck = new(sync.Mutex)
		store.pthlks[dir] = lck
	}
	store.lk.Unlock()
	lck.Lock()
	return lck.Unlock
}

func getCore(principal security.Principal, permspath, sigpath string) (access.Permissions, string, error) {
	f, err := os.Open(permspath)
	if err != nil {
		// This path is rarely a fatal error so log informationally only.
		vlog.VI(2).Infof("os.Open(%s) failed: %v", permspath, err)
		return nil, "", err
	}
	defer f.Close()

	s, err := os.Open(sigpath)
	if err != nil {
		vlog.Errorf("Signatures for Permissions are required: %s unavailable: %v", permspath, err)
		return nil, "", verror.New(ErrOperationFailed, nil)
	}
	defer s.Close()

	// read and verify the signature of the perms file
	vf, err := serialization.NewVerifyingReader(f, s, principal.PublicKey())
	if err != nil {
		vlog.Errorf("NewVerifyingReader() failed: %v (perms=%s, sig=%s)", err, permspath, sigpath)
		return nil, "", verror.New(ErrOperationFailed, nil)
	}

	perms, err := access.ReadPermissions(vf)
	if err != nil {
		vlog.Errorf("ReadPermissions(%s) failed: %v", permspath, err)
		return nil, "", err
	}
	version, err := ComputeVersion(perms)
	if err != nil {
		vlog.Errorf("pathperms.ComputeVersion failed: %v", err)
		return nil, "", err
	}
	return perms, version, nil
}

// Set writes the specified Permissions to the provided directory with
// enforcement of version synchronization mechanism and locking.
func (store PathStore) Set(dir string, perms access.Permissions, version string) error {
	permspath := filepath.Join(dir, permsName)
	sigpath := filepath.Join(dir, sigName)
	defer store.lockPath(dir)()
	_, oversion, err := getCore(store.principal, permspath, sigpath)
	if err != nil && !os.IsNotExist(err) {
		return verror.New(ErrOperationFailed, nil)
	}
	if len(version) > 0 && version != oversion {
		return verror.NewErrBadVersion(nil)
	}
	return write(store.principal, permspath, sigpath, dir, perms)
}

// write writes the specified Permissions to the permsFile with a
// signature in sigFile.
func write(principal security.Principal, permsFile, sigFile, dir string, perms access.Permissions) error {
	// Create dir directory if it does not exist
	os.MkdirAll(dir, os.FileMode(0700))
	// Save the object to temporary data and signature files, and then move
	// those files to the actual data and signature file.
	data, err := ioutil.TempFile(dir, permsName)
	if err != nil {
		vlog.Errorf("Failed to open tmpfile data:%v", err)
		return verror.New(ErrOperationFailed, nil)
	}
	defer os.Remove(data.Name())
	sig, err := ioutil.TempFile(dir, sigName)
	if err != nil {
		vlog.Errorf("Failed to open tmpfile sig:%v", err)
		return verror.New(ErrOperationFailed, nil)
	}
	defer os.Remove(sig.Name())
	writer, err := serialization.NewSigningWriteCloser(data, sig, principal, nil)
	if err != nil {
		vlog.Errorf("Failed to create NewSigningWriteCloser:%v", err)
		return verror.New(ErrOperationFailed, nil)
	}
	if err = perms.WriteTo(writer); err != nil {
		vlog.Errorf("Failed to SavePermissions:%v", err)
		return verror.New(ErrOperationFailed, nil)
	}
	if err = writer.Close(); err != nil {
		vlog.Errorf("Failed to Close() SigningWriteCloser:%v", err)
		return verror.New(ErrOperationFailed, nil)
	}
	if err := os.Rename(data.Name(), permsFile); err != nil {
		vlog.Errorf("os.Rename() failed:%v", err)
		return verror.New(ErrOperationFailed, nil)
	}
	if err := os.Rename(sig.Name(), sigFile); err != nil {
		vlog.Errorf("os.Rename() failed:%v", err)
		return verror.New(ErrOperationFailed, nil)
	}
	return nil
}

func (store PathStore) PermsForPath(path string) (access.Permissions, bool, error) {
	perms, _, err := store.Get(path)
	if os.IsNotExist(err) {
		return nil, true, nil
	} else if err != nil {
		return nil, false, err
	}
	return perms, false, nil
}

// PrefixPatterns creates a pattern containing all of the prefix patterns of the
// provided blessings.
func PrefixPatterns(blessings []string) []security.BlessingPattern {
	var patterns []security.BlessingPattern
	for _, b := range blessings {
		patterns = append(patterns, security.BlessingPattern(b).PrefixPatterns()...)
	}
	return patterns
}

// PermissionsForBlessings creates the Permissions list that should be used with
// a newly created object.
func PermissionsForBlessings(blessings []string) access.Permissions {
	perms := make(access.Permissions)

	// Add the invoker's blessings and all its prefixes.
	for _, p := range PrefixPatterns(blessings) {
		for _, tag := range access.AllTypicalTags() {
			perms.Add(p, string(tag))
		}
	}
	return perms
}

// NilAuthPermissions creates Permissions that mimics the default authorization
// policy (i.e., Permissions is matched by all blessings that are either
// extensions of one of the local blessings or can be extended to form one of
// the local blessings.)
func NilAuthPermissions(ctx *context.T, call security.Call) access.Permissions {
	perms := make(access.Permissions)
	lb := security.LocalBlessingNames(ctx, call)
	for _, p := range PrefixPatterns(lb) {
		for _, tag := range access.AllTypicalTags() {
			perms.Add(p, string(tag))
		}
	}
	return perms
}
