Exemplo n.º 1
0
func PostUserSettings(w rest.ResponseWriter, r *rest.Request) {
	form := UserSettings{}
	err := r.DecodeJsonPayload(&form)
	if err != nil {
		apiutils.WriteRestError(w, apierrors.NewBadRequest(err.Error()))
		return
	}

	changed := false // true if config really was updated
	err = clientconfig.Update(func(conf *clientconfig.Config) error {

		s := &conf.Settings.Local
		prevLang := s.Language
		if ValidLanguage(form.Language) {
			s.Language = form.Language
		} else {
			s.Language = "en"
		}
		if prevLang != s.Language {
			ui.Language(s.Language)
			changed = true
		}
		if s.CountryCode != form.CountryCode {
			s.CountryCode = form.CountryCode
			changed = true
		}
		if s.ClientAutoUpdate != form.ClientAutoUpdate {
			s.ClientAutoUpdate = form.ClientAutoUpdate
			changed = true
		}
		if s.BlocklistAutoUpdate != form.BlocklistAutoUpdate {
			s.BlocklistAutoUpdate = form.BlocklistAutoUpdate
			changed = true
		}

		return nil
	})
	if changed {
		err := clientconfig.Write()
		if err != nil {
			lg.Errorln(err)
		}
	}

	if err != nil {
		lg.Errorln(err)
	}

}
Exemplo n.º 2
0
func DeleteConnection(w rest.ResponseWriter, r *rest.Request) {
	ID := r.PathParam("id")

	err := clientconfig.Update(func(conf *clientconfig.Config) error {

		all := conf.Settings.Connections
		var result []shared.Connection

		// validate that the id exists
		found := false
		nEnabled := 0
		for _, v := range all {
			if v.ID == ID {
				found = true
				if v.Protected {
					apiutils.WriteRestError(w, apierrors.NewForbidden("connection", ID, nil))
					return nil
				}
			} else {
				if !v.Disabled {
					nEnabled += 1
				}
				result = append(result, v)
			}
		}
		if !found {
			apiutils.WriteRestError(w, apierrors.NewNotFound("connection", ID))
			return nil
		}
		if nEnabled < 1 {
			apiutils.WriteRestError(w,
				apierrors.NewForbidden("connection", ID, errors.New("one connection must be enabled")))
			return nil
		}
		service.UpdateConnections(result)
		conf.Settings.Connections = result
		return nil
	})
	if err != nil {
		lg.Errorln(err)
	}
	clientconfig.Write()
	w.WriteJson(true)

}
Exemplo n.º 3
0
func ToggleConnection(w rest.ResponseWriter, r *rest.Request) {
	ID := r.PathParam("id")

	err := clientconfig.Update(func(conf *clientconfig.Config) error {
		// validate that the id exists, if supplied
		all := conf.Settings.Connections
		foundIdx := 0
		found := false
		nEnabled := 0
		for k, v := range all {
			if !v.Disabled {
				nEnabled += 1
			}
			if v.ID == ID {
				found = true
				foundIdx = k
			}

		}

		if !found {
			apiutils.WriteRestError(w, apierrors.NewNotFound("connection", ID))
			return nil
		}
		if nEnabled < 2 && !conf.Settings.Connections[foundIdx].Disabled {
			apiutils.WriteRestError(w,
				apierrors.NewForbidden("connection", ID, errors.New("one connection must be enabled")))
			return nil
		}
		conf.Settings.Connections[foundIdx].Disabled = !conf.Settings.Connections[foundIdx].Disabled
		service.UpdateConnections(conf.Settings.Connections)

		return nil
	})
	if err != nil {
		lg.Errorln(err)
	}
	clientconfig.Write()
	w.WriteJson(true)

}
Exemplo n.º 4
0
// Init does precondition check if the application can/should be started.
// Init will return an error message with reason for exit printed.
func Run() {
	if debugEnabled {
		log.Println("ALKASIR_DEBUG ENABLED!")
		err := os.Setenv("ALKASIR_DEBUG", "1")
		if err != nil {
			log.Fatal(err)
		}
	}
	if hotEnabled {
		log.Println("ALKASIR_HOT ENABLED!")
		err := os.Setenv("ALKASIR_HOT", "1")
		if err != nil {
			log.Fatal(err)
		}
	}

	// the darwin systray does not exit the main loop
	if runtime.GOOS != "darwin" {
		uiRunning.Add(1)
	}

	err := ui.Run(func() {
		Atexit(ui.Done)

		// start the getpublic ip updater.
		go func() {
			_ = shared.GetPublicIPAddr()
		}()

		if debugEnabled {
			go func() {
				err := http.ListenAndServe(
					fmt.Sprintf("localhost:%d", debugPort), nil)
				if err != nil {
					panic(err)
				}
			}()
		}

		// wipe user data
		if wipeData {
			settingsdir := clientconfig.ConfigPath()
			if settingsdir == "" {
				log.Println("[wipe] Configdir not set")
				os.Exit(1)
			}
			settingsfile := clientconfig.ConfigPath("settings.json")
			if _, err := os.Stat(settingsfile); os.IsNotExist(err) {
				log.Println("[wipe] No settings.json in configdir, will NOT wipe data")
				os.Exit(1)
			}
			log.Println("Wiping all user data")
			if err := os.RemoveAll(settingsdir); err != nil {
				log.Println(err)
			}
		}

		// Prepare logging
		logdir := clientconfig.ConfigPath("log")
		err := os.MkdirAll(logdir, 0775)
		if err != nil {
			log.Println("Could not create logging directory")
			os.Exit(1)
		}
		err = flag.Set("log_dir", logdir)
		if err != nil {
			panic(err)
		}
		lg.SetSrcHighlight("alkasir/cmd", "alkasir/pkg")
		lg.CopyStandardLogTo("INFO")

		// Start init
		if VERSION != "" {
			lg.Infoln("Alkasir v" + VERSION)
		} else {
			lg.Warningln("Alkasir dev version (VERSION not set)")
		}

		lg.V(1).Info("Log v-level:", lg.Verbosity())
		_, err = clientconfig.Read()
		if err != nil {
			lg.Infoln("Could not read config")
			exit()
		}
		lg.V(30).Infoln("settings", clientconfig.Get().Settings)

		if saveChromeExt {
			err := saveChromeExtension()
			if err != nil {
				lg.Fatal(err)
			}
		}

		{
			configChanged, err := clientconfig.UpgradeConfig()
			if err != nil {
				lg.Fatalln("Could not upgrade config", err)

			}
			clientconfig.Update(func(conf *clientconfig.Config) error {

				if clientAuthKeyFlag != "" {
					lg.Warningln("Overriding generated authKey with", clientAuthKeyFlag)
					conf.Settings.Local.ClientAuthKey = clientAuthKeyFlag
					configChanged = true
				}

				if bindAddrFlag != "" {
					lg.Warningln("Overriding configured bindAddr with", bindAddrFlag)
					conf.Settings.Local.ClientBindAddr = bindAddrFlag
					configChanged = true
				}

				if centralAddrFlag != "" {
					lg.Warningln("Overriding central server addr with", centralAddrFlag)
					conf.Settings.Local.CentralAddr = centralAddrFlag
					configChanged = true
				}

				return nil
			})

			if configChanged {
				if err := clientconfig.Write(); err != nil {
					lg.Warning(err)
				}
			}

		}
		conf := clientconfig.Get()
		loadTranslations(LanguageOptions...)
		if err := ui.Language(conf.Settings.Local.Language); err != nil {
			lg.Warningln(err)
		}

		go func() {
			select {
			case <-sigIntC:
				exit()
			case <-ui.Actions.Quit:
				exit()
			}
		}()

		for _, e := range []error{
			mime.AddExtensionType(".json", "application/json"),
			mime.AddExtensionType(".js", "application/javascript"),
			mime.AddExtensionType(".css", "text/css"),
			mime.AddExtensionType(".md", "text/plain"),
		} {
			if e != nil {
				lg.Warning(e)
			}
		}

		err = startInternalHTTPServer(conf.Settings.Local.ClientAuthKey)
		if err != nil {
			lg.Fatal("could not start internal http services")
		}

		// Connect the default transport
		service.UpdateConnections(conf.Settings.Connections)
		service.UpdateTransports(conf.Settings.Transports)
		go service.StartConnectionManager(conf.Settings.Local.ClientAuthKey)

		// TODO: async
		pac.UpdateDirectList(conf.DirectHosts.Hosts)
		pac.UpdateBlockedList(conf.BlockedHostsCentral.Hosts, conf.BlockedHosts.Hosts)
		lastBlocklistChange = time.Now()

		go StartBlocklistUpgrader()
		if upgradeDiffsBaseURL != "" {
			lg.V(19).Infoln("upgradeDiffsBaseURL is ", upgradeDiffsBaseURL)
			go StartBinaryUpgradeChecker(upgradeDiffsBaseURL)
		} else {
			lg.Warningln("empty upgradeDiffsBaseURL, disabling upgrade checks")
		}

		lg.V(5).Info("Alkasir has started")

	})
	// the darwin systray does not exit the main loop
	if runtime.GOOS != "darwin" {
		uiRunning.Done()
	}

	lg.Infoln("ui.Run ended")
	if err != nil {
		log.Println("client.Run error:", err)
	}
}
Exemplo n.º 5
0
func exit() {
	lg.Infoln("alkasir is shutting down")
	atexitMu.Lock() // this lock should be kept, one shutdown should be enough for everyone.
	lg.Flush()
	if err := clientconfig.Write(); err != nil {
		lg.Errorf("could not save config file: %s", err.Error())
	}
	lg.V(9).Infoln("running atexit funcs")
	for _, f := range atexitFuncs {
		funcName := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
		lg.V(10).Infoln("Running at exit func", funcName)
		f()
		lg.V(10).Infoln("Finished at exit func", funcName)
	}
	atexitFuncs = atexitFuncs[:0]
	lg.V(9).Infoln("atexit funcs done")

	{
		lg.V(9).Infoln("stopping connectionmanager")
		done := make(chan bool)
		go func() {
			service.StopConnectionManager()
			done <- true
		}()
		select {
		case <-done:
		case <-time.After(10 * time.Second):
			lg.Errorln("services stop timed out")
		}
	}

	{
		done := make(chan bool)
		go func() {
			service.StopAll()
			done <- true
		}()
		select {
		case <-done:
			lg.V(9).Infoln("services stopped")
		case <-time.After(10 * time.Second):
			lg.Errorln("services stop timed out")
		}
	}

	{
		lg.V(9).Infoln("waiting for UI shutdown to finish")
		done := make(chan bool)
		go func() {
			uiRunning.Wait()
			done <- true
		}()
		select {
		case <-done:
		case <-time.After(10 * time.Second):
			lg.Errorln("timed out watning for ui shutdown")
		}
	}
	lg.Flush()
	lg.Infoln("alkasir shutdown complete")
	lg.Flush()
	time.Sleep(time.Millisecond * 1)
	os.Exit(0)
}
Exemplo n.º 6
0
func PostConnection(w rest.ResponseWriter, r *rest.Request) {
	form := ConnectionSetting{}
	err := r.DecodeJsonPayload(&form)
	if err != nil {
		apiutils.WriteRestError(w, apierrors.NewBadRequest(err.Error()))
		return
	}

	err = clientconfig.Update(func(conf *clientconfig.Config) error {

		all := conf.Settings.Connections

		var connection shared.Connection // decoded connection
		var invalids fielderrors.ValidationErrorList

		// Verify that the encoded field is set
		{
			if form.Encoded == "" {
				invalids = append(invalids, fielderrors.NewFieldRequired("encoded"))
			}
		}

		// verify that the connection is decodeable
		{
			var err error
			connection, err = shared.DecodeConnection(form.Encoded)
			if err != nil {
				invalids = append(invalids, fielderrors.NewFieldInvalid("encoded", form.Encoded, "invalid formatting"))
			}
		}

		// validate that the id exists, if supplied
		foundIdx := 0
		{
			if form.ID != "" {
				found := false
				for k, v := range all {
					if v.ID == form.ID {
						found = true
						foundIdx = k
					}
				}
				if !found {
					invalids = append(invalids, fielderrors.NewFieldNotFound("id", form.ID))
				}
			}
		}

		// validate that the connection doesnt alreay exist
		{
			encoded, err := connection.Encode()
			if err != nil {
				apiutils.WriteRestError(w, err)
				return nil
			}

			found := false
			for _, v := range all {
				enc2, err := v.Encode()
				if err != nil {
					lg.Errorln(err)
					continue
				}
				if enc2 == encoded {
					found = true
				}
			}
			if found {
				invalids = append(invalids, fielderrors.NewFieldDuplicate("encoded", form.Encoded))
			}
		}

		// end of field validations
		if len(invalids) > 0 {
			apiutils.WriteRestError(w, apierrors.NewInvalid("post-connection", "", invalids))
			return nil
		}

		// add connection to settings and save
		if form.ID == "" {
			connection.EnsureID()
			conf.Settings.Connections = append(conf.Settings.Connections, connection)
		} else {
			conf.Settings.Connections[foundIdx] = connection
		}
		service.UpdateConnections(conf.Settings.Connections)
		return nil
	})
	if err != nil {
		lg.Errorln(err)
	}
	clientconfig.Write()
	w.WriteJson(true)

}