public Ret <ICollection <Group> > Create(Bulk <GroupForm.Create> forms) { var result = new List <Group>(); // Validando foreach (var form in forms) { var name = form.Name?.Trim(); if (string.IsNullOrWhiteSpace(name)) { return(Ret.Fail(HttpStatusCode.BadRequest, $"O nome de grupo deve ser informado.")); } if (Db.Groups.Any(x => x.Name == name)) { return(Ret.Fail(HttpStatusCode.Conflict, $"Já existe um grupo de usuário com este nome.")); } } // Editando foreach (var form in forms) { var group = new Group { Id = Db.GenerateId(), Name = form.Name.Trim() }; Db.Groups.Add(group); result.Add(group); } return(result); }
public Ret <ICollection <Group> > Edit(Bulk <GroupForm.BulkEdit, Group> edits) { var result = new List <Group>(); // Validando foreach (var edit in edits) { edit.Record = Db.Groups.FirstOrDefault(x => x.Id == edit.Record.Id); if (edit.Record == null) { return(Ret.Fail(HttpStatusCode.NotFound, $"O grupo de usuário não existe.")); } var form = edit.Form; var group = edit.Record; var name = form.Name ?? group.Name; if (string.IsNullOrWhiteSpace(name)) { return(Ret.Fail(HttpStatusCode.BadRequest, $"O nome do grupo de usuário deve ser informado.")); } } // Editando foreach (var edit in edits) { var form = edit.Form; var group = edit.Record; group.Name = (form.Name ?? group.Name)?.Trim(); result.Add(group); } return(result); }
public async Task <Ret <byte[]> > TransferBytesAsync( UriString route, string method = MethodNames.Get, byte[] requestData = null ) { try { Ret ret = null; await DoRequestAsync(route, method, "application/octet-stream", requestData, async webResponse => { if (webResponse.StatusCode == HttpStatusCode.OK) { using (var stream = webResponse.GetResponseStream()) using (var memory = new MemoryStream()) { await stream.CopyToAsync(memory); ret = Ret.Ok(memory.ToArray(), webResponse.StatusCode); } } else { ret = Ret.Fail(webResponse.StatusCode); } }); return(ret); } catch (Exception ex) { ex.Trace(); return(ex); } }
public Ret <Entity> RenderEntity(HttpContext httpContext, string path) { if (httpContext.Request.Method != "GET") { return(Ret.Fail(HttpStatusCode.MethodNotAllowed)); } var query = injector.CreateInstance(PaperType); try { var entity = new Entity(); RenderEntity(httpContext, query, entity); return(entity); } catch (Exception ex) { return(ex); } finally { (query as IDisposable)?.Dispose(); } }
public Ret <ProjectHeader> LoadProjectHeader(string folder = ".") { try { bool ok; var svn = new Svn(); svn.User = SvnUser ?? Svn.DefaultUser; svn.Pass = SvnPass ?? Svn.DefaultPass; ok = svn.Fill(); if (!ok) { Ret.Fail(); } var pack = new PackDm.PackDm(); pack.PackConf = PackConf; pack.PackInfo = PackInfo; ok = pack.Fill(); if (!ok) { Ret.Fail(); } var header = LoadProjectHeader(svn, pack); return(header); } catch (Exception ex) { return(ex); } }
public async Task Invoke(HttpContext httpContext) { try { var req = httpContext.Request; var query = httpContext.Request.Query; var path = (string)query["path"]; var reverseUri = (string)query["reverseUri"]; var isShowInfoOnly = (req.Method == "GET" && reverseUri == null); if (isShowInfoOnly) { await SendProxyAsync(httpContext); } else { await EditProxyAsync(httpContext); } } catch (Exception ex) { await SendStatusAsync(httpContext, Ret.Fail(ex)); } }
private Ret <Entity> ExecuteMethod(HttpContext httpContext, MethodInfo method) { try { var target = injector.CreateInstance(PaperType); try { var ret = CreateParameters(httpContext, method); if (ret.IsFault()) { return(Ret.Throw(ret)); } object[] parameters = ret.Data; method.Invoke(target, parameters); } finally { (target as IDisposable)?.Dispose(); } return(Ret.Ok()); } catch (Exception ex) { return(Ret.Fail(ex)); } }
async Task GetPaper(string paper) { var descriptor = paperCatalog.FindPaperDescriptor(defaultCatalog, paper); if (descriptor == null) { var ret = Ret.Fail(HttpStatusCode.NotFound, $"O objeto não existe: {defaultCatalog}/{paper}"); await Res.SendEntityStatusAsync(ret); return; } object output; var instance = objectFactory.CreateObject(descriptor.PaperType); if (instance._HasMethod("Render")) { output = objectFactory.Call(instance, "Render", null); } else { throw new HttpException($"Não há um algoritmo de renderização conhecido para objeto do tipo ${descriptor.PaperType.FullName}."); } if (output is Stream stream) { await stream.CopyToAsync(Res.Body); await Res.Body.FlushAsync(); } else if (output is StreamReader reader) { var encoding = Encoding.UTF8; var writer = new StreamWriter(Res.Body, encoding); await reader.CopyToAsync(writer); await writer.FlushAsync(); await Res.Body.FlushAsync(); } else if (output is Entity entity) { var encoding = Encoding.UTF8; var mimeType = "json"; var serializer = new MediaSerializer(mimeType); serializer.Serialize(entity, Res.Body, encoding); await Res.Body.FlushAsync(); } else { throw new HttpException($"Não há suporte para renderização de dados do tipo {output.GetType().FullName}"); } }
private async Task RedirectRequest(HttpContext httpContext, Proxy proxy) { Ret ret; using (var httpClient = new HttpClient()) { try { var req = httpContext.Request; var res = httpContext.Response; var uri = CreateTargetUri(req, proxy); if (!uri.OK) { await SendStatusAsync(httpContext, uri); return; } var message = CreateMessage(req, uri); if (!message.OK) { await SendStatusAsync(httpContext, message); return; } ret = CopyRequestToMessage(req, message); if (!ret.OK) { await SendStatusAsync(httpContext, ret); return; } var result = await httpClient.SendAsync(message); ret = CopyResultToResponse(result, res); if (!ret.OK) { await SendStatusAsync(httpContext, ret); return; } await result.Content.CopyToAsync(res.Body); } catch (Exception ex) { await SendStatusAsync(httpContext, Ret.Fail(ex)); } } }
protected async override Task SendFaultAsync(Exception exception) { try { var payload = Ret.Fail(exception); await Res.SendEntityAsync(payload, mediaFormat : null); } catch { await base.SendFaultAsync(exception); } }
public async Task <Ret <Result> > CallAsync(PaperContext context) { var descriptor = context.Paper; var req = context.Request; var res = context.Response; Entity form = null; if (!req.Method.EqualsAnyIgnoreCase(MethodNames.Get, MethodNames.Delete)) { form = req.ReadEntityAsync().RunSync(); // TODO: Uma entidade diferente de "form" não está sendo suportada, mas poderia, // se houvesse um algoritmo de conversão. var isValid = form.Class.Has(ClassNames.Form); if (!isValid) { return(Ret.Fail(HttpStatusCode.BadRequest, "Formato de dados não suportado. Os dados devem ser enviados em uma entidade do tipo \"form\".")); } } MethodInfo method = descriptor.GetMethod(context.Action); Ret <Result> ret = CallPaperMethod(context, descriptor.Paper, method, context.Args, form); var isFailure = (ret.Status.CodeClass != HttpStatusClass.Success); if (isFailure) { return(await Task.FromResult(ret)); } Result result = ret.Value; var isUri = typeof(string).IsAssignableFrom(result.ValueType) || typeof(Uri).IsAssignableFrom(result.ValueType) || typeof(Href).IsAssignableFrom(result.ValueType) || typeof(UriString).IsAssignableFrom(result.ValueType); if (isUri) { var href = (result.Value as Href)?.ToString() ?? result.Value?.ToString(); ret = Ret.Create(HttpStatusCode.Found); ret.Status.Headers[HeaderNames.Location] = href; return(await Task.FromResult(ret)); } return(await Task.FromResult(ret)); }
private Ret <string> CreateTargetUri(HttpRequest req, Proxy proxy) { if (!req.Path.StartsWithSegments(proxy.Path)) { return(Ret.Fail(HttpStatusCode.BadGateway, $"As configurações de proxy para esta roda não estão corretas: {req.Path.Value}")); } var path = req.Path.Value.Substring(proxy.Path.Value.Length); var currentRoute = new Route(req.GetRequestUri()).Combine("/"); var reverseRoute = new Route(proxy.ReverseUri); var uri = currentRoute.Combine(reverseRoute).Append(path).ToString(); return(uri); }
async Task GetPaper(string paper) { var descriptor = paperCatalog.FindPaperDescriptor(defaultCatalog, paper); if (descriptor == null) { var ret = Ret.Fail(HttpStatusCode.NotFound, $"O obteto não existe: {defaultCatalog}/{paper}"); await Res.SendEntityStatusAsync(ret); return; } var instance = new Beans.Paper { Catalog = descriptor.Catalog, Name = descriptor.Paper, Title = descriptor.Title, Path = $"/Paper/Api/Catalogs/{descriptor.Catalog}/Papers/{descriptor.Paper}" }; await Res.SendEntityAsync(instance, payload => { var entity = FormatPayload(payload); entity.Add(new Link { Href = new Url(Req.RequestUri).Combine("../.."), Title = "Catálogo" }); entity.Add(new Link { Href = new Url(Req.RequestUri).Combine(".."), Title = "Papers" }); entity.Add(new Link { Href = new Url(Req.RequestUri).Append("Actions"), Title = "Ações" }); return(entity); }); }
public Ret <ICollection <User> > Create(Bulk <UserForm.Create> forms) { var result = new List <User>(); // Validando foreach (var form in forms) { if (Db.Users.Any(x => x.Login == form.Login)) { return(Ret.Fail(HttpStatusCode.Conflict, $"Já existe uma conta de usuário para este login.")); } if (string.IsNullOrWhiteSpace(form.Login)) { return(Ret.Fail(HttpStatusCode.BadRequest, $"O nome de login deve ser informado.")); } if (string.IsNullOrWhiteSpace(form.Name)) { return(Ret.Fail(HttpStatusCode.BadRequest, $"O nome de usuário deve ser informado.")); } if (!Db.Groups.Any(x => x.Id == form.GroupId)) { return(Ret.Fail(HttpStatusCode.BadRequest, $"O grupo de usuário não existe.")); } } // Editando foreach (var form in forms) { var user = new User { Id = Db.GenerateId(), Login = form.Login.Trim(), Name = form.Name.Trim(), Enabled = true, GroupId = form.GroupId }; Db.Users.Add(user); result.Add(user); } return(result); }
private Ret <object[]> CreateParameters(HttpContext httpContext, MethodInfo method) { var args = ParseArgs(httpContext); var parameters = method.GetParameters().ToList(); var parameterValues = new object[parameters.Count]; for (int i = 0; i < parameters.Count; i++) { var parameter = parameters[i]; if (!IsSimpleValue(parameter.ParameterType)) { parameterValues[i] = injector.CreateInstance(parameter.ParameterType); } } foreach (var arg in args) { var tokens = arg.Key.Split('.'); var argName = tokens.First(); var argProperty = tokens.Skip(1).FirstOrDefault(); var parameter = parameters.FirstOrDefault(x => x.Name.EqualsIgnoreCase(argName)); if (parameter == null) { return(Ret.Fail(HttpStatusCode.BadRequest, $"Parâmetro não esperado: {arg.Value}")); } var parameterIndex = parameters.IndexOf(parameter); if (argProperty == null) { var value = Cast.To(arg.Value, parameter.ParameterType); parameterValues[parameterIndex] = value; } else { var target = parameterValues[parameterIndex]; target.Set(argProperty, arg.Value); } } return(parameterValues); }
public Ret <ICollection <User> > Edit(Bulk <UserForm.BulkEdit, User> edits) { var result = new List <User>(); // Validando foreach (var edit in edits) { edit.Record = Db.Users.FirstOrDefault(x => x.Id == edit.Record.Id); if (edit.Record == null) { return(Ret.Fail(HttpStatusCode.NotFound, $"A conta de usuário não existe.")); } var form = edit.Form; var user = edit.Record; var name = form.Name ?? user.Name; var enabled = form.Enabled ?? user.Enabled; var groupId = form.GroupId ?? user.GroupId; if (string.IsNullOrWhiteSpace(name)) { return(Ret.Fail(HttpStatusCode.BadRequest, $"O nome de usuário deve ser informado.")); } if (!Db.Groups.Any(x => x.Id == groupId)) { return(Ret.Fail(HttpStatusCode.BadRequest, $"O grupo de usuário não existe.")); } } // Editando foreach (var edit in edits) { var form = edit.Form; var user = edit.Record; user.Name = (form.Name ?? user.Name)?.Trim(); user.Enabled = form.Enabled ?? user.Enabled; user.GroupId = form.GroupId ?? user.GroupId; result.Add(user); } return(result); }
public async Task <Ret> SubmitAsync() { var form = (ActionForm)Host; try { form.SubmitButton.Enabled = form.ExitButton.Enabled = false; var hasErrors = CheckForErrors(); if (hasErrors) { MessageBox.Show( form, "Não é possível prosseguir porque existem erros no formulário.", form.Text, MessageBoxButtons.OK ); return(Ret.Fail("Não é possível prosseguir porque existem erros no formulário.")); } var ret = await SendFormAsync(); if (ret.Ok) { complete = true; Host.Close(); } return(ret); } catch (Exception ex) { ex.Trace(); return(ex); } finally { form.SubmitButton.Enabled = form.ExitButton.Enabled = true; } }
public async Task <Ret <Content> > RequestAsync(string uri, string method, Entity data) { Ret <Content> ret; try { var http = new HttpClient(); ret = await http.RequestAsync(uri, method, data); } catch (Exception ex) { var fault = HttpEntity.Create(uri, ex); ret = Ret.Fail(uri, ex); ret.Value = new Content { Href = uri, Data = fault.Value }; } return(ret); }
public Ret <Entity> RenderEntity(PaperContext ctx) { var entity = new Entity(); if (ctx.Paper is Entity) { CloneEntity(entity, (Entity)ctx.Paper, ctx); } else if (ctx.Paper is IPaper) { RenderPaper(entity, (IPaper)ctx.Paper, ctx); } else { return(Ret.Fail("Tipo não suportado pelo renderizador do Paper.Media: " + ctx.Paper?.GetType().FullName)); } entity.AddClass(ctx.Paper.GetType()); entity.AddLinkSelf(ctx.RequestUri); entity.ResolveLinks(ctx.RequestUri); return(entity); }
public Ret <ICollection <User> > Edit(Mass <UserForm.MassEdit, User> edits) { var result = new List <User>(); var form = edits.Form; var users = ( from user in edits select Db.Users.FirstOrDefault(x => x.Id == user.Id) ).ToArray(); // Validando foreach (var user in users) { if (user == null) { return(Ret.Fail(HttpStatusCode.NotFound, $"A conta de usuário não existe.")); } var groupId = form.GroupId ?? user.GroupId; if (!Db.Groups.Any(x => x.Id == groupId)) { return(Ret.Fail(HttpStatusCode.BadRequest, $"O grupo de usuário não existe.")); } } // Editando foreach (var user in users) { user.Enabled = form.Enabled ?? user.Enabled; user.GroupId = form.GroupId ?? user.GroupId; result.Add(user); } return(result); }
private bool SaveChanges() { Settings.Host = txHost.Text; try { Settings.Port = Change.To <int>(txPort.Text); } catch (Exception ex) { var ln = Environment.NewLine; var causes = string.Join(ln, ex.GetCauseMessages().Select(x => $"• {x}")); var message = $"O valor indicado para a porta não é um número de porta válido.{ln}{ln}Causa: {ln}{causes}"; using (var dialog = new FaultDialog(Ret.Fail(new Exception(message, ex)))) { dialog.ShowDialog(this); } return(false); } var hasChanges = CheckForChanges(); return(!hasChanges); }
async Task NotFound(string path) { var ret = Ret.Fail(HttpStatusCode.NotFound, $"Este caminho não corresponde a qualquer método da API: {path}"); await Res.SendEntityStatusAsync(ret); }
async Task GetAction(string paper, string action) { var ret = Ret.Fail(HttpStatusCode.NotImplemented, $"Ainda náo implementado: {defaultCatalog}/{paper}/{action}"); await Res.SendEntityStatusAsync(ret); }
public static Ret <MediaFormat> GetMediaFormat(this IRequest req) { var args = req.QueryArgs; var accept = req.Headers[HeaderNames.Accept]; var charset = req.Headers[HeaderNames.AcceptCharset]; if (args["out"] is Var outVar) { var format = outVar.RawValue?.ToString() ?? ""; // exemplos: // text/csv // application/json; charset=UTF-8 var pattern = @"^([^/=;\s]+)/([^/=;\s]+)(?:;\s*charset=([^/=;\s]+))?$"; var match = Regex.Match(format, pattern); if (match.Success) { return(Ret.Fail(HttpStatusCode.BadRequest, "O valor do parâmetro `out' é inválido.")); } accept = match.Groups[1].Value; if (!string.IsNullOrEmpty(match.Groups[2].Value)) { charset = match.Groups[2].Value; } } if (args["charset"] is Var charsetVar) { var format = charsetVar.RawValue?.ToString() ?? ""; // exemplos: // UTF-8 // Latin1 // ISO-8859-15 var pattern = @"^[^/=;\s]+$"; var match = Regex.Match(format, pattern); if (match.Success) { return(Ret.Fail(HttpStatusCode.BadRequest, "O valor do parâmetro `charset' é inválido.")); } charset = format; } if (args["encoding"] is Var encodingVar) { var format = encodingVar.RawValue?.ToString() ?? ""; // exemplo: // UTF-8 var pattern = @"^[^/=;\s]+$"; var match = Regex.Match(format, pattern); if (match.Success) { return(Ret.Fail(HttpStatusCode.BadRequest, "O valor do parâmetro `charset' é inválido.")); } charset = format; } if (args["f"] is Var fVar) { var format = fVar.RawValue?.ToString() ?? ""; // pattern: // type.compression // exemplos: // xml // json.gz // csv.gzip var pattern = @"^([^/=;\s]+)/([^/=;\s]+)(?:;\s*charset=([^/=;\s]+))?$"; var match = Regex.Match(format, pattern); if (match.Success) { return(Ret.Fail(HttpStatusCode.BadRequest, "O valor do parâmetro `out' é inválido.")); } //[\w\d]+(?:\.([\w\d]+))? } var mediaFormat = new MediaFormat(); var acceptType = req.Headers[HeaderNames.Accept]; if (acceptType?.Contains(MimeTypeNames.JsonSiren) == true) { mediaFormat.Type = MimeTypeNames.JsonSiren; } else if (acceptType?.Contains(MimeTypeNames.XmlSiren) == true) { mediaFormat.Type = MimeTypeNames.XmlSiren; } else if (acceptType?.Contains(MimeTypeNames.JsonApplication) == true) { mediaFormat.Type = MimeTypeNames.JsonApplication; } else if (acceptType?.Contains(MimeTypeNames.JsonText) == true) { mediaFormat.Type = MimeTypeNames.JsonText; } else if (acceptType?.Contains(MimeTypeNames.XmlApplication) == true) { mediaFormat.Type = MimeTypeNames.XmlApplication; } else if (acceptType?.Contains(MimeTypeNames.XmlText) == true) { mediaFormat.Type = MimeTypeNames.XmlText; } else { mediaFormat.Type = MimeTypeNames.JsonText; } return(mediaFormat); }
private Ret <Result> CallPaperMethod(PaperContext context, IPaper paper, MethodInfo method, Args args, Entity form) { object result = null; try { var methodArgs = CreateParameters(context, paper, method, args, form); context.RenderContext.Sort = methodArgs.OfType <Sort>().FirstOrDefault(); context.RenderContext.Page = methodArgs.OfType <Page>().FirstOrDefault(); context.RenderContext.Filter = methodArgs.OfType <IFilter>().FirstOrDefault(); context.RenderContext.Page?.IncreaseLimit(); result = objectFactory.Invoke(paper, method, methodArgs); } catch (Exception ex) { result = Ret.Fail(ex); } var resultType = method.ReturnType; if (Is.Ret(resultType)) { resultType = TypeOf.Ret(resultType); } Ret <Result> ret; if (result == null) { // Um método que resulta "void" é considerado OK quando não emite exceção. // Um método que resulta nulo é considerado NotFound (Não encontrado). var isVoid = method.ReturnType == typeof(void); if (isVoid) { ret = Ret.OK(new Result { Value = result, ValueType = resultType }); } else { ret = Ret.NotFound(new Result { Value = result, ValueType = resultType }); } } else if (Is.Ret(result)) { ret = new Ret <Result>(); ret.Status = (RetStatus)result._Get(nameof(ret.Status)); ret.Fault = (RetFault)result._Get(nameof(ret.Fault)); ret.Value = new Result { Value = result._Get(nameof(ret.Value)), ValueType = resultType }; } else { ret = Ret.OK(new Result { Value = result, ValueType = resultType }); } return(ret); }