private async Task <InvokeResponse> OnInvoke(object link, string method, object[] args) { var user = _authenticationService != null ? await _authenticationService.GetPrincipalAsync(Context.ConnectionId) : null; var type = link.GetType(); var authorized = await AuthorizationHelper.AuthorizeAsync(type, user, _authorizationService); if (!authorized) { return(new InvokeResponse(StatusCodes.Status403Forbidden)); } var name = _componentsService.GetComponentName(type); var methodInfo = _componentsService.GetMethodInfo(name, $"{method}{ComponentsService.Delimiter}{args?.Length ?? 0}"); if (methodInfo == null) { return(new InvokeResponse(StatusCodes.Status404NotFound)); } authorized = await AuthorizationHelper.AuthorizeAsync(methodInfo, user, _authorizationService); if (!authorized) { return(new InvokeResponse(StatusCodes.Status403Forbidden)); } var returnType = methodInfo.ReturnType; var parameters = methodInfo.GetParameters(); if (args != null) { for (int j = 0; j < args.Length; ++j) { args[j] = Convert(args[j], parameters[j].ParameterType); } } if (returnType == typeof(void)) { // void Method(T1,...,Tn) methodInfo.Invoke(link, args); return(new InvokeResponse(StatusCodes.Status200OK)); } if (returnType == typeof(Task)) { // Task Method(T1,...,Tn) => {...} var task = (Task)methodInfo.Invoke(link, args); await task; return(new InvokeResponse(StatusCodes.Status200OK)); } if (returnType.GetTypeInfo().BaseType == typeof(Task)) { // Task<TResult> Method(T1,...,Tn) dynamic task = methodInfo.Invoke(link, args); await task; return(new InvokeResponse(StatusCodes.Status200OK, task.Result, true)); } // TResult Method(T1,...,Tn) var result = methodInfo.Invoke(link, args); return(new InvokeResponse(StatusCodes.Status200OK, result, true)); }
public async Task <bool> AddStateAsync(string name, string fullname, IViewModel viewModel, IPrincipal user) { this.States.Add(fullname, viewModel); if (!this.Methods.ContainsKey(name)) { this.Methods.Add(name, _componentsService.GetMethodNames(name)); } if (viewModel.Components != null) { foreach (var component in viewModel.Components) { if (component.Type != null) { var authorized = await AuthorizationHelper.AuthorizeAsync(component.Type, user, _authorizationService); if (!authorized) { return(false); } } var childName = component.Type != null ? _componentsService.GetComponentName(component.Type) : component.Name; var childFullName = $"{fullname}.{childName}"; if (component.Id != null) { childFullName += $"${component.Id}"; } AddAssets(childName); if (component.Type != null) { var link = (IInternalDirectLink <ViewModel>)_provider.GetService(component.Type); var args = component.Args ?? Array.Empty <object>(); var childViewModel = CreateViewModel(link, args, childName); var succeeded = await AddStateAsync(childName, childFullName, childViewModel, user); if (!succeeded) { return(false); } } else { if (component.State != null) { States.Add(childFullName, component.State); } } } } return(true); }
private async Task <DirectLinkData> GetDataAsync(string path, DirectLinkContext context) { var name = _componentsService.GetComponentName(_entryType); var fullname = name; var data = new DirectLinkData(name, _provider, _authorizationService, _componentsService); var authorized = await AuthorizationHelper.AuthorizeAsync(_entryType, context.User, _authorizationService); if (!authorized) { data.IsAuthorized = false; data.Title = context.Title; return(data); } var link = (IInternalDirectLink <ViewModel>)_provider.GetService(_entryType); var args = Array.Empty <object>(); var viewModel = data.CreateViewModel(link, args, name); data.AddAssets(name); await data.AddStateAsync(name, fullname, viewModel, context.User); var idx = path.IndexOf('#'); if (idx >= 0) { path = path.Substring(0, idx); } var routedPath = ""; context.PathBase = ""; foreach (var pathBase in _pathBases) { if (path.StartsWith(pathBase)) { context.PathBase = pathBase; routedPath = pathBase; path = path.Substring(pathBase.Length, path.Length - pathBase.Length); } } var routes = Routes.Get(_entryType); if (routes == null) { data.IsRouted = true; data.Title = context.Title; return(data); } var restPath = path; while (true) { args = null; Route nextRoute = null; foreach (var route in routes) { if (route.Regex == null) { if (restPath.StartsWith(route.Template) || (restPath == "" || restPath == "/") && route.Default) { nextRoute = route; args = nextRoute.Args; if (route.Default) { routedPath += restPath; restPath = ""; } else { routedPath += route.Template; restPath = restPath.Substring(route.Template.Length); } break; } } else { var m = route.Regex.Match(restPath); if (!m.Success) { continue; } if (m.Groups.Count - 1 != route.Parameters.Count) { break; } var values = m.Groups.Skip(1).Select(p => p.Value).ToArray(); if (RouteTypesHelper.TryGetArgs(route.Parameters, values, ref args)) { if (route.Args != null) { args = args.Concat(route.Args).ToArray(); } nextRoute = route; routedPath += m.Groups[0]; restPath = restPath.Substring(m.Value.Length); break; } } } if (nextRoute == null) { break; } var routerViewModel = (RouterViewModel)viewModel; routerViewModel.OnRouted(nextRoute); name = nextRoute.Type != null ? _componentsService.GetComponentName(nextRoute.Type) : nextRoute.Name; fullname += $".{name}"; routerViewModel.Component = new RouteComponent(name, fullname); data.AddAssets(name); if (nextRoute.Type != null) { authorized = await AuthorizationHelper.AuthorizeAsync(nextRoute.Type, context.User, _authorizationService); if (!authorized) { data.IsAuthorized = false; break; } link = (IInternalDirectLink <ViewModel>)_provider.GetService(nextRoute.Type); args = args ?? Array.Empty <object>(); viewModel = data.CreateViewModel(link, args, name); var succeeded = await data.AddStateAsync(name, fullname, viewModel, context.User); if (!succeeded) { data.IsAuthorized = false; break; } routes = Routes.Get(nextRoute.Type); if (routes == null) { if (restPath == "/") { routedPath += "/"; } break; } } else { if (nextRoute.State != null) { data.States.Add(fullname, nextRoute.State); } else { if (args == null) { data.States.Add(fullname, new Dictionary <string, object> { { "args", null } }); } else { var values = new Dictionary <string, object>(); for (int i = 0; i < nextRoute.Parameters.Count; ++i) { values.Add(nextRoute.Parameters[i].Name, args[i]); } data.States.Add(fullname, new Dictionary <string, object> { { "args", values } }); } } if (restPath == "/") { routedPath += "/"; } break; } } data.IsRouted = routedPath == context.PathBase + path; data.Title = context.Title; return(data); }