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  }