diff --git a/docs/config-template.yaml b/docs/config-template.yaml index 9e73a3e..af6c615 100644 --- a/docs/config-template.yaml +++ b/docs/config-template.yaml @@ -60,12 +60,12 @@ go_live: # optional, only useful if you also set early_reg_role, should be earlier than start_iso_datetime early_reg_start_iso_datetime: '' dues: - earliest_due_date: '2023-01-01' - latest_due_date: '2023-09-23' + earliest_due_date: '2024-01-01' + latest_due_date: '2024-09-21' due_days: 14 # calendar days birthday: earliest: '1901-01-01' - latest: '2004-08-24' + latest: '2006-09-18' additional_info_areas: # the key is the "area" parameter in the API url (/attendees/{id}/additional-info/{area}). # Key must be [a-z]+. The key "overdue" is reserved for internal use and thus not allowed here. @@ -90,11 +90,13 @@ choices: description: 'Legal Name is Confidential' digi-book: description: 'Digital only convention booklet' - visible_for: regdesk + visible_for: + - regdesk ev: description: 'Eurofurence e.V. Member' admin_only: true - visible_for: regdesk + visible_for: + - regdesk terms-accepted: description: 'Accepted the terms' default: true @@ -102,18 +104,27 @@ choices: guest: description: 'Guest of the Convention' admin_only: true - visible_for: self,regdesk,sponsordesk + visible_for: + - self + - regdesk + - sponsordesk skip_ban_check: description: 'Bypass ban check for this attendee' admin_only: true staff: description: 'Staff' admin_only: true - visible_for: self,regdesk,sponsordesk + visible_for: + - self + - regdesk + - sponsordesk director: description: 'Director' admin_only: true - visible_for: self,regdesk,sponsordesk + visible_for: + - self + - regdesk + - sponsordesk packages: room-none: description: 'No Room' @@ -126,64 +137,90 @@ choices: vat_percent: 19 default: true at-least-one-mandatory: true - visible_for: regdesk + visible_for: + - regdesk + early: + description: 'Early Bird Discount' + price: -500 + vat_percent: 19 + visible_for: + - regdesk + default: true + read_only: true + door: + description: 'At The Door Fee' + price: 1000 + vat_percent: 19 + visible_for: + - regdesk + read_only: true stage: description: 'Entrance Fee (Stage Ticket)' price: 500 vat_percent: 19 default: true - visible_for: regdesk + visible_for: + - regdesk sponsor: description: 'Sponsor Upgrade' price: 8000 vat_percent: 19 - visible_for: regdesk,sponsordesk + visible_for: + - regdesk + - sponsordesk sponsor2: description: 'Supersponsor Upgrade' price: 19000 vat_percent: 19 constraint: '!sponsor' constraint_msg: 'Please choose only one of Sponsor or Supersponsor.' - visible_for: regdesk,sponsordesk + visible_for: + - regdesk + - sponsordesk tshirt: description: 'Paid T-Shirt (non-sponsor)' price: 2000 vat_percent: 19 constraint: '!sponsor,!sponsor2' constraint_msg: 'Sponsors and supersponsors get their T-Shirt for free.' - visible_for: sponsordesk - day-sun: - description: 'Day Guest (Sunday)' + visible_for: + - sponsordesk + day-wed: + description: 'Day Guest (Wednesday)' price: 7000 vat_percent: 19 at-least-one-mandatory: true constraint: '!attendance,!stage' constraint_msg: 'Must disable Convention Ticket and Stage Ticket for Day Guests.' - visible_for: regdesk - day-mon: - description: 'Day Guest (Monday)' + visible_for: + - regdesk + day-thu: + description: 'Day Guest (Thursday)' price: 7000 vat_percent: 19 at-least-one-mandatory: true constraint: '!attendance,!stage' constraint_msg: 'Must disable Convention Ticket and Stage Ticket for Day Guests.' - visible_for: regdesk - day-tue: - description: 'Day Guest (Tuesday)' + visible_for: + - regdesk + day-fri: + description: 'Day Guest (Friday)' price: 7000 vat_percent: 19 at-least-one-mandatory: true constraint: '!attendance,!stage' constraint_msg: 'Must disable Convention Ticket and Stage Ticket for Day Guests.' - visible_for: regdesk - day-wed: - description: 'Day Guest (Wednesday)' + visible_for: + - regdesk + day-sat: + description: 'Day Guest (Saturday)' price: 7000 vat_percent: 19 at-least-one-mandatory: true constraint: '!attendance,!stage' constraint_msg: 'Must disable Convention Ticket and Stage Ticket for Day Guests.' - visible_for: regdesk + visible_for: + - regdesk dealer-half: description: 'Dealer Table Fee (Half)' price: 5000 @@ -227,16 +264,86 @@ choices: price: 10000 vat_percent: 19 read_only: true - artshow-table: - description: 'Artshow Tablespace' + artshow-table-half: + description: 'Artshow (Half Table)' price: 500 vat_percent: 19 read_only: true - artshow-panel: - description: 'Artshow Panelspace' + artshow-table-one: + description: 'Artshow (1 Table)' + price: 1000 + vat_percent: 19 + read_only: true + artshow-table-oneandhalf: + description: 'Artshow (1.5 Tables)' + price: 1500 + vat_percent: 19 + read_only: true + artshow-table-two: + description: 'Artshow (2 Tables)' + price: 2000 + vat_percent: 19 + read_only: true + artshow-table-twoandhalf: + description: 'Artshow (2.5 Tables)' + price: 2500 + vat_percent: 19 + read_only: true + artshow-table-three: + description: 'Artshow (3 Tables)' + price: 3000 + vat_percent: 19 + read_only: true + artshow-table-threeandhalf: + description: 'Artshow (3.5 Tables)' + price: 3500 + vat_percent: 19 + read_only: true + artshow-table-four: + description: 'Artshow (4 Tables)' + price: 4000 + vat_percent: 19 + read_only: true + artshow-panel-half: + description: 'Artshow (Half Panel)' price: 1000 vat_percent: 19 read_only: true + artshow-panel-one: + description: 'Artshow (1 Panel)' + price: 2000 + vat_percent: 19 + read_only: true + artshow-panel-oneandhalf: + description: 'Artshow (1.5 Panels)' + price: 3000 + vat_percent: 19 + read_only: true + artshow-panel-two: + description: 'Artshow (2 Panels)' + price: 4000 + vat_percent: 19 + read_only: true + artshow-panel-twoandhalf: + description: 'Artshow (2.5 Panels)' + price: 5000 + vat_percent: 19 + read_only: true + artshow-panel-three: + description: 'Artshow (3 Panels)' + price: 6000 + vat_percent: 19 + read_only: true + artshow-panel-threeandhalf: + description: 'Artshow (3.5 Panels)' + price: 7000 + vat_percent: 19 + read_only: true + artshow-panel-four: + description: 'Artshow Panel (4 Panels)' + price: 8000 + vat_percent: 19 + read_only: true options: art: description: 'Artist' diff --git a/internal/repository/config/loading.go b/internal/repository/config/loading.go index 384b41e..29447bf 100644 --- a/internal/repository/config/loading.go +++ b/internal/repository/config/loading.go @@ -55,6 +55,8 @@ func parseAndOverwriteConfig(yamlFile []byte) error { setConfigurationDefaults(newConfigurationData) + applyEnvVarOverrides(newConfigurationData) + errs := url.Values{} validateServerConfiguration(errs, newConfigurationData.Server) validateServiceConfiguration(errs, newConfigurationData.Service) diff --git a/internal/repository/config/structure.go b/internal/repository/config/structure.go index f4a5408..5be6601 100644 --- a/internal/repository/config/structure.go +++ b/internal/repository/config/structure.go @@ -118,16 +118,16 @@ type ( } ChoiceConfig struct { - Description string `yaml:"description"` - Price int64 `yaml:"price"` - VatPercent float64 `yaml:"vat_percent"` - Default bool `yaml:"default"` // if set to true, is added to flags by default. Not available for admin only flags! - AdminOnly bool `yaml:"admin_only"` // this flag is kept under the adminInfo structure, so it is not visible to users - ReadOnly bool `yaml:"read_only"` // this flag is kept under the normal flags, thus visible to end user, but only admin can change it - VisibleFor string `yaml:"visible_for"` // comma separated list of permissions which allow seeing the flag/option/package. Admin can always see everything, "self" can always see non-admin_only, but you can add it for admin_only fields. This field also controls who else can see the info based on their permissions admin field. Example: "self,sponsordesk" - Mandatory bool `yaml:"at-least-one-mandatory"` // one of these MUST be chosen (no constraint if not set on any choices) - Constraint string `yaml:"constraint"` - ConstraintMsg string `yaml:"constraint_msg"` + Description string `yaml:"description"` + Price int64 `yaml:"price"` + VatPercent float64 `yaml:"vat_percent"` + Default bool `yaml:"default"` // if set to true, is added to flags by default. Not available for admin only flags! + AdminOnly bool `yaml:"admin_only"` // this flag is kept under the adminInfo structure, so it is not visible to users + ReadOnly bool `yaml:"read_only"` // this flag is kept under the normal flags, thus visible to end user, but only admin can change it + VisibleFor []string `yaml:"visible_for"` // list of permissions which allow seeing the flag/option/package. Admin can always see everything, "self" can always see non-admin_only, but you can add it for admin_only fields. This field also controls who else can see the info based on their permissions admin field. Example: "self,sponsordesk" + Mandatory bool `yaml:"at-least-one-mandatory"` // one of these MUST be chosen (no constraint if not set on any choices) + Constraint string `yaml:"constraint"` + ConstraintMsg string `yaml:"constraint_msg"` } // AddInfoConfig configures access permissions to an additional info field diff --git a/internal/repository/config/validation.go b/internal/repository/config/validation.go index 7a44d17..e93f2a4 100644 --- a/internal/repository/config/validation.go +++ b/internal/repository/config/validation.go @@ -6,6 +6,7 @@ import ( "github.com/eurofurence/reg-attendee-service/internal/web/util/validation" "github.com/golang-jwt/jwt/v4" "net/url" + "os" "strings" "time" ) @@ -55,6 +56,20 @@ func setConfigurationDefaults(c *Application) { } } +const ( + envDbPassword = "REG_SECRET_DB_PASSWORD" + envApiToken = "REG_SECRET_API_TOKEN" +) + +func applyEnvVarOverrides(c *Application) { + if dbPassword := os.Getenv(envDbPassword); dbPassword != "" { + c.Database.Password = dbPassword + } + if apiToken := os.Getenv(envApiToken); apiToken != "" { + c.Security.Fixed.Api = apiToken + } +} + const portPattern = "^[1-9][0-9]{0,4}$" func validateServerConfiguration(errs url.Values, c ServerConfig) { diff --git a/internal/web/controller/attendeectl/attendeectl.go b/internal/web/controller/attendeectl/attendeectl.go index e7b7b2a..6f1222a 100644 --- a/internal/web/controller/attendeectl/attendeectl.go +++ b/internal/web/controller/attendeectl/attendeectl.go @@ -21,7 +21,6 @@ import ( "net/url" "sort" "strconv" - "strings" "time" ) @@ -324,7 +323,7 @@ func choiceVisibilityCheckMustReturnOnError(ctx context.Context, w http.Response // self if choiceType == "flag" { if choice.AdminOnly { - if !commaSeparatedContains(choice.VisibleFor, "self") { + if !sliceContains(choice.VisibleFor, "self") { choiceNotAccessibleHandler(ctx, w, r, choiceType, code) return errors.New("not accessible") } @@ -334,9 +333,8 @@ func choiceVisibilityCheckMustReturnOnError(ctx context.Context, w http.Response } else { // by area allowed := false - if choice.VisibleFor != "" { - flagVisibleFor := strings.Split(choice.VisibleFor, ",") - allowed, err = attendeeService.CanAccessAdditionalInfoArea(ctx, flagVisibleFor...) + if len(choice.VisibleFor) > 0 { + allowed, err = attendeeService.CanAccessAdditionalInfoArea(ctx, choice.VisibleFor...) if err != nil { choiceErrorHandler(ctx, w, r, choiceType, code, err) return errors.New("internal error") diff --git a/internal/web/controller/attendeectl/mapping.go b/internal/web/controller/attendeectl/mapping.go index 65525dc..fcdb324 100644 --- a/internal/web/controller/attendeectl/mapping.go +++ b/internal/web/controller/attendeectl/mapping.go @@ -86,7 +86,11 @@ func addWrappingCommas(v string) string { func commaSeparatedContains(commaSeparated string, singleValue string) bool { list := strings.Split(removeWrappingCommas(commaSeparated), ",") - for _, e := range list { + return sliceContains(list, singleValue) +} + +func sliceContains(slice []string, singleValue string) bool { + for _, e := range slice { if e == singleValue { return true } diff --git a/test/testconfig-base.yaml b/test/testconfig-base.yaml index cbc8772..d68fee8 100644 --- a/test/testconfig-base.yaml +++ b/test/testconfig-base.yaml @@ -56,11 +56,13 @@ choices: description: 'Wheelchair' anon: description: 'Legal Name is Confidential' - visible_for: regdesk + visible_for: + - regdesk ev: description: 'Eurofurence e.V. Member' read_only: true - visible_for: regdesk + visible_for: + - regdesk terms-accepted: description: 'Accepted the terms' default: true @@ -68,7 +70,10 @@ choices: guest: description: 'Guest of the Convention' admin_only: true - visible_for: self,sponsordesk,regdesk + visible_for: + - self + - sponsordesk + - regdesk skip_ban_check: description: 'Bypass ban check for this attendee' admin_only: true @@ -97,19 +102,22 @@ choices: description: 'Sponsor Upgrade' price: 6500 vat_percent: 19 - visible_for: sponsordesk + visible_for: + - sponsordesk sponsor2: description: 'Supersponsor Upgrade' price: 16000 vat_percent: 19 constraint: '!sponsor' constraint_msg: 'Please choose only one of Sponsor or Supersponsor.' - visible_for: sponsordesk + visible_for: + - sponsordesk boat-trip: description: 'Boat Trip' price: 2000 vat_percent: 19 - visible_for: regdesk + visible_for: + - regdesk mountain-trip: description: 'Mountain Trip' price: 3000 @@ -141,12 +149,14 @@ choices: options: art: description: 'Artist' - visible_for: sponsordesk + visible_for: + - sponsordesk anim: description: 'Animator' music: description: 'Musician' - visible_for: sponsordesk + visible_for: + - sponsordesk suit: description: 'Fursuiter' tshirtsizes: