Esempio n. 1
0
func main() {
	// Create a DB with the test table and a seed widget
	os.Remove("./grapi-example.db")
	db, _ := gorm.Open("sqlite3", "./grapi-example.db")
	db.CreateTable(&Widget{})
	db.Create(&Widget{Name: "Test Widget"})

	// Initialise grapi
	api := grapi.New(grapi.Options{Db: db.Debug()})
	http.Handle("/api/", api)

	// Add index, get, post, patch and delete routes for widget
	api.AddDefaultRoutes(&Widget{})

	// Start Server
	log.Fatal(http.ListenAndServe("127.0.0.1:3000", nil))
}
Esempio n. 2
0
func main() {
	// Create a DB with the test table and seed data
	db, _ := gorm.Open("sqlite3", "./grapi-example.db")
	seedDb(&db)

	// Create an API server. We need to supply JwtKey if we're doing authentication.
	// We pass db.Debug() instead of &db so you can see the sql queries in the log.
	a := grapi.New(grapi.Options{Db: db.Debug(), JwtKey: "SomethingLongAndDifficultToGuess"})
	http.Handle("/api/", a)
	http.HandleFunc("/", indexHandler)

	// Allow logging in with the User model at /api/login. Details will be checked by User.CheckLoginDetails()
	a.SetAuth(&User{}, "login")

	// Setup some useful RouteOptions that we will use for adding authenticated routs.

	// This one allows only authenticated users (ie. they've logged in at "/login" above).
	onlyAuthenticated := grapi.RouteOptions{UseDefaultAuth: true}

	// Only Allow Admin
	onlyAdmin := grapi.RouteOptions{
		UseDefaultAuth: true,
		// Add an authorize callback. This is a Martini handler, and can access the LoginModel
		// used for authentication. As we called API.SetAuth with &User{} this is guaranteed to
		// be a *User, so we can do a type assertion.
		Authorize: func(req grapi.ReqToAuthorize) bool {
			user := req.GetLoginObject().(*User)
			if !user.Admin {
				http.Error(req.GetResponseWriter(), `{"error":"You need to be admin to do that"}`, 403)
				return false
			}
			return true
		}}

	// This RouteOptions can be used for any table with a user_id field. If logged in as admin
	// it allows anything. If logged in as user it limits GETs to those of own user_id, and
	// delete to own user_id. It also prevents changing user ownership.
	onlyOwnUnlessAdmin := grapi.RouteOptions{
		UseDefaultAuth: true,
		Query: func(req grapi.ReqToLimit) bool {
			user := req.GetLoginObject().(*User)
			// Scope the requests database to only contain owned items. This prevents unauthorized
			// GET, DELETE, and PATCH requests, and limits the index to own items.
			if !user.Admin {
				req.SetDB(req.GetDB().Where("user_id = ?", user.ID))
			}
			return true
		},
		CheckUpload: func(req grapi.ReqULToCheck) bool {
			user := req.GetLoginObject().(*User)
			uploaded := req.GetUpload().(BelongsToUser)
			// For PATCH and POST routes we also need to check that the uploaded object has the correct user_id
			if !user.Admin && user.ID != uploaded.UserId() {
				http.Error(req.GetResponseWriter(), `{"error":"Only admin can change a user_id"}`, 403)
				return false
			}
			return true
		}}

	// Add the Default REST routes for User.
	// If two RouteOptions structures are provided the first is used for Read routes,
	// and the second for Write routes. If three are given then the third is used for
	// DELETE requests.
	a.AddDefaultRoutes(&User{}, onlyAuthenticated, onlyAdmin)

	// We want people to only see their own widgets, unless they are admin.
	a.AddDefaultRoutes(&PrivateWidget{}, onlyOwnUnlessAdmin)

	// We are going to make the widget list available to view by user at
	// /api/user/:user_id/private_widgets
	a.AddIndexRoute(&PrivateWidget{},
		&grapi.RouteOptions{
			Prefix: "/user/:user_id",
			Query: func(req grapi.ReqToLimit) bool {
				req.SetDB(req.GetDB().Where("user_id = ?", req.Param("user_id")))
				return true
			}})

	// Run the server.
	listener, err := net.Listen("tcp", "127.0.0.1:3000")
	if err != nil {
		panic(err.Error())
	}
	err = graceful.Serve(listener, http.DefaultServeMux)
	if err != nil {
		panic(err.Error())
	}

	graceful.Wait()
}