File tree Expand file tree Collapse file tree 6 files changed +120
-0
lines changed Expand file tree Collapse file tree 6 files changed +120
-0
lines changed Original file line number Diff line number Diff line change @@ -106,6 +106,10 @@ export default class CrateHeader extends Component {
106106 Dependents
107107 </nav.Tab >
108108
109+ <nav.Tab @ link ={{link_ ' crate.security' @ crate }} data-test-security-tab >
110+ Security
111+ </nav.Tab >
112+
109113 {{#if this . isOwner }}
110114 <nav.Tab @ link ={{link_ ' crate.settings' @ crate}} data-test-settings-tab >
111115 Settings
Original file line number Diff line number Diff line change 1+ import Controller from '@ember/controller' ;
2+ import { service } from '@ember/service' ;
3+ import { tracked } from '@glimmer/tracking' ;
4+
5+ import { didCancel , dropTask } from 'ember-concurrency' ;
6+
7+ import { AjaxError } from '../../utils/ajax' ;
8+
9+ export default class SearchController extends Controller {
10+ @service releaseTracks ;
11+ @service sentry ;
12+
13+ @tracked crate ;
14+ @tracked data ;
15+
16+ constructor ( ) {
17+ super ( ...arguments ) ;
18+ this . reset ( ) ;
19+ }
20+
21+ loadMoreTask = dropTask ( async ( ) => {
22+ let { crate, data } = this ;
23+ let url = `https://rustsec.org/packages/${ crate . id } .json` ;
24+
25+ try {
26+ let response = await fetch ( url ) ;
27+ if ( response . status === 404 ) {
28+ this . data = [ ] ;
29+ } else if ( ! response . ok ) {
30+ throw new Error ( `HTTP error! status: ${ response } ` ) ;
31+ } else {
32+ this . data = await response . json ( ) ;
33+ }
34+ } catch ( error ) {
35+ // report unexpected errors to Sentry and ignore `ajax()` errors
36+ if ( ! didCancel ( error ) && ! ( error instanceof AjaxError ) ) {
37+ this . sentry . captureException ( error ) ;
38+ }
39+ }
40+ } ) ;
41+
42+ reset ( ) {
43+ this . crate = undefined ;
44+ this . data = undefined ;
45+ }
46+ }
Original file line number Diff line number Diff line change @@ -18,6 +18,7 @@ Router.map(function () {
1818 this . route ( 'range' , { path : '/range/:range' } ) ;
1919
2020 this . route ( 'reverse-dependencies' , { path : 'reverse_dependencies' } ) ;
21+ this . route ( 'security' , { path : 'security' } ) ;
2122
2223 this . route ( 'owners' ) ;
2324 this . route ( 'settings' , function ( ) {
Original file line number Diff line number Diff line change 1+ import Route from '@ember/routing/route' ;
2+ import { waitForPromise } from '@ember/test-waiters' ;
3+
4+ export default class SecurityRoute extends Route {
5+ queryParams = {
6+ sort : { refreshModel : true } ,
7+ } ;
8+
9+ model ( params ) {
10+ // we need a model() implementation that changes, otherwise the setupController() hook
11+ // is not called and we won't reload the results if a new query string is used
12+ return params ;
13+ }
14+
15+ setupController ( controller ) {
16+ super . setupController ( ...arguments ) ;
17+ let crate = this . modelFor ( 'crate' ) ;
18+ // reset when crate changes
19+ if ( crate && crate !== controller . crate ) {
20+ controller . reset ( ) ;
21+ }
22+ controller . set ( 'crate' , crate ) ;
23+ if ( controller . data === undefined ) {
24+ waitForPromise ( controller . loadMoreTask . perform ( ) ) ;
25+ }
26+ }
27+ }
Original file line number Diff line number Diff line change 1+ .heading {
2+ font-size : 1.17em ;
3+ margin-block-start : 1em ;
4+ margin-block-end : 1em ;
5+ }
6+
7+ .advisories {
8+ list-style : none;
9+ margin : 0 ;
10+ padding : 0 ;
11+ }
12+
13+ .row {
14+ margin-top : var (--space-2xs );
15+ background-color : light-dark (white, # 141413 );
16+ padding : var (--space-m ) var (--space-l );
17+ list-style : none;
18+ }
Original file line number Diff line number Diff line change 1+ import CrateHeader from ' crates-io/components/crate-header' ;
2+ import RenderedHtml from ' crates-io/components/rendered-html' ;
3+
4+ <template >
5+ <CrateHeader @ crate ={{@ controller.crate }} />
6+ {{#if @ controller.model }}
7+ <h2 class =' heading' >Advisories</h2 >
8+ <ul class =' advisories' data-test-list >
9+ {{#each @ controller.data as | advisory | }}
10+ <li class =' row' >
11+ <h3 >
12+ <a href =" https://rustsec.org/advisories/{{ advisory.id }} .html" >{{ advisory.id }} </a >:
13+ {{ advisory.summary }}
14+ </h3 >
15+ <p >{{ advisory.details }} </p >
16+ </li >
17+ {{/each }}
18+ </ul >
19+ {{else }}
20+ <div class =' no-results' >
21+ No advisories found for this crate.
22+ </div >
23+ {{/if }}
24+ </template >
You can’t perform that action at this time.
0 commit comments