Пример #1
0
func Main() {
	// Read in any environment variables we care about
	readEnv()

	var err error

	AWS_AUTH, err = aws.EnvAuth()
	if err != nil {
		panic(err.Error())
	}

	// Open database connection
	db, err := models.OpenDB("postgres", IRLMOJI_DBURI)
	if err != nil {
		log.Fatalf("Error opening database connection: %v", err.Error())
		return
	}
	if err = createAllTables(db); err != nil {
		log.Fatalf("Error creating database table: %v", err.Error())
	}

	// Start setting up martini
	m := martini.Classic()

	// Set up the middleware
	m.Use(gzip.All())
	m.Use(render.Renderer())
	m.Use(BackchannelAuth(IRLMOJI_API_BASIC_USER))

	// Inject the database
	m.Map(db)

	// Map the URL routes
	m.Get("/", HandleIndex)

	// User routes (see handlers_user.go)
	m.Get("/api/v1/users/current.json", HandleGetCurrentUser)
	m.Post("/api/v1/users/twitter.json", binding.Json(models.UserForm{}), HandleCreateUserByTwitter)

	// IRLMoji routes (see handlers_irlmoji.go)
	m.Get("/api/v1/timelines/home.json", binding.Form(Limit{}), HandleGetHomeTimeline)
	m.Get("/api/v1/timelines/user/username/:username.json", binding.Form(Limit{}), HandleGetUserTimeline)
	m.Get("/api/v1/timelines/emoji/:emoji.json", binding.Form(Limit{}), HandleGetEmojiTimeline)
	m.Get("/api/v1/irlmoji/id/:irlmojiId.json", binding.Form(Limit{}), HandleGetIRLMoji)
	m.Delete("/api/v1/irlmoji/id/:irlmojiId.json", HandleDeleteIRLMoji)
	m.Post("/api/v1/irlmoji.json", binding.Json(models.IRLMoji{}), HandleCreateIRLMoji)
	m.Post("/api/v1/irlmoji/id/:irlmojiId/heart.json", binding.Json(models.Heart{}), HandleToggleHeart)

	m.Post("/upload", HandleUpload)

	m.NotFound(HandleNotFound)

	m.Run()
}
Пример #2
0
func main() {

	m := martini.Classic()
	// specify the layout to use when rendering HTML
	m.Use(render.Renderer(render.Options{
		Layout: "layout",
	}))
	// use the Mongo middleware
	m.Use(DB())

	// list of all cribs
	m.Get("/", func(r render.Render, db *mgo.Database) {
		r.HTML(200, "list", All(db))
	})

	/*
	   create a new crib the form submission. Contains some martini magic. The call
	   to binding.Form(Crib{}) parses out form data when the request comes in.
	   It binds the data to the struct, maps it to the request context  and
	   injects into our next handler function to insert into Mongodb.
	*/
	m.Post("/", binding.Form(Crib{}), func(crib Crib, r render.Render, db *mgo.Database) {
		db.C("cribs").Insert(crib)
		r.HTML(200, "list", All(db))
	})

	// display the crib for a specific user
	m.Get("/:handle", func(params martini.Params, r render.Render, db *mgo.Database) {
		r.HTML(200, "display", Fetch(db, params["handle"]))
	})

	http.ListenAndServe(":8080", m)

}
Пример #3
0
func main() {
	quotes := make([]Quote, 0, 50)

	m := martini.Classic()
	// render html templates from templates directory
	m.Use(render.Renderer(render.Options{
		Layout: "layout",
	}))
	m.Use(martini.Static("assets"))

	m.Get("/", func(r render.Render) {
		r.Redirect("/list", 302)
	})

	m.Get("/list", func(r render.Render) {
		r.HTML(200, "list", quotes)
	})

	m.Get("/newitem.html", func(r render.Render) {
		r.HTML(200, "newitem", nil)
	})

	m.Post("/list", binding.Form(Quote{}), func(q Quote, r render.Render) {
		quotes = append(quotes, q)
		r.Redirect("/list", 302)
	})

	m.Run()
}
Пример #4
0
func main() {
	m := martini.Classic()

	m.Use(render.Renderer())

	m.Get("/post/:id", controllers.GetPost)
	m.Get("/posts", controllers.ListPosts)
	m.Post("/post", binding.Form(forms.Post{}), controllers.CreatePost)

	m.Run()
}
Пример #5
0
func main() {
	m := martini.Classic()
	m.Use(render.Renderer())
	m.Use(martini.Static("scripts"))

	collection := monitor.New()

	collection.AddMonitor(&monitor.Monitor{Name: "Motherbrain", HttpAddress: "10.10.8.81:80", MonitorType: "web"})
	collection.AddMonitor(&monitor.Monitor{Name: "AQR Web 1", HttpAddress: "10.10.11.144:80", MonitorType: "web", ActiveRedirect: true})
	collection.AddMonitor(&monitor.Monitor{Name: "AQR Web 2", HttpAddress: "10.10.9.8:80", MonitorType: "web"})
	collection.AddMonitor(&monitor.Monitor{Name: "AQR Web 3", HttpAddress: "10.10.9.247:80", MonitorType: "web"})
	collection.AddMonitor(&monitor.Monitor{Name: "AQR Web 4", HttpAddress: "10.10.8.32:80", MonitorType: "web"})

	go collection.Run()

	m.Get("/", func(w http.ResponseWriter, r *http.Request) {
		if redirectAddress, err := collection.FetchActiveRedirect(); err == nil {
			http.Redirect(w, r, "http://"+redirectAddress, http.StatusMovedPermanently)
		}

	})

	m.Get("/dashboard", func(r render.Render) {
		r.HTML(200, "master", nil)
	})

	m.Get("/api/getMonitors", func() string {
		data, _ := json.Marshal(collection)
		return string(data)
	})

	m.Post("/api/addMonitor", binding.Form(monitor.Monitor{}), func(monitor monitor.Monitor) {
		collection.AddMonitor(&monitor)
	})

	m.Post("/api/removeMonitor", func(w http.ResponseWriter, r *http.Request) {
		name := r.FormValue("removeName")
		collection.Remove(name)
		http.Redirect(w, r, "/dashboard", http.StatusFound)
	})

	m.Post("/api/activateMonitor", func(w http.ResponseWriter, r *http.Request) {
		name := r.FormValue("activateName")
		collection.ActivateMonitor(name)
		http.Redirect(w, r, "/dashboard", http.StatusFound)
	})

	m.Run()
}
Пример #6
0
Файл: main.go Проект: top/Synux
func main() {
	m := martini.Classic()
	m.Use(render.Renderer())
	m.Use(DB())

	m.Get("/wishes", func(r render.Render, db *mgo.Database) {
		r.HTML(200, "list", GetAll(db))
	})

	m.Post("/wishes", binding.Form(Wish{}), func(wish Wish, r render.Render, db *mgo.Database) {
		db.C("wishes").Insert(wish)
		r.HTML(200, "list", GetAll(db))
	})

	m.Run()
}
Пример #7
0
func main() {
	m := martini.Classic()
	db, err := gorm.Open("sqlite3", "./gorm.db")
	if err != nil {
		panic("Could not open db")
	}
	migrateDb(db)

	m.Use(render.Renderer()) //HTML & JSON renderer middleware

	m.Get("/", func() string {
		return "Hello world!"
	})

	m.Get("/error", func() (int, string) {
		return 400, "i'm a teapot" // HTTP 418 : "i'm a teapot"
	})

	m.Get("/error500", func() (int, string) {
		return 500, "i'm a teapot" // HTTP 418 : "i'm a teapot"
	})

	m.Get("/api/user", func(r render.Render) {
		user := ormTest(db)
		r.JSON(201, user)
	})

	m.Get("/user", func(r render.Render) {
		users := ormTest(db)
		r.HTML(200, "user", users)
	})

	m.Get("/users", func(r render.Render) {
		users := GetAllUsers(db)
		r.HTML(200, "createUser", users)
	})

	m.Post("/users", binding.Form(model.User{}), func(user model.User, r render.Render) {
		db.Create(&user)
		fmt.Printf("%v\n", user)
		users := GetAllUsers(db)
		r.HTML(200, "createUser", users)
	})

	m.Run()
}
Пример #8
0
func main() {
	m := martini.Classic()

	postsController := new(controllers.PostsController)

	m.Use(render.Renderer(render.Options{
		Directory: "templates",
		Layout:    "layout",
	}))
	m.Use(PopulateAppContext)
	m.Use(CloseDatabase)
	m.Use(martini.Static("public"))

	m.Get("/", postsController.Index)
	m.Get("/posts/new", postsController.New)
	m.Post("/posts/new", binding.Form(models.Post{}), postsController.Create)

	log.Fatal(http.ListenAndServe("192.168.1.60:8080", m))
}
Пример #9
0
func main() {
	var err error
	var latestheight, latestheightcache int
	var blockscached *[]*btcplex.Block
	usage := `BTCplex webapp/API server.

Usage:
  btcplex-server [--config=<path>]
  btcplex-server -h | --help

Options:
  -h --help         Show this screen.
  -c <path>, --config <path>    Path to config file [default: config.json].
`
	arguments, _ := docopt.Parse(usage, nil, true, "btcplex-server", false)

	confFile := "config.json"
	if arguments["--config"] != nil {
		confFile = arguments["--config"].(string)
	}

	log.Println("Starting btcplex-server")

	conf, err = btcplex.LoadConfig(confFile)
	if err != nil {
		log.Fatalf("Can't load config file: %v\n", err)
	}

	// Used for pub/sub in the webapp and data like latest processed height
	pool, err := btcplex.GetRedis(conf)
	if err != nil {
		log.Fatalf("Can't connect to Redis: %v\n", err)
	}

	// Due to args injection I can't use two *redis.Pool with maritini
	rediswrapper := new(RedisWrapper)
	rediswrapper.Pool = pool

	ssdb, err := btcplex.GetSSDB(conf)
	if err != nil {
		log.Fatalf("Can't connect to SSDB: %v\n", err)
	}

	// Setup some pubsub:

	// Compute the unconfirmed transaction count in a ticker
	utxscnt := 0
	utxscntticker := time.NewTicker(1 * time.Second)
	go func(pool *redis.Pool, utxscnt *int) {
		c := pool.Get()
		defer c.Close()
		for _ = range utxscntticker.C {
			*utxscnt, _ = redis.Int(c.Do("ZCARD", "btcplex:rawmempool"))
		}
	}(pool, &utxscnt)

	// Pool the latest height from BTCplex db,
	// also track the status/check if BTCplex goes out of sync
	latestheightticker := time.NewTicker(1 * time.Second)
	checkinprogress := false
	bitcoindheight := btcplex.GetBlockCountRPC(conf)
	btcplexsynced := true
	go func(pool *redis.Pool, latestheight *int) {
		c := pool.Get()
		defer c.Close()
		for _ = range latestheightticker.C {
			*latestheight, _ = redis.Int(c.Do("GET", "height:latest"))

			if latestheightcache != *latestheight {
				log.Println("Re-building homepage blocks cache")
				blocks, _ := btcplex.GetLastXBlocks(ssdb, uint(*latestheight), uint(*latestheight-30))
				blockscached = &blocks
				latestheightcache = *latestheight
			}

			bitcoindheight = btcplex.GetBlockCountRPC(conf)
			if uint(latestheightcache) != bitcoindheight && !checkinprogress && btcplexsynced {
				checkinprogress = true
				go func(checkinprogress *bool) {
					if bitcoindheight-uint(latestheightcache) > 20 {
						btcplexsynced = false
						log.Printf("CRITICAL: OUT OF SYNC / btcplex:%v, bitcoind:%v\n", latestheightcache, bitcoindheight)
					} else {
						log.Println("WARNING: BTCplex Out of sync, waiting before another check")
						time.Sleep(synctimeout * time.Second)
						if btcplexsynced && uint(latestheightcache) != bitcoindheight {
							btcplexsynced = false
							log.Printf("CRITICAL: OUT OF SYNC / btcplex:%v, bitcoind:%v\n", latestheightcache, bitcoindheight)
						}
					}
					*checkinprogress = false
				}(&checkinprogress)
			}
			if uint(latestheightcache) == bitcoindheight && !btcplexsynced {
				log.Println("INFO: Sync with bitcoind done")
				btcplexsynced = true
			}
		}
	}(ssdb, &latestheight)

	// PubSub channel for blocknotify bitcoind RPC like
	blocknotifygroup := bcast.NewGroup()
	go blocknotifygroup.Broadcasting(0)
	go bcastToRedisPubSub(pool, blocknotifygroup, "btcplex:blocknotify2")

	// PubSub channel for unconfirmed txs / rawmemorypool
	utxgroup := bcast.NewGroup()
	go utxgroup.Broadcasting(0)
	go bcastToRedisPubSub(pool, utxgroup, "btcplex:utxs")
	// TODO Ticker for utxs count => events_unconfirmed

	newblockgroup := bcast.NewGroup()
	go newblockgroup.Broadcasting(0)
	go bcastToRedisPubSub(pool, newblockgroup, "btcplex:newblock")

	btcplexsyncedgroup := bcast.NewGroup()
	go btcplexsyncedgroup.Broadcasting(0)

	// Go template helper
	appHelpers := template.FuncMap{
		"cut": func(addr string, length int) string {
			return fmt.Sprintf("%v...", addr[:length])
		},
		"cutmiddle": func(addr string, length int) string {
			return fmt.Sprintf("%v...%v", addr[:length], addr[len(addr)-length:])
		},
		"tokb": func(size uint32) string {
			return fmt.Sprintf("%.3f", float32(size)/1024)
		},
		"computefee": func(tx *btcplex.Tx) string {
			if tx.TotalIn == 0 {
				return "0"
			}
			return fmt.Sprintf("%v", float32(tx.TotalIn-tx.TotalOut)/1e8)
		},
		"generationmsg": func(tx *btcplex.Tx) string {
			reward := btcplex.GetBlockReward(tx.BlockHeight)
			fee := float64(tx.TotalOut-uint64(reward)) / 1e8
			return fmt.Sprintf("%v MAZA + %.8f total fees", float64(reward)/1e8, fee)
		},
		"tobtc": func(val uint64) string {
			return fmt.Sprintf("%.8f", float64(val)/1e8)
		},
		"inttobtc": func(val int64) string {
			return fmt.Sprintf("%.8f", float64(val)/1e8)
		},
		"formatprevout": func(prevout *btcplex.PrevOut) string {
			return fmt.Sprintf("%v:%v", prevout.Hash, prevout.Vout)
		},
		"formattime": func(ts uint32) string {
			return fmt.Sprintf("%v", time.Unix(int64(ts), 0).UTC())
		},
		"formatiso": func(ts uint32) string {
			return fmt.Sprintf("%v", time.Unix(int64(ts), 0).Format(time.RFC3339))
		},
		"sub": func(h, p uint) uint {
			return h - p
		},
		"add": func(h, p uint) uint {
			return h + p
		},
		"iadd": func(h, p int) int {
			return h + p
		},
		"confirmation": func(hash string, height uint) uint {
			bm, _ := btcplex.NewBlockMeta(ssdb, hash)
			if bm.Main == false {
				return 0
			}
			return uint(latestheight) - height + 1
		},
		"is_orphaned": func(block *btcplex.Block) bool {
			if block.Height == uint(latestheight) {
				return false
			}
			return !block.Main
		},
	}

	m := martini.Classic()
	m.Map(rediswrapper)
	m.Map(ssdb)

	tmpldir := "templates"
	if conf.AppTemplatesPath != "" {
		tmpldir = conf.AppTemplatesPath
	}
	m.Use(render.Renderer(render.Options{
		Directory: tmpldir,
		Layout:    "layout",
		Funcs:     []template.FuncMap{appHelpers},
	}))

	// We rate limit the API if enabled in the config
	if conf.AppApiRateLimited {
		m.Use(func(res http.ResponseWriter, req *http.Request, rediswrapper *RedisWrapper, log *log.Logger) {
			remoteIP := strings.Split(req.RemoteAddr, ":")[0]
			_, xforwardedfor := req.Header["X-Forwarded-For"]
			if xforwardedfor {
				remoteIP = req.Header["X-Forwarded-For"][1]
			}
			log.Printf("R:%v\nip:%+v\n", time.Now(), remoteIP)
			if strings.Contains(req.RequestURI, "/api/") {
				ratelimited, cnt, reset := rateLimited(rediswrapper, remoteIP)
				// Set X-RateLimit-* Header
				res.Header().Set("X-RateLimit-Limit", strconv.Itoa(ratelimitcnt))
				res.Header().Set("X-RateLimit-Remaining", strconv.Itoa(ratelimitcnt-cnt))
				res.Header().Set("X-RateLimit-Reset", strconv.Itoa(reset))
				// Set CORS header
				res.Header().Set("Access-Control-Expose-Headers", " X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset")
				res.Header().Set("Access-Control-Allow-Origin", "*")

				if ratelimited {
					res.WriteHeader(429)
				}
			}
		})
	}

	// Don't want Google to crawl API
	m.Get("/robots.txt", func() string {
		return "User-agent: *\nDisallow: /api"
	})

	m.Get("/", func(r render.Render, db *redis.Pool) {
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		pm.Blocks = blockscached
		pm.Title = "Latest Bitcoin blocks"
		pm.Description = "Open source Bitcoin block chain explorer with JSON API"
		pm.Menu = "latest_blocks"
		pm.LastHeight = uint(latestheight)
		pm.Analytics = conf.AppGoogleAnalytics
		r.HTML(200, "index", &pm)
	})

	m.Get("/blocks/:currentheight", func(params martini.Params, r render.Render, db *redis.Pool) {
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		currentheight, _ := strconv.ParseUint(params["currentheight"], 10, 0)
		blocks, _ := btcplex.GetLastXBlocks(db, uint(currentheight), uint(currentheight-30))
		pm.Blocks = &blocks
		pm.Title = "Bitcoin blocks"
		pm.Menu = "blocks"
		pm.LastHeight = uint(latestheight)
		pm.CurrentHeight = uint(currentheight)
		pm.Analytics = conf.AppGoogleAnalytics
		r.HTML(200, "blocks", &pm)
	})

	m.Get("/block/:hash", func(params martini.Params, r render.Render, db *redis.Pool) {
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		pm.LastHeight = uint(latestheight)
		block, _ := btcplex.GetBlockCachedByHash(db, params["hash"])
		block.FetchMeta(db)
		btcplex.By(btcplex.TxIndex).Sort(block.Txs)
		pm.Block = block
		pm.Title = fmt.Sprintf("Bitcoin block #%v", block.Height)
		pm.Description = fmt.Sprintf("Bitcoin block #%v summary and related transactions", block.Height)
		pm.Analytics = conf.AppGoogleAnalytics
		r.HTML(200, "block", &pm)
	})

	m.Get("/api/block/:hash", func(params martini.Params, r render.Render, db *redis.Pool, req *http.Request) {
		block, _ := btcplex.GetBlockCachedByHash(db, params["hash"])
		block.FetchMeta(db)
		btcplex.By(btcplex.TxIndex).Sort(block.Txs)
		block.Links = initHATEOAS(block.Links, req)
		if block.Parent != "" {
			block.Links = addHATEOAS(block.Links, "previous_block", fmt.Sprintf("%v/api/block/%v", conf.AppUrl, block.Parent))
		}
		if block.Next != "" {
			block.Links = addHATEOAS(block.Links, "next_block", fmt.Sprintf("%v/api/block/%v", conf.AppUrl, block.Next))
		}
		r.JSON(200, block)
	})

	m.Get("/unconfirmed-transactions", func(params martini.Params, r render.Render, db *redis.Pool, rdb *RedisWrapper) {
		//rpool := rdb.Pool
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		pm.LastHeight = uint(latestheight)
		pm.Menu = "utxs"
		pm.Title = "Unconfirmed transactions"
		pm.Description = "Transactions waiting to be included in a Bitcoin block, updated in real time."
		//utxs, _ := btcplex.GetUnconfirmedTxs(rpool)
		pm.Txs = &[]*btcplex.Tx{}
		pm.Analytics = conf.AppGoogleAnalytics
		r.HTML(200, "unconfirmed-transactions", &pm)
	})

	m.Get("/tx/:hash", func(params martini.Params, r render.Render, db *redis.Pool, rdb *RedisWrapper) {
		var tx *btcplex.Tx
		rpool := rdb.Pool
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		pm.LastHeight = uint(latestheight)
		isutx, _ := btcplex.IsUnconfirmedTx(rpool, params["hash"])
		if isutx {
			pm.TxUnconfirmed = true
			tx, _ = btcplex.GetUnconfirmedTx(rpool, params["hash"])
		} else {
			tx, _ = btcplex.GetTx(db, params["hash"])
			tx.Build(db)
		}
		pm.Tx = tx
		pm.Title = fmt.Sprintf("Bitcoin transaction %v", tx.Hash)
		pm.Description = fmt.Sprintf("Bitcoin transaction %v summary.", tx.Hash)
		pm.Analytics = conf.AppGoogleAnalytics
		r.HTML(200, "tx", pm)
	})
	m.Get("/api/tx/:hash", func(params martini.Params, r render.Render, db *redis.Pool, rdb *RedisWrapper, req *http.Request) {
		var tx *btcplex.Tx
		rpool := rdb.Pool
		isutx, _ := btcplex.IsUnconfirmedTx(rpool, params["hash"])
		if isutx {
			tx, _ = btcplex.GetUnconfirmedTx(rpool, params["hash"])
		} else {
			tx, _ = btcplex.GetTx(db, params["hash"])
			tx.Build(db)
		}
		tx.Links = initHATEOAS(tx.Links, req)
		if tx.BlockHash != "" {
			tx.Links = addHATEOAS(tx.Links, "block", fmt.Sprintf("%v/api/block/%v", conf.AppUrl, tx.BlockHash))
		}
		r.JSON(200, tx)
	})

	m.Get("/address/:address", func(params martini.Params, r render.Render, db *redis.Pool, req *http.Request) {
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		pm.LastHeight = uint(latestheight)
		pm.PaginationData = new(PaginationData)
		pm.Title = fmt.Sprintf("Bitcoin address %v", params["address"])
		pm.Description = fmt.Sprintf("Transactions and summary for the Bitcoin address %v.", params["address"])
		// AddressData
		addressdata, _ := btcplex.GetAddress(db, params["address"])
		pm.AddressData = addressdata
		// Pagination
		d := float64(addressdata.TxCnt) / float64(txperpage)
		pm.PaginationData.MaxPage = int(math.Ceil(d))
		currentPage := req.URL.Query().Get("page")
		if currentPage == "" {
			currentPage = "1"
		}
		pm.PaginationData.CurrentPage, _ = strconv.Atoi(currentPage)
		pm.PaginationData.Pages = N(pm.PaginationData.MaxPage)
		pm.PaginationData.Next = 0
		pm.PaginationData.Prev = 0
		if pm.PaginationData.CurrentPage > 1 {
			pm.PaginationData.Prev = pm.PaginationData.CurrentPage - 1
		}
		if pm.PaginationData.CurrentPage < pm.PaginationData.MaxPage {
			pm.PaginationData.Next = pm.PaginationData.CurrentPage + 1
		}
		fmt.Printf("%+v\n", pm.PaginationData)
		// Fetch txs given the pagination
		addressdata.FetchTxs(db, txperpage*(pm.PaginationData.CurrentPage-1), txperpage*pm.PaginationData.CurrentPage)
		r.HTML(200, "address", pm)
	})
	m.Get("/api/address/:address", func(params martini.Params, r render.Render, db *redis.Pool, req *http.Request) {
		addressdata, _ := btcplex.GetAddress(db, params["address"])
		lastPage := int(math.Ceil(float64(addressdata.TxCnt) / float64(txperpage)))
		currentPageStr := req.URL.Query().Get("page")
		if currentPageStr == "" {
			currentPageStr = "1"
		}
		currentPage, _ := strconv.Atoi(currentPageStr)
		// HATEOS section
		addressdata.Links = initHATEOAS(addressdata.Links, req)
		pageurl := "%v/api/address/%v?page=%v"
		if currentPage < lastPage {
			addressdata.Links = addHATEOAS(addressdata.Links, "last", fmt.Sprintf(pageurl, conf.AppUrl, params["address"], lastPage))
			addressdata.Links = addHATEOAS(addressdata.Links, "next", fmt.Sprintf(pageurl, conf.AppUrl, params["address"], currentPage+1))
		}
		if currentPage > 1 {
			addressdata.Links = addHATEOAS(addressdata.Links, "previous", fmt.Sprintf(pageurl, conf.AppUrl, params["address"], currentPage-1))
		}
		addressdata.FetchTxs(db, txperpage*(currentPage-1), txperpage*currentPage)
		r.JSON(200, addressdata)
	})

	m.Get("/about", func(r render.Render) {
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		pm.LastHeight = uint(latestheight)
		pm.Title = "About"
		pm.Description = "Learn more about BTCPlex, an open source Bitcoin blockchain browser written in Go."
		pm.Menu = "about"
		pm.Analytics = conf.AppGoogleAnalytics
		r.HTML(200, "about", pm)
	})

	m.Get("/status", func(r render.Render) {
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		pm.LastHeight = uint(latestheight)
		pm.Title = "Status"
		pm.Description = "BTCplex status page."
		pm.Menu = "status"
		pm.Analytics = conf.AppGoogleAnalytics
		btcplexinfo, _ := btcplex.GetInfoRPC(conf)
		pm.BitcoindInfo = btcplexinfo
		r.HTML(200, "status", pm)
	})

	m.Post("/search", binding.Form(searchForm{}), binding.ErrorHandler, func(search searchForm, r render.Render, db *redis.Pool, rdb *RedisWrapper) {
		rpool := rdb.Pool
		pm := new(pageMeta)
		pm.BtcplexSynced = btcplexsynced
		// Check if the query isa block height
		isblockheight, hash := btcplex.IsBlockHeight(db, search.Query)
		if isblockheight && hash != "" {
			r.Redirect(fmt.Sprintf("/block/%v", hash))
		}
		// Check if the query is block hash
		isblockhash, hash := btcplex.IsBlockHash(db, search.Query)
		if isblockhash {
			r.Redirect(fmt.Sprintf("/block/%v", hash))
		}
		// Check for TX
		istxhash, txhash := btcplex.IsTxHash(db, search.Query)
		if istxhash {
			r.Redirect(fmt.Sprintf("/tx/%v", txhash))
		}
		isutx, txhash := btcplex.IsUnconfirmedTx(rpool, search.Query)
		if isutx {
			r.Redirect(fmt.Sprintf("/tx/%v", txhash))
		}
		// Check for Bitcoin address
		isaddress, address := btcplex.IsAddress(search.Query)
		if isaddress {
			r.Redirect(fmt.Sprintf("/address/%v", address))
		}
		pm.Title = "Search"
		pm.Error = "Nothing found"
		pm.Analytics = conf.AppGoogleAnalytics
		r.HTML(200, "search", pm)
	})

	m.Get("/api/getblockcount", func(r render.Render) {
		r.JSON(200, latestheight)
	})

	//	m.Get("/api/latesthash", func(r render.Render) {
	//		r.JSON(200, latesthash)
	//	})

	m.Get("/api/getblockhash/:height", func(r render.Render, params martini.Params, db *redis.Pool) {
		height, _ := strconv.ParseUint(params["height"], 10, 0)
		blockhash, _ := btcplex.GetBlockHash(db, uint(height))
		r.JSON(200, blockhash)
	})

	m.Get("/api/getreceivedbyaddress/:address", func(r render.Render, params martini.Params, db *redis.Pool) {
		res, _ := btcplex.GetReceivedByAddress(db, params["address"])
		r.JSON(200, res)
	})

	m.Get("/api/getsentbyaddress/:address", func(r render.Render, params martini.Params, db *redis.Pool) {
		res, _ := btcplex.GetSentByAddress(db, params["address"])
		r.JSON(200, res)
	})

	m.Get("/api/addressbalance/:address", func(r render.Render, params martini.Params, db *redis.Pool) {
		res, _ := btcplex.AddressBalance(db, params["address"])
		r.JSON(200, res)
	})

	m.Get("/api/checkaddress/:address", func(params martini.Params, r render.Render) {
		valid, _ := btcplex.ValidA58([]byte(params["address"]))
		r.JSON(200, valid)
	})

	m.Get("/api/blocknotify", func(w http.ResponseWriter, r *http.Request) {
		incrementClient()
		defer decrementClient()
		running := true
		notifier := w.(http.CloseNotifier).CloseNotify()
		timer := time.NewTimer(time.Second * 1800)

		f, _ := w.(http.Flusher)
		w.Header().Set("Content-Type", "text/event-stream")
		w.Header().Set("Cache-Control", "no-cache")
		w.Header().Set("Connection", "keep-alive")

		bnotifier := blocknotifygroup.Join()
		defer bnotifier.Close()

		var ls interface{}
		for {
			if running {
				select {
				case ls = <-bnotifier.In:
					io.WriteString(w, fmt.Sprintf("data: %v\n\n", ls.(string)))
					f.Flush()
				case <-notifier:
					running = false
					log.Println("CLOSED")
					break
				case <-timer.C:
					running = false
					log.Println("TimeOUT")
				}
			} else {
				log.Println("DONE")
				break
			}
		}
	})

	m.Get("/api/utxs/:address", func(w http.ResponseWriter, params martini.Params, r *http.Request, rdb *RedisWrapper) {
		incrementClient()
		defer decrementClient()
		rpool := rdb.Pool
		running := true
		notifier := w.(http.CloseNotifier).CloseNotify()
		timer := time.NewTimer(time.Second * 3600)

		f, _ := w.(http.Flusher)
		w.Header().Set("Content-Type", "text/event-stream")
		w.Header().Set("Cache-Control", "no-cache")
		w.Header().Set("Connection", "keep-alive")

		utxs := make(chan string)
		go func(rpool *redis.Pool, utxs chan<- string) {
			conn := rpool.Get()
			defer conn.Close()
			psc := redis.PubSubConn{Conn: conn}
			psc.Subscribe(fmt.Sprintf("addr:%v:txs", params["address"]))
			for {
				switch v := psc.Receive().(type) {
				case redis.Message:
					utxs <- string(v.Data)
				}
			}
		}(rpool, utxs)

		var ls string
		for {
			if running {
				select {
				case ls = <-utxs:
					io.WriteString(w, fmt.Sprintf("data: %v\n\n", ls))
					f.Flush()
				case <-notifier:
					running = false
					log.Println("CLOSED")
					break
				case <-timer.C:
					running = false
					log.Println("TimeOUT")
				}
			} else {
				log.Println("DONE")
				break
			}
		}
	})

	m.Get("/api/utxs", func(w http.ResponseWriter, r *http.Request) {
		incrementClient()
		defer decrementClient()
		running := true
		notifier := w.(http.CloseNotifier).CloseNotify()
		timer := time.NewTimer(time.Second * 3600)

		f, _ := w.(http.Flusher)
		w.Header().Set("Content-Type", "text/event-stream")
		w.Header().Set("Cache-Control", "no-cache")
		w.Header().Set("Connection", "keep-alive")

		utx := utxgroup.Join()
		defer utx.Close()

		var ls interface{}
		for {
			if running {
				select {
				case ls = <-utx.In:
					io.WriteString(w, fmt.Sprintf("data: %v\n\n", ls.(string)))
					f.Flush()
				case <-notifier:
					running = false
					log.Println("CLOSED")
					break
				case <-timer.C:
					running = false
					log.Println("TimeOUT")
				}
			} else {
				log.Println("DONE")
				break
			}
		}
	})

	m.Get("/events", func(w http.ResponseWriter, r *http.Request) {
		running := true
		notifier := w.(http.CloseNotifier).CloseNotify()
		timer := time.NewTimer(time.Second * 8400)

		f, _ := w.(http.Flusher)
		w.Header().Set("Content-Type", "text/event-stream")
		w.Header().Set("Cache-Control", "no-cache")
		w.Header().Set("Connection", "keep-alive")

		newblockg := newblockgroup.Join()
		defer newblockg.Close()
		var ls interface{}
		for {
			if running {
				select {
				case ls = <-newblockg.In:
					io.WriteString(w, fmt.Sprintf("data: %v\n\n", ls.(string)))
					f.Flush()
				case <-notifier:
					running = false
					log.Println("CLOSED")
					break
				case <-timer.C:
					running = false
					log.Println("TimeOUT")
				}
			} else {
				log.Println("DONE")
				break
			}
		}
	})

	m.Get("/events_unconfirmed", func(w http.ResponseWriter, r *http.Request) {
		running := true
		notifier := w.(http.CloseNotifier).CloseNotify()
		timer := time.NewTimer(time.Second * 3600)

		f, _ := w.(http.Flusher)
		w.Header().Set("Content-Type", "text/event-stream")
		w.Header().Set("Cache-Control", "no-cache")
		w.Header().Set("Connection", "keep-alive")

		utx := utxgroup.Join()
		defer utx.Close()

		var ls interface{}
		for {
			if running {
				select {
				case ls = <-utx.In:
					buf := bytes.NewBufferString("")
					utx := new(btcplex.Tx)
					json.Unmarshal([]byte(ls.(string)), utx)
					t := template.New("").Funcs(appHelpers)
					utxtmpl, _ := ioutil.ReadFile(fmt.Sprintf("%v/utx.tmpl", tmpldir))
					t, err := t.Parse(string(utxtmpl))
					if err != nil {
						log.Printf("ERR:%v", err)
					}

					err = t.Execute(buf, utx)
					if err != nil {
						log.Printf("ERR EXEC:%v", err)
					}
					res := map[string]interface{}{}
					// Full unconfirmed cnt from global variables
					res["cnt"] = utxscnt
					// HTML template of the transaction
					res["tmpl"] = buf.String()
					// Last updated time
					res["time"] = time.Now().UTC().Format(time.RFC3339)
					resjson, _ := json.Marshal(res)
					io.WriteString(w, fmt.Sprintf("data: %v\n\n", string(resjson)))
					f.Flush()
				case <-notifier:
					running = false
					log.Println("CLOSED")
					break
				case <-timer.C:
					running = false
					log.Println("TimeOUT")
				}
			} else {
				log.Println("DONE")
				break
			}
		}
	})

	m.Get("/api/info", func(r render.Render) {
		activeclientsmutex.Lock()
		defer activeclientsmutex.Unlock()
		btcplexinfo, _ := btcplex.GetInfoRPC(conf)
		r.JSON(200, map[string]interface{}{"activeclients": activeclients, "info": btcplexinfo})
	})

	log.Printf("Listening on port: %v\n", conf.AppPort)
	http.ListenAndServe(fmt.Sprintf(":%v", conf.AppPort), m)
}
Пример #10
0
func main() {
	//Change secret123 to something more secure and store session in backend instead of cookie
	store := sessions.NewCookieStore([]byte("secret123"))

	dbmap = initDb()

	defer dbmap.Db.Close()

	err := dbmap.TruncateTables()
	checkErr(err, "TruncateTables failed")

	u1 := newUser("*****@*****.**", "pass", "Bob", false)

	//insert rows
	err = dbmap.Insert(&u1)
	checkErr(err, "Insert failed")

	//create two posts, assign to user 1 above
	p1 := newPost("Post 1", "Lorem ipsum lorem ipsum", 1)
	p2 := newPost("Post 2", "This is my second post", 1)

	// insert rows
	err = dbmap.Insert(&p1, &p2)
	checkErr(err, "Insert failed")

	m := martini.Classic()

	m.Use(render.Renderer(render.Options{
		Directory: "templates",
		Layout:    "layout",
		Funcs: []template.FuncMap{
			{
				"formatTime": func(args ...interface{}) string {
					t1 := time.Unix(args[0].(int64), 0)
					return t1.Format(time.Stamp)
				},
			},
		},
	}))

	m.Use(sessions.Sessions("my_session", store))
	m.Use(sessionauth.SessionUser(GenerateAnonymousUser))

	sessionauth.RedirectUrl = "/login"
	sessionauth.RedirectParam = "next"

	//ROUTES

	m.Get("/register", func(r render.Render, user sessionauth.User) {

		//redirect to homepage if already authenticated
		if user.IsAuthenticated() {
			r.Redirect("/")
		} else {
			r.HTML(200, "register", nil)
		}

	})

	m.Get("/login", func(r render.Render, user sessionauth.User) {

		//redirect to homepage if already authenticated
		if user.IsAuthenticated() {
			r.Redirect("/")
		} else {
			r.HTML(200, "login", nil)
		}
	})

	m.Post("/login", binding.Form(User{}), func(session sessions.Session, postedUser User, r render.Render, ferr binding.Errors, req *http.Request) {

		log.Println(ferr)

		//Example of server side error validation for the client side form
		if ferr.Count() > 0 {
			newmap := map[string]interface{}{"metatitle": "Registration", "errormessage": "Error with Form Submission"}
			r.HTML(200, "login", newmap)
		} else {

			user := User{}

			//check login credentails with DataBase
			err := dbmap.SelectOne(&user, "SELECT * FROM users WHERE email = ? and password = ?", postedUser.Email, postedUser.Password)
			if err != nil {
				r.Redirect(sessionauth.RedirectUrl)
				return
			} else {
				err := sessionauth.AuthenticateSession(session, &user)
				if err != nil {
					r.JSON(500, err)
				}

				params := req.URL.Query()
				redirect := params.Get(sessionauth.RedirectParam)
				r.Redirect(redirect)
				return
			}

		}

	})

	m.Get("/logout", sessionauth.LoginRequired, func(session sessions.Session, user sessionauth.User, r render.Render) {
		sessionauth.Logout(session, user)
		r.Redirect("/")
	})

	m.Get("/", func(r render.Render, authuser sessionauth.User) {

		var posts []Post
		_, err = dbmap.Select(&posts, "select * from posts order by post_id")
		checkErr(err, "Select failed")

		newmap := map[string]interface{}{"metatitle": "HomePage", "authuser": authuser, "posts": posts}
		r.HTML(200, "posts", newmap)
	})

	m.Get("/users", func(r render.Render, authuser sessionauth.User) {

		var users []User

		_, err = dbmap.Select(&users, "select * from users order by id")
		checkErr(err, "Select failed")

		newmap := map[string]interface{}{"metatitle": "Users listing", "authuser": authuser, "users": users}
		r.HTML(200, "users", newmap)

	})

	m.Get("/users/:id", sessionauth.LoginRequired, func(args martini.Params, r render.Render, authuser sessionauth.User) {

		var user User

		err = dbmap.SelectOne(&user, "select * from users where id=?", args["id"])

		//simple error check
		if err != nil {
			newmap := map[string]interface{}{"metatitle": "404 Error", "message": "User not found"}
			r.HTML(404, "error", newmap)
		} else {

			var posts []Post
			_, err = dbmap.Select(&posts, "select * from posts where UserId=?", args["id"])
			checkErr(err, "Select failed")

			newmap := map[string]interface{}{"metatitle": user.Name + " profile page", "authuser": authuser, "user": user, "posts": posts}
			r.HTML(200, "user", newmap)
		}

	})

	m.Post("/users", binding.Form(User{}), func(session sessions.Session, user User, ferr binding.Errors, r render.Render) {

		//Example of server side error validation for the client side form
		if ferr.Count() > 0 {
			fmt.Println(ferr)
			newmap := map[string]interface{}{"metatitle": "Registration", "errormessage": "Error with Form Submission"}
			r.HTML(200, "register", newmap)
		} else {

			u := newUser(user.Email, user.Password, user.Name, user.authenticated)

			err = dbmap.Insert(&u)
			checkErr(err, "Insert failed")

			//create the session and redirect always to homepage
			err := sessionauth.AuthenticateSession(session, &u)
			if err != nil {
				r.JSON(500, err)
			}

			r.Redirect("/")
		}

	})

	m.Put("/users/:id", binding.Bind(User{}), func(args martini.Params, user User, r render.Render, authuser sessionauth.User) {

		//convert string to int64 so you can match the struct (passing userid via ajax does not work as it comes in as a string)
		f, _ := strconv.ParseInt(args["id"], 0, 64)

		//only allow the authenticated user to update his user attributes
		if authuser.UniqueId() == f {

			//specify the user id
			user.Id = f

			count, err := dbmap.Update(&user)
			checkErr(err, "Update failed")
			log.Println("Rows updated:", count)

			if count == 1 {
				newmap := map[string]interface{}{"responseText": "success"}
				r.JSON(200, newmap)
			} else {
				newmap := map[string]interface{}{"responseText": "error"}
				r.JSON(400, newmap)
			}

		} else {
			newmap := map[string]interface{}{"responseText": "You are not allowed to update this resource."}
			r.JSON(403, newmap)
		}

	})

	m.Delete("/users/:id", func(args martini.Params, r render.Render, authuser sessionauth.User) {

		//convert id from string to int64
		f, _ := strconv.ParseInt(args["id"], 0, 64)

		//only allow the authenticated user to delete him or her
		if authuser.UniqueId() == f {

			_, err = dbmap.Exec("delete from users where id=?", args["id"])
			checkErr(err, "Delete failed")

			if err == nil {
				newmap := map[string]interface{}{"responseText": "success"}
				r.JSON(200, newmap)
				//if you delete yourself, Ajax should redirec you
			} else {
				newmap := map[string]interface{}{"responseText": "error"}
				r.JSON(400, newmap)
			}

		} else {
			newmap := map[string]interface{}{"responseText": "You are not allowed to delete this resource."}
			r.JSON(403, newmap)
		}

	})

	m.Post("/posts", sessionauth.LoginRequired, binding.Bind(Post{}), func(post Post, r render.Render, authuser sessionauth.User) {

		//convert to int64
		f := authuser.UniqueId().(int64)
		p1 := newPost(post.Title, post.Body, f)

		err = dbmap.Insert(&p1)
		checkErr(err, "Insert failed")

		r.Redirect("/")
	})

	m.Get("/posts/:id", func(args martini.Params, r render.Render, authuser sessionauth.User) {

		var post Post

		err = dbmap.SelectOne(&post, "select * from posts where post_id=?", args["id"])

		//simple error check
		if err != nil {
			newmap := map[string]interface{}{"metatitle": "404 Error", "message": "This is not found"}
			r.HTML(404, "error", newmap)
		} else {
			newmap := map[string]interface{}{"metatitle": post.Title + " more custom", "authuser": authuser, "post": post}
			r.HTML(200, "post", newmap)
		}
	})

	m.Get("/p/:str", func(args martini.Params, r render.Render, authuser sessionauth.User) {

		var post Post

		err = dbmap.SelectOne(&post, "select * from posts where url=?", args["str"])

		//simple error check
		if err != nil {
			newmap := map[string]interface{}{"metatitle": "404 Error", "message": "This is not found"}
			r.HTML(404, "error", newmap)
		} else {
			newmap := map[string]interface{}{"metatitle": post.Title + " more custom", "authuser": authuser, "post": post}
			r.HTML(200, "post", newmap)
		}
	})

	m.Put("/posts/:id", binding.Bind(Post{}), func(args martini.Params, post Post, r render.Render, authuser sessionauth.User) {

		var newTitle = post.Title
		var newBody = post.Body

		err = dbmap.SelectOne(&post, "select * from posts where post_id=?", args["id"])

		//simple database error check
		if err != nil {
			newmap := map[string]interface{}{"message": "Something went wrong."}
			r.JSON(400, newmap)
		} else {

			//owner check
			if authuser.UniqueId() == post.UserId {

				post.Title = newTitle
				post.Body = newBody

				count, err := dbmap.Update(&post)
				checkErr(err, "Update failed")

				if count == 1 {
					newmap := map[string]interface{}{"responseText": "success"}
					r.JSON(200, newmap)
				} else {
					newmap := map[string]interface{}{"responseText": "error"}
					r.JSON(400, newmap)
				}

			} else {
				newmap := map[string]interface{}{"responseText": "You are not allowed to modify this resource."}
				r.JSON(403, newmap)
			}

		}

	})

	m.Delete("/posts/:id", func(args martini.Params, r render.Render, authuser sessionauth.User) {

		//retrieve the post to check the real owner
		var post Post
		err = dbmap.SelectOne(&post, "select * from posts where post_id=?", args["id"])

		//simple DB error check
		if err != nil {
			newmap := map[string]interface{}{"message": "Something went wrong."}
			r.JSON(400, newmap)
		} else {

			//owner check
			if authuser.UniqueId() == post.UserId {

				//delete it
				_, err := dbmap.Delete(&post)
				checkErr(err, "Delete failed")

				newmap := map[string]interface{}{"responseText": "success"}
				r.JSON(200, newmap)

			} else {
				newmap := map[string]interface{}{"responseText": "You are not allowed to delete this resource."}
				r.JSON(403, newmap)
			}

		}

	})

	m.Run()
}
Пример #11
0
func main() {
	// Read the configuration file
	file, _ := os.Open("conf/app.json")
	decoder := json.NewDecoder(file)
	configuration := &Configuration{}
	decoder.Decode(&configuration)

	// Initialize background processing
	workers.Configure(map[string]string{
		// Location of the redis instance.
		"server": configuration.RedisURI,

		// The number of connections to keep open with Redis.
		"pool": configuration.RedisConn,

		// Unique process id for this instance of workers; helps with proper
		// recovery of inprogress jobs on a crash.
		"process": "1",
	})

	m := martini.Classic()
	m.Use(gzip.All())
	m.Use(render.Renderer())
	m.Use(martini.Static("assets"))
	m.Use(DB())

	m.Get("/", func(r render.Render) {
		r.HTML(200, "welcome", nil)
	})

	m.Post("/join", binding.Form(Account{}), func(account Account, r render.Render, db *mgo.Database) {
		u, err := uuid.NewV4()
		if err != nil {
			panic(err)
		}
		token := strings.Replace(u.String(), "-", "", -1)
		reflect.ValueOf(&account).Elem().FieldByName("EmailValidationToken").SetString(token)
		db.C("accounts").Insert(account)

		// Send the activation email

		r.HTML(200, "join_success", nil)
	})

	m.Get("/accounts/activate/:token", func(r render.Render) {
		r.HTML(200, "registration", nil)
	})

	/*
	  m.Post("/accounts/new", binding.Form(Account{}), func(account Account, r render.Render, db *mgo.Database) {
	    colQuerier := bson.M{"email": ""}
	    change := bson.M{"$set": bson.M{}}
	    err = db.C("accounts").Update(colQuerier, change)
	    if err != nil {
	      log.Fatal(err)
	    }
	  })*/

	// Handle 404.
	m.NotFound(func(r render.Render) {
		r.HTML(404, "notfound", nil)
	})

	s := &http.Server{
		Addr:           ":8080",
		Handler:        m,
		ReadTimeout:    10 * time.Second,
		WriteTimeout:   10 * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	log.Fatal(s.ListenAndServe())
}
Пример #12
0
func main() {
	m := martini.Classic()

	store := sessions.NewCookieStore([]byte("battle_answers"))
	m.Use(sessions.Sessions("my_battle_answers_session", store))

	m.Use(DB())

	m.Use(render.Renderer(render.Options{
		Directory: "templates",
		Layout:    "layout",
		Funcs: []template.FuncMap{
			{
				"addInClass": func(args ...interface{}) string {
					var i int
					var className string

					i = args[0].(int)

					if i == 0 {
						className = " in"
					} else {
						className = ""
					}

					return className
				},
				"addSelected": func(args ...interface{}) string {
					var lastGameIdSearched string
					selectedString := ""

					lastGameIdSearched = args[1].(string)

					if args[0] == bson.ObjectIdHex(lastGameIdSearched) {
						selectedString = "selected"
					}

					return selectedString
				},
				"addActiveClass": func(args ...interface{}) string {
					className := ""

					for _, path := range args[1:] {
						if path == args[0] {
							className = "active"
							break
						}
					}

					return className
				},
			},
		},
	}))

	m.Get("/", func(r render.Render, db *mgo.Database, req *http.Request) {
		templateData := map[string]interface{}{"metatitle": "Battle Answers", "currentPath": req.URL.Path}
		r.HTML(200, "index", templateData)
	})

	m.Get("/games", controllers.GamesIndex)
	m.Get("/games/new", controllers.GamesNew)
	m.Post("/games", binding.Form(controllers.GameForm{}), controllers.GamesCreate)

	m.Get("/battle_answers", controllers.BattleAnswersIndex)
	m.Get("/battle_answers/new", controllers.BattleAnswersNew)
	m.Post("/battle_answers", binding.Form(controllers.BattleAnswerForm{}), controllers.BattleAnswersCreate)

	m.Get("/search_answers", controllers.SearchAnswersIndex)
	m.Get("/search_answers/new", controllers.SearchAnswersNew)
	m.Post("/search_answers", binding.Form(controllers.SearchAnswerForm{}), controllers.SearchAnswersCreate)

	m.Run()
}