mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-31 01:10:20 -06:00
Bump reva
This commit is contained in:
5
go.mod
5
go.mod
@@ -60,10 +60,10 @@ require (
|
||||
github.com/oklog/run v1.1.0
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/onsi/ginkgo v1.16.5
|
||||
github.com/onsi/ginkgo/v2 v2.23.0
|
||||
github.com/onsi/ginkgo/v2 v2.23.1
|
||||
github.com/onsi/gomega v1.36.2
|
||||
github.com/open-policy-agent/opa v1.2.0
|
||||
github.com/opencloud-eu/reva/v2 v2.28.1-0.20250319144557-ae6d4d54cb01
|
||||
github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320105919-be91238e6b11
|
||||
github.com/orcaman/concurrent-map v1.0.0
|
||||
github.com/owncloud/libre-graph-api-go v1.0.5-0.20240829135935-80dc00d6f5ea
|
||||
github.com/pkg/errors v0.9.1
|
||||
@@ -287,6 +287,7 @@ require (
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/sercand/kuberesolver/v5 v5.1.1 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/sethvargo/go-diceware v0.5.0 // indirect
|
||||
github.com/sethvargo/go-password v0.3.1 // indirect
|
||||
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
|
||||
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect
|
||||
|
||||
10
go.sum
10
go.sum
@@ -852,8 +852,8 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.23.0 h1:FA1xjp8ieYDzlgS5ABTpdUDB7wtngggONc8a7ku2NqQ=
|
||||
github.com/onsi/ginkgo/v2 v2.23.0/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
|
||||
github.com/onsi/ginkgo/v2 v2.23.1 h1:Ox0cOPv/t8RzKJUfDo9ZKtRvBOJY369sFJnl00CjqwY=
|
||||
github.com/onsi/ginkgo/v2 v2.23.1/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
@@ -861,8 +861,8 @@ github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
|
||||
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
|
||||
github.com/open-policy-agent/opa v1.2.0 h1:88NDVCM0of1eO6Z4AFeL3utTEtMuwloFmWWU7dRV1z0=
|
||||
github.com/open-policy-agent/opa v1.2.0/go.mod h1:30euUmOvuBoebRCcJ7DMF42bRBOPznvt0ACUMYDUGVY=
|
||||
github.com/opencloud-eu/reva/v2 v2.28.1-0.20250319144557-ae6d4d54cb01 h1:XhxHB2APcLCFaYFP1AEXwPSld6aUyK4PgGkT+AvxVGI=
|
||||
github.com/opencloud-eu/reva/v2 v2.28.1-0.20250319144557-ae6d4d54cb01/go.mod h1:IWorhegiAG25pT0L3tbXeTqP70a8ALJNBOXa4t4QG14=
|
||||
github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320105919-be91238e6b11 h1:MjfgrhEs73BezOXQZUgEtNTZsmXDVixFpGzZljR5lrk=
|
||||
github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320105919-be91238e6b11/go.mod h1:iK0tNdLgqK0zBi0l7Q4uWSn9GPUbYtNxz3YAMfYvYNg=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||
@@ -1000,6 +1000,8 @@ github.com/sercand/kuberesolver/v5 v5.1.1 h1:CYH+d67G0sGBj7q5wLK61yzqJJ8gLLC8aep
|
||||
github.com/sercand/kuberesolver/v5 v5.1.1/go.mod h1:Fs1KbKhVRnB2aDWN12NjKCB+RgYMWZJ294T3BtmVCpQ=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sethvargo/go-diceware v0.5.0 h1:exrQ7GpaBo00GqRVM1N8ChXSsi3oS7tjQiIehsD+yR0=
|
||||
github.com/sethvargo/go-diceware v0.5.0/go.mod h1:Lg1SyPS7yQO6BBgTN5r4f2MUDkqGfLWsOjHPY0kA8iw=
|
||||
github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU=
|
||||
github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs=
|
||||
github.com/shamaton/msgpack/v2 v2.2.3 h1:uDOHmxQySlvlUYfQwdjxyybAOzjlQsD1Vjy+4jmO9NM=
|
||||
|
||||
15
vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md
generated
vendored
15
vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md
generated
vendored
@@ -1,3 +1,18 @@
|
||||
## 2.23.1
|
||||
|
||||
## 🚨 For users on MacOS 🚨
|
||||
|
||||
A long-standing Ginkgo performance issue on MacOS seems to be due to mac's antimalware XProtect. You can follow the instructions [here](https://onsi.github.io/ginkgo/#if-you-are-running-on-macos) to disable it in your terminal. Doing so sped up Ginkgo's own test suite from 1m8s to 47s.
|
||||
|
||||
### Fixes
|
||||
|
||||
Ginkgo's CLI is now a bit clearer if you pass flags in incorrectly:
|
||||
|
||||
- make it clearer that you need to pass a filename to the various profile flags, not an absolute directory [a0e52ff]
|
||||
- emit an error and exit if the ginkgo invocation includes flags after positional arguments [b799d8d]
|
||||
|
||||
This might cause existing CI builds to fail. If so then it's likely that your CI build was misconfigured and should be corrected. Open an issue if you need help.
|
||||
|
||||
## 2.23.0
|
||||
|
||||
Ginkgo 2.23.0 adds a handful of methods to `GinkgoT()` to make it compatible with the `testing.TB` interface in Go 1.24. `GinkgoT().Context()`, in particular, is a useful shorthand for generating a new context that will clean itself up in a `DeferCleanup()`. This has subtle behavior differences from the golang implementation but should make sense in a Ginkgo... um... context.
|
||||
|
||||
6
vendor/github.com/onsi/ginkgo/v2/ginkgo/command/command.go
generated
vendored
6
vendor/github.com/onsi/ginkgo/v2/ginkgo/command/command.go
generated
vendored
@@ -24,7 +24,11 @@ func (c Command) Run(args []string, additionalArgs []string) {
|
||||
if err != nil {
|
||||
AbortWithUsage(err.Error())
|
||||
}
|
||||
|
||||
for _, arg := range args {
|
||||
if strings.HasPrefix(arg, "-") {
|
||||
AbortWith("Malformed arguments - make sure all flags appear {{bold}}after{{/}} the Ginkgo subcommand and {{bold}}before{{/}} your list of packages.\n{{gray}}e.g. 'ginkgo run -p my_package' is valid `ginkgo -p run my_package` is not.{{/}}")
|
||||
}
|
||||
}
|
||||
c.Command(args, additionalArgs)
|
||||
}
|
||||
|
||||
|
||||
26
vendor/github.com/onsi/ginkgo/v2/types/config.go
generated
vendored
26
vendor/github.com/onsi/ginkgo/v2/types/config.go
generated
vendored
@@ -257,8 +257,12 @@ var FlagSections = GinkgoFlagSections{
|
||||
{Key: "filter", Style: "{{cyan}}", Heading: "Filtering Tests"},
|
||||
{Key: "failure", Style: "{{red}}", Heading: "Failure Handling"},
|
||||
{Key: "output", Style: "{{magenta}}", Heading: "Controlling Output Formatting"},
|
||||
{Key: "code-and-coverage-analysis", Style: "{{orange}}", Heading: "Code and Coverage Analysis"},
|
||||
{Key: "performance-analysis", Style: "{{coral}}", Heading: "Performance Analysis"},
|
||||
{Key: "code-and-coverage-analysis", Style: "{{orange}}", Heading: "Code and Coverage Analysis",
|
||||
Description: "When generating a cover files, please pass a filename {{bold}}not{{/}} a path. To specify a different directory use {{magenta}}--output-dir{{/}}.",
|
||||
},
|
||||
{Key: "performance-analysis", Style: "{{coral}}", Heading: "Performance Analysis",
|
||||
Description: "When generating profile files, please pass filenames {{bold}}not{{/}} a path. Ginkgo will generate a profile file with the given name in the package's directory. To specify a different directory use {{magenta}}--output-dir{{/}}.",
|
||||
},
|
||||
{Key: "debug", Style: "{{blue}}", Heading: "Debugging Tests",
|
||||
Description: "In addition to these flags, Ginkgo supports a few debugging environment variables. To change the parallel server protocol set {{blue}}GINKGO_PARALLEL_PROTOCOL{{/}} to {{bold}}HTTP{{/}}. To avoid pruning callstacks set {{blue}}GINKGO_PRUNE_STACK{{/}} to {{bold}}FALSE{{/}}."},
|
||||
{Key: "watch", Style: "{{light-yellow}}", Heading: "Controlling Ginkgo Watch"},
|
||||
@@ -572,7 +576,7 @@ var GoBuildFlags = GinkgoFlags{
|
||||
// GoRunFlags provides flags for the Ginkgo CLI run, and watch commands that capture go's run-time flags. These are passed to the compiled test binary by the ginkgo CLI
|
||||
var GoRunFlags = GinkgoFlags{
|
||||
{KeyPath: "Go.CoverProfile", Name: "coverprofile", UsageArgument: "file", SectionKey: "code-and-coverage-analysis",
|
||||
Usage: `Write a coverage profile to the file after all tests have passed. Sets -cover.`},
|
||||
Usage: `Write a coverage profile to the file after all tests have passed. Sets -cover. Must be passed a filename, not a path. Use output-dir to control the location of the output.`},
|
||||
{KeyPath: "Go.BlockProfile", Name: "blockprofile", UsageArgument: "file", SectionKey: "performance-analysis",
|
||||
Usage: `Write a goroutine blocking profile to the specified file when all tests are complete. Preserves test binary.`},
|
||||
{KeyPath: "Go.BlockProfileRate", Name: "blockprofilerate", UsageArgument: "rate", SectionKey: "performance-analysis",
|
||||
@@ -600,6 +604,22 @@ func VetAndInitializeCLIAndGoConfig(cliConfig CLIConfig, goFlagsConfig GoFlagsCo
|
||||
errors = append(errors, GinkgoErrors.BothRepeatAndUntilItFails())
|
||||
}
|
||||
|
||||
if strings.ContainsRune(goFlagsConfig.CoverProfile, os.PathSeparator) {
|
||||
errors = append(errors, GinkgoErrors.ExpectFilenameNotPath("--coverprofile", goFlagsConfig.CoverProfile))
|
||||
}
|
||||
if strings.ContainsRune(goFlagsConfig.CPUProfile, os.PathSeparator) {
|
||||
errors = append(errors, GinkgoErrors.ExpectFilenameNotPath("--cpuprofile", goFlagsConfig.CPUProfile))
|
||||
}
|
||||
if strings.ContainsRune(goFlagsConfig.MemProfile, os.PathSeparator) {
|
||||
errors = append(errors, GinkgoErrors.ExpectFilenameNotPath("--memprofile", goFlagsConfig.MemProfile))
|
||||
}
|
||||
if strings.ContainsRune(goFlagsConfig.BlockProfile, os.PathSeparator) {
|
||||
errors = append(errors, GinkgoErrors.ExpectFilenameNotPath("--blockprofile", goFlagsConfig.BlockProfile))
|
||||
}
|
||||
if strings.ContainsRune(goFlagsConfig.MutexProfile, os.PathSeparator) {
|
||||
errors = append(errors, GinkgoErrors.ExpectFilenameNotPath("--mutexprofile", goFlagsConfig.MutexProfile))
|
||||
}
|
||||
|
||||
//initialize the output directory
|
||||
if cliConfig.OutputDir != "" {
|
||||
err := os.MkdirAll(cliConfig.OutputDir, 0777)
|
||||
|
||||
7
vendor/github.com/onsi/ginkgo/v2/types/errors.go
generated
vendored
7
vendor/github.com/onsi/ginkgo/v2/types/errors.go
generated
vendored
@@ -629,6 +629,13 @@ func (g ginkgoErrors) BothRepeatAndUntilItFails() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (g ginkgoErrors) ExpectFilenameNotPath(flag string, path string) error {
|
||||
return GinkgoError{
|
||||
Heading: fmt.Sprintf("%s expects a filename but was given a path: %s", flag, path),
|
||||
Message: fmt.Sprintf("%s takes a filename, not a path. Use --output-dir to specify a directory to collect all test outputs.", flag),
|
||||
}
|
||||
}
|
||||
|
||||
/* Stack-Trace parsing errors */
|
||||
|
||||
func (g ginkgoErrors) FailedToParseStackTrace(message string) error {
|
||||
|
||||
2
vendor/github.com/onsi/ginkgo/v2/types/version.go
generated
vendored
2
vendor/github.com/onsi/ginkgo/v2/types/version.go
generated
vendored
@@ -1,3 +1,3 @@
|
||||
package types
|
||||
|
||||
const VERSION = "2.23.0"
|
||||
const VERSION = "2.23.1"
|
||||
|
||||
494
vendor/github.com/opencloud-eu/reva/v2/pkg/appauth/manager/jsoncs3/jsoncs3.go
generated
vendored
Normal file
494
vendor/github.com/opencloud-eu/reva/v2/pkg/appauth/manager/jsoncs3/jsoncs3.go
generated
vendored
Normal file
@@ -0,0 +1,494 @@
|
||||
package jsoncs3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/alexedwards/argon2id"
|
||||
apppb "github.com/cs3org/go-cs3apis/cs3/auth/applications/v1beta1"
|
||||
authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
|
||||
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
typespb "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
||||
"github.com/google/uuid"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/appauth"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/appauth/manager/registry"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/appctx"
|
||||
ctxpkg "github.com/opencloud-eu/reva/v2/pkg/ctx"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/storage/utils/metadata"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sethvargo/go-diceware/diceware"
|
||||
"github.com/sethvargo/go-password/password"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
)
|
||||
|
||||
type PasswordGenerator interface {
|
||||
GeneratePassword() (string, error)
|
||||
}
|
||||
|
||||
func init() {
|
||||
registry.Register("jsoncs3", New)
|
||||
}
|
||||
|
||||
type manager struct {
|
||||
sync.RWMutex // for lazy initialization
|
||||
mds metadata.Storage
|
||||
generator PasswordGenerator
|
||||
initialized bool
|
||||
}
|
||||
|
||||
type config struct {
|
||||
ProviderAddr string `mapstructure:"provider_addr"`
|
||||
ServiceUserID string `mapstructure:"service_user_id"`
|
||||
ServiceUserIdp string `mapstructure:"service_user_idp"`
|
||||
MachineAuthAPIKey string `mapstructure:"machine_auth_apikey"`
|
||||
Generator string `mapstructure:"password_generator"`
|
||||
GeneratorConfig map[string]any `mapstructure:"generator_config"`
|
||||
}
|
||||
|
||||
type updaterFunc func(map[string]*apppb.AppPassword) (map[string]*apppb.AppPassword, error)
|
||||
|
||||
const tracerName = "jsoncs3"
|
||||
|
||||
func New(m map[string]any) (appauth.Manager, error) {
|
||||
c := &config{}
|
||||
if err := mapstructure.Decode(m, c); err != nil {
|
||||
err = errors.Wrap(err, "error creating a new manager")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.ProviderAddr == "" {
|
||||
return nil, fmt.Errorf("appauth jsoncs3 manager: provider_addr not set")
|
||||
}
|
||||
|
||||
if c.ServiceUserID == "" {
|
||||
return nil, fmt.Errorf("appauth jsoncs3 manager: service_user_id not set")
|
||||
}
|
||||
|
||||
if c.ServiceUserIdp == "" {
|
||||
return nil, fmt.Errorf("appauth jsoncs3 manager: service_user_idp not set")
|
||||
}
|
||||
|
||||
if c.MachineAuthAPIKey == "" {
|
||||
return nil, fmt.Errorf("appauth jsoncs3 manager: machine_auth_apikey not set")
|
||||
}
|
||||
|
||||
if c.Generator == "" {
|
||||
c.Generator = "diceware"
|
||||
}
|
||||
|
||||
var pwgen PasswordGenerator
|
||||
var err error
|
||||
switch c.Generator {
|
||||
case "diceware":
|
||||
pwgen, err = NewDicewareGenerator(c.GeneratorConfig)
|
||||
case "random":
|
||||
pwgen, err = NewRandGenerator(c.GeneratorConfig)
|
||||
default:
|
||||
return nil, fmt.Errorf("appauth jsoncs3 manager: unknown generator: %s", c.Generator)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("appauth jsoncs3 manager: failed initialize password generator: %w", err)
|
||||
}
|
||||
|
||||
cs3, err := metadata.NewCS3Storage(c.ProviderAddr, c.ProviderAddr, c.ServiceUserID, c.ServiceUserIdp, c.MachineAuthAPIKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewWithOptions(cs3, pwgen)
|
||||
}
|
||||
|
||||
func NewWithOptions(mds metadata.Storage, generator PasswordGenerator) (*manager, error) {
|
||||
return &manager{
|
||||
mds: mds,
|
||||
generator: generator,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GenerateAppPassword creates a password with specified scope to be used by
|
||||
// third-party applications.
|
||||
func (m *manager) GenerateAppPassword(ctx context.Context, scope map[string]*authpb.Scope, label string, expiration *typespb.Timestamp) (*apppb.AppPassword, error) {
|
||||
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GenerateAppPassword")
|
||||
defer span.End()
|
||||
if err := m.initialize(ctx); err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
token, err := m.generator.GeneratePassword()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating new token")
|
||||
}
|
||||
|
||||
tokenHashed, err := argon2id.CreateHash(token, argon2id.DefaultParams)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating new token")
|
||||
}
|
||||
|
||||
var userID *userpb.UserId
|
||||
if user, ok := ctxpkg.ContextGetUser(ctx); ok {
|
||||
userID = user.GetId()
|
||||
} else {
|
||||
return nil, errtypes.BadRequest("no user in context")
|
||||
}
|
||||
|
||||
cTime := &typespb.Timestamp{Seconds: uint64(time.Now().Unix())}
|
||||
|
||||
// For persisting we use the hashed password, since we don't
|
||||
// want to store it in cleartext
|
||||
appPass := &apppb.AppPassword{
|
||||
Password: tokenHashed,
|
||||
TokenScope: scope,
|
||||
Label: label,
|
||||
Expiration: expiration,
|
||||
Ctime: cTime,
|
||||
Utime: cTime,
|
||||
User: userID,
|
||||
}
|
||||
|
||||
id := uuid.New().String()
|
||||
|
||||
err = m.updateWithRetry(ctx, 5, true, userID, func(a map[string]*apppb.AppPassword) (map[string]*apppb.AppPassword, error) {
|
||||
a[id] = appPass
|
||||
return a, nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Here we need to resplace the hash with the cleartext password again since
|
||||
// the requestor needs to know the cleartext value.
|
||||
appPass.Password = token
|
||||
|
||||
return appPass, nil
|
||||
}
|
||||
|
||||
// ListAppPasswords lists the application passwords created by a user.
|
||||
func (m *manager) ListAppPasswords(ctx context.Context) ([]*apppb.AppPassword, error) {
|
||||
log := appctx.GetLogger(ctx)
|
||||
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "ListAppPasswords")
|
||||
defer span.End()
|
||||
if err := m.initialize(ctx); err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
var userID *userpb.UserId
|
||||
if user, ok := ctxpkg.ContextGetUser(ctx); ok {
|
||||
userID = user.GetId()
|
||||
} else {
|
||||
return nil, errtypes.BadRequest("no user in context")
|
||||
}
|
||||
_, userAppPasswords, err := m.getUserAppPasswords(ctx, userID)
|
||||
if err != nil {
|
||||
if _, ok := err.(errtypes.NotFound); ok {
|
||||
return []*apppb.AppPassword{}, nil
|
||||
}
|
||||
log.Error().Err(err).Msg("getUserAppPasswords failed")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userAppPasswordSlice := make([]*apppb.AppPassword, 0, len(userAppPasswords))
|
||||
|
||||
for _, p := range userAppPasswords {
|
||||
userAppPasswordSlice = append(userAppPasswordSlice, p)
|
||||
}
|
||||
|
||||
return userAppPasswordSlice, nil
|
||||
}
|
||||
|
||||
// InvalidateAppPassword invalidates a generated password.
|
||||
func (m *manager) InvalidateAppPassword(ctx context.Context, secret string) error {
|
||||
log := appctx.GetLogger(ctx)
|
||||
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "InvalidateAppPassword")
|
||||
defer span.End()
|
||||
if err := m.initialize(ctx); err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
var userID *userpb.UserId
|
||||
if user, ok := ctxpkg.ContextGetUser(ctx); ok {
|
||||
userID = user.GetId()
|
||||
} else {
|
||||
return errtypes.BadRequest("no user in context")
|
||||
}
|
||||
|
||||
updater := func(a map[string]*apppb.AppPassword) (map[string]*apppb.AppPassword, error) {
|
||||
for key, pw := range a {
|
||||
ok, err := argon2id.ComparePasswordAndHash(secret, pw.Password)
|
||||
switch {
|
||||
case err != nil:
|
||||
log.Debug().Err(err).Msg("Error comparing password and hash")
|
||||
case ok:
|
||||
delete(a, key)
|
||||
return a, nil
|
||||
}
|
||||
}
|
||||
return a, errtypes.NotFound("password not found")
|
||||
}
|
||||
|
||||
err := m.updateWithRetry(ctx, 5, false, userID, updater)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("getUserAppPasswords failed")
|
||||
return errtypes.NotFound("password not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAppPassword retrieves the password information by the combination of username and password.
|
||||
func (m *manager) GetAppPassword(ctx context.Context, user *userpb.UserId, secret string) (*apppb.AppPassword, error) {
|
||||
log := appctx.GetLogger(ctx)
|
||||
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetAppPassword")
|
||||
defer span.End()
|
||||
if err := m.initialize(ctx); err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
errUpdateSkipped := errors.New("update skipped")
|
||||
|
||||
var matchedPw *apppb.AppPassword
|
||||
updater := func(a map[string]*apppb.AppPassword) (map[string]*apppb.AppPassword, error) {
|
||||
matchedPw = nil
|
||||
for id, pw := range a {
|
||||
ok, err := argon2id.ComparePasswordAndHash(secret, pw.Password)
|
||||
switch {
|
||||
case err != nil:
|
||||
log.Debug().Err(err).Msg("Error comparing password and hash")
|
||||
case ok:
|
||||
// password found
|
||||
if pw.Expiration != nil && pw.Expiration.Seconds != 0 && uint64(time.Now().Unix()) > pw.Expiration.Seconds {
|
||||
log.Debug().Str("AppPasswordId", id).Msg("password expired")
|
||||
return nil, errtypes.NotFound("password not found")
|
||||
}
|
||||
|
||||
matchedPw = pw
|
||||
// password not expired
|
||||
// Updating the Utime will cause an Upload for every single GetAppPassword request. We are limiting this to one
|
||||
// update per 5 minutes otherwise this backend will become unusable.
|
||||
if time.Since(utils.TSToTime(pw.Utime)) > 5*time.Minute {
|
||||
a[id].Utime = utils.TSNow()
|
||||
return a, nil
|
||||
}
|
||||
return a, errUpdateSkipped
|
||||
}
|
||||
}
|
||||
return nil, errtypes.NotFound("password not found")
|
||||
}
|
||||
|
||||
err := m.updateWithRetry(ctx, 5, false, user, updater)
|
||||
switch {
|
||||
case err == nil:
|
||||
fallthrough
|
||||
case errors.Is(err, errUpdateSkipped):
|
||||
return matchedPw, nil
|
||||
}
|
||||
|
||||
return nil, errtypes.NotFound("password not found")
|
||||
}
|
||||
|
||||
func (m *manager) initialize(ctx context.Context) error {
|
||||
_, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "initialize")
|
||||
defer span.End()
|
||||
if m.initialized {
|
||||
span.SetStatus(codes.Ok, "already initialized")
|
||||
return nil
|
||||
}
|
||||
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
if m.initialized { // check if initialization happened while grabbing the lock
|
||||
span.SetStatus(codes.Ok, "initialized while grabbing lock")
|
||||
return nil
|
||||
}
|
||||
|
||||
ctx = context.Background()
|
||||
err := m.mds.Init(ctx, "jsoncs3-appauth-data")
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
return err
|
||||
}
|
||||
m.initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *manager) updateWithRetry(ctx context.Context, retries int, createIfNotFound bool, userid *userpb.UserId, updater updaterFunc) error {
|
||||
_, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "initialize")
|
||||
defer span.End()
|
||||
|
||||
retry := true
|
||||
var (
|
||||
etag string
|
||||
userAppPasswords map[string]*apppb.AppPassword
|
||||
err error
|
||||
)
|
||||
|
||||
// retry for the specified number of times, then error out
|
||||
for i := 0; i < retries && retry; i++ {
|
||||
etag, userAppPasswords, err = m.getUserAppPasswords(ctx, userid)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
// empty
|
||||
case errtypes.NotFound:
|
||||
if createIfNotFound {
|
||||
userAppPasswords = map[string]*apppb.AppPassword{}
|
||||
} else {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, "downloading app tokens failed")
|
||||
return err
|
||||
}
|
||||
default:
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, "downloading app tokens failed")
|
||||
return err
|
||||
}
|
||||
|
||||
userAppPasswords, err = updater(userAppPasswords)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = m.updateUserAppPassword(ctx, userid, userAppPasswords, etag)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
retry = false
|
||||
case errtypes.PreconditionFailed:
|
||||
retry = true
|
||||
default:
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
return err
|
||||
}
|
||||
}
|
||||
if retry {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, "updating app tokens failed")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *manager) updateUserAppPassword(ctx context.Context, userid *userpb.UserId, appPasswords map[string]*apppb.AppPassword, ifMatchEtag string) error {
|
||||
log := appctx.GetLogger(ctx)
|
||||
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "getUserAppPasswords")
|
||||
jsonPath := userAppTokenJSONPath(userid)
|
||||
|
||||
pwBytes, err := json.Marshal(appPasswords)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
ur := metadata.UploadRequest{
|
||||
Path: jsonPath,
|
||||
Content: pwBytes,
|
||||
IfMatchEtag: ifMatchEtag,
|
||||
}
|
||||
|
||||
// If there is no etag, make sure to only upload if the file wasn't craeted yet
|
||||
if ifMatchEtag == "" {
|
||||
ur.IfNoneMatch = []string{"*"}
|
||||
}
|
||||
_, err = m.mds.Upload(ctx, ur)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
log.Debug().Err(err).Msg("persisting provider cache failed")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *manager) getUserAppPasswords(ctx context.Context, userid *userpb.UserId) (string, map[string]*apppb.AppPassword, error) {
|
||||
log := appctx.GetLogger(ctx)
|
||||
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "getUserAppPasswords")
|
||||
jsonPath := userAppTokenJSONPath(userid)
|
||||
dlreq := metadata.DownloadRequest{
|
||||
Path: jsonPath,
|
||||
}
|
||||
|
||||
var userAppPasswords = map[string]*apppb.AppPassword{}
|
||||
dlres, err := m.mds.Download(ctx, dlreq)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
err = json.Unmarshal(dlres.Content, &userAppPasswords)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("unmarshaling app tokens failed")
|
||||
return "", nil, err
|
||||
}
|
||||
case errtypes.NotFound:
|
||||
return "", nil, errtypes.NotFound("password not found")
|
||||
default:
|
||||
span.RecordError(err)
|
||||
span.SetStatus(codes.Error, "downloading app tokens failed")
|
||||
return "", nil, err
|
||||
}
|
||||
return dlres.Etag, userAppPasswords, nil
|
||||
}
|
||||
|
||||
func userAppTokenJSONPath(userID *userpb.UserId) string {
|
||||
return userID.GetOpaqueId() + ".json"
|
||||
}
|
||||
|
||||
type randomPassword struct {
|
||||
Strength int `mapstructure:"token_strength"`
|
||||
}
|
||||
|
||||
func NewRandGenerator(config map[string]any) (*randomPassword, error) {
|
||||
r := &randomPassword{}
|
||||
if err := mapstructure.Decode(config, r); err != nil {
|
||||
err = errors.Wrap(err, "error configuring password generator")
|
||||
return nil, err
|
||||
}
|
||||
if r.Strength <= 0 {
|
||||
r.Strength = 11
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r randomPassword) GeneratePassword() (string, error) {
|
||||
token, err := password.Generate(r.Strength, r.Strength/2, 0, false, false)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error creating new token")
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
type dicewarePassword struct {
|
||||
NumWords int `mapstructure:"number_of_words"`
|
||||
}
|
||||
|
||||
func NewDicewareGenerator(config map[string]any) (*dicewarePassword, error) {
|
||||
d := &dicewarePassword{}
|
||||
if err := mapstructure.Decode(config, d); err != nil {
|
||||
err = errors.Wrap(err, "error creating a new manager")
|
||||
return nil, err
|
||||
}
|
||||
if d.NumWords <= 0 {
|
||||
d.NumWords = 6
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (d dicewarePassword) GeneratePassword() (string, error) {
|
||||
token, err := diceware.Generate(d.NumWords)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error creating new token")
|
||||
}
|
||||
return strings.Join(token, " "), nil
|
||||
}
|
||||
1
vendor/github.com/opencloud-eu/reva/v2/pkg/appauth/manager/loader/loader.go
generated
vendored
1
vendor/github.com/opencloud-eu/reva/v2/pkg/appauth/manager/loader/loader.go
generated
vendored
@@ -21,5 +21,6 @@ package loader
|
||||
import (
|
||||
// Load core application auth manager drivers.
|
||||
_ "github.com/opencloud-eu/reva/v2/pkg/appauth/manager/json"
|
||||
_ "github.com/opencloud-eu/reva/v2/pkg/appauth/manager/jsoncs3"
|
||||
// Add your own here
|
||||
)
|
||||
|
||||
5
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/lookup/lookup.go
generated
vendored
5
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/lookup/lookup.go
generated
vendored
@@ -276,6 +276,11 @@ func (lu *Lookup) InternalRoot() string {
|
||||
return lu.Options.Root
|
||||
}
|
||||
|
||||
// InternalSpaceRoot returns the internal path for a space
|
||||
func (lu *Lookup) InternalSpaceRoot(spaceID string) string {
|
||||
return lu.InternalPath(spaceID, spaceID)
|
||||
}
|
||||
|
||||
// InternalPath returns the internal path for a given ID
|
||||
func (lu *Lookup) InternalPath(spaceID, nodeID string) string {
|
||||
if strings.Contains(nodeID, node.RevisionIDDelimiter) || strings.HasSuffix(nodeID, node.CurrentIDDelimiter) {
|
||||
|
||||
5
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/lookup/lookup.go
generated
vendored
5
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/lookup/lookup.go
generated
vendored
@@ -263,6 +263,11 @@ func (lu *Lookup) InternalRoot() string {
|
||||
return lu.Options.Root
|
||||
}
|
||||
|
||||
// InternalSpaceRoot returns the internal path for a space
|
||||
func (lu *Lookup) InternalSpaceRoot(spaceID string) string {
|
||||
return filepath.Join(lu.Options.Root, "spaces", Pathify(spaceID, 1, 2))
|
||||
}
|
||||
|
||||
// InternalPath returns the internal path for a given ID
|
||||
func (lu *Lookup) InternalPath(spaceID, nodeID string) string {
|
||||
return filepath.Join(lu.Options.Root, "spaces", Pathify(spaceID, 1, 2), "nodes", Pathify(nodeID, 4, 2))
|
||||
|
||||
1
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/node/node.go
generated
vendored
1
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/node/node.go
generated
vendored
@@ -156,6 +156,7 @@ type PathLookup interface {
|
||||
GenerateSpaceID(spaceType string, owner *userpb.User) (string, error)
|
||||
|
||||
InternalRoot() string
|
||||
InternalSpaceRoot(spaceID string) string
|
||||
InternalPath(spaceID, nodeID string) string
|
||||
VersionPath(spaceID, nodeID, version string) string
|
||||
Path(ctx context.Context, n *Node, hasPermission PermissionFunc) (path string, err error)
|
||||
|
||||
7
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/spaces.go
generated
vendored
7
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/spaces.go
generated
vendored
@@ -786,8 +786,11 @@ func (fs *Decomposedfs) DeleteStorageSpace(ctx context.Context, req *provider.De
|
||||
}
|
||||
|
||||
// remove space metadata
|
||||
if err := os.RemoveAll(root); err != nil {
|
||||
return err
|
||||
spaceRoot := fs.lu.InternalSpaceRoot(spaceID)
|
||||
if spaceRoot != "" {
|
||||
if err := os.RemoveAll(fs.lu.InternalSpaceRoot(spaceID)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// invalidate id in cache
|
||||
|
||||
25
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/tree/revisions.go
generated
vendored
25
vendor/github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/tree/revisions.go
generated
vendored
@@ -30,6 +30,7 @@ import (
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rogpeppe/go-internal/lockedfile"
|
||||
"github.com/shamaton/msgpack/v2"
|
||||
|
||||
"github.com/opencloud-eu/reva/v2/pkg/appctx"
|
||||
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
|
||||
@@ -62,7 +63,29 @@ func (tp *Tree) CreateRevision(ctx context.Context, n *node.Node, version string
|
||||
vf, err := os.OpenFile(versionPath, os.O_CREATE|os.O_EXCL, 0600)
|
||||
if err != nil {
|
||||
if os.IsExist(err) {
|
||||
err := os.Remove(versionPath)
|
||||
revisionNode := node.NewBaseNode(n.SpaceID, n.ID+node.RevisionIDDelimiter+version, tp.lookup)
|
||||
revisionPath := tp.lookup.MetadataBackend().MetadataPath(revisionNode)
|
||||
b, err := os.ReadFile(revisionPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
m := map[string][]byte{}
|
||||
if err := msgpack.Unmarshal(b, &m); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
bid := m["user.oc.blobid"]
|
||||
if string(bid) != "" {
|
||||
if err := tp.DeleteBlob(&node.Node{
|
||||
BaseNode: *revisionNode,
|
||||
BlobID: string(bid),
|
||||
}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
err = os.Remove(versionPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
20
vendor/github.com/sethvargo/go-diceware/LICENSE
generated
vendored
Normal file
20
vendor/github.com/sethvargo/go-diceware/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright 2017 Seth Vargo <seth@sethvargo.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
195
vendor/github.com/sethvargo/go-diceware/diceware/generate.go
generated
vendored
Normal file
195
vendor/github.com/sethvargo/go-diceware/diceware/generate.go
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
package diceware
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// sides is the number of sides on a die.
|
||||
var sides = big.NewInt(6)
|
||||
|
||||
var _ DicewareGenerator = (*Generator)(nil)
|
||||
|
||||
// Generator is the stateful generator which can be used to customize the word
|
||||
// list and other generation options.
|
||||
type Generator struct {
|
||||
wordList WordList
|
||||
randReader io.Reader
|
||||
}
|
||||
|
||||
// GeneratorInput is used as input to the NewGenerator function.
|
||||
type GeneratorInput struct {
|
||||
// WordList is the word list to use. There are built-in word lists like
|
||||
// WordListEffBig (default), WordListEffSmall, and WordListOriginal. You can
|
||||
// also bring your own word list by implementing the WordList interface.
|
||||
WordList WordList
|
||||
|
||||
// RandReader is an optional reader to use in place of the default
|
||||
// (crypto/rand.Reader), which can be used to generate repeatable sets of
|
||||
// words
|
||||
RandReader io.Reader
|
||||
}
|
||||
|
||||
// NewGenerator creates a new Generator from the specified configuration. If no
|
||||
// input is given, all the default values are used. This function is safe for
|
||||
// concurrent use.
|
||||
func NewGenerator(i *GeneratorInput) (*Generator, error) {
|
||||
if i == nil {
|
||||
i = new(GeneratorInput)
|
||||
}
|
||||
|
||||
if i.WordList == nil {
|
||||
i.WordList = WordListEffLarge()
|
||||
}
|
||||
|
||||
gen := &Generator{
|
||||
wordList: i.WordList,
|
||||
randReader: i.RandReader,
|
||||
}
|
||||
|
||||
if gen.randReader == nil {
|
||||
gen.randReader = rand.Reader
|
||||
}
|
||||
|
||||
return gen, nil
|
||||
}
|
||||
|
||||
// Generate generates a collection of diceware words, specified by the numWords
|
||||
// parameter.
|
||||
//
|
||||
// The algorithm is fast, but it's not designed to be performant, favoring
|
||||
// entropy over speed.
|
||||
//
|
||||
// This function is safe for concurrent use, but there is a possibility of
|
||||
// concurrent invocations generating overlapping words. To generate multiple
|
||||
// non-overlapping words, use a single invocation of the function and split the
|
||||
// resulting string list.
|
||||
func (g *Generator) Generate(numWords int) ([]string, error) {
|
||||
if typ, ok := g.wordList.(WordListNumWordser); ok {
|
||||
if l := typ.NumWords(); numWords > l {
|
||||
return nil, fmt.Errorf("number of requested words (%d) cannot exceed the size of the wordlist (%d)",
|
||||
numWords, l)
|
||||
}
|
||||
}
|
||||
|
||||
list := make([]string, 0, numWords)
|
||||
seen := make(map[string]struct{}, numWords)
|
||||
|
||||
for i := 0; i < numWords; i++ {
|
||||
n, err := g.RollWord(g.wordList.Digits())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
word := g.wordList.WordAt(n)
|
||||
if _, ok := seen[word]; ok {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
|
||||
list = append(list, word)
|
||||
seen[word] = struct{}{}
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// MustGenerate is the same as Generate, but panics on error.
|
||||
func (g *Generator) MustGenerate(numWords int) []string {
|
||||
list, err := g.Generate(numWords)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// Generate - see Generator.Generate for usage.
|
||||
func Generate(numWords int) ([]string, error) {
|
||||
gen, err := NewGenerator(nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gen.Generate(numWords)
|
||||
}
|
||||
|
||||
// MustGenerate - see Generator.MustGenerate for usage.
|
||||
func MustGenerate(numWords int) []string {
|
||||
gen, err := NewGenerator(nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return gen.MustGenerate(numWords)
|
||||
}
|
||||
|
||||
// GenerateWithWordList generates a list of the given number of words from the
|
||||
// given word list.
|
||||
func GenerateWithWordList(numWords int, wordList WordList) ([]string, error) {
|
||||
gen, err := NewGenerator(&GeneratorInput{
|
||||
WordList: wordList,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gen.Generate(numWords)
|
||||
}
|
||||
|
||||
// WordAt retrieves the word at the given index from EFF's large wordlist.
|
||||
//
|
||||
// Deprecated: Use WordList.WordAt instead.
|
||||
func WordAt(i int) string {
|
||||
return WordListEffLarge().WordAt(i)
|
||||
}
|
||||
|
||||
// RollDie rolls a single 6-sided die and returns a value between [1,6].
|
||||
//
|
||||
// Internally this creates a new Generator with a nil configuration and calls
|
||||
// Generator.RollDie.
|
||||
func RollDie() (int, error) {
|
||||
gen, err := NewGenerator(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return gen.RollDie()
|
||||
}
|
||||
|
||||
// RollWord rolls and aggregates dice to represent one word in the list. The
|
||||
// result is the index of the word in the list.
|
||||
//
|
||||
// Internally this creates a new Generator with a nil configuration and calls
|
||||
// Generator.RollWord.
|
||||
func RollWord(d int) (int, error) {
|
||||
gen, err := NewGenerator(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return gen.RollWord(d)
|
||||
}
|
||||
|
||||
// RollDie rolls a single 6-sided die and returns a value between [1,6].
|
||||
func (g *Generator) RollDie() (int, error) {
|
||||
r, err := rand.Int(g.randReader, sides)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to generate a random number: %w", err)
|
||||
}
|
||||
return int(r.Int64()) + 1, nil
|
||||
}
|
||||
|
||||
// RollWord rolls and aggregates dice to represent one word in the list. The
|
||||
// result is the index of the word in the list.
|
||||
func (g *Generator) RollWord(d int) (int, error) {
|
||||
var final int
|
||||
|
||||
for i := d; i > 0; i-- {
|
||||
res, err := g.RollDie()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
final += res * int(math.Pow(10, float64(i-1)))
|
||||
}
|
||||
|
||||
return final, nil
|
||||
}
|
||||
6
vendor/github.com/sethvargo/go-diceware/diceware/interface.go
generated
vendored
Normal file
6
vendor/github.com/sethvargo/go-diceware/diceware/interface.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
package diceware
|
||||
|
||||
type DicewareGenerator interface {
|
||||
Generate(int) ([]string, error)
|
||||
MustGenerate(int) []string
|
||||
}
|
||||
38
vendor/github.com/sethvargo/go-diceware/diceware/mock.go
generated
vendored
Normal file
38
vendor/github.com/sethvargo/go-diceware/diceware/mock.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
package diceware
|
||||
|
||||
var _ DicewareGenerator = (*mockGenerator)(nil)
|
||||
|
||||
type mockGenerator struct {
|
||||
result []string
|
||||
err error
|
||||
}
|
||||
|
||||
// NewMockGenerator creates a new generator that satisfies the DicewareGenerator
|
||||
// interface. If an error is provided, the error is returned. If a result if
|
||||
// provided, the result is always returned, regardless of what parameters are
|
||||
// passed into the Generate or MustGenerate methods.
|
||||
//
|
||||
// This function is most useful for tests where you want to have predicable
|
||||
// results for a transitive resource that depends on go-diceware.
|
||||
func NewMockGenerator(result []string, err error) *mockGenerator {
|
||||
return &mockGenerator{
|
||||
result: result,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
// Generate returns the mocked result or error.
|
||||
func (g *mockGenerator) Generate(int) ([]string, error) {
|
||||
if g.err != nil {
|
||||
return nil, g.err
|
||||
}
|
||||
return g.result, nil
|
||||
}
|
||||
|
||||
// MustGenerate returns the mocked result or panics if an error was given.
|
||||
func (g *mockGenerator) MustGenerate(int) []string {
|
||||
if g.err != nil {
|
||||
panic(g.err)
|
||||
}
|
||||
return g.result
|
||||
}
|
||||
42
vendor/github.com/sethvargo/go-diceware/diceware/word_list.go
generated
vendored
Normal file
42
vendor/github.com/sethvargo/go-diceware/diceware/word_list.go
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
package diceware
|
||||
|
||||
// WordList is an interface that must be implemented to be considered a word
|
||||
// list for use in the diceware algorithm. This interface can be implemented by
|
||||
// other libraries.
|
||||
type WordList interface {
|
||||
// Digits is the number of digits for indexes in the word list. This
|
||||
// determines the number of dice rolls.
|
||||
Digits() int
|
||||
|
||||
// WordAt returns the word at the given integer in the word list.
|
||||
WordAt(int) string
|
||||
}
|
||||
|
||||
// WordListNumWordser is an auxiliary interface that returns the number of words
|
||||
// in the list. This is a separate interface for backwards compatibility.
|
||||
type WordListNumWordser interface {
|
||||
// NumWords returns the total number of words in the list.
|
||||
NumWords() int
|
||||
}
|
||||
|
||||
var (
|
||||
_ WordList = (*wordListInternal)(nil)
|
||||
_ WordListNumWordser = (*wordListInternal)(nil)
|
||||
)
|
||||
|
||||
type wordListInternal struct {
|
||||
digits int
|
||||
words map[int]string
|
||||
}
|
||||
|
||||
func (w *wordListInternal) Digits() int {
|
||||
return w.digits
|
||||
}
|
||||
|
||||
func (w *wordListInternal) WordAt(i int) string {
|
||||
return w.words[i]
|
||||
}
|
||||
|
||||
func (w *wordListInternal) NumWords() int {
|
||||
return len(w.words)
|
||||
}
|
||||
7794
vendor/github.com/sethvargo/go-diceware/diceware/word_list_eff_large.go
generated
vendored
Normal file
7794
vendor/github.com/sethvargo/go-diceware/diceware/word_list_eff_large.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1314
vendor/github.com/sethvargo/go-diceware/diceware/word_list_eff_small.go
generated
vendored
Normal file
1314
vendor/github.com/sethvargo/go-diceware/diceware/word_list_eff_small.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
7789
vendor/github.com/sethvargo/go-diceware/diceware/word_list_original.go
generated
vendored
Normal file
7789
vendor/github.com/sethvargo/go-diceware/diceware/word_list_original.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
vendor/modules.txt
vendored
8
vendor/modules.txt
vendored
@@ -1057,7 +1057,7 @@ github.com/onsi/ginkgo/reporters/stenographer
|
||||
github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable
|
||||
github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty
|
||||
github.com/onsi/ginkgo/types
|
||||
# github.com/onsi/ginkgo/v2 v2.23.0
|
||||
# github.com/onsi/ginkgo/v2 v2.23.1
|
||||
## explicit; go 1.23.0
|
||||
github.com/onsi/ginkgo/v2
|
||||
github.com/onsi/ginkgo/v2/config
|
||||
@@ -1191,7 +1191,7 @@ github.com/open-policy-agent/opa/v1/types
|
||||
github.com/open-policy-agent/opa/v1/util
|
||||
github.com/open-policy-agent/opa/v1/util/decoding
|
||||
github.com/open-policy-agent/opa/v1/version
|
||||
# github.com/opencloud-eu/reva/v2 v2.28.1-0.20250319144557-ae6d4d54cb01
|
||||
# github.com/opencloud-eu/reva/v2 v2.28.1-0.20250320105919-be91238e6b11
|
||||
## explicit; go 1.24.1
|
||||
github.com/opencloud-eu/reva/v2/cmd/revad/internal/grace
|
||||
github.com/opencloud-eu/reva/v2/cmd/revad/runtime
|
||||
@@ -1295,6 +1295,7 @@ github.com/opencloud-eu/reva/v2/pkg/app/registry/registry
|
||||
github.com/opencloud-eu/reva/v2/pkg/app/registry/static
|
||||
github.com/opencloud-eu/reva/v2/pkg/appauth
|
||||
github.com/opencloud-eu/reva/v2/pkg/appauth/manager/json
|
||||
github.com/opencloud-eu/reva/v2/pkg/appauth/manager/jsoncs3
|
||||
github.com/opencloud-eu/reva/v2/pkg/appauth/manager/loader
|
||||
github.com/opencloud-eu/reva/v2/pkg/appauth/manager/registry
|
||||
github.com/opencloud-eu/reva/v2/pkg/appctx
|
||||
@@ -1763,6 +1764,9 @@ github.com/sercand/kuberesolver/v5
|
||||
# github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
|
||||
## explicit; go 1.13
|
||||
github.com/sergi/go-diff/diffmatchpatch
|
||||
# github.com/sethvargo/go-diceware v0.5.0
|
||||
## explicit; go 1.22
|
||||
github.com/sethvargo/go-diceware/diceware
|
||||
# github.com/sethvargo/go-password v0.3.1
|
||||
## explicit; go 1.21
|
||||
github.com/sethvargo/go-password/password
|
||||
|
||||
Reference in New Issue
Block a user