// ApiFindOne verifies the session and returns user and profile in meta if valid. func (SessionResourceHooks) ApiFindOne(res kit.Resource, rawId string, r kit.Request) kit.Response { if rawId == "" { return kit.NewErrorResponse("empty_token", "Empty token") } userService := res.Registry().UserService() user, session, err := userService.VerifySession(rawId) if err != nil { return kit.NewErrorResponse(err) } meta := make(map[string]interface{}) if user != nil { userData, err := res.Backend().ModelToMap(user, true, false) if err != nil { return kit.NewErrorResponse("marshal_error", err) } meta["user"] = userData if user.GetProfile() != nil { profileData, err := res.Backend().ModelToMap(user.GetProfile(), true, false) if err != nil { return kit.NewErrorResponse("marshal_error", err) } meta["profile"] = profileData } } return &kit.AppResponse{ Data: session, Meta: meta, } }
func (_ FilesResource) ApiCreate(res kit.Resource, obj kit.Model, r kit.Request) kit.Response { // Verify that tmp path is set either in metadata or on model. file := obj.(kit.File) if file.GetTmpPath() == "" { file.SetTmpPath(r.GetMeta().String("file")) } filePath := file.GetTmpPath() if filePath == "" { return kit.NewErrorResponse("no_tmp_path", "A tmp path must be set when creating a file", true) } tmpPath := getTmpPath(res) if !strings.HasPrefix(filePath, tmpPath) && filePath[0] != '/' { filePath = tmpPath + string(os.PathSeparator) + filePath file.SetTmpPath(filePath) } // Build the file, save it to backend and persist it to the db. err := res.Registry().FileService().BuildFile(file, r.GetUser(), true, true) if err != nil { kit.NewErrorResponse(err) } return &kit.AppResponse{ Data: file, } }
func HandleFind(registry kit.Registry, request kit.Request) (kit.Response, bool) { collection := request.GetContext().MustString("collection") res := registry.Resource(collection) if res == nil || !res.IsPublic() { err := &apperror.Err{ Code: "unknown_resource", Message: fmt.Sprintf("The resource '%v' does not exist", collection), } return kit.NewErrorResponse(err), false } response, err := Find(res, request) if err != nil { response = kit.NewErrorResponse(err) } // If response contains a count and the request a "perPage" param, add a total_pages param // to meta. perPage, err2 := request.GetContext().Int("per_page") meta := response.GetMeta() if meta != nil && err2 == nil { count, ok := meta["count"] if ok { meta["total_pages"] = math.Ceil(float64(count.(int)) / float64(perPage)) } } return response, false }
func (SessionResourceHooks) ApiDelete(res kit.Resource, id string, r kit.Request) kit.Response { if id != r.GetSession().GetStrId() { return kit.NewErrorResponse("permission_denied", "Permission denied", 403) } if err := res.Backend().Delete(r.GetSession()); err != nil { return kit.NewErrorResponse("db_delete_error", err, true) } return &kit.AppResponse{} }
func AuthenticationMiddleware(registry kit.Registry, r kit.Request) (kit.Response, bool) { // Handle authentication. httpRequest := r.GetHttpRequest() userService := registry.UserService() if userService == nil { return nil, false } authHeader := httpRequest.Header.Get("Authentication") if authHeader == "" { return nil, false } // Check for basic auth. if strings.HasPrefix(authHeader, "Basic ") { str := authHeader[6:] data, err := base64.StdEncoding.DecodeString(str) if err != nil { return kit.NewErrorResponse("invalid_basic_auth"), false } else { parts := strings.Split(string(data), ":") if len(parts) == 2 { userIdentifier := parts[0] pw := parts[1] user, err := userService.AuthenticateUser(userIdentifier, "password", map[string]interface{}{"password": pw}) if err != nil { return kit.NewErrorResponse(err), false } r.SetUser(user) return nil, false } } } // Check for auth token. if authHeader != "" { token := authHeader user, session, err := userService.VerifySession(token) if err == nil { r.SetUser(user) r.SetSession(session) return nil, false } else { return kit.NewErrorResponse(err), false } } return nil, false }
func (hooks UserResourceHooks) ApiCreate(res kit.Resource, obj kit.Model, r kit.Request) kit.Response { meta := r.GetMeta() adaptor := meta.String("adaptor") if adaptor == "" { return kit.NewErrorResponse("adaptor_missing", "Expected 'adaptor' in metadata.", true) } rawData, ok := meta.Get("authData") if !ok { return kit.NewErrorResponse("auth_data_missing", "Expected 'authData' in metadata.", true) } data, ok := rawData.(map[string]interface{}) if !ok { return kit.NewErrorResponse("invalid_auth_data", "Invalid auth data: expected dictionary", true) } user := obj.(kit.User) service := res.Registry().UserService() // If a profile model was registered, and profile data is in meta, // create the profile model. if profiles := service.ProfileResource(); profiles != nil { profile := profiles.CreateModel().(kit.UserProfile) if rawData, ok := meta.Get("profile"); ok { if data, ok := rawData.(map[string]interface{}); ok { // Profile data present in meta. // Update profile with data. if err := res.ModelInfo().UpdateModelFromData(profile, data); err != nil { return kit.NewErrorResponse("invalid_profile_data", "Invalid profile data.", err, true) } } } user.SetProfile(profile) } if err := service.CreateUser(user, adaptor, data); err != nil { return kit.NewErrorResponse(err) } return &kit.AppResponse{ Data: user, } }
func SerializeResponseMiddleware(registry kit.Registry, request kit.Request, response kit.Response) (kit.Response, bool) { // Try to serialize the reponse data. // Determine serializer. serializer := registry.DefaultSerializer() // Check if a custom serializer was specified. if name := request.GetContext().String("response-serializer"); name != "" { serializer = registry.Serializer(name) if serializer == nil { errResp := kit.NewErrorResponse("unknown_response_serializer", true) data, _ := serializer.MustSerializeResponse(errResp) errResp.SetData(data) return errResp, false } } // Set format in metadata. meta := response.GetMeta() if meta == nil { meta = make(map[string]interface{}) } meta["format"] = serializer.Name() response.SetMeta(meta) data, err := serializer.MustSerializeResponse(response) if err != nil { registry.Logger().Errorf("Response serialization error: %v (%+v)", err, response) } response.SetData(data) return nil, false }
func notFoundHandler(registry kit.Registry, r kit.Request) (kit.Response, bool) { httpRequest := r.GetHttpRequest() apiPrefix := "/" + registry.Config().UString("api.prefix", "api") isApiRequest := strings.HasPrefix(httpRequest.URL.Path, apiPrefix) // Try to render the page on the server, if enabled. if !isApiRequest { renderEnabled := registry.Config().UBool("serverRenderer.enabled", false) noRender := strings.Contains(httpRequest.URL.String(), "no-server-render") if renderEnabled && !noRender { return serverRenderer(registry, r), false } } // For non-api requests, render the default template. if !isApiRequest { tpl, err := getIndexTpl(registry) if err != nil { return kit.NewErrorResponse(err), false } return &kit.AppResponse{ RawData: tpl, }, false } // For api requests, render the api not found error. return &kit.AppResponse{ Error: &apperror.Err{ Code: "not_found", Message: "This api route does not exist", }, }, false }
func HandleUpdate(registry kit.Registry, request kit.Request) (kit.Response, bool) { response, err := Update(registry, request) if err != nil { return kit.NewErrorResponse(err), false } return response, false }
func UnserializeRequestMiddleware(registry kit.Registry, request kit.Request) (kit.Response, bool) { // Try to parse json in body. Ignore error since body might not contain json. contentType := request.GetHttpRequest().Header.Get("Content-Type") if strings.Contains(contentType, "json") { // Only read the HTTP body automatically for json content type requests, // since some handlers might need to read it themselfes (see the files package resource). if err := request.ReadHttpBody(); err != nil { return kit.NewErrorResponse(err, "http_body_read_error"), false } else { if request.GetRawData() != nil { if err := request.ParseJsonData(); err != nil { return kit.NewErrorResponse(err, "invalid_json_body", true), false } if request.GetData() != nil { // Successfully parsed json body. // Now try to unserialize. // Determine serializer. serializer := registry.DefaultSerializer() // Check if a custom serializer was specified. if name := request.GetContext().String("request-serializer"); name != "" { serializer = registry.Serializer(name) } if serializer == nil { return kit.NewErrorResponse("unknown_serializer", fmt.Sprintf("The specified request serializer does not exist")), false } else { if err := request.Unserialize(serializer); err != nil { return kit.NewErrorResponse(err, "request_unserialize_error", true), false } } } } } } return nil, false }
func (PageResource) Methods(res kit.Resource) []kit.Method { publish := &methods.Method{ Name: "cms.page.publish", Blocking: true, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { user := r.GetUser() if user == nil || !user.HasRole("admin") { return kit.NewErrorResponse("permission_denied") } id := utils.GetMapStringKey(r.GetData(), "id") if id == "" { return kit.NewErrorResponse("no_id_in_data", "Expected 'id' key in data.") } rawPage, err := res.Backend().FindOne("pages", id) if err != nil { return kit.NewErrorResponse("db_error", err) } else if rawPage == nil { return kit.NewErrorResponse("not_found", "The specified page id does not exist.") } err = res.ModelInfo().UpdateModelFromData(rawPage, map[string]interface{}{ "published": true, "published_at": time.Now(), }) if err != nil { return kit.NewErrorResponse("db_error", err) } return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } return []kit.Method{publish} }
func HandleDelete(registry kit.Registry, request kit.Request) (kit.Response, bool) { collection := request.GetContext().MustString("collection") id := request.GetContext().MustString("id") res := registry.Resource(collection) if res == nil || !res.IsPublic() { resp := kit.NewErrorResponse("unknown_resource", fmt.Sprintf("The resource '%v' does not exist", collection)) return resp, false } return res.ApiDelete(id, request), false }
func (res *Resource) ApiDelete(id string, r kit.Request) kit.Response { if deleteHook, ok := res.hooks.(ApiDeleteHook); ok { return deleteHook.ApiDelete(res, id, r) } oldObj, err := res.FindOne(id) if err != nil { return kit.NewErrorResponse(err) } else if oldObj == nil { return kit.NewErrorResponse("not_found", "") } user := r.GetUser() if err := res.Delete(oldObj, user); err != nil { return kit.NewErrorResponse(err) } return &kit.AppResponse{ Data: oldObj, } }
// Creating a session is equivalent to logging in. func (hooks SessionResourceHooks) ApiCreate(res kit.Resource, obj kit.Model, r kit.Request) kit.Response { userService := res.Registry().UserService() meta := r.GetMeta() isAnonymous, _ := meta.Bool("anonymous") // Find user. userIdentifier := meta.String("user") adaptor := meta.String("adaptor") data, _ := meta.Map("authData") var user kit.User if !isAnonymous { if adaptor == "" { return kit.NewErrorResponse("adaptor_missing", "Expected 'adaptor' in metadata.", true) } if data == nil { kit.NewErrorResponse("no_or_invalid_auth_data", "Expected 'authData' dictionary in metadata.") } var err apperror.Error user, err = userService.AuthenticateUser(userIdentifier, adaptor, data) if err != nil { return kit.NewErrorResponse(err) } } session, err := userService.StartSession(user, r.GetFrontend()) if err != nil { return kit.NewErrorResponse(err) } responseMeta := make(map[string]interface{}) if !isAnonymous { userData, err := res.Backend().ModelToMap(user, true, false) if err != nil { return kit.NewErrorResponse("marshal_error", err) } responseMeta["user"] = userData if user.GetProfile() != nil { profileData, err := res.Backend().ModelToMap(user.GetProfile(), true, false) if err != nil { return kit.NewErrorResponse("marshal_error", err) } responseMeta["profile"] = profileData } } return &kit.AppResponse{ Data: session, Meta: responseMeta, } }
func UnserializerMiddleware(registry kit.Registry, request kit.Request) (kit.Response, bool) { serializer := registry.DefaultSerializer() // Try to find custom serializer. data, ok := request.GetData().(map[string]interface{}) if ok { name, ok := data["request_serializer"].(string) if ok { s := registry.Serializer(name) if s == nil { resp := kit.NewErrorResponse("unknown_request_serializer", fmt.Sprintf("The given request serializer %v does not exist", name)) return resp, false } else { serializer = s } } } if err := serializer.UnserializeRequest(request.GetData(), request); err != nil { return kit.NewErrorResponse(err), false } return nil, false }
func (res *Resource) ApiFindOne(rawId string, r kit.Request) kit.Response { hook, ok := res.hooks.(ApiFindOneHook) if ok { return hook.ApiFindOne(res, rawId, r) } result, err := res.FindOne(rawId) if err != nil { return kit.NewErrorResponse(err) } else if result == nil { return kit.NewErrorResponse("not_found", "") } user := r.GetUser() if allowFind, ok := res.hooks.(AllowFindHook); ok { if !allowFind.AllowFind(res, result, user) { return kit.NewErrorResponse("permission_denied", "") } } return &kit.AppResponse{ Data: result, } }
func (res *Resource) ApiPartialUpdate(obj kit.Model, r kit.Request) kit.Response { if updateHook, ok := res.hooks.(ApiUpdateHook); ok { return updateHook.ApiUpdate(res, obj, r) } user := r.GetUser() err := res.PartialUpdate(obj, user) if err != nil { return kit.NewErrorResponse(err) } return &kit.AppResponse{ Data: obj, } }
} type ResourceMethodData struct { Resource kit.Resource Objects []kit.Model Ids []string Query db.Query } var createMethod kit.Method = &Method{ Name: "create", Blocking: true, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { models := r.GetTransferData().GetModels() if len(models) == 0 { return kit.NewErrorResponse("no_model", "No model was found in the request.") } else if len(models) > 1 { return kit.NewErrorResponse("multiple_models", "Request contained more than one model.") } res := registry.Resource(models[0].Collection()) if res == nil || !res.IsPublic() { return kit.NewErrorResponse("unknown_collection", fmt.Sprintf("The collection %v does not exist", models[0].Collection())) } return res.ApiCreate(models[0], r) }, } var updateMethod kit.Method = &Method{ Name: "update",
func (UserResourceHooks) Methods(res kit.Resource) []kit.Method { sendConfirmationEmail := &methods.Method{ Name: "users.send-confirmation-email", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { user := r.GetUser() if user == nil { return kit.NewErrorResponse("not_authenticated", "") } if user.IsEmailConfirmed() { return kit.NewErrorResponse("email_already_confirmed", "The users email address is already confirmed") } err := registry.UserService().SendConfirmationEmail(user) if err != nil { return kit.NewErrorResponse("confirm_failed", "Could not confirm email") } return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } confirmEmail := &methods.Method{ Name: "users.confirm-email", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { data, ok := r.GetData().(map[string]interface{}) if !ok { return kit.NewErrorResponse("invalid_data", "Expected data dict with 'token' key") } token, ok := data["token"].(string) if !ok { return kit.NewErrorResponse("invalid_data", "Expected 'token' string key in data") } if token == "" { return kit.NewErrorResponse("empty_token", "") } _, err := registry.UserService().ConfirmEmail(token) if err != nil { return kit.NewErrorResponse("confirm_failed", "Could not confirm email") } return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } requestPwReset := &methods.Method{ Name: "users.request-password-reset", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { data, ok := r.GetData().(map[string]interface{}) if !ok { return kit.NewErrorResponse("invalid_data", "Expected data dict with 'user' key", true) } userIdentifier, ok := data["user"].(string) if !ok { return kit.NewErrorResponse("invalid_data", "Expected data dict with 'user' string key", true) } rawUser, err := res.Q().Filter("email", userIdentifier).Or("username", userIdentifier).First() if err != nil { return kit.NewErrorResponse(err) } if rawUser == nil { return kit.NewErrorResponse("unknown_user", fmt.Sprintf("The user %v does not exist", userIdentifier), true) } user := rawUser.(kit.User) err = registry.UserService().SendPasswordResetEmail(user) if err != nil { registry.Logger().Errorf("Could not send password reset email for user %v: %v", user, err) return kit.NewErrorResponse("reset_email_send_failed", "Could not send the reset password mail.", true) } return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } pwReset := &methods.Method{ Name: "users.password-reset", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { // Verify that token is in data. data, ok := r.GetData().(map[string]interface{}) if !ok { return kit.NewErrorResponse("invalid_data", "Expected 'token' key in data", true) } token, ok := data["token"].(string) if !ok { return kit.NewErrorResponse("invalid_data", "Expected 'token' string key in data", true) } if token == "" { return kit.NewErrorResponse("empty_token", "", true) } // Verify that password is in data. newPw, ok := data["password"].(string) if !ok { return kit.NewErrorResponse("invalid_passord", "Expected 'password' string key in data", true) } if newPw == "" { return kit.NewErrorResponse("empty_password", "Password may not be empty", true) } user, err := registry.UserService().ResetPassword(token, newPw) if err != nil { if err.IsPublic() { return kit.NewErrorResponse(err) } else { return kit.NewErrorResponse("password_reset_failed", "Could not reset the password.", true) } } return &kit.AppResponse{ Data: map[string]interface{}{ "success": true, "userId": user.GetId(), "userEmail": user.GetEmail(), }, } }, } changePassword := &methods.Method{ Name: "users.change-password", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { // Get userId and password from request. userId := utils.GetMapStringKey(r.GetData(), "userId") if userId == "" { return kit.NewErrorResponse("no_userid", "Expected userId key in data", true) } password := utils.GetMapStringKey(r.GetData(), "password") if password == "" { return kit.NewErrorResponse("no_password", "Expected password key in data", true) } // Permission check. user := r.GetUser() if user == nil { return kit.NewErrorResponse("permission_denied", true) } // Users can only change their own password, unless they are admins. if userId != user.GetStrId() { if !(user.HasRole("admin") || user.HasPermission("users.change_passwords")) { return kit.NewErrorResponse("permission_denied", true) } } // User has the right permissions. userService := registry.UserService() // Find the user. rawUser, err := userService.UserResource().FindOne(userId) if err != nil { return kit.NewErrorResponse("db_error", true, err) } if rawUser == nil { return kit.NewErrorResponse("user_does_not_exist", true) } targetUser := rawUser.(kit.User) if err := userService.ChangePassword(targetUser, password); err != nil { return kit.NewErrorResponse(err) } // Everything worked fine. return &kit.AppResponse{ Data: map[string]interface{}{"success": true}, } }, } return []kit.Method{ AuthenticateMethod, ResumeSessionMethod, UnAuthenticateMethod, sendConfirmationEmail, confirmEmail, requestPwReset, pwReset, changePassword, } }
package tasks import ( kit "github.com/app-kit/go-appkit" "github.com/app-kit/go-appkit/app/methods" ) var RetryTaskMethod = &methods.Method{ Name: "task.retry", Blocking: false, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { user := r.GetUser() if user == nil { return kit.NewErrorResponse("not_authenticated", true) } taskId := r.GetData() if taskId == nil { return kit.NewErrorResponse("invalid_task_id", "Expected 'data' to be the task Id.", true) } backend := registry.DefaultBackend() rawTask, err := backend.FindOne("tasks", taskId) if err != nil { return kit.NewErrorResponse(err) } else if rawTask == nil { return kit.NewErrorResponse("not_found", "Task does not exist.") } task := rawTask.(kit.Task)
func (f *Frontend) registerMethod(method kit.Method) { f.client.Register(method.GetName(), func(args []interface{}, kwargs map[string]interface{}, details map[string]interface{}) (result *turnpike.CallResult) { methodName := method.GetName() fmt.Printf("WAMP method %v |\n data: %v |\n details: %v\n", methodName, kwargs, details) request := kit.NewRequest() request.SetFrontend("wamp") request.SetPath("/method/" + methodName) request.SetData(kwargs) var response kit.Response // Find session. sessionId := uint(details["session_id"].(turnpike.ID)) session := f.sessions[sessionId] if session == nil { s, err := f.registry.UserService().StartSession(nil, "wamp") if err != nil { response = kit.NewErrorResponse(err) } else { f.sessions[sessionId] = s session = s } } request.SetSession(session) if session.GetUser() != nil { request.SetUser(session.GetUser()) } // Run before middlewares. for _, middleware := range f.beforeMiddlewares { resp, skip := middleware(f.registry, request) if skip { panic("WAMP frontend middlewares do not support skipping.") } else if resp != nil { response = resp break } } // Run the method. if response == nil { responder := func(r kit.Response) { response = r } finishedChannel, err := f.registry.App().RunMethod(methodName, request, responder, true) if err != nil { response = kit.NewErrorResponse(err) } else { <-finishedChannel } } // Run after middlewares. for _, middleware := range f.afterMiddlewares { resp, skip := middleware(f.registry, request, response) if skip { panic("WAMP frontend middlewares do not support skipping.") } if resp != nil { response = resp } } return &turnpike.CallResult{Kwargs: response.GetData().(map[string]interface{})} }, nil) }
func (hooks FilesResource) HttpRoutes(res kit.Resource) []kit.HttpRoute { maxRunning := res.Registry().Config().UInt("files.thumbGenerator.maxRunning", 10) maxPerIPPerMinute := res.Registry().Config().UInt("files.thumbGenerator.maxPerIPPerMinute", 100) maxQueueSize := res.Registry().Config().UInt("files.thumbGenerator.maxQueueSize", 100) hooks.thumbnailRateLimiter = newRateLimiter(maxRunning, maxPerIPPerMinute, maxQueueSize) routes := make([]kit.HttpRoute, 0) // Upload route. uploadOptionsHandler := func(registry kit.Registry, r kit.Request) (kit.Response, bool) { header := r.GetHttpResponseWriter().Header() allowedOrigins := registry.Config().UString("fileHandler.allowedOrigins", "*") header.Set("Access-Control-Allow-Origin", allowedOrigins) header.Set("Access-Control-Allow-Methods", "OPTIONS, POST") allowedHeaders := registry.Config().UString("accessControl.allowedHeaders") if allowedHeaders == "" { allowedHeaders = "Authentication, Content-Type, Content-Range, Content-Disposition" } else { allowedHeaders += ", Authentication, Content-Type, Content-Range, Content-Disposition" } header.Set("Access-Control-Allow-Headers", allowedHeaders) return &kit.AppResponse{ HttpStatus: 200, RawData: []byte{}, }, true } uploadOptionsRoute := kit.NewHttpRoute("/api/file-upload", "OPTIONS", uploadOptionsHandler) routes = append(routes, uploadOptionsRoute) tmpPath := getTmpPath(res) if tmpPath == "" { panic("Empty tmp path") } uploadHandler := func(registry kit.Registry, r kit.Request) (kit.Response, bool) { if registry.Config().UBool("fileHandler.requiresAuth", false) { if r.GetUser() == nil { return kit.NewErrorResponse("permission_denied", ""), false } } var files []string var err apperror.Error if err == nil { files, err = handleUpload(registry, tmpPath, r.GetHttpRequest()) if err != nil { return kit.NewErrorResponse(err), false } } data := map[string]interface{}{ "data": files, } return &kit.AppResponse{Data: data}, false } uploadRoute := kit.NewHttpRoute("/api/file-upload", "POST", uploadHandler) routes = append(routes, uploadRoute) serveFileHandler := func(registry kit.Registry, r kit.Request) (kit.Response, bool) { file, err := registry.FileService().FindOne(r.GetContext().String("id")) if err != nil { return kit.NewErrorResponse(err), false } if file == nil { return &kit.AppResponse{ HttpStatus: 404, RawData: []byte("File not found"), }, false } reader, err := file.Reader() if err != nil { return kit.NewErrorResponse(err), false } defer reader.Close() w := r.GetHttpResponseWriter() err = serveFile(w, r.GetHttpRequest(), file.GetMime(), file.GetSize(), reader) reader.Close() if err != nil { registry.Logger().Errorf("Error while serving file %v(%v): %v", file.GetId(), file.GetBackendId(), err) } return nil, true } serveFileRoute := kit.NewHttpRoute("/files/:id/*rest", "GET", serveFileHandler) routes = append(routes, serveFileRoute) serveImageHandler := func(registry kit.Registry, r kit.Request) (kit.Response, bool) { file, err := registry.FileService().FindOne(r.GetContext().String("id")) if err != nil { return kit.NewErrorResponse(err), false } if file == nil { return &kit.AppResponse{ HttpStatus: 404, RawData: []byte("File not found"), }, false } if !file.GetIsImage() { return &kit.AppResponse{ Error: &apperror.Err{ Code: "file_is_no_image", Message: "The requested file is not an image", }, }, false } httpRequest := r.GetHttpRequest() query := httpRequest.URL.Query() rawWidth := query.Get("width") rawHeight := query.Get("height") var width, height int64 if rawWidth != "" { width, _ = strconv.ParseInt(rawWidth, 10, 64) } if rawHeight != "" { height, _ = strconv.ParseInt(rawHeight, 10, 64) } rawFilters := query.Get("filters") filters := strings.Split(rawFilters, ",") thumbDir := registry.Config().UString("thumbnailDir") if thumbDir == "" { thumbDir = tmpPath + string(os.PathSeparator) + "thumbnails" } ip := strings.Split(httpRequest.RemoteAddr, ":")[0] if ip == "" { ip = httpRequest.Header.Get("X-Forwarded-For") } reader, size, err := hooks.getImageReader(registry, thumbDir, file, width, height, filters, ip) if err != nil { return kit.NewErrorResponse(err), false } w := r.GetHttpResponseWriter() err = serveFile(w, httpRequest, file.GetMime(), size, reader) reader.Close() if err != nil { registry.Logger().Errorf("Error while serving image %v(%v): %v", file.GetId(), file.GetBackendId(), err) } return nil, true } serveImageRoute := kit.NewHttpRoute("/images/:id/*rest", "GET", serveImageHandler) routes = append(routes, serveImageRoute) return routes }
package users import ( //"github.com/theduke/go-apperror" kit "github.com/app-kit/go-appkit" "github.com/app-kit/go-appkit/app/methods" ) var AuthenticateMethod kit.Method = &methods.Method{ Name: "users.authenticate", Blocking: true, Handler: func(registry kit.Registry, r kit.Request, unblock func()) kit.Response { if r.GetUser() != nil { return kit.NewErrorResponse("already_authenticated", "Can't authenticate a session which is already authenticated", true) } data, ok := r.GetData().(map[string]interface{}) if !ok { return kit.NewErrorResponse("invalid_data", "Invalid data: expected dict", true) } // Find user. userIdentifier, _ := data["user"].(string) adaptor, _ := data["adaptor"].(string) if adaptor == "" { return kit.NewErrorResponse("adaptor_missing", "Expected 'adaptor' in metadata.", true) } authData, _ := data["authData"].(map[string]interface{})
func (res *Resource) ApiFind(query *db.Query, r kit.Request) kit.Response { // If query is empty, query for all records. if query == nil { query = res.Q() } apiFindHook, ok := res.hooks.(ApiFindHook) if ok { return apiFindHook.ApiFind(res, query, r) } if alterQuery, ok := res.hooks.(ApiAlterQueryHook); ok { alterQuery.ApiAlterQuery(res, query, r) } result, err := res.Query(query) if err != nil { return kit.NewErrorResponse(err) } user := r.GetUser() if allowFind, ok := res.hooks.(AllowFindHook); ok { finalItems := make([]kit.Model, 0) for _, item := range result { if allowFind.AllowFind(res, item, user) { finalItems = append(finalItems, item) } } result = finalItems } response := &kit.AppResponse{ Data: result, } // If a limit was set, count the total number of results // and set count parameter in metadata. limit := query.GetLimit() if limit > 0 { query.Limit(0).Offset(0) count, err := res.backend.Count(query) if err != nil { return &kit.AppResponse{ Error: apperror.Wrap(err, "count_error", ""), } } response.SetMeta(map[string]interface{}{ "count": count, "total_pages": math.Ceil(float64(count) / float64(limit)), }) } if hook, ok := res.hooks.(ApiAfterFindHook); ok { if err := hook.ApiAfterFind(res, result, r, response); err != nil { return kit.NewErrorResponse(err) } } return response }
func serverRenderer(registry kit.Registry, r kit.Request) kit.Response { url := r.GetHttpRequest().URL // Build the url to query. if url.Scheme == "" { url.Scheme = "http" } if url.Host == "" { url.Host = registry.Config().UString("host", "localhost") + ":" + registry.Config().UString("port", "8000") } q := url.Query() q.Set("no-server-render", "1") url.RawQuery = q.Encode() strUrl := url.String() cacheKey := "serverrenderer_" + strUrl cacheName := registry.Config().UString("serverRenderer.cache") var cache kit.Cache // If a cache is specified, try to retrieve it. if cacheName != "" { cache = registry.Cache(cacheName) if cache == nil { registry.Logger().Errorf("serverRenderer.cache is set to %v, but the cache is not registered with app", cacheName) } } // If a cache was found, try to retrieve cached response. if cache != nil { item, err := cache.Get(cacheKey) if err != nil { registry.Logger().Errorf("serverRenderer: cache retrieval error: %v", err) } else if item != nil { // Cache item found, return response with cache item. status, _ := strconv.ParseInt(item.GetTags()[0], 10, 64) data, _ := item.ToString() return &kit.AppResponse{ HttpStatus: int(status), RawData: []byte(data), } } } // Either no cache or url not yet cached, so render it. // First, ensure that the tmp directory exists. tmpDir := path.Join(registry.Config().TmpDir(), "phantom") if ok, _ := utils.FileExists(tmpDir); !ok { if err := os.MkdirAll(tmpDir, 0777); err != nil { return &kit.AppResponse{ Error: &apperror.Err{ Code: "create_tmp_dir_failed", Message: fmt.Sprintf("Could not create the tmp directory at %v: %v", tmpDir, err), }, } } } // Build a unique file name. filePath := path.Join(tmpDir, utils.UUIdv4()+".html") // Execute phantom js. // Find path of phantom script. _, filename, _, _ := runtime.Caller(1) scriptPath := path.Join(path.Dir(path.Dir(filename)), "phantom", "render.js") start := time.Now() phantomPath := registry.Config().UString("serverRenderer.phantomJsPath", "phantomjs") args := []string{ "--web-security=false", "--local-to-remote-url-access=true", scriptPath, "10", strUrl, filePath, } result, err := exec.Command(phantomPath, args...).CombinedOutput() if err != nil { registry.Logger().Errorf("Phantomjs execution error: %v", string(result)) return &kit.AppResponse{ Error: apperror.Wrap(err, "phantom_execution_failed"), } } // Get time taken as milliseconds. timeTaken := int(time.Now().Sub(start) / time.Millisecond) registry.Logger().WithFields(log.Fields{ "action": "phantomjs_render", "milliseconds": timeTaken, }).Debugf("Rendered url %v with phantomjs", url) content, err2 := utils.ReadFile(filePath) if err2 != nil { return kit.NewErrorResponse(err2) } // Find http status code. status := 200 res := regexp.MustCompile("http_status_code\\=(\\d+)").FindStringSubmatch(string(content)) if res != nil { s, _ := strconv.ParseInt(res[1], 10, 64) status = int(s) } // Save to cache. if cache != nil { lifetime := registry.Config().UInt("serverRenderer.cacheLiftetime", 3600) err := cache.Set(&caches.StrItem{ Key: cacheKey, Value: string(content), Tags: []string{strconv.FormatInt(int64(status), 10)}, ExpiresAt: time.Now().Add(time.Duration(lifetime) * time.Second), }) if err != nil { registry.Logger().Errorf("serverRenderer: Cache persist error: %v", err) } } return &kit.AppResponse{ HttpStatus: status, RawData: content, } }