Added relations to redis ORM
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const {User} = require('../models/user');
|
||||
const {AuthToken} = require('../models/token');
|
||||
const Table = require('../models');
|
||||
const {User, AuthToken} = Table.models;
|
||||
|
||||
|
||||
class Auth{
|
||||
@@ -35,6 +35,7 @@ class Auth{
|
||||
|
||||
throw this.errors.login();
|
||||
}catch(error){
|
||||
console.log('check error', error);
|
||||
throw this.errors.login();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const {Auth} = require('../controller/auth');
|
||||
async function auth(req, res, next){
|
||||
try{
|
||||
req.token = await Auth.checkToken(req.header('auth-token'));
|
||||
req.user = await req.token.getUser();
|
||||
req.user = req.token.user;
|
||||
return next();
|
||||
}catch(error){
|
||||
next(error);
|
||||
@@ -15,7 +15,7 @@ async function auth(req, res, next){
|
||||
async function authIO(socket, next){
|
||||
try{
|
||||
let token = await Auth.checkToken(socket.handshake.auth.token || 0);
|
||||
socket.user = await token.getUser();
|
||||
socket.user = token.user;
|
||||
next();
|
||||
}catch(error){
|
||||
next(error);
|
||||
|
||||
@@ -9,9 +9,9 @@ const ModelPs = require('../utils/model_pubsub');
|
||||
const tldExtract = require('tld-extract').parse_host;
|
||||
|
||||
const providers = {
|
||||
PorkBun: require('./dns_provider/porkbun'),
|
||||
DigitalOcean: require('./dns_provider/digitalocean'),
|
||||
Cloudflare: require('./dns_provider/cloudflare'),
|
||||
DigitalOcean: require('./dns_provider/digitalocean'),
|
||||
PorkBun: require('./dns_provider/porkbun'),
|
||||
};
|
||||
|
||||
class Domain extends Table{
|
||||
@@ -23,17 +23,22 @@ class Domain extends Table{
|
||||
'updated_on': {default: function(){return (new Date).getTime()}, always: true},
|
||||
'domain': {isRequired: true, type: 'string'},
|
||||
'dnsProvider_id': {isRequired: true, type: 'string'},
|
||||
'provider': {model: 'DnsProvider', rel:'one', localKey: 'dnsProvider_id'},
|
||||
'zoneId': {isRequired: false, type: 'string'},
|
||||
}
|
||||
|
||||
static async get(data, ...args){
|
||||
let instance = await super.get(data, ...args);
|
||||
// instance.provider = (await DnsProvider.get(instance.dnsProvider_id)).provider;
|
||||
static async get(domain, ...args){
|
||||
try{
|
||||
domain = tldExtract(domain).domain;
|
||||
}catch{}
|
||||
|
||||
let instance = await super.get(domain, ...args);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
static async getByProviderId(id){
|
||||
let domains = await this.listDetail();
|
||||
static async getByProviderId(id, ...args){
|
||||
let domains = await this.listDetail(...args);
|
||||
let results = [];
|
||||
for(let domain of domains){
|
||||
if(domain.dnsProvider_id == id) results.push(domain);
|
||||
@@ -41,8 +46,21 @@ class Domain extends Table{
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// toJSON(){
|
||||
// return {
|
||||
// ...super.toJSON(),
|
||||
// provider: {
|
||||
// displayName: this.provider.constructor.displayName,
|
||||
// displayIconUni: this.provider.constructor.displayIconUni,
|
||||
// displayIconHtml: this.provider.constructor.displayIconHtml,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
Domain.register(ModelPs(Domain))
|
||||
|
||||
class DnsProvider extends Table{
|
||||
static _key = 'id';
|
||||
static _keyMap = {
|
||||
@@ -53,7 +71,7 @@ class DnsProvider extends Table{
|
||||
'id': {default: ()=>crypto.randomBytes(8).toString("hex")},
|
||||
'name': {isRequired: true, type: 'string'},
|
||||
'dnsProvider': {isRequired: true, type: 'string'},
|
||||
'zoneId': {isRequired: false, type: 'string'},
|
||||
'domains': {model:'Domain', rel: 'many', remoteKey: 'dnsProvider_id'}
|
||||
}
|
||||
|
||||
static __intraModel(provider){
|
||||
@@ -74,23 +92,16 @@ class DnsProvider extends Table{
|
||||
|
||||
static async create(data, ...args){
|
||||
let __intraModel = this.__intraModel(data.dnsProvider)
|
||||
let provider = new __intraModel.Provider(data);
|
||||
let res = await provider.listDomains();
|
||||
let provider = new __intraModel.Provider(data, ...args);
|
||||
|
||||
let instance = await super.create.call(__intraModel, data);
|
||||
if(data.noUpdate !== false) await instance.updateDomains();
|
||||
|
||||
return instance;
|
||||
return await super.create.call(__intraModel, data, ...args);
|
||||
}
|
||||
|
||||
static async get(data, ...args){
|
||||
let instance = await super.get(data);
|
||||
let instance = await super.get(data, ...args);
|
||||
let __intraModel = this.__intraModel(instance.dnsProvider)
|
||||
|
||||
instance = await super.get.call(__intraModel, data);
|
||||
instance.provider = new __intraModel.Provider(instance);
|
||||
|
||||
return instance;
|
||||
return await super.get.call(__intraModel, data, ...args);
|
||||
}
|
||||
|
||||
static listProviders(){
|
||||
@@ -138,24 +149,33 @@ class DnsProvider extends Table{
|
||||
toJSON(){
|
||||
return {
|
||||
...super.toJSON(),
|
||||
displayName: this.provider.constructor.displayName,
|
||||
displayIconHtml: this.provider.constructor.displayIconHtml,
|
||||
displayIconUni: this.provider.constructor.displayIconUni,
|
||||
...this.constructor.Provider.toJSON()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Domain = ModelPs(Domain);
|
||||
DnsProvider = ModelPs(DnsProvider);
|
||||
DnsProvider.register(ModelPs(DnsProvider))
|
||||
|
||||
module.exports = {Domain, DnsProvider};
|
||||
|
||||
if(require.main === module){(async function(){try{
|
||||
const conf = require('../conf');
|
||||
|
||||
console.log(Table.models)
|
||||
|
||||
// console.log(await Domain.listDetail())
|
||||
|
||||
// console.log(JSON.stringify(await Domain.get('ipa.wtf'), null, 2))
|
||||
|
||||
// console.log(JSON.stringify(await Domain.listDetail() ,null, 2))
|
||||
console.log(JSON.stringify(await Table.models.DnsProvider.listDetail() ,null, 2))
|
||||
|
||||
|
||||
// console.log(await Domain.getByProviderId('e8443e03ac503c7b'));
|
||||
|
||||
// console.log(aw)
|
||||
|
||||
process.exit(0)
|
||||
|
||||
}catch(error){
|
||||
console.log('IIFE Error:', error);
|
||||
}})()}
|
||||
@@ -1,28 +1,29 @@
|
||||
'use strict';
|
||||
|
||||
const axios = require('axios');
|
||||
const {dnsErrors} = require('./common');
|
||||
const {dnsErrors, DnsApi} = require('./common');
|
||||
|
||||
//like the options obj will always use domain data and type
|
||||
// change content to data
|
||||
// change name to domain
|
||||
|
||||
|
||||
class CloudFlare{
|
||||
class CloudFlare extends DnsApi{
|
||||
static _keyMap = {
|
||||
token: {isRequired: true, type: 'string', isPrivate: true, displayName: 'API Token'},
|
||||
}
|
||||
|
||||
static displayName = 'CloudFlare'
|
||||
static displayIconHtml = `
|
||||
<svg width="32px" height="32px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="512" cy="512" r="512" style="fill:#0080ff"/>
|
||||
<path d="m273.8 669.2-.1-63.7h63.7v63.7h76v-98.8h98.8v98.5c105.1-.1 186.2-104.1 146.1-214.6-14.9-40.9-47.6-73.6-88.5-88.4-110.7-40.2-214.7 41.2-214.7 146.3H256c0-167.5 161.8-298 337.4-243.2 76.8 24 137.7 84.9 161.6 161.6C809.9 606.2 679.4 768 511.9 768v-98.8h-98.6v75.9h-75.9v-75.9h-63.6z" style="fill:#fff"/>
|
||||
</svg>`
|
||||
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="512" cy="512" r="512" style="fill:#f38020"/>
|
||||
<path d="M608.2 592.4c3.1-10.8 1.9-20.7-3.3-28.1-4.8-6.7-12.9-10.6-22.6-11.1l-184.7-2.4c-1.1 0-2.2-.6-2.8-1.5-.6-.9-.7-2.1-.4-3.3.6-1.8 2.4-3.2 4.3-3.3l186.4-2.4c22.1-1 46.1-18.9 54.5-40.8l10.6-27.8c.5-1.2.6-2.4.3-3.6-12-54.3-60.5-94.8-118.4-94.8-53.4 0-98.7 34.5-114.9 82.4-10.5-7.8-23.9-12-38.3-10.6-25.7 2.5-46.2 23.1-48.8 48.8-.6 6.6-.1 13.1 1.4 19.1-41.9 1.2-75.3 35.4-75.3 77.6 0 3.7.3 7.5.8 11.2.3 1.8 1.8 3.1 3.6 3.1h340.9c1.9 0 3.8-1.4 4.3-3.3l2.4-9.2zM667 473.7c-1.6 0-3.4 0-5.1.2-1.2 0-2.2.9-2.7 2.1l-7.2 25c-3.1 10.8-2 20.7 3.3 28.1 4.8 6.7 12.9 10.6 22.7 11.1l39.3 2.4c1.2 0 2.3.6 2.8 1.5.6.9.7 2.3.5 3.3-.6 1.8-2.4 3.2-4.4 3.3l-41 2.4c-22.2 1-46 18.9-54.5 40.8l-3 7.6c-.6 1.5.5 3 2.1 3h140.8c1.6 0 3.1-1 3.6-2.7 2.4-8.7 3.7-17.9 3.7-27.3 0-55.5-45.3-100.8-101-100.8" style="fill:#fff"/>
|
||||
</svg>`
|
||||
// Cloud icon for cloudflare
|
||||
static displayIconUni = ''
|
||||
|
||||
constructor(token){
|
||||
super()
|
||||
this.token = token.token || token;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,52 @@ let dnsErrors = {
|
||||
},
|
||||
}
|
||||
|
||||
class DnsApi{
|
||||
errors = {
|
||||
unauthorized(instance){
|
||||
let error = new Error('UnauthorizedDnsApi');
|
||||
error.name = 'UnauthorizedDnsApi';
|
||||
error.message = `Unauthorized call to ${instance.constructor ? instance.constructor.name : instance.name}`;
|
||||
error.status = 424;
|
||||
|
||||
return error;
|
||||
},
|
||||
other(instance, status, message){
|
||||
let error = new Error('OtherDnsApiError');
|
||||
error.name = 'OtherDnsApiError';
|
||||
error.message = `DNS API Error ${instance.constructor ? instance.constructor.name : instance.name}: `;
|
||||
error.status = 424;
|
||||
|
||||
return error;
|
||||
},
|
||||
}
|
||||
|
||||
static info(){
|
||||
let svgDataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(this.displayIconHtml)
|
||||
.replace(/'/g, '%27')
|
||||
.replace(/"/g, '%22')}`
|
||||
|
||||
return {
|
||||
displayName: this.displayName,
|
||||
displayIconUni: this.displayIconUni,
|
||||
displayIconHtml: svgDataUrl,
|
||||
fields: this._keyMap,
|
||||
}
|
||||
}
|
||||
|
||||
static toJSON(){
|
||||
return {
|
||||
...this.info(),
|
||||
}
|
||||
}
|
||||
|
||||
toJSON(){
|
||||
return this.constructor.toJSON()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
dnsErrors
|
||||
dnsErrors,
|
||||
DnsApi,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const axios = require('axios');
|
||||
const {dnsErrors} = require('./common');
|
||||
const {dnsErrors, DnsApi} = require('./common');
|
||||
|
||||
class DigitalOcean{
|
||||
class DigitalOcean extends DnsApi{
|
||||
static _keyMap = {
|
||||
token: {isRequired: true, type: 'string', isPrivate: true, displayName: 'API Token'},
|
||||
}
|
||||
|
||||
static displayName = 'DigitalOcean'
|
||||
static displayIconHtml = `
|
||||
<svg width="32px" height="32px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg height="100%" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="512" cy="512" r="512" style="fill:#0080ff"/>
|
||||
<path d="m273.8 669.2-.1-63.7h63.7v63.7h76v-98.8h98.8v98.5c105.1-.1 186.2-104.1 146.1-214.6-14.9-40.9-47.6-73.6-88.5-88.4-110.7-40.2-214.7 41.2-214.7 146.3H256c0-167.5 161.8-298 337.4-243.2 76.8 24 137.7 84.9 161.6 161.6C809.9 606.2 679.4 768 511.9 768v-98.8h-98.6v75.9h-75.9v-75.9h-63.6z" style="fill:#fff"/>
|
||||
</svg>`
|
||||
@@ -18,6 +18,7 @@ class DigitalOcean{
|
||||
static displayIconUni = ''
|
||||
|
||||
constructor(token){
|
||||
super()
|
||||
this.token = token.token || token;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const axios = require('axios');
|
||||
const {dnsErrors} = require('./common');
|
||||
const {dnsErrors, DnsApi} = require('./common');
|
||||
|
||||
|
||||
class PorkBun{
|
||||
class PorkBun extends DnsApi{
|
||||
static _keyMap = {
|
||||
'apiKey': {isRequired: true, type: 'string', isPrivate: true, displayName: 'API key'},
|
||||
'secretApiKey': {isRequired: true, type: 'string', isPrivate: true, displayName: 'API Secret key'},
|
||||
}
|
||||
|
||||
static displayName = 'DigitalOcean';
|
||||
static displayName = 'PorkBun';
|
||||
static displayIconUni = '';
|
||||
static displayIconHtml = `
|
||||
<svg width="32px" height="32px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.st1{fill:#fff}
|
||||
</style>
|
||||
@@ -24,12 +25,9 @@ class PorkBun{
|
||||
</g>
|
||||
</g>
|
||||
</svg>`
|
||||
// '<i class="fa-solid fa-bacon"></i>';
|
||||
static displayIconUni = '';
|
||||
|
||||
baseUrl = 'https://api.porkbun.com/api/json/v3';
|
||||
|
||||
constructor(args){
|
||||
super()
|
||||
this.apiKey = args.apiKey;
|
||||
this.secretApiKey = args.secretApiKey;
|
||||
}
|
||||
@@ -42,7 +40,7 @@ class PorkBun{
|
||||
secretapikey: this.secretApiKey,
|
||||
apikey: this.apiKey,
|
||||
};
|
||||
res = await axios.post(`${this.baseUrl}${url}`, data);
|
||||
res = await axios.post(`'https://api.porkbun.com/api/json/v3'${url}`, data);
|
||||
|
||||
return res;
|
||||
}catch(error){
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const Table = require('../utils/redis_model');
|
||||
const Table = require('.');
|
||||
const ModelPs = require('../utils/model_pubsub');
|
||||
|
||||
const tldExtract = require('tld-extract').parse_host;
|
||||
const PorkBun = require('./dns_provider/porkbun');
|
||||
const LetsEncrypt = require('../utils/letsencrypt');
|
||||
const conf = require('../conf');
|
||||
|
||||
// let porkBun = new PorkBun(conf.porkBun.apiKey, conf.porkBun.secretApiKey);
|
||||
// let letsEncrypt = new LetsEncrypt({
|
||||
// directoryUrl: LetsEncrypt.AcmeClient.directory.letsencrypt.staging,
|
||||
// });
|
||||
|
||||
|
||||
class Host extends Table{
|
||||
static _key = 'host';
|
||||
@@ -31,6 +25,7 @@ class Host extends Table{
|
||||
'wildcard_status': {isRequired: false, type: 'string', min: 3, max: 500, default: 'Requesting'},
|
||||
'wildcard_parent': {isRequired: false, type: 'string', min: 3, max: 500},
|
||||
'wildcard_expires': {isRequired: false, type: 'number'},
|
||||
'domain': {model: 'Domain', rel: 'one'},
|
||||
}
|
||||
|
||||
static lookUpObj = {};
|
||||
@@ -322,6 +317,7 @@ class Host extends Table{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Host.register(ModelPs(Host))
|
||||
|
||||
|
||||
class Cached extends Table{
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const Table = require('../utils/redis_model')
|
||||
module.exports = Table;
|
||||
|
||||
require('./dns_provider');
|
||||
require('./host');
|
||||
require('./token');
|
||||
require('./user');
|
||||
+10
-11
@@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const Table = require('../utils/redis_model');
|
||||
const {User} = require('./user');
|
||||
const Table = require('.');
|
||||
const UUID = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)};
|
||||
|
||||
|
||||
@@ -11,8 +10,8 @@ class Token extends Table{
|
||||
'created_by': {isRequired: true, type: 'string', min: 3, max: 500},
|
||||
'created_on': {default: function(){return (new Date).getTime()}},
|
||||
'updated_on': {default: function(){return (new Date).getTime()}, always: true},
|
||||
'token': {default: UUID, type: 'string', min: 36, max: 36},
|
||||
'is_valid': {default: true, type: 'boolean'}
|
||||
'token': {default: UUID, type: 'string', min: 36, max: 36, isPrivate: true},
|
||||
'is_valid': {default: true, type: 'boolean'},
|
||||
}
|
||||
|
||||
constructor(...args){
|
||||
@@ -28,13 +27,12 @@ class Token extends Table{
|
||||
}
|
||||
}
|
||||
|
||||
class AuthToken extends Token{
|
||||
constructor(...args){
|
||||
super(...args);
|
||||
}
|
||||
Token.register();
|
||||
|
||||
async getUser(){
|
||||
return await User.get(this.created_by);
|
||||
class AuthToken extends Token{
|
||||
static _keyMap = {
|
||||
...super._keyMap,
|
||||
user: {model: 'User', rel: 'one', localKey: 'created_by'},
|
||||
}
|
||||
|
||||
static async create(data){
|
||||
@@ -42,8 +40,8 @@ class AuthToken extends Token{
|
||||
return super.create(data)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
AuthToken.register();
|
||||
|
||||
class InviteToken extends Token{
|
||||
static _keyMap = {
|
||||
@@ -66,5 +64,6 @@ class InviteToken extends Token{
|
||||
}
|
||||
}
|
||||
}
|
||||
InviteToken.register();
|
||||
|
||||
module.exports = {Token, InviteToken, AuthToken};
|
||||
|
||||
@@ -58,12 +58,9 @@ class User extends Table{
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = {User};
|
||||
|
||||
User.register();
|
||||
|
||||
(async function(){
|
||||
var defaultUser = 'proxyadmin2'
|
||||
|
||||
@@ -264,7 +264,7 @@ MIT license
|
||||
return {
|
||||
...this.__parseData(data),
|
||||
nestedTemplates: this.__parseNestedTemplates(index, data),
|
||||
_parent: this.__jqParent ? $.scope[this.__jqParent][this.__jqParentIndex] : undefined,
|
||||
_parent: this._parentData,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -307,6 +307,7 @@ MIT license
|
||||
result.__index = $this.attr('jq-repeat-index');
|
||||
|
||||
if($this.attr('jq-repeat-parent')){
|
||||
result._parentData = $.scope[$this.attr('jq-repeat-parent')][$this.attr('jq-repeat-parent-index')]
|
||||
result.__jqParent = $this.attr('jq-repeat-parent');
|
||||
result.__jqParentIndex = $this.attr('jq-repeat-parent-index');
|
||||
}
|
||||
|
||||
+12
-1
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const router = require('express').Router();
|
||||
const {DnsProvider, Domain} = require('../models/dnsProvider');
|
||||
const {DnsProvider, Domain} = require('../models').models;
|
||||
|
||||
const Model = DnsProvider;
|
||||
|
||||
@@ -49,6 +49,7 @@ router.get('/domain', async function(req, res, next){
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
router.get('/domain/byProvider/:item', async function(req, res, next){
|
||||
try{
|
||||
return res.json({
|
||||
@@ -68,6 +69,16 @@ router.post('/domain/refresh/:item', async function(req, res, next){
|
||||
}
|
||||
})
|
||||
|
||||
router.get('/domain/:item', async function(req, res, next){
|
||||
try{
|
||||
return res.json({
|
||||
results: [await Domain.get(req.params.item)]
|
||||
});
|
||||
}catch(error){
|
||||
return next(error);
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/:item', async function(req, res, next){
|
||||
try{
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const router = require('express').Router();
|
||||
const {Host} = require('../models/host');
|
||||
const {Host, Domain} = require('../models').models;
|
||||
|
||||
const Model = Host;
|
||||
|
||||
router.get('/', async function(req, res, next){
|
||||
try{
|
||||
return res.json({
|
||||
hosts: await Model[req.query.detail ? "listDetail" : "list"]()
|
||||
results: await Model[req.query.detail ? "listDetail" : "list"](),
|
||||
});
|
||||
}catch(error){
|
||||
return next(error);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const router = require('express').Router();
|
||||
const {User} = require('../models/user');
|
||||
const {User} = require('../models').models;
|
||||
|
||||
router.get('/', async function(req, res, next){
|
||||
try{
|
||||
|
||||
@@ -22,10 +22,8 @@ function ModelPs(model){
|
||||
}
|
||||
|
||||
return new Proxy(model, {
|
||||
construct(target, args) {
|
||||
let instance = ModelPs(new model(...args));
|
||||
|
||||
return instance;
|
||||
construct(target, args, newTarget) {
|
||||
return ModelPs(Reflect.construct(target, args, newTarget))
|
||||
},
|
||||
get(target, propKey, receiver) {
|
||||
if(propKey == 'constructor') return target.constructor;
|
||||
@@ -46,7 +44,7 @@ function ModelPs(model){
|
||||
}
|
||||
return res;
|
||||
}catch(error){
|
||||
console.log("grrrr")
|
||||
console.log("grrrr", error)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -5,14 +5,37 @@ const objValidate = require('../utils/object_validate');
|
||||
const conf = require('../conf');
|
||||
|
||||
const client = createClient({});
|
||||
client.connect()
|
||||
client.connect();
|
||||
|
||||
function redisPrefix(key){
|
||||
return `${conf.redis.prefix}${key}`;
|
||||
}
|
||||
|
||||
class QueryHelper{
|
||||
hisroty = []
|
||||
constructor(orgin){
|
||||
this.orgin = orgin
|
||||
this.hisroty.push(orgin.constructor.name);
|
||||
}
|
||||
|
||||
static isNotCycle(modleName, queryHelper){
|
||||
if(queryHelper instanceof this){
|
||||
if(queryHelper.hisroty.includes(modleName)){
|
||||
return true;
|
||||
}
|
||||
queryHelper.hisroty.push(modleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Table{
|
||||
static redisClient = client;
|
||||
|
||||
static models = {}
|
||||
static register = function(Model){
|
||||
Model = Model || this;
|
||||
this.models[Model.name] = Model;
|
||||
}
|
||||
|
||||
constructor(data){
|
||||
for(let key in data){
|
||||
@@ -20,9 +43,8 @@ class Table{
|
||||
}
|
||||
}
|
||||
|
||||
static async get(index){
|
||||
static async get(index, queryHelper){
|
||||
try{
|
||||
|
||||
if(typeof index === 'object'){
|
||||
index = index[this._key];
|
||||
}
|
||||
@@ -43,13 +65,37 @@ class Table{
|
||||
// back to native values.
|
||||
result = objValidate.parseFromString(this._keyMap, result);
|
||||
|
||||
return new this(result);
|
||||
|
||||
let instance = new this(result);
|
||||
await instance.buildRelations(queryHelper);
|
||||
|
||||
return instance;
|
||||
}catch(error){
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async buildRelations(queryHelper){
|
||||
|
||||
for(let [key, options] of Object.entries(this.constructor._keyMap)){
|
||||
if(options.model){
|
||||
let remoteModel = this.constructor.models[options.model]
|
||||
try{
|
||||
if(QueryHelper.isNotCycle(remoteModel.name, queryHelper)) continue;
|
||||
if(options.rel === 'one'){
|
||||
// console.log('relone:', this[key], queryHelper, remoteModel, await remoteModel.get(this[key], queryHelper || new QueryHelper(this)))
|
||||
this[key] = await remoteModel.get(this[key] || this[options.localKey || this.constructor._key] , queryHelper || new QueryHelper(this))
|
||||
}
|
||||
if(options.rel === 'many'){
|
||||
this[key] = await remoteModel.listDetail({
|
||||
[options.remoteKey]: this[options.localKey || this.constructor._key],
|
||||
},queryHelper || new QueryHelper(this))
|
||||
|
||||
}
|
||||
}catch{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async exists(index){
|
||||
if(typeof index === 'object'){
|
||||
index = index[this._key];
|
||||
@@ -73,12 +119,21 @@ class Table{
|
||||
}
|
||||
}
|
||||
|
||||
static async listDetail(){
|
||||
static async listDetail(options, queryHelper){
|
||||
|
||||
// Return a list of the entries as instances.
|
||||
let out = [];
|
||||
|
||||
for(let entry of await this.list()){
|
||||
out.push(await this.get(entry));
|
||||
let instance = await this.get(entry, arguments[arguments.length - 1]);
|
||||
if(!options) out.push(instance);
|
||||
let matchCount = 0;
|
||||
for(let option in options){
|
||||
if(instance[option] === options[option] && ++matchCount === Object.keys(options).length){
|
||||
out.push(instance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
@@ -213,8 +268,9 @@ class Table{
|
||||
|
||||
toJSON(){
|
||||
let result = {};
|
||||
for (const [key, keyProps] of Object.entries(this.constructor._keyMap)) {
|
||||
if(!keyProps.isPrivate) result[key] = this[key];
|
||||
for (const [key, value] of Object.entries(this)) {
|
||||
if(this.constructor._keyMap[key] && this.constructor._keyMap[key].isPrivate) continue;
|
||||
result[key] = value;
|
||||
}
|
||||
|
||||
return result
|
||||
@@ -222,6 +278,10 @@ class Table{
|
||||
// return JSON.stringify(result);
|
||||
}
|
||||
|
||||
toString(){
|
||||
return this[this.constructor._key];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+5
-12
@@ -59,16 +59,10 @@
|
||||
|
||||
$.scope.DnsProvider.parseData = function(row){
|
||||
row['created_on_text'] = moment(row['updated_on'], "x").fromNow();
|
||||
|
||||
row['domainsString'] = JSON.stringify(row.domains);
|
||||
return row
|
||||
};
|
||||
|
||||
(async function(){
|
||||
|
||||
})()
|
||||
|
||||
|
||||
|
||||
$(document).ready(async function(){
|
||||
// Set the jq Templates
|
||||
$.scope.providerField.put = function(){};
|
||||
@@ -102,7 +96,6 @@
|
||||
$.scope[Model].update(pk, data)
|
||||
}catch{}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -182,7 +175,7 @@
|
||||
<li jq-repeat="DnsProvider" jq-repeat-index="id" style="display:none" class="list-group-item" onload="provider">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<h3>{{{ displayIconHtml }}} {{ dnsProvider }}</h3>
|
||||
<h3><img height="32px" src="{{ displayIconHtml }}"/> {{ dnsProvider }}</h3>
|
||||
<h4>{{ name }}</h4>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
@@ -200,9 +193,9 @@
|
||||
{{domain}}
|
||||
</b>
|
||||
<script type="text/javascript">
|
||||
app.api.get(`dns/domain/byProvider/{{id}}`, function(error, domains){
|
||||
$.scope.Domain_{{id}}.push(...domains.results);
|
||||
});
|
||||
try{
|
||||
$.scope.Domain_{{id}}.push(...{{{domainsString}}});
|
||||
}catch{}
|
||||
</script>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -62,10 +62,10 @@
|
||||
}
|
||||
|
||||
function hostPopulate(){
|
||||
app.host.list(function(error, res){
|
||||
app.api.get('host?detail=1&provider=1', function(error, res){
|
||||
if(error) return app.util.actionMessage(error, $.scope.hosts.$this, 'danger');
|
||||
|
||||
for(let host of res){
|
||||
for(let host of res.results){
|
||||
$.scope.hosts.push(hostParseRow(host));
|
||||
}
|
||||
|
||||
@@ -150,9 +150,9 @@
|
||||
$el.slideUp();
|
||||
};
|
||||
|
||||
// app.subscribe(/^model:Host/, function(data, topic){
|
||||
// console.log(topic, data);
|
||||
// });
|
||||
app.subscribe(/^model:Host/, function(data, topic){
|
||||
console.log(topic, data);
|
||||
});
|
||||
|
||||
app.subscribe(/^model:Host:create/, function(data, topic){
|
||||
let [a,b, action, host] = topic.split(':');
|
||||
@@ -391,6 +391,10 @@
|
||||
<a target="_blank" href="{{ forcessl_text }}{{ host }}">
|
||||
{{{ forcessl_text }}}{{ host }}
|
||||
</a>
|
||||
{{#domain.provider}}
|
||||
<br />
|
||||
<img width="24px" src="{{displayIconHtml}}" /> {{displayName}}
|
||||
{{/domain.provider}}
|
||||
</td>
|
||||
<td>
|
||||
{{{ targetssl_text }}}{{ ip }}:{{ targetPort }}
|
||||
|
||||
@@ -31,55 +31,11 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<!-- <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">Navbar</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="#">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Link</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Dropdown
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||
<li><a class="dropdown-item" href="#">Action</a></li>
|
||||
<li><a class="dropdown-item" href="#">Another action</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="#">Something else here</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link disabled">Disabled</a>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="d-flex" role="search">
|
||||
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
|
||||
<button class="btn btn-outline-success" type="submit">Search</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</nav> -->
|
||||
|
||||
|
||||
|
||||
|
||||
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
|
||||
<a class="navbar-brand" href="#">Dynamic Proxy <%- title %></a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<!-- <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button> -->
|
||||
<div class="collapse navbar-collapse justify-content-end" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav top-nav">
|
||||
<li class="nav-item">
|
||||
|
||||
Reference in New Issue
Block a user