Add swagger and spec finder

This commit is contained in:
Melon 2022-09-08 17:22:22 +01:00
parent f2eea7a1e7
commit 52ef284562
Signed by: melon
GPG Key ID: B0ADD5395BCDAAB6
20 changed files with 275 additions and 36 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

View File

@ -0,0 +1,16 @@
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
margin: 0;
background: #fafafa;
}

View File

@ -0,0 +1,19 @@
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
<link rel="stylesheet" type="text/css" href="index.css" />
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
<script src="./swagger-initializer.js" charset="UTF-8"> </script>
</body>
</html>

View File

@ -0,0 +1,79 @@
<!doctype html>
<html lang="en-US">
<head>
<title>Swagger UI: OAuth2 Redirect</title>
</head>
<body>
<script>
'use strict';
function run () {
var oauth2 = window.opener.swaggerUIRedirectOauth2;
var sentState = oauth2.state;
var redirectUrl = oauth2.redirectUrl;
var isValid, qp, arr;
if (/code|token|error/.test(window.location.hash)) {
qp = window.location.hash.substring(1).replace('?', '&');
} else {
qp = location.search.substring(1);
}
arr = qp.split("&");
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
qp = qp ? JSON.parse('{' + arr.join() + '}',
function (key, value) {
return key === "" ? value : decodeURIComponent(value);
}
) : {};
isValid = qp.state === sentState;
if ((
oauth2.auth.schema.get("flow") === "accessCode" ||
oauth2.auth.schema.get("flow") === "authorizationCode" ||
oauth2.auth.schema.get("flow") === "authorization_code"
) && !oauth2.auth.code) {
if (!isValid) {
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "warning",
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
});
}
if (qp.code) {
delete oauth2.state;
oauth2.auth.code = qp.code;
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
} else {
let oauthErrorMsg;
if (qp.error) {
oauthErrorMsg = "["+qp.error+"]: " +
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
(qp.error_uri ? "More info: "+qp.error_uri : "");
}
oauth2.errCb({
authId: oauth2.auth.name,
source: "auth",
level: "error",
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
});
}
} else {
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
}
window.close();
}
if (document.readyState !== 'loading') {
run();
} else {
document.addEventListener('DOMContentLoaded', function () {
run();
});
}
</script>
</body>
</html>

View File

@ -0,0 +1,26 @@
window.onload = function() {
//<editor-fold desc="Changeable Configuration Block">
// the following lines will be replaced by docker/configurator, when it runs in a docker-container
window.ui = SwaggerUIBundle({
urls: [
{url: "spec/mailbox.yml", name: "Mailbox"},
{url: "spec/mailmaster.yml", name: "Mail Master"},
{url: "spec/mailconfig.yml", name: "Mail Config"},
{url: "spec/nginxconfig.yml", name: "NGINX Config"},
],
"urls.primaryName": "NGINX Config", // default document (if other than the first)
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
//</editor-fold>
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -13,6 +13,7 @@ import (
"html/template"
"net/http"
"os"
"path/filepath"
"strings"
)
@ -86,43 +87,58 @@ func (m *Module) homepage(rw http.ResponseWriter, req *http.Request, state *util
}
selOrg := ""
myOrg := ""
repoSimple := make([]struct{ Name string }, 0)
repoSimple := make([]struct {
Name string
Private bool
}, 0)
selRepo := ""
selModule := ""
selCommitTime := ""
selCommitHash := ""
mySpecs := make([]string, 0)
q := req.URL.Query()
if q.Has("org") {
selOrg = q.Get("org")
var repos []*gitea.Repository
if selOrg == "$me" {
if selOrg == "!me" {
myOrg = myUser.UserName
repos, _, err = giteaClient.ListMyRepos(gitea.ListReposOptions{ListOptions: gitea.ListOptions{Page: 0, PageSize: 100}})
repos, _, err = giteaClient.ListMyRepos(gitea.ListReposOptions{ListOptions: gitea.ListOptions{Page: 0, PageSize: 50}})
} else {
myOrg = selOrg
repos, _, err = giteaClient.ListOrgRepos(myOrg, gitea.ListOrgReposOptions{ListOptions: gitea.ListOptions{Page: 0, PageSize: 100}})
repos, _, err = giteaClient.ListOrgRepos(myOrg, gitea.ListOrgReposOptions{ListOptions: gitea.ListOptions{Page: 0, PageSize: 50}})
}
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
repoSimple = make([]struct{ Name string }, len(repos))
repoSimple = make([]struct {
Name string
Private bool
}, len(repos))
for i, j := range repos {
repoSimple[i] = struct{ Name string }{Name: j.Name}
repoSimple[i] = struct {
Name string
Private bool
}{Name: j.Name, Private: j.Private}
}
if q.Has("repo") {
selRepo = q.Get("repo")
repo, _, err := giteaClient.GetRepo(myOrg, selRepo)
repo, resp, err := giteaClient.GetRepo(myOrg, selRepo)
if err != nil {
http.Error(rw, "GetRepo: "+err.Error(), http.StatusInternalServerError)
return
if resp.StatusCode != http.StatusNotFound {
http.Error(rw, "GetRepo: "+err.Error(), http.StatusInternalServerError)
return
}
}
refs, _, err := giteaClient.GetRepoRefs(myOrg, selRepo, "heads/"+repo.DefaultBranch)
refs, resp, err := giteaClient.GetRepoRefs(myOrg, selRepo, "heads/"+repo.DefaultBranch)
if err != nil {
http.Error(rw, "GetRepoRefs: "+err.Error(), http.StatusInternalServerError)
return
if resp.StatusCode != http.StatusNotFound {
http.Error(rw, "GetRepoRefs: "+err.Error(), http.StatusInternalServerError)
return
}
refs = make([]*gitea.Reference, 0)
}
if len(refs) == 1 {
ref := refs[0]
@ -131,18 +147,51 @@ func (m *Module) homepage(rw http.ResponseWriter, req *http.Request, state *util
http.Error(rw, "GetSingleCommit: "+err.Error(), http.StatusInternalServerError)
return
}
if q.Has("spec") {
spec := q.Get("spec")
specFile, _, err := giteaClient.GetFile(myOrg, selRepo, ref.Object.SHA, spec)
if err != nil {
http.Error(rw, "OpenAPI spec: "+err.Error(), http.StatusInternalServerError)
return
}
rw.Header().Set("Content-Type", "text/html")
rw.WriteHeader(http.StatusOK)
_, _ = fmt.Fprintf(rw, "Showing spec file: '%s'\n", spec)
_, _ = fmt.Fprintf(rw, "\n<pre><code>\n")
_, _ = rw.Write(specFile)
_, _ = fmt.Fprintf(rw, "\n</code></pre>\n")
return
}
selCommitTime = commit.CommitMeta.Created.UTC().Format("20060102150405")
selCommitHash = commit.CommitMeta.SHA[:12]
goMod, _, err := giteaClient.GetFile(myOrg, selRepo, ref.Object.SHA, "go.mod")
goMod, resp, err := giteaClient.GetFile(myOrg, selRepo, ref.Object.SHA, "go.mod")
if err != nil {
http.Error(rw, "go.mod: "+err.Error(), http.StatusInternalServerError)
return
if resp.StatusCode != http.StatusNotFound {
http.Error(rw, "go.mod: "+err.Error(), http.StatusInternalServerError)
return
}
}
goModStr := string(goMod)
goModIdx := strings.Index(goModStr, "\n")
goModLine := goModStr[:goModIdx]
goModSpace := strings.Index(goModLine, " ")
selModule = goModLine[goModSpace+1:]
trees, resp, err := giteaClient.GetTrees(myOrg, selRepo, ref.Object.SHA, true)
if err != nil {
if resp.StatusCode != http.StatusNotFound {
http.Error(rw, "%s: "+err.Error(), http.StatusInternalServerError)
return
}
}
for i := range trees.Entries {
switch filepath.Ext(trees.Entries[i].Path) {
case ".yml", ".yaml":
mySpecs = append(mySpecs, trees.Entries[i].Path)
}
}
}
}
}
@ -153,27 +202,36 @@ func (m *Module) homepage(rw http.ResponseWriter, req *http.Request, state *util
return
}
err = tmp.Execute(rw, struct {
Username string
Orgs []struct{ Name string }
Repos []struct{ Name string }
Username string
Orgs []struct{ Name string }
Repos []struct {
Name string
Private bool
}
MyOrg string
SelOrg string
SelRepo string
ShowOrg bool
SelModule string
ShowRepo bool
CommitTime string
CommitHash string
ShowSpec bool
Specs []string
}{
Username: myUser.UserName,
Orgs: orgSimple,
Repos: repoSimple,
MyOrg: myOrg,
SelOrg: selOrg,
SelRepo: selRepo,
SelModule: selModule,
ShowOrg: myOrg != "",
ShowRepo: selModule != "",
CommitTime: selCommitTime,
CommitHash: selCommitHash,
ShowSpec: len(mySpecs) > 0,
Specs: mySpecs,
})
if err != nil {
fmt.Println("Template execute error:", err)

View File

@ -28,32 +28,49 @@
<p>Select repository source:</p>
<ul>
<li>
<a href="?org=$me">{{.Username}} (my user account)</a>
<a href="?org=!me">{{.Username}} (my user account)</a>
</li>
{{range .Orgs}}
<li>
<a href="?org={{.Name}}">{{.Name}}</a>
</li>
<li>
<a href="?org={{.Name}}">{{.Name}}</a>
</li>
{{end}}
</ul>
</div>
{{if .ShowOrg}}
<div>
<p>Select repository:</p>
<ul>
{{range .Repos}}
<li>
<a href="?org={{$.SelOrg}}&repo={{.Name}}">{{$.MyOrg}}/{{.Name}}</a>
</li>
{{end}}
</ul>
</div>
<div>
<p>Select repository:</p>
<ul>
{{range .Repos}}
<li>
<a href="?org={{$.SelOrg}}&repo={{.Name}}">
<span>{{$.MyOrg}}/{{.Name}}</span>
{{if .Private}}
<span> (private)</span>
{{end}}
</a>
</li>
{{end}}
</ul>
</div>
{{end}}
{{if .ShowRepo}}
<div>
<p>Repository details:</p>
<p>Go import: go get {{.SelModule}}@v0.0.0-{{.CommitTime}}-{{.CommitHash}}</p>
</div>
<div>
<p>Repository details:</p>
<p>Go import: go get {{.SelModule}}@v0.0.0-{{.CommitTime}}-{{.CommitHash}}</p>
</div>
{{end}}
{{if .ShowSpec}}
<div>
<p>OpenAPI specs:</p>
<ul>
{{range .Specs}}
<li>
<a href="?org={{$.SelOrg}}&repo={{$.SelRepo}}&spec={{.}}" target="_blank">{{.}}</a>
</li>
{{end}}
</ul>
</div>
{{end}}
</div>
</body>