From 233c009a90d2fb47aadf6678248775a97fc3941a Mon Sep 17 00:00:00 2001 From: zepatrik Date: Mon, 22 Nov 2021 18:01:24 +0100 Subject: [PATCH 1/4] fix: de-duplicate message IDs --- Makefile | 6 +- cmd/clidoc/main.go | 77 ++++++++++++-- docs/docs/concepts/ui-user-interface.mdx | 46 ++++----- text/id.go | 124 +++++++++++++++++++++++ text/message_login.go | 24 ----- text/message_node.go | 11 -- text/message_recovery.go | 15 --- text/message_registration.go | 12 --- text/message_settings.go | 25 ----- text/message_validation.go | 18 ---- text/message_verification.go | 15 --- 11 files changed, 217 insertions(+), 156 deletions(-) diff --git a/Makefile b/Makefile index f3f1aa63d169..ea766689fe62 100644 --- a/Makefile +++ b/Makefile @@ -28,11 +28,9 @@ endef $(foreach dep, $(GO_DEPENDENCIES), $(eval $(call make-go-dependency, $(dep)))) $(call make-lint-dependency) -.bin/clidoc: - go build -o .bin/clidoc ./cmd/clidoc/. - +.PHONY: docs/cli docs/cli: .bin/clidoc - clidoc . + go run ./cmd/clidoc/. . .bin/ory: Makefile bash <(curl https://raw.githubusercontent.com/ory/meta/master/install.sh) -d -b .bin ory v0.1.0 diff --git a/cmd/clidoc/main.go b/cmd/clidoc/main.go index f2734f696650..6d0c57e8e0d0 100644 --- a/cmd/clidoc/main.go +++ b/cmd/clidoc/main.go @@ -5,8 +5,10 @@ import ( "encoding/json" "fmt" "go/ast" + "go/importer" "go/parser" "go/token" + "go/types" "os" "path/filepath" "regexp" @@ -123,12 +125,12 @@ func main() { } if err := validateAllMessages(filepath.Join(os.Args[1], "text")); err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Unable to validate messages: %+v", err) + _, _ = fmt.Fprintf(os.Stderr, "Unable to validate messages: %+v\n", err) os.Exit(1) } if err := writeMessages(filepath.Join(os.Args[1], "docs/docs/concepts/ui-user-interface.mdx")); err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Unable to generate message table: %+v", err) + _, _ = fmt.Fprintf(os.Stderr, "Unable to generate message table: %+v\n", err) os.Exit(1) } @@ -192,19 +194,63 @@ func writeMessages(path string) error { } func validateAllMessages(path string) error { + type message struct { + ID, Name string + } + + usedIDs := make([]message, 0, len(messages)) set := token.NewFileSet() packs, err := parser.ParseDir(set, path, nil, 0) if err != nil { return errors.Wrapf(err, "unable to parse text directory") } + info := &types.Info{ + Defs: make(map[*ast.Ident]types.Object), + } + var pack *ast.Package + for _, p := range packs { + if p.Name == "text" { + pack = p + break + } + } + allFiles := make([]*ast.File, 0) + for fn, f := range pack.Files { + if strings.HasSuffix(fn, "/id.go") { + allFiles = append(allFiles, f) + } + } + _, err = (&types.Config{Importer: importer.Default()}).Check("text", set, allFiles, info) + if err != nil { + return err // type error + } - for _, pack := range packs { - for _, f := range pack.Files { - for _, d := range f.Decls { - if fn, isFn := d.(*ast.FuncDecl); isFn { - if name := fn.Name.String(); fn.Name.IsExported() && strings.HasPrefix(name, "New") { - if _, ok := messages[name]; !ok { - return errors.Errorf("expected to find message %s in the list for the documentation generation but could not", name) + for _, f := range pack.Files { + for _, d := range f.Decls { + switch decl := d.(type) { + case *ast.FuncDecl: + if name := decl.Name.String(); decl.Name.IsExported() && strings.HasPrefix(name, "New") { + if _, ok := messages[name]; !ok { + return errors.Errorf("expected to find message %s in the list for the documentation generation but could not", name) + } + } + case *ast.GenDecl: + if decl.Tok == token.CONST { + for _, spec := range decl.Specs { + value := spec.(*ast.ValueSpec) // safe because decl.Tok is token.CONST + if t, ok := value.Type.(*ast.Ident); ok { + if t.Name == "ID" { + for _, name := range value.Names { + c := info.ObjectOf(name) + if c == nil { + return errors.Errorf("expected to find const %s in text/id.go", name.Name) + } + usedIDs = append(usedIDs, message{ + ID: c.(*types.Const).Val().ExactString(), + Name: name.Name, + }) + } + } } } } @@ -212,5 +258,18 @@ func validateAllMessages(path string) error { } } + sort.Slice(usedIDs, func(i, j int) bool { + return usedIDs[i].ID < usedIDs[j].ID + }) + for i := 1; i < len(usedIDs); i++ { + if usedIDs[i].ID == usedIDs[i-1].ID { + return errors.Errorf("message ID %s is used more than once: %s %s", usedIDs[i].ID, usedIDs[i].Name, usedIDs[i-1].Name) + } + } + return nil } + +type importerFunc func(path string) (*types.Package, error) + +func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) } diff --git a/docs/docs/concepts/ui-user-interface.mdx b/docs/docs/concepts/ui-user-interface.mdx index c25e25a2397a..bed6e5c0642b 100644 --- a/docs/docs/concepts/ui-user-interface.mdx +++ b/docs/docs/concepts/ui-user-interface.mdx @@ -1423,17 +1423,6 @@ will be overwritten! } ``` -###### An email containing a verification link has been sent to the email address you provided. (1070001) - -```json -{ - "id": 1070001, - "text": "An email containing a verification link has been sent to the email address you provided.", - "type": "info", - "context": {} -} -``` - ###### Password (1070001) ```json @@ -1444,16 +1433,6 @@ will be overwritten! } ``` -###### You successfully verified your email address. (1070002) - -```json -{ - "id": 1070002, - "text": "You successfully verified your email address.", - "type": "info" -} -``` - ###### {title} (1070002) ```json @@ -1514,6 +1493,27 @@ will be overwritten! } ``` +###### An email containing a verification link has been sent to the email address you provided. (1080001) + +```json +{ + "id": 1080001, + "text": "An email containing a verification link has been sent to the email address you provided.", + "type": "info", + "context": {} +} +``` + +###### You successfully verified your email address. (1080002) + +```json +{ + "id": 1080002, + "text": "You successfully verified your email address.", + "type": "info" +} +``` + ###### {reason} (4000001) ```json @@ -1545,8 +1545,8 @@ will be overwritten! "text": "Length must be \u003e= 1, but got 2.", "type": "error", "context": { - "actual_length": 2, - "expected_length": 1 + "expected_length": 1, + "actual_length": 2 } } ``` diff --git a/text/id.go b/text/id.go index 465252d6b1e3..c58a64f662d0 100644 --- a/text/id.go +++ b/text/id.go @@ -1,7 +1,24 @@ package text +// This file MUST not have any imports to modules that are not in the standard library. +// Otherwise, `make docs/cli` will fail. + type ID int +const ( + InfoSelfServiceLoginRoot ID = 1010000 + iota // 1010000 + InfoSelfServiceLogin // 1010001 + InfoSelfServiceLoginWith // 1010002 + InfoSelfServiceLoginReAuth // 1010003 + InfoSelfServiceLoginMFA // 1010004 + InfoSelfServiceLoginVerify // 1010005 + InfoSelfServiceLoginTOTPLabel // 1010006 + InfoLoginLookupLabel // 1010007 + InfoSelfServiceLoginWebAuthn // 1010008 + InfoLoginTOTP // 1010009 + InfoLoginLookup // 1010010 +) + const ( InfoSelfServiceLogout ID = 1020000 + iota ) @@ -10,6 +27,113 @@ const ( InfoSelfServiceMFA ID = 1030000 + iota ) +const ( + InfoSelfServiceRegistrationRoot ID = 1040000 + iota // 1040000 + InfoSelfServiceRegistration // 1040001 + InfoSelfServiceRegistrationWith // 1040002 + InfoRegistrationContinue // 1040003 +) + +const ( + InfoSelfServiceSettings ID = 1050000 + iota + InfoSelfServiceSettingsUpdateSuccess + InfoSelfServiceSettingsUpdateLinkOidc + InfoSelfServiceSettingsUpdateUnlinkOidc + InfoSelfServiceSettingsUpdateUnlinkTOTP + InfoSelfServiceSettingsTOTPQRCode + InfoSelfServiceSettingsTOTPSecret + InfoSelfServiceSettingsRevealLookup + InfoSelfServiceSettingsRegenerateLookup + InfoSelfServiceSettingsLookupSecret + InfoSelfServiceSettingsLookupSecretLabel + InfoSelfServiceSettingsLookupConfirm + InfoSelfServiceSettingsRegisterWebAuthn + InfoSelfServiceSettingsRegisterWebAuthnDisplayName + InfoSelfServiceSettingsLookupSecretUsed + InfoSelfServiceSettingsLookupSecretList + InfoSelfServiceSettingsDisableLookup + InfoSelfServiceSettingsTOTPSecretLabel +) + +const ( + InfoSelfServiceRecovery ID = 1060000 + iota // 1060000 + InfoSelfServiceRecoverySuccessful // 1060001 + InfoSelfServiceRecoveryEmailSent // 1060002 +) + +const ( + InfoNodeLabel ID = 1070000 + iota // 1070000 + InfoNodeLabelInputPassword // 1070001 + InfoNodeLabelGenerated // 1070002 + InfoNodeLabelSave // 1070003 + InfoNodeLabelID // 1070004 + InfoNodeLabelSubmit // 1070005 + InfoNodeLabelVerifyOTP // 1070006 + InfoNodeLabelEmail // 1070007 +) + +const ( + InfoSelfServiceVerification ID = 1080000 + iota // 1070000 + InfoSelfServiceVerificationEmailSent // 1070001 + InfoSelfServiceVerificationSuccessful // 1070002 +) + +const ( + ErrorValidation ID = 4000000 + iota + ErrorValidationGeneric + ErrorValidationRequired + ErrorValidationMinLength + ErrorValidationInvalidFormat + ErrorValidationPasswordPolicyViolation + ErrorValidationInvalidCredentials + ErrorValidationDuplicateCredentials + ErrorValidationTOTPVerifierWrong + ErrorValidationIdentifierMissing + ErrorValidationAddressNotVerified + ErrorValidationNoTOTPDevice + ErrorValidationLookupAlreadyUsed + ErrorValidationNoWebAuthnDevice + ErrorValidationNoLookup +) + +const ( + ErrorValidationLogin ID = 4010000 + iota // 4010000 + ErrorValidationLoginFlowExpired // 4010001 + ErrorValidationLoginNoStrategyFound // 4010002 + ErrorValidationRegistrationNoStrategyFound // 4010003 + ErrorValidationSettingsNoStrategyFound // 4010004 + ErrorValidationRecoveryNoStrategyFound // 4010005 + ErrorValidationVerificationNoStrategyFound // 4010006 +) + +const ( + ErrorValidationRegistration ID = 4040000 + iota + ErrorValidationRegistrationFlowExpired +) + +const ( + ErrorValidationSettings ID = 4050000 + iota + ErrorValidationSettingsFlowExpired +) + +const ( + ErrorValidationRecovery ID = 4060000 + iota // 4060000 + ErrorValidationRecoveryRetrySuccess // 4060001 + ErrorValidationRecoveryStateFailure // 4060002 + ErrorValidationRecoveryMissingRecoveryToken // 4060003 + ErrorValidationRecoveryTokenInvalidOrAlreadyUsed // 4060004 + ErrorValidationRecoveryFlowExpired // 4060005 +) + +const ( + ErrorValidationVerification ID = 4070000 + iota // 4070000 + ErrorValidationVerificationTokenInvalidOrAlreadyUsed // 4070001 + ErrorValidationVerificationRetrySuccess // 4070002 + ErrorValidationVerificationStateFailure // 4070003 + ErrorValidationVerificationMissingVerificationToken // 4070004 + ErrorValidationVerificationFlowExpired // 4070005 +) + const ( ErrorSystem ID = 5000000 + iota ErrorSystemGeneric diff --git a/text/message_login.go b/text/message_login.go index 05d04196476d..1beab9956331 100644 --- a/text/message_login.go +++ b/text/message_login.go @@ -5,30 +5,6 @@ import ( "time" ) -const ( - InfoSelfServiceLoginRoot ID = 1010000 + iota // 1010000 - InfoSelfServiceLogin // 1010001 - InfoSelfServiceLoginWith // 1010002 - InfoSelfServiceLoginReAuth // 1010003 - InfoSelfServiceLoginMFA // 1010004 - InfoSelfServiceLoginVerify // 1010005 - InfoSelfServiceLoginTOTPLabel // 1010006 - InfoLoginLookupLabel // 1010007 - InfoSelfServiceLoginWebAuthn // 1010008 - InfoLoginTOTP // 1010009 - InfoLoginLookup // 1010010 -) - -const ( - ErrorValidationLogin ID = 4010000 + iota // 4010000 - ErrorValidationLoginFlowExpired // 4010001 - ErrorValidationLoginNoStrategyFound // 4010002 - ErrorValidationRegistrationNoStrategyFound // 4010003 - ErrorValidationSettingsNoStrategyFound // 4010004 - ErrorValidationRecoveryNoStrategyFound // 4010005 - ErrorValidationVerificationNoStrategyFound // 4010006 -) - func NewInfoLoginReAuth() *Message { return &Message{ ID: InfoSelfServiceLoginReAuth, diff --git a/text/message_node.go b/text/message_node.go index 8b40178d7628..73083931913b 100644 --- a/text/message_node.go +++ b/text/message_node.go @@ -1,16 +1,5 @@ package text -const ( - InfoNodeLabel ID = 1070000 + iota // 1070000 - InfoNodeLabelInputPassword // 1070001 - InfoNodeLabelGenerated // 1070002 - InfoNodeLabelSave // 1070003 - InfoNodeLabelID // 1070004 - InfoNodeLabelSubmit // 1070005 - InfoNodeLabelVerifyOTP // 1070006 - InfoNodeLabelEmail // 1070007 -) - func NewInfoNodeLabelVerifyOTP() *Message { return &Message{ ID: InfoNodeLabelVerifyOTP, diff --git a/text/message_recovery.go b/text/message_recovery.go index 93f5a6c9d5b7..ae13cbef9472 100644 --- a/text/message_recovery.go +++ b/text/message_recovery.go @@ -5,21 +5,6 @@ import ( "time" ) -const ( - InfoSelfServiceRecovery ID = 1060000 + iota // 1060000 - InfoSelfServiceRecoverySuccessful // 1060001 - InfoSelfServiceRecoveryEmailSent // 1060002 -) - -const ( - ErrorValidationRecovery ID = 4060000 + iota // 4060000 - ErrorValidationRecoveryRetrySuccess // 4060001 - ErrorValidationRecoveryStateFailure // 4060002 - ErrorValidationRecoveryMissingRecoveryToken // 4060003 - ErrorValidationRecoveryTokenInvalidOrAlreadyUsed // 4060004 - ErrorValidationRecoveryFlowExpired // 4060005 -) - func NewErrorValidationRecoveryFlowExpired(ago time.Duration) *Message { return &Message{ ID: ErrorValidationRecoveryFlowExpired, diff --git a/text/message_registration.go b/text/message_registration.go index 276d9daaeb49..f5069ba5f316 100644 --- a/text/message_registration.go +++ b/text/message_registration.go @@ -5,18 +5,6 @@ import ( "time" ) -const ( - InfoSelfServiceRegistrationRoot ID = 1040000 + iota // 1040000 - InfoSelfServiceRegistration // 1040001 - InfoSelfServiceRegistrationWith // 1040002 - InfoRegistrationContinue // 1040003 -) - -const ( - ErrorValidationRegistration ID = 4040000 + iota - ErrorValidationRegistrationFlowExpired -) - func NewInfoRegistration() *Message { return &Message{ ID: InfoSelfServiceRegistration, diff --git a/text/message_settings.go b/text/message_settings.go index 17cd1b754d66..5cbd01a092a3 100644 --- a/text/message_settings.go +++ b/text/message_settings.go @@ -6,31 +6,6 @@ import ( "time" ) -const ( - InfoSelfServiceSettings ID = 1050000 + iota - InfoSelfServiceSettingsUpdateSuccess - InfoSelfServiceSettingsUpdateLinkOidc - InfoSelfServiceSettingsUpdateUnlinkOidc - InfoSelfServiceSettingsUpdateUnlinkTOTP - InfoSelfServiceSettingsTOTPQRCode - InfoSelfServiceSettingsTOTPSecret - InfoSelfServiceSettingsRevealLookup - InfoSelfServiceSettingsRegenerateLookup - InfoSelfServiceSettingsLookupSecret - InfoSelfServiceSettingsLookupSecretLabel - InfoSelfServiceSettingsLookupConfirm - InfoSelfServiceSettingsRegisterWebAuthn - InfoSelfServiceSettingsRegisterWebAuthnDisplayName - InfoSelfServiceSettingsLookupSecretUsed - InfoSelfServiceSettingsLookupSecretList - InfoSelfServiceSettingsDisableLookup -) - -const ( - ErrorValidationSettings ID = 4050000 + iota - ErrorValidationSettingsFlowExpired -) - func NewErrorValidationSettingsFlowExpired(ago time.Duration) *Message { return &Message{ ID: ErrorValidationSettingsFlowExpired, diff --git a/text/message_validation.go b/text/message_validation.go index 4d4a04a7c06c..b98abc8ec366 100644 --- a/text/message_validation.go +++ b/text/message_validation.go @@ -4,24 +4,6 @@ import ( "fmt" ) -const ( - ErrorValidation ID = 4000000 + iota - ErrorValidationGeneric - ErrorValidationRequired - ErrorValidationMinLength - ErrorValidationInvalidFormat - ErrorValidationPasswordPolicyViolation - ErrorValidationInvalidCredentials - ErrorValidationDuplicateCredentials - ErrorValidationTOTPVerifierWrong - ErrorValidationIdentifierMissing - ErrorValidationAddressNotVerified - ErrorValidationNoTOTPDevice - ErrorValidationLookupAlreadyUsed - ErrorValidationNoWebAuthnDevice - ErrorValidationNoLookup -) - func NewValidationErrorGeneric(reason string) *Message { return &Message{ ID: ErrorValidationGeneric, diff --git a/text/message_verification.go b/text/message_verification.go index db544edd8048..2e7a1b54f498 100644 --- a/text/message_verification.go +++ b/text/message_verification.go @@ -5,21 +5,6 @@ import ( "time" ) -const ( - InfoSelfServiceVerification ID = 1070000 + iota // 1070000 - InfoSelfServiceVerificationEmailSent // 1070001 - InfoSelfServiceVerificationSuccessful // 1070002 -) - -const ( - ErrorValidationVerification ID = 4070000 + iota // 4070000 - ErrorValidationVerificationTokenInvalidOrAlreadyUsed // 4070001 - ErrorValidationVerificationRetrySuccess // 4070002 - ErrorValidationVerificationStateFailure // 4070003 - ErrorValidationVerificationMissingVerificationToken // 4070004 - ErrorValidationVerificationFlowExpired // 4070005 -) - func NewErrorValidationVerificationFlowExpired(ago time.Duration) *Message { return &Message{ ID: ErrorValidationVerificationFlowExpired, From c1fdb30e54b26fefc7ad0753bab55440e7f6b73a Mon Sep 17 00:00:00 2001 From: zepatrik Date: Mon, 22 Nov 2021 18:03:01 +0100 Subject: [PATCH 2/4] fix: make dep --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ea766689fe62..2de6ed1f40f6 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ $(foreach dep, $(GO_DEPENDENCIES), $(eval $(call make-go-dependency, $(dep)))) $(call make-lint-dependency) .PHONY: docs/cli -docs/cli: .bin/clidoc +docs/cli: go run ./cmd/clidoc/. . .bin/ory: Makefile From 2237a40be92cf0a0225386f4434c00725ac15a3b Mon Sep 17 00:00:00 2001 From: zepatrik Date: Mon, 22 Nov 2021 18:09:23 +0100 Subject: [PATCH 3/4] ci: fix make error --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 2de6ed1f40f6..20dcaea2314a 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,10 @@ endef $(foreach dep, $(GO_DEPENDENCIES), $(eval $(call make-go-dependency, $(dep)))) $(call make-lint-dependency) +.bin/clidoc: + echo "deprecated usage, use docs/cli instead" + go build -o .bin/clidoc ./cmd/clidoc/. + .PHONY: docs/cli docs/cli: go run ./cmd/clidoc/. . From cf8699f931966239df931519e03865f2ac8b6c2a Mon Sep 17 00:00:00 2001 From: aeneasr <3372410+aeneasr@users.noreply.github.com> Date: Mon, 22 Nov 2021 20:32:35 +0000 Subject: [PATCH 4/4] autogen(docs): generate cli docs --- docs/docs/concepts/ui-user-interface.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/concepts/ui-user-interface.mdx b/docs/docs/concepts/ui-user-interface.mdx index 5f201418e1b4..d016069fbbe3 100644 --- a/docs/docs/concepts/ui-user-interface.mdx +++ b/docs/docs/concepts/ui-user-interface.mdx @@ -1545,8 +1545,8 @@ will be overwritten! "text": "Length must be \u003e= 1, but got 2.", "type": "error", "context": { - "expected_length": 1, - "actual_length": 2 + "actual_length": 2, + "expected_length": 1 } } ```