mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
3.5 KiB
143 lines
3.5 KiB
// Package gendoc generates documentation for REST APIs. |
|
package gendoc |
|
|
|
import ( |
|
"encoding/json" |
|
"io" |
|
"path" |
|
"sort" |
|
"strings" |
|
) |
|
|
|
func ParseGoogleAPI(r io.Reader) (Document, error) { |
|
var d doc |
|
if err := json.NewDecoder(r).Decode(&d); err != nil { |
|
return Document{}, err |
|
} |
|
return d.toDocument(), nil |
|
} |
|
|
|
// doc represents a Google API specification document. It is NOT intended to encompass all |
|
// options provided by the spec, only the minimal fields needed to convert dex's API |
|
// definitions into documentation. |
|
type doc struct { |
|
Name string `json:"name"` |
|
Version string `json:"version"` |
|
Title string `json:"title"` |
|
Description string `json:"description"` |
|
DocumentationLink string `json:"documentationLink"` |
|
Protocol string `json:"protocol"` |
|
BasePath string `json:"basePath"` |
|
Schemas map[string]schema `json:"schemas"` |
|
Resources map[string]methods `json:"resources"` |
|
} |
|
|
|
type methods struct { |
|
Methods map[string]resource `json:"methods"` |
|
} |
|
|
|
type param struct { |
|
Type string `json:"type"` |
|
Required bool `json:"required"` |
|
Location string `json:"location"` |
|
} |
|
|
|
type schema struct { |
|
ID string `json:"id"` |
|
Type string `json:"type"` |
|
Description string `json:"description"` |
|
Items *schema `json:"items"` |
|
Format string `json:"format"` |
|
Properties map[string]schema |
|
Ref string `json:"$ref"` |
|
} |
|
|
|
type resource struct { |
|
Description string `json:"description"` |
|
Method string `json:"httpMethod"` |
|
Path string `json:"path"` |
|
Parameters map[string]param `json:"parameters"` |
|
Request *ref `json:"request"` |
|
Response *ref `json:"response"` |
|
} |
|
|
|
type ref struct { |
|
Ref string `json:"$ref"` |
|
} |
|
|
|
func (d doc) toDocument() Document { |
|
gDoc := Document{ |
|
Title: d.Title, |
|
Description: d.Description, |
|
Version: d.Version, |
|
} |
|
for name, s := range d.Schemas { |
|
s.ID = name |
|
gDoc.Models = append(gDoc.Models, s.toSchema()) |
|
} |
|
|
|
for object, methods := range d.Resources { |
|
for action, r := range methods.Methods { |
|
gDoc.Paths = append(gDoc.Paths, r.toPath(d, object, action)) |
|
} |
|
} |
|
|
|
sort.Sort(byPath(gDoc.Paths)) |
|
sort.Sort(byName(gDoc.Models)) |
|
return gDoc |
|
} |
|
|
|
func (s schema) toSchema() Schema { |
|
sch := Schema{ |
|
Name: s.ID, |
|
Type: s.Type, |
|
Description: s.Description, |
|
Ref: s.Ref, |
|
} |
|
for name, prop := range s.Properties { |
|
c := prop.toSchema() |
|
c.Name = name |
|
sch.Children = append(sch.Children, c) |
|
} |
|
if s.Items != nil { |
|
sch.Children = []Schema{s.Items.toSchema()} |
|
} |
|
sort.Sort(byName(sch.Children)) |
|
return sch |
|
} |
|
|
|
func (r resource) toPath(d doc, object, action string) Path { |
|
p := Path{ |
|
Method: r.Method, |
|
Path: path.Join("/", r.Path), |
|
Summary: strings.TrimSpace(action + " " + object), |
|
Description: r.Description, |
|
} |
|
for name, param := range r.Parameters { |
|
p.Parameters = append(p.Parameters, Parameter{ |
|
Name: name, |
|
LocatedIn: param.Location, |
|
Required: param.Required, |
|
Type: param.Type, |
|
}) |
|
} |
|
if r.Request != nil { |
|
ref := r.Request.Ref |
|
p.Parameters = append(p.Parameters, Parameter{ |
|
LocatedIn: "body", |
|
Required: true, |
|
Type: ref, |
|
}) |
|
} |
|
if r.Response != nil { |
|
p.Responses = append(p.Responses, Response{ |
|
Code: 200, |
|
Type: r.Response.Ref, |
|
}) |
|
} |
|
p.Responses = append(p.Responses, Response{ |
|
Code: CodeDefault, |
|
Description: "Unexpected error", |
|
}) |
|
return p |
|
}
|
|
|