mirror of
https://github.com/donl/gPanel.git
synced 2026-05-28 06:12:23 -06:00
Merge pull request #103 from george-e-shaw-iv/master
Bundle Creation Sends Email to Bundle Client
This commit is contained in:
commit
cb0a9ae577
12 changed files with 427 additions and 68 deletions
|
|
@ -1,27 +0,0 @@
|
|||
jQuery('#registerForm').on('submit', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var formData = {};
|
||||
for(var y = 0, yy = this.length; y < yy; y++) {
|
||||
var input = this[y];
|
||||
if(input.name) {
|
||||
formData[input.name] = input.value;
|
||||
}
|
||||
}
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(jQuery(this).attr('method'), jQuery(this).attr('action'), true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
xhr.send(JSON.stringify(formData));
|
||||
|
||||
xhr.onloadend = function() {
|
||||
if(xhr.status == 200 || xhr.status == 204) {
|
||||
jQuery('.index-alert').html('<strong>Register Success: </strong>You may now login.');
|
||||
jQuery('.index-alert').removeClass('alert-danger').addClass('alert-success').removeClass('d-none');
|
||||
}
|
||||
else {
|
||||
jQuery('.index-alert').html("<strong>Register Error: </strong>" + xhr.response);
|
||||
jQuery('.index-alert').removeClass('alert-success').addClass('alert-danger').removeClass('d-none');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -51,30 +51,6 @@
|
|||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-12 d-flex justify-content-center align-items-center mt-5">
|
||||
<form id="registerForm" method="POST" action="api/user/register">
|
||||
<div class="form-group">
|
||||
<label class="sr-only" for="loginUsername">Username</label>
|
||||
<div class="input-group mb-2">
|
||||
<div class="input-group-addon"><i class="fa fa-user" aria-hidden="true"></i></div>
|
||||
<input name="user" type="text" class="form-control" id="loginUsername" placeholder="Username">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="sr-only" for="loginPassword">Password</label>
|
||||
<div class="input-group mb-2">
|
||||
<div class="input-group-addon"><i class="fa fa-key" aria-hidden="true"></i></div>
|
||||
<input name="pass" type="password" class="form-control" id="loginPassword" placeholder="Password">
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Register</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-12 d-flex justify-content-center align-items-center mt-2">
|
||||
<small class="text-muted">Register is Temporary, for development purposes only.</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -95,8 +71,8 @@
|
|||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
|
||||
|
||||
<script type="text/javascript" src="assets/js/formHandlers/login.js"></script>
|
||||
<script type="text/javascript" src="assets/js/formHandlers/register.js"></script>
|
||||
<script type="text/javascript" src="assets/js/formHandlers/search.js"></script>
|
||||
<!-- KEEP AT BOTTOM OF BODY TAGS -->
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/database"
|
||||
"github.com/Ennovar/gPanel/pkg/emailer"
|
||||
"github.com/Ennovar/gPanel/pkg/encryption"
|
||||
"github.com/Ennovar/gPanel/pkg/file"
|
||||
"github.com/Ennovar/gPanel/pkg/gpaccount"
|
||||
)
|
||||
|
|
@ -24,6 +26,7 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
Name string `json:"name"`
|
||||
AccPort int `json:"account_port"`
|
||||
PubPort int `json:"public_port"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&createBundleRequestData)
|
||||
|
|
@ -82,10 +85,9 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
ds, err := database.Open(newBundle + "/" + database.DB_MAIN)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
defer ds.Close()
|
||||
|
||||
var databaseBundlePorts struct {
|
||||
Account int `json:"account"`
|
||||
|
|
@ -97,14 +99,75 @@ func Create(res http.ResponseWriter, req *http.Request, logger *log.Logger, bund
|
|||
err = ds.Put(database.BUCKET_PORTS, []byte("bundle_ports"), databaseBundlePorts)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
var defaultBundleUser database.Struct_Users
|
||||
|
||||
defaultBundleUser.Pass, err = encryption.HashPassword("root")
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
defaultBundleUser.Secret = ""
|
||||
|
||||
err = ds.Put(database.BUCKET_USERS, []byte("root"), defaultBundleUser)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
ds.Close()
|
||||
|
||||
bundles[createBundleRequestData.Name] = gpaccount.New(newBundle+"/", databaseBundlePorts.Account, databaseBundlePorts.Public)
|
||||
_ = bundles[createBundleRequestData.Name].Start()
|
||||
_ = bundles[createBundleRequestData.Name].Public.Start()
|
||||
|
||||
ds, err = database.Open("server/" + database.DB_SETTINGS)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
defer ds.Close()
|
||||
|
||||
var smtpSettings database.Struct_SMTP
|
||||
|
||||
err = ds.Get(database.BUCKET_GENERAL, []byte("smtp"), &smtpSettings)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
mail, err := emailer.New(smtpSettings.Type, emailer.Credentials{
|
||||
Username: smtpSettings.Username,
|
||||
Password: smtpSettings.Password,
|
||||
Server: smtpSettings.Server,
|
||||
Port: smtpSettings.Port,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
msg := string("Your new gPanel Bundle has been successfully registered.\r\n\n" +
|
||||
"Account Port: " + strconv.Itoa(createBundleRequestData.AccPort) + "\r\n" +
|
||||
"Public Port: " + strconv.Itoa(createBundleRequestData.PubPort) + "\r\n\n" +
|
||||
"Default account username: root\r\n" +
|
||||
"Default account password: root")
|
||||
|
||||
err = mail.SendSimple(createBundleRequestData.Email, "New gPanel Bundle - "+createBundleRequestData.Name, msg)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write([]byte(createBundleRequestData.Name))
|
||||
|
||||
|
|
|
|||
49
pkg/api/email/get_smtp.go
Normal file
49
pkg/api/email/get_smtp.go
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package email
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/database"
|
||||
)
|
||||
|
||||
func GetSMTP(res http.ResponseWriter, req *http.Request, logger *log.Logger, dir string) bool {
|
||||
if req.Method != "GET" {
|
||||
logger.Println(req.URL.Path + "::" + req.Method + "::" + strconv.Itoa(http.StatusMethodNotAllowed) + "::" + http.StatusText(http.StatusMethodNotAllowed))
|
||||
http.Error(res, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
||||
return false
|
||||
}
|
||||
|
||||
ds, err := database.Open(dir + database.DB_SETTINGS)
|
||||
if err != nil || ds == nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
defer ds.Close()
|
||||
|
||||
var smtpDbData database.Struct_SMTP
|
||||
|
||||
err = ds.Get(database.BUCKET_GENERAL, []byte("smtp"), &smtpDbData)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
// Remove password
|
||||
smtpDbData.Password = ""
|
||||
|
||||
b, err := json.Marshal(smtpDbData)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write(b)
|
||||
return true
|
||||
}
|
||||
60
pkg/api/email/set_smtp.go
Normal file
60
pkg/api/email/set_smtp.go
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
package email
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/database"
|
||||
"github.com/Ennovar/gPanel/pkg/emailer"
|
||||
)
|
||||
|
||||
func SetSMTP(res http.ResponseWriter, req *http.Request, logger *log.Logger, dir string) bool {
|
||||
if req.Method != "POST" && req.Method != "UPDATE" {
|
||||
logger.Println(req.URL.Path + "::" + req.Method + "::" + strconv.Itoa(http.StatusMethodNotAllowed) + "::" + http.StatusText(http.StatusMethodNotAllowed))
|
||||
http.Error(res, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
||||
return false
|
||||
}
|
||||
|
||||
var smtpRequestData database.Struct_SMTP
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&smtpRequestData)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
// Test Authentication
|
||||
_, err = emailer.New(smtpRequestData.Type, emailer.Credentials{
|
||||
Username: smtpRequestData.Username,
|
||||
Password: smtpRequestData.Password,
|
||||
Server: smtpRequestData.Server,
|
||||
Port: smtpRequestData.Port,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
ds, err := database.Open(dir + database.DB_SETTINGS)
|
||||
if err != nil || ds == nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
defer ds.Close()
|
||||
|
||||
err = ds.Put(database.BUCKET_GENERAL, []byte("smtp"), smtpRequestData)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
res.WriteHeader(http.StatusNoContent)
|
||||
return true
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ package database
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
|
|
@ -11,14 +12,19 @@ import (
|
|||
|
||||
// Database constants
|
||||
const (
|
||||
DB_MAIN = "datastore.db"
|
||||
DB_MAIN = "datastore.db"
|
||||
DB_SETTINGS = "settings.db"
|
||||
)
|
||||
|
||||
// Bucket constants
|
||||
const (
|
||||
// DB_MAIN BUCKETS
|
||||
BUCKET_USERS = "users"
|
||||
BUCKET_PORTS = "ports"
|
||||
BUCKET_FILTERED_IPS = "filtered_ips"
|
||||
|
||||
// DB_SETTINGS BUCKETS
|
||||
BUCKET_GENERAL = "general"
|
||||
)
|
||||
|
||||
// Error codes
|
||||
|
|
@ -45,19 +51,28 @@ func Open(filepath string) (*Datastore, error) {
|
|||
|
||||
// Ensure that all top-level buckets exist
|
||||
err = ds.handle.Update(func(tx *bolt.Tx) error {
|
||||
_, err := tx.CreateBucketIfNotExists([]byte(BUCKET_USERS))
|
||||
if err != nil {
|
||||
return err
|
||||
if strings.HasSuffix(filepath, DB_MAIN) {
|
||||
_, err := tx.CreateBucketIfNotExists([]byte(BUCKET_USERS))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BUCKET_PORTS))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BUCKET_FILTERED_IPS))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BUCKET_PORTS))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BUCKET_FILTERED_IPS))
|
||||
if err != nil {
|
||||
return err
|
||||
if strings.HasSuffix(filepath, DB_SETTINGS) {
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BUCKET_GENERAL))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
9
pkg/database/settings.go
Normal file
9
pkg/database/settings.go
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package database
|
||||
|
||||
type Struct_SMTP struct {
|
||||
Type string `json:"type"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Server string `json:"server"`
|
||||
Port int `json:"port"`
|
||||
}
|
||||
74
pkg/emailer/emailer.go
Normal file
74
pkg/emailer/emailer.go
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package emailer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/smtp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Credentials struct {
|
||||
Username string
|
||||
Password string
|
||||
Server string
|
||||
Port int
|
||||
}
|
||||
|
||||
type Emailer struct {
|
||||
auth smtp.Auth
|
||||
cred Credentials
|
||||
}
|
||||
|
||||
func New(eType string, creds Credentials) (*Emailer, error) {
|
||||
var a smtp.Auth
|
||||
|
||||
switch eType {
|
||||
case "crammd5":
|
||||
a = smtp.CRAMMD5Auth(creds.Username, creds.Password)
|
||||
default:
|
||||
a = smtp.PlainAuth("", creds.Username, creds.Password, creds.Server)
|
||||
}
|
||||
|
||||
if a == nil {
|
||||
return nil, errors.New("unable to authenticate")
|
||||
}
|
||||
|
||||
return &Emailer{
|
||||
auth: a,
|
||||
cred: creds,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SendSimple function will fill out the to/subject email headers for you and allow
|
||||
// you to just input a string as the email body.
|
||||
func (e *Emailer) SendSimple(to string, subject string, body string) error {
|
||||
if e.auth == nil {
|
||||
return errors.New("smtp server authentication has expired")
|
||||
}
|
||||
|
||||
m := []byte("To:" + to + "\r\n" +
|
||||
"Subject:" + subject + "\r\n" +
|
||||
"\r\n" +
|
||||
body + "\r\n")
|
||||
|
||||
err := smtp.SendMail(e.cred.Server+":"+strconv.Itoa(e.cred.Port), e.auth, e.cred.Username, []string{to}, m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendCustom function will not fill out the to/subject email headers for you and allow
|
||||
// you to send a completely custom message in the form of bytes.
|
||||
func (e *Emailer) SendCustom(to string, msg []byte) error {
|
||||
if e.auth == nil {
|
||||
return errors.New("smtp server authentication has expired")
|
||||
}
|
||||
|
||||
err := smtp.SendMail(e.cred.Server+":"+strconv.Itoa(e.cred.Port), e.auth, e.cred.Username, []string{to}, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/Ennovar/gPanel/pkg/api/bundle"
|
||||
"github.com/Ennovar/gPanel/pkg/api/email"
|
||||
logapi "github.com/Ennovar/gPanel/pkg/api/log"
|
||||
"github.com/Ennovar/gPanel/pkg/api/server"
|
||||
"github.com/Ennovar/gPanel/pkg/api/user"
|
||||
|
|
@ -86,6 +87,10 @@ func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request) (b
|
|||
return true, logapi.Read(res, req, con.APILogger, con.Directory)
|
||||
case "/log/delete":
|
||||
return true, logapi.Truncate(res, req, con.APILogger, con.Directory)
|
||||
case "/email/set_smtp":
|
||||
return true, email.SetSMTP(res, req, con.APILogger, con.Directory)
|
||||
case "/email/get_smtp":
|
||||
return true, email.GetSMTP(res, req, con.APILogger, con.Directory)
|
||||
default:
|
||||
return false, false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
var smtpModal = jQuery('.smtp-settings-modal');
|
||||
|
||||
jQuery('._js_smtp-credentials').on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'api/email/get_smtp', true);
|
||||
xhr.send();
|
||||
|
||||
xhr.onloadend = function() {
|
||||
if(xhr.status == 200) {
|
||||
var resp = JSON.parse(xhr.response);
|
||||
|
||||
if(resp["type"] == "crammd5") {
|
||||
jQuery('#smtpType').val(resp["type"]).change();
|
||||
}
|
||||
|
||||
jQuery('#smtpUsername').val(resp["username"]);
|
||||
jQuery('#smtpServer').val(resp["server"]);
|
||||
jQuery('#smtpPort').val(resp["port"]);
|
||||
}
|
||||
smtpModal.modal('show');
|
||||
}
|
||||
});
|
||||
|
||||
jQuery('._js_smtp-settings-form').on('submit', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var flag = false;
|
||||
jQuery(this).find('input').each(function(i){
|
||||
if(jQuery(this) && jQuery(this).val()) return true;
|
||||
else {
|
||||
flag = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if(flag) {
|
||||
alert('All inputs need to be filled out.');
|
||||
return;
|
||||
}
|
||||
|
||||
var requestData = {};
|
||||
requestData["type"] = jQuery(this).find('#smtpType').val();
|
||||
requestData["username"] = jQuery(this).find('#smtpUsername').val();
|
||||
requestData["password"] = jQuery(this).find('#smtpPassword').val();
|
||||
requestData["server"] = jQuery(this).find('#smtpServer').val();
|
||||
requestData["port"] = parseInt(jQuery(this).find('#smtpPort').val());
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(jQuery(this).attr('method'), jQuery(this).attr('action'), true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
xhr.send(JSON.stringify(requestData));
|
||||
|
||||
xhr.onloadend = function() {
|
||||
if(xhr.status == 204) {
|
||||
alert("New SMTP Settings Connect Successfully and are Saved.");
|
||||
}
|
||||
else {
|
||||
if(xhr.response != undefined && xhr.response.length != 0) {
|
||||
alert('Error: ' + xhr.response);
|
||||
}
|
||||
else {
|
||||
alert('An error has occurred, refresh and try again. If problem persists please contact your administrator.');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -44,6 +44,11 @@
|
|||
<input name="name" type="text" class="form-control" id="newBundleName" aria-describedby="newBundleNameHelp" placeholder="Bundle Name">
|
||||
<small id="newBundleNameHelp" class="form-text text-muted">Bundle name must be unqiue in terms of your current bundle collection.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="newBundleEmail">Bundle Client Email</label>
|
||||
<input name="email" type="text" class="form-control" id="newBundleEmail" aria-describedby="newBundleEmailHelp" placeholder="Bundle Client Email">
|
||||
<small id="newBundleEmailHelp" class="form-text text-muted">The client whose bundle this is will recieve an email with instructions and default username/password.</small>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="newBundleAccountPort">Bundle Account Port</label>
|
||||
<input name="account_port" type="number" class="form-control" id="newBundleAccountPort" aria-describedby="newBundleAccountPortHelp" min="2000" max="4000" value="2083">
|
||||
|
|
@ -278,6 +283,53 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SMTP Settings Modal -->
|
||||
<div class="modal fade smtp-settings-modal" tabindex="-1" role="dialog" aria-labelledby="smtp-settings-modal" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">SMTP Settings</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="_js_smtp-settings-form" action="api/email/set_smtp" method="POST">
|
||||
<div class="form-group">
|
||||
<label for="smtpType">Authentication Type</label>
|
||||
<select class="form-control" id="smtpType">
|
||||
<option selected value="plain">Plain</option>
|
||||
<option value="crammd5">CRAM-MD5</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="smtpUsername">Username</label>
|
||||
<input type="text" class="form-control" id="smtpUsername" placeholder="Username" value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="smtpPassword">Password</label>
|
||||
<input type="password" class="form-control" id="smtpPassword" placeholder="Password" value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="smtpServer">Server</label>
|
||||
<input type="text" class="form-control" id="smtpServer" placeholder="Server" value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="smtpPort">Port</label>
|
||||
<input type="number" class="form-control" id="smtpPort" aria-describedby="newBundleAccountPortHelp" min="0" max="65535" value="587">
|
||||
</div>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="submit" class="btn btn-primary">Test & Set SMTP Settings</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
|
|
@ -321,6 +373,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-5">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Server Settings</h4>
|
||||
<h6 class="card-subtitle mb-4 text-muted">Set or update various settings, such as smtp credentials, that the server uses</h6>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-outline-primary _js_smtp-credentials">SMTP Credentials</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="sticky-footer">
|
||||
|
|
@ -366,6 +432,8 @@
|
|||
<script type="text/javascript" src="assets/js/panelHandlers/users/new.js"></script>
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/users/delete.js"></script>
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/users/new_password.js"></script>
|
||||
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/settings/smtp.js"></script>
|
||||
<!-- KEEP AT BOTTOM OF BODY TAGS -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@
|
|||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" crossorigin="anonymous"></script>
|
||||
|
||||
<script type="text/javascript" src="assets/js/formHandlers/login.js"></script>
|
||||
<script type="text/javascript" src="assets/js/formHandlers/register.js"></script>
|
||||
<script type="text/javascript" src="assets/js/formHandlers/search.js"></script>
|
||||
<!-- KEEP AT BOTTOM OF BODY TAGS -->
|
||||
</body>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue