common-func-dev.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. //go:build dev
  2. // +build dev
  3. package locals
  4. import (
  5. "bytes"
  6. "crypto/sha256"
  7. "encoding/base64"
  8. "encoding/json"
  9. "errors"
  10. "fmt"
  11. "io/ioutil"
  12. "net/http"
  13. "strings"
  14. "time"
  15. "github.com/dabory/abango-rest"
  16. e "github.com/dabory/abango-rest/etc"
  17. "github.com/go-xorm/xorm"
  18. "github.com/microcosm-cc/bluemonday"
  19. )
  20. const (
  21. // Tpf string = "dbr_" // TablePrefix
  22. //QueryComment
  23. QcWhere string = "-- @where"
  24. QcSubWhere string = "-- @subwhere"
  25. QcHaving string = "-- @having"
  26. QcOrder string = "-- @order"
  27. QcLimitOffset string = "-- @limitoffset"
  28. QcExtract string = "-- @extract:"
  29. QcClosed string = "-- @closed:"
  30. QcDelivery string = "-- @delivery:"
  31. QcBetweenDates string = "-- @between_dates"
  32. QcEnd string = "--" //QueryComment
  33. //QueryKeyword
  34. QkWhere string = "\nwhere true "
  35. // QkWhere string = "\nwhere 1 "
  36. QkHaving string = "\nhaving true "
  37. QkOrder string = "\norder by "
  38. QkLimit string = "\nlimit "
  39. QkOffset string = " offset "
  40. QkTmpOrder string = " order by is_sum desc, t_id asc "
  41. )
  42. type AppApi struct {
  43. ApiUrl string
  44. GateToken string
  45. }
  46. // 0:Sso, 1:Dbu 매우 중요하다.
  47. var gAppApis [2]AppApi
  48. var (
  49. SQL_DEBUG bool
  50. NORMAL_DEBUG bool
  51. )
  52. var BlockNoCnt int
  53. // type GateTokenGetReq struct {
  54. // ClientId string
  55. // BeforeBase64 string
  56. // AppBase64 string
  57. // }
  58. func (y *SyncController) Init() error {
  59. vmc := &struct {
  60. Driver string
  61. Host string
  62. Port int
  63. Username string
  64. Database string
  65. Password string
  66. }{}
  67. connStr := vmc.Username + ":" + vmc.Password + "@tcp(" + vmc.Host + ":" + e.NumToStr(vmc.Port) + ")/" + vmc.Database
  68. fmt.Println("connStr:", connStr)
  69. y.Scb.ConnString = connStr
  70. var err error
  71. if y.Db, err = xorm.NewEngine(abango.XConfig["DbType"], connStr); err != nil {
  72. return e.ErrLog(e.FuncRun("309upajs3w: DBEngine Open Error ", e.CurrFuncName()), err)
  73. }
  74. var connHint string
  75. strArr := strings.Split(connStr, "@tcp")
  76. if len(strArr) == 2 {
  77. connHint = strArr[1]
  78. } else {
  79. return e.ErrLog(e.FuncRun("309upajs3w: connString format mismatch: "+strArr[1], e.CurrFuncName()), err)
  80. }
  81. y.Db.ShowSQL(false)
  82. y.Db.SetMaxOpenConns(100)
  83. y.Db.SetMaxIdleConns(20)
  84. y.Db.SetConnMaxLifetime(60 * time.Second)
  85. if _, err := y.Db.IsTableExist("aaa"); err == nil {
  86. e.OkLog("SyncDB connection in " + connHint)
  87. return nil
  88. } else {
  89. return e.ErrLog(e.FuncRun("93haoy93d: SyncDB connection Fail in "+connHint+": ", e.CurrFuncName()), err)
  90. }
  91. }
  92. type (
  93. MemoryMap map[string]interface{}
  94. MapStore struct {
  95. store MemoryMap
  96. }
  97. )
  98. func (c *MapStore) Get(key string) interface{} {
  99. return c.store[key]
  100. }
  101. func (c *MapStore) Set(key string, val interface{}) {
  102. if c.store == nil {
  103. c.store = make(MemoryMap)
  104. }
  105. c.store[key] = val
  106. }
  107. func DbrPasswd(password string, salt string) string {
  108. salt16 := DbrSaltBase(salt, 16)
  109. var passwordBytes = []byte(password)
  110. var sha256Hasher = sha256.New()
  111. passwordBytes = append(passwordBytes, salt16...)
  112. sha256Hasher.Write(passwordBytes)
  113. var hashedPasswordBytes = sha256Hasher.Sum(nil)
  114. var base64EncodedPasswordHash = base64.URLEncoding.EncodeToString(hashedPasswordBytes)
  115. return base64EncodedPasswordHash
  116. }
  117. func DbrHashedIndex(target string) string {
  118. //!!중요: salt는 16char에서만 작동된다. hash 값은 44 char나오지만 32char로 잘라서 쓴다.
  119. fmt.Println("hash_full_length:", DbrPasswd(target, "$$hashed_index$$"))
  120. return DbrPasswd(target, "$$hashed_index$$")[0:32]
  121. }
  122. func DbrCompare(hashedPassword, currPassword string, salt string) bool {
  123. // fmt.Println("salt:", salt)
  124. // fmt.Println("currPassword:", currPassword)
  125. var currPasswordHash = DbrPasswd(currPassword, salt)
  126. // fmt.Println("currPasswordHash:", currPasswordHash)
  127. // fmt.Println("hashedPassword:", hashedPassword)
  128. return hashedPassword == currPasswordHash
  129. }
  130. func DbrSaltBase(salt string, saltSize int) []byte { //어떤 사이즈라도 16byte의 Base64로 변경
  131. tmp := []byte(salt)
  132. salt64 := base64.StdEncoding.EncodeToString(tmp)
  133. return []byte(salt64[4 : saltSize+4])
  134. }
  135. func HasPickActPage(uri string, table string) bool {
  136. if table == "member" {
  137. if uri == "/"+table+"-pick" || uri == "/"+table+"-act" || uri == "/"+table+"-page" || uri == "/"+table+"-secured-pick" || uri == "/"+table+"-secured-page" || uri == "/"+table+"-secured-act" {
  138. return true
  139. } else {
  140. return false
  141. }
  142. } else {
  143. if uri == "/"+table+"-pick" || uri == "/"+table+"-act" || uri == "/"+table+"-page" {
  144. return true
  145. } else {
  146. return false
  147. }
  148. }
  149. }
  150. // func ByteIndex(ba *[]byte, bt byte, opt int) int {
  151. // if opt == 0 { //normal
  152. // for i := 0; i < len(*ba); i++ {
  153. // if (*ba)[i] == bt {
  154. // return i
  155. // }
  156. // }
  157. // } else if opt == 1 { //rerverse
  158. // for i := len(*ba) - 1; i > 0; i-- {
  159. // if (*ba)[i] == bt {
  160. // return i
  161. // }
  162. // }
  163. // }
  164. // return -1
  165. // }
  166. func LastQry(qry xorm.Session) string {
  167. ret, _ := qry.LastSQL()
  168. fmt.Println("\n" + ret + "\n")
  169. return ret
  170. }
  171. func ShowQry(qry xorm.Session, qryName string) string {
  172. if SQL_DEBUG {
  173. ret, _ := qry.LastSQL()
  174. return e.LogStr("", "ShowQry===["+qryName+"]==="+"\n[ "+ret+" ]\n")
  175. }
  176. return ""
  177. }
  178. func ShowSql(sqlStr string, qryName string) string {
  179. if SQL_DEBUG {
  180. return e.LogStr("", "ShowSql===["+qryName+"]==="+"\n[ "+sqlStr+" ]\n")
  181. }
  182. return ""
  183. }
  184. // func ShowDebug(debugStr string, index string) string {
  185. // if NORMAL_DEBUG {
  186. // return e.LogStr("", "ShowDebug===["+index+"]==="+"\n[ "+debugStr+" ]\n")
  187. // }
  188. // return ""
  189. // }
  190. func QryDirName(qryName string) (string, string) {
  191. if !strings.Contains(qryName, "::") {
  192. return "queries/", qryName
  193. } else {
  194. q := strings.Split(qryName, "::")
  195. return "queries/themes/" + q[0] + "/", q[1]
  196. }
  197. }
  198. func StripHtml(cont string, max int) string {
  199. p := bluemonday.StripTagsPolicy()
  200. s := p.Sanitize(cont)
  201. if len(s) > max {
  202. return string([]rune(s)[:max])
  203. } else {
  204. return s
  205. }
  206. }
  207. func Sanitize(cont string) string {
  208. p := bluemonday.UGCPolicy()
  209. return p.Sanitize(cont)
  210. }
  211. func AddStrIfNotExist(s *string, target string) {
  212. if !strings.Contains(*s, target) {
  213. *s += target
  214. }
  215. }
  216. func HttpResponseSimplePost(method string, apiurl string, jsBytes []byte) (retbody []byte, retsta int, reterr error) {
  217. response, err := http.Post(apiurl, "application/json", bytes.NewBuffer(jsBytes))
  218. if err != nil {
  219. return nil, 0, errors.New(e.FuncRunErr("65rfg0csdew", "The HTTP request failed with error "+e.CurrFuncName()+err.Error()))
  220. } else {
  221. retbody, err = ioutil.ReadAll(response.Body)
  222. if err != nil {
  223. return nil, 0, errors.New(e.FuncRunErr("kjda89382", "ReadAll error "+e.CurrFuncName()+err.Error()))
  224. }
  225. }
  226. return retbody, response.StatusCode, nil
  227. }
  228. func HttpResponseWithGt(method string, apiurl string, jsBytes []byte, gateToken string) (retbody []byte, retsta int, reterr error) {
  229. reader := bytes.NewBuffer(jsBytes)
  230. req, err := http.NewRequest(method, apiurl, reader)
  231. if err != nil {
  232. return nil, 909, e.ErrLog(e.FuncRun("xcawrq3276fa-http.NewRequest "+apiurl, e.CurrFuncName()), err)
  233. }
  234. req.Header.Add("RemoteIp", "localhost")
  235. req.Header.Add("Referer", "http://localhost")
  236. req.Header.Add("GateToken", gateToken)
  237. req.Body = ioutil.NopCloser(bytes.NewReader(jsBytes))
  238. // Client객체에서 Request 실행
  239. client := &http.Client{
  240. Timeout: time.Second * 20, //Otherwirse, it can cause crash without this line. Must Must.
  241. } // Normal is 10 but extend 20 on 1 Dec 2018
  242. // fmt.Println(reflect.TypeOf(respo))
  243. resp, err := client.Do(req)
  244. if err != nil {
  245. return nil, 909, e.ErrLog(e.FuncRun("wewer2354e-client.Do "+apiurl, e.CurrFuncName()), err)
  246. }
  247. defer resp.Body.Close()
  248. byteRtn, _ := ioutil.ReadAll(resp.Body)
  249. return byteRtn, resp.StatusCode, nil
  250. }
  251. func GuestGateTokenGet(appType int, pivotUrl string, ab64 string) (string, string, error) {
  252. if gAppApis[appType].GateToken == "" {
  253. req := &struct {
  254. AppType string
  255. AppBase64 string
  256. }{
  257. AppType: "Main",
  258. AppBase64: ab64,
  259. }
  260. bodyBytes, _ := json.Marshal(req)
  261. apiUrl := pivotUrl + "/gate-token-get"
  262. msgBytes, staInt, err := HttpResponseSimplePost("POST", apiUrl, bodyBytes)
  263. // fmt.Println("apiUrl:", apiUrl)
  264. // fmt.Println("bodyBytes:", string(bodyBytes))
  265. if err != nil {
  266. return "", "", e.ErrLog(e.FuncRun("45425fd34sd-The HTTP request "+apiUrl, e.CurrFuncName()), err)
  267. }
  268. if staInt != 200 {
  269. return "", "", errors.New(e.FuncRun("87ty344ra3-Request Fail "+string(msgBytes), e.CurrFuncName()))
  270. }
  271. ret := &struct {
  272. ApiUrl string
  273. GateToken string
  274. }{}
  275. if err := json.Unmarshal(msgBytes, ret); err != nil {
  276. return "", "", e.ErrLog(e.FuncRun("45425fd34sd-Json Format "+apiUrl, e.CurrFuncName()), err)
  277. }
  278. gAppApis[appType].ApiUrl = ret.ApiUrl
  279. gAppApis[appType].GateToken = ret.GateToken
  280. } else {
  281. fmt.Println("GateToken already is in the ARRAY")
  282. }
  283. // fmt.Println("gSsoApiUrl:", gSsoApiUrl)
  284. // fmt.Println("gSsoGateToken:", gSsoGateToken)
  285. return gAppApis[appType].ApiUrl, gAppApis[appType].GateToken, nil
  286. }
  287. func GuestEncryptGet(code string) (string, string, error) {
  288. appType := 1 //Dbupdate
  289. req := &struct {
  290. EncryptCode string
  291. }{
  292. EncryptCode: code,
  293. }
  294. // 0:Sso, 1:Dbu
  295. pivotUrl, gateToken, err := GuestGateTokenGet(appType, abango.XConfig["DbuConnString"], abango.XConfig["DbuAppBase64"])
  296. if err != nil {
  297. return "", "", e.ErrLog(e.FuncRun("23rfsr3qrase", e.CurrFuncName()), err)
  298. }
  299. ret := &struct {
  300. EncrypteKey string
  301. SaltKey string
  302. }{}
  303. bodyBytes, _ := json.Marshal(req)
  304. apiUrl := pivotUrl + "/encrypt-get"
  305. msgBytes, staInt, err := HttpResponseWithGt("POST", apiUrl, bodyBytes, gateToken)
  306. if err != nil {
  307. return "", "", e.ErrLog(e.FuncRun("1eadwrq34dxc-The HTTP request "+apiUrl, e.CurrFuncName()), err)
  308. }
  309. if staInt != 200 {
  310. gAppApis[appType].GateToken = "" // GateToke Expired 경우 Clear 한다.
  311. return "", "", errors.New(e.FuncRun("45faw3rfw-Request Fail "+string(msgBytes), e.CurrFuncName()))
  312. }
  313. if err := json.Unmarshal(msgBytes, ret); err != nil {
  314. return "", "", e.ErrLog(e.FuncRun("6756er345r3", e.CurrFuncName()), err)
  315. }
  316. return ret.EncrypteKey, ret.SaltKey, nil
  317. }
  318. func GuestAvailDbupdateGet(lastno string, isskipup string) ([]byte, error) {
  319. appType := 1 //Dbupdate
  320. req := &struct {
  321. DbupdateNo string
  322. IsSkipUpdate string
  323. }{
  324. DbupdateNo: lastno,
  325. IsSkipUpdate: isskipup,
  326. }
  327. // 0:Sso, 1:Dbu
  328. pivotUrl, gateToken, err := GuestGateTokenGet(appType, abango.XConfig["DbuConnString"], abango.XConfig["DbuAppBase64"])
  329. if err != nil {
  330. return nil, e.ErrLog(e.FuncRun("23rfsr3qrase", e.CurrFuncName()), err)
  331. }
  332. bodyBytes, _ := json.Marshal(req)
  333. apiUrl := pivotUrl + "/avail-dbupdate-get"
  334. msgBytes, staInt, err := HttpResponseWithGt("POST", apiUrl, bodyBytes, gateToken)
  335. if err != nil {
  336. return nil, e.ErrLog(e.FuncRun("1eadwrq34dxc-The HTTP request "+apiUrl, e.CurrFuncName()), err)
  337. }
  338. if staInt != 200 {
  339. gAppApis[appType].GateToken = "" // GateToke Expired 경우 Clear 한다.
  340. return nil, errors.New(e.FuncRun("0asfweijcvs-Request Fail "+string(msgBytes), e.CurrFuncName()))
  341. }
  342. return msgBytes, nil
  343. }
  344. func GuestKeyPairGet(clientId string) (string, error) {
  345. appType := 0 //Dbupdate
  346. req := &struct {
  347. ClientId string
  348. }{
  349. ClientId: clientId,
  350. }
  351. // fmt.Println("clientId:", clientId)
  352. // 0:Sso, 1:Dbu
  353. pivotUrl, gateToken, err := GuestGateTokenGet(appType, abango.XConfig["SsoConnString"], abango.XConfig["SsoAppBase64"])
  354. if err != nil {
  355. return "", e.ErrLog(e.FuncRun("23rfsr3qrase", e.CurrFuncName()), err)
  356. }
  357. ret := &struct {
  358. KeyPair string
  359. }{}
  360. bodyBytes, _ := json.Marshal(req)
  361. apiUrl := pivotUrl + "/key-pair-get"
  362. msgBytes, staInt, err := HttpResponseWithGt("POST", apiUrl, bodyBytes, gateToken)
  363. if err != nil {
  364. return "", e.ErrLog(e.FuncRun("1eadwrq34dxc-The HTTP request "+apiUrl, e.CurrFuncName()), err)
  365. }
  366. if staInt != 200 {
  367. gAppApis[appType].GateToken = "" // GateToke Expired 경우 Clear 한다.
  368. return "", errors.New(e.FuncRun("09665gsre3-Request Fail "+string(msgBytes), e.CurrFuncName()))
  369. }
  370. if err := json.Unmarshal(msgBytes, ret); err != nil {
  371. return "", e.ErrLog(e.FuncRun("9074tf32de", e.CurrFuncName()), err)
  372. }
  373. return ret.KeyPair, nil
  374. }
  375. func OneRowQuery(y *abango.Controller, sql string) (c1 string, c2 string, c3 string, err error) {
  376. page, err := y.Db.Query(sql)
  377. if err != nil {
  378. return "", "", "", errors.New(e.FuncRunErr("0hjnboisqow", e.CurrFuncName()+err.Error()))
  379. }
  380. if len(page) > 1 {
  381. return "", "", "", errors.New(e.FuncRunErr("0k1dt6j3d", e.CurrFuncName()+"Row Count > 1 "))
  382. }
  383. for _, row := range page {
  384. c1 = string(row["c1"])
  385. c2 = string(row["c2"])
  386. c3 = string(row["c3"])
  387. }
  388. return
  389. }
  390. func IsFirstOrderGet(y *abango.Controller, buyerId int) string {
  391. qry := fmt.Sprintf("select count(*) as c1 from dbr_sorder where buyer_id = %d ", buyerId)
  392. ordCnt, _, _, _ := OneRowQuery(y, qry)
  393. if ordCnt == "1" {
  394. return "1"
  395. } else {
  396. return "0"
  397. }
  398. }
  399. func TimeFormatGet(format string) string {
  400. rtn := ""
  401. if format == "" {
  402. rtn = "060102"
  403. } else if format == "YYMMDD" {
  404. rtn = "060102"
  405. } else if format == "YYYYMMDD" {
  406. rtn = "20060102"
  407. } else if format == "YY-MM-DD" {
  408. rtn = "06-01-02"
  409. } else if format == "YY.MM.DD" {
  410. rtn = "06.01.02"
  411. } else if format == "YYMM" {
  412. rtn = "0601"
  413. } else if format == "YY" {
  414. rtn = "06"
  415. }
  416. return rtn
  417. }