github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libpages/config/config_v1_test.go (about)

     1  // Copyright 2017 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package config
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func TestConfigV1Default(t *testing.T) {
    17  	config := DefaultV1()
    18  	read, list,
    19  		possibleRead, possibleList,
    20  		realm, err := config.GetPermissions("/", nil)
    21  	require.NoError(t, err)
    22  	require.True(t, read)
    23  	require.False(t, list)
    24  	require.True(t, possibleRead)
    25  	require.False(t, possibleList)
    26  	require.Equal(t, "/", realm)
    27  }
    28  
    29  func TestConfigV1Invalid(t *testing.T) {
    30  	err := (&V1{
    31  		Common: Common{
    32  			Version: Version1Str,
    33  		},
    34  		PerPathConfigs: map[string]PerPathConfigV1{
    35  			"/": {
    36  				WhitelistAdditionalPermissions: map[string]string{
    37  					"alice": PermRead,
    38  				},
    39  			},
    40  		},
    41  	}).EnsureInit()
    42  	require.Error(t, err)
    43  	require.IsType(t, ErrUndefinedUsername{}, err)
    44  
    45  	err = (&V1{
    46  		Common: Common{
    47  			Version: Version1Str,
    48  		},
    49  		PerPathConfigs: map[string]PerPathConfigV1{
    50  			"/": {
    51  				AnonymousPermissions: "",
    52  			},
    53  			"": {
    54  				AnonymousPermissions: PermRead,
    55  			},
    56  		},
    57  	}).EnsureInit()
    58  	require.Error(t, err)
    59  	require.IsType(t, ErrDuplicatePerPathConfigPath{}, err)
    60  
    61  	err = (&V1{
    62  		Common: Common{
    63  			Version: Version1Str,
    64  		},
    65  		PerPathConfigs: map[string]PerPathConfigV1{
    66  			"/foo": {
    67  				AnonymousPermissions: "",
    68  			},
    69  			"/foo/../foo": {
    70  				AnonymousPermissions: PermRead,
    71  			},
    72  		},
    73  	}).EnsureInit()
    74  	require.Error(t, err)
    75  	require.IsType(t, ErrDuplicatePerPathConfigPath{}, err)
    76  
    77  	err = (&V1{
    78  		Common: Common{
    79  			Version: Version1Str,
    80  		},
    81  		PerPathConfigs: map[string]PerPathConfigV1{
    82  			"/": {
    83  				AnonymousPermissions: "huh?",
    84  			},
    85  		},
    86  	}).EnsureInit()
    87  	require.Error(t, err)
    88  	require.IsType(t, ErrInvalidPermissions{}, err)
    89  }
    90  
    91  func TestConfigV1Full(t *testing.T) {
    92  	config := V1{
    93  		Common: Common{
    94  			Version: Version1Str,
    95  		},
    96  		Users: map[string]string{
    97  			"alice": generateBcryptPasswordHashForTestOrBust(t, "12345"),
    98  			"bob":   generateSHA256PasswordHashForTestOrBust(t, "54321"),
    99  		},
   100  		PerPathConfigs: map[string]PerPathConfigV1{
   101  			"/": {
   102  				AnonymousPermissions: "read,list",
   103  			},
   104  			"/alice-and-bob": {
   105  				WhitelistAdditionalPermissions: map[string]string{
   106  					"alice": PermReadAndList,
   107  					"bob":   PermRead,
   108  				},
   109  			},
   110  			"/bob": {
   111  				AnonymousPermissions: "",
   112  				WhitelistAdditionalPermissions: map[string]string{
   113  					"bob": PermReadAndList,
   114  				},
   115  			},
   116  			"/public": {
   117  				AnonymousPermissions: PermReadAndList,
   118  			},
   119  			"/public/not-really": {
   120  				AnonymousPermissions: "",
   121  				WhitelistAdditionalPermissions: map[string]string{
   122  					"alice": PermReadAndList,
   123  				},
   124  			},
   125  			"/bob/dir/deep-dir/deep-deep-dir": {},
   126  		},
   127  	}
   128  
   129  	ctx := context.Background()
   130  
   131  	authenticated := config.Authenticate(ctx, "alice", "54321")
   132  	require.False(t, authenticated)
   133  	authenticated = config.Authenticate(ctx, "bob", "12345")
   134  	require.False(t, authenticated)
   135  	authenticated = config.Authenticate(ctx, "alice", "12345")
   136  	require.True(t, authenticated)
   137  	authenticated = config.Authenticate(ctx, "bob", "54321")
   138  	require.True(t, authenticated)
   139  
   140  	read, list, possibleRead, possibleList,
   141  		realm, err := config.GetPermissions("/", nil)
   142  	require.NoError(t, err)
   143  	require.True(t, read)
   144  	require.True(t, list)
   145  	require.True(t, possibleRead)
   146  	require.True(t, possibleList)
   147  	require.Equal(t, "/", realm)
   148  	read, list, possibleRead, possibleList,
   149  		realm, err = config.GetPermissions("/", stringPtr("alice"))
   150  	require.NoError(t, err)
   151  	require.True(t, read)
   152  	require.True(t, list)
   153  	require.True(t, possibleRead)
   154  	require.True(t, possibleList)
   155  	require.Equal(t, "/", realm)
   156  	read, list, possibleRead, possibleList,
   157  		realm, err = config.GetPermissions("/", stringPtr("bob"))
   158  	require.NoError(t, err)
   159  	require.True(t, read)
   160  	require.True(t, list)
   161  	require.True(t, possibleRead)
   162  	require.True(t, possibleList)
   163  	require.Equal(t, "/", realm)
   164  
   165  	read, list, possibleRead, possibleList,
   166  		realm, err = config.GetPermissions("/alice-and-bob", nil)
   167  	require.NoError(t, err)
   168  	require.False(t, read)
   169  	require.False(t, list)
   170  	require.True(t, possibleRead)
   171  	require.True(t, possibleList)
   172  	require.Equal(t, "/alice-and-bob", realm)
   173  	read, list, possibleRead, possibleList,
   174  		realm, err = config.GetPermissions("/alice-and-bob", stringPtr("alice"))
   175  	require.NoError(t, err)
   176  	require.True(t, read)
   177  	require.True(t, list)
   178  	require.True(t, possibleRead)
   179  	require.True(t, possibleList)
   180  	require.Equal(t, "/alice-and-bob", realm)
   181  	read, list, possibleRead, possibleList,
   182  		realm, err = config.GetPermissions("/alice-and-bob", stringPtr("bob"))
   183  	require.NoError(t, err)
   184  	require.True(t, read)
   185  	require.False(t, list)
   186  	require.True(t, possibleRead)
   187  	require.True(t, possibleList)
   188  	require.Equal(t, "/alice-and-bob", realm)
   189  
   190  	read, list, possibleRead, possibleList,
   191  		realm, err = config.GetPermissions("/bob", nil)
   192  	require.NoError(t, err)
   193  	require.False(t, read)
   194  	require.False(t, list)
   195  	require.True(t, possibleRead)
   196  	require.True(t, possibleList)
   197  	require.Equal(t, "/bob", realm)
   198  	read, list, possibleRead, possibleList,
   199  		realm, err = config.GetPermissions("/bob", stringPtr("alice"))
   200  	require.NoError(t, err)
   201  	require.False(t, read)
   202  	require.False(t, list)
   203  	require.True(t, possibleRead)
   204  	require.True(t, possibleList)
   205  	require.Equal(t, "/bob", realm)
   206  	read, list, possibleRead, possibleList,
   207  		realm, err = config.GetPermissions("/bob", stringPtr("bob"))
   208  	require.NoError(t, err)
   209  	require.True(t, read)
   210  	require.True(t, list)
   211  	require.True(t, possibleRead)
   212  	require.True(t, possibleList)
   213  	require.Equal(t, "/bob", realm)
   214  
   215  	read, list, possibleRead, possibleList,
   216  		realm, err = config.GetPermissions("/public", nil)
   217  	require.NoError(t, err)
   218  	require.True(t, read)
   219  	require.True(t, list)
   220  	require.True(t, possibleRead)
   221  	require.True(t, possibleList)
   222  	require.Equal(t, "/public", realm)
   223  	read, list, possibleRead, possibleList,
   224  		realm, err = config.GetPermissions("/public", stringPtr("alice"))
   225  	require.NoError(t, err)
   226  	require.True(t, read)
   227  	require.True(t, list)
   228  	require.True(t, possibleRead)
   229  	require.True(t, possibleList)
   230  	require.Equal(t, "/public", realm)
   231  	read, list, possibleRead, possibleList,
   232  		realm, err = config.GetPermissions("/public", stringPtr("bob"))
   233  	require.NoError(t, err)
   234  	require.True(t, read)
   235  	require.True(t, list)
   236  	require.True(t, possibleRead)
   237  	require.True(t, possibleList)
   238  	require.Equal(t, "/public", realm)
   239  
   240  	read, list, possibleRead, possibleList,
   241  		realm, err = config.GetPermissions("/public/not-really", nil)
   242  	require.NoError(t, err)
   243  	require.False(t, read)
   244  	require.False(t, list)
   245  	require.True(t, possibleRead)
   246  	require.True(t, possibleList)
   247  	require.Equal(t, "/public/not-really", realm)
   248  	read, list, possibleRead, possibleList,
   249  		realm, err = config.GetPermissions("/public/not-really", stringPtr("alice"))
   250  	require.NoError(t, err)
   251  	require.True(t, read)
   252  	require.True(t, list)
   253  	require.True(t, possibleRead)
   254  	require.True(t, possibleList)
   255  	require.Equal(t, "/public/not-really", realm)
   256  	read, list, possibleRead, possibleList,
   257  		realm, err = config.GetPermissions("/public/not-really", stringPtr("bob"))
   258  	require.NoError(t, err)
   259  	require.False(t, read)
   260  	require.False(t, list)
   261  	require.True(t, possibleRead)
   262  	require.True(t, possibleList)
   263  	require.Equal(t, "/public/not-really", realm)
   264  
   265  	read, list, possibleRead, possibleList,
   266  		realm, err = config.GetPermissions("/bob/dir", nil)
   267  	require.NoError(t, err)
   268  	require.False(t, read)
   269  	require.False(t, list)
   270  	require.True(t, possibleRead)
   271  	require.True(t, possibleList)
   272  	require.Equal(t, "/bob", realm)
   273  	read, list, possibleRead, possibleList,
   274  		realm, err = config.GetPermissions("/bob/dir", stringPtr("alice"))
   275  	require.NoError(t, err)
   276  	require.False(t, read)
   277  	require.False(t, list)
   278  	require.True(t, possibleRead)
   279  	require.True(t, possibleList)
   280  	require.Equal(t, "/bob", realm)
   281  	read, list, possibleRead, possibleList,
   282  		realm, err = config.GetPermissions("/bob/dir", stringPtr("bob"))
   283  	require.NoError(t, err)
   284  	require.True(t, read)
   285  	require.True(t, list)
   286  	require.True(t, possibleRead)
   287  	require.True(t, possibleList)
   288  	require.Equal(t, "/bob", realm)
   289  
   290  	read, list, possibleRead, possibleList,
   291  		realm, err = config.GetPermissions("/bob/dir/sub", nil)
   292  	require.NoError(t, err)
   293  	require.False(t, read)
   294  	require.False(t, list)
   295  	require.True(t, possibleRead)
   296  	require.True(t, possibleList)
   297  	require.Equal(t, "/bob", realm)
   298  	read, list, possibleRead, possibleList,
   299  		realm, err = config.GetPermissions("/bob/dir/sub", stringPtr("alice"))
   300  	require.NoError(t, err)
   301  	require.False(t, read)
   302  	require.False(t, list)
   303  	require.True(t, possibleRead)
   304  	require.True(t, possibleList)
   305  	require.Equal(t, "/bob", realm)
   306  	read, list, possibleRead, possibleList,
   307  		realm, err = config.GetPermissions("/bob/dir/sub", stringPtr("bob"))
   308  	require.NoError(t, err)
   309  	require.True(t, read)
   310  	require.True(t, list)
   311  	require.True(t, possibleRead)
   312  	require.True(t, possibleList)
   313  	require.Equal(t, "/bob", realm)
   314  
   315  	read, list, possibleRead, possibleList,
   316  		realm, err = config.GetPermissions("/bob/dir/deep-dir/deep-deep-dir", nil)
   317  	require.NoError(t, err)
   318  	require.False(t, read)
   319  	require.False(t, list)
   320  	require.False(t, possibleRead)
   321  	require.False(t, possibleList)
   322  	require.Equal(t, "/bob/dir/deep-dir/deep-deep-dir", realm)
   323  	read, list, possibleRead, possibleList,
   324  		realm, err = config.GetPermissions("/bob/dir/deep-dir/deep-deep-dir", stringPtr("alice"))
   325  	require.NoError(t, err)
   326  	require.False(t, read)
   327  	require.False(t, list)
   328  	require.False(t, possibleRead)
   329  	require.False(t, possibleList)
   330  	require.Equal(t, "/bob/dir/deep-dir/deep-deep-dir", realm)
   331  	read, list, possibleRead, possibleList,
   332  		realm, err = config.GetPermissions("/bob/dir/deep-dir/deep-deep-dir", stringPtr("bob"))
   333  	require.NoError(t, err)
   334  	require.False(t, read)
   335  	require.False(t, list)
   336  	require.False(t, possibleRead)
   337  	require.False(t, possibleList)
   338  	require.Equal(t, "/bob/dir/deep-dir/deep-deep-dir", realm)
   339  }
   340  
   341  func TestV1EncodeObjectKeyOrder(t *testing.T) {
   342  	// We are relying on an undocumented feature of encoding/json where struct
   343  	// fields are serialized into json with the same order that they are
   344  	// defined in the struct. If this ever changes in the future, this test
   345  	// helps us catch it.
   346  	v1 := DefaultV1()
   347  	buf := &bytes.Buffer{}
   348  	err := v1.Encode(buf, false)
   349  	require.NoError(t, err)
   350  	const expectedJSON = `{"version":"v1","users":null,` +
   351  		`"per_path_configs":{"/":{"whitelist_additional_permissions":null,` +
   352  		`"anonymous_permissions":"read"}}}`
   353  	require.Equal(t, expectedJSON, strings.TrimSpace(buf.String()))
   354  }
   355  
   356  func TestV1DeprecatingACLsField(t *testing.T) {
   357  	perPathConfigs := map[string]PerPathConfigV1{
   358  		"/": {
   359  			WhitelistAdditionalPermissions: map[string]string{
   360  				"alice": PermRead,
   361  			},
   362  		},
   363  	}
   364  
   365  	configWithDeprecatedACLs := &V1{
   366  		Common: Common{
   367  			Version: Version1Str,
   368  		},
   369  		Users: map[string]string{
   370  			"alice": generateBcryptPasswordHashForTestOrBust(t, "12345"),
   371  		},
   372  		ACLs: perPathConfigs,
   373  	}
   374  	err := (configWithDeprecatedACLs).EnsureInit()
   375  	require.NoError(t, err)
   376  	require.Nil(t, configWithDeprecatedACLs.ACLs)
   377  	require.Equal(t, perPathConfigs, configWithDeprecatedACLs.PerPathConfigs)
   378  
   379  	err = (&V1{
   380  		Common: Common{
   381  			Version: Version1Str,
   382  		},
   383  		Users: map[string]string{
   384  			"alice": generateBcryptPasswordHashForTestOrBust(t, "12345"),
   385  		},
   386  		ACLs:           perPathConfigs,
   387  		PerPathConfigs: perPathConfigs,
   388  	}).EnsureInit()
   389  	require.IsType(t, ErrACLsPerPathConfigsBothPresent{}, err)
   390  }