common-func.go 15 KB

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