// 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 rpc

import (
	"testing"

	"v.io/v23"
	"v.io/v23/options"
	"v.io/v23/security"
	"v.io/x/ref/runtime/internal/naming"

	"v.io/x/ref/test/testutil"
)

func TestServerAuthorizer(t *testing.T) {
	var (
		pclient = testutil.NewPrincipal()
		pserver = testutil.NewPrincipal()
		pother  = testutil.NewPrincipal()

		ali, _      = pserver.BlessSelf("ali")
		bob, _      = pserver.BlessSelf("bob")
		che, _      = pserver.BlessSelf("che")
		otherAli, _ = pother.BlessSelf("ali")
		zero        = security.Blessings{}

		ctx, shutdown = initForTest()

		U = func(blessings ...security.Blessings) security.Blessings {
			u, err := security.UnionOfBlessings(blessings...)
			if err != nil {
				t.Fatal(err)
			}
			return u
		}
	)
	defer shutdown()
	ctx, _ = v23.WithPrincipal(ctx, pclient)
	// Make client recognize ali, bob and otherAli blessings
	for _, b := range []security.Blessings{ali, bob, otherAli} {
		if err := pclient.AddToRoots(b); err != nil {
			t.Fatal(err)
		}
	}
	// All tests are run as if pclient is the client end and pserver is remote end.
	tests := []struct {
		serverBlessingNames []string
		auth                security.Authorizer
		authorizedServers   []security.Blessings
		unauthorizedServers []security.Blessings
	}{
		{
			// No blessings in the endpoint means that all servers are authorized.
			nil,
			newServerAuthorizer(""),
			[]security.Blessings{ali, otherAli, bob, che},
			[]security.Blessings{zero},
		},
		{
			// Endpoint sets the expectations for "ali" and "bob".
			[]string{"ali", "bob"},
			newServerAuthorizer(""),
			[]security.Blessings{ali, otherAli, bob, U(ali, che), U(bob, che)},
			[]security.Blessings{che},
		},
		{
			// Still only ali, otherAli and bob are authorized (che is not
			// authorized since it is not recognized by the client)
			[]string{"ali", "bob", "che"},
			newServerAuthorizer(""),
			[]security.Blessings{ali, otherAli, bob, U(ali, che), U(bob, che)},
			[]security.Blessings{che},
		},
		{

			// Only ali and otherAli are authorized (since there is an
			// allowed-servers policy that does not allow "bob")
			[]string{"ali", "bob", "che"},
			newServerAuthorizer("", options.AllowedServersPolicy{"ali", "bob"}, options.AllowedServersPolicy{"ali"}),
			[]security.Blessings{ali, otherAli, U(ali, che), U(ali, bob)},
			[]security.Blessings{bob, che},
		},
		{
			// Multiple AllowedServersPolicy are treated as an AND (and individual ones are "ORs")
			nil,
			newServerAuthorizer("", options.AllowedServersPolicy{"ali", "che"}, options.AllowedServersPolicy{"bob", "che"}),
			[]security.Blessings{U(ali, bob)},
			[]security.Blessings{ali, bob, che, U(ali, che), U(bob, che)},
		},
		{
			// Only otherAli is authorized (since only pother's public key is
			// authorized)
			[]string{"ali"},
			newServerAuthorizer("", options.ServerPublicKey{pother.PublicKey()}),
			[]security.Blessings{otherAli},
			[]security.Blessings{ali, bob, che},
		},
		{
			// Blessings in endpoint can be ignored.
			[]string{"ali"},
			newServerAuthorizer("", options.SkipServerEndpointAuthorization{}),
			[]security.Blessings{ali, bob, che, otherAli},
			nil,
		},
		{
			// Pattern specified is respected
			nil,
			newServerAuthorizer("bob"),
			[]security.Blessings{bob, U(ali, bob)},
			[]security.Blessings{ali, otherAli, che},
		},
		{
			// And concatenated with any existing AllowedServersPolicy
			[]string{"ali", "bob", "che"},
			newServerAuthorizer("bob", options.AllowedServersPolicy{"bob", "che"}),
			[]security.Blessings{bob, U(ali, bob), U(ali, bob, che)},
			[]security.Blessings{ali, che},
		},
		{
			// And if the intersection of AllowedServersPolicy and the pattern be empty, then so be it!
			[]string{"ali", "bob", "che"},
			newServerAuthorizer("bob", options.AllowedServersPolicy{"ali", "che"}),
			[]security.Blessings{U(ali, bob), U(ali, bob, che)},
			[]security.Blessings{ali, otherAli, bob, che, U(ali, che)},
		},
	}
	for _, test := range tests {
		for _, s := range test.authorizedServers {
			if err := test.auth.Authorize(ctx, &mockCall{
				p:   pclient,
				r:   s,
				rep: &naming.Endpoint{Blessings: test.serverBlessingNames},
			}); err != nil {
				t.Errorf("serverAuthorizer: %#v failed to authorize server: %v", test.auth, s)
			}
		}
		for _, s := range test.unauthorizedServers {
			if err := test.auth.Authorize(ctx, &mockCall{
				p:   pclient,
				r:   s,
				rep: &naming.Endpoint{Blessings: test.serverBlessingNames},
			}); err == nil {
				t.Errorf("serverAuthorizer: %#v authorized server: %v", test.auth, s)
			}
		}
	}
}
