mirror of
https://github.com/openziti/zrok.git
synced 2025-06-26 04:31:30 +02:00
controller config structure improvements
This commit is contained in:
parent
c1f481e416
commit
e2d3208165
@ -8,11 +8,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type createAccountHandler struct {
|
type createAccountHandler struct {
|
||||||
cfg *Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCreateAccountHandler(cfg *Config) *createAccountHandler {
|
func newCreateAccountHandler() *createAccountHandler {
|
||||||
return &createAccountHandler{cfg: cfg}
|
return &createAccountHandler{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *createAccountHandler) Handle(params identity.CreateAccountParams) middleware.Responder {
|
func (self *createAccountHandler) Handle(params identity.CreateAccountParams) middleware.Responder {
|
||||||
@ -66,7 +65,7 @@ func (self *createAccountHandler) Handle(params identity.CreateAccountParams) mi
|
|||||||
return identity.NewCreateAccountInternalServerError()
|
return identity.NewCreateAccountInternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sendVerificationEmail(params.Body.Email, token, self.cfg); err != nil {
|
if err := sendVerificationEmail(params.Body.Email, token); err != nil {
|
||||||
logrus.Errorf("error sending verification email for '%v': %v", params.Body.Email, err)
|
logrus.Errorf("error sending verification email for '%v': %v", params.Body.Email, err)
|
||||||
return identity.NewCreateAccountInternalServerError()
|
return identity.NewCreateAccountInternalServerError()
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ type Config struct {
|
|||||||
Store *store.Config
|
Store *store.Config
|
||||||
Ziti *ZitiConfig
|
Ziti *ZitiConfig
|
||||||
Metrics *MetricsConfig
|
Metrics *MetricsConfig
|
||||||
|
Influx *InfluxConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type EndpointConfig struct {
|
type EndpointConfig struct {
|
||||||
@ -44,6 +45,17 @@ type ZitiConfig struct {
|
|||||||
Password string
|
Password string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MetricsConfig struct {
|
||||||
|
ServiceName string
|
||||||
|
}
|
||||||
|
|
||||||
|
type InfluxConfig struct {
|
||||||
|
Url string
|
||||||
|
Bucket string
|
||||||
|
Org string
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
|
||||||
func LoadConfig(path string) (*Config, error) {
|
func LoadConfig(path string) (*Config, error) {
|
||||||
cfg := &Config{}
|
cfg := &Config{}
|
||||||
if err := cf.BindYaml(cfg, path, cf.DefaultOptions()); err != nil {
|
if err := cf.BindYaml(cfg, path, cf.DefaultOptions()); err != nil {
|
||||||
|
@ -10,12 +10,15 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var cfg *Config
|
||||||
var str *store.Store
|
var str *store.Store
|
||||||
var mtr *metricsAgent
|
var mtr *metricsAgent
|
||||||
|
|
||||||
const version = "v0.2.0"
|
const version = "v0.2.0"
|
||||||
|
|
||||||
func Run(cfg *Config) error {
|
func Run(inCfg *Config) error {
|
||||||
|
cfg = inCfg
|
||||||
|
|
||||||
swaggerSpec, err := loads.Embedded(rest_server_zrok.SwaggerJSON, rest_server_zrok.FlatSwaggerJSON)
|
swaggerSpec, err := loads.Embedded(rest_server_zrok.SwaggerJSON, rest_server_zrok.FlatSwaggerJSON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error loading embedded swagger spec")
|
return errors.Wrap(err, "error loading embedded swagger spec")
|
||||||
@ -23,18 +26,18 @@ func Run(cfg *Config) error {
|
|||||||
|
|
||||||
api := operations.NewZrokAPI(swaggerSpec)
|
api := operations.NewZrokAPI(swaggerSpec)
|
||||||
api.KeyAuth = ZrokAuthenticate
|
api.KeyAuth = ZrokAuthenticate
|
||||||
api.IdentityCreateAccountHandler = newCreateAccountHandler(cfg)
|
api.IdentityCreateAccountHandler = newCreateAccountHandler()
|
||||||
api.IdentityEnableHandler = newEnableHandler(cfg)
|
api.IdentityEnableHandler = newEnableHandler()
|
||||||
api.IdentityDisableHandler = newDisableHandler(cfg)
|
api.IdentityDisableHandler = newDisableHandler()
|
||||||
api.IdentityLoginHandler = identity.LoginHandlerFunc(loginHandler)
|
api.IdentityLoginHandler = identity.LoginHandlerFunc(loginHandler)
|
||||||
api.IdentityRegisterHandler = newRegisterHandler()
|
api.IdentityRegisterHandler = newRegisterHandler()
|
||||||
api.IdentityVerifyHandler = newVerifyHandler(cfg)
|
api.IdentityVerifyHandler = newVerifyHandler()
|
||||||
api.MetadataOverviewHandler = metadata.OverviewHandlerFunc(overviewHandler)
|
api.MetadataOverviewHandler = metadata.OverviewHandlerFunc(overviewHandler)
|
||||||
api.MetadataVersionHandler = metadata.VersionHandlerFunc(versionHandler)
|
api.MetadataVersionHandler = metadata.VersionHandlerFunc(versionHandler)
|
||||||
api.TunnelTunnelHandler = newTunnelHandler(cfg)
|
api.TunnelTunnelHandler = newTunnelHandler()
|
||||||
api.TunnelUntunnelHandler = newUntunnelHandler(cfg)
|
api.TunnelUntunnelHandler = newUntunnelHandler()
|
||||||
|
|
||||||
if err := controllerStartup(cfg); err != nil {
|
if err := controllerStartup(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +48,7 @@ func Run(cfg *Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Metrics != nil {
|
if cfg.Metrics != nil {
|
||||||
mtr = newMetricsAgent(cfg.Metrics)
|
mtr = newMetricsAgent()
|
||||||
go mtr.run()
|
go mtr.run()
|
||||||
defer func() {
|
defer func() {
|
||||||
mtr.stop()
|
mtr.stop()
|
||||||
|
@ -11,11 +11,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type disableHandler struct {
|
type disableHandler struct {
|
||||||
cfg *Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDisableHandler(cfg *Config) *disableHandler {
|
func newDisableHandler() *disableHandler {
|
||||||
return &disableHandler{cfg: cfg}
|
return &disableHandler{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *disableHandler) Handle(params identity.DisableParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
func (self *disableHandler) Handle(params identity.DisableParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
||||||
@ -30,7 +29,7 @@ func (self *disableHandler) Handle(params identity.DisableParams, principal *res
|
|||||||
logrus.Errorf("identity check failed: %v", err)
|
logrus.Errorf("identity check failed: %v", err)
|
||||||
return identity.NewDisableUnauthorized()
|
return identity.NewDisableUnauthorized()
|
||||||
}
|
}
|
||||||
edge, err := edgeClient(self.cfg.Ziti)
|
edge, err := edgeClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("error getting edge client: %v", err)
|
logrus.Errorf("error getting edge client: %v", err)
|
||||||
return identity.NewDisableInternalServerError()
|
return identity.NewDisableInternalServerError()
|
||||||
|
@ -20,11 +20,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type enableHandler struct {
|
type enableHandler struct {
|
||||||
cfg *Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEnableHandler(cfg *Config) *enableHandler {
|
func newEnableHandler() *enableHandler {
|
||||||
return &enableHandler{cfg: cfg}
|
return &enableHandler{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *enableHandler) Handle(params identity.EnableParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
func (self *enableHandler) Handle(params identity.EnableParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
||||||
@ -37,7 +36,7 @@ func (self *enableHandler) Handle(params identity.EnableParams, principal *rest_
|
|||||||
return identity.NewEnableInternalServerError()
|
return identity.NewEnableInternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := edgeClient(self.cfg.Ziti)
|
client, err := edgeClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Errorf("error getting edge client: %v", err)
|
logrus.Errorf("error getting edge client: %v", err)
|
||||||
return identity.NewEnableInternalServerError()
|
return identity.NewEnableInternalServerError()
|
||||||
|
@ -15,7 +15,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GC(cfg *Config) error {
|
func GC(inCfg *Config) error {
|
||||||
|
cfg = inCfg
|
||||||
if v, err := store.Open(cfg.Store); err == nil {
|
if v, err := store.Open(cfg.Store); err == nil {
|
||||||
str = v
|
str = v
|
||||||
} else {
|
} else {
|
||||||
@ -26,7 +27,7 @@ func GC(cfg *Config) error {
|
|||||||
logrus.Errorf("error closing store: %v", err)
|
logrus.Errorf("error closing store: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
edge, err := edgeClient(cfg.Ziti)
|
edge, err := edgeClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -20,20 +20,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MetricsConfig struct {
|
|
||||||
ServiceName string
|
|
||||||
Influx *InfluxConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
type InfluxConfig struct {
|
|
||||||
Url string
|
|
||||||
Bucket string
|
|
||||||
Org string
|
|
||||||
Token string
|
|
||||||
}
|
|
||||||
|
|
||||||
type metricsAgent struct {
|
type metricsAgent struct {
|
||||||
cfg *MetricsConfig
|
|
||||||
influx influxdb2.Client
|
influx influxdb2.Client
|
||||||
writeApi api.WriteAPIBlocking
|
writeApi api.WriteAPIBlocking
|
||||||
metricsQueue chan *model.Metrics
|
metricsQueue chan *model.Metrics
|
||||||
@ -49,9 +36,8 @@ type envCacheEntry struct {
|
|||||||
lastAccess time.Time
|
lastAccess time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMetricsAgent(cfg *MetricsConfig) *metricsAgent {
|
func newMetricsAgent() *metricsAgent {
|
||||||
ma := &metricsAgent{
|
ma := &metricsAgent{
|
||||||
cfg: cfg,
|
|
||||||
metricsQueue: make(chan *model.Metrics, 1024),
|
metricsQueue: make(chan *model.Metrics, 1024),
|
||||||
envCache: make(map[string]*envCacheEntry),
|
envCache: make(map[string]*envCacheEntry),
|
||||||
shutdown: make(chan struct{}),
|
shutdown: make(chan struct{}),
|
||||||
@ -106,9 +92,9 @@ func (ma *metricsAgent) bindService() error {
|
|||||||
ConnectTimeout: 5 * time.Minute,
|
ConnectTimeout: 5 * time.Minute,
|
||||||
MaxConnections: 1024,
|
MaxConnections: 1024,
|
||||||
}
|
}
|
||||||
ma.zListener, err = ma.zCtx.ListenWithOptions(ma.cfg.ServiceName, opts)
|
ma.zListener, err = ma.zCtx.ListenWithOptions(cfg.Metrics.ServiceName, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error listening for metrics on '%v'", ma.cfg.ServiceName)
|
return errors.Wrapf(err, "error listening for metrics on '%v'", cfg.Metrics.ServiceName)
|
||||||
}
|
}
|
||||||
go ma.listen()
|
go ma.listen()
|
||||||
return nil
|
return nil
|
||||||
|
@ -26,29 +26,31 @@ func overviewHandler(_ metadata.OverviewParams, principal *rest_model_zrok.Princ
|
|||||||
logrus.Errorf("error finding services for environment '%v': %v", env.ZId, err)
|
logrus.Errorf("error finding services for environment '%v': %v", env.ZId, err)
|
||||||
return metadata.NewOverviewInternalServerError()
|
return metadata.NewOverviewInternalServerError()
|
||||||
}
|
}
|
||||||
es := &rest_model_zrok.EnvironmentServices{
|
if env.Active {
|
||||||
Environment: &rest_model_zrok.Environment{
|
es := &rest_model_zrok.EnvironmentServices{
|
||||||
Active: env.Active,
|
Environment: &rest_model_zrok.Environment{
|
||||||
Address: env.Address,
|
Address: env.Address,
|
||||||
CreatedAt: env.CreatedAt.String(),
|
CreatedAt: env.CreatedAt.String(),
|
||||||
Description: env.Description,
|
Description: env.Description,
|
||||||
Host: env.Host,
|
Host: env.Host,
|
||||||
UpdatedAt: env.UpdatedAt.String(),
|
UpdatedAt: env.UpdatedAt.String(),
|
||||||
ZID: env.ZId,
|
ZID: env.ZId,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
for _, svc := range svcs {
|
||||||
|
if svc.Active {
|
||||||
|
es.Services = append(es.Services, &rest_model_zrok.Service{
|
||||||
|
CreatedAt: svc.CreatedAt.String(),
|
||||||
|
Frontend: svc.Frontend,
|
||||||
|
Backend: svc.Backend,
|
||||||
|
UpdatedAt: svc.UpdatedAt.String(),
|
||||||
|
ZID: svc.ZId,
|
||||||
|
Name: svc.Name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out = append(out, es)
|
||||||
}
|
}
|
||||||
for _, svc := range svcs {
|
|
||||||
es.Services = append(es.Services, &rest_model_zrok.Service{
|
|
||||||
Active: svc.Active,
|
|
||||||
CreatedAt: svc.CreatedAt.String(),
|
|
||||||
Frontend: svc.Frontend,
|
|
||||||
Backend: svc.Backend,
|
|
||||||
UpdatedAt: svc.UpdatedAt.String(),
|
|
||||||
ZID: svc.ZId,
|
|
||||||
Name: svc.Name,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
out = append(out, es)
|
|
||||||
}
|
}
|
||||||
return metadata.NewOverviewOK().WithPayload(out)
|
return metadata.NewOverviewOK().WithPayload(out)
|
||||||
}
|
}
|
||||||
|
@ -14,17 +14,17 @@ import (
|
|||||||
|
|
||||||
var zrokProxyConfigId string
|
var zrokProxyConfigId string
|
||||||
|
|
||||||
func controllerStartup(cfg *Config) error {
|
func controllerStartup() error {
|
||||||
if err := inspectZiti(cfg); err != nil {
|
if err := inspectZiti(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func inspectZiti(cfg *Config) error {
|
func inspectZiti() error {
|
||||||
logrus.Infof("inspecting ziti controller configuration")
|
logrus.Infof("inspecting ziti controller configuration")
|
||||||
|
|
||||||
edge, err := edgeClient(cfg.Ziti)
|
edge, err := edgeClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "error getting ziti edge client")
|
return errors.Wrap(err, "error getting ziti edge client")
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type tunnelHandler struct {
|
type tunnelHandler struct {
|
||||||
cfg *Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTunnelHandler(cfg *Config) *tunnelHandler {
|
func newTunnelHandler() *tunnelHandler {
|
||||||
return &tunnelHandler{cfg: cfg}
|
return &tunnelHandler{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *tunnelHandler) Handle(params tunnel.TunnelParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
func (self *tunnelHandler) Handle(params tunnel.TunnelParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
||||||
@ -58,7 +57,7 @@ func (self *tunnelHandler) Handle(params tunnel.TunnelParams, principal *rest_mo
|
|||||||
return tunnel.NewTunnelInternalServerError()
|
return tunnel.NewTunnelInternalServerError()
|
||||||
}
|
}
|
||||||
|
|
||||||
edge, err := edgeClient(self.cfg.Ziti)
|
edge, err := edgeClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
return tunnel.NewTunnelInternalServerError()
|
return tunnel.NewTunnelInternalServerError()
|
||||||
@ -203,7 +202,7 @@ func (self *tunnelHandler) createServicePolicyBind(svcName, svcId, envId string,
|
|||||||
|
|
||||||
func (self *tunnelHandler) createServicePolicyDial(svcName, svcId string, edge *rest_management_api_client.ZitiEdgeManagement) error {
|
func (self *tunnelHandler) createServicePolicyDial(svcName, svcId string, edge *rest_management_api_client.ZitiEdgeManagement) error {
|
||||||
var identityRoles []string
|
var identityRoles []string
|
||||||
for _, proxyIdentity := range self.cfg.Proxy.Identities {
|
for _, proxyIdentity := range cfg.Proxy.Identities {
|
||||||
identityRoles = append(identityRoles, "@"+proxyIdentity)
|
identityRoles = append(identityRoles, "@"+proxyIdentity)
|
||||||
logrus.Infof("added proxy identity role '%v'", proxyIdentity)
|
logrus.Infof("added proxy identity role '%v'", proxyIdentity)
|
||||||
}
|
}
|
||||||
@ -259,7 +258,7 @@ func (self *tunnelHandler) createServiceEdgeRouterPolicy(svcName, svcId string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *tunnelHandler) proxyUrl(svcName string) string {
|
func (self *tunnelHandler) proxyUrl(svcName string) string {
|
||||||
return strings.Replace(self.cfg.Proxy.UrlTemplate, "{svcName}", svcName, -1)
|
return strings.Replace(cfg.Proxy.UrlTemplate, "{svcName}", svcName, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *tunnelHandler) zrokTags(svcName string) *rest_model.Tags {
|
func (self *tunnelHandler) zrokTags(svcName string) *rest_model.Tags {
|
||||||
|
@ -15,11 +15,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type untunnelHandler struct {
|
type untunnelHandler struct {
|
||||||
cfg *Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newUntunnelHandler(cfg *Config) *untunnelHandler {
|
func newUntunnelHandler() *untunnelHandler {
|
||||||
return &untunnelHandler{cfg: cfg}
|
return &untunnelHandler{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *untunnelHandler) Handle(params tunnel.UntunnelParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
func (self *untunnelHandler) Handle(params tunnel.UntunnelParams, principal *rest_model_zrok.Principal) middleware.Responder {
|
||||||
@ -32,7 +31,7 @@ func (self *untunnelHandler) Handle(params tunnel.UntunnelParams, principal *res
|
|||||||
}
|
}
|
||||||
defer func() { _ = tx.Rollback() }()
|
defer func() { _ = tx.Rollback() }()
|
||||||
|
|
||||||
edge, err := edgeClient(self.cfg.Ziti)
|
edge, err := edgeClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Error(err)
|
logrus.Error(err)
|
||||||
return tunnel.NewUntunnelInternalServerError()
|
return tunnel.NewUntunnelInternalServerError()
|
||||||
|
@ -31,8 +31,8 @@ func ZrokAuthenticate(token string) (*rest_model_zrok.Principal, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func edgeClient(cfg *ZitiConfig) (*rest_management_api_client.ZitiEdgeManagement, error) {
|
func edgeClient() (*rest_management_api_client.ZitiEdgeManagement, error) {
|
||||||
caCerts, err := rest_util.GetControllerWellKnownCas(cfg.ApiEndpoint)
|
caCerts, err := rest_util.GetControllerWellKnownCas(cfg.Ziti.ApiEndpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ func edgeClient(cfg *ZitiConfig) (*rest_management_api_client.ZitiEdgeManagement
|
|||||||
for _, ca := range caCerts {
|
for _, ca := range caCerts {
|
||||||
caPool.AddCert(ca)
|
caPool.AddCert(ca)
|
||||||
}
|
}
|
||||||
return rest_util.NewEdgeManagementClientWithUpdb(cfg.Username, cfg.Password, cfg.ApiEndpoint, caPool)
|
return rest_util.NewEdgeManagementClientWithUpdb(cfg.Ziti.Username, cfg.Ziti.Password, cfg.Ziti.ApiEndpoint, caPool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createToken() (string, error) {
|
func createToken() (string, error) {
|
||||||
|
@ -8,11 +8,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type verifyHandler struct {
|
type verifyHandler struct {
|
||||||
cfg *Config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newVerifyHandler(cfg *Config) *verifyHandler {
|
func newVerifyHandler() *verifyHandler {
|
||||||
return &verifyHandler{cfg: cfg}
|
return &verifyHandler{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *verifyHandler) Handle(params identity.VerifyParams) middleware.Responder {
|
func (self *verifyHandler) Handle(params identity.VerifyParams) middleware.Responder {
|
||||||
|
@ -14,7 +14,7 @@ type verificationEmail struct {
|
|||||||
VerifyUrl string
|
VerifyUrl string
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendVerificationEmail(emailAddress, token string, cfg *Config) error {
|
func sendVerificationEmail(emailAddress, token string) error {
|
||||||
emailData := &verificationEmail{
|
emailData := &verificationEmail{
|
||||||
EmailAddress: emailAddress,
|
EmailAddress: emailAddress,
|
||||||
VerifyUrl: cfg.Registration.RegistrationUrlTemplate + "/" + token,
|
VerifyUrl: cfg.Registration.RegistrationUrlTemplate + "/" + token,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user