Merge pull request #8 from armisss4/email-settings-UI-old
Email settings UI old
This commit is contained in:
		
						commit
						60cc154fd3
					
				|  | @ -314,7 +314,7 @@ func NewClient(db store.IStore) echo.HandlerFunc { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // EmailClient handler to send the configuration via email
 | // EmailClient handler to send the configuration via email
 | ||||||
| func EmailClient(db store.IStore, mailer emailer.Emailer, emailSubject, emailContent string) echo.HandlerFunc { | func EmailClient(db store.IStore) echo.HandlerFunc { | ||||||
| 	type clientIdEmailPayload struct { | 	type clientIdEmailPayload struct { | ||||||
| 		ID    string `json:"id"` | 		ID    string `json:"id"` | ||||||
| 		Email string `json:"email"` | 		Email string `json:"email"` | ||||||
|  | @ -337,6 +337,15 @@ func EmailClient(db store.IStore, mailer emailer.Emailer, emailSubject, emailCon | ||||||
| 			return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"}) | 			return c.JSON(http.StatusNotFound, jsonHTTPResponse{false, "Client not found"}) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		// init mailer
 | ||||||
|  | 		var mailer emailer.Emailer | ||||||
|  | 		emailSetting, _ := db.GetEmailSettings() | ||||||
|  | 		if emailSetting.SendgridApiKey != "" { | ||||||
|  | 			mailer = emailer.NewSendgridApiMail(emailSetting.SendgridApiKey, emailSetting.EmailFromName, emailSetting.EmailFrom) | ||||||
|  | 		} else { | ||||||
|  | 			mailer = emailer.NewSmtpMail(emailSetting.SmtpHostname, emailSetting.SmtpPort, emailSetting.SmtpUsername, emailSetting.SmtpPassword, emailSetting.SmtpNoTLSCheck, emailSetting.SmtpAuthType, emailSetting.EmailFromName, emailSetting.EmailFrom, emailSetting.SmtpEncryption) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		// build config
 | 		// build config
 | ||||||
| 		server, _ := db.GetServer() | 		server, _ := db.GetServer() | ||||||
| 		globalSettings, _ := db.GetGlobalSettings() | 		globalSettings, _ := db.GetGlobalSettings() | ||||||
|  | @ -357,8 +366,8 @@ func EmailClient(db store.IStore, mailer emailer.Emailer, emailSubject, emailCon | ||||||
| 		err = mailer.Send( | 		err = mailer.Send( | ||||||
| 			clientData.Client.Name, | 			clientData.Client.Name, | ||||||
| 			payload.Email, | 			payload.Email, | ||||||
| 			emailSubject, | 			emailSetting.DefaultEmailSubject, | ||||||
| 			emailContent, | 			emailSetting.DefaultEmailContent, | ||||||
| 			attachments, | 			attachments, | ||||||
| 		) | 		) | ||||||
| 
 | 
 | ||||||
|  | @ -596,6 +605,64 @@ func GlobalSettings(db store.IStore) echo.HandlerFunc { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // EmailSettings handler
 | ||||||
|  | func EmailSettings(db store.IStore) echo.HandlerFunc { | ||||||
|  | 	return func(c echo.Context) error { | ||||||
|  | 
 | ||||||
|  | 		emailSettings, err := db.GetEmailSettings() | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Error("Cannot get email settings: ", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return c.Render(http.StatusOK, "email_settings.html", map[string]interface{}{ | ||||||
|  | 			"baseData":      model.BaseData{Active: "email-settings", CurrentUser: currentUser(c), Admin: isAdmin(c)}, | ||||||
|  | 			"emailSettings": emailSettings, | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // EmailSettingsSubmit handler to update the email settings
 | ||||||
|  | func EmailSettingsSubmit(db store.IStore) echo.HandlerFunc { | ||||||
|  | 	return func(c echo.Context) error { | ||||||
|  | 		data := make(map[string]interface{}) | ||||||
|  | 		err := json.NewDecoder(c.Request().Body).Decode(&data) | ||||||
|  | 
 | ||||||
|  | 		if err != nil { | ||||||
|  | 			return c.JSON(http.StatusBadRequest, jsonHTTPResponse{false, "Bad post data"}) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		emailSetting, err := db.GetEmailSettings() | ||||||
|  | 		if err != nil { | ||||||
|  | 			log.Error("Cannot get email settings: ", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if len(data) == 2 { | ||||||
|  | 			emailSetting.DefaultEmailSubject = data["default_email_subject"].(string) | ||||||
|  | 			emailSetting.DefaultEmailContent = data["default_email_content"].(string) | ||||||
|  | 		} else { | ||||||
|  | 			emailSetting.SendgridApiKey = data["sendgrid_api_key"].(string) | ||||||
|  | 			emailSetting.EmailFromName = data["email_from_name"].(string) | ||||||
|  | 			emailSetting.EmailFrom = data["email_from"].(string) | ||||||
|  | 			emailSetting.SmtpHostname = data["smtp_hostname"].(string) | ||||||
|  | 			emailSetting.SmtpPort = int(data["smtp_port"].(float64)) | ||||||
|  | 			emailSetting.SmtpUsername = data["smtp_username"].(string) | ||||||
|  | 			emailSetting.SmtpPassword = data["smtp_password"].(string) | ||||||
|  | 			emailSetting.SmtpNoTLSCheck = data["smtp_no_tls_check"].(bool) | ||||||
|  | 			emailSetting.SmtpAuthType = data["smtp_auth_type"].(string) | ||||||
|  | 			emailSetting.SmtpEncryption = data["smtp_encryption"].(string) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// write config to the database
 | ||||||
|  | 		if err := db.SaveEmailSettings(emailSetting); err != nil { | ||||||
|  | 			return c.JSON(http.StatusInternalServerError, jsonHTTPResponse{false, "Cannot update email settings"}) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		log.Infof("Updated email settings: %v", emailSetting) | ||||||
|  | 
 | ||||||
|  | 		return c.JSON(http.StatusOK, jsonHTTPResponse{true, "Updated email settings successfully"}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Status handler
 | // Status handler
 | ||||||
| func Status(db store.IStore) echo.HandlerFunc { | func Status(db store.IStore) echo.HandlerFunc { | ||||||
| 	type PeerVM struct { | 	type PeerVM struct { | ||||||
|  |  | ||||||
							
								
								
									
										51
									
								
								main.go
								
								
								
								
							
							
						
						
									
										51
									
								
								main.go
								
								
								
								
							|  | @ -11,7 +11,6 @@ import ( | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	rice "github.com/GeertJohan/go.rice" | 	rice "github.com/GeertJohan/go.rice" | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/emailer" |  | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/handler" | 	"github.com/ngoduykhanh/wireguard-ui/handler" | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/router" | 	"github.com/ngoduykhanh/wireguard-ui/router" | ||||||
| 	"github.com/ngoduykhanh/wireguard-ui/store/jsondb" | 	"github.com/ngoduykhanh/wireguard-ui/store/jsondb" | ||||||
|  | @ -42,18 +41,11 @@ var ( | ||||||
| 	flagBasePath       string | 	flagBasePath       string | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( |  | ||||||
| 	defaultEmailSubject = "Your wireguard configuration" |  | ||||||
| 	defaultEmailContent = `Hi,</br> |  | ||||||
| <p>In this email you can find your personal configuration for our wireguard server.</p> |  | ||||||
| 
 |  | ||||||
| <p>Best</p> |  | ||||||
| ` |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| func init() { | func init() { | ||||||
| 
 | 
 | ||||||
| 	// command-line flags and env variables
 | 	// command-line flags and env variables
 | ||||||
|  | 	// TODO move ENV_VAR variables and default values to config.go
 | ||||||
|  | 
 | ||||||
| 	flag.BoolVar(&flagDisableLogin, "disable-login", util.LookupEnvOrBool("DISABLE_LOGIN", flagDisableLogin), "Disable authentication on the app. This is potentially dangerous.") | 	flag.BoolVar(&flagDisableLogin, "disable-login", util.LookupEnvOrBool("DISABLE_LOGIN", flagDisableLogin), "Disable authentication on the app. This is potentially dangerous.") | ||||||
| 	flag.StringVar(&flagBindAddress, "bind-address", util.LookupEnvOrString("BIND_ADDRESS", flagBindAddress), "Address:Port to which the app will be bound.") | 	flag.StringVar(&flagBindAddress, "bind-address", util.LookupEnvOrString("BIND_ADDRESS", flagBindAddress), "Address:Port to which the app will be bound.") | ||||||
| 	flag.StringVar(&flagSmtpHostname, "smtp-hostname", util.LookupEnvOrString("SMTP_HOSTNAME", flagSmtpHostname), "SMTP Hostname") | 	flag.StringVar(&flagSmtpHostname, "smtp-hostname", util.LookupEnvOrString("SMTP_HOSTNAME", flagSmtpHostname), "SMTP Hostname") | ||||||
|  | @ -127,6 +119,34 @@ func main() { | ||||||
| 	// create the wireguard config on start, if it doesn't exist
 | 	// create the wireguard config on start, if it doesn't exist
 | ||||||
| 	initServerConfig(db, tmplBox) | 	initServerConfig(db, tmplBox) | ||||||
| 
 | 
 | ||||||
|  | 	// check and update email settings if necessary
 | ||||||
|  | 	if util.SendgridApiKey != "" { | ||||||
|  | 		emailSetting, _ := db.GetEmailSettings() | ||||||
|  | 		emailSetting.SendgridApiKey = util.SendgridApiKey | ||||||
|  | 		emailSetting.EmailFromName = util.EmailFromName | ||||||
|  | 		emailSetting.EmailFrom = util.EmailFrom | ||||||
|  | 		err := db.SaveEmailSettings(emailSetting) | ||||||
|  | 		if err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if util.SmtpUsername != "" { | ||||||
|  | 		emailSetting, _ := db.GetEmailSettings() | ||||||
|  | 		emailSetting.EmailFromName = util.EmailFromName | ||||||
|  | 		emailSetting.EmailFrom = util.EmailFrom | ||||||
|  | 		emailSetting.SmtpHostname = util.SmtpHostname | ||||||
|  | 		emailSetting.SmtpPort = util.SmtpPort | ||||||
|  | 		emailSetting.SmtpUsername = util.SmtpUsername | ||||||
|  | 		emailSetting.SmtpPassword = util.SmtpPassword | ||||||
|  | 		emailSetting.SmtpNoTLSCheck = util.SmtpNoTLSCheck | ||||||
|  | 		emailSetting.SmtpAuthType = util.SmtpAuthType | ||||||
|  | 		emailSetting.SmtpEncryption = util.SmtpEncryption | ||||||
|  | 		err := db.SaveEmailSettings(emailSetting) | ||||||
|  | 		if err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// register routes
 | 	// register routes
 | ||||||
| 	app := router.New(tmplBox, extraData, util.SessionSecret) | 	app := router.New(tmplBox, extraData, util.SessionSecret) | ||||||
| 
 | 
 | ||||||
|  | @ -140,17 +160,10 @@ func main() { | ||||||
| 		app.POST(util.BasePath+"/profile", handler.UpdateProfile(db), handler.ValidSession) | 		app.POST(util.BasePath+"/profile", handler.UpdateProfile(db), handler.ValidSession) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var sendmail emailer.Emailer |  | ||||||
| 	if util.SendgridApiKey != "" { |  | ||||||
| 		sendmail = emailer.NewSendgridApiMail(util.SendgridApiKey, util.EmailFromName, util.EmailFrom) |  | ||||||
| 	} else { |  | ||||||
| 		sendmail = emailer.NewSmtpMail(util.SmtpHostname, util.SmtpPort, util.SmtpUsername, util.SmtpPassword, util.SmtpNoTLSCheck, util.SmtpAuthType, util.EmailFromName, util.EmailFrom, util.SmtpEncryption) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	app.GET(util.BasePath+"/_health", handler.Health()) | 	app.GET(util.BasePath+"/_health", handler.Health()) | ||||||
| 	app.POST(util.BasePath+"/new-client", handler.NewClient(db), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/new-client", handler.NewClient(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.POST(util.BasePath+"/update-client", handler.UpdateClient(db), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/update-client", handler.UpdateClient(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.POST(util.BasePath+"/email-client", handler.EmailClient(db, sendmail, defaultEmailSubject, defaultEmailContent), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/email-client", handler.EmailClient(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.POST(util.BasePath+"/client/set-status", handler.SetClientStatus(db), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/client/set-status", handler.SetClientStatus(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.POST(util.BasePath+"/remove-client", handler.RemoveClient(db), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/remove-client", handler.RemoveClient(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.GET(util.BasePath+"/download", handler.DownloadClient(db), handler.ValidSession) | 	app.GET(util.BasePath+"/download", handler.DownloadClient(db), handler.ValidSession) | ||||||
|  | @ -159,6 +172,8 @@ func main() { | ||||||
| 	app.POST(util.BasePath+"/wg-server/keypair", handler.WireGuardServerKeyPair(db), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/wg-server/keypair", handler.WireGuardServerKeyPair(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
| 	app.GET(util.BasePath+"/global-settings", handler.GlobalSettings(db), handler.ValidSession) | 	app.GET(util.BasePath+"/global-settings", handler.GlobalSettings(db), handler.ValidSession) | ||||||
| 	app.POST(util.BasePath+"/global-settings", handler.GlobalSettingSubmit(db), handler.ValidSession, handler.ContentTypeJson) | 	app.POST(util.BasePath+"/global-settings", handler.GlobalSettingSubmit(db), handler.ValidSession, handler.ContentTypeJson) | ||||||
|  |   app.GET(util.BasePath+"/email-settings", handler.EmailSettings(db), handler.ValidSession) | ||||||
|  | 	app.POST(util.BasePath+"/email-settings", handler.EmailSettingsSubmit(db), handler.ValidSession) | ||||||
| 	app.GET(util.BasePath+"/status", handler.Status(db), handler.ValidSession) | 	app.GET(util.BasePath+"/status", handler.Status(db), handler.ValidSession) | ||||||
| 	app.GET(util.BasePath+"/api/clients", handler.GetClients(db), handler.ValidSession) | 	app.GET(util.BasePath+"/api/clients", handler.GetClients(db), handler.ValidSession) | ||||||
| 	app.GET(util.BasePath+"/api/client/:id", handler.GetClient(db), handler.ValidSession) | 	app.GET(util.BasePath+"/api/client/:id", handler.GetClient(db), handler.ValidSession) | ||||||
|  |  | ||||||
|  | @ -14,3 +14,18 @@ type GlobalSetting struct { | ||||||
| 	ConfigFilePath      string    `json:"config_file_path"` | 	ConfigFilePath      string    `json:"config_file_path"` | ||||||
| 	UpdatedAt           time.Time `json:"updated_at"` | 	UpdatedAt           time.Time `json:"updated_at"` | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | type EmailSetting struct { | ||||||
|  | 	SendgridApiKey      string `json:"sendgrid_api_key"` | ||||||
|  | 	EmailFromName       string `json:"email_from_name"` | ||||||
|  | 	EmailFrom           string `json:"email_from"` | ||||||
|  | 	SmtpHostname        string `json:"smtp_hostname"` | ||||||
|  | 	SmtpPort            int    `json:"smtp_port"` | ||||||
|  | 	SmtpUsername        string `json:"smtp_username"` | ||||||
|  | 	SmtpPassword        string `json:"smtp_password"` | ||||||
|  | 	SmtpNoTLSCheck      bool   `json:"smtp_no_tls_check"` | ||||||
|  | 	SmtpAuthType        string `json:"smtp_auth_type"` | ||||||
|  | 	SmtpEncryption      string `json:"smtp_encryption"` | ||||||
|  | 	DefaultEmailSubject string `json:"default_email_subject"` | ||||||
|  | 	DefaultEmailContent string `json:"default_email_content"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -83,6 +83,11 @@ func New(tmplBox *rice.Box, extraData map[string]string, secret []byte) *echo.Ec | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	tmplEmailSettingsString, err := tmplBox.String("email_settings.html") | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	tmplStatusString, err := tmplBox.String("status.html") | 	tmplStatusString, err := tmplBox.String("status.html") | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
|  | @ -103,6 +108,7 @@ func New(tmplBox *rice.Box, extraData map[string]string, secret []byte) *echo.Ec | ||||||
| 	templates["clients.html"] = template.Must(template.New("clients").Funcs(funcs).Parse(tmplBaseString + tmplClientsString)) | 	templates["clients.html"] = template.Must(template.New("clients").Funcs(funcs).Parse(tmplBaseString + tmplClientsString)) | ||||||
| 	templates["server.html"] = template.Must(template.New("server").Funcs(funcs).Parse(tmplBaseString + tmplServerString)) | 	templates["server.html"] = template.Must(template.New("server").Funcs(funcs).Parse(tmplBaseString + tmplServerString)) | ||||||
| 	templates["global_settings.html"] = template.Must(template.New("global_settings").Funcs(funcs).Parse(tmplBaseString + tmplGlobalSettingsString)) | 	templates["global_settings.html"] = template.Must(template.New("global_settings").Funcs(funcs).Parse(tmplBaseString + tmplGlobalSettingsString)) | ||||||
|  | 	templates["email_settings.html"] = template.Must(template.New("email_settings").Funcs(funcs).Parse(tmplBaseString + tmplEmailSettingsString)) | ||||||
| 	templates["status.html"] = template.Must(template.New("status").Funcs(funcs).Parse(tmplBaseString + tmplStatusString)) | 	templates["status.html"] = template.Must(template.New("status").Funcs(funcs).Parse(tmplBaseString + tmplStatusString)) | ||||||
| 	templates["wake_on_lan_hosts.html"] = template.Must(template.New("wake_on_lan_hosts").Funcs(funcs).Parse(tmplBaseString + tmplWakeOnLanHostsString)) | 	templates["wake_on_lan_hosts.html"] = template.Must(template.New("wake_on_lan_hosts").Funcs(funcs).Parse(tmplBaseString + tmplWakeOnLanHostsString)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -42,7 +42,9 @@ func (o *JsonDB) Init() error { | ||||||
| 	var serverInterfacePath string = path.Join(serverPath, "interfaces.json") | 	var serverInterfacePath string = path.Join(serverPath, "interfaces.json") | ||||||
| 	var serverKeyPairPath string = path.Join(serverPath, "keypair.json") | 	var serverKeyPairPath string = path.Join(serverPath, "keypair.json") | ||||||
| 	var globalSettingPath string = path.Join(serverPath, "global_settings.json") | 	var globalSettingPath string = path.Join(serverPath, "global_settings.json") | ||||||
|  | 	var emailSettingPath string = path.Join(serverPath, "email_settings.json") | ||||||
| 	var userPath string = path.Join(serverPath, "users.json") | 	var userPath string = path.Join(serverPath, "users.json") | ||||||
|  | 
 | ||||||
| 	// create directories if they do not exist
 | 	// create directories if they do not exist
 | ||||||
| 	if _, err := os.Stat(clientPath); os.IsNotExist(err) { | 	if _, err := os.Stat(clientPath); os.IsNotExist(err) { | ||||||
| 		os.MkdirAll(clientPath, os.ModePerm) | 		os.MkdirAll(clientPath, os.ModePerm) | ||||||
|  | @ -102,6 +104,27 @@ func (o *JsonDB) Init() error { | ||||||
| 		o.conn.Write("server", "global_settings", globalSetting) | 		o.conn.Write("server", "global_settings", globalSetting) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// email settings
 | ||||||
|  | 	// TODO move ENV_VAR variables and default values to config.go
 | ||||||
|  | 	if _, err := os.Stat(emailSettingPath); os.IsNotExist(err) { | ||||||
|  | 		emailSetting := new(model.EmailSetting) | ||||||
|  | 		emailSetting.SendgridApiKey = util.LookupEnvOrString("SENDGRID_API_KEY", "") | ||||||
|  | 		emailSetting.EmailFromName = util.LookupEnvOrString("EMAIL_FROM_NAME", "WireGuard UI") | ||||||
|  | 		emailSetting.EmailFrom = util.LookupEnvOrString("EMAIL_FROM_ADDRESS", "") | ||||||
|  | 		emailSetting.SmtpHostname = util.LookupEnvOrString("SMTP_HOSTNAME", "127.0.0.1") | ||||||
|  | 		emailSetting.SmtpPort = util.LookupEnvOrInt("SMTP_PORT", 25) | ||||||
|  | 		emailSetting.SmtpUsername = util.LookupEnvOrString("SMTP_USERNAME", "") | ||||||
|  | 		emailSetting.SmtpPassword = util.LookupEnvOrString("SMTP_PASSWORD", "") | ||||||
|  | 		emailSetting.SmtpNoTLSCheck = util.LookupEnvOrBool("SMTP_NO_TLS_CHECK", false) | ||||||
|  | 		emailSetting.SmtpAuthType = util.LookupEnvOrString("SMTP_AUTH_TYPE", "NONE") | ||||||
|  | 		emailSetting.SmtpEncryption = util.LookupEnvOrString("SMTP_ENCRYPTION", "STARTTLS") | ||||||
|  | 		emailSetting.DefaultEmailSubject = "Your wireguard configuration" | ||||||
|  | 		emailSetting.DefaultEmailContent = `Hi,</br> | ||||||
|  | <p>In this email you can find your personal configuration for our wireguard server.</p> | ||||||
|  | <p>Best</p>` | ||||||
|  | 		o.conn.Write("server", "email_settings", emailSetting) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// user info
 | 	// user info
 | ||||||
| 	if _, err := os.Stat(userPath); os.IsNotExist(err) { | 	if _, err := os.Stat(userPath); os.IsNotExist(err) { | ||||||
| 		user := new(model.User) | 		user := new(model.User) | ||||||
|  | @ -255,3 +278,13 @@ func (o *JsonDB) SaveServerKeyPair(serverKeyPair model.ServerKeypair) error { | ||||||
| func (o *JsonDB) SaveGlobalSettings(globalSettings model.GlobalSetting) error { | func (o *JsonDB) SaveGlobalSettings(globalSettings model.GlobalSetting) error { | ||||||
| 	return o.conn.Write("server", "global_settings", globalSettings) | 	return o.conn.Write("server", "global_settings", globalSettings) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // GetEmailSettings func to query email settings from the database
 | ||||||
|  | func (o *JsonDB) GetEmailSettings() (model.EmailSetting, error) { | ||||||
|  | 	settings := model.EmailSetting{} | ||||||
|  | 	return settings, o.conn.Read("server", "email_settings", &settings) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (o *JsonDB) SaveEmailSettings(emailSettings model.EmailSetting) error { | ||||||
|  | 	return o.conn.Write("server", "email_settings", emailSettings) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ type IStore interface { | ||||||
| 	GetUser() (model.User, error) | 	GetUser() (model.User, error) | ||||||
| 	SaveUser(user model.User) error | 	SaveUser(user model.User) error | ||||||
| 	GetGlobalSettings() (model.GlobalSetting, error) | 	GetGlobalSettings() (model.GlobalSetting, error) | ||||||
|  | 	GetEmailSettings() (model.EmailSetting, error) | ||||||
| 	GetServer() (model.Server, error) | 	GetServer() (model.Server, error) | ||||||
| 	GetClients(hasQRCode bool) ([]model.ClientData, error) | 	GetClients(hasQRCode bool) ([]model.ClientData, error) | ||||||
| 	GetClientByID(clientID string, qrCode model.QRCodeSettings) (model.ClientData, error) | 	GetClientByID(clientID string, qrCode model.QRCodeSettings) (model.ClientData, error) | ||||||
|  | @ -17,6 +18,7 @@ type IStore interface { | ||||||
| 	SaveServerInterface(serverInterface model.ServerInterface) error | 	SaveServerInterface(serverInterface model.ServerInterface) error | ||||||
| 	SaveServerKeyPair(serverKeyPair model.ServerKeypair) error | 	SaveServerKeyPair(serverKeyPair model.ServerKeypair) error | ||||||
| 	SaveGlobalSettings(globalSettings model.GlobalSetting) error | 	SaveGlobalSettings(globalSettings model.GlobalSetting) error | ||||||
|  | 	SaveEmailSettings(emailSettings model.EmailSetting) error | ||||||
| 	GetWakeOnLanHosts() ([]model.WakeOnLanHost, error) | 	GetWakeOnLanHosts() ([]model.WakeOnLanHost, error) | ||||||
| 	GetWakeOnLanHost(macAddress string) (*model.WakeOnLanHost, error) | 	GetWakeOnLanHost(macAddress string) (*model.WakeOnLanHost, error) | ||||||
| 	DeleteWakeOnHostLanHost(macAddress string) error | 	DeleteWakeOnHostLanHost(macAddress string) error | ||||||
|  |  | ||||||
|  | @ -124,6 +124,14 @@ | ||||||
|                                 </p> |                                 </p> | ||||||
|                             </a> |                             </a> | ||||||
|                         </li> |                         </li> | ||||||
|  |                         <li class="nav-item"> | ||||||
|  |                             <a href="{{.basePath}}/email-settings" class="nav-link {{if eq .baseData.Active "email-settings" }}active{{end}}"> | ||||||
|  |                             <i class="nav-icon fas fa-cog"></i> | ||||||
|  |                             <p> | ||||||
|  |                                 Email Settings | ||||||
|  |                             </p> | ||||||
|  |                             </a> | ||||||
|  |                         </li> | ||||||
|                         <li class="nav-header">UTILITIES</li> |                         <li class="nav-header">UTILITIES</li> | ||||||
|                         <li class="nav-item"> |                         <li class="nav-item"> | ||||||
|                             <a href="{{.basePath}}/status" class="nav-link {{if eq .baseData.Active "status" }}active{{end}}"> |                             <a href="{{.basePath}}/status" class="nav-link {{if eq .baseData.Active "status" }}active{{end}}"> | ||||||
|  | @ -206,6 +214,14 @@ | ||||||
|                                     </label> |                                     </label> | ||||||
|                                 </div> |                                 </div> | ||||||
|                             </div> |                             </div> | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <div class="icheck-primary d-inline"> | ||||||
|  |                                     <input type="checkbox" id="send_email_after_creation" {{ if .client_defaults.EnableAfterCreation }}checked{{ end }}> | ||||||
|  |                                     <label for="send_email_after_creation"> | ||||||
|  |                                         Send email after creation | ||||||
|  |                                     </label> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|                             <details> |                             <details> | ||||||
|                                 <summary><strong>Public and Preshared Keys</strong> |                                 <summary><strong>Public and Preshared Keys</strong> | ||||||
|                                     <i class="fas fa-info-circle" data-toggle="tooltip" |                                     <i class="fas fa-info-circle" data-toggle="tooltip" | ||||||
|  | @ -379,6 +395,7 @@ | ||||||
|                 success: function(resp) { |                 success: function(resp) { | ||||||
|                     $("#modal_new_client").modal('hide'); |                     $("#modal_new_client").modal('hide'); | ||||||
|                     toastr.success('Created new client successfully'); |                     toastr.success('Created new client successfully'); | ||||||
|  |                         sendEmailAfterCreation(resp.id, resp.email); | ||||||
|                     // Update the home page (clients page) after adding successfully |                     // Update the home page (clients page) after adding successfully | ||||||
|                     if (window.location.pathname === "{{.basePath}}/") { |                     if (window.location.pathname === "{{.basePath}}/") { | ||||||
|                         populateClient(resp.id); |                         populateClient(resp.id); | ||||||
|  | @ -411,6 +428,31 @@ | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         function sendEmailAfterCreation(client_id, client_email) { | ||||||
|  |             console.log("Do you even try?"); | ||||||
|  |             if ($("#send_email_after_creation").is(':checked')) { | ||||||
|  |                 if (client_email !== "" && client_id) { | ||||||
|  |                     const data = {"id": client_id, "email": client_email}; | ||||||
|  |                     $.ajax({ | ||||||
|  |                         cache: false, | ||||||
|  |                         method: 'POST', | ||||||
|  |                         url: '{{.basePath}}/email-client', | ||||||
|  |                         dataType: 'json', | ||||||
|  |                         contentType: "application/json", | ||||||
|  |                         data: JSON.stringify(data), | ||||||
|  |                         success: function (resp) { | ||||||
|  |                             toastr.success('Sent email to client successfully'); | ||||||
|  |                         }, | ||||||
|  |                         error: function (jqXHR, exception) { | ||||||
|  |                             const responseJson = jQuery.parseJSON(jqXHR.responseText); | ||||||
|  |                             toastr.error(responseJson['message']); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|     </script> |     </script> | ||||||
|     <script> |     <script> | ||||||
|         //Initialize Select2 Elements |         //Initialize Select2 Elements | ||||||
|  |  | ||||||
|  | @ -0,0 +1,364 @@ | ||||||
|  | {{define "title"}} | ||||||
|  | Email Settings | ||||||
|  | {{end}} | ||||||
|  | 
 | ||||||
|  | {{define "top_css"}} | ||||||
|  | {{end}} | ||||||
|  | 
 | ||||||
|  | {{define "username"}} | ||||||
|  | {{ .username }} | ||||||
|  | {{end}} | ||||||
|  | 
 | ||||||
|  | {{define "page_title"}} | ||||||
|  | Email Settings | ||||||
|  | {{end}} | ||||||
|  | 
 | ||||||
|  | {{define "page_content"}} | ||||||
|  | <section class="content"> | ||||||
|  |     <div class="container-fluid"> | ||||||
|  |         <!-- <h5 class="mt-4 mb-2">Global Settings</h5> --> | ||||||
|  |         <div class="row"> | ||||||
|  |             <!-- left column --> | ||||||
|  |             <div class="col-md-6"> | ||||||
|  |                 <div class="card card-success"> | ||||||
|  |                     <div class="card-header"> | ||||||
|  |                         <h3 class="card-title">Email Settings</h3> | ||||||
|  |                     </div> | ||||||
|  |                     <!-- /.card-header --> | ||||||
|  |                     <!-- form start --> | ||||||
|  |                     <form role="form" id="frm_email_settings" name="frm_email_settings"> | ||||||
|  |                         <div class="card-body"> | ||||||
|  | 
 | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <label for="sendgrid_api_key">Sendgrid API Key (If provided, overrules SMTP | ||||||
|  |                                     settings)</label> | ||||||
|  |                                 <input type="text" class="form-control" id="sendgrid_api_key" | ||||||
|  |                                        name="sendgrid_api_key" value="{{ .emailSettings.SendgridApiKey }}"> | ||||||
|  |                             </div> | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <label for="email_from_name">Email From Name</label> | ||||||
|  |                                 <input type="text" class="form-control" id="email_from_name" | ||||||
|  |                                        name="email_from_name" placeholder="E.g. WireGuard UI" | ||||||
|  |                                        value="{{ .emailSettings.EmailFromName }}"> | ||||||
|  |                             </div> | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <label for="email_from">Email From</label> | ||||||
|  |                                 <input type="text" class="form-control" id="email_from" | ||||||
|  |                                        name="email_from" placeholder="E.g. system@wireguard.com" | ||||||
|  |                                        value="{{ .emailSettings.EmailFrom }}"> | ||||||
|  |                             </div> | ||||||
|  |                             <div style="display: flex;"> | ||||||
|  |                                 <div class="form-group" style="width: 48%;"> | ||||||
|  |                                     <label for="smtp_hostname">SMTP Hostname</label> | ||||||
|  |                                     <input type="text" class="form-control" id="smtp_hostname" | ||||||
|  |                                            name="smtp_hostname" placeholder="E.g. 127.0.0.1" | ||||||
|  |                                            value="{{ .emailSettings.SmtpHostname }}"> | ||||||
|  |                                 </div> | ||||||
|  |                                 <div class="form-group" style="width: 48%; margin-left: 4%"> | ||||||
|  |                                     <label for="smtp_port">SMTP Port</label> | ||||||
|  |                                     <input type="text" class="form-control" id="smtp_port" | ||||||
|  |                                            name="smtp_port" placeholder="E.g. 25" | ||||||
|  |                                            value="{{ .emailSettings.SmtpPort }}"> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                             <div style="display: flex;"> | ||||||
|  |                                 <div class="form-group" style="width: 48%;"> | ||||||
|  |                                     <label for="smtp_username">SMTP Username</label> | ||||||
|  |                                     <input type="text" class="form-control" id="smtp_username" | ||||||
|  |                                            name="smtp_username" placeholder="E.g. system@wireguard.com" | ||||||
|  |                                            value="{{ .emailSettings.SmtpUsername }}"> | ||||||
|  |                                 </div> | ||||||
|  |                                 <div class="form-group" style="width: 48%; margin-left: 4%"> | ||||||
|  |                                     <label for="smtp_password">SMTP Password</label> | ||||||
|  |                                     <input type="password" class="form-control" id="smtp_password" | ||||||
|  |                                            name="smtp_password" placeholder="E.g. *******" | ||||||
|  |                                            value="{{ .emailSettings.SmtpPassword }}"> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                             <div style="display: flex;"> | ||||||
|  |                                 <div class="form-group" style="width: 48%;"> | ||||||
|  |                                     <label for="smtp_auth_type">SMTP Auth Type</label> | ||||||
|  |                                     <input type="text" class="form-control" id="smtp_auth_type" | ||||||
|  |                                            name="smtp_auth_type" placeholder="NONE/LOGIN/PLAIN" | ||||||
|  |                                            value="{{ .emailSettings.SmtpAuthType }}"> | ||||||
|  |                                 </div> | ||||||
|  |                                 <div class="form-group" style="width: 48%; margin-left: 4%"> | ||||||
|  |                                     <label for="smtp_encryption">SMTP Encryption</label> | ||||||
|  |                                     <input type="text" class="form-control" id="smtp_encryption" | ||||||
|  |                                            name="smtp_encryption" placeholder="SSL/SSLTLS/TLS/STARTTLS" | ||||||
|  |                                            value="{{ .emailSettings.SmtpEncryption }}"> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <div class="icheck-primary d-inline"> | ||||||
|  |                                     <input type="checkbox" id="smtp_no_tls_check" {{if .emailSettings.SmtpNoTLSCheck | ||||||
|  |                                            }}checked{{end}}> | ||||||
|  |                                     <label for="smtp_no_tls_check"> | ||||||
|  |                                         SMTP No TLS Check | ||||||
|  |                                     </label> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  | 
 | ||||||
|  |                         </div> | ||||||
|  |                         <!-- /.card-body --> | ||||||
|  | 
 | ||||||
|  |                         <div class="card-footer"> | ||||||
|  |                             <button type="submit" class="btn btn-success">Save</button> | ||||||
|  |                         </div> | ||||||
|  |                     </form> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- /.card --> | ||||||
|  |             </div> | ||||||
|  |             <div class="col-md-6"> | ||||||
|  |                 <div class="card card-success"> | ||||||
|  |                     <div class="card-header"> | ||||||
|  |                         <h3 class="card-title">Email Template</h3> | ||||||
|  |                     </div> | ||||||
|  |                     <!-- /.card-header --> | ||||||
|  |                     <form role="form" id="frm_email_settings2" name="frm_email_settings2"> | ||||||
|  |                         <div class="card-body"> | ||||||
|  | 
 | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <label for="default_email_subject">Email Subject</label> | ||||||
|  |                                 <input type="text" class="form-control" id="default_email_subject" | ||||||
|  |                                        name="default_email_subject" placeholder="Your Wireguard configuration" | ||||||
|  |                                        value="{{ .emailSettings.DefaultEmailSubject }}"> | ||||||
|  |                             </div> | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <label for="default_email_content">Email Content</label> | ||||||
|  |                                 <textarea class="form-control" id="default_email_content" | ||||||
|  |                                           name="default_email_content" rows="10" style="white-space: pre-wrap;">{{ .emailSettings.DefaultEmailContent }}</textarea> | ||||||
|  |                             </div> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="card-footer"> | ||||||
|  |                             <button type="submit" class="btn btn-success">Save</button> | ||||||
|  |                         </div> | ||||||
|  |                     </form> | ||||||
|  |                 </div> | ||||||
|  |                 <!-- /.card --> | ||||||
|  |             </div> | ||||||
|  |             <!-- /.row --> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | </section> | ||||||
|  | 
 | ||||||
|  | {{end}} | ||||||
|  | 
 | ||||||
|  | {{define "bottom_js"}} | ||||||
|  | <script> | ||||||
|  |     function submitEmailSettings() { | ||||||
|  | 
 | ||||||
|  |         const sendgrid_api_key = $("#sendgrid_api_key").val(); | ||||||
|  |         const email_from_name = $("#email_from_name").val(); | ||||||
|  |         const email_from = $("#email_from").val(); | ||||||
|  |         const smtp_hostname = $("#smtp_hostname").val(); | ||||||
|  |         let smtp_port = 0; | ||||||
|  |         if ($("#smtp_port").val().length !== 0) { | ||||||
|  |             smtp_port = parseInt($("#smtp_port").val()); | ||||||
|  |         } | ||||||
|  |         const smtp_username = $("#smtp_username").val(); | ||||||
|  |         const smtp_password = $("#smtp_password").val(); | ||||||
|  |         const smtp_auth_type = $("#smtp_auth_type").val(); | ||||||
|  |         const smtp_encryption = $("#smtp_encryption").val(); | ||||||
|  |         let smtp_no_tls_check = false; | ||||||
|  |         if ($("#smtp_no_tls_check").is(':checked')) { | ||||||
|  |             smtp_no_tls_check = true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const data = { | ||||||
|  |             "sendgrid_api_key": sendgrid_api_key, | ||||||
|  |             "email_from_name": email_from_name, | ||||||
|  |             "email_from": email_from, | ||||||
|  |             "smtp_hostname": smtp_hostname, | ||||||
|  |             "smtp_port": smtp_port, | ||||||
|  |             "smtp_username": smtp_username, | ||||||
|  |             "smtp_password": smtp_password, | ||||||
|  |             "smtp_no_tls_check": smtp_no_tls_check, | ||||||
|  |             "smtp_auth_type": smtp_auth_type, | ||||||
|  |             "smtp_encryption": smtp_encryption | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         $.ajax({ | ||||||
|  |             cache: false, | ||||||
|  |             method: 'POST', | ||||||
|  |             url: '{{.basePath}}/email-settings', | ||||||
|  |             dataType: 'json', | ||||||
|  |             contentType: "application/json", | ||||||
|  |             data: JSON.stringify(data), | ||||||
|  |             success: function (data) { | ||||||
|  |                 toastr.success('Updated email settings successfully'); | ||||||
|  |             }, | ||||||
|  |             error: function (jqXHR, exception) { | ||||||
|  |                 const responseJson = jQuery.parseJSON(jqXHR.responseText); | ||||||
|  |                 toastr.error(responseJson['message']); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     function submitEmailSettings2() { | ||||||
|  | 
 | ||||||
|  |         const default_email_subject = $("#default_email_subject").val(); | ||||||
|  |         const default_email_content = $("#default_email_content").val(); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |         const data = { | ||||||
|  |             "default_email_content": default_email_content, | ||||||
|  |             "default_email_subject": default_email_subject | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         $.ajax({ | ||||||
|  |             cache: false, | ||||||
|  |             method: 'POST', | ||||||
|  |             url: '{{.basePath}}/email-settings', | ||||||
|  |             dataType: 'json', | ||||||
|  |             contentType: "application/json", | ||||||
|  |             data: JSON.stringify(data), | ||||||
|  |             success: function (data) { | ||||||
|  |                 toastr.success('Updated email default message settings successfully'); | ||||||
|  |             }, | ||||||
|  |             error: function (jqXHR, exception) { | ||||||
|  |                 const responseJson = jQuery.parseJSON(jqXHR.responseText); | ||||||
|  |                 toastr.error(responseJson['message']); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | <script> | ||||||
|  | 
 | ||||||
|  |     // submitHandler | ||||||
|  |     function submitHandler(form) { | ||||||
|  |         const formId = $(form).attr('id'); | ||||||
|  |         if (formId === "frm_email_settings") { | ||||||
|  |             submitEmailSettings(); | ||||||
|  |         } else if (formId === "frm_email_settings2") { | ||||||
|  |             submitEmailSettings2(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Global setting form validation | ||||||
|  |     $(document).ready(function () { | ||||||
|  |         $.validator.setDefaults({ | ||||||
|  |             submitHandler: function (form) { | ||||||
|  |                 submitHandler(form); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |         $("#frm_email_settings").validate({ | ||||||
|  |             rules: { | ||||||
|  |                 email_from_name: { | ||||||
|  |                     required: true | ||||||
|  |                 }, | ||||||
|  |                 email_from: { | ||||||
|  |                     required: true | ||||||
|  |                 }, | ||||||
|  |                 smtp_hostname: { | ||||||
|  |                     required: function () { | ||||||
|  |                         return $("#sendgrid_api_key").val() === ""; | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 smtp_port: { | ||||||
|  |                     required: function () { | ||||||
|  |                         return $("#sendgrid_api_key").val() === ""; | ||||||
|  |                     }, | ||||||
|  |                     digits: true, | ||||||
|  |                     range: [0, 65535] | ||||||
|  |                 }, | ||||||
|  |                 smtp_username: { | ||||||
|  |                     required: function () { | ||||||
|  |                         return $("#sendgrid_api_key").val() === ""; | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 smtp_password: { | ||||||
|  |                     required: function () { | ||||||
|  |                         return $("#sendgrid_api_key").val() === ""; | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 smtp_no_tls_check: { | ||||||
|  |                     digits: true | ||||||
|  |                 }, | ||||||
|  |                 smtp_auth_type: { | ||||||
|  |                     required: function () { | ||||||
|  |                         return $("#sendgrid_api_key").val() === ""; | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 smtp_encryption: { | ||||||
|  |                     required: function () { | ||||||
|  |                         return $("#sendgrid_api_key").val() === ""; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             messages: { | ||||||
|  |                 email_from_name: { | ||||||
|  |                     required: "Field is mandatory" | ||||||
|  |                 }, | ||||||
|  |                 email_from: { | ||||||
|  |                     required: "Field is mandatory" | ||||||
|  |                 }, | ||||||
|  |                 smtp_hostname: { | ||||||
|  |                     required: "No Sendgrid API key, this field is mandatory" | ||||||
|  |                 }, | ||||||
|  |                 smtp_port: { | ||||||
|  |                     required: "No Sendgrid API key, this field is mandatory", | ||||||
|  |                     digits: "Port must be an integer", | ||||||
|  |                     range: "Port must be in range 0..65535" | ||||||
|  |                 }, | ||||||
|  |                 smtp_username: { | ||||||
|  |                     required: "No Sendgrid API key, this field is mandatory" | ||||||
|  |                 }, | ||||||
|  |                 smtp_password: { | ||||||
|  |                     required: "No Sendgrid API key, this field is mandatory" | ||||||
|  |                 }, | ||||||
|  |                 smtp_auth_type: { | ||||||
|  |                     required: "No Sendgrid API key, this field is mandatory" | ||||||
|  |                 }, | ||||||
|  |                 smtp_encryption: { | ||||||
|  |                     required: "No Sendgrid API key, this field is mandatory" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             errorElement: 'span', | ||||||
|  |             errorPlacement: function (error, element) { | ||||||
|  |                 error.addClass('invalid-feedback'); | ||||||
|  |                 element.closest('.form-group').append(error); | ||||||
|  |             }, | ||||||
|  |             highlight: function (element, errorClass, validClass) { | ||||||
|  |                 $(element).addClass('is-invalid'); | ||||||
|  |             }, | ||||||
|  |             unhighlight: function (element, errorClass, validClass) { | ||||||
|  |                 $(element).removeClass('is-invalid'); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         $("#frm_email_settings2").validate({ | ||||||
|  |             rules: { | ||||||
|  |                 default_email_subject: { | ||||||
|  |                     required: true | ||||||
|  |                 }, | ||||||
|  |                 default_email_content: { | ||||||
|  |                     required: true | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             messages: { | ||||||
|  |                 default_email_subject: { | ||||||
|  |                     required: "Field is mandatory" | ||||||
|  |                 }, | ||||||
|  |                 default_email_content: { | ||||||
|  |                     required: "Field is mandatory" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             errorElement: 'span', | ||||||
|  |             errorPlacement: function (error, element) { | ||||||
|  |                 error.addClass('invalid-feedback'); | ||||||
|  |                 element.closest('.form-group').append(error); | ||||||
|  |             }, | ||||||
|  |             highlight: function (element, errorClass, validClass) { | ||||||
|  |                 $(element).addClass('is-invalid'); | ||||||
|  |             }, | ||||||
|  |             unhighlight: function (element, errorClass, validClass) { | ||||||
|  |                 $(element).removeClass('is-invalid'); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | {{end}} | ||||||
		Loading…
	
		Reference in New Issue