mirror of
https://github.com/xiaoxinpro/nginx-proxy-manager-zh.git
synced 2025-02-02 17:58:13 -05:00
Convert db backend to use Gorm, with basis for support
for Mysql and Postgres in addition to existing Sqlite
This commit is contained in:
parent
b4e5b8b6db
commit
29990110b1
@ -30,7 +30,7 @@ tasks:
|
|||||||
silent: true
|
silent: true
|
||||||
- cmd: rm -f dist/bin/*
|
- cmd: rm -f dist/bin/*
|
||||||
silent: true
|
silent: true
|
||||||
- cmd: go build -buildvcs=false -ldflags="-X main.commit={{.GIT_COMMIT}} -X main.version={{.VERSION}}" -o ../dist/bin/server ./cmd/server/main.go
|
- cmd: go build -tags 'json1' -buildvcs=false -ldflags="-X main.commit={{.GIT_COMMIT}} -X main.version={{.VERSION}}" -o ../dist/bin/server ./cmd/server/main.go
|
||||||
silent: true
|
silent: true
|
||||||
- cmd: go build -buildvcs=false -ldflags="-X main.commit={{.GIT_COMMIT}} -X main.version={{.VERSION}}" -o ../dist/bin/ipranges ./cmd/ipranges/main.go
|
- cmd: go build -buildvcs=false -ldflags="-X main.commit={{.GIT_COMMIT}} -X main.version={{.VERSION}}" -o ../dist/bin/ipranges ./cmd/ipranges/main.go
|
||||||
silent: true
|
silent: true
|
||||||
|
@ -11,6 +11,8 @@ import (
|
|||||||
"npm/internal/entity/certificate"
|
"npm/internal/entity/certificate"
|
||||||
"npm/internal/entity/host"
|
"npm/internal/entity/host"
|
||||||
"npm/internal/entity/setting"
|
"npm/internal/entity/setting"
|
||||||
|
"npm/internal/entity/user"
|
||||||
|
"npm/internal/errors"
|
||||||
"npm/internal/jobqueue"
|
"npm/internal/jobqueue"
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
)
|
)
|
||||||
@ -25,7 +27,7 @@ func main() {
|
|||||||
|
|
||||||
database.Migrate(func() {
|
database.Migrate(func() {
|
||||||
setting.ApplySettings()
|
setting.ApplySettings()
|
||||||
database.CheckSetup()
|
checkSetup()
|
||||||
|
|
||||||
// Internal Job Queue
|
// Internal Job Queue
|
||||||
jobqueue.Start()
|
jobqueue.Start()
|
||||||
@ -41,7 +43,8 @@ func main() {
|
|||||||
if irq == syscall.SIGINT || irq == syscall.SIGTERM {
|
if irq == syscall.SIGINT || irq == syscall.SIGTERM {
|
||||||
logger.Info("Got ", irq, " shutting server down ...")
|
logger.Info("Got ", irq, " shutting server down ...")
|
||||||
// Close db
|
// Close db
|
||||||
err := database.GetInstance().Close()
|
sqlDB, _ := database.GetDB().DB()
|
||||||
|
err := sqlDB.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("DatabaseCloseError", err)
|
logger.Error("DatabaseCloseError", err)
|
||||||
}
|
}
|
||||||
@ -52,3 +55,28 @@ func main() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkSetup Quick check by counting the number of users in the database
|
||||||
|
func checkSetup() {
|
||||||
|
db := database.GetDB()
|
||||||
|
var count int64
|
||||||
|
|
||||||
|
if db != nil {
|
||||||
|
db.Model(&user.Model{}).
|
||||||
|
Where("is_disabled = ?", false).
|
||||||
|
Where("is_system = ?", false).
|
||||||
|
Count(&count)
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
logger.Warn("No users found, starting in Setup Mode")
|
||||||
|
} else {
|
||||||
|
config.IsSetup = true
|
||||||
|
logger.Info("Application is setup")
|
||||||
|
}
|
||||||
|
if config.ErrorReporting {
|
||||||
|
logger.Warn("Error reporting is enabled - Application Errors WILL be sent to Sentry, you can disable this in the Settings interface")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.Error("DatabaseError", errors.ErrDatabaseUnavailable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3
backend/db/schema.sql
Normal file
3
backend/db/schema.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
INSERT INTO "schema_migrations" (version) VALUES
|
||||||
|
('20201013035318'),
|
||||||
|
('20201013035839');
|
@ -14,7 +14,7 @@ var Assets embed.FS
|
|||||||
|
|
||||||
// MigrationFiles are database migrations
|
// MigrationFiles are database migrations
|
||||||
//
|
//
|
||||||
//go:embed migrations/*.sql
|
//go:embed migrations
|
||||||
var MigrationFiles embed.FS
|
var MigrationFiles embed.FS
|
||||||
|
|
||||||
// NginxFiles hold nginx config templates
|
// NginxFiles hold nginx config templates
|
||||||
|
@ -3,40 +3,39 @@
|
|||||||
CREATE TABLE IF NOT EXISTS `user`
|
CREATE TABLE IF NOT EXISTS `user`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
nickname TEXT NOT NULL,
|
nickname TEXT NOT NULL,
|
||||||
email TEXT NOT NULL,
|
email TEXT NOT NULL,
|
||||||
is_system INTEGER NOT NULL DEFAULT 0,
|
is_system INTEGER NOT NULL DEFAULT 0,
|
||||||
is_disabled INTEGER NOT NULL DEFAULT 0,
|
is_disabled INTEGER NOT NULL DEFAULT 0
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `capability`
|
CREATE TABLE IF NOT EXISTS `capability`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
name TEXT PRIMARY KEY,
|
||||||
name TEXT NOT NULL,
|
|
||||||
UNIQUE (name)
|
UNIQUE (name)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `user_has_capability`
|
CREATE TABLE IF NOT EXISTS `user_has_capability`
|
||||||
(
|
(
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
capability_id INTEGER NOT NULL,
|
capability_name TEXT NOT NULL,
|
||||||
UNIQUE (user_id, capability_id),
|
UNIQUE (user_id, capability_name),
|
||||||
FOREIGN KEY (capability_id) REFERENCES capability (id)
|
FOREIGN KEY (capability_name) REFERENCES capability (name)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `auth`
|
CREATE TABLE IF NOT EXISTS `auth`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
type TEXT NOT NULL,
|
type TEXT NOT NULL,
|
||||||
secret TEXT NOT NULL,
|
secret TEXT NOT NULL,
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user (id),
|
FOREIGN KEY (user_id) REFERENCES user (id),
|
||||||
UNIQUE (user_id, type)
|
UNIQUE (user_id, type)
|
||||||
);
|
);
|
||||||
@ -44,8 +43,9 @@ CREATE TABLE IF NOT EXISTS `auth`
|
|||||||
CREATE TABLE IF NOT EXISTS `setting`
|
CREATE TABLE IF NOT EXISTS `setting`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
description TEXT NOT NULL DEFAULT "",
|
description TEXT NOT NULL DEFAULT "",
|
||||||
value TEXT NOT NULL,
|
value TEXT NOT NULL,
|
||||||
@ -55,8 +55,9 @@ CREATE TABLE IF NOT EXISTS `setting`
|
|||||||
CREATE TABLE IF NOT EXISTS `audit_log`
|
CREATE TABLE IF NOT EXISTS `audit_log`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
object_type TEXT NOT NULL,
|
object_type TEXT NOT NULL,
|
||||||
object_id INTEGER NOT NULL,
|
object_id INTEGER NOT NULL,
|
||||||
@ -68,36 +69,37 @@ CREATE TABLE IF NOT EXISTS `audit_log`
|
|||||||
CREATE TABLE IF NOT EXISTS `certificate_authority`
|
CREATE TABLE IF NOT EXISTS `certificate_authority`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
acmesh_server TEXT NOT NULL DEFAULT "",
|
acmesh_server TEXT NOT NULL DEFAULT "",
|
||||||
ca_bundle TEXT NOT NULL DEFAULT "",
|
ca_bundle TEXT NOT NULL DEFAULT "",
|
||||||
is_wildcard_supported INTEGER NOT NULL DEFAULT 0, -- specific to each CA, acme v1 doesn't usually have wildcards
|
is_wildcard_supported INTEGER NOT NULL DEFAULT 0, -- specific to each CA, acme v1 doesn't usually have wildcards
|
||||||
max_domains INTEGER NOT NULL DEFAULT 5, -- per request
|
max_domains INTEGER NOT NULL DEFAULT 5, -- per request
|
||||||
is_readonly INTEGER NOT NULL DEFAULT 0,
|
is_readonly INTEGER NOT NULL DEFAULT 0
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `dns_provider`
|
CREATE TABLE IF NOT EXISTS `dns_provider`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
acmesh_name TEXT NOT NULL,
|
acmesh_name TEXT NOT NULL,
|
||||||
dns_sleep INTEGER NOT NULL DEFAULT 0,
|
dns_sleep INTEGER NOT NULL DEFAULT 0,
|
||||||
meta TEXT NOT NULL,
|
meta TEXT NOT NULL,
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user (id)
|
FOREIGN KEY (user_id) REFERENCES user (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `certificate`
|
CREATE TABLE IF NOT EXISTS `certificate`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
type TEXT NOT NULL, -- custom,dns,http
|
type TEXT NOT NULL, -- custom,dns,http
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
certificate_authority_id INTEGER, -- 0 for a custom cert
|
certificate_authority_id INTEGER, -- 0 for a custom cert
|
||||||
@ -109,7 +111,6 @@ CREATE TABLE IF NOT EXISTS `certificate`
|
|||||||
error_message text NOT NULL DEFAULT "",
|
error_message text NOT NULL DEFAULT "",
|
||||||
meta TEXT NOT NULL,
|
meta TEXT NOT NULL,
|
||||||
is_ecc INTEGER NOT NULL DEFAULT 0,
|
is_ecc INTEGER NOT NULL DEFAULT 0,
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user (id),
|
FOREIGN KEY (user_id) REFERENCES user (id),
|
||||||
FOREIGN KEY (certificate_authority_id) REFERENCES certificate_authority (id),
|
FOREIGN KEY (certificate_authority_id) REFERENCES certificate_authority (id),
|
||||||
FOREIGN KEY (dns_provider_id) REFERENCES dns_provider (id)
|
FOREIGN KEY (dns_provider_id) REFERENCES dns_provider (id)
|
||||||
@ -118,8 +119,9 @@ CREATE TABLE IF NOT EXISTS `certificate`
|
|||||||
CREATE TABLE IF NOT EXISTS `stream`
|
CREATE TABLE IF NOT EXISTS `stream`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
listen_interface TEXT NOT NULL,
|
listen_interface TEXT NOT NULL,
|
||||||
incoming_port INTEGER NOT NULL,
|
incoming_port INTEGER NOT NULL,
|
||||||
@ -127,15 +129,15 @@ CREATE TABLE IF NOT EXISTS `stream`
|
|||||||
udp_forwarding INTEGER NOT NULL DEFAULT 0,
|
udp_forwarding INTEGER NOT NULL DEFAULT 0,
|
||||||
advanced_config TEXT NOT NULL,
|
advanced_config TEXT NOT NULL,
|
||||||
is_disabled INTEGER NOT NULL DEFAULT 0,
|
is_disabled INTEGER NOT NULL DEFAULT 0,
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user (id)
|
FOREIGN KEY (user_id) REFERENCES user (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `upstream`
|
CREATE TABLE IF NOT EXISTS `upstream`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
nginx_template_id INTEGER NOT NULL,
|
nginx_template_id INTEGER NOT NULL,
|
||||||
@ -148,7 +150,6 @@ CREATE TABLE IF NOT EXISTS `upstream`
|
|||||||
advanced_config TEXT NOT NULL,
|
advanced_config TEXT NOT NULL,
|
||||||
status TEXT NOT NULL DEFAULT "",
|
status TEXT NOT NULL DEFAULT "",
|
||||||
error_message TEXT NOT NULL DEFAULT "",
|
error_message TEXT NOT NULL DEFAULT "",
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user (id),
|
FOREIGN KEY (user_id) REFERENCES user (id),
|
||||||
FOREIGN KEY (nginx_template_id) REFERENCES nginx_template (id)
|
FOREIGN KEY (nginx_template_id) REFERENCES nginx_template (id)
|
||||||
);
|
);
|
||||||
@ -156,49 +157,50 @@ CREATE TABLE IF NOT EXISTS `upstream`
|
|||||||
CREATE TABLE IF NOT EXISTS `upstream_server`
|
CREATE TABLE IF NOT EXISTS `upstream_server`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
upstream_id INTEGER NOT NULL,
|
upstream_id INTEGER NOT NULL,
|
||||||
server TEXT NOT NULL,
|
server TEXT NOT NULL,
|
||||||
weight INTEGER NOT NULL DEFAULT 0,
|
weight INTEGER NOT NULL DEFAULT 0,
|
||||||
max_conns INTEGER NOT NULL DEFAULT 0,
|
max_conns INTEGER NOT NULL DEFAULT 0,
|
||||||
max_fails INTEGER NOT NULL DEFAULT 0,
|
max_fails INTEGER NOT NULL DEFAULT 0,
|
||||||
fail_timeout INTEGER NOT NULL DEFAULT 0,
|
fail_timeout INTEGER NOT NULL DEFAULT 0,
|
||||||
backup INTEGER NOT NULL DEFAULT 0,
|
is_backup INTEGER NOT NULL DEFAULT 0,
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (upstream_id) REFERENCES upstream (id)
|
FOREIGN KEY (upstream_id) REFERENCES upstream (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `access_list`
|
CREATE TABLE IF NOT EXISTS `access_list`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
meta TEXT NOT NULL,
|
meta TEXT NOT NULL,
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user (id)
|
FOREIGN KEY (user_id) REFERENCES user (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `nginx_template`
|
CREATE TABLE IF NOT EXISTS `nginx_template`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
type TEXT NOT NULL,
|
type TEXT NOT NULL,
|
||||||
template TEXT NOT NULL,
|
template TEXT NOT NULL,
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user (id)
|
FOREIGN KEY (user_id) REFERENCES user (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS `host`
|
CREATE TABLE IF NOT EXISTS `host`
|
||||||
(
|
(
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
created_on INTEGER NOT NULL DEFAULT 0,
|
created_at INTEGER NOT NULL DEFAULT 0,
|
||||||
modified_on INTEGER NOT NULL DEFAULT 0,
|
updated_at INTEGER NOT NULL DEFAULT 0,
|
||||||
|
is_deleted INTEGER NOT NULL DEFAULT 0,
|
||||||
user_id INTEGER NOT NULL,
|
user_id INTEGER NOT NULL,
|
||||||
type TEXT NOT NULL,
|
type TEXT NOT NULL,
|
||||||
nginx_template_id INTEGER NOT NULL,
|
nginx_template_id INTEGER NOT NULL,
|
||||||
@ -222,7 +224,6 @@ CREATE TABLE IF NOT EXISTS `host`
|
|||||||
status TEXT NOT NULL DEFAULT "",
|
status TEXT NOT NULL DEFAULT "",
|
||||||
error_message TEXT NOT NULL DEFAULT "",
|
error_message TEXT NOT NULL DEFAULT "",
|
||||||
is_disabled INTEGER NOT NULL DEFAULT 0,
|
is_disabled INTEGER NOT NULL DEFAULT 0,
|
||||||
is_deleted INTEGER NOT NULL DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES user (id),
|
FOREIGN KEY (user_id) REFERENCES user (id),
|
||||||
FOREIGN KEY (nginx_template_id) REFERENCES nginx_template (id),
|
FOREIGN KEY (nginx_template_id) REFERENCES nginx_template (id),
|
||||||
FOREIGN KEY (upstream_id) REFERENCES upstream (id),
|
FOREIGN KEY (upstream_id) REFERENCES upstream (id),
|
@ -25,14 +25,14 @@ INSERT INTO `capability` (
|
|||||||
|
|
||||||
-- Default error reporting setting
|
-- Default error reporting setting
|
||||||
INSERT INTO `setting` (
|
INSERT INTO `setting` (
|
||||||
created_on,
|
created_at,
|
||||||
modified_on,
|
updated_at,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
value
|
value
|
||||||
) VALUES (
|
) VALUES (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"error-reporting",
|
"error-reporting",
|
||||||
"If enabled, any application errors are reported to Sentry. Sensitive information is not sent.",
|
"If enabled, any application errors are reported to Sentry. Sensitive information is not sent.",
|
||||||
"true" -- remember this is json
|
"true" -- remember this is json
|
||||||
@ -40,14 +40,14 @@ INSERT INTO `setting` (
|
|||||||
|
|
||||||
-- Default site
|
-- Default site
|
||||||
INSERT INTO `setting` (
|
INSERT INTO `setting` (
|
||||||
created_on,
|
created_at,
|
||||||
modified_on,
|
updated_at,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
value
|
value
|
||||||
) VALUES (
|
) VALUES (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"default-site",
|
"default-site",
|
||||||
"What to show users who hit your Nginx server by default",
|
"What to show users who hit your Nginx server by default",
|
||||||
'"welcome"' -- remember this is json
|
'"welcome"' -- remember this is json
|
||||||
@ -56,56 +56,56 @@ INSERT INTO `setting` (
|
|||||||
-- Default Certificate Authorities
|
-- Default Certificate Authorities
|
||||||
|
|
||||||
INSERT INTO `certificate_authority` (
|
INSERT INTO `certificate_authority` (
|
||||||
created_on,
|
created_at,
|
||||||
modified_on,
|
updated_at,
|
||||||
name,
|
name,
|
||||||
acmesh_server,
|
acmesh_server,
|
||||||
is_wildcard_supported,
|
is_wildcard_supported,
|
||||||
max_domains,
|
max_domains,
|
||||||
is_readonly
|
is_readonly
|
||||||
) VALUES (
|
) VALUES (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"ZeroSSL",
|
"ZeroSSL",
|
||||||
"zerossl",
|
"zerossl",
|
||||||
1,
|
1,
|
||||||
10,
|
10,
|
||||||
1
|
1
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"Let's Encrypt",
|
"Let's Encrypt",
|
||||||
"https://acme-v02.api.letsencrypt.org/directory",
|
"https://acme-v02.api.letsencrypt.org/directory",
|
||||||
1,
|
1,
|
||||||
10,
|
10,
|
||||||
1
|
1
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"Buypass Go SSL",
|
"Buypass Go SSL",
|
||||||
"https://api.buypass.com/acme/directory",
|
"https://api.buypass.com/acme/directory",
|
||||||
0,
|
0,
|
||||||
5,
|
5,
|
||||||
1
|
1
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"SSL.com",
|
"SSL.com",
|
||||||
"ssl.com",
|
"ssl.com",
|
||||||
0,
|
0,
|
||||||
10,
|
10,
|
||||||
1
|
1
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"Let's Encrypt (Testing)",
|
"Let's Encrypt (Testing)",
|
||||||
"https://acme-staging-v02.api.letsencrypt.org/directory",
|
"https://acme-staging-v02.api.letsencrypt.org/directory",
|
||||||
1,
|
1,
|
||||||
10,
|
10,
|
||||||
1
|
1
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"Buypass Go SSL (Testing)",
|
"Buypass Go SSL (Testing)",
|
||||||
"https://api.test4.buypass.no/acme/directory",
|
"https://api.test4.buypass.no/acme/directory",
|
||||||
0,
|
0,
|
||||||
@ -115,15 +115,15 @@ INSERT INTO `certificate_authority` (
|
|||||||
|
|
||||||
-- System User
|
-- System User
|
||||||
INSERT INTO `user` (
|
INSERT INTO `user` (
|
||||||
created_on,
|
created_at,
|
||||||
modified_on,
|
updated_at,
|
||||||
name,
|
name,
|
||||||
nickname,
|
nickname,
|
||||||
email,
|
email,
|
||||||
is_system
|
is_system
|
||||||
) VALUES (
|
) VALUES (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
"System",
|
"System",
|
||||||
"System",
|
"System",
|
||||||
"system@localhost",
|
"system@localhost",
|
||||||
@ -132,15 +132,15 @@ INSERT INTO `user` (
|
|||||||
|
|
||||||
-- Host Templates
|
-- Host Templates
|
||||||
INSERT INTO `nginx_template` (
|
INSERT INTO `nginx_template` (
|
||||||
created_on,
|
created_at,
|
||||||
modified_on,
|
updated_at,
|
||||||
user_id,
|
user_id,
|
||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
template
|
template
|
||||||
) VALUES (
|
) VALUES (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
||||||
"Default Proxy Template",
|
"Default Proxy Template",
|
||||||
"proxy",
|
"proxy",
|
||||||
@ -262,29 +262,29 @@ server {
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
||||||
"Default Redirect Template",
|
"Default Redirect Template",
|
||||||
"redirect",
|
"redirect",
|
||||||
"# this is a redirect template"
|
"# this is a redirect template"
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
||||||
"Default Dead Template",
|
"Default Dead Template",
|
||||||
"dead",
|
"dead",
|
||||||
"# this is a dead template"
|
"# this is a dead template"
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
||||||
"Default Stream Template",
|
"Default Stream Template",
|
||||||
"stream",
|
"stream",
|
||||||
"# this is a stream template"
|
"# this is a stream template"
|
||||||
), (
|
), (
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
strftime('%s', 'now'),
|
unixepoch() * 1000,
|
||||||
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
(SELECT id FROM user WHERE is_system = 1 LIMIT 1),
|
||||||
"Default Upstream Template",
|
"Default Upstream Template",
|
||||||
"upstream",
|
"upstream",
|
@ -4,54 +4,61 @@ go 1.20
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alexflint/go-arg v1.4.3
|
github.com/alexflint/go-arg v1.4.3
|
||||||
|
github.com/amacneil/dbmate/v2 v2.3.0
|
||||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible
|
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/drexedam/gravatar v0.0.0-20210327211422-e94eea8c338e
|
github.com/drexedam/gravatar v0.0.0-20210327211422-e94eea8c338e
|
||||||
github.com/fatih/color v1.13.0
|
github.com/fatih/color v1.15.0
|
||||||
github.com/getsentry/sentry-go v0.17.0
|
github.com/getsentry/sentry-go v0.21.0
|
||||||
|
github.com/glebarez/sqlite v1.8.0
|
||||||
github.com/go-chi/chi v4.1.2+incompatible
|
github.com/go-chi/chi v4.1.2+incompatible
|
||||||
github.com/go-chi/cors v1.2.1
|
github.com/go-chi/cors v1.2.1
|
||||||
github.com/go-chi/jwtauth v4.0.4+incompatible
|
github.com/go-chi/jwtauth v4.0.4+incompatible
|
||||||
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec
|
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec
|
||||||
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760
|
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760
|
||||||
github.com/jmoiron/sqlx v1.3.5
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/qri-io/jsonschema v0.2.1
|
github.com/qri-io/jsonschema v0.2.1
|
||||||
github.com/rotisserie/eris v0.5.4
|
github.com/rotisserie/eris v0.5.4
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/vrischmann/envconfig v1.3.0
|
github.com/vrischmann/envconfig v1.3.0
|
||||||
golang.org/x/crypto v0.5.0
|
golang.org/x/crypto v0.9.0
|
||||||
modernc.org/sqlite v1.21.1
|
gorm.io/datatypes v1.2.0
|
||||||
|
gorm.io/driver/mysql v1.5.1
|
||||||
|
gorm.io/driver/postgres v1.5.2
|
||||||
|
gorm.io/gorm v1.25.1
|
||||||
|
gorm.io/plugin/soft_delete v1.2.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alexflint/go-scalar v1.2.0 // indirect
|
github.com/alexflint/go-scalar v1.2.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
|
github.com/glebarez/go-sqlite v1.21.1 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||||
|
github.com/jackc/pgx/v5 v5.3.1 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/lestrrat-go/jspointer v0.0.0-20181205001929-82fadba7561c // indirect
|
github.com/lestrrat-go/jspointer v0.0.0-20181205001929-82fadba7561c // indirect
|
||||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||||
github.com/lestrrat-go/pdebug/v3 v3.0.1 // indirect
|
github.com/lestrrat-go/pdebug/v3 v3.0.1 // indirect
|
||||||
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb // indirect
|
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb // indirect
|
||||||
|
github.com/lib/pq v1.10.9 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/qri-io/jsonpointer v0.1.1 // indirect
|
github.com/qri-io/jsonpointer v0.1.1 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/sys v0.8.0 // indirect
|
||||||
golang.org/x/text v0.6.0 // indirect
|
golang.org/x/text v0.9.0 // indirect
|
||||||
golang.org/x/tools v0.1.12 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
lukechampine.com/uint128 v1.2.0 // indirect
|
modernc.org/libc v1.22.6 // indirect
|
||||||
modernc.org/cc/v3 v3.40.0 // indirect
|
|
||||||
modernc.org/ccgo/v3 v3.16.13 // indirect
|
|
||||||
modernc.org/libc v1.22.3 // indirect
|
|
||||||
modernc.org/mathutil v1.5.0 // indirect
|
modernc.org/mathutil v1.5.0 // indirect
|
||||||
modernc.org/memory v1.5.0 // indirect
|
modernc.org/memory v1.5.0 // indirect
|
||||||
modernc.org/opt v0.1.3 // indirect
|
modernc.org/sqlite v1.22.1 // indirect
|
||||||
modernc.org/strutil v1.1.3 // indirect
|
|
||||||
modernc.org/token v1.0.1 // indirect
|
|
||||||
)
|
)
|
||||||
|
129
backend/go.sum
129
backend/go.sum
@ -3,6 +3,8 @@ github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258m
|
|||||||
github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||||
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
|
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
|
||||||
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||||
|
github.com/amacneil/dbmate/v2 v2.3.0 h1:2Q90DiJmOxLQGgGELm+hCrIJejGldx9R3jN2++FsHQI=
|
||||||
|
github.com/amacneil/dbmate/v2 v2.3.0/go.mod h1:Vwi1HgvTnkuJ0GLBzT/GWG0ZnOm870FQXQL9qshSswM=
|
||||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns=
|
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns=
|
||||||
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
@ -13,12 +15,16 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
|
|||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/drexedam/gravatar v0.0.0-20210327211422-e94eea8c338e h1:2R8DvYLNr5DL25eWwpOdPno1eIbTNjJC0d7v8ti5cus=
|
github.com/drexedam/gravatar v0.0.0-20210327211422-e94eea8c338e h1:2R8DvYLNr5DL25eWwpOdPno1eIbTNjJC0d7v8ti5cus=
|
||||||
github.com/drexedam/gravatar v0.0.0-20210327211422-e94eea8c338e/go.mod h1:YjikoytuRI4q+GRd3xrOrKJN+Ayi2dwRomHLDDeMHfs=
|
github.com/drexedam/gravatar v0.0.0-20210327211422-e94eea8c338e/go.mod h1:YjikoytuRI4q+GRd3xrOrKJN+Ayi2dwRomHLDDeMHfs=
|
||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||||
github.com/getsentry/sentry-go v0.17.0 h1:UustVWnOoDFHBS7IJUB2QK/nB5pap748ZEp0swnQJak=
|
github.com/getsentry/sentry-go v0.21.0 h1:c9l5F1nPF30JIppulk4veau90PK6Smu3abgVtVQWon4=
|
||||||
github.com/getsentry/sentry-go v0.17.0/go.mod h1:B82dxtBvxG0KaPD8/hfSV+VcHD+Lg/xUS4JuQn1P4cM=
|
github.com/getsentry/sentry-go v0.21.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||||
|
github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY=
|
||||||
|
github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E=
|
||||||
|
github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc=
|
||||||
|
github.com/glebarez/sqlite v1.8.0/go.mod h1:bpET16h1za2KOOMb8+jCp6UBP/iahDpfPQqSaYLTLx8=
|
||||||
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
|
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
|
||||||
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||||
@ -26,20 +32,32 @@ github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vz
|
|||||||
github.com/go-chi/jwtauth v4.0.4+incompatible h1:LGIxg6YfvSBzxU2BljXbrzVc1fMlgqSKBQgKOGAVtPY=
|
github.com/go-chi/jwtauth v4.0.4+incompatible h1:LGIxg6YfvSBzxU2BljXbrzVc1fMlgqSKBQgKOGAVtPY=
|
||||||
github.com/go-chi/jwtauth v4.0.4+incompatible/go.mod h1:Q5EIArY/QnD6BdS+IyDw7B2m6iNbnPxtfd6/BcmtWbs=
|
github.com/go-chi/jwtauth v4.0.4+incompatible/go.mod h1:Q5EIArY/QnD6BdS+IyDw7B2m6iNbnPxtfd6/BcmtWbs=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||||
|
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||||
|
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||||
|
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
|
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
|
||||||
|
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
|
||||||
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec h1:KKntwkZlM2w/88QiDyAeZ4th8grqtituzMW8qyapYzc=
|
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec h1:KKntwkZlM2w/88QiDyAeZ4th8grqtituzMW8qyapYzc=
|
||||||
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec/go.mod h1:4v5Xmm0eYuaWqKJ63XUV5YfQPoxtId3DgDytbnWhi+s=
|
github.com/jc21/go-sse v0.0.0-20230307071053-2e6b1dbcb7ec/go.mod h1:4v5Xmm0eYuaWqKJ63XUV5YfQPoxtId3DgDytbnWhi+s=
|
||||||
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760 h1:7wxq2DIgtO36KLrFz1RldysO0WVvcYsD49G9tyAs01k=
|
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760 h1:7wxq2DIgtO36KLrFz1RldysO0WVvcYsD49G9tyAs01k=
|
||||||
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760/go.mod h1:yIq2t51OJgVsdRlPY68NAnyVdBH0kYXxDTFtUxOap80=
|
github.com/jc21/jsref v0.0.0-20210608024405-a97debfc4760/go.mod h1:yIq2t51OJgVsdRlPY68NAnyVdBH0kYXxDTFtUxOap80=
|
||||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@ -56,21 +74,20 @@ github.com/lestrrat-go/pdebug/v3 v3.0.1/go.mod h1:za+m+Ve24yCxTEhR59N7UlnJomWwCi
|
|||||||
github.com/lestrrat-go/structinfo v0.0.0-20190212233437-acd51874663b/go.mod h1:s2U6PowV3/Jobkx/S9d0XiPwOzs6niW3DIouw+7nZC8=
|
github.com/lestrrat-go/structinfo v0.0.0-20190212233437-acd51874663b/go.mod h1:s2U6PowV3/Jobkx/S9d0XiPwOzs6niW3DIouw+7nZC8=
|
||||||
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb h1:DDg5u5lk2v8O8qxs8ecQkMUBj3tLW6wkSLzxxOyi1Ig=
|
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb h1:DDg5u5lk2v8O8qxs8ecQkMUBj3tLW6wkSLzxxOyi1Ig=
|
||||||
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb/go.mod h1:i+E8Uf04vf2QjOWyJdGY75vmG+4rxiZW2kIj1lTB5mo=
|
github.com/lestrrat-go/structinfo v0.0.0-20210312050401-7f8bd69d6acb/go.mod h1:i+E8Uf04vf2QjOWyJdGY75vmG+4rxiZW2kIj1lTB5mo=
|
||||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
|
||||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||||
|
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
|
||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
@ -87,40 +104,43 @@ github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Ung
|
|||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||||
github.com/rotisserie/eris v0.5.4 h1:Il6IvLdAapsMhvuOahHWiBnl1G++Q0/L5UIkI5mARSk=
|
github.com/rotisserie/eris v0.5.4 h1:Il6IvLdAapsMhvuOahHWiBnl1G++Q0/L5UIkI5mARSk=
|
||||||
github.com/rotisserie/eris v0.5.4/go.mod h1:Z/kgYTJiJtocxCbFfvRmO+QejApzG6zpyky9G1A4g9s=
|
github.com/rotisserie/eris v0.5.4/go.mod h1:Z/kgYTJiJtocxCbFfvRmO+QejApzG6zpyky9G1A4g9s=
|
||||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/vrischmann/envconfig v1.3.0 h1:4XIvQTXznxmWMnjouj0ST5lFo/WAYf5Exgl3x82crEk=
|
github.com/vrischmann/envconfig v1.3.0 h1:4XIvQTXznxmWMnjouj0ST5lFo/WAYf5Exgl3x82crEk=
|
||||||
github.com/vrischmann/envconfig v1.3.0/go.mod h1:bbvxFYJdRSpXrhS63mBFtKJzkDiNkyArOLXtY6q0kuI=
|
github.com/vrischmann/envconfig v1.3.0/go.mod h1:bbvxFYJdRSpXrhS63mBFtKJzkDiNkyArOLXtY6q0kuI=
|
||||||
github.com/wacul/ptr v1.0.0/go.mod h1:BD0gjsZrCwtoR+yWDB9v2hQ8STlq9tT84qKfa+3txOc=
|
github.com/wacul/ptr v1.0.0/go.mod h1:BD0gjsZrCwtoR+yWDB9v2hQ8STlq9tT84qKfa+3txOc=
|
||||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 h1:qXafrlZL1WsJW5OokjraLLRURHiw0OzKHD/RNdspp4w=
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
@ -128,27 +148,26 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
|
gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco=
|
||||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
gorm.io/datatypes v1.2.0/go.mod h1:o1dh0ZvjIjhH/bngTpypG6lVRJ5chTBxE09FH/71k04=
|
||||||
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
|
gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
|
||||||
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
|
||||||
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
|
gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
|
||||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
|
||||||
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
|
gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c=
|
||||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
|
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
|
||||||
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
|
||||||
modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw=
|
gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
|
||||||
|
gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
|
||||||
|
gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64=
|
||||||
|
gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||||
|
gorm.io/plugin/soft_delete v1.2.1 h1:qx9D/c4Xu6w5KT8LviX8DgLcB9hkKl6JC9f44Tj7cGU=
|
||||||
|
gorm.io/plugin/soft_delete v1.2.1/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk=
|
||||||
|
modernc.org/libc v1.22.6 h1:cbXU8R+A6aOjRuhsFh3nbDWXO/Hs4ClJRXYB11KmPDo=
|
||||||
|
modernc.org/libc v1.22.6/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||||
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
|
modernc.org/sqlite v1.22.1 h1:P2+Dhp5FR1RlVRkQ3dDfCiv3Ok8XPxqpe70IjYVA9oE=
|
||||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
modernc.org/sqlite v1.22.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||||
modernc.org/sqlite v1.21.1 h1:GyDFqNnESLOhwwDRaHGdp2jKLDzpyT/rNLglX3ZkMSU=
|
|
||||||
modernc.org/sqlite v1.21.1/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI=
|
|
||||||
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
|
|
||||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
|
||||||
modernc.org/tcl v1.15.1 h1:mOQwiEK4p7HruMZcwKTZPw/aqtGM4aY00uzWhlKKYws=
|
|
||||||
modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
|
|
||||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
|
||||||
modernc.org/z v1.7.0 h1:xkDw/KepgEjeizO2sNco+hqYkU12taxQFqPEmgm1GWE=
|
|
||||||
|
@ -35,7 +35,7 @@ func GetAccessLists() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetAccessList() func(http.ResponseWriter, *http.Request) {
|
func GetAccessList() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var accessListID int
|
var accessListID uint
|
||||||
if accessListID, err = getURLParamInt(r, "accessListID"); err != nil {
|
if accessListID, err = getURLParamInt(r, "accessListID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -81,7 +81,7 @@ func CreateAccessList() func(http.ResponseWriter, *http.Request) {
|
|||||||
func UpdateAccessList() func(http.ResponseWriter, *http.Request) {
|
func UpdateAccessList() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var accessListID int
|
var accessListID uint
|
||||||
if accessListID, err = getURLParamInt(r, "accessListID"); err != nil {
|
if accessListID, err = getURLParamInt(r, "accessListID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -113,7 +113,7 @@ func UpdateAccessList() func(http.ResponseWriter, *http.Request) {
|
|||||||
func DeleteAccessList() func(http.ResponseWriter, *http.Request) {
|
func DeleteAccessList() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var accessListID int
|
var accessListID uint
|
||||||
if accessListID, err = getURLParamInt(r, "accessListID"); err != nil {
|
if accessListID, err = getURLParamInt(r, "accessListID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
|
@ -14,9 +14,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type setAuthModel struct {
|
type setAuthModel struct {
|
||||||
Type string `json:"type" db:"type"`
|
Type string
|
||||||
Secret string `json:"secret,omitempty" db:"secret"`
|
Secret string
|
||||||
CurrentSecret string `json:"current_secret,omitempty"`
|
CurrentSecret string
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAuth sets a auth method. This can be used for "me" and `2` for example
|
// SetAuth sets a auth method. This can be used for "me" and `2` for example
|
||||||
|
@ -38,7 +38,7 @@ func GetCertificateAuthorities() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetCertificateAuthority() func(http.ResponseWriter, *http.Request) {
|
func GetCertificateAuthority() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var caID int
|
var caID uint
|
||||||
if caID, err = getURLParamInt(r, "caID"); err != nil {
|
if caID, err = getURLParamInt(r, "caID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -92,7 +92,7 @@ func CreateCertificateAuthority() func(http.ResponseWriter, *http.Request) {
|
|||||||
func UpdateCertificateAuthority() func(http.ResponseWriter, *http.Request) {
|
func UpdateCertificateAuthority() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var caID int
|
var caID uint
|
||||||
if caID, err = getURLParamInt(r, "caID"); err != nil {
|
if caID, err = getURLParamInt(r, "caID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -132,7 +132,7 @@ func UpdateCertificateAuthority() func(http.ResponseWriter, *http.Request) {
|
|||||||
func DeleteCertificateAuthority() func(http.ResponseWriter, *http.Request) {
|
func DeleteCertificateAuthority() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var caID int
|
var caID uint
|
||||||
if caID, err = getURLParamInt(r, "caID"); err != nil {
|
if caID, err = getURLParamInt(r, "caID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
|
@ -55,7 +55,7 @@ func CreateCertificate() func(http.ResponseWriter, *http.Request) {
|
|||||||
var item certificate.Model
|
var item certificate.Model
|
||||||
if fillObjectFromBody(w, r, "", &item) {
|
if fillObjectFromBody(w, r, "", &item) {
|
||||||
// Get userID from token
|
// Get userID from token
|
||||||
userID, _ := r.Context().Value(c.UserIDCtxKey).(int)
|
userID, _ := r.Context().Value(c.UserIDCtxKey).(uint)
|
||||||
item.UserID = userID
|
item.UserID = userID
|
||||||
|
|
||||||
if err := item.Save(); err != nil {
|
if err := item.Save(); err != nil {
|
||||||
@ -131,7 +131,7 @@ func DownloadCertificate() func(http.ResponseWriter, *http.Request) {
|
|||||||
// have a certificate id in the url. it will write errors to the output.
|
// have a certificate id in the url. it will write errors to the output.
|
||||||
func getCertificateFromRequest(w http.ResponseWriter, r *http.Request) *certificate.Model {
|
func getCertificateFromRequest(w http.ResponseWriter, r *http.Request) *certificate.Model {
|
||||||
var err error
|
var err error
|
||||||
var certificateID int
|
var certificateID uint
|
||||||
if certificateID, err = getURLParamInt(r, "certificateID"); err != nil {
|
if certificateID, err = getURLParamInt(r, "certificateID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return nil
|
return nil
|
||||||
|
@ -38,7 +38,7 @@ func GetDNSProviders() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetDNSProvider() func(http.ResponseWriter, *http.Request) {
|
func GetDNSProvider() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var providerID int
|
var providerID uint
|
||||||
if providerID, err = getURLParamInt(r, "providerID"); err != nil {
|
if providerID, err = getURLParamInt(r, "providerID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -87,7 +87,7 @@ func CreateDNSProvider() func(http.ResponseWriter, *http.Request) {
|
|||||||
func UpdateDNSProvider() func(http.ResponseWriter, *http.Request) {
|
func UpdateDNSProvider() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var providerID int
|
var providerID uint
|
||||||
if providerID, err = getURLParamInt(r, "providerID"); err != nil {
|
if providerID, err = getURLParamInt(r, "providerID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -122,7 +122,7 @@ func UpdateDNSProvider() func(http.ResponseWriter, *http.Request) {
|
|||||||
func DeleteDNSProvider() func(http.ResponseWriter, *http.Request) {
|
func DeleteDNSProvider() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var providerID int
|
var providerID uint
|
||||||
if providerID, err = getURLParamInt(r, "providerID"); err != nil {
|
if providerID, err = getURLParamInt(r, "providerID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/api/context"
|
"npm/internal/api/context"
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
@ -19,11 +18,6 @@ func getPageInfoFromRequest(r *http.Request) (model.PageInfo, error) {
|
|||||||
var pageInfo model.PageInfo
|
var pageInfo model.PageInfo
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
pageInfo.FromDate, pageInfo.ToDate, err = getDateRanges(r)
|
|
||||||
if err != nil {
|
|
||||||
return pageInfo, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pageInfo.Offset, pageInfo.Limit, err = getPagination(r)
|
pageInfo.Offset, pageInfo.Limit, err = getPagination(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pageInfo, err
|
return pageInfo, err
|
||||||
@ -34,32 +28,6 @@ func getPageInfoFromRequest(r *http.Request) (model.PageInfo, error) {
|
|||||||
return pageInfo, nil
|
return pageInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDateRanges(r *http.Request) (time.Time, time.Time, error) {
|
|
||||||
queryValues := r.URL.Query()
|
|
||||||
from := queryValues.Get("from")
|
|
||||||
fromDate := time.Now().AddDate(0, -1, 0) // 1 month ago by default
|
|
||||||
to := queryValues.Get("to")
|
|
||||||
toDate := time.Now()
|
|
||||||
|
|
||||||
if from != "" {
|
|
||||||
var fromErr error
|
|
||||||
fromDate, fromErr = time.Parse(time.RFC3339, from)
|
|
||||||
if fromErr != nil {
|
|
||||||
return fromDate, toDate, eris.Errorf("From date is not in correct format: %v", strings.ReplaceAll(time.RFC3339, "Z", "+"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if to != "" {
|
|
||||||
var toErr error
|
|
||||||
toDate, toErr = time.Parse(time.RFC3339, to)
|
|
||||||
if toErr != nil {
|
|
||||||
return fromDate, toDate, eris.Errorf("To date is not in correct format: %v", strings.ReplaceAll(time.RFC3339, "Z", "+"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fromDate, toDate, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSortParameter(r *http.Request) []model.Sort {
|
func getSortParameter(r *http.Request) []model.Sort {
|
||||||
var sortFields []model.Sort
|
var sortFields []model.Sort
|
||||||
|
|
||||||
@ -132,12 +100,11 @@ func getQueryVarBool(r *http.Request, varName string, required bool, defaultValu
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func getURLParamInt(r *http.Request, varName string) (int, error) {
|
func getURLParamInt(r *http.Request, varName string) (uint, error) {
|
||||||
|
var defaultValue uint = 0
|
||||||
|
|
||||||
required := true
|
required := true
|
||||||
defaultValue := 0
|
|
||||||
paramStr := chi.URLParam(r, varName)
|
paramStr := chi.URLParam(r, varName)
|
||||||
var err error
|
|
||||||
var paramInt int
|
|
||||||
|
|
||||||
if paramStr == "" && required {
|
if paramStr == "" && required {
|
||||||
return 0, eris.Errorf("%v was not supplied in the request", varName)
|
return 0, eris.Errorf("%v was not supplied in the request", varName)
|
||||||
@ -145,11 +112,13 @@ func getURLParamInt(r *http.Request, varName string) (int, error) {
|
|||||||
return defaultValue, nil
|
return defaultValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if paramInt, err = strconv.Atoi(paramStr); err != nil {
|
// func ParseUint(s string, base int, bitSize int) (n uint64, err error)
|
||||||
|
paramUint, err := strconv.ParseUint(paramStr, 10, 32)
|
||||||
|
if err != nil {
|
||||||
return 0, eris.Wrapf(err, "%v is not a valid number", varName)
|
return 0, eris.Wrapf(err, "%v is not a valid number", varName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return paramInt, nil
|
return uint(paramUint), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getURLParamString(r *http.Request, varName string) (string, error) {
|
func getURLParamString(r *http.Request, varName string) (string, error) {
|
||||||
|
@ -40,7 +40,7 @@ func GetHosts() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetHost() func(http.ResponseWriter, *http.Request) {
|
func GetHost() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var hostID int
|
var hostID uint
|
||||||
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -74,7 +74,7 @@ func CreateHost() func(http.ResponseWriter, *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get userID from token
|
// Get userID from token
|
||||||
userID, _ := r.Context().Value(c.UserIDCtxKey).(int)
|
userID, _ := r.Context().Value(c.UserIDCtxKey).(uint)
|
||||||
newHost.UserID = userID
|
newHost.UserID = userID
|
||||||
|
|
||||||
if err = validator.ValidateHost(newHost); err != nil {
|
if err = validator.ValidateHost(newHost); err != nil {
|
||||||
@ -103,7 +103,7 @@ func CreateHost() func(http.ResponseWriter, *http.Request) {
|
|||||||
func UpdateHost() func(http.ResponseWriter, *http.Request) {
|
func UpdateHost() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var hostID int
|
var hostID uint
|
||||||
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -148,7 +148,7 @@ func UpdateHost() func(http.ResponseWriter, *http.Request) {
|
|||||||
func DeleteHost() func(http.ResponseWriter, *http.Request) {
|
func DeleteHost() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var hostID int
|
var hostID uint
|
||||||
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -173,7 +173,7 @@ func DeleteHost() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetHostNginxConfig(format string) func(http.ResponseWriter, *http.Request) {
|
func GetHostNginxConfig(format string) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var hostID int
|
var hostID uint
|
||||||
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
|
@ -36,7 +36,7 @@ func GetNginxTemplates() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetNginxTemplate() func(http.ResponseWriter, *http.Request) {
|
func GetNginxTemplate() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var templateID int
|
var templateID uint
|
||||||
if templateID, err = getURLParamInt(r, "templateID"); err != nil {
|
if templateID, err = getURLParamInt(r, "templateID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -85,7 +85,7 @@ func CreateNginxTemplate() func(http.ResponseWriter, *http.Request) {
|
|||||||
func UpdateNginxTemplate() func(http.ResponseWriter, *http.Request) {
|
func UpdateNginxTemplate() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var templateID int
|
var templateID uint
|
||||||
if templateID, err = getURLParamInt(r, "templateID"); err != nil {
|
if templateID, err = getURLParamInt(r, "templateID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -122,7 +122,7 @@ func UpdateNginxTemplate() func(http.ResponseWriter, *http.Request) {
|
|||||||
func DeleteNginxTemplate() func(http.ResponseWriter, *http.Request) {
|
func DeleteNginxTemplate() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var templateID int
|
var templateID uint
|
||||||
if templateID, err = getURLParamInt(r, "templateID"); err != nil {
|
if templateID, err = getURLParamInt(r, "templateID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
|
@ -36,7 +36,7 @@ func GetStreams() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetStream() func(http.ResponseWriter, *http.Request) {
|
func GetStream() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var hostID int
|
var hostID uint
|
||||||
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -85,7 +85,7 @@ func CreateStream() func(http.ResponseWriter, *http.Request) {
|
|||||||
func UpdateStream() func(http.ResponseWriter, *http.Request) {
|
func UpdateStream() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var hostID int
|
var hostID uint
|
||||||
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -120,7 +120,7 @@ func UpdateStream() func(http.ResponseWriter, *http.Request) {
|
|||||||
func DeleteStream() func(http.ResponseWriter, *http.Request) {
|
func DeleteStream() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var hostID int
|
var hostID uint
|
||||||
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
if hostID, err = getURLParamInt(r, "hostID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
|
@ -93,7 +93,7 @@ func RefreshToken() func(http.ResponseWriter, *http.Request) {
|
|||||||
// Route: POST /tokens/sse
|
// Route: POST /tokens/sse
|
||||||
func NewSSEToken() func(http.ResponseWriter, *http.Request) {
|
func NewSSEToken() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
userID := r.Context().Value(c.UserIDCtxKey).(int)
|
userID := r.Context().Value(c.UserIDCtxKey).(uint)
|
||||||
|
|
||||||
// Find user
|
// Find user
|
||||||
userObj, userErr := user.GetByID(userID)
|
userObj, userErr := user.GetByID(userID)
|
||||||
|
@ -41,7 +41,7 @@ func GetUpstreams() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetUpstream() func(http.ResponseWriter, *http.Request) {
|
func GetUpstream() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var upstreamID int
|
var upstreamID uint
|
||||||
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
|
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -75,7 +75,7 @@ func CreateUpstream() func(http.ResponseWriter, *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get userID from token
|
// Get userID from token
|
||||||
userID, _ := r.Context().Value(c.UserIDCtxKey).(int)
|
userID, _ := r.Context().Value(c.UserIDCtxKey).(uint)
|
||||||
newUpstream.UserID = userID
|
newUpstream.UserID = userID
|
||||||
|
|
||||||
if err = validator.ValidateUpstream(newUpstream); err != nil {
|
if err = validator.ValidateUpstream(newUpstream); err != nil {
|
||||||
@ -99,7 +99,7 @@ func CreateUpstream() func(http.ResponseWriter, *http.Request) {
|
|||||||
func UpdateUpstream() func(http.ResponseWriter, *http.Request) {
|
func UpdateUpstream() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var upstreamID int
|
var upstreamID uint
|
||||||
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
|
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -141,7 +141,7 @@ func UpdateUpstream() func(http.ResponseWriter, *http.Request) {
|
|||||||
func DeleteUpstream() func(http.ResponseWriter, *http.Request) {
|
func DeleteUpstream() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var upstreamID int
|
var upstreamID uint
|
||||||
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
|
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
@ -172,7 +172,7 @@ func DeleteUpstream() func(http.ResponseWriter, *http.Request) {
|
|||||||
func GetUpstreamNginxConfig(format string) func(http.ResponseWriter, *http.Request) {
|
func GetUpstreamNginxConfig(format string) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var err error
|
var err error
|
||||||
var upstreamID int
|
var upstreamID uint
|
||||||
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
|
if upstreamID, err = getURLParamInt(r, "upstreamID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
|
@ -121,14 +121,14 @@ func UpdateUser() func(http.ResponseWriter, *http.Request) {
|
|||||||
// Route: DELETE /users/{userID}
|
// Route: DELETE /users/{userID}
|
||||||
func DeleteUser() func(http.ResponseWriter, *http.Request) {
|
func DeleteUser() func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var userID int
|
var userID uint
|
||||||
var err error
|
var err error
|
||||||
if userID, err = getURLParamInt(r, "userID"); err != nil {
|
if userID, err = getURLParamInt(r, "userID"); err != nil {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, err.Error(), nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
myUserID, _ := r.Context().Value(c.UserIDCtxKey).(int)
|
myUserID, _ := r.Context().Value(c.UserIDCtxKey).(uint)
|
||||||
if myUserID == userID {
|
if myUserID == userID {
|
||||||
h.ResultErrorJSON(w, r, http.StatusBadRequest, "You cannot delete yourself!", nil)
|
h.ResultErrorJSON(w, r, http.StatusBadRequest, "You cannot delete yourself!", nil)
|
||||||
return
|
return
|
||||||
@ -224,11 +224,11 @@ func DeleteUsers() func(http.ResponseWriter, *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserIDFromRequest(r *http.Request) (int, bool, error) {
|
func getUserIDFromRequest(r *http.Request) (uint, bool, error) {
|
||||||
userIDstr := chi.URLParam(r, "userID")
|
userIDstr := chi.URLParam(r, "userID")
|
||||||
selfUserID, _ := r.Context().Value(c.UserIDCtxKey).(int)
|
selfUserID, _ := r.Context().Value(c.UserIDCtxKey).(uint)
|
||||||
|
|
||||||
var userID int
|
var userID uint
|
||||||
self := false
|
self := false
|
||||||
if userIDstr == "me" {
|
if userIDstr == "me" {
|
||||||
// Get user id from Token
|
// Get user id from Token
|
||||||
|
@ -48,7 +48,7 @@ func Enforce(permission string) func(http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userID := int(claims["uid"].(float64))
|
userID := uint(claims["uid"].(float64))
|
||||||
_, enabled := user.IsEnabled(userID)
|
_, enabled := user.IsEnabled(userID)
|
||||||
if token == nil || !token.Valid || !enabled {
|
if token == nil || !token.Valid || !enabled {
|
||||||
h.ResultErrorJSON(w, r, http.StatusUnauthorized, "Unauthorised", nil)
|
h.ResultErrorJSON(w, r, http.StatusUnauthorized, "Unauthorised", nil)
|
||||||
|
@ -21,7 +21,7 @@ func SSEAuth(next http.Handler) http.Handler {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userID := int(claims["uid"].(float64))
|
userID := uint(claims["uid"].(float64))
|
||||||
_, enabled := user.IsEnabled(userID)
|
_, enabled := user.IsEnabled(userID)
|
||||||
if token == nil || !token.Valid || !enabled || !claims.VerifyIssuer("sse", true) {
|
if token == nil || !token.Valid || !enabled || !claims.VerifyIssuer("sse", true) {
|
||||||
h.ResultErrorJSON(w, r, http.StatusUnauthorized, "Unauthorised", nil)
|
h.ResultErrorJSON(w, r, http.StatusUnauthorized, "Unauthorised", nil)
|
||||||
|
@ -8,15 +8,6 @@ import (
|
|||||||
"npm/internal/api/middleware"
|
"npm/internal/api/middleware"
|
||||||
"npm/internal/api/schema"
|
"npm/internal/api/schema"
|
||||||
"npm/internal/config"
|
"npm/internal/config"
|
||||||
"npm/internal/entity/accesslist"
|
|
||||||
"npm/internal/entity/certificate"
|
|
||||||
"npm/internal/entity/certificateauthority"
|
|
||||||
"npm/internal/entity/dnsprovider"
|
|
||||||
"npm/internal/entity/host"
|
|
||||||
"npm/internal/entity/nginxtemplate"
|
|
||||||
"npm/internal/entity/setting"
|
|
||||||
"npm/internal/entity/stream"
|
|
||||||
"npm/internal/entity/upstream"
|
|
||||||
"npm/internal/entity/user"
|
"npm/internal/entity/user"
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
"npm/internal/serverevents"
|
"npm/internal/serverevents"
|
||||||
@ -102,7 +93,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
|
|
||||||
r.With(middleware.Enforce(user.CapabilityUsersManage)).Route("/", func(r chi.Router) {
|
r.With(middleware.Enforce(user.CapabilityUsersManage)).Route("/", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Enforce(user.CapabilityUsersManage), middleware.Filters(user.GetFilterSchema())).
|
// r.With(middleware.Enforce(user.CapabilityUsersManage), middleware.Filters(user.GetFilterSchema())).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityUsersManage)).
|
||||||
Get("/", handler.GetUsers())
|
Get("/", handler.GetUsers())
|
||||||
|
|
||||||
// Specific Item
|
// Specific Item
|
||||||
@ -132,8 +124,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
r.With(middleware.EnforceSetup(true), middleware.Enforce(user.CapabilitySettingsManage)).Route("/settings", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true), middleware.Enforce(user.CapabilitySettingsManage)).Route("/settings", func(r chi.Router) {
|
||||||
r.With(middleware.Filters(setting.GetFilterSchema())).
|
// r.With(middleware.Filters(setting.GetFilterSchema())).
|
||||||
Get("/", handler.GetSettings())
|
r.Get("/", handler.GetSettings())
|
||||||
r.Get("/{name}", handler.GetSetting())
|
r.Get("/{name}", handler.GetSetting())
|
||||||
r.With(middleware.EnforceRequestSchema(schema.CreateSetting())).
|
r.With(middleware.EnforceRequestSchema(schema.CreateSetting())).
|
||||||
Post("/", handler.CreateSetting())
|
Post("/", handler.CreateSetting())
|
||||||
@ -144,7 +136,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
// Access Lists
|
// Access Lists
|
||||||
r.With(middleware.EnforceSetup(true)).Route("/access-lists", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true)).Route("/access-lists", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Filters(accesslist.GetFilterSchema()), middleware.Enforce(user.CapabilityAccessListsView)).
|
// r.With(middleware.Filters(accesslist.GetFilterSchema()), middleware.Enforce(user.CapabilityAccessListsView)).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityAccessListsView)).
|
||||||
Get("/", handler.GetAccessLists())
|
Get("/", handler.GetAccessLists())
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
@ -166,7 +159,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
// DNS Providers
|
// DNS Providers
|
||||||
r.With(middleware.EnforceSetup(true)).Route("/dns-providers", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true)).Route("/dns-providers", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Enforce(user.CapabilityDNSProvidersView), middleware.Filters(dnsprovider.GetFilterSchema())).
|
// r.With(middleware.Enforce(user.CapabilityDNSProvidersView), middleware.Filters(dnsprovider.GetFilterSchema())).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityDNSProvidersView)).
|
||||||
Get("/", handler.GetDNSProviders())
|
Get("/", handler.GetDNSProviders())
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
@ -194,7 +188,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
// Certificate Authorities
|
// Certificate Authorities
|
||||||
r.With(middleware.EnforceSetup(true)).Route("/certificate-authorities", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true)).Route("/certificate-authorities", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Enforce(user.CapabilityCertificateAuthoritiesView), middleware.Filters(certificateauthority.GetFilterSchema())).
|
// r.With(middleware.Enforce(user.CapabilityCertificateAuthoritiesView), middleware.Filters(certificateauthority.GetFilterSchema())).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityCertificateAuthoritiesView)).
|
||||||
Get("/", handler.GetCertificateAuthorities())
|
Get("/", handler.GetCertificateAuthorities())
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
@ -216,7 +211,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
// Certificates
|
// Certificates
|
||||||
r.With(middleware.EnforceSetup(true)).Route("/certificates", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true)).Route("/certificates", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Enforce(user.CapabilityCertificatesView), middleware.Filters(certificate.GetFilterSchema())).
|
// r.With(middleware.Enforce(user.CapabilityCertificatesView), middleware.Filters(certificate.GetFilterSchema())).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityCertificatesView)).
|
||||||
Get("/", handler.GetCertificates())
|
Get("/", handler.GetCertificates())
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
@ -241,7 +237,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
// Hosts
|
// Hosts
|
||||||
r.With(middleware.EnforceSetup(true)).Route("/hosts", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true)).Route("/hosts", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Enforce(user.CapabilityHostsView), middleware.Filters(host.GetFilterSchema())).
|
// r.With(middleware.Enforce(user.CapabilityHostsView), middleware.Filters(host.GetFilterSchema())).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityHostsView)).
|
||||||
Get("/", handler.GetHosts())
|
Get("/", handler.GetHosts())
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
@ -265,7 +262,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
// Nginx Templates
|
// Nginx Templates
|
||||||
r.With(middleware.EnforceSetup(true)).Route("/nginx-templates", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true)).Route("/nginx-templates", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Enforce(user.CapabilityNginxTemplatesView), middleware.Filters(nginxtemplate.GetFilterSchema())).
|
// r.With(middleware.Enforce(user.CapabilityNginxTemplatesView), middleware.Filters(nginxtemplate.GetFilterSchema())).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityNginxTemplatesView)).
|
||||||
Get("/", handler.GetNginxTemplates())
|
Get("/", handler.GetNginxTemplates())
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
@ -287,7 +285,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
// Streams
|
// Streams
|
||||||
r.With(middleware.EnforceSetup(true)).Route("/streams", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true)).Route("/streams", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Enforce(user.CapabilityStreamsView), middleware.Filters(stream.GetFilterSchema())).
|
// r.With(middleware.Enforce(user.CapabilityStreamsView), middleware.Filters(stream.GetFilterSchema())).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityStreamsView)).
|
||||||
Get("/", handler.GetStreams())
|
Get("/", handler.GetStreams())
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
@ -309,7 +308,8 @@ func applyRoutes(r chi.Router) chi.Router {
|
|||||||
// Upstreams
|
// Upstreams
|
||||||
r.With(middleware.EnforceSetup(true)).Route("/upstreams", func(r chi.Router) {
|
r.With(middleware.EnforceSetup(true)).Route("/upstreams", func(r chi.Router) {
|
||||||
// List
|
// List
|
||||||
r.With(middleware.Enforce(user.CapabilityHostsView), middleware.Filters(upstream.GetFilterSchema())).
|
// r.With(middleware.Enforce(user.CapabilityHostsView), middleware.Filters(upstream.GetFilterSchema())).
|
||||||
|
r.With(middleware.Enforce(user.CapabilityHostsView)).
|
||||||
Get("/", handler.GetUpstreams())
|
Get("/", handler.GetUpstreams())
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
|
16
backend/internal/config/acmesh.go
Normal file
16
backend/internal/config/acmesh.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type acmesh struct {
|
||||||
|
Home string `json:"home" envconfig:"optional,default=/data/.acme.sh"`
|
||||||
|
ConfigHome string `json:"config_home" envconfig:"optional,default=/data/.acme.sh/config"`
|
||||||
|
CertHome string `json:"cert_home" envconfig:"optional,default=/data/.acme.sh/certs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWellknown returns the well known path
|
||||||
|
func (a *acmesh) GetWellknown() string {
|
||||||
|
return fmt.Sprintf("%s/.well-known", a.Home)
|
||||||
|
}
|
79
backend/internal/config/db.go
Normal file
79
backend/internal/config/db.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DatabaseSqlite = "sqlite"
|
||||||
|
DatabasePostgres = "postgres"
|
||||||
|
DatabaseMysql = "mysql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type db struct {
|
||||||
|
Driver string `json:"driver" envconfig:"optional,default=sqlite"`
|
||||||
|
Host string `json:"host" envconfig:"optional,default="`
|
||||||
|
Port int `json:"port" envconfig:"optional,default="`
|
||||||
|
Username string `json:"username" envconfig:"optional,default="`
|
||||||
|
Password string `json:"password" envconfig:"optional,default="`
|
||||||
|
Name string `json:"name" envconfig:"optional,default="`
|
||||||
|
SSLMode string `json:"sslmode" envconfig:"optional,default=deisable"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDriver returns the lowercase driver name
|
||||||
|
func (d *db) GetDriver() string {
|
||||||
|
return strings.ToLower(d.Driver)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGormConnectURL is used by Gorm
|
||||||
|
func (d *db) GetGormConnectURL() string {
|
||||||
|
switch d.GetDriver() {
|
||||||
|
case DatabaseSqlite:
|
||||||
|
return fmt.Sprintf("%s/nginxproxymanager.db", Configuration.DataFolder)
|
||||||
|
case DatabasePostgres:
|
||||||
|
return fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=UTC",
|
||||||
|
d.Host,
|
||||||
|
d.Username,
|
||||||
|
d.Password,
|
||||||
|
d.Name,
|
||||||
|
d.Port,
|
||||||
|
d.SSLMode,
|
||||||
|
)
|
||||||
|
case DatabaseMysql:
|
||||||
|
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
||||||
|
d.Username,
|
||||||
|
d.Password,
|
||||||
|
d.Host,
|
||||||
|
d.Port,
|
||||||
|
d.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDBMateConnectURL is used by Dbmate
|
||||||
|
func (d *db) GetDBMateConnectURL() string {
|
||||||
|
switch d.GetDriver() {
|
||||||
|
case DatabaseSqlite:
|
||||||
|
return fmt.Sprintf("sqlite:%s/nginxproxymanager.db", Configuration.DataFolder)
|
||||||
|
case DatabasePostgres:
|
||||||
|
return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
|
||||||
|
d.Username,
|
||||||
|
d.Password,
|
||||||
|
d.Host,
|
||||||
|
d.Port,
|
||||||
|
d.Name,
|
||||||
|
d.SSLMode,
|
||||||
|
)
|
||||||
|
case DatabaseMysql:
|
||||||
|
return fmt.Sprintf("mysql://%s:%s@%s:%d/%s",
|
||||||
|
d.Username,
|
||||||
|
d.Password,
|
||||||
|
d.Host,
|
||||||
|
d.Port,
|
||||||
|
d.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,22 +29,12 @@ type log struct {
|
|||||||
Format string `json:"format" envconfig:"optional,default=nice"`
|
Format string `json:"format" envconfig:"optional,default=nice"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type acmesh struct {
|
|
||||||
Home string `json:"home" envconfig:"optional,default=/data/.acme.sh"`
|
|
||||||
ConfigHome string `json:"config_home" envconfig:"optional,default=/data/.acme.sh/config"`
|
|
||||||
CertHome string `json:"cert_home" envconfig:"optional,default=/data/.acme.sh/certs"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configuration is the main configuration object
|
// Configuration is the main configuration object
|
||||||
var Configuration struct {
|
var Configuration struct {
|
||||||
DataFolder string `json:"data_folder" envconfig:"optional,default=/data"`
|
DataFolder string `json:"data_folder" envconfig:"optional,default=/data"`
|
||||||
DisableIPV4 bool `json:"disable_ipv4" envconfig:"optional"`
|
DisableIPV4 bool `json:"disable_ipv4" envconfig:"optional"`
|
||||||
DisableIPV6 bool `json:"disable_ipv6" envconfig:"optional"`
|
DisableIPV6 bool `json:"disable_ipv6" envconfig:"optional"`
|
||||||
Acmesh acmesh `json:"acmesh"`
|
Acmesh acmesh `json:"acmesh"`
|
||||||
|
DB db `json:"db"`
|
||||||
Log log `json:"log"`
|
Log log `json:"log"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetWellknown returns the well known path
|
|
||||||
func (a *acmesh) GetWellknown() string {
|
|
||||||
return fmt.Sprintf("%s/.well-known", a.Home)
|
|
||||||
}
|
|
||||||
|
80
backend/internal/database/db.go
Normal file
80
backend/internal/database/db.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"npm/internal/config"
|
||||||
|
"npm/internal/logger"
|
||||||
|
|
||||||
|
"github.com/glebarez/sqlite"
|
||||||
|
"github.com/rotisserie/eris"
|
||||||
|
"gorm.io/driver/mysql"
|
||||||
|
"gorm.io/driver/postgres"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
var dbInstance *gorm.DB
|
||||||
|
|
||||||
|
// NewDB creates a new connection
|
||||||
|
func NewDB() {
|
||||||
|
logger.Info("Creating new DB instance using %s", strings.ToLower(config.Configuration.DB.Driver))
|
||||||
|
db, err := connect()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("DatabaseConnectError", err)
|
||||||
|
} else if db != nil {
|
||||||
|
dbInstance = db
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDB returns an existing or new instance
|
||||||
|
func GetDB() *gorm.DB {
|
||||||
|
if dbInstance == nil {
|
||||||
|
NewDB()
|
||||||
|
}
|
||||||
|
return dbInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
func connect() (*gorm.DB, error) {
|
||||||
|
var d gorm.Dialector
|
||||||
|
dsn := config.Configuration.DB.GetGormConnectURL()
|
||||||
|
switch strings.ToLower(config.Configuration.DB.Driver) {
|
||||||
|
|
||||||
|
case config.DatabaseSqlite:
|
||||||
|
// autocreate(dsn)
|
||||||
|
d = sqlite.Open(dsn)
|
||||||
|
|
||||||
|
case config.DatabasePostgres:
|
||||||
|
d = postgres.Open(dsn)
|
||||||
|
|
||||||
|
case config.DatabaseMysql:
|
||||||
|
d = mysql.Open(dsn)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, eris.New(fmt.Sprintf("Database driver %s is not supported. Valid options are: %s, %s or %s", config.Configuration.DB.Driver, config.DatabaseSqlite, config.DatabasePostgres, config.DatabaseMysql))
|
||||||
|
}
|
||||||
|
|
||||||
|
return gorm.Open(d, &gorm.Config{
|
||||||
|
// see: https://gorm.io/docs/gorm_config.html
|
||||||
|
NamingStrategy: schema.NamingStrategy{
|
||||||
|
SingularTable: true,
|
||||||
|
NoLowerCase: true,
|
||||||
|
},
|
||||||
|
PrepareStmt: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func autocreate(dbFile string) {
|
||||||
|
if _, err := os.Stat(dbFile); os.IsNotExist(err) {
|
||||||
|
// Create it
|
||||||
|
logger.Info("Creating Sqlite DB: %s", dbFile)
|
||||||
|
// nolint: gosec
|
||||||
|
_, err = os.Create(dbFile)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("FileCreateError", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
@ -1,46 +1,8 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/model"
|
|
||||||
"npm/internal/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// DateFormat for DateFormat
|
// DateFormat for DateFormat
|
||||||
DateFormat = "2006-01-02"
|
DateFormat = "2006-01-02"
|
||||||
// DateTimeFormat for DateTimeFormat
|
// DateTimeFormat for DateTimeFormat
|
||||||
DateTimeFormat = "2006-01-02T15:04:05"
|
DateTimeFormat = "2006-01-02T15:04:05"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByQuery returns a row given a query, populating the model given
|
|
||||||
func GetByQuery(model interface{}, query string, params []interface{}) error {
|
|
||||||
db := GetInstance()
|
|
||||||
if db != nil {
|
|
||||||
err := db.Get(model, query, params...)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildOrderBySQL takes a `Sort` slice and constructs a query fragment
|
|
||||||
func BuildOrderBySQL(columns []string, sort *[]model.Sort) (string, []model.Sort) {
|
|
||||||
var sortStrings []string
|
|
||||||
var newSort []model.Sort
|
|
||||||
for _, sortItem := range *sort {
|
|
||||||
if util.SliceContainsItem(columns, sortItem.Field) {
|
|
||||||
sortStrings = append(sortStrings, fmt.Sprintf("`%s` %s", sortItem.Field, sortItem.Direction))
|
|
||||||
newSort = append(newSort, sortItem)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sortStrings) > 0 {
|
|
||||||
return fmt.Sprintf("ORDER BY %s", strings.Join(sortStrings, ", ")), newSort
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", newSort
|
|
||||||
}
|
|
||||||
|
@ -1,203 +1,44 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"net/url"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/embed"
|
"npm/embed"
|
||||||
|
"npm/internal/config"
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
"npm/internal/util"
|
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/amacneil/dbmate/v2/pkg/dbmate"
|
||||||
"github.com/rotisserie/eris"
|
_ "github.com/amacneil/dbmate/v2/pkg/driver/postgres"
|
||||||
|
_ "github.com/amacneil/dbmate/v2/pkg/driver/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MigrationConfiguration options for the migrator.
|
|
||||||
type MigrationConfiguration struct {
|
|
||||||
Table string `json:"table"`
|
|
||||||
mux sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default migrator configuration
|
|
||||||
var mConfiguration = MigrationConfiguration{
|
|
||||||
Table: "migration",
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigureMigrator and will return error if missing required fields.
|
|
||||||
func ConfigureMigrator(c *MigrationConfiguration) error {
|
|
||||||
// ensure updates to the config are atomic
|
|
||||||
mConfiguration.mux.Lock()
|
|
||||||
defer mConfiguration.mux.Unlock()
|
|
||||||
if c == nil {
|
|
||||||
return eris.Errorf("a non nil Configuration is mandatory")
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(c.Table) != "" {
|
|
||||||
mConfiguration.Table = c.Table
|
|
||||||
}
|
|
||||||
mConfiguration.Table = c.Table
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type afterMigrationComplete func()
|
type afterMigrationComplete func()
|
||||||
|
|
||||||
// Migrate will perform the migration from start to finish
|
// Migrate will bring the db up to date
|
||||||
func Migrate(followup afterMigrationComplete) bool {
|
func Migrate(followup afterMigrationComplete) bool {
|
||||||
logger.Info("Migration: Started")
|
dbURL := config.Configuration.DB.GetDBMateConnectURL()
|
||||||
|
u, _ := url.Parse(dbURL)
|
||||||
|
db := dbmate.New(u)
|
||||||
|
db.FS = embed.MigrationFiles
|
||||||
|
db.MigrationsDir = []string{fmt.Sprintf("./migrations/%s", config.Configuration.DB.GetDriver())}
|
||||||
|
|
||||||
// Try to connect to the database sleeping for 15 seconds in between
|
migrations, err := db.FindMigrations()
|
||||||
var db *sqlx.DB
|
|
||||||
for {
|
|
||||||
db = GetInstance()
|
|
||||||
if db == nil {
|
|
||||||
logger.Warn("Database is unavailable for migration, retrying in 15 seconds")
|
|
||||||
time.Sleep(15 * time.Second)
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for migration table existence
|
|
||||||
if !tableExists(db, mConfiguration.Table) {
|
|
||||||
err := createMigrationTable(db)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("MigratorError", err)
|
logger.Error("MigrationError", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
logger.Info("Migration: Migration Table created")
|
|
||||||
|
for _, m := range migrations {
|
||||||
|
logger.Debug("%s: %s", m.Version, m.FilePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DO MIGRATION
|
err = db.CreateAndMigrate()
|
||||||
migrationCount, migrateErr := performFileMigrations(db)
|
if err != nil {
|
||||||
if migrateErr != nil {
|
logger.Error("MigrationError", err)
|
||||||
logger.Error("MigratorError", migrateErr)
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if migrateErr == nil {
|
|
||||||
logger.Info("Migration: Completed %v migration files", migrationCount)
|
|
||||||
followup()
|
followup()
|
||||||
return true
|
return true
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// createMigrationTable performs a query to create the migration table
|
|
||||||
// with the name specified in the configuration
|
|
||||||
func createMigrationTable(db *sqlx.DB) error {
|
|
||||||
logger.Info("Migration: Creating Migration Table: %v", mConfiguration.Table)
|
|
||||||
// nolint:lll
|
|
||||||
query := fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%v` (filename TEXT PRIMARY KEY, migrated_on INTEGER NOT NULL DEFAULT 0)", mConfiguration.Table)
|
|
||||||
_, err := db.Exec(query)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// tableExists will check the database for the existence of the specified table.
|
|
||||||
func tableExists(db *sqlx.DB, tableName string) bool {
|
|
||||||
query := `SELECT CASE name WHEN $1 THEN true ELSE false END AS found FROM sqlite_master WHERE type='table' AND name = $1`
|
|
||||||
|
|
||||||
row := db.QueryRowx(query, tableName)
|
|
||||||
if row == nil {
|
|
||||||
logger.Error("MigratorError", eris.Errorf("Cannot check if table exists, no row returned: %v", tableName))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var exists *bool
|
|
||||||
if err := row.Scan(&exists); err != nil {
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
logger.Error("MigratorError", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return *exists
|
|
||||||
}
|
|
||||||
|
|
||||||
// performFileMigrations will perform the actual migration,
|
|
||||||
// importing files and updating the database with the rows imported.
|
|
||||||
func performFileMigrations(db *sqlx.DB) (int, error) {
|
|
||||||
var importedCount = 0
|
|
||||||
|
|
||||||
// Grab a list of previously ran migrations from the database:
|
|
||||||
previousMigrations, prevErr := getPreviousMigrations(db)
|
|
||||||
if prevErr != nil {
|
|
||||||
return importedCount, prevErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// List up the ".sql" files on disk
|
|
||||||
err := fs.WalkDir(embed.MigrationFiles, ".", func(file string, d fs.DirEntry, err error) error {
|
|
||||||
if !d.IsDir() {
|
|
||||||
shortFile := filepath.Base(file)
|
|
||||||
|
|
||||||
// Check if this file already exists in the previous migrations
|
|
||||||
// and if so, ignore it
|
|
||||||
if util.SliceContainsItem(previousMigrations, shortFile) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Info("Migration: Importing %v", shortFile)
|
|
||||||
|
|
||||||
sqlContents, ioErr := embed.MigrationFiles.ReadFile(path.Clean(file))
|
|
||||||
if ioErr != nil {
|
|
||||||
return ioErr
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlString := string(sqlContents)
|
|
||||||
|
|
||||||
tx := db.MustBegin()
|
|
||||||
if _, execErr := tx.Exec(sqlString); execErr != nil {
|
|
||||||
return execErr
|
|
||||||
}
|
|
||||||
if commitErr := tx.Commit(); commitErr != nil {
|
|
||||||
return commitErr
|
|
||||||
}
|
|
||||||
if markErr := markMigrationSuccessful(db, shortFile); markErr != nil {
|
|
||||||
return markErr
|
|
||||||
}
|
|
||||||
|
|
||||||
importedCount++
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return importedCount, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// getPreviousMigrations will query the migration table for names
|
|
||||||
// of migrations we can ignore because they should have already
|
|
||||||
// been imported
|
|
||||||
func getPreviousMigrations(db *sqlx.DB) ([]string, error) {
|
|
||||||
var existingMigrations []string
|
|
||||||
// nolint:gosec
|
|
||||||
query := fmt.Sprintf("SELECT filename FROM `%v` ORDER BY filename", mConfiguration.Table)
|
|
||||||
rows, err := db.Queryx(query)
|
|
||||||
if err != nil {
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return existingMigrations, nil
|
|
||||||
}
|
|
||||||
return existingMigrations, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
var filename *string
|
|
||||||
err := rows.Scan(&filename)
|
|
||||||
if err != nil {
|
|
||||||
return existingMigrations, err
|
|
||||||
}
|
|
||||||
existingMigrations = append(existingMigrations, *filename)
|
|
||||||
}
|
|
||||||
|
|
||||||
return existingMigrations, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// markMigrationSuccessful will add a row to the migration table
|
|
||||||
func markMigrationSuccessful(db *sqlx.DB, filename string) error {
|
|
||||||
// nolint:gosec
|
|
||||||
query := fmt.Sprintf("INSERT INTO `%v` (filename) VALUES ($1)", mConfiguration.Table)
|
|
||||||
_, err := db.Exec(query, filename)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"npm/internal/config"
|
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CheckSetup Quick check by counting the number of users in the database
|
|
||||||
func CheckSetup() {
|
|
||||||
query := `SELECT COUNT(*) FROM "user" WHERE is_deleted = $1 AND is_disabled = $1 AND is_system = $1`
|
|
||||||
db := GetInstance()
|
|
||||||
|
|
||||||
if db != nil {
|
|
||||||
row := db.QueryRowx(query, false)
|
|
||||||
var totalRows int
|
|
||||||
queryErr := row.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Error("SetupError", queryErr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if totalRows == 0 {
|
|
||||||
logger.Warn("No users found, starting in Setup Mode")
|
|
||||||
} else {
|
|
||||||
config.IsSetup = true
|
|
||||||
logger.Info("Application is setup")
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.ErrorReporting {
|
|
||||||
logger.Warn("Error reporting is enabled - Application Errors WILL be sent to Sentry, you can disable this in the Settings interface")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.Error("DatabaseError", errors.ErrDatabaseUnavailable)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
package database
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"npm/internal/config"
|
|
||||||
"npm/internal/logger"
|
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
|
|
||||||
// Blank import for Sqlite
|
|
||||||
_ "modernc.org/sqlite"
|
|
||||||
)
|
|
||||||
|
|
||||||
var dbInstance *sqlx.DB
|
|
||||||
|
|
||||||
// NewDB creates a new connection
|
|
||||||
func NewDB() {
|
|
||||||
logger.Info("Creating new DB instance")
|
|
||||||
db := SqliteDB()
|
|
||||||
if db != nil {
|
|
||||||
dbInstance = db
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetInstance returns an existing or new instance
|
|
||||||
func GetInstance() *sqlx.DB {
|
|
||||||
if dbInstance == nil {
|
|
||||||
NewDB()
|
|
||||||
} else if err := dbInstance.Ping(); err != nil {
|
|
||||||
NewDB()
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbInstance
|
|
||||||
}
|
|
||||||
|
|
||||||
// SqliteDB Create sqlite client
|
|
||||||
func SqliteDB() *sqlx.DB {
|
|
||||||
dbFile := fmt.Sprintf("%s/nginxproxymanager.db", config.Configuration.DataFolder)
|
|
||||||
autocreate(dbFile)
|
|
||||||
db, err := sqlx.Open("sqlite", dbFile)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("SqliteError", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return db
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commit will close and reopen the db file
|
|
||||||
func Commit() *sqlx.DB {
|
|
||||||
if dbInstance != nil {
|
|
||||||
err := dbInstance.Close()
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("DatabaseCloseError", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NewDB()
|
|
||||||
return dbInstance
|
|
||||||
}
|
|
||||||
|
|
||||||
func autocreate(dbFile string) {
|
|
||||||
if _, err := os.Stat(dbFile); os.IsNotExist(err) {
|
|
||||||
// Create it
|
|
||||||
logger.Info("Creating Sqlite DB: %s", dbFile)
|
|
||||||
// nolint: gosec
|
|
||||||
_, err = os.Create(dbFile)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("FileCreateError", err)
|
|
||||||
}
|
|
||||||
Commit()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package accesslist
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,122 +1,41 @@
|
|||||||
package accesslist
|
package accesslist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a row by ID
|
// GetByID finds a row by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create will create a row from this model
|
|
||||||
func Create(m *Model) (int, error) {
|
|
||||||
if m.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create access list when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
user_id,
|
|
||||||
name,
|
|
||||||
meta,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:user_id,
|
|
||||||
:name,
|
|
||||||
:meta,
|
|
||||||
:is_deleted
|
|
||||||
)`, m)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will Update a row from this model
|
|
||||||
func Update(m *Model) error {
|
|
||||||
if m.ID == 0 {
|
|
||||||
return eris.New("Cannot update access list when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
m.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
user_id = :user_id,
|
|
||||||
name = :name,
|
|
||||||
meta = :meta,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, m)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a list of access lists
|
// List will return a list of access lists
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "name",
|
Field: "name",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Error("ListAccessListsError", queryErr)
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Error("ListAccessListsError", err)
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
|
@ -1,77 +1,54 @@
|
|||||||
package accesslist
|
package accesslist
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/entity/user"
|
"npm/internal/entity/user"
|
||||||
"npm/internal/types"
|
"npm/internal/types"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
"github.com/rotisserie/eris"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "access_list"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the access list model
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
UserID int `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
UserID int `json:"user_id" db:"user_id" filter:"user_id,integer"`
|
Meta types.JSONB `json:"meta" gorm:"column:meta"`
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
|
||||||
Meta types.JSONB `json:"meta" db:"meta"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
// Expansions
|
// Expansions
|
||||||
User *user.Model `json:"user,omitempty"`
|
User *user.Model `json:"user,omitempty" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "access_list"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
|
||||||
|
|
||||||
if m.UserID == 0 {
|
if m.UserID == 0 {
|
||||||
return eris.Errorf("User ID must be specified")
|
return eris.Errorf("User ID must be specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = Create(m)
|
result := db.Save(m)
|
||||||
} else {
|
return result.Error
|
||||||
err = Update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a access list as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package accesslist
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for the list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -1,11 +1,7 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a auth by ID
|
// GetByID finds a auth by ID
|
||||||
@ -16,12 +12,17 @@ func GetByID(id int) (Model, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetByUserIDType finds a user by email
|
// GetByUserIDType finds a user by email
|
||||||
func GetByUserIDType(userID int, authType string) (Model, error) {
|
func GetByUserIDType(userID uint, authType string) (Model, error) {
|
||||||
var m Model
|
var auth Model
|
||||||
err := m.LoadByUserIDType(userID, authType)
|
db := database.GetDB()
|
||||||
return m, err
|
result := db.
|
||||||
|
Where("user_id = ?", userID).
|
||||||
|
Where("type = ?", authType).
|
||||||
|
First(&auth)
|
||||||
|
return auth, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Create will create a Auth from this model
|
// Create will create a Auth from this model
|
||||||
func Create(auth *Model) (int, error) {
|
func Create(auth *Model) (int, error) {
|
||||||
if auth.ID != 0 {
|
if auth.ID != 0 {
|
||||||
@ -59,7 +60,9 @@ func Create(auth *Model) (int, error) {
|
|||||||
|
|
||||||
return int(last), nil
|
return int(last), nil
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
// Update will Update a Auth from this model
|
// Update will Update a Auth from this model
|
||||||
func Update(auth *Model) error {
|
func Update(auth *Model) error {
|
||||||
if auth.ID == 0 {
|
if auth.ID == 0 {
|
||||||
@ -81,3 +84,4 @@ func Update(auth *Model) error {
|
|||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
@ -1,52 +1,49 @@
|
|||||||
package auth
|
package auth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/types"
|
"npm/internal/entity"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
"github.com/rotisserie/eris"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tableName = "auth"
|
|
||||||
|
|
||||||
// TypePassword is the Password Type
|
// TypePassword is the Password Type
|
||||||
TypePassword = "password"
|
TypePassword = "password"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Model is the user model
|
// Model is the model
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id"`
|
entity.ModelBase
|
||||||
UserID int `json:"user_id" db:"user_id"`
|
UserID uint `json:"user_id" gorm:"column:user_id"`
|
||||||
Type string `json:"type" db:"type"`
|
Type string `json:"type" gorm:"column:type;default:password"`
|
||||||
Secret string `json:"secret,omitempty" db:"secret"`
|
Secret string `json:"secret,omitempty" gorm:"column:secret"`
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on"`
|
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "auth"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id int) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByUserIDType will load from an ID
|
// LoadByUserIDType will load from an ID
|
||||||
func (m *Model) LoadByUserIDType(userID int, authType string) error {
|
func (m *Model) LoadByUserIDType(userID int, authType string) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE user_id = ? AND type = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{userID, authType}
|
result := db.
|
||||||
return m.getByQuery(query, params)
|
Where("user_id = ?", userID).
|
||||||
|
Where("type = ?", authType).
|
||||||
|
First(&m)
|
||||||
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Touch will update model's timestamp(s)
|
// Touch will update model's timestamp(s)
|
||||||
func (m *Model) Touch(created bool) {
|
func (m *Model) Touch(created bool) {
|
||||||
var d types.DBDate
|
var d types.DBDate
|
||||||
@ -56,18 +53,14 @@ func (m *Model) Touch(created bool) {
|
|||||||
}
|
}
|
||||||
m.ModifiedOn = d
|
m.ModifiedOn = d
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
db := database.GetDB()
|
||||||
|
// todo: touch? not sure that save does this or not?
|
||||||
if m.ID == 0 {
|
result := db.Save(m)
|
||||||
m.ID, err = Create(m)
|
return result.Error
|
||||||
} else {
|
|
||||||
err = Update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPassword will generate a hashed password based on given string
|
// SetPassword will generate a hashed password based on given string
|
||||||
|
11
backend/internal/entity/capability.go
Normal file
11
backend/internal/entity/capability.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
// Capability is the db model
|
||||||
|
type Capability struct {
|
||||||
|
Name string `json:"name" gorm:"column:name;primaryKey" filter:"name,string"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName overrides the table name used by gorm
|
||||||
|
func (Capability) TableName() string {
|
||||||
|
return "capability"
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
package certificate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,142 +1,54 @@
|
|||||||
package certificate
|
package certificate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/jobqueue"
|
"npm/internal/jobqueue"
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a row by ID
|
// GetByID finds a row by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create will create a row from this model
|
// GetByStatus will select rows that are ready for requesting
|
||||||
func Create(certificate *Model) (int, error) {
|
func GetByStatus(status string) ([]Model, error) {
|
||||||
if certificate.ID != 0 {
|
items := make([]Model, 0)
|
||||||
return 0, eris.New("Cannot create certificate when model already has an ID")
|
db := database.GetDB()
|
||||||
}
|
result := db.
|
||||||
|
Joins("INNER JOIN certificate_authority ON certificate_authority.id = certificate.certificate_authority_id AND certificate_authority.is_deleted = ?", 0).
|
||||||
certificate.Touch(true)
|
Where("type IN ?", []string{"http", "dns"}).
|
||||||
|
Where("status = ?", status).
|
||||||
db := database.GetInstance()
|
Where("certificate_authority_id > ?", 0).
|
||||||
// nolint: gosec
|
Find(&items)
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
return items, result.Error
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
user_id,
|
|
||||||
type,
|
|
||||||
certificate_authority_id,
|
|
||||||
dns_provider_id,
|
|
||||||
name,
|
|
||||||
domain_names,
|
|
||||||
expires_on,
|
|
||||||
status,
|
|
||||||
error_message,
|
|
||||||
meta,
|
|
||||||
is_ecc,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:user_id,
|
|
||||||
:type,
|
|
||||||
:certificate_authority_id,
|
|
||||||
:dns_provider_id,
|
|
||||||
:name,
|
|
||||||
:domain_names,
|
|
||||||
:expires_on,
|
|
||||||
:status,
|
|
||||||
:error_message,
|
|
||||||
:meta,
|
|
||||||
:is_ecc,
|
|
||||||
:is_deleted
|
|
||||||
)`, certificate)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will Update a Auth from this model
|
|
||||||
func Update(certificate *Model) error {
|
|
||||||
if certificate.ID == 0 {
|
|
||||||
return eris.New("Cannot update certificate when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
certificate.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
type = :type,
|
|
||||||
user_id = :user_id,
|
|
||||||
certificate_authority_id = :certificate_authority_id,
|
|
||||||
dns_provider_id = :dns_provider_id,
|
|
||||||
name = :name,
|
|
||||||
domain_names = :domain_names,
|
|
||||||
expires_on = :expires_on,
|
|
||||||
status = :status,
|
|
||||||
error_message = :error_message,
|
|
||||||
meta = :meta,
|
|
||||||
is_ecc = :is_ecc,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, certificate)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List will return a list of certificates
|
// List will return a list of certificates
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "name",
|
Field: "name",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if expand != nil {
|
if expand != nil {
|
||||||
@ -148,7 +60,7 @@ func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (Lis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
@ -160,33 +72,6 @@ func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (Lis
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByStatus will select rows that are ready for requesting
|
|
||||||
func GetByStatus(status string) ([]Model, error) {
|
|
||||||
models := make([]Model, 0)
|
|
||||||
db := database.GetInstance()
|
|
||||||
|
|
||||||
query := fmt.Sprintf(`
|
|
||||||
SELECT
|
|
||||||
t.*
|
|
||||||
FROM "%s" t
|
|
||||||
INNER JOIN "certificate_authority" c ON c."id" = t."certificate_authority_id"
|
|
||||||
WHERE
|
|
||||||
t."type" IN ("http", "dns") AND
|
|
||||||
t."status" = ? AND
|
|
||||||
t."certificate_authority_id" > 0 AND
|
|
||||||
t."is_deleted" = 0
|
|
||||||
`, tableName)
|
|
||||||
|
|
||||||
params := []interface{}{StatusReady}
|
|
||||||
err := db.Select(&models, query, params...)
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
logger.Error("GetByStatusError", err)
|
|
||||||
logger.Debug("Query: %s -- %+v", query, params)
|
|
||||||
}
|
|
||||||
|
|
||||||
return models, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddPendingJobs is intended to be used at startup to add
|
// AddPendingJobs is intended to be used at startup to add
|
||||||
// anything pending to the JobQueue just once, based on
|
// anything pending to the JobQueue just once, based on
|
||||||
// the database row status
|
// the database row status
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"npm/internal/acme"
|
"npm/internal/acme"
|
||||||
"npm/internal/config"
|
"npm/internal/config"
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/entity/certificateauthority"
|
"npm/internal/entity/certificateauthority"
|
||||||
"npm/internal/entity/dnsprovider"
|
"npm/internal/entity/dnsprovider"
|
||||||
"npm/internal/entity/user"
|
"npm/internal/entity/user"
|
||||||
@ -22,8 +23,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tableName = "certificate"
|
|
||||||
|
|
||||||
// TypeCustom custom cert type
|
// TypeCustom custom cert type
|
||||||
TypeCustom = "custom"
|
TypeCustom = "custom"
|
||||||
// TypeHTTP http cert type
|
// TypeHTTP http cert type
|
||||||
@ -43,54 +42,40 @@ const (
|
|||||||
StatusProvided = "provided"
|
StatusProvided = "provided"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Model is the user model
|
// Model is the model
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
ExpiresOn types.NullableDBDate `json:"expires_on" gorm:"column:expires_on" filter:"expires_on,integer"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
Type string `json:"type" gorm:"column:type" filter:"type,string"`
|
||||||
ExpiresOn types.NullableDBDate `json:"expires_on" db:"expires_on" filter:"expires_on,integer"`
|
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
|
||||||
Type string `json:"type" db:"type" filter:"type,string"`
|
CertificateAuthorityID uint `json:"certificate_authority_id" gorm:"column:certificate_authority_id" filter:"certificate_authority_id,integer"`
|
||||||
UserID int `json:"user_id" db:"user_id" filter:"user_id,integer"`
|
DNSProviderID uint `json:"dns_provider_id" gorm:"column:dns_provider_id" filter:"dns_provider_id,integer"`
|
||||||
CertificateAuthorityID int `json:"certificate_authority_id" db:"certificate_authority_id" filter:"certificate_authority_id,integer"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
DNSProviderID int `json:"dns_provider_id" db:"dns_provider_id" filter:"dns_provider_id,integer"`
|
DomainNames types.JSONB `json:"domain_names" gorm:"column:domain_names" filter:"domain_names,string"`
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
Status string `json:"status" gorm:"column:status" filter:"status,string"`
|
||||||
DomainNames types.JSONB `json:"domain_names" db:"domain_names" filter:"domain_names,string"`
|
ErrorMessage string `json:"error_message" gorm:"column:error_message" filter:"error_message,string"`
|
||||||
Status string `json:"status" db:"status" filter:"status,string"`
|
Meta types.JSONB `json:"-" gorm:"column:meta"`
|
||||||
ErrorMessage string `json:"error_message" db:"error_message" filter:"error_message,string"`
|
IsECC bool `json:"is_ecc" gorm:"column:is_ecc" filter:"is_ecc,bool"`
|
||||||
Meta types.JSONB `json:"-" db:"meta"`
|
|
||||||
IsECC bool `json:"is_ecc" db:"is_ecc" filter:"is_ecc,bool"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
// Expansions:
|
// Expansions:
|
||||||
CertificateAuthority *certificateauthority.Model `json:"certificate_authority,omitempty"`
|
CertificateAuthority *certificateauthority.Model `json:"certificate_authority,omitempty" gorm:"-"`
|
||||||
DNSProvider *dnsprovider.Model `json:"dns_provider,omitempty"`
|
DNSProvider *dnsprovider.Model `json:"dns_provider,omitempty" gorm:"-"`
|
||||||
User *user.Model `json:"user,omitempty"`
|
User *user.Model `json:"user,omitempty" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "certificate"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
|
||||||
|
|
||||||
if m.UserID == 0 {
|
if m.UserID == 0 {
|
||||||
return eris.Errorf("User ID must be specified")
|
return eris.Errorf("User ID must be specified")
|
||||||
}
|
}
|
||||||
@ -108,26 +93,22 @@ func (m *Model) Save() error {
|
|||||||
// ensure name is trimmed of whitespace
|
// ensure name is trimmed of whitespace
|
||||||
m.Name = strings.TrimSpace(m.Name)
|
m.Name = strings.TrimSpace(m.Name)
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = Create(m)
|
result := db.Save(m)
|
||||||
} else {
|
return result.Error
|
||||||
err = Update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a certificate as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
|
|
||||||
// todo: delete from acme.sh as well
|
// todo: delete from acme.sh as well
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate will make sure the data given is expected. This object is a bit complicated,
|
// Validate will make sure the data given is expected. This object is a bit complicated,
|
||||||
@ -304,8 +285,8 @@ func (m *Model) GetTemplate() Template {
|
|||||||
|
|
||||||
return Template{
|
return Template{
|
||||||
ID: m.ID,
|
ID: m.ID,
|
||||||
CreatedOn: m.CreatedOn.Time.String(),
|
CreatedAt: fmt.Sprintf("%d", m.CreatedAt), // todo: nice date string
|
||||||
ModifiedOn: m.ModifiedOn.Time.String(),
|
UpdatedAt: fmt.Sprintf("%d", m.UpdatedAt), // todo: nice date string
|
||||||
ExpiresOn: m.ExpiresOn.AsString(),
|
ExpiresOn: m.ExpiresOn.AsString(),
|
||||||
Type: m.Type,
|
Type: m.Type,
|
||||||
UserID: m.UserID,
|
UserID: m.UserID,
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package certificate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for users list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -2,14 +2,14 @@ package certificate
|
|||||||
|
|
||||||
// Template is the model given to the template parser, converted from the Model
|
// Template is the model given to the template parser, converted from the Model
|
||||||
type Template struct {
|
type Template struct {
|
||||||
ID int
|
ID uint
|
||||||
CreatedOn string
|
CreatedAt string
|
||||||
ModifiedOn string
|
UpdatedAt string
|
||||||
ExpiresOn string
|
ExpiresOn string
|
||||||
Type string
|
Type string
|
||||||
UserID int
|
UserID uint
|
||||||
CertificateAuthorityID int
|
CertificateAuthorityID uint
|
||||||
DNSProviderID int
|
DNSProviderID uint
|
||||||
Name string
|
Name string
|
||||||
DomainNames []string
|
DomainNames []string
|
||||||
Status string
|
Status string
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package certificateauthority
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,128 +1,41 @@
|
|||||||
package certificateauthority
|
package certificateauthority
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a row by ID
|
// GetByID finds a row by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create will create a row from this model
|
|
||||||
func Create(ca *Model) (int, error) {
|
|
||||||
if ca.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create certificate authority when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
ca.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
name,
|
|
||||||
acmesh_server,
|
|
||||||
ca_bundle,
|
|
||||||
max_domains,
|
|
||||||
is_wildcard_supported,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:name,
|
|
||||||
:acmesh_server,
|
|
||||||
:ca_bundle,
|
|
||||||
:max_domains,
|
|
||||||
:is_wildcard_supported,
|
|
||||||
:is_deleted
|
|
||||||
)`, ca)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will Update a row from this model
|
|
||||||
func Update(ca *Model) error {
|
|
||||||
if ca.ID == 0 {
|
|
||||||
return eris.New("Cannot update certificate authority when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
ca.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
name = :name,
|
|
||||||
acmesh_server = :acmesh_server,
|
|
||||||
ca_bundle = :ca_bundle,
|
|
||||||
max_domains = :max_domains,
|
|
||||||
is_wildcard_supported = :is_wildcard_supported,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, ca)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a list of certificates
|
// List will return a list of certificates
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "name",
|
Field: "name",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Error("ListCertificateAuthoritiesError", queryErr)
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Error("ListCertificateAuthoritiesError", err)
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
|
@ -1,78 +1,55 @@
|
|||||||
package certificateauthority
|
package certificateauthority
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
"npm/internal/errors"
|
||||||
"npm/internal/types"
|
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
"github.com/rotisserie/eris"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "certificate_authority"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the user model
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
AcmeshServer string `json:"acmesh_server" gorm:"column:acmesh_server" filter:"acmesh_server,string"`
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
CABundle string `json:"ca_bundle" gorm:"column:ca_bundle" filter:"ca_bundle,string"`
|
||||||
AcmeshServer string `json:"acmesh_server" db:"acmesh_server" filter:"acmesh_server,string"`
|
MaxDomains int `json:"max_domains" gorm:"column:max_domains" filter:"max_domains,integer"`
|
||||||
CABundle string `json:"ca_bundle" db:"ca_bundle" filter:"ca_bundle,string"`
|
IsWildcardSupported bool `json:"is_wildcard_supported" gorm:"column:is_wildcard_supported" filter:"is_wildcard_supported,boolean"`
|
||||||
MaxDomains int `json:"max_domains" db:"max_domains" filter:"max_domains,integer"`
|
IsReadonly bool `json:"is_readonly" gorm:"column:is_readonly" filter:"is_readonly,boolean"`
|
||||||
IsWildcardSupported bool `json:"is_wildcard_supported" db:"is_wildcard_supported" filter:"is_wildcard_supported,boolean"`
|
|
||||||
IsReadonly bool `json:"is_readonly" db:"is_readonly" filter:"is_readonly,boolean"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "certificate_authority"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
db := database.GetDB()
|
||||||
|
result := db.Save(m)
|
||||||
if m.ID == 0 {
|
return result.Error
|
||||||
m.ID, err = Create(m)
|
|
||||||
} else {
|
|
||||||
err = Update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a certificate as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check will ensure the ca bundle path exists if it's set
|
// Check will ensure the ca bundle path exists if it's set
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package certificateauthority
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for users list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package dnsprovider
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,128 +1,41 @@
|
|||||||
package dnsprovider
|
package dnsprovider
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a row by ID
|
// GetByID finds a row by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create will create a row from this model
|
|
||||||
func Create(provider *Model) (int, error) {
|
|
||||||
if provider.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create dns provider when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
provider.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
user_id,
|
|
||||||
name,
|
|
||||||
acmesh_name,
|
|
||||||
dns_sleep,
|
|
||||||
meta,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:user_id,
|
|
||||||
:name,
|
|
||||||
:acmesh_name,
|
|
||||||
:dns_sleep,
|
|
||||||
:meta,
|
|
||||||
:is_deleted
|
|
||||||
)`, provider)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will Update a row from this model
|
|
||||||
func Update(provider *Model) error {
|
|
||||||
if provider.ID == 0 {
|
|
||||||
return eris.New("Cannot update dns provider when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
provider.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
user_id = :user_id,
|
|
||||||
name = :name,
|
|
||||||
acmesh_name = :acmesh_name,
|
|
||||||
dns_sleep = :dns_sleep,
|
|
||||||
meta = :meta,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, provider)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a list of certificates
|
// List will return a list of certificates
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "name",
|
Field: "name",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Error("ListDnsProvidersError", queryErr)
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Error("ListDnsProvidersError", err)
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
|
@ -2,80 +2,58 @@ package dnsprovider
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/dnsproviders"
|
"npm/internal/dnsproviders"
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
"npm/internal/types"
|
"npm/internal/types"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
"github.com/rotisserie/eris"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "dns_provider"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the user model
|
|
||||||
// Also see: https://github.com/acmesh-official/acme.sh/wiki/dnscheck
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
UserID int `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
UserID int `json:"user_id" db:"user_id" filter:"user_id,integer"`
|
AcmeshName string `json:"acmesh_name" gorm:"column:acmesh_name" filter:"acmesh_name,string"`
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
DNSSleep int `json:"dns_sleep" gorm:"column:dns_sleep" filter:"dns_sleep,integer"`
|
||||||
AcmeshName string `json:"acmesh_name" db:"acmesh_name" filter:"acmesh_name,string"`
|
Meta types.JSONB `json:"meta" gorm:"column:meta"`
|
||||||
DNSSleep int `json:"dns_sleep" db:"dns_sleep" filter:"dns_sleep,integer"`
|
|
||||||
Meta types.JSONB `json:"meta" db:"meta"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "dns_provider"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
|
||||||
|
|
||||||
if m.UserID == 0 {
|
if m.UserID == 0 {
|
||||||
return eris.Errorf("User ID must be specified")
|
return eris.Errorf("User ID must be specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = Create(m)
|
result := db.Save(m)
|
||||||
} else {
|
return result.Error
|
||||||
err = Update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a certificate as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAcmeShEnvVars returns the env vars required for acme.sh dns cert requests
|
// GetAcmeShEnvVars returns the env vars required for acme.sh dns cert requests
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package dnsprovider
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for the list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -11,12 +11,6 @@ import (
|
|||||||
// FilterMapFunction is a filter map function
|
// FilterMapFunction is a filter map function
|
||||||
type FilterMapFunction func(value []string) []string
|
type FilterMapFunction func(value []string) []string
|
||||||
|
|
||||||
// FilterTagName tag name user for filter pickups
|
|
||||||
const FilterTagName = "filter"
|
|
||||||
|
|
||||||
// DBTagName tag name user for field name pickups
|
|
||||||
const DBTagName = "db"
|
|
||||||
|
|
||||||
// GenerateSQLFromFilters will return a Query and params for use as WHERE clause in SQL queries
|
// GenerateSQLFromFilters will return a Query and params for use as WHERE clause in SQL queries
|
||||||
// This will use a AND where clause approach.
|
// This will use a AND where clause approach.
|
||||||
func GenerateSQLFromFilters(filters []model.Filter, fieldMap map[string]string, fieldMapFunctions map[string]FilterMapFunction) (string, []interface{}) {
|
func GenerateSQLFromFilters(filters []model.Filter, fieldMap map[string]string, fieldMapFunctions map[string]FilterMapFunction) (string, []interface{}) {
|
||||||
@ -96,6 +90,7 @@ func getSQLAssignmentFromModifier(filter model.Filter, params *[]interface{}) st
|
|||||||
return clause
|
return clause
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// GetFilterMap returns the filter map
|
// GetFilterMap returns the filter map
|
||||||
func GetFilterMap(m interface{}) map[string]string {
|
func GetFilterMap(m interface{}) map[string]string {
|
||||||
var filterMap = make(map[string]string)
|
var filterMap = make(map[string]string)
|
||||||
@ -110,8 +105,8 @@ func GetFilterMap(m interface{}) map[string]string {
|
|||||||
field := t.Field(i)
|
field := t.Field(i)
|
||||||
|
|
||||||
// Get the field tag value
|
// Get the field tag value
|
||||||
filterTag := field.Tag.Get(FilterTagName)
|
filterTag := field.Tag.Get("filter")
|
||||||
dbTag := field.Tag.Get(DBTagName)
|
dbTag := field.Tag.Get("db")
|
||||||
if filterTag != "" && dbTag != "" && dbTag != "-" && filterTag != "-" {
|
if filterTag != "" && dbTag != "" && dbTag != "-" && filterTag != "-" {
|
||||||
// Filter tag can be a 2 part thing: name,type
|
// Filter tag can be a 2 part thing: name,type
|
||||||
// ie: account_id,integer
|
// ie: account_id,integer
|
||||||
@ -124,6 +119,7 @@ func GetFilterMap(m interface{}) map[string]string {
|
|||||||
|
|
||||||
return filterMap
|
return filterMap
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// GetDBColumns returns the db columns
|
// GetDBColumns returns the db columns
|
||||||
func GetDBColumns(m interface{}) []string {
|
func GetDBColumns(m interface{}) []string {
|
||||||
@ -132,7 +128,7 @@ func GetDBColumns(m interface{}) []string {
|
|||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
field := t.Field(i)
|
field := t.Field(i)
|
||||||
dbTag := field.Tag.Get(DBTagName)
|
dbTag := field.Tag.Get("db")
|
||||||
if dbTag != "" && dbTag != "-" {
|
if dbTag != "" && dbTag != "-" {
|
||||||
columns = append(columns, dbTag)
|
columns = append(columns, dbTag)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ func GetFilterSchema(m interface{}) string {
|
|||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
field := t.Field(i)
|
field := t.Field(i)
|
||||||
filterTag := field.Tag.Get(FilterTagName)
|
filterTag := field.Tag.Get("filter")
|
||||||
|
|
||||||
if filterTag != "" && filterTag != "-" {
|
if filterTag != "" && filterTag != "-" {
|
||||||
// split out tag value "field,filtreType"
|
// split out tag value "field,filtreType"
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,181 +1,40 @@
|
|||||||
package host
|
package host
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a Host by ID
|
// GetByID finds a Host by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// create will create a Host from this model
|
|
||||||
func create(host *Model) (int, error) {
|
|
||||||
if host.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create host when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
host.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+tableName+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
user_id,
|
|
||||||
type,
|
|
||||||
nginx_template_id,
|
|
||||||
listen_interface,
|
|
||||||
domain_names,
|
|
||||||
upstream_id,
|
|
||||||
proxy_scheme,
|
|
||||||
proxy_host,
|
|
||||||
proxy_port,
|
|
||||||
certificate_id,
|
|
||||||
access_list_id,
|
|
||||||
ssl_forced,
|
|
||||||
caching_enabled,
|
|
||||||
block_exploits,
|
|
||||||
allow_websocket_upgrade,
|
|
||||||
http2_support,
|
|
||||||
hsts_enabled,
|
|
||||||
hsts_subdomains,
|
|
||||||
paths,
|
|
||||||
advanced_config,
|
|
||||||
status,
|
|
||||||
error_message,
|
|
||||||
is_disabled,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:user_id,
|
|
||||||
:type,
|
|
||||||
:nginx_template_id,
|
|
||||||
:listen_interface,
|
|
||||||
:domain_names,
|
|
||||||
:upstream_id,
|
|
||||||
:proxy_scheme,
|
|
||||||
:proxy_host,
|
|
||||||
:proxy_port,
|
|
||||||
:certificate_id,
|
|
||||||
:access_list_id,
|
|
||||||
:ssl_forced,
|
|
||||||
:caching_enabled,
|
|
||||||
:block_exploits,
|
|
||||||
:allow_websocket_upgrade,
|
|
||||||
:http2_support,
|
|
||||||
:hsts_enabled,
|
|
||||||
:hsts_subdomains,
|
|
||||||
:paths,
|
|
||||||
:advanced_config,
|
|
||||||
:status,
|
|
||||||
:error_message,
|
|
||||||
:is_disabled,
|
|
||||||
:is_deleted
|
|
||||||
)`, host)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Debug("Created Host: %+v", host)
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// update will Update a Host from this model
|
|
||||||
func update(host *Model) error {
|
|
||||||
if host.ID == 0 {
|
|
||||||
return eris.New("Cannot update host when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
host.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
user_id = :user_id,
|
|
||||||
type = :type,
|
|
||||||
nginx_template_id = :nginx_template_id,
|
|
||||||
listen_interface = :listen_interface,
|
|
||||||
domain_names = :domain_names,
|
|
||||||
upstream_id = :upstream_id,
|
|
||||||
proxy_scheme = :proxy_scheme,
|
|
||||||
proxy_host = :proxy_host,
|
|
||||||
proxy_port = :proxy_port,
|
|
||||||
certificate_id = :certificate_id,
|
|
||||||
access_list_id = :access_list_id,
|
|
||||||
ssl_forced = :ssl_forced,
|
|
||||||
caching_enabled = :caching_enabled,
|
|
||||||
block_exploits = :block_exploits,
|
|
||||||
allow_websocket_upgrade = :allow_websocket_upgrade,
|
|
||||||
http2_support = :http2_support,
|
|
||||||
hsts_enabled = :hsts_enabled,
|
|
||||||
hsts_subdomains = :hsts_subdomains,
|
|
||||||
paths = :paths,
|
|
||||||
advanced_config = :advanced_config,
|
|
||||||
status = :status,
|
|
||||||
error_message = :error_message,
|
|
||||||
is_disabled = :is_disabled,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, host)
|
|
||||||
|
|
||||||
logger.Debug("Updated Host: %+v", host)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a list of hosts
|
// List will return a list of hosts
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "domain_names",
|
Field: "domain_names",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if expand != nil {
|
if expand != nil {
|
||||||
@ -187,7 +46,7 @@ func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (Lis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
@ -201,32 +60,28 @@ func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (Lis
|
|||||||
|
|
||||||
// GetUpstreamUseCount returns the number of hosts that are using
|
// GetUpstreamUseCount returns the number of hosts that are using
|
||||||
// an upstream, and have not been deleted.
|
// an upstream, and have not been deleted.
|
||||||
func GetUpstreamUseCount(upstreamID int) int {
|
func GetUpstreamUseCount(upstreamID uint) int64 {
|
||||||
db := database.GetInstance()
|
db := database.GetDB()
|
||||||
query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE upstream_id = ? AND is_deleted = ?", tableName)
|
|
||||||
countRow := db.QueryRowx(query, upstreamID, 0)
|
var count int64
|
||||||
var totalRows int
|
if result := db.Model(&Model{}).Where("upstream_id = ?", upstreamID).Count(&count); result.Error != nil {
|
||||||
queryErr := countRow.Scan(&totalRows)
|
logger.Debug("GetUpstreamUseCount Error: %v", result.Error)
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%s", query)
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return totalRows
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCertificateUseCount returns the number of hosts that are using
|
// GetCertificateUseCount returns the number of hosts that are using
|
||||||
// a certificate, and have not been deleted.
|
// a certificate, and have not been deleted.
|
||||||
func GetCertificateUseCount(certificateID int) int {
|
func GetCertificateUseCount(certificateID uint) int64 {
|
||||||
db := database.GetInstance()
|
db := database.GetDB()
|
||||||
query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE certificate_id = ? AND is_deleted = ?", tableName)
|
|
||||||
countRow := db.QueryRowx(query, certificateID, 0)
|
var count int64
|
||||||
var totalRows int
|
if result := db.Model(&Model{}).Where("certificate_id = ?", certificateID).Count(&count); result.Error != nil {
|
||||||
queryErr := countRow.Scan(&totalRows)
|
logger.Debug("GetUpstreamUseCount Error: %v", result.Error)
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%s", query)
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return totalRows
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddPendingJobs is intended to be used at startup to add
|
// AddPendingJobs is intended to be used at startup to add
|
||||||
|
@ -2,9 +2,8 @@ package host
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/entity/certificate"
|
"npm/internal/entity/certificate"
|
||||||
"npm/internal/entity/nginxtemplate"
|
"npm/internal/entity/nginxtemplate"
|
||||||
"npm/internal/entity/upstream"
|
"npm/internal/entity/upstream"
|
||||||
@ -17,8 +16,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
tableName = "host"
|
|
||||||
|
|
||||||
// ProxyHostType is self explanatory
|
// ProxyHostType is self explanatory
|
||||||
ProxyHostType = "proxy"
|
ProxyHostType = "proxy"
|
||||||
// RedirectionHostType is self explanatory
|
// RedirectionHostType is self explanatory
|
||||||
@ -27,67 +24,53 @@ const (
|
|||||||
DeadHostType = "dead"
|
DeadHostType = "dead"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Model is the user model
|
// Model is the model
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
Type string `json:"type" gorm:"column:type" filter:"type,string"`
|
||||||
UserID int `json:"user_id" db:"user_id" filter:"user_id,integer"`
|
NginxTemplateID uint `json:"nginx_template_id" gorm:"column:nginx_template_id" filter:"nginx_template_id,integer"`
|
||||||
Type string `json:"type" db:"type" filter:"type,string"`
|
ListenInterface string `json:"listen_interface" gorm:"column:listen_interface" filter:"listen_interface,string"`
|
||||||
NginxTemplateID int `json:"nginx_template_id" db:"nginx_template_id" filter:"nginx_template_id,integer"`
|
DomainNames types.JSONB `json:"domain_names" gorm:"column:domain_names" filter:"domain_names,string"`
|
||||||
ListenInterface string `json:"listen_interface" db:"listen_interface" filter:"listen_interface,string"`
|
UpstreamID uint `json:"upstream_id" gorm:"column:upstream_id" filter:"upstream_id,integer"`
|
||||||
DomainNames types.JSONB `json:"domain_names" db:"domain_names" filter:"domain_names,string"`
|
ProxyScheme string `json:"proxy_scheme" gorm:"column:proxy_scheme" filter:"proxy_scheme,string"`
|
||||||
UpstreamID int `json:"upstream_id" db:"upstream_id" filter:"upstream_id,integer"`
|
ProxyHost string `json:"proxy_host" gorm:"column:proxy_host" filter:"proxy_host,string"`
|
||||||
ProxyScheme string `json:"proxy_scheme" db:"proxy_scheme" filter:"proxy_scheme,string"`
|
ProxyPort int `json:"proxy_port" gorm:"column:proxy_port" filter:"proxy_port,integer"`
|
||||||
ProxyHost string `json:"proxy_host" db:"proxy_host" filter:"proxy_host,string"`
|
CertificateID uint `json:"certificate_id" gorm:"column:certificate_id" filter:"certificate_id,integer"`
|
||||||
ProxyPort int `json:"proxy_port" db:"proxy_port" filter:"proxy_port,integer"`
|
AccessListID uint `json:"access_list_id" gorm:"column:access_list_id" filter:"access_list_id,integer"`
|
||||||
CertificateID int `json:"certificate_id" db:"certificate_id" filter:"certificate_id,integer"`
|
SSLForced bool `json:"ssl_forced" gorm:"column:ssl_forced" filter:"ssl_forced,boolean"`
|
||||||
AccessListID int `json:"access_list_id" db:"access_list_id" filter:"access_list_id,integer"`
|
CachingEnabled bool `json:"caching_enabled" gorm:"column:caching_enabled" filter:"caching_enabled,boolean"`
|
||||||
SSLForced bool `json:"ssl_forced" db:"ssl_forced" filter:"ssl_forced,boolean"`
|
BlockExploits bool `json:"block_exploits" gorm:"column:block_exploits" filter:"block_exploits,boolean"`
|
||||||
CachingEnabled bool `json:"caching_enabled" db:"caching_enabled" filter:"caching_enabled,boolean"`
|
AllowWebsocketUpgrade bool `json:"allow_websocket_upgrade" gorm:"column:allow_websocket_upgrade" filter:"allow_websocket_upgrade,boolean"`
|
||||||
BlockExploits bool `json:"block_exploits" db:"block_exploits" filter:"block_exploits,boolean"`
|
HTTP2Support bool `json:"http2_support" gorm:"column:http2_support" filter:"http2_support,boolean"`
|
||||||
AllowWebsocketUpgrade bool `json:"allow_websocket_upgrade" db:"allow_websocket_upgrade" filter:"allow_websocket_upgrade,boolean"`
|
HSTSEnabled bool `json:"hsts_enabled" gorm:"column:hsts_enabled" filter:"hsts_enabled,boolean"`
|
||||||
HTTP2Support bool `json:"http2_support" db:"http2_support" filter:"http2_support,boolean"`
|
HSTSSubdomains bool `json:"hsts_subdomains" gorm:"column:hsts_subdomains" filter:"hsts_subdomains,boolean"`
|
||||||
HSTSEnabled bool `json:"hsts_enabled" db:"hsts_enabled" filter:"hsts_enabled,boolean"`
|
Paths string `json:"paths" gorm:"column:paths" filter:"paths,string"`
|
||||||
HSTSSubdomains bool `json:"hsts_subdomains" db:"hsts_subdomains" filter:"hsts_subdomains,boolean"`
|
AdvancedConfig string `json:"advanced_config" gorm:"column:advanced_config" filter:"advanced_config,string"`
|
||||||
Paths string `json:"paths" db:"paths" filter:"paths,string"`
|
Status string `json:"status" gorm:"column:status" filter:"status,string"`
|
||||||
AdvancedConfig string `json:"advanced_config" db:"advanced_config" filter:"advanced_config,string"`
|
ErrorMessage string `json:"error_message" gorm:"column:error_message" filter:"error_message,string"`
|
||||||
Status string `json:"status" db:"status" filter:"status,string"`
|
IsDisabled bool `json:"is_disabled" gorm:"column:is_disabled" filter:"is_disabled,boolean"`
|
||||||
ErrorMessage string `json:"error_message" db:"error_message" filter:"error_message,string"`
|
|
||||||
IsDisabled bool `json:"is_disabled" db:"is_disabled" filter:"is_disabled,boolean"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
// Expansions
|
// Expansions
|
||||||
Certificate *certificate.Model `json:"certificate,omitempty"`
|
Certificate *certificate.Model `json:"certificate,omitempty" gorm:"-"`
|
||||||
NginxTemplate *nginxtemplate.Model `json:"nginx_template,omitempty"`
|
NginxTemplate *nginxtemplate.Model `json:"nginx_template,omitempty" gorm:"-"`
|
||||||
User *user.Model `json:"user,omitempty"`
|
User *user.Model `json:"user,omitempty" gorm:"-"`
|
||||||
Upstream *upstream.Model `json:"upstream,omitempty"`
|
Upstream *upstream.Model `json:"upstream,omitempty" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "host"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save(skipConfiguration bool) error {
|
func (m *Model) Save(skipConfiguration bool) error {
|
||||||
var err error
|
|
||||||
|
|
||||||
if m.UserID == 0 {
|
if m.UserID == 0 {
|
||||||
return eris.Errorf("User ID must be specified")
|
return eris.Errorf("User ID must be specified")
|
||||||
}
|
}
|
||||||
@ -97,23 +80,20 @@ func (m *Model) Save(skipConfiguration bool) error {
|
|||||||
m.Status = status.StatusReady
|
m.Status = status.StatusReady
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = create(m)
|
result := db.Save(m)
|
||||||
} else {
|
return result.Error
|
||||||
err = update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a host as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(false); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand will fill in more properties
|
// Expand will fill in more properties
|
||||||
@ -160,8 +140,8 @@ func (m *Model) GetTemplate() Template {
|
|||||||
|
|
||||||
t := Template{
|
t := Template{
|
||||||
ID: m.ID,
|
ID: m.ID,
|
||||||
CreatedOn: m.CreatedOn.Time.String(),
|
CreatedAt: fmt.Sprintf("%d", m.CreatedAt), // todo: format as nice string
|
||||||
ModifiedOn: m.ModifiedOn.Time.String(),
|
UpdatedAt: fmt.Sprintf("%d", m.UpdatedAt), // todo: format as nice string
|
||||||
UserID: m.UserID,
|
UserID: m.UserID,
|
||||||
Type: m.Type,
|
Type: m.Type,
|
||||||
NginxTemplateID: m.NginxTemplateID,
|
NginxTemplateID: m.NginxTemplateID,
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package host
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for this list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -4,20 +4,20 @@ import "npm/internal/entity/upstream"
|
|||||||
|
|
||||||
// Template is the model given to the template parser, converted from the Model
|
// Template is the model given to the template parser, converted from the Model
|
||||||
type Template struct {
|
type Template struct {
|
||||||
ID int
|
ID uint
|
||||||
CreatedOn string
|
CreatedAt string
|
||||||
ModifiedOn string
|
UpdatedAt string
|
||||||
UserID int
|
UserID uint
|
||||||
Type string
|
Type string
|
||||||
NginxTemplateID int
|
NginxTemplateID uint
|
||||||
ProxyScheme string
|
ProxyScheme string
|
||||||
ProxyHost string
|
ProxyHost string
|
||||||
ProxyPort int
|
ProxyPort int
|
||||||
ListenInterface string
|
ListenInterface string
|
||||||
DomainNames []string
|
DomainNames []string
|
||||||
UpstreamID int
|
UpstreamID uint
|
||||||
CertificateID int
|
CertificateID uint
|
||||||
AccessListID int
|
AccessListID uint
|
||||||
SSLForced bool
|
SSLForced bool
|
||||||
CachingEnabled bool
|
CachingEnabled bool
|
||||||
BlockExploits bool
|
BlockExploits bool
|
||||||
|
36
backend/internal/entity/lists.go
Normal file
36
backend/internal/entity/lists.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"npm/internal/database"
|
||||||
|
"npm/internal/model"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListableModel is a interface for common use
|
||||||
|
type ListableModel interface {
|
||||||
|
TableName() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListResponse is the JSON response for users list
|
||||||
|
type ListResponse struct {
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
Offset int `json:"offset"`
|
||||||
|
Limit int `json:"limit"`
|
||||||
|
Sort []model.Sort `json:"sort"`
|
||||||
|
Filter []model.Filter `json:"filter,omitempty"`
|
||||||
|
Items interface{} `json:"items,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListQueryBuilder is used to setup queries for lists
|
||||||
|
func ListQueryBuilder(
|
||||||
|
pageInfo *model.PageInfo,
|
||||||
|
defaultSort model.Sort,
|
||||||
|
filters []model.Filter,
|
||||||
|
) *gorm.DB {
|
||||||
|
scopes := make([]func(*gorm.DB) *gorm.DB, 0)
|
||||||
|
scopes = append(scopes, ScopeOrderBy(pageInfo, defaultSort))
|
||||||
|
scopes = append(scopes, ScopeOffsetLimit(pageInfo))
|
||||||
|
// scopes = append(scopes, ScopeFilters(GetFilterMap(m)))
|
||||||
|
return database.GetDB().Scopes(scopes...)
|
||||||
|
}
|
@ -1,80 +0,0 @@
|
|||||||
package entity
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListQueryBuilder should be able to return the query and params to get items agnostically based
|
|
||||||
// on given params.
|
|
||||||
func ListQueryBuilder(modelExample interface{}, tableName string, pageInfo *model.PageInfo, defaultSort model.Sort, filters []model.Filter, filterMapFunctions map[string]FilterMapFunction, returnCount bool) (string, []interface{}) {
|
|
||||||
var queryStrings []string
|
|
||||||
var whereStrings []string
|
|
||||||
var params []interface{}
|
|
||||||
|
|
||||||
if returnCount {
|
|
||||||
queryStrings = append(queryStrings, "SELECT COUNT(*)")
|
|
||||||
} else {
|
|
||||||
queryStrings = append(queryStrings, "SELECT *")
|
|
||||||
}
|
|
||||||
|
|
||||||
// nolint: gosec
|
|
||||||
queryStrings = append(queryStrings, fmt.Sprintf("FROM `%s`", tableName))
|
|
||||||
|
|
||||||
// Append filters to where clause:
|
|
||||||
if filters != nil {
|
|
||||||
filterMap := GetFilterMap(modelExample)
|
|
||||||
filterQuery, filterParams := GenerateSQLFromFilters(filters, filterMap, filterMapFunctions)
|
|
||||||
whereStrings = []string{filterQuery}
|
|
||||||
params = append(params, filterParams...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add is deletee check if model has the field
|
|
||||||
if hasDeletedField(modelExample) {
|
|
||||||
params = append(params, 0)
|
|
||||||
whereStrings = append(whereStrings, "`is_deleted` = ?")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append where clauses to query
|
|
||||||
if len(whereStrings) > 0 {
|
|
||||||
// nolint: gosec
|
|
||||||
queryStrings = append(queryStrings, fmt.Sprintf("WHERE %s", strings.Join(whereStrings, " AND ")))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !returnCount {
|
|
||||||
var orderBy string
|
|
||||||
columns := GetDBColumns(modelExample)
|
|
||||||
orderBy, pageInfo.Sort = database.BuildOrderBySQL(columns, &pageInfo.Sort)
|
|
||||||
|
|
||||||
if orderBy != "" {
|
|
||||||
queryStrings = append(queryStrings, orderBy)
|
|
||||||
} else {
|
|
||||||
pageInfo.Sort = append(pageInfo.Sort, defaultSort)
|
|
||||||
queryStrings = append(queryStrings, fmt.Sprintf("ORDER BY `%v` COLLATE NOCASE %v", defaultSort.Field, defaultSort.Direction))
|
|
||||||
}
|
|
||||||
|
|
||||||
params = append(params, pageInfo.Offset)
|
|
||||||
params = append(params, pageInfo.Limit)
|
|
||||||
queryStrings = append(queryStrings, "LIMIT ?, ?")
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join(queryStrings, " "), params
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasDeletedField(modelExample interface{}) bool {
|
|
||||||
t := reflect.TypeOf(modelExample)
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
|
||||||
field := t.Field(i)
|
|
||||||
dbTag := field.Tag.Get(DBTagName)
|
|
||||||
if dbTag == "is_deleted" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
13
backend/internal/entity/model_base.go
Normal file
13
backend/internal/entity/model_base.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/plugin/soft_delete"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModelBase include common fields for db control
|
||||||
|
type ModelBase struct {
|
||||||
|
ID uint `json:"id" gorm:"column:id;primaryKey"`
|
||||||
|
CreatedAt int64 `json:"created_at" gorm:"<-:create;autoCreateTime:milli;column:created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at" gorm:"<-;autoUpdateTime:milli;column:updated_at"`
|
||||||
|
DeletedAt soft_delete.DeletedAt `json:"-" gorm:"column:is_deleted;softDelete:flag"`
|
||||||
|
}
|
@ -1,25 +0,0 @@
|
|||||||
package nginxtemplate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,123 +1,41 @@
|
|||||||
package nginxtemplate
|
package nginxtemplate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a Host by ID
|
// GetByID finds a Host by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create will create a Host from this model
|
|
||||||
func Create(host *Model) (int, error) {
|
|
||||||
if host.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create host template when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
host.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
user_id,
|
|
||||||
name,
|
|
||||||
host_type,
|
|
||||||
template,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:user_id,
|
|
||||||
:name,
|
|
||||||
:host_type,
|
|
||||||
:template,
|
|
||||||
:is_deleted
|
|
||||||
)`, host)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will Update a Host from this model
|
|
||||||
func Update(host *Model) error {
|
|
||||||
if host.ID == 0 {
|
|
||||||
return eris.New("Cannot update host template when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
host.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
user_id = :user_id,
|
|
||||||
name = :name,
|
|
||||||
host_type = :host_type,
|
|
||||||
template = :template,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, host)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a list of hosts
|
// List will return a list of hosts
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "created_on",
|
Field: "created_on",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
|
@ -1,75 +1,51 @@
|
|||||||
package nginxtemplate
|
package nginxtemplate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/types"
|
"npm/internal/entity"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
"github.com/rotisserie/eris"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "nginx_template"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the user model
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
UserID int `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
UserID int `json:"user_id" db:"user_id" filter:"user_id,integer"`
|
Type string `json:"type" gorm:"column:type" filter:"type,string"`
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
Template string `json:"template" gorm:"column:template" filter:"template,string"`
|
||||||
Type string `json:"type" db:"type" filter:"type,string"`
|
|
||||||
Template string `json:"template" db:"template" filter:"template,string"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "nginx_template"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
|
||||||
|
|
||||||
if m.UserID == 0 {
|
if m.UserID == 0 {
|
||||||
return eris.Errorf("User ID must be specified")
|
return eris.Errorf("User ID must be specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = Create(m)
|
result := db.Save(m)
|
||||||
} else {
|
return result.Error
|
||||||
err = Update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a template as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package nginxtemplate
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for this list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
62
backend/internal/entity/scopes.go
Normal file
62
backend/internal/entity/scopes.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package entity
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"npm/internal/model"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ScopeOffsetLimit(pageInfo *model.PageInfo) func(db *gorm.DB) *gorm.DB {
|
||||||
|
return func(db *gorm.DB) *gorm.DB {
|
||||||
|
if pageInfo.Offset > 0 || pageInfo.Limit > 0 {
|
||||||
|
return db.Limit(pageInfo.Limit).Offset(pageInfo.Offset)
|
||||||
|
}
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScopeOrderBy(pageInfo *model.PageInfo, defaultSort model.Sort) func(db *gorm.DB) *gorm.DB {
|
||||||
|
return func(db *gorm.DB) *gorm.DB {
|
||||||
|
if pageInfo.Sort != nil {
|
||||||
|
// Sort by items in slice
|
||||||
|
return db.Order(sortToOrderString(pageInfo.Sort))
|
||||||
|
} else if defaultSort.Field != "" {
|
||||||
|
// Default to this sort
|
||||||
|
str := defaultSort.Field
|
||||||
|
if defaultSort.Direction != "" {
|
||||||
|
str = str + " " + defaultSort.Direction
|
||||||
|
}
|
||||||
|
return db.Order(str)
|
||||||
|
}
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScopeFilters(filters map[string]string) func(db *gorm.DB) *gorm.DB {
|
||||||
|
return func(db *gorm.DB) *gorm.DB {
|
||||||
|
// todo
|
||||||
|
/*
|
||||||
|
if filters != nil {
|
||||||
|
filterMap := GetFilterMap(m)
|
||||||
|
filterQuery, filterParams := GenerateSQLFromFilters(filters, filterMap, filterMapFunctions)
|
||||||
|
whereStrings = []string{filterQuery}
|
||||||
|
params = append(params, filterParams...)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortToOrderString(sorts []model.Sort) string {
|
||||||
|
strs := make([]string, 0)
|
||||||
|
for _, i := range sorts {
|
||||||
|
str := i.Field
|
||||||
|
if i.Direction != "" {
|
||||||
|
str = str + " " + i.Direction
|
||||||
|
}
|
||||||
|
strs = append(strs, str)
|
||||||
|
}
|
||||||
|
return strings.Join(strs, ", ")
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
package setting
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/config"
|
|
||||||
"npm/internal/logger"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ApplySettings will load settings from the DB and apply them where required
|
|
||||||
func ApplySettings() {
|
|
||||||
logger.Debug("Applying Settings")
|
|
||||||
|
|
||||||
// Error-reporting
|
|
||||||
m, err := GetByName("error-reporting")
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("ApplySettingsError", err)
|
|
||||||
} else {
|
|
||||||
config.ErrorReporting = m.Value.Decoded.(bool)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package setting
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,16 +1,10 @@
|
|||||||
package setting
|
package setting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"npm/internal/config"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a setting by ID
|
// GetByID finds a setting by ID
|
||||||
@ -27,95 +21,30 @@ func GetByName(name string) (Model, error) {
|
|||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create will Create a Setting from this model
|
|
||||||
func Create(setting *Model) (int, error) {
|
|
||||||
if setting.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create setting when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
setting.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
name,
|
|
||||||
value
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:name,
|
|
||||||
:value
|
|
||||||
)`, setting)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will Update a Setting from this model
|
|
||||||
func Update(setting *Model) error {
|
|
||||||
if setting.ID == 0 {
|
|
||||||
return eris.New("Cannot update setting when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
setting.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
name = :name,
|
|
||||||
value = :value
|
|
||||||
WHERE id = :id`, setting)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a list of settings
|
// List will return a list of settings
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "name",
|
Field: "name",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%+v", queryErr)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("%+v", err)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
@ -126,3 +55,16 @@ func List(pageInfo model.PageInfo, filters []model.Filter) (ListResponse, error)
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ApplySettings will load settings from the DB and apply them where required
|
||||||
|
func ApplySettings() {
|
||||||
|
logger.Debug("Applying Settings")
|
||||||
|
|
||||||
|
// Error-reporting
|
||||||
|
m, err := GetByName("error-reporting")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("ApplySettingsError", err)
|
||||||
|
} else {
|
||||||
|
config.ErrorReporting = m.Value.String() == "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,73 +1,50 @@
|
|||||||
package setting
|
package setting
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/types"
|
"npm/internal/entity"
|
||||||
|
|
||||||
|
"gorm.io/datatypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "setting"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the user model
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
Description string `json:"description" gorm:"column:description" filter:"description,string"`
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
Value datatypes.JSON `json:"value" gorm:"column:value"`
|
||||||
Description string `json:"description" db:"description" filter:"description,string"`
|
|
||||||
Value types.JSONB `json:"value" db:"value"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "setting"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id int) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE `id` = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByName will load from a Name
|
// LoadByName will load from a Name
|
||||||
func (m *Model) LoadByName(name string) error {
|
func (m *Model) LoadByName(name string) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE LOWER(`name`) = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{strings.TrimSpace(strings.ToLower(name))}
|
result := db.Where("name = ?", strings.ToLower(name)).First(&m)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
|
||||||
|
|
||||||
// ensure name is trimmed of whitespace
|
// ensure name is trimmed of whitespace
|
||||||
m.Name = strings.TrimSpace(m.Name)
|
m.Name = strings.TrimSpace(m.Name)
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = Create(m)
|
if result := db.Save(m); result.Error != nil {
|
||||||
} else {
|
return result.Error
|
||||||
err = Update(m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reapply settings
|
|
||||||
if err == nil {
|
|
||||||
ApplySettings()
|
ApplySettings()
|
||||||
}
|
return nil
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package setting
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for settings list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package stream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,129 +1,41 @@
|
|||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a auth by ID
|
// GetByID finds a auth by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create will create a Auth from this model
|
|
||||||
func Create(host *Model) (int, error) {
|
|
||||||
if host.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create stream when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
host.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
user_id,
|
|
||||||
provider,
|
|
||||||
name,
|
|
||||||
domain_names,
|
|
||||||
expires_on,
|
|
||||||
meta,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:user_id,
|
|
||||||
:provider,
|
|
||||||
:name,
|
|
||||||
:domain_names,
|
|
||||||
:expires_on,
|
|
||||||
:meta,
|
|
||||||
:is_deleted
|
|
||||||
)`, host)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will Update a Host from this model
|
|
||||||
func Update(host *Model) error {
|
|
||||||
if host.ID == 0 {
|
|
||||||
return eris.New("Cannot update stream when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
host.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
user_id = :user_id,
|
|
||||||
provider = :provider,
|
|
||||||
name = :name,
|
|
||||||
domain_names = :domain_names,
|
|
||||||
expires_on = :expires_on,
|
|
||||||
meta = :meta,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, host)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a list of hosts
|
// List will return a list of hosts
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "name",
|
Field: "name",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
|
@ -1,77 +1,54 @@
|
|||||||
package stream
|
package stream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/types"
|
"npm/internal/types"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
"github.com/rotisserie/eris"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "stream"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the user model
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
ExpiresOn types.DBDate `json:"expires_on" gorm:"column:expires_on" filter:"expires_on,integer"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
UserID int `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
|
||||||
ExpiresOn types.DBDate `json:"expires_on" db:"expires_on" filter:"expires_on,integer"`
|
Provider string `json:"provider" gorm:"column:provider" filter:"provider,string"`
|
||||||
UserID int `json:"user_id" db:"user_id" filter:"user_id,integer"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
Provider string `json:"provider" db:"provider" filter:"provider,string"`
|
DomainNames types.JSONB `json:"domain_names" gorm:"column:domain_names" filter:"domain_names,string"`
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
Meta types.JSONB `json:"-" gorm:"column:meta"`
|
||||||
DomainNames types.JSONB `json:"domain_names" db:"domain_names" filter:"domain_names,string"`
|
|
||||||
Meta types.JSONB `json:"-" db:"meta"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "stream"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
|
||||||
|
|
||||||
if m.UserID == 0 {
|
if m.UserID == 0 {
|
||||||
return eris.Errorf("User ID must be specified")
|
return eris.Errorf("User ID must be specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = Create(m)
|
result := db.Save(m)
|
||||||
} else {
|
return result.Error
|
||||||
err = Update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a host as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package stream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for this list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package upstream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,147 +1,38 @@
|
|||||||
package upstream
|
package upstream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a Upstream by ID
|
// GetByID finds a Upstream by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// create will create a Upstream from this model
|
|
||||||
func create(u *Model) (int, error) {
|
|
||||||
if u.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create upstream when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
user_id,
|
|
||||||
name,
|
|
||||||
nginx_template_id,
|
|
||||||
ip_hash,
|
|
||||||
ntlm,
|
|
||||||
keepalive,
|
|
||||||
keepalive_requests,
|
|
||||||
keepalive_time,
|
|
||||||
keepalive_timeout,
|
|
||||||
advanced_config,
|
|
||||||
status,
|
|
||||||
error_message,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:user_id,
|
|
||||||
:name,
|
|
||||||
:nginx_template_id,
|
|
||||||
:ip_hash,
|
|
||||||
:ntlm,
|
|
||||||
:keepalive,
|
|
||||||
:keepalive_requests,
|
|
||||||
:keepalive_time,
|
|
||||||
:keepalive_timeout,
|
|
||||||
:advanced_config,
|
|
||||||
:status,
|
|
||||||
:error_message,
|
|
||||||
:is_deleted
|
|
||||||
)`, u)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Debug("Created Upstream: %+v", u)
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// update will Update a Upstream from this model
|
|
||||||
func update(u *Model) error {
|
|
||||||
if u.ID == 0 {
|
|
||||||
return eris.New("Cannot update upstream when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
user_id = :user_id,
|
|
||||||
name = :name,
|
|
||||||
nginx_template_id = :nginx_template_id,
|
|
||||||
ip_hash = :ip_hash,
|
|
||||||
ntlm = :ntlm,
|
|
||||||
keepalive = :keepalive,
|
|
||||||
keepalive_requests = :keepalive_requests,
|
|
||||||
keepalive_time = :keepalive_time,
|
|
||||||
advanced_config = :advanced_config,
|
|
||||||
status = :status,
|
|
||||||
error_message = :error_message,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, u)
|
|
||||||
|
|
||||||
logger.Debug("Updated Upstream: %+v", u)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List will return a list of Upstreams
|
// List will return a list of Upstreams
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "name",
|
Field: "name",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand to get servers, at a minimum
|
// Expand to get servers, at a minimum
|
||||||
@ -150,7 +41,7 @@ func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (Lis
|
|||||||
items[idx].Expand(expand)
|
items[idx].Expand(expand)
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
|
@ -1,79 +1,55 @@
|
|||||||
package upstream
|
package upstream
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/entity/nginxtemplate"
|
"npm/internal/entity/nginxtemplate"
|
||||||
"npm/internal/entity/upstreamserver"
|
"npm/internal/entity/upstreamserver"
|
||||||
"npm/internal/entity/user"
|
"npm/internal/entity/user"
|
||||||
"npm/internal/status"
|
"npm/internal/status"
|
||||||
"npm/internal/types"
|
|
||||||
"npm/internal/util"
|
"npm/internal/util"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
"github.com/rotisserie/eris"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "upstream"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the Upstream model
|
|
||||||
// See: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream
|
// See: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
UserID uint `json:"user_id" gorm:"column:user_id" filter:"user_id,integer"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
UserID int `json:"user_id" db:"user_id" filter:"user_id,integer"`
|
NginxTemplateID uint `json:"nginx_template_id" gorm:"column:nginx_template_id" filter:"nginx_template_id,integer"`
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
IPHash bool `json:"ip_hash" gorm:"column:ip_hash" filter:"ip_hash,boolean"`
|
||||||
NginxTemplateID int `json:"nginx_template_id" db:"nginx_template_id" filter:"nginx_template_id,integer"`
|
NTLM bool `json:"ntlm" gorm:"column:ntlm" filter:"ntlm,boolean"`
|
||||||
IPHash bool `json:"ip_hash" db:"ip_hash" filter:"ip_hash,boolean"`
|
Keepalive int `json:"keepalive" gorm:"column:keepalive" filter:"keepalive,integer"`
|
||||||
NTLM bool `json:"ntlm" db:"ntlm" filter:"ntlm,boolean"`
|
KeepaliveRequests int `json:"keepalive_requests" gorm:"column:keepalive_requests" filter:"keepalive_requests,integer"`
|
||||||
Keepalive int `json:"keepalive" db:"keepalive" filter:"keepalive,integer"`
|
KeepaliveTime string `json:"keepalive_time" gorm:"column:keepalive_time" filter:"keepalive_time,string"`
|
||||||
KeepaliveRequests int `json:"keepalive_requests" db:"keepalive_requests" filter:"keepalive_requests,integer"`
|
KeepaliveTimeout string `json:"keepalive_timeout" gorm:"column:keepalive_timeout" filter:"keepalive_timeout,string"`
|
||||||
KeepaliveTime string `json:"keepalive_time" db:"keepalive_time" filter:"keepalive_time,string"`
|
AdvancedConfig string `json:"advanced_config" gorm:"column:advanced_config" filter:"advanced_config,string"`
|
||||||
KeepaliveTimeout string `json:"keepalive_timeout" db:"keepalive_timeout" filter:"keepalive_timeout,string"`
|
Status string `json:"status" gorm:"column:status" filter:"status,string"`
|
||||||
AdvancedConfig string `json:"advanced_config" db:"advanced_config" filter:"advanced_config,string"`
|
ErrorMessage string `json:"error_message" gorm:"column:error_message" filter:"error_message,string"`
|
||||||
Status string `json:"status" db:"status" filter:"status,string"`
|
|
||||||
ErrorMessage string `json:"error_message" db:"error_message" filter:"error_message,string"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
// Expansions
|
// Expansions
|
||||||
Servers []upstreamserver.Model `json:"servers"`
|
Servers []upstreamserver.Model `json:"servers" gorm:"-"`
|
||||||
NginxTemplate *nginxtemplate.Model `json:"nginx_template,omitempty"`
|
NginxTemplate *nginxtemplate.Model `json:"nginx_template,omitempty" gorm:"-"`
|
||||||
User *user.Model `json:"user,omitempty"`
|
User *user.Model `json:"user,omitempty" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "upstream"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
err := m.getByQuery(query, params)
|
return result.Error
|
||||||
if err == nil {
|
|
||||||
err = m.Expand(nil)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save(skipConfiguration bool) error {
|
func (m *Model) Save(skipConfiguration bool) error {
|
||||||
var err error
|
|
||||||
|
|
||||||
if m.UserID == 0 {
|
if m.UserID == 0 {
|
||||||
return eris.Errorf("User ID must be specified")
|
return eris.Errorf("User ID must be specified")
|
||||||
}
|
}
|
||||||
@ -86,14 +62,13 @@ func (m *Model) Save(skipConfiguration bool) error {
|
|||||||
m.Status = status.StatusReady
|
m.Status = status.StatusReady
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = create(m)
|
if result := db.Save(m); result.Error != nil {
|
||||||
} else {
|
return result.Error
|
||||||
err = update(m)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save Servers
|
// Save Servers
|
||||||
if err == nil {
|
var err error
|
||||||
for idx := range m.Servers {
|
for idx := range m.Servers {
|
||||||
// Continue if previous iteration didn't cause an error
|
// Continue if previous iteration didn't cause an error
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -101,19 +76,19 @@ func (m *Model) Save(skipConfiguration bool) error {
|
|||||||
err = m.Servers[idx].Save()
|
err = m.Servers[idx].Save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a upstream as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(false); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand will fill in more properties
|
// Expand will fill in more properties
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package upstream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for this list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package upstreamserver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,16 +1,9 @@
|
|||||||
package upstreamserver
|
package upstreamserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a Upstream Server by ID
|
// GetByID finds a Upstream Server by ID
|
||||||
@ -21,128 +14,37 @@ func GetByID(id int) (Model, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetByUpstreamID finds all servers in the upstream
|
// GetByUpstreamID finds all servers in the upstream
|
||||||
func GetByUpstreamID(upstreamID int) ([]Model, error) {
|
func GetByUpstreamID(upstreamID uint) ([]Model, error) {
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query := `SELECT * FROM ` + fmt.Sprintf("`%s`", tableName) + ` WHERE upstream_id = ? ORDER BY server`
|
db := database.GetDB()
|
||||||
db := database.GetInstance()
|
result := db.Where("upstream_id = ?", upstreamID).Order("server ASC").Find(&items)
|
||||||
err := db.Select(&items, query, upstreamID)
|
return items, result.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("%s -- %d", query, upstreamID)
|
|
||||||
}
|
|
||||||
return items, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// create will create a Upstream Server from this model
|
|
||||||
func create(u *Model) (int, error) {
|
|
||||||
if u.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create upstream server when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
upstream_id,
|
|
||||||
server,
|
|
||||||
weight,
|
|
||||||
max_conns,
|
|
||||||
max_fails,
|
|
||||||
fail_timeout,
|
|
||||||
backup,
|
|
||||||
is_deleted
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:upstream_id,
|
|
||||||
:server,
|
|
||||||
:weight,
|
|
||||||
:max_conns,
|
|
||||||
:max_fails,
|
|
||||||
:fail_timeout,
|
|
||||||
:backup,
|
|
||||||
:is_deleted
|
|
||||||
)`, u)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Debug("Created Upstream Server: %+v", u)
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// update will Update a Upstream from this model
|
|
||||||
func update(u *Model) error {
|
|
||||||
if u.ID == 0 {
|
|
||||||
return eris.New("Cannot update upstream server when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
upstream_id = :upstream_id,
|
|
||||||
server = :server,
|
|
||||||
weight = :weight,
|
|
||||||
max_conns = :max_conns,
|
|
||||||
max_fails = :max_fails,
|
|
||||||
fail_timeout = :fail_timeout,
|
|
||||||
backup = :backup,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, u)
|
|
||||||
|
|
||||||
logger.Debug("Updated Upstream Server: %+v", u)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List will return a list of Upstreams
|
// List will return a list of Upstreams
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "server",
|
Field: "server",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("%s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
|
@ -1,78 +1,48 @@
|
|||||||
package upstreamserver
|
package upstreamserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/types"
|
"npm/internal/entity"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "upstream_server"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the upstream model
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
UpstreamID uint `json:"upstream_id" gorm:"column:upstream_id" filter:"upstream_id,integer"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
Server string `json:"server" gorm:"column:server" filter:"server,string"`
|
||||||
UpstreamID int `json:"upstream_id" db:"upstream_id" filter:"upstream_id,integer"`
|
Weight int `json:"weight" gorm:"column:weight" filter:"weight,integer"`
|
||||||
Server string `json:"server" db:"server" filter:"server,string"`
|
MaxConns int `json:"max_conns" gorm:"column:max_conns" filter:"max_conns,integer"`
|
||||||
Weight int `json:"weight" db:"weight" filter:"weight,integer"`
|
MaxFails int `json:"max_fails" gorm:"column:max_fails" filter:"max_fails,integer"`
|
||||||
MaxConns int `json:"max_conns" db:"max_conns" filter:"max_conns,integer"`
|
FailTimeout int `json:"fail_timeout" gorm:"column:fail_timeout" filter:"fail_timeout,integer"`
|
||||||
MaxFails int `json:"max_fails" db:"max_fails" filter:"max_fails,integer"`
|
Backup bool `json:"backup" gorm:"column:is_backup" filter:"backup,boolean"`
|
||||||
FailTimeout int `json:"fail_timeout" db:"fail_timeout" filter:"fail_timeout,integer"`
|
|
||||||
Backup bool `json:"backup" db:"backup" filter:"backup,boolean"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
return database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
|
return "upstream_server"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id int) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, 0}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
// Touch will update model's timestamp(s)
|
|
||||||
func (m *Model) Touch(created bool) {
|
|
||||||
var d types.DBDate
|
|
||||||
d.Time = time.Now()
|
|
||||||
if created {
|
|
||||||
m.CreatedOn = d
|
|
||||||
}
|
|
||||||
m.ModifiedOn = d
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
db := database.GetDB()
|
||||||
|
result := db.Save(m)
|
||||||
if m.UpstreamID == 0 {
|
return result.Error
|
||||||
return eris.Errorf("Upstream ID must be specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
if m.ID == 0 {
|
|
||||||
m.ID, err = create(m)
|
|
||||||
} else {
|
|
||||||
err = update(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a upstream as deleted
|
// Delete will mark row as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package upstreamserver
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for this list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/entity"
|
|
||||||
)
|
|
||||||
|
|
||||||
var filterMapFunctions = make(map[string]entity.FilterMapFunction)
|
|
||||||
|
|
||||||
// getFilterMapFunctions is a map of functions that should be executed
|
|
||||||
// during the filtering process, if a field is defined here then the value in
|
|
||||||
// the filter will be given to the defined function and it will return a new
|
|
||||||
// value for use in the sql query.
|
|
||||||
func getFilterMapFunctions() map[string]entity.FilterMapFunction {
|
|
||||||
// if len(filterMapFunctions) == 0 {
|
|
||||||
// TODO: See internal/model/file_item.go:620 for an example
|
|
||||||
// }
|
|
||||||
|
|
||||||
return filterMapFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFilterSchema returns filter schema
|
|
||||||
func GetFilterSchema() string {
|
|
||||||
var m Model
|
|
||||||
return entity.GetFilterSchema(m)
|
|
||||||
}
|
|
@ -1,20 +1,14 @@
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
"npm/internal/entity"
|
"npm/internal/entity"
|
||||||
"npm/internal/errors"
|
|
||||||
"npm/internal/logger"
|
"npm/internal/logger"
|
||||||
"npm/internal/model"
|
"npm/internal/model"
|
||||||
|
|
||||||
"github.com/rotisserie/eris"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetByID finds a user by ID
|
// GetByID finds a user by ID
|
||||||
func GetByID(id int) (Model, error) {
|
func GetByID(id uint) (Model, error) {
|
||||||
var m Model
|
var m Model
|
||||||
err := m.LoadByID(id)
|
err := m.LoadByID(id)
|
||||||
return m, err
|
return m, err
|
||||||
@ -27,140 +21,38 @@ func GetByEmail(email string) (Model, error) {
|
|||||||
return m, err
|
return m, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create will create a User from given model
|
|
||||||
func Create(user *Model) (int, error) {
|
|
||||||
// We need to ensure that a user can't be created with the same email
|
|
||||||
// as an existing non-deleted user. Usually you would do this with the
|
|
||||||
// database schema, but it's a bit more complex because of the is_deleted field.
|
|
||||||
|
|
||||||
if user.ID != 0 {
|
|
||||||
return 0, eris.New("Cannot create user when model already has an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if an existing user with this email exists
|
|
||||||
_, err := GetByEmail(user.Email)
|
|
||||||
if err == nil {
|
|
||||||
return 0, errors.ErrDuplicateEmailUser
|
|
||||||
}
|
|
||||||
|
|
||||||
user.Touch(true)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
result, err := db.NamedExec(`INSERT INTO `+fmt.Sprintf("`%s`", tableName)+` (
|
|
||||||
created_on,
|
|
||||||
modified_on,
|
|
||||||
name,
|
|
||||||
nickname,
|
|
||||||
email,
|
|
||||||
is_disabled
|
|
||||||
) VALUES (
|
|
||||||
:created_on,
|
|
||||||
:modified_on,
|
|
||||||
:name,
|
|
||||||
:nickname,
|
|
||||||
:email,
|
|
||||||
:is_disabled
|
|
||||||
)`, user)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
last, lastErr := result.LastInsertId()
|
|
||||||
if lastErr != nil {
|
|
||||||
return 0, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
return int(last), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update will Update a User from this model
|
|
||||||
func Update(user *Model) error {
|
|
||||||
if user.ID == 0 {
|
|
||||||
return eris.New("Cannot update user when model doesn't have an ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the email address isn't associated with another user
|
|
||||||
if existingUser, _ := GetByEmail(user.Email); existingUser.ID != 0 && existingUser.ID != user.ID {
|
|
||||||
return errors.ErrDuplicateEmailUser
|
|
||||||
}
|
|
||||||
|
|
||||||
user.Touch(false)
|
|
||||||
|
|
||||||
db := database.GetInstance()
|
|
||||||
// nolint: gosec
|
|
||||||
_, err := db.NamedExec(`UPDATE `+fmt.Sprintf("`%s`", tableName)+` SET
|
|
||||||
created_on = :created_on,
|
|
||||||
modified_on = :modified_on,
|
|
||||||
name = :name,
|
|
||||||
nickname = :nickname,
|
|
||||||
email = :email,
|
|
||||||
is_disabled = :is_disabled,
|
|
||||||
is_deleted = :is_deleted
|
|
||||||
WHERE id = :id`, user)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsEnabled is used by middleware to ensure the user is still enabled
|
// IsEnabled is used by middleware to ensure the user is still enabled
|
||||||
// returns (userExist, isEnabled)
|
// returns (userExist, isEnabled)
|
||||||
func IsEnabled(userID int) (bool, bool) {
|
func IsEnabled(userID uint) (bool, bool) {
|
||||||
// nolint: gosec
|
var user Model
|
||||||
query := `SELECT is_disabled FROM ` + fmt.Sprintf("`%s`", tableName) + ` WHERE id = ? AND is_deleted = ?`
|
db := database.GetDB()
|
||||||
disabled := true
|
if result := db.First(&user, userID); result.Error != nil {
|
||||||
db := database.GetInstance()
|
|
||||||
err := db.QueryRowx(query, userID, 0).Scan(&disabled)
|
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
return false, false
|
return false, false
|
||||||
} else if err != nil {
|
|
||||||
logger.Error("QueryError", err)
|
|
||||||
}
|
}
|
||||||
|
return true, !user.IsDisabled
|
||||||
return true, !disabled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List will return a list of users
|
// List will return a list of users
|
||||||
func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (ListResponse, error) {
|
func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (entity.ListResponse, error) {
|
||||||
var result ListResponse
|
var result entity.ListResponse
|
||||||
var exampleModel Model
|
|
||||||
|
|
||||||
defaultSort := model.Sort{
|
defaultSort := model.Sort{
|
||||||
Field: "name",
|
Field: "name",
|
||||||
Direction: "ASC",
|
Direction: "ASC",
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
dbo := entity.ListQueryBuilder(&pageInfo, defaultSort, filters)
|
||||||
if db == nil {
|
|
||||||
return result, errors.ErrDatabaseUnavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
filters = append(filters, model.Filter{
|
|
||||||
Field: "is_system",
|
|
||||||
Modifier: "equals",
|
|
||||||
Value: []string{"0"},
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Get count of items in this search
|
// Get count of items in this search
|
||||||
query, params := entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), true)
|
var totalRows int64
|
||||||
countRow := db.QueryRowx(query, params...)
|
if res := dbo.Model(&Model{}).Count(&totalRows); res.Error != nil {
|
||||||
var totalRows int
|
return result, res.Error
|
||||||
queryErr := countRow.Scan(&totalRows)
|
|
||||||
if queryErr != nil && queryErr != sql.ErrNoRows {
|
|
||||||
logger.Debug("Query: %s -- %+v", query, params)
|
|
||||||
return result, queryErr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get rows
|
// Get rows
|
||||||
items := make([]Model, 0)
|
items := make([]Model, 0)
|
||||||
query, params = entity.ListQueryBuilder(exampleModel, tableName, &pageInfo, defaultSort, filters, getFilterMapFunctions(), false)
|
if res := dbo.Find(&items); res.Error != nil {
|
||||||
err := db.Select(&items, query, params...)
|
return result, res.Error
|
||||||
if err != nil {
|
|
||||||
logger.Debug("Query: %s -- %+v", query, params)
|
|
||||||
return result, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx := range items {
|
for idx := range items {
|
||||||
@ -176,7 +68,7 @@ func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (Lis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = ListResponse{
|
result = entity.ListResponse{
|
||||||
Items: items,
|
Items: items,
|
||||||
Total: totalRows,
|
Total: totalRows,
|
||||||
Limit: pageInfo.Limit,
|
Limit: pageInfo.Limit,
|
||||||
@ -190,41 +82,21 @@ func List(pageInfo model.PageInfo, filters []model.Filter, expand []string) (Lis
|
|||||||
|
|
||||||
// DeleteAll will do just that, and should only be used for testing purposes.
|
// DeleteAll will do just that, and should only be used for testing purposes.
|
||||||
func DeleteAll() error {
|
func DeleteAll() error {
|
||||||
db := database.GetInstance()
|
db := database.GetDB()
|
||||||
_, err := db.Exec(fmt.Sprintf("DELETE FROM `%s`", tableName))
|
result := db.Exec("DELETE FROM users")
|
||||||
return err
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCapabilities gets capabilities for a user
|
// GetCapabilities gets capabilities for a user
|
||||||
func GetCapabilities(userID int) ([]string, error) {
|
func GetCapabilities(userID uint) ([]string, error) {
|
||||||
var capabilities []string
|
capabilities := make([]string, 0)
|
||||||
db := database.GetInstance()
|
var hasCapabilities []UserHasCapabilityModel
|
||||||
if db == nil {
|
db := database.GetDB()
|
||||||
return []string{}, errors.ErrDatabaseUnavailable
|
if result := db.Where("user_id = ?", userID).Find(&hasCapabilities); result.Error != nil {
|
||||||
|
return nil, result.Error
|
||||||
}
|
}
|
||||||
|
for _, obj := range hasCapabilities {
|
||||||
query := `SELECT c.name FROM "user_has_capability" h
|
capabilities = append(capabilities, obj.CapabilityName)
|
||||||
INNER JOIN "capability" c ON c.id = h.capability_id
|
|
||||||
WHERE h.user_id = ?`
|
|
||||||
|
|
||||||
rows, err := db.Query(query, userID)
|
|
||||||
if err != nil && err != sql.ErrNoRows {
|
|
||||||
logger.Debug("QUERY: %v -- %v", query, userID)
|
|
||||||
return []string{}, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint: errcheck
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
var name string
|
|
||||||
err := rows.Scan(&name)
|
|
||||||
if err != nil {
|
|
||||||
return []string{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
capabilities = append(capabilities, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return capabilities, nil
|
return capabilities, nil
|
||||||
}
|
}
|
||||||
|
@ -1,62 +1,67 @@
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"npm/internal/database"
|
"npm/internal/database"
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/entity/auth"
|
"npm/internal/entity/auth"
|
||||||
"npm/internal/errors"
|
"npm/internal/errors"
|
||||||
"npm/internal/logger"
|
|
||||||
"npm/internal/types"
|
|
||||||
"npm/internal/util"
|
"npm/internal/util"
|
||||||
|
|
||||||
"github.com/drexedam/gravatar"
|
"github.com/drexedam/gravatar"
|
||||||
"github.com/rotisserie/eris"
|
"github.com/rotisserie/eris"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
// Model is the model
|
||||||
tableName = "user"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Model is the user model
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
ID int `json:"id" db:"id" filter:"id,integer"`
|
entity.ModelBase
|
||||||
Name string `json:"name" db:"name" filter:"name,string"`
|
Name string `json:"name" gorm:"column:name" filter:"name,string"`
|
||||||
Nickname string `json:"nickname" db:"nickname" filter:"nickname,string"`
|
Nickname string `json:"nickname" gorm:"column:nickname" filter:"nickname,string"`
|
||||||
Email string `json:"email" db:"email" filter:"email,email"`
|
Email string `json:"email" gorm:"column:email" filter:"email,email"`
|
||||||
CreatedOn types.DBDate `json:"created_on" db:"created_on" filter:"created_on,integer"`
|
IsDisabled bool `json:"is_disabled" gorm:"column:is_disabled" filter:"is_disabled,boolean"`
|
||||||
ModifiedOn types.DBDate `json:"modified_on" db:"modified_on" filter:"modified_on,integer"`
|
IsSystem bool `json:"is_system,omitempty" gorm:"column:is_system"`
|
||||||
GravatarURL string `json:"gravatar_url"`
|
// Other
|
||||||
IsDisabled bool `json:"is_disabled" db:"is_disabled" filter:"is_disabled,boolean"`
|
GravatarURL string `json:"gravatar_url" gorm:"-"`
|
||||||
IsSystem bool `json:"is_system,omitempty" db:"is_system"`
|
|
||||||
IsDeleted bool `json:"is_deleted,omitempty" db:"is_deleted"`
|
|
||||||
// Expansions
|
// Expansions
|
||||||
Auth *auth.Model `json:"auth,omitempty" db:"-"`
|
Auth *auth.Model `json:"auth,omitempty" gorm:"-"`
|
||||||
Capabilities []string `json:"capabilities,omitempty"`
|
Capabilities []string `json:"capabilities,omitempty" gorm:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Model) getByQuery(query string, params []interface{}) error {
|
// TableName overrides the table name used by gorm
|
||||||
err := database.GetByQuery(m, query, params)
|
func (Model) TableName() string {
|
||||||
m.generateGravatar()
|
return "user"
|
||||||
return err
|
}
|
||||||
|
|
||||||
|
// UserHasCapabilityModel is the model
|
||||||
|
type UserHasCapabilityModel struct {
|
||||||
|
UserID uint `json:"user_id" gorm:"column:user_id"`
|
||||||
|
CapabilityName string `json:"name" gorm:"column:capability_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TableName overrides the table name used by gorm
|
||||||
|
func (UserHasCapabilityModel) TableName() string {
|
||||||
|
return "user_has_capability"
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByID will load from an ID
|
// LoadByID will load from an ID
|
||||||
func (m *Model) LoadByID(id int) error {
|
func (m *Model) LoadByID(id uint) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE id = ? AND is_deleted = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{id, false}
|
result := db.First(&m, id)
|
||||||
return m.getByQuery(query, params)
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadByEmail will load from an Email
|
// LoadByEmail will load from an Email
|
||||||
func (m *Model) LoadByEmail(email string) error {
|
func (m *Model) LoadByEmail(email string) error {
|
||||||
query := fmt.Sprintf("SELECT * FROM `%s` WHERE email = ? AND is_deleted = ? AND is_system = ? LIMIT 1", tableName)
|
db := database.GetDB()
|
||||||
params := []interface{}{strings.TrimSpace(strings.ToLower(email)), false, false}
|
result := db.
|
||||||
return m.getByQuery(query, params)
|
Where("email = ?", strings.TrimSpace(strings.ToLower(email))).
|
||||||
|
Where("is_system = ?", false).
|
||||||
|
First(&m)
|
||||||
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Touch will update model's timestamp(s)
|
// Touch will update model's timestamp(s)
|
||||||
func (m *Model) Touch(created bool) {
|
func (m *Model) Touch(created bool) {
|
||||||
var d types.DBDate
|
var d types.DBDate
|
||||||
@ -67,34 +72,31 @@ func (m *Model) Touch(created bool) {
|
|||||||
m.ModifiedOn = d
|
m.ModifiedOn = d
|
||||||
m.generateGravatar()
|
m.generateGravatar()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Save will save this model to the DB
|
// Save will save this model to the DB
|
||||||
func (m *Model) Save() error {
|
func (m *Model) Save() error {
|
||||||
var err error
|
|
||||||
// Ensure email is nice
|
// Ensure email is nice
|
||||||
m.Email = strings.TrimSpace(strings.ToLower(m.Email))
|
m.Email = strings.TrimSpace(strings.ToLower(m.Email))
|
||||||
|
|
||||||
if m.IsSystem {
|
if m.IsSystem {
|
||||||
return errors.ErrSystemUserReadonly
|
return errors.ErrSystemUserReadonly
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.ID == 0 {
|
db := database.GetDB()
|
||||||
m.ID, err = Create(m)
|
// todo: touch? not sure that save does this or not?
|
||||||
} else {
|
result := db.Save(m)
|
||||||
err = Update(m)
|
return result.Error
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete will mark a user as deleted
|
// Delete will mark a user as deleted
|
||||||
func (m *Model) Delete() bool {
|
func (m *Model) Delete() bool {
|
||||||
m.Touch(false)
|
if m.ID == 0 {
|
||||||
m.IsDeleted = true
|
// Can't delete a new object
|
||||||
if err := m.Save(); err != nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
db := database.GetDB()
|
||||||
|
result := db.Delete(m)
|
||||||
|
return result.Error == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPermissions will wipe out any existing permissions and add new ones for this user
|
// SetPermissions will wipe out any existing permissions and add new ones for this user
|
||||||
@ -103,30 +105,20 @@ func (m *Model) SetPermissions(permissions []string) error {
|
|||||||
return eris.Errorf("Cannot set permissions without first saving the User")
|
return eris.Errorf("Cannot set permissions without first saving the User")
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
db := database.GetDB()
|
||||||
|
|
||||||
// Wipe out previous permissions
|
// Wipe out previous permissions
|
||||||
query := `DELETE FROM "user_has_capability" WHERE "user_id" = ?`
|
if result := db.Where("user_id = ?", m.ID).Delete(&UserHasCapabilityModel{}); result.Error != nil {
|
||||||
if _, err := db.Exec(query, m.ID); err != nil {
|
return result.Error
|
||||||
logger.Debug("QUERY: %v -- %v", query, m.ID)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(permissions) > 0 {
|
if len(permissions) > 0 {
|
||||||
// Add new permissions
|
// Add new permissions
|
||||||
|
objs := []*UserHasCapabilityModel{}
|
||||||
for _, permission := range permissions {
|
for _, permission := range permissions {
|
||||||
query = `INSERT INTO "user_has_capability" (
|
objs = append(objs, &UserHasCapabilityModel{UserID: m.ID, CapabilityName: permission})
|
||||||
"user_id", "capability_id"
|
|
||||||
) VALUES (
|
|
||||||
?,
|
|
||||||
(SELECT id FROM capability WHERE name = ?)
|
|
||||||
)`
|
|
||||||
|
|
||||||
_, err := db.Exec(query, m.ID, permission)
|
|
||||||
if err != nil {
|
|
||||||
logger.Debug("QUERY: %v -- %v -- %v", query, m.ID, permission)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
if result := db.Create(objs); result.Error != nil {
|
||||||
|
return result.Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,21 +156,18 @@ func (m *Model) SaveCapabilities() error {
|
|||||||
return eris.New("At least 1 capability required for a user")
|
return eris.New("At least 1 capability required for a user")
|
||||||
}
|
}
|
||||||
|
|
||||||
db := database.GetInstance()
|
db := database.GetDB()
|
||||||
|
|
||||||
// Get a full list of capabilities
|
// Get a full list of capabilities
|
||||||
var capabilities []string
|
var capabilities []entity.Capability
|
||||||
query := `SELECT "name" from "capability"`
|
if result := db.Find(&capabilities); result.Error != nil {
|
||||||
err := db.Select(&capabilities, query)
|
return result.Error
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the capabilities defined exist in the db
|
// Check that the capabilities defined exist in the db
|
||||||
for _, cap := range m.Capabilities {
|
for _, cap := range m.Capabilities {
|
||||||
found := false
|
found := false
|
||||||
for _, a := range capabilities {
|
for _, a := range capabilities {
|
||||||
if a == cap {
|
if a.Name == cap {
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
package user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"npm/internal/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ListResponse is the JSON response for users list
|
|
||||||
type ListResponse struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Sort []model.Sort `json:"sort"`
|
|
||||||
Filter []model.Filter `json:"filter,omitempty"`
|
|
||||||
Items []Model `json:"items,omitempty"`
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
// UserJWTClaims is the structure of a JWT for a User
|
// UserJWTClaims is the structure of a JWT for a User
|
||||||
type UserJWTClaims struct {
|
type UserJWTClaims struct {
|
||||||
UserID int `json:"uid"`
|
UserID uint `json:"uid"`
|
||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
jwt.StandardClaims
|
jwt.StandardClaims
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PageInfo is the model used by Api Handlers and passed on to other parts
|
// PageInfo is the model used by Api Handlers and passed on to other parts
|
||||||
// of the application
|
// of the application
|
||||||
type PageInfo struct {
|
type PageInfo struct {
|
||||||
FromDate time.Time `json:"from_date"`
|
|
||||||
ToDate time.Time `json:"to_date"`
|
|
||||||
Sort []Sort `json:"sort"`
|
Sort []Sort `json:"sort"`
|
||||||
Offset int `json:"offset"`
|
Offset int `json:"offset"`
|
||||||
Limit int `json:"limit"`
|
Limit int `json:"limit"`
|
||||||
|
@ -49,9 +49,10 @@ func ConfigureHost(h host.Model) error {
|
|||||||
|
|
||||||
removeHostFiles(h)
|
removeHostFiles(h)
|
||||||
filename := getHostFilename(h, "")
|
filename := getHostFilename(h, "")
|
||||||
if h.IsDeleted {
|
// if h.IsDeleted {
|
||||||
filename = getHostFilename(h, DeletedSuffix)
|
// filename = getHostFilename(h, DeletedSuffix)
|
||||||
} else if h.IsDisabled {
|
// } else if h.IsDisabled {
|
||||||
|
if h.IsDisabled {
|
||||||
filename = getHostFilename(h, DisabledSuffix)
|
filename = getHostFilename(h, DisabledSuffix)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ func ConfigureHost(h host.Model) error {
|
|||||||
|
|
||||||
// Write the .error file, if this isn't a deleted or disabled host
|
// Write the .error file, if this isn't a deleted or disabled host
|
||||||
// as the reload will only fail because of this host, if it's enabled
|
// as the reload will only fail because of this host, if it's enabled
|
||||||
if !h.IsDeleted && !h.IsDisabled {
|
if !h.IsDisabled {
|
||||||
filename = getHostFilename(h, ErrorSuffix)
|
filename = getHostFilename(h, ErrorSuffix)
|
||||||
// Clear existing file(s) again
|
// Clear existing file(s) again
|
||||||
removeHostFiles(h)
|
removeHostFiles(h)
|
||||||
@ -108,9 +109,9 @@ func ConfigureUpstream(u upstream.Model) error {
|
|||||||
|
|
||||||
removeUpstreamFiles(u)
|
removeUpstreamFiles(u)
|
||||||
filename := getUpstreamFilename(u, "")
|
filename := getUpstreamFilename(u, "")
|
||||||
if u.IsDeleted {
|
// if u.IsDeleted {
|
||||||
filename = getUpstreamFilename(u, DeletedSuffix)
|
// filename = getUpstreamFilename(u, DeletedSuffix)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Write the config to disk
|
// Write the config to disk
|
||||||
err := writeTemplate(filename, u.NginxTemplate.Template, data, "")
|
err := writeTemplate(filename, u.NginxTemplate.Template, data, "")
|
||||||
@ -130,14 +131,14 @@ func ConfigureUpstream(u upstream.Model) error {
|
|||||||
|
|
||||||
// Write the .error file, if this isn't a deleted upstream
|
// Write the .error file, if this isn't a deleted upstream
|
||||||
// as the reload will only fail because of this upstream
|
// as the reload will only fail because of this upstream
|
||||||
if !u.IsDeleted {
|
// if !u.IsDeleted {
|
||||||
filename = getUpstreamFilename(u, ErrorSuffix)
|
filename = getUpstreamFilename(u, ErrorSuffix)
|
||||||
// Clear existing file(s) again
|
// Clear existing file(s) again
|
||||||
removeUpstreamFiles(u)
|
removeUpstreamFiles(u)
|
||||||
// Write the template again, but with an error message at the end of the file
|
// Write the template again, but with an error message at the end of the file
|
||||||
// nolint: errcheck, gosec
|
// nolint: errcheck, gosec
|
||||||
writeTemplate(filename, u.NginxTemplate.Template, data, u.ErrorMessage)
|
writeTemplate(filename, u.NginxTemplate.Template, data, u.ErrorMessage)
|
||||||
}
|
// }
|
||||||
|
|
||||||
logger.Debug(u.ErrorMessage)
|
logger.Debug(u.ErrorMessage)
|
||||||
} else {
|
} else {
|
||||||
@ -195,9 +196,9 @@ func GetHostConfigContent(h host.Model) (string, error) {
|
|||||||
if h.IsDisabled {
|
if h.IsDisabled {
|
||||||
filename = getHostFilename(h, DisabledSuffix)
|
filename = getHostFilename(h, DisabledSuffix)
|
||||||
}
|
}
|
||||||
if h.IsDeleted {
|
// if h.IsDeleted {
|
||||||
filename = getHostFilename(h, DeletedSuffix)
|
// filename = getHostFilename(h, DeletedSuffix)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// nolint: gosec
|
// nolint: gosec
|
||||||
cnt, err := os.ReadFile(filename)
|
cnt, err := os.ReadFile(filename)
|
||||||
@ -213,9 +214,9 @@ func GetUpstreamConfigContent(u upstream.Model) (string, error) {
|
|||||||
if u.ErrorMessage != "" {
|
if u.ErrorMessage != "" {
|
||||||
filename = getUpstreamFilename(u, ErrorSuffix)
|
filename = getUpstreamFilename(u, ErrorSuffix)
|
||||||
}
|
}
|
||||||
if u.IsDeleted {
|
// if u.IsDeleted {
|
||||||
filename = getUpstreamFilename(u, DeletedSuffix)
|
// filename = getUpstreamFilename(u, DeletedSuffix)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// nolint: gosec
|
// nolint: gosec
|
||||||
cnt, err := os.ReadFile(filename)
|
cnt, err := os.ReadFile(filename)
|
||||||
|
@ -3,6 +3,7 @@ package nginx
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"npm/internal/entity"
|
||||||
"npm/internal/entity/certificate"
|
"npm/internal/entity/certificate"
|
||||||
"npm/internal/entity/host"
|
"npm/internal/entity/host"
|
||||||
|
|
||||||
@ -45,7 +46,9 @@ server {
|
|||||||
IsDisabled: false,
|
IsDisabled: false,
|
||||||
},
|
},
|
||||||
cert: certificate.Model{
|
cert: certificate.Model{
|
||||||
|
ModelBase: entity.ModelBase{
|
||||||
ID: 77,
|
ID: 77,
|
||||||
|
},
|
||||||
Status: certificate.StatusProvided,
|
Status: certificate.StatusProvided,
|
||||||
Type: certificate.TypeHTTP,
|
Type: certificate.TypeHTTP,
|
||||||
CertificateAuthorityID: 99,
|
CertificateAuthorityID: 99,
|
||||||
@ -61,7 +64,9 @@ server {
|
|||||||
IsDisabled: false,
|
IsDisabled: false,
|
||||||
},
|
},
|
||||||
cert: certificate.Model{
|
cert: certificate.Model{
|
||||||
|
ModelBase: entity.ModelBase{
|
||||||
ID: 66,
|
ID: 66,
|
||||||
|
},
|
||||||
Status: certificate.StatusProvided,
|
Status: certificate.StatusProvided,
|
||||||
Type: certificate.TypeCustom,
|
Type: certificate.TypeCustom,
|
||||||
},
|
},
|
||||||
|
@ -58,6 +58,7 @@ build_backend() {
|
|||||||
-w '/app/backend' \
|
-w '/app/backend' \
|
||||||
"${IMAGE}" \
|
"${IMAGE}" \
|
||||||
go build \
|
go build \
|
||||||
|
-tags 'json1' \
|
||||||
-buildvcs=false \
|
-buildvcs=false \
|
||||||
-ldflags "-w -s -X main.commit=${BUILD_COMMIT:-notset} -X main.version=${BUILD_VERSION} -X main.sentryDSN=${SENTRY_DSN:-}" \
|
-ldflags "-w -s -X main.commit=${BUILD_COMMIT:-notset} -X main.version=${BUILD_VERSION} -X main.sentryDSN=${SENTRY_DSN:-}" \
|
||||||
-o "/app/bin/$FILENAME" \
|
-o "/app/bin/$FILENAME" \
|
||||||
|
@ -24,6 +24,7 @@ echo -e "${BLUE}❯ ${CYAN}Building binaries for ${YELLOW}${GOARCH} (${TARGETPLA
|
|||||||
|
|
||||||
# server
|
# server
|
||||||
go build \
|
go build \
|
||||||
|
-tags 'json1' \
|
||||||
-buildvcs=false \
|
-buildvcs=false \
|
||||||
-ldflags "-w -s -X main.commit=${BUILD_COMMIT:-notset} -X main.version=${BUILD_VERSION} -X main.sentryDSN=${SENTRY_DSN:-}" \
|
-ldflags "-w -s -X main.commit=${BUILD_COMMIT:-notset} -X main.version=${BUILD_VERSION} -X main.sentryDSN=${SENTRY_DSN:-}" \
|
||||||
-o "${1:-/dist/server}" \
|
-o "${1:-/dist/server}" \
|
||||||
|
Loading…
Reference in New Issue
Block a user