This commit is contained in:
biosvos
2026-08-07 17:38:18 +09:00
commit 873193a243
9613 changed files with 2755992 additions and 0 deletions
+642
View File
@@ -0,0 +1,642 @@
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
"net"
"os"
"strconv"
"time"
//"errors"
"github.com/labstack/gommon/color"
_ "github.com/lib/pq"
"gopkg.in/labstack/echo.v1"
mw "gopkg.in/labstack/echo.v1/middleware"
)
var (
PORT = os.Getenv("PORT")
DATABASE_URL = os.Getenv("DATABASE_URL")
API_LOG = os.Getenv("API_LOG")
FIXED_TOKEN = os.Getenv("X_Auth_Token")
)
const (
version = "v1"
//fixedtoken = "2eefa2912f40a6072d28ff0b571aa820"
//accesslog = "api_log"
//connectionString = "user=solboxcs password=thsutleodlQj dbname=cs_ccdb sslmode=disable connect_timeout=1 host=cc-gts.ktsh.co.kr port=9000"
)
type JsonFloat64 float64
func (f JsonFloat64) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("%0.2f", f)), nil
}
type MessageStruct struct {
Id string `json:"id"`
Message string `json:"message"`
}
type UserStruct struct {
Id string `json:"id"`
Name string `json:"name"`
}
type ServiceStruct struct {
Id string `json:"id"`
Service string `json:"service"`
Pass string `json:"password"`
Domin string `json:"domain"`
}
type TrafficStruct struct {
Sdate string `json:"date"`
In JsonFloat64 `json:"in"`
In_min JsonFloat64 `json:"in_min"`
In_max JsonFloat64 `json:"in_max"`
In_avg JsonFloat64 `json:"in_avg,numbers"`
Out JsonFloat64 `json:"out"`
Out_min JsonFloat64 `json:"out_min"`
Out_max JsonFloat64 `json:"out_max"`
Out_avg JsonFloat64 `json:"out_avg"`
}
type UsageStruct struct {
Sdate string `json:"date"`
Quota uint64 `json:"quota"`
//Quota_min uint64 `json:"quota_min"`
//Quota_max uint64 `json:"quota_max"`
Used JsonFloat64 `json:"used"`
Used_min JsonFloat64 `json:"used_min"`
Used_max JsonFloat64 `json:"used_max"`
}
// Response
type ErrMsgOutput struct {
Status string `json:"status"`
Code int `json:"errorcode"`
Message string `json:"error"`
}
type UserOutput struct {
Data []UserStruct `json:"data"`
}
type ServiceOutput struct {
Data []ServiceStruct `json:"data"`
}
type TrafficOutput struct {
Data []TrafficStruct `json:"data"`
}
type UsageOutput struct {
Data []UsageStruct `json:"data"`
}
// Handler
func hello(c *echo.Context) error {
//fmt.Println("token => " + c.Form("token"))
s := fmt.Sprintf("Hello, World! token = %v\n", c.Form("token"))
return c.String(http.StatusOK, s)
}
func users(c *echo.Context) error {
keyword := c.Form("lkey")
db, err := sql.Open("postgres", DATABASE_URL)
if err != nil {
//log.Fatal(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer db.Close()
var rows *sql.Rows
if keyword != "" {
like := "%" + keyword + "%"
rows, err = db.Query("SELECT c.id, ext.name FROM cs_service.cs_customer c LEFT JOIN cs_service.cs_customer_ext ext ON ext.user_seq = c.user_seq WHERE c.del_yn = 'N' AND ext.name LIKE $1 ORDER BY c.id;", like)
} else {
rows, err = db.Query("SELECT c.id, ext.name FROM cs_service.cs_customer c LEFT JOIN cs_service.cs_customer_ext ext ON ext.user_seq = c.user_seq WHERE c.del_yn = 'N' ORDER BY c.id;")
}
if err != nil {
//log.Fatal(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer rows.Close()
users := make([]UserStruct, 0)
var uid string
var name string
for rows.Next() {
err = rows.Scan(&uid, &name)
users = append(users, UserStruct{uid, name})
}
return c.JSON(http.StatusOK, UserOutput{users})
}
func services(c *echo.Context) error {
qid := c.Form("id")
db, err := sql.Open("postgres", DATABASE_URL)
if err != nil {
//log.Fatal(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer db.Close()
res, err := db.Query("SELECT base_domain FROM cs_service.cs_cc_info")
if err != nil {
//log.Fatal(err)
//panic(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer res.Close()
var base string
for res.Next() {
err = res.Scan(&base)
}
var rows *sql.Rows
if qid != "" {
rows, err = db.Query("SELECT c.id, c.passwd, s.svc_id FROM cs_service.cs_customer c, cs_service.cs_service s WHERE c.user_seq = s.user_seq AND c.id = $1 AND code NOT IN($2) AND s.status_code = $3 ORDER BY c.id", qid, "SVC_TYPE_A_02", "SVC_STATUS_ING")
} else {
rows, err = db.Query("SELECT c.id, c.passwd, s.svc_id FROM cs_service.cs_customer c, cs_service.cs_service s WHERE c.user_seq = s.user_seq AND code NOT IN($1) AND s.status_code = $2 ORDER BY c.id", "SVC_TYPE_A_02", "SVC_STATUS_ING")
}
if err != nil {
//log.Fatal(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer rows.Close()
services := make([]ServiceStruct, 0)
var uid string
var passwd string
var sid string
for rows.Next() {
err = rows.Scan(&uid, &passwd, &sid)
services = append(services, ServiceStruct{uid, sid, passwd, base})
}
return c.JSON(http.StatusOK, ServiceOutput{services})
}
func service(c *echo.Context) error {
//return c.String(http.StatusOK, "Hello, service!!!! svc_id = %v\n", c.Param("svc_id"))
in := c.Param("svc_id")
db, err := sql.Open("postgres", DATABASE_URL)
if err != nil {
//log.Fatal(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer db.Close()
res, err := db.Query("SELECT base_domain FROM cs_service.cs_cc_info")
if err != nil {
//log.Fatal(err)
//panic(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer res.Close()
var base string
for res.Next() {
err = res.Scan(&base)
}
rows, err := db.Query("SELECT c.id, c.passwd, s.svc_id FROM cs_service.cs_customer c, cs_service.cs_service s WHERE c.user_seq = s.user_seq AND s.svc_id = $1 AND code NOT IN($2) AND s.status_code = $3 ORDER BY c.id", in, "SVC_TYPE_A_02", "SVC_STATUS_ING")
if err != nil {
//log.Fatal(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer rows.Close()
services := make([]ServiceStruct, 0)
var uid string
var passwd string
var sid string
for rows.Next() {
err = rows.Scan(&uid, &passwd, &sid)
services = append(services, ServiceStruct{uid, sid, passwd, base})
}
return c.JSON(http.StatusOK, ServiceOutput{services})
}
func traffic(c *echo.Context) error {
sid := c.Param("svc_id")
sdata := c.Form("start_date")
edata := c.Form("end_date")
now := time.Now()
if sdata == "" {
sdata = fmt.Sprintf("%v%v%v", now.Year(), now.Month(), now.Day())
}
if edata == "" {
edata = fmt.Sprintf("%v%v%v", now.Year(), now.Month(), now.Day())
}
sdata += " 00:00:00"
edata += " 23:59:59"
db, err := sql.Open("postgres", DATABASE_URL)
if err != nil {
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer db.Close()
res, err := db.Query("SELECT user_seq, svc_seq FROM cs_service.cs_service WHERE svc_id = $1", sid)
if err != nil {
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer res.Close()
var useq uint64
var sseq uint64
//fmt.Printf("value %v => %v", sid, useq)
for res.Next() {
err = res.Scan(&useq, &sseq)
//fmt.Printf("value 1 => %v",useq)
}
if useq == 0 || sseq == 0 {
log.Println("Not Found Service.[", sid, "]")
return echo.NewHTTPError(http.StatusNotFound)
}
var rows *sql.Rows
qstr := `select
b.all_dates reg_date,
round(coalesce(up_traffic_sum, 0), 2) up_traffic_sum,
round(coalesce(up_traffic_min, 0), 2) up_traffic_min,
round(coalesce(up_traffic_max, 0), 2) up_traffic_max,
round(coalesce(up_traffic_avg, 0), 2) up_traffic_avg,
round(coalesce(down_traffic_sum, 0), 2) down_traffic_sum,
round(coalesce(down_traffic_min, 0), 2) down_traffic_min,
round(coalesce(down_traffic_max, 0), 2) down_traffic_max,
round(coalesce(down_traffic_avg, 0), 2) down_traffic_avg
from ( select
distinct to_char(reg_date,
'YYYYmmdd'
) reg_date,
(coalesce(max(down_traffic), 0) ) down_traffic_max,
(coalesce(max(up_traffic), 0) ) up_traffic_max,
(coalesce(min(down_traffic), 0) ) down_traffic_min,
(coalesce(min(up_traffic), 0) ) up_traffic_min,
(coalesce(sum(down_traffic), 0) ) down_traffic_sum,
(coalesce(sum(up_traffic), 0) ) up_traffic_sum,
(coalesce(avg(down_traffic), 0) ) down_traffic_avg,
(coalesce(avg(up_traffic), 0) ) up_traffic_avg
from cs_stat.cs_stat_network
where 1 = 1
and svc_seq = $1
and user_seq = $2
-- AND reg_date between to_date($3::text, 'YYYY-mm-dd HH24:MI:SS') AND to_date($4::text, 'YYYY-mm-dd HH24:MI:SS')
AND reg_date >= $3 AND reg_date <= $4
group by to_char(reg_date, 'YYYYmmdd')
order by reg_date
) a
right join
(select a.all_dates
from (
select distinct d1.dates as all_dates
from (
select to_char(to_date($3::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYY') || month || day as dates
from cs_web.cs_calen_day366
WHERE LEAP_YN = 'N'
Union All
select to_char(to_date($4::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYY') || month || day as dates
from cs_web.cs_calen_day366
WHERE LEAP_YN = 'N'
Union All
SELECT to_char(to_date( to_char(to_date($3::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYY') || '0301'::text, 'YYYYmmdd') -1, 'YYYYmmdd')
Union All
SELECT to_char(to_date( to_char(to_date($4::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYY') || '0301'::text, 'YYYYmmdd') -1, 'YYYYmmdd')
) d1
order by d1.dates
) a
where a.all_dates between (to_char(to_date($3::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYYmmdd')) and (to_char(to_date($4::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYYmmdd'))
order by a.all_dates
)b
on a.reg_date = b.all_dates
order by b.all_dates`
rows, err = db.Query(qstr, sseq, useq, sdata, edata)
if err != nil {
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer rows.Close()
traffic := make([]TrafficStruct, 0)
for rows.Next() {
var v TrafficStruct
err = rows.Scan(&v.Sdate,
&v.In,
&v.In_min,
&v.In_max,
&v.In_avg,
&v.Out,
&v.Out_min,
&v.Out_max,
&v.Out_avg)
traffic = append(traffic, v)
}
return c.JSON(http.StatusOK, TrafficOutput{traffic})
}
func usage(c *echo.Context) error {
sid := c.Param("svc_id")
sdata := c.Form("start_date")
edata := c.Form("end_date")
now := time.Now()
if sdata == "" {
sdata = fmt.Sprintf("%v%v%v", now.Year(), now.Month(), now.Day())
}
if edata == "" {
edata = fmt.Sprintf("%v%v%v", now.Year(), now.Month(), now.Day())
}
sdata += " 00:00:00"
edata += " 23:59:59"
db, err := sql.Open("postgres", DATABASE_URL)
if err != nil {
//log.Fatal(err)
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer db.Close()
res, err := db.Query("SELECT user_seq, svc_seq, stg_size FROM cs_service.cs_service WHERE svc_id = $1", sid)
if err != nil {
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer res.Close()
var useq uint64
var sseq uint64
var quota uint64
//fmt.Printf("value %v => %v", sid, useq)
for res.Next() {
err = res.Scan(&useq, &sseq, &quota)
//fmt.Printf("value 1 => %v",useq)
}
if useq == 0 || sseq == 0 {
log.Println("Not Found Service.[", sid, "]")
return echo.NewHTTPError(http.StatusNotFound)
}
var rows *sql.Rows
qstr := `select b.all_dates reg_date,
round(coalesce(used_stg_size_last, 0), 2) used_stg_size_last,
round(coalesce(used_stg_size_max, 0), 2) used_stg_size_max,
round(coalesce(used_stg_size_min, 0), 2) used_stg_size_min
from (
select
to_char(a.reg_date,
'YYYYmmdd'
) reg_date,
(array_agg(used_stg_size ORDER BY a.reg_date DESC))[1] used_stg_size_last,
max(used_stg_size) used_stg_size_max,
min(used_stg_size) used_stg_size_min
from cs_stat.cs_stat_storage a
where svc_seq = $1
and user_seq = $2
-- AND a.reg_date between (to_date($3::text, 'YYYY-mm-dd')) AND to_date($4::text, 'YYYY-mm-dd')
AND a.reg_date >= $3 AND a.reg_date <= $4
group by to_char(a.reg_date, 'YYYYmmdd')
) a
right join
(select a.all_dates
from (
select distinct d1.dates as all_dates
from (
select to_char(to_date($3::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYY') || month || day as dates
from cs_web.cs_calen_day366
WHERE LEAP_YN = 'N'
Union All
select to_char(to_date($4::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYY') || month || day as dates
from cs_web.cs_calen_day366
WHERE LEAP_YN = 'N'
Union All
SELECT to_char(to_date( to_char(to_date($3::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYY') || '0301'::text, 'YYYYmmdd') -1, 'YYYYmmdd')
Union All
SELECT to_char(to_date( to_char(to_date($4::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYY') || '0301'::text, 'YYYYmmdd') -1, 'YYYYmmdd')
) d1
order by d1.dates
) a
where a.all_dates between (to_char(to_date($3::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYYmmdd')) and (to_char(to_date($4::text, 'YYYY-mm-dd HH24:MI:SS'), 'YYYYmmdd'))
order by a.all_dates
)b
on a.reg_date = b.all_dates
order by b.all_dates`
rows, err = db.Query(qstr, sseq, useq, sdata, edata)
if err != nil {
log.Println(err)
return echo.NewHTTPError(http.StatusInternalServerError)
}
defer rows.Close()
usage := make([]UsageStruct, 0)
for rows.Next() {
var v UsageStruct
err = rows.Scan(&v.Sdate,
&v.Used,
&v.Used_min,
&v.Used_max)
v.Quota = quota
usage = append(usage, v)
}
/*
var v UsageStruct
usage := make([]UsageStruct,0);
for i := 0; i < 10; i++ {
v.Sdate = strconv.Itoa(i);
i64 := uint64(i)
v.Quota = i64
//v.Quota_min = i64
//v.Quota_max = i64
v.Used = i64
v.Used_min = i64
v.Used_max = i64
usage= append(usage,v);
}
*/
return c.JSON(http.StatusOK, UsageOutput{usage})
}
// Middleware
// auth
func FixedCert() echo.MiddlewareFunc {
return func(h echo.HandlerFunc) echo.HandlerFunc {
return func(c *echo.Context) error {
//token := c.Form("token")
token := c.Request().Header.Get("X-Auth-Token")
if token != "" && FIXED_TOKEN == token {
//fmt.Println("token => " + token)
//log.Println("token => " + token)
return h(c)
}
log.Println("ERROR : missing token.")
return echo.NewHTTPError(http.StatusUnauthorized)
}
}
}
// logger(get gopkg.in/labstack/echo.v0/middleware/logger.go)
func Logger() echo.MiddlewareFunc {
return func(h echo.HandlerFunc) echo.HandlerFunc {
return func(c *echo.Context) error {
start := time.Now()
if err := h(c); err != nil {
c.Error(err)
}
end := time.Now()
req := c.Request()
remoteAddr := req.RemoteAddr
if ip := req.Header.Get(echo.XRealIP); ip != "" {
remoteAddr = ip
} else if ip = req.Header.Get(echo.XForwardedFor); ip != "" {
remoteAddr = ip
} else {
remoteAddr, _, _ = net.SplitHostPort(remoteAddr)
}
method := c.Request().Method
path := c.Request().URL.Path
if path == "" {
path = "/"
}
size := c.Response().Size()
n := c.Response().Status()
code := color.Green(n)
switch {
case n >= 500:
code = color.Red(n)
case n >= 400:
code = color.Yellow(n)
case n >= 300:
code = color.Cyan(n)
}
log.Printf("%s %s %s %s %s %d", remoteAddr, method, path, code, end.Sub(start), size)
return nil
}
}
}
// error function
func MyError(err error, c *echo.Context) {
//fmt.Println("MyError" + c.Form("token"))
code := http.StatusInternalServerError
msg := http.StatusText(code)
if he, ok := err.(*echo.HTTPError); ok {
code = he.Code()
msg = he.Error()
}
//if code == http.StatusNotFound {
// c.JSON(http.StatusMethodNotAllowed, ErrMsgOutput{strconv.Itoa(code), 405, msg} )
//} else {
c.JSON(code, ErrMsgOutput{strconv.Itoa(code), code, msg})
//}
}
func main() {
// Echo instance
e := echo.New()
e.SetHTTPErrorHandler(MyError)
// set log file
f, err := os.OpenFile(API_LOG, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
//t.Fatalf("error opening file: %v", err)
fmt.Printf("error opening file: %v", err)
os.Exit(1)
}
defer f.Close()
log.SetOutput(f)
e.SetLogOutput(f)
// Middleware
e.Use(Logger())
e.Use(mw.Recover())
e.Use(FixedCert())
// Error
//e.Use(func(*echo.Context) error {
// return errors.New("error")
//})
// Routes
e.Get("/", hello)
//e.Get("/user", users)
//e.Get("/service", services)
ver := e.Group("/" + version)
//dev := e.Group("/" + "dev")
// Management class
gm := ver.Group("/" + "management")
gm.Get("/user", users)
gms := gm.Group("/" + "service")
gms.Get("", services)
gms.Get("/:svc_id", service)
// Statistics class
gs := ver.Group("/" + "statistics")
//gs := dev.Group("/" + "statistics")
gss := gs.Group("/" + "service")
gss.Get("/:svc_id/traffic", traffic)
gss.Get("/:svc_id/usage", usage)
// Start server (HTTP)
log.Printf("Listening on :%s", PORT)
e.Run(":" + PORT)
// Start server (HTTPS)
//e.RunTLS(":1323", "cert.pem", "key.pem")
}