mirror of
https://github.com/genuinetools/reg.git
synced 2024-09-28 11:46:20 -04:00
Merge pull request #1 from mwindower/dynamic-frontend
Load BadVulns count with AJAX calls
This commit is contained in:
commit
4a8066c14d
4 changed files with 141 additions and 22 deletions
|
@ -194,7 +194,7 @@ td {
|
||||||
td:last-child,
|
td:last-child,
|
||||||
th:last-child {
|
th:last-child {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding-right: 0px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
td a {
|
td a {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -205,6 +205,38 @@ tr.parent a {
|
||||||
.parent a:hover {
|
.parent a:hover {
|
||||||
color: #2a2a2a;
|
color: #2a2a2a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*------------------------------------*\
|
||||||
|
Loading Indicator
|
||||||
|
\*------------------------------------*/
|
||||||
|
.signal {
|
||||||
|
border: 2px solid #333;
|
||||||
|
border-radius: 15px;
|
||||||
|
height: 15px;
|
||||||
|
left: 50%;
|
||||||
|
margin: -8px 0 0 -8px;
|
||||||
|
opacity: 0;
|
||||||
|
top: 50%;
|
||||||
|
width: 15px;
|
||||||
|
float: right;
|
||||||
|
animation: pulsate 1s ease-out;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulsate {
|
||||||
|
0% {
|
||||||
|
transform: scale(.1);
|
||||||
|
opacity: 0.0;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1.2);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------*\
|
/*------------------------------------*\
|
||||||
Footer
|
Footer
|
||||||
\*------------------------------------*/
|
\*------------------------------------*/
|
||||||
|
|
|
@ -35,6 +35,24 @@ function search(search_val){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadVulnerabilityCount(url){
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', url);
|
||||||
|
xhr.onload = function() {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
var report = JSON.parse(xhr.responseText);
|
||||||
|
var id = report.Repo + ':' + report.Tag;
|
||||||
|
var element = document.getElementById(id);
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
element.innerHTML = report.BadVulns;
|
||||||
|
} else {
|
||||||
|
console.log("element not found for given id ", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
var el = document.querySelectorAll('tr:nth-child(2)')[0].querySelectorAll('td:nth-child(2)')[0];
|
var el = document.querySelectorAll('tr:nth-child(2)')[0].querySelectorAll('td:nth-child(2)')[0];
|
||||||
if (el.textContent == 'Parent Directory'){
|
if (el.textContent == 'Parent Directory'){
|
||||||
|
@ -72,22 +90,26 @@ our_table.setAttribute('id', 'directory');
|
||||||
var search_input = document.querySelectorAll('input[name="filter"]')[0];
|
var search_input = document.querySelectorAll('input[name="filter"]')[0];
|
||||||
var clear_button = document.querySelectorAll('a.clear')[0];
|
var clear_button = document.querySelectorAll('a.clear')[0];
|
||||||
|
|
||||||
if (search_input.value !== ''){
|
if (search_input) {
|
||||||
search(search_input.value);
|
if (search_input.value !== ''){
|
||||||
|
search(search_input.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
search_input.addEventListener('keyup', function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
search(search_input.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
search_input.addEventListener('keypress', function(e){
|
||||||
|
if ( e.which == 13 ) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
search_input.addEventListener('keyup', function(e){
|
if (clear_button) {
|
||||||
e.preventDefault();
|
clear_button.addEventListener('click', function(e){
|
||||||
search(search_input.value);
|
search_input.value = '';
|
||||||
});
|
search('');
|
||||||
|
});
|
||||||
search_input.addEventListener('keypress', function(e){
|
}
|
||||||
if ( e.which == 13 ) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
clear_button.addEventListener('click', function(e){
|
|
||||||
search_input.value = '';
|
|
||||||
search('');
|
|
||||||
});
|
|
||||||
|
|
|
@ -37,9 +37,9 @@
|
||||||
<td align="right" nowrap>
|
<td align="right" nowrap>
|
||||||
{{ $value.Created.Format "02 Jan, 2006 15:04:05 UTC" }}
|
{{ $value.Created.Format "02 Jan, 2006 15:04:05 UTC" }}
|
||||||
</td>
|
</td>
|
||||||
<td >
|
<td align="right" nowrap>
|
||||||
<a href="/repo/{{ $value.Name | urlquery }}/{{ $value.Tag }}/vulns">
|
<a href="/repo/{{ $value.Name | urlquery }}/{{ $value.Tag }}/vulns" id="{{ $value.Name }}:{{ $value.Tag }}">
|
||||||
{{ $value.VulnerabilityReport.BadVulns }}
|
<div class="signal"></div>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -51,6 +51,18 @@
|
||||||
<a href="https://twitter.com/jessfraz">@jessfraz</a>
|
<a href="https://twitter.com/jessfraz">@jessfraz</a>
|
||||||
</div><!--/.footer-->
|
</div><!--/.footer-->
|
||||||
<script src="/js/scripts.js"></script>
|
<script src="/js/scripts.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var ajaxCalls = [
|
||||||
|
{{ range $key, $value := .Repositories }}
|
||||||
|
'/repo/{{ $value.Name | urlquery }}/{{ $value.Tag }}/report',
|
||||||
|
{{ end }}
|
||||||
|
];
|
||||||
|
window.onload = function() {
|
||||||
|
Array.prototype.forEach.call(ajaxCalls, function(url, index){
|
||||||
|
loadVulnerabilityCount(url);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
|
|
@ -103,6 +103,7 @@ func listenAndServe(port, keyfile, certfile string, r *registry.Registry, c *cla
|
||||||
e.GET("/repo/:repo", rc.tags)
|
e.GET("/repo/:repo", rc.tags)
|
||||||
e.GET("/repo/:repo/:tag", rc.tag)
|
e.GET("/repo/:repo/:tag", rc.tag)
|
||||||
e.GET("/repo/:repo/:tag/vulns", rc.vulnerabilities)
|
e.GET("/repo/:repo/:tag/vulns", rc.vulnerabilities)
|
||||||
|
e.GET("/repo/:repo/:tag/report", rc.report)
|
||||||
|
|
||||||
srv := &http.Server{
|
srv := &http.Server{
|
||||||
Addr: ":" + port,
|
Addr: ":" + port,
|
||||||
|
@ -260,6 +261,58 @@ func (rc *registryController) tags(c echo.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rc *registryController) report(c echo.Context) error {
|
||||||
|
repo, err := url.QueryUnescape(c.Param("repo"))
|
||||||
|
if err != nil {
|
||||||
|
return c.String(http.StatusNotFound, "Given repo can not be unescaped.")
|
||||||
|
}
|
||||||
|
if repo == "" {
|
||||||
|
return c.String(http.StatusNotFound, "No repo given")
|
||||||
|
}
|
||||||
|
tag := c.Param("tag")
|
||||||
|
if tag == "" {
|
||||||
|
return c.String(http.StatusNotFound, "No tag given")
|
||||||
|
}
|
||||||
|
|
||||||
|
m1, err := r.ManifestV1(repo, tag)
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"error": err,
|
||||||
|
"repo": repo,
|
||||||
|
"tag": tag,
|
||||||
|
}).Warn("getting v1 manifest failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, h := range m1.History {
|
||||||
|
var comp v1Compatibility
|
||||||
|
if err := json.Unmarshal([]byte(h.V1Compatibility), &comp); err != nil {
|
||||||
|
msg := "unmarshal v1compatibility failed"
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"error": err,
|
||||||
|
"repo": repo,
|
||||||
|
"tag": tag,
|
||||||
|
}).Warn(msg)
|
||||||
|
return c.String(http.StatusInternalServerError, msg)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
result := clair.VulnerabilityReport{}
|
||||||
|
|
||||||
|
if rc.cl != nil {
|
||||||
|
result, err = rc.cl.Vulnerabilities(rc.reg, repo, tag, m1)
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(log.Fields{
|
||||||
|
"error": err,
|
||||||
|
"repo": repo,
|
||||||
|
"tag": tag,
|
||||||
|
}).Error("error during vulnerability scanning.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(http.StatusOK, result)
|
||||||
|
}
|
||||||
|
|
||||||
func (rc *registryController) vulnerabilities(c echo.Context) error {
|
func (rc *registryController) vulnerabilities(c echo.Context) error {
|
||||||
repo, err := url.QueryUnescape(c.Param("repo"))
|
repo, err := url.QueryUnescape(c.Param("repo"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue