mirror of
https://github.com/donl/gPanel.git
synced 2026-05-25 22:06:55 -06:00
started implimenting domain manager
This commit is contained in:
parent
1ba13fd5d9
commit
aeff7c00c8
13 changed files with 405 additions and 1 deletions
20
account/assets/js/init.js
Normal file
20
account/assets/js/init.js
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* Store bundle name in global variable */
|
||||
var BUNDLE_NAME = "";
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'api/settings/name', true);
|
||||
xhr.send();
|
||||
|
||||
xhr.onloadend = function() {
|
||||
if(xhr.status == 200) {
|
||||
BUNDLE_NAME = xhr.response;
|
||||
}
|
||||
else {
|
||||
if (xhr.response != undefined && xhr.response.length != 0) {
|
||||
alert('Error getting bundle name: ' + xhr.status);
|
||||
}
|
||||
else {
|
||||
alert('An error has occurred while getting the bundle name. If problem persists please contact your community administrator.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
jQuery('._js_link-domain-form').on('submit', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
if(jQuery('#linkDomain') && jQuery('#linkDomain').val()) {
|
||||
var requestData = {};
|
||||
requestData["domain"] = jQuery('#linkDomain').val();
|
||||
requestData["name"] = BUNDLE_NAME;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open(jQuery(this).attr('method'), jQuery(this).attr('action'), true);
|
||||
xhr.send(JSON.stringify(requestData));
|
||||
|
||||
xhr.onloadend = function() {
|
||||
if(xhr.status == 204) {
|
||||
ListDomains(BUNDLE_NAME);
|
||||
}
|
||||
else {
|
||||
if(xhr.response != undefined && xhr.response.length != 0) {
|
||||
alert('Error: ' + xhr.status);
|
||||
}
|
||||
else {
|
||||
alert('An error has occurred. If problem persists please contact your community administrator.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
alert('The domain field must be filled out to submit this form.');
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
var domainManagementModal = jQuery('.domain-management-modal');
|
||||
|
||||
jQuery('._js_domain-management').on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
ListDomains(BUNDLE_NAME);
|
||||
domainManagementModal.modal('show');
|
||||
});
|
||||
|
||||
function ListDomains(bundle_name) {
|
||||
var list = jQuery('._js_registered-domains');
|
||||
|
||||
var requestData = {};
|
||||
requestData["name"] = bundle_name;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', 'api/domain/list', true);
|
||||
xhr.send(JSON.stringify(requestData));
|
||||
|
||||
xhr.onloadend = function() {
|
||||
list.html('');
|
||||
if(xhr.status == 200) {
|
||||
jsonResponse = JSON.parse(xhr.response)
|
||||
jQuery.each(jsonResponse, function(k, v) {
|
||||
list.append('<div class="row mt-2"><div class="col-6 d-flex align-items-center"><p class="mb-0">'+v+'</p></div><div class="col-6 d-flex justify-content-end"><div class="btn-group" role="group"><button class="btn btn-outline-danger _js_delete-registered-domain" data="'+v+'">Delete</button></div></div></div>');
|
||||
});
|
||||
}
|
||||
else if(xhr.status == 204) {
|
||||
list.html('<div class="row mt-2"><div class="col-6 d-flex align-items-center"><p>No registered domains exist for this account.</p></div></div>');
|
||||
}
|
||||
else {
|
||||
if(xhr.response != undefined && xhr.response.length != 0) {
|
||||
alert('Error: ' + xhr.status);
|
||||
}
|
||||
else {
|
||||
alert('An error has occurred. If problem persists please contact your community administrator.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
jQuery(document).on('click', '._js_delete-registered-domain', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var domain = jQuery(this).attr('data');
|
||||
var ensure = confirm("Are you sure you want to unlink the domain \""+ domain +"\" from your account?");
|
||||
|
||||
if(ensure) {
|
||||
var requestData = {};
|
||||
requestData["domain"] = domain;
|
||||
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('DELETE', 'api/domain/unlink', true);
|
||||
xhr.send(JSON.stringify(requestData));
|
||||
|
||||
xhr.onloadend = function () {
|
||||
if (xhr.status == 204) {
|
||||
ListDomains(BUNDLE_NAME);
|
||||
}
|
||||
else {
|
||||
if (xhr.response != undefined && xhr.response.length != 0) {
|
||||
alert('Error: ' + xhr.status);
|
||||
}
|
||||
else {
|
||||
alert('An error has occurred. If problem persists please contact your community administrator.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -27,7 +27,7 @@ function listCurrentUsers() {
|
|||
});
|
||||
}
|
||||
else {
|
||||
display.html('<p>An error has occurred, please refresh. If problem persists please contact your administrator.</p>');
|
||||
display.html('<div class="row mt-2"><div class="col-6 d-flex align-items-center"><p>An error has occurred, please refresh. If problem persists please contact your administrator.</p></div></div>');
|
||||
}
|
||||
}
|
||||
else if(xhr.status == 204) {
|
||||
|
|
|
|||
|
|
@ -185,6 +185,40 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Domain Management Modal -->
|
||||
<div class="modal fade domain-management-modal" tabindex="-1" role="dialog" aria-labelledby="domain-management-modal" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Domain Management</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="api/domain/link" class="_js_link-domain-form">
|
||||
<div class="form-group">
|
||||
<label for="linkDomain" class="sr-only">Register Domain</label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="linkDomain" class="form-control" placeholder="Domain">
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="submit" class="btn btn-primary">Register Domain</button>
|
||||
</div>
|
||||
</form>
|
||||
<h4 class="mt-3 mb-0">Registered Domains</h4>
|
||||
<div class="container-full _js_registered-domains">
|
||||
|
||||
</div>
|
||||
</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">
|
||||
|
|
@ -273,6 +307,20 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-5">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">Domains & Sub-domains</h4>
|
||||
<h6 class="card-subtitle mb-4 text-muted">View registered domains, register new domains, and set up or manage existing document roots for sub-domains.</h6>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-outline-primary _js_domain-management">Domain Management</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer class="sticky-footer">
|
||||
|
|
@ -293,6 +341,8 @@
|
|||
<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/init.js"></script>
|
||||
|
||||
<script type="text/javascript" src="assets/js/formHandlers/search.js"></script>
|
||||
<script type="text/javascript" src="assets/js/formHandlers/logout.js"></script>
|
||||
|
||||
|
|
@ -313,6 +363,10 @@
|
|||
<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/domains_subdomains/domain_management.js"></script>
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/domains_subdomains/domain_link.js"></script>
|
||||
<script type="text/javascript" src="assets/js/panelHandlers/domains_subdomains/domain_unlink.js"></script>
|
||||
<!-- KEEP AT BOTTOM OF BODY TAGS -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
50
pkg/api/domain/link.go
Normal file
50
pkg/api/domain/link.go
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"log"
|
||||
"strconv"
|
||||
"github.com/Ennovar/gPanel/pkg/database"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
func Link(res http.ResponseWriter, req *http.Request, logger *log.Logger) bool {
|
||||
if req.Method != "POST" {
|
||||
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 linkDomainReqData struct {
|
||||
Domain string `json:"domain"`
|
||||
Bundle string `json:"name"`
|
||||
}
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&linkDomainReqData)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
ds, err := database.Open("server/"+database.DB_DOMAINS)
|
||||
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 domainDatabaseData database.Struct_Domain
|
||||
domainDatabaseData.BundleName = linkDomainReqData.Bundle
|
||||
|
||||
err = ds.Put(database.BUCKET_DOMAINS, []byte(linkDomainReqData.Domain), domainDatabaseData)
|
||||
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
|
||||
}
|
||||
59
pkg/api/domain/list.go
Normal file
59
pkg/api/domain/list.go
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"log"
|
||||
"strconv"
|
||||
"encoding/json"
|
||||
"github.com/Ennovar/gPanel/pkg/database"
|
||||
)
|
||||
|
||||
func List(res http.ResponseWriter, req *http.Request, logger *log.Logger) bool {
|
||||
if req.Method != "POST" {
|
||||
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 listDomainsReqData struct {
|
||||
Bundle string `json:"name"`
|
||||
}
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&listDomainsReqData)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
ds, err := database.Open("server/" + database.DB_DOMAINS)
|
||||
if err != nil || ds == nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
defer ds.Close()
|
||||
|
||||
domains, err := ds.ListDomains(listDomainsReqData.Bundle)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusInternalServerError)
|
||||
return false
|
||||
}
|
||||
|
||||
if len(domains) > 0 {
|
||||
b, err := json.Marshal(domains)
|
||||
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
|
||||
}
|
||||
|
||||
res.WriteHeader(http.StatusNoContent)
|
||||
return true
|
||||
}
|
||||
46
pkg/api/domain/unlink.go
Normal file
46
pkg/api/domain/unlink.go
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"log"
|
||||
"strconv"
|
||||
"encoding/json"
|
||||
"github.com/Ennovar/gPanel/pkg/database"
|
||||
)
|
||||
|
||||
func Unlink(res http.ResponseWriter, req *http.Request, logger *log.Logger) bool {
|
||||
if req.Method != "DELETE" {
|
||||
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 unlinkDomainRequestData struct {
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
err := json.NewDecoder(req.Body).Decode(&unlinkDomainRequestData)
|
||||
if err != nil {
|
||||
logger.Println(req.URL.Path + "::" + err.Error())
|
||||
http.Error(res, err.Error(), http.StatusBadRequest)
|
||||
return false
|
||||
}
|
||||
|
||||
ds, err := database.Open("server/"+database.DB_DOMAINS)
|
||||
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.Delete(database.BUCKET_DOMAINS, []byte(unlinkDomainRequestData.Domain))
|
||||
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
|
||||
}
|
||||
23
pkg/api/settings/bundle_name.go
Normal file
23
pkg/api/settings/bundle_name.go
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package settings
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"log"
|
||||
)
|
||||
|
||||
func BundleName(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.StatusNotFound) + "::" + http.StatusText(http.StatusMethodNotAllowed))
|
||||
http.Error(res, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
||||
return false
|
||||
}
|
||||
|
||||
dir = strings.Replace(dir, "bundles/bundle_", "", 1)
|
||||
dir = strings.Replace(dir, "/", "", 1)
|
||||
|
||||
res.WriteHeader(http.StatusOK)
|
||||
res.Write([]byte(dir))
|
||||
return true
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import (
|
|||
const (
|
||||
DB_MAIN = "datastore.db"
|
||||
DB_SETTINGS = "settings.db"
|
||||
DB_DOMAINS = "domains.db"
|
||||
)
|
||||
|
||||
// Bucket constants
|
||||
|
|
@ -25,6 +26,9 @@ const (
|
|||
|
||||
// DB_SETTINGS BUCKETS
|
||||
BUCKET_GENERAL = "general"
|
||||
|
||||
// DB_DOMAINS BUCKETS
|
||||
BUCKET_DOMAINS = "domains"
|
||||
)
|
||||
|
||||
// Error codes
|
||||
|
|
@ -75,6 +79,13 @@ func Open(filepath string) (*Datastore, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if strings.HasSuffix(filepath, DB_DOMAINS) {
|
||||
_, err = tx.CreateBucketIfNotExists([]byte(BUCKET_DOMAINS))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
|
|
|
|||
32
pkg/database/domains.go
Normal file
32
pkg/database/domains.go
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"github.com/boltdb/bolt"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type Struct_Domain struct {
|
||||
BundleName string `json:"name"`
|
||||
}
|
||||
|
||||
func (ds *Datastore) ListDomains(bundle string) (map[string]string, error) {
|
||||
filtered := make(map[string]string)
|
||||
var holder Struct_Domain
|
||||
|
||||
ds.handle.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(BUCKET_DOMAINS))
|
||||
c := b.Cursor()
|
||||
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
json.Unmarshal(v, &holder)
|
||||
|
||||
if bundle == "*" || holder.BundleName == bundle {
|
||||
filtered[holder.BundleName] = string(k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return filtered, nil
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@ import (
|
|||
logapi "github.com/Ennovar/gPanel/pkg/api/log"
|
||||
"github.com/Ennovar/gPanel/pkg/api/server"
|
||||
"github.com/Ennovar/gPanel/pkg/api/user"
|
||||
"github.com/Ennovar/gPanel/pkg/api/domain"
|
||||
"github.com/Ennovar/gPanel/pkg/api/settings"
|
||||
)
|
||||
|
||||
func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request) (bool, bool) {
|
||||
|
|
@ -23,6 +25,8 @@ func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request) (b
|
|||
suspectApi := strings.ToLower(splitUrl[len(splitUrl)-1])
|
||||
|
||||
switch suspectApi {
|
||||
case "/settings/name":
|
||||
return true, settings.BundleName(res, req, con.APILogger, con.Directory)
|
||||
case "/user/auth":
|
||||
return true, user.Auth(res, req, con.APILogger, con.Directory)
|
||||
case "/user/register":
|
||||
|
|
@ -55,6 +59,12 @@ func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request) (b
|
|||
return true, ip.Filter(res, req, con.APILogger, con.Directory)
|
||||
case "/ip/unfilter":
|
||||
return true, ip.Unfilter(res, req, con.APILogger, con.Directory)
|
||||
case "/domain/list":
|
||||
return true, domain.List(res, req, con.APILogger)
|
||||
case "/domain/link":
|
||||
return true, domain.Link(res, req, con.APILogger)
|
||||
case "/domain/unlink":
|
||||
return true, domain.Unlink(res, req, con.APILogger)
|
||||
default:
|
||||
return false, false
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue