github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libpages/config/config.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  	"encoding/json"
    11  	"io"
    12  )
    13  
    14  // DefaultConfigFilename is the default filename for Keybase Pages config file.
    15  const DefaultConfigFilename = ".kbp_config"
    16  
    17  // DefaultConfigFilepath is the default path for Keybase Pages config file
    18  // under the site root, and is what's used in kbpagesd.
    19  const DefaultConfigFilepath = "/.kbp_config"
    20  
    21  // Common includes common fields that should appear in all versions of
    22  // configs.
    23  type Common struct {
    24  	// Version specifies the version of the config.
    25  	Version string `json:"version"`
    26  }
    27  
    28  // Version specifies the version of a config.
    29  type Version int
    30  
    31  const (
    32  	// VersionUnknown defines an unknown config version.
    33  	VersionUnknown Version = iota
    34  	// Version1 is version 1.
    35  	Version1
    36  	// Version2 is version 2.
    37  	//
    38  	// Currently the only difference between V1 and V2 is that V2 uses
    39  	// sha-based password hash instead of bcrypt in V1. V2 still uses the ACL
    40  	// definition and checker from V1.
    41  	Version2
    42  )
    43  const (
    44  	// VersionUnknownStr is the string representation of VUnknown.
    45  	VersionUnknownStr string = "unknown"
    46  	// Version1Str is the string representation of Version1.
    47  	Version1Str string = "v1"
    48  	// Version2Str is the string representation of Version2.
    49  	Version2Str string = "v2"
    50  )
    51  
    52  func (v Version) String() string {
    53  	switch v {
    54  	case Version1:
    55  		return Version1Str
    56  	case Version2:
    57  		return Version2Str
    58  	default:
    59  		return VersionUnknownStr
    60  	}
    61  
    62  }
    63  
    64  func parseVersion(s string) (Version, error) {
    65  	switch s {
    66  	case Version1Str:
    67  		return Version1, nil
    68  	case Version2Str:
    69  		return Version2, nil
    70  	default:
    71  		return VersionUnknown, ErrInvalidVersion{s}
    72  	}
    73  }
    74  
    75  // Config is a collection of methods for getting different configuration
    76  // parameters.
    77  type Config interface {
    78  	Version() Version
    79  	Authenticate(ctx context.Context, username, password string) bool
    80  	// GetPermissions returns permission info. If username is nil, anonymous
    81  	// permissions are returned. Otherwise, permissions for *username is
    82  	// returned. Additionally, "maximum possible permissions" are returned,
    83  	// which indicates whether a permission (read or list) is possible to be
    84  	// granted on the path if proper authentication is provided.
    85  	GetPermissions(path string, username *string) (
    86  		read, list bool,
    87  		possibleRead, possibleList bool,
    88  		realm string, err error)
    89  	// GetAccessControlAllowOrigin returns a string that, if non-empty, should
    90  	// be set as Access-Control-Allow-Origin header.
    91  	GetAccessControlAllowOrigin(path string) (setting string, err error)
    92  
    93  	Encode(w io.Writer, prettify bool) error
    94  }
    95  
    96  // ParseConfig parses a config from reader, and initializes internal checker(s)
    97  // in the config.
    98  func ParseConfig(reader io.Reader) (config Config, err error) {
    99  	// TODO: make a better decoder to avoid having a buffer here and decoding
   100  	// twice.
   101  	buf := &bytes.Buffer{}
   102  	var common Common
   103  	err = json.NewDecoder(io.TeeReader(reader, buf)).Decode(&common)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	v, err := parseVersion(common.Version)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	switch v {
   112  	case Version1:
   113  		var v1 V1
   114  		err = json.NewDecoder(buf).Decode(&v1)
   115  		if err != nil {
   116  			return nil, err
   117  		}
   118  		return &v1, (&v1).EnsureInit()
   119  	default:
   120  		return nil, ErrInvalidVersion{}
   121  	}
   122  }