public static JObject AddPathObjects(this JObject spec, ApiMetaData data) { var paths = from s in data.Sections from r in s.Resources from e in r.Endpoints orderby e.Route select new { Path = $"/{e.Route.TrimStart("v1")}", Verb = e.HttpVerb.Method.ToLower(), EndpointObj = new EndpointObject(r, e, data).ToJObject() }; var jp = new JObject(); foreach (var p in paths.GroupBy(p => p.Path)) { var je = new JObject(); foreach (var e in p.OrderBy(x => x.Verb.SortOrder())) { je.Add(e.Verb, e.EndpointObj); } jp.Add(p.Key, je); } spec.Add("paths", jp); return(spec); }
public static JObject AddComponents(this JObject spec, ApiMetaData data) { spec.Add("components", new JObject( new JProperty("securitySchemes", new SecurityObject(data).ToJObject()), new JProperty("schemas", new SchemaObject(data).ToJObject()))); return(spec); }
public SecurityObject(ApiMetaData data) { var scopes = new JObject(); foreach (var role in data.Roles) { scopes.Add(role, ""); } var flowDefinition = new JObject( new JProperty("tokenUrl", "/oauth/token"), new JProperty("scopes", scopes) ); _obj = new JObject { { "OAuth2", new JObject( new JProperty("type", "oauth2"), new JProperty("flows", new JObject( new JProperty("password", flowDefinition), new JProperty("clientCredentials", flowDefinition) ))) } }; }
public EndpointObject(ApiResource res, ApiEndpoint method, ApiMetaData data) { //Add responses obj _obj.Add("responses", new ResponseObject(method).ToJObject()); //Add operationId and tags _obj.Add("operationId", res.Name + '.' + method.Name); _obj.Add("tags", new JArray(res.Description)); //Add parameters obj var param = new ParamObject(res, method, data).ToTuples(); param.ForEach(p => _obj.Add(p.Item1, p.Item2)); _obj.Add("summary", method.Description); _obj.Add("description", string.Join("<br/></br>", method.Comments)); //Add scopes needed to access this endpoint _obj.Add("security", new JArray(new JObject(new JProperty("OAuth2", method.RequiredRoles)))); }
public static JObject AddResourceTags(this JObject spec, ApiMetaData data) { var tagsArray = new JArray(); foreach (var section in data.Sections) { tagsArray.Add(new JObject( new JProperty("name", section.Name), new JProperty("description", String.Join("\n", section.Description)), new JProperty("x-id", section.ID))); foreach (var resource in section.Resources) { tagsArray.Add(new JObject( new JProperty("name", resource.Description), new JProperty("description", String.Join("\n", resource.Comments)), new JProperty("x-section-id", section.ID))); } } spec.Add("tags", tagsArray); return(spec); }
public ParamObject(ApiResource resource, ApiEndpoint endpoint, ApiMetaData data) { _param = new List <Tuple <string, JRaw> >(); if (endpoint.SubResource != null) { // Used to get correct enumerables on query params such as sortBy and searchOn for the Me resource resource = data.Resources.FirstOrDefault(r => r.Name == endpoint.SubResource); } var paramArray = new JArray(); foreach (var p in endpoint.PathArgs) { var paramObj = new JObject { { "name", p.Name }, { "in", "path" }, { "description", string.Join("\n", p.Description) }, { "required", p.Required } }; var type = p.SimpleType; if (type == "date") { type = "string"; } var paramSchema = new JObject(new JProperty("type", type)); if (p.Type.IsEnum) { paramSchema.Add("enum", new JArray(p.Type.GetEnumNames())); } paramObj.Add("schema", paramSchema); paramArray.Add(paramObj); } foreach (var p in endpoint.QueryArgs) { var paramObj = new JObject { { "name", p.Name }, { "in", "query" }, { "description", string.Join("\n", p.Description) }, { "required", p.Required } }; var type = p.SimpleType; if (type == "date") { type = "string"; } var paramSchema = new JObject(); //TODO: figure out how to identify List<string> types vs. simple string types. if (p.Name == "sortBy" || p.Name == "searchOn") { var model = (endpoint.ResponseModel.Type.WithoutGenericArgs() == typeof(ListPage <>) ? endpoint.ResponseModel.InnerModel : endpoint.ResponseModel).BuildStringListEnum(p.Name); //TODO: evaluate the best way to handle this.. It's hard coded to OC paramSchema.Add("type", "array"); paramSchema.Add("items", new JObject( new JProperty("type", "string"), new JProperty("enum", model.Count > 0 ? model : new JArray("ID")))); } else { paramSchema.Add("type", p.Name == "filters" ? "object" : type); if (p.Type.IsEnum) { paramSchema.Add("enum", new JArray(p.Type.GetEnumNames())); } } paramObj.Add("schema", paramSchema); if (p.Name != "defaultSearchOn" && p.Name != "defaultSortBy") { paramArray.Add(paramObj); } } if (endpoint.RequestModel != null) { var requestObj = new JObject { { "required", true }, { "description", "" } }; //Body params are always required var type = endpoint.RequestModel.Type.PropertySimpleName(); var schema = new JObject( new JProperty("allOf", new JArray(new JObject(new JProperty("$ref", "#/components/schemas/" + type))))); if (!endpoint.HttpVerb.Equals(new HttpMethod("patch"))) { var requiredFields = new JArray(); foreach (var property in endpoint.RequestModel.Properties) { if (property.Required) { requiredFields.Add(property.Name); } } ; if (requiredFields.Count > 0) { schema.Add("required", requiredFields); } } requestObj.Add("content", new JObject( new JProperty("application/json", new JObject( new JProperty("schema", schema) )))); _param.Add(new Tuple <string, JRaw>("requestBody", requestObj.ToJRaw())); } if (paramArray.Count > 0) { _param.Add(new Tuple <string, JRaw>("parameters", paramArray.ToJRaw())); } }
public OpenApiGenerator <TController> CollectMetaData(string refPath, IDictionary <string, IErrorCode> errors) { this._data = ApiReflector.GetMetaData <TController>(refPath, errors); return(this); }
public SchemaObject(ApiMetaData data) { var schemas = new Dictionary <string, JToken>(); foreach (var model in data.Models) { if (!model.Name.Contains("Partial")) { var modelDefinitionKey = model.Name; var schemaDef = new JObject { { "type", "object" } }; var propertiesDef = new JObject(); foreach (var prop in model.Properties) { var propDefinitionKey = prop.Name; var propObject = new PropertyObject(prop.Type).ToJObject(); if (prop.HasDefaultValue) { propObject.Add("default", new JValue(prop.DefaultValue)); } if (prop.ReadOnly || model.IsReadOnly) { propObject.Add("readOnly", true); } var docCommentsAttribute = prop.PropInfo.GetCustomAttribute <DocCommentsAttribute>(); if (docCommentsAttribute != null) { propObject.Add("description", string.Join("\n", docCommentsAttribute.Comments)); } var minValueAttribute = prop.PropInfo.GetCustomAttribute <MinValueAttribute>(); if (minValueAttribute != null) { propObject.Add("minimum", minValueAttribute.Minimum.ToJRaw()); } var maxValueAttribute = prop.PropInfo.GetCustomAttribute <MaxValueAttribute>(); if (maxValueAttribute != null) { propObject.Add("maximum", maxValueAttribute.Maximum.ToJRaw()); } var maxLengthAttribute = prop.PropInfo.GetCustomAttribute <MaxLengthAttribute>(); if (maxLengthAttribute != null) { propObject.Add("maxLength", maxLengthAttribute.Length); } var minLengthAttribute = prop.PropInfo.GetCustomAttribute <MinLengthAttribute>(); if (minLengthAttribute != null) { propObject.Add("minLength", minLengthAttribute.Length); } if (propDefinitionKey.Contains("Password")) { if (propObject.ContainsKey("format")) { propObject.Merge(new JObject(new JProperty("format", "password"))); } else { propObject.Add("format", "password"); } } propertiesDef.Add(propDefinitionKey, propObject); } schemaDef.Add("example", model.Sample.ToJRaw()); schemaDef.Add("properties", propertiesDef); schemas.Add(modelDefinitionKey, schemaDef); } } schemas.Add("Meta", new DefinitionObject(typeof(ListPageMeta)).ToJObject()); schemas.Add("MetaWithFacets", new DefinitionObject(typeof(ListPageMetaWithFacets)).ToJObject()); schemas.Add("ListFacet", new DefinitionObject(typeof(ListFacet)).ToJObject()); schemas.Add("ListFacetValue", new DefinitionObject(typeof(ListFacetValue)).ToJObject()); //Find all methods that return ListPage and create all the different types of List objects foreach (var endpoint in data.Resources.SelectMany(r => r.Endpoints).Where(e => e.IsList)) { var itemType = endpoint.ResponseModel.Type .UnwrapGeneric(typeof(ListPage <>)) .UnwrapGeneric(typeof(ListPageWithFacets <>)).PropertySimpleName(); var listTypeName = "List" + itemType; //Check if this list type doesn't exist yet if (!schemas.ContainsKey(listTypeName)) { var listObj = new JObject { { "type", "object" } }; var listProperties = new JObject { { "Items", new JObject( new JProperty("type", "array"), new JProperty("items", new JObject(new JProperty("$ref", "#/components/schemas/" + itemType))) ) } }; var metaDef = (endpoint.ResponseModel.Type.WithoutGenericArgs() == typeof(ListPageWithFacets <>)) ? "MetaWithFacets" : "Meta"; listProperties.Add("Meta", new JObject(new JProperty("$ref", "#/components/schemas/" + metaDef))); listObj.Add("properties", listProperties); schemas.Add(listTypeName, listObj); } } foreach (var def in schemas.OrderBy(d => d.Key)) { _obj.Add(def.Key, def.Value); } _obj.Add("Authentication", new JObject( new JProperty("type", "object"), new JProperty("properties", new JObject(new JProperty("access_token", new JObject(new JProperty("type", "string")))) ))); }