github.com/kotovmak/go-admin@v1.1.1/adm/project_web.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "html/template" 6 "log" 7 "net" 8 "net/http" 9 "os" 10 "os/exec" 11 "os/signal" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "time" 16 17 "github.com/kotovmak/go-admin/modules/config" 18 "github.com/kotovmak/go-admin/modules/db" 19 "github.com/kotovmak/go-admin/modules/system" 20 "github.com/kotovmak/go-admin/modules/utils" 21 ) 22 23 func buildProjectWeb(port string) { 24 25 var startChan = make(chan struct{}) 26 27 type InstallationPage struct { 28 Version string 29 GoVer string 30 Port string 31 CSRFToken string 32 CurrentLang string 33 GOOS string 34 DefModuleName string 35 } 36 37 var tokens = make([]string, 0) 38 39 rootPath, err := os.Getwd() 40 41 if err != nil { 42 rootPath = "." 43 } else { 44 rootPath = filepath.ToSlash(rootPath) 45 } 46 47 dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 48 if err != nil { 49 panic(err) 50 } 51 defModuleName := filepath.Base(dir) 52 53 go func(sc chan struct{}) { 54 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 55 56 lang := defaultLang 57 if r.URL.Query().Get("lang") != "" { 58 lang = r.URL.Query().Get("lang") 59 } 60 61 w.Header().Add("Content-Type", "text/html; charset=utf-8") 62 t, err := template.New("web_installation").Funcs(map[string]interface{}{ 63 "local": local(lang), 64 }).Parse(projectWebTmpl) 65 if err != nil { 66 fmt.Println("get web installation page template error", err) 67 w.WriteHeader(http.StatusInternalServerError) 68 return 69 } 70 curLang := "web.simplified chinese" 71 if lang == "en" { 72 curLang = "web.english" 73 } 74 tk := utils.Uuid(25) 75 tokens = append(tokens, tk) 76 err = t.Execute(w, InstallationPage{ 77 Version: system.Version(), 78 GoVer: strings.Title(runtime.Version()), 79 Port: port, 80 CSRFToken: tk, 81 CurrentLang: curLang, 82 GOOS: runtime.GOOS, 83 DefModuleName: defModuleName, 84 }) 85 if err != nil { 86 fmt.Println("get web installation page template error", err) 87 w.WriteHeader(http.StatusInternalServerError) 88 return 89 } 90 }) 91 92 var checkEmpty = func(list []string, r *http.Request) (string, bool) { 93 for i := 0; i < len(list); i++ { 94 if r.PostFormValue(list[i]) == "" { 95 return list[i], false 96 } 97 } 98 return "", true 99 } 100 101 http.HandleFunc("/install", func(w http.ResponseWriter, r *http.Request) { 102 103 if r.Method != "POST" { 104 w.WriteHeader(http.StatusBadRequest) 105 w.Header().Add("Content-Type", "application/json") 106 _, _ = w.Write([]byte(`{"code": 400, "msg": "wrong method"}`)) 107 return 108 } 109 110 lang := defaultLang 111 if r.URL.Query().Get("lang") != "" { 112 lang = r.URL.Query().Get("lang") 113 } 114 115 _ = r.ParseForm() 116 117 fields := []string{"db_type", "web_framework", "module_name", "theme", "language", "http_port", "prefix", 118 "web_title", "login_page_logo", "sidebar_logo", "sidebar_min_logo"} 119 120 if field, ok := checkEmpty(fields, r); !ok { 121 w.WriteHeader(http.StatusOK) 122 w.Header().Add("Content-Type", "application/json") 123 _, _ = w.Write([]byte(`{"code": 400, "msg": "` + local(lang)("web.wrong parameter") + `: ` + field + `"}`)) 124 return 125 } 126 127 if r.PostFormValue("db_type") == "sqlite" { 128 if r.PostFormValue("db_path") == "" { 129 w.WriteHeader(http.StatusOK) 130 w.Header().Add("Content-Type", "application/json") 131 _, _ = w.Write([]byte(`{"code": 400, "msg": "` + local(lang)("web.wrong parameter") + `"}`)) 132 return 133 } 134 } else if r.PostFormValue("db_type") == "postgresql" { 135 if field, ok := checkEmpty([]string{"db_schema", "db_port", "db_host", "db_user", "db_passwd", "db_name"}, r); !ok { 136 w.WriteHeader(http.StatusOK) 137 w.Header().Add("Content-Type", "application/json") 138 _, _ = w.Write([]byte(`{"code": 400, "msg": "` + local(lang)("web.wrong parameter") + `: ` + field + `"}`)) 139 return 140 } 141 } else if r.PostFormValue("db_type") == "oceanbase" { 142 if field, ok := checkEmpty([]string{"db_port", "db_host", "db_user", "db_name"}, r); !ok { 143 w.WriteHeader(http.StatusOK) 144 w.Header().Add("Content-Type", "application/json") 145 _, _ = w.Write([]byte(`{"code": 400, "msg": "` + local(lang)("web.wrong parameter") + `: ` + field + `"}`)) 146 return 147 } 148 149 } else { 150 if field, ok := checkEmpty([]string{"db_port", "db_host", "db_user", "db_passwd", "db_name"}, r); !ok { 151 w.WriteHeader(http.StatusOK) 152 w.Header().Add("Content-Type", "application/json") 153 _, _ = w.Write([]byte(`{"code": 400, "msg": "` + local(lang)("web.wrong parameter") + `: ` + field + `"}`)) 154 return 155 } 156 } 157 158 var p = Project{ 159 Port: r.PostFormValue("http_port"), 160 Theme: r.PostFormValue("theme"), 161 Prefix: r.PostFormValue("prefix"), 162 Language: r.PostFormValue("language"), 163 Driver: r.PostFormValue("db_type"), 164 DriverModule: r.PostFormValue("db_type"), 165 Framework: r.PostFormValue("web_framework"), 166 Module: r.PostFormValue("module_name"), 167 Orm: r.PostFormValue("use_gorm"), 168 } 169 170 if p.Driver == db.DriverPostgresql { 171 p.DriverModule = "postgres" 172 } 173 174 var ( 175 info = &dbInfo{ 176 DriverName: r.PostFormValue("db_type"), 177 Host: r.PostFormValue("db_host"), 178 Port: r.PostFormValue("db_port"), 179 File: r.PostFormValue("db_path"), 180 User: r.PostFormValue("db_user"), 181 Password: r.PostFormValue("db_passwd"), 182 Schema: r.PostFormValue("db_schema"), 183 Database: r.PostFormValue("db_name"), 184 } 185 dbList config.DatabaseList 186 ) 187 188 if info.DriverName != db.DriverSqlite { 189 dbList = map[string]config.Database{ 190 "default": { 191 Host: info.Host, 192 Port: info.Port, 193 User: info.User, 194 Pwd: info.Password, 195 Name: info.Database, 196 MaxIdleConns: 5, 197 MaxOpenConns: 10, 198 ConnMaxLifetime: time.Hour, 199 ConnMaxIdleTime: 0, 200 Driver: info.DriverName, 201 }, 202 } 203 } else { 204 dbList = map[string]config.Database{ 205 "default": { 206 Driver: info.DriverName, 207 File: info.File, 208 }, 209 } 210 } 211 212 cfg := config.SetDefault(&config.Config{ 213 Debug: true, 214 Env: config.EnvLocal, 215 Theme: p.Theme, 216 Store: config.Store{ 217 Path: "./uploads", 218 Prefix: "uploads", 219 }, 220 Language: p.Language, 221 UrlPrefix: p.Prefix, 222 IndexUrl: "/", 223 AccessLogPath: rootPath + "/logs/access.log", 224 ErrorLogPath: rootPath + "/logs/error.log", 225 InfoLogPath: rootPath + "/logs/info.log", 226 BootstrapFilePath: rootPath + "/bootstrap.go", 227 GoModFilePath: rootPath + "/go.mod", 228 Logo: template.HTML(r.PostFormValue("sidebar_logo")), 229 LoginLogo: template.HTML(r.PostFormValue("login_page_logo")), 230 MiniLogo: template.HTML(r.PostFormValue("sidebar_min_logo")), 231 Title: r.PostFormValue("web_title"), 232 Databases: dbList, 233 }) 234 235 installProjectTmpl(p, cfg, "", info) 236 237 w.Header().Add("Content-Type", "application/json") 238 w.WriteHeader(http.StatusOK) 239 _, _ = w.Write([]byte(`{"code": 0, "msg": "` + local(lang)("web.install success") + `", "data": {"readme": ""}}`)) 240 }) 241 242 l, err := net.Listen("tcp", ":"+port) 243 if err != nil { 244 log.Fatal("ListenAndServe: ", err) 245 } 246 247 fmt.Println("GoAdmin web install program start.") 248 sc <- struct{}{} 249 250 if err := http.Serve(l, nil); err != nil { 251 log.Fatal("ListenAndServe: ", err) 252 } 253 fmt.Println("GoAdmin web install program start.") 254 255 }(startChan) 256 257 <-startChan 258 err = open("http://localhost:" + port + "/") 259 if err != nil { 260 fmt.Println("failed to open browser", err) 261 } 262 263 quit := make(chan os.Signal, 1) 264 signal.Notify(quit, os.Interrupt) 265 <-quit 266 } 267 268 func open(url string) error { 269 var cmd string 270 var args []string 271 272 switch runtime.GOOS { 273 case "windows": 274 cmd = "cmd" 275 args = []string{"/c", "start"} 276 case "darwin": 277 cmd = "open" 278 default: // "linux", "freebsd", "openbsd", "netbsd" 279 cmd = "xdg-open" 280 } 281 args = append(args, url) 282 return exec.Command(cmd, args...).Start() 283 }