Skip to content

Commit

Permalink
Add support for ignoring snippets everywhere
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Sep 9, 2024
1 parent 86931c9 commit f870b19
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 27 deletions.
4 changes: 4 additions & 0 deletions assets/vue/EditSnippet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@
<span v-if="this.hash !== null && this.from !== null">
<button name="create-ignore" type="submit" value="1" class="btn btn-danger mb-2">Ignore Pattern</button>
&nbsp;
<button name="mark-non-license" type="submit" value="1" class="btn btn-primary mb-2">
Not a License
</button>
&nbsp; &nbsp; &nbsp;
</span>
</span>
<button
Expand Down
28 changes: 24 additions & 4 deletions assets/vue/ProposedPatterns.vue
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,23 @@
<div v-else-if="change.action === 'create_ignore'">
<div class="row">
<div class="col mb-3">
<label class="fomr-label" for="license">Package</label>
<input v-model="change.data.from" type="text" class="form-control" />
<label class="form-label" for="license">Package</label>
<div class="d-flex form-check align-items-center form-check">
<input
class="form-check-input"
id="ignore-one"
type="checkbox"
name="ignore-for"
value="one"
v-model="ignoreForPackage"
/>
<input
v-model="change.data.from"
type="text"
class="form-control ms-2"
:disabled="!ignoreForPackage"
/>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -144,6 +159,7 @@ export default {
name: 'RecentChanges',
data() {
return {
ignoreForPackage: true,
params: {before: 0},
changes: null,
changeUrl: '/licenses/proposed/meta',
Expand Down Expand Up @@ -172,9 +188,13 @@ export default {
form['create-pattern'] = 1;
form.checksum = change.token_hexsum;
} else if (change.action === 'create_ignore') {
form['create-ignore'] = 1;
form.hash = change.token_hexsum;
form.from = change.data.from;
if (this.ignoreForPackage === true) {
form['create-ignore'] = 1;
form.from = change.data.from;
} else {
form['mark-non-license'] = 1;
}
}
await ua.post(change.createUrl, {form});
Expand Down
54 changes: 37 additions & 17 deletions lib/Cavil/Controller/Snippet.pm
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use Mojo::File qw(path);
use Cavil::Util qw(pattern_matches);
use Mojo::JSON qw(true false);

my $CHECKSUM_RE = qr/^(?:[a-f0-9]{32}|manual[\w:-]+)$/i;

sub approve ($self) {
my $v = $self->validation;
$v->required('license')->in('true', 'false');
Expand All @@ -28,7 +30,6 @@ sub approve ($self) {

my $id = $self->param('id');
$self->snippets->approve($id, $license);

my $user = $self->session('user');
$self->app->log->info(qq{Snippet $id approved by $user (License: $license))});

Expand Down Expand Up @@ -66,15 +67,11 @@ sub decision ($self) {
$validation->optional('mark-non-license');
return $self->reply->json_validation_error if $validation->has_error;

my $id = $self->param('id');
my $snippets = $self->snippets;
my $packages = $snippets->packages_for_snippet($id);

# Only admins can create patterns or ignore snippets directly
my $is_admin = $self->current_user_has_role('admin');
if ($validation->param('create-pattern')) {
return $self->render('permissions', status => 403) unless $is_admin;
$self->_create_pattern($packages, $validation);
$self->_create_pattern;
}

elsif ($validation->param('create-ignore')) {
Expand All @@ -84,13 +81,11 @@ sub decision ($self) {

elsif ($validation->param('mark-non-license')) {
return $self->render('permissions', status => 403) unless $is_admin;
$snippets->mark_non_license($id);
$self->packages->analyze($_, 4) for @$packages;
$self->render(packages => $packages);
$self->_mark_non_license;
}

elsif ($validation->param('propose-pattern')) { $self->_propose_pattern($validation) }
elsif ($validation->param('propose-ignore')) { $self->_propose_ignore($validation) }
elsif ($validation->param('propose-pattern')) { $self->_propose_pattern }
elsif ($validation->param('propose-ignore')) { $self->_propose_ignore }

else { $self->reply->not_found }
}
Expand All @@ -101,7 +96,7 @@ sub edit ($self) {

sub from_file ($self) {
my $v = $self->validation;
$v->optional('hash')->like(qr/^(?:[a-f0-9]{32}|manual[\w:-]+)$/i);
$v->optional('hash')->like($CHECKSUM_RE);
$v->optional('from');
return $self->reply->json_validation_error if $v->has_error;

Expand Down Expand Up @@ -168,7 +163,8 @@ sub meta ($self) {
$self->render(json => {snippet => $snippet, licenses => $licenses, closest => $pattern->{license}});
}

sub _create_pattern ($self, $packages, $validation) {
sub _create_pattern ($self) {
my $validation = $self->validation;
$validation->required('license');
$validation->required('pattern', 'not_empty');
$validation->required('risk')->num;
Expand All @@ -180,6 +176,8 @@ sub _create_pattern ($self, $packages, $validation) {
$validation->optional('delay')->num;
return $self->reply->json_validation_error if $validation->has_error;

my $packages = $self->snippets->packages_for_snippet($self->stash('id'));

my $owner_id = $self->users->id_for_login($self->current_user);
my $contributor = $validation->param('contributor');
my $contributor_id = $contributor ? $self->users->id_for_login($contributor) : undef;
Expand All @@ -206,7 +204,7 @@ sub _create_pattern ($self, $packages, $validation) {

sub _create_ignore ($self) {
my $validation = $self->validation;
$validation->required('hash', 'not_empty')->like(qr/^(?:[a-f0-9]{32}|manual[\w:-]+)$/i);
$validation->required('hash', 'not_empty')->like($CHECKSUM_RE);
$validation->required('from', 'not_empty');
$validation->optional('delay')->num;
$validation->optional('contributor');
Expand All @@ -232,7 +230,28 @@ sub _create_ignore ($self) {
return $self->render(ignore => 1);
}

sub _propose_pattern ($self, $validation) {
sub _mark_non_license ($self) {
my $validation = $self->validation;
$validation->required('hash')->like($CHECKSUM_RE);
$validation->optional('delay')->num;
return $self->reply->json_validation_error if $validation->has_error;

my $delay = $validation->param('delay') // 0;
my $hash = $validation->param('hash');
my $snippets = $self->snippets;
return $self->reply->not_found unless my $id = $snippets->id_for_checksum($hash);

$self->patterns->remove_proposal($hash);
$snippets->mark_non_license($id);

my $packages = $snippets->packages_for_snippet($id);
$self->packages->reindex($_, 3, [], $delay) for @$packages;

$self->render(packages => $packages);
}

sub _propose_pattern ($self) {
my $validation = $self->validation;
$validation->required('license');
$validation->required('pattern', 'not_empty');
$validation->required('risk')->num;
Expand Down Expand Up @@ -277,8 +296,9 @@ sub _propose_pattern ($self, $validation) {
$self->render(proposal => 1);
}

sub _propose_ignore ($self, $validation) {
$validation->required('hash', 'not_empty')->like(qr/^(?:[a-f0-9]{32}|manual[\w:-]+)$/i);
sub _propose_ignore ($self) {
my $validation = $self->validation;
$validation->required('hash', 'not_empty')->like($CHECKSUM_RE);
$validation->required('from', 'not_empty');
$validation->required('pattern', 'not_empty');
$validation->required('edited', 'not_empty');
Expand Down
11 changes: 8 additions & 3 deletions lib/Cavil/Model/Snippets.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ use Spooky::Patterns::XS;

has [qw(checkout_dir pg)];

sub approve ($self, $id, $license) {
my $db = $self->pg->db;
$db->update('snippets', {license => $license eq 'true' ? 1 : 0, approved => 1, classified => 1}, {id => $id});
}

sub find ($self, $id) {
return $self->pg->db->select('snippets', '*', {id => $id})->hash;
}
Expand Down Expand Up @@ -55,9 +60,9 @@ sub from_file ($self, $file_id, $first_line, $last_line) {
return $snippet_id;
}

sub approve ($self, $id, $license) {
my $db = $self->pg->db;
$db->update('snippets', {license => $license eq 'true' ? 1 : 0, approved => 1, classified => 1}, {id => $id});
sub id_for_checksum ($self, $checksum) {
return undef unless my $hash = $self->pg->db->select('snippets', 'id', {hash => $checksum})->hash;
return $hash->{id};
}

sub unclassified ($self, $options) {
Expand Down
4 changes: 2 additions & 2 deletions t/classifier.t
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ subtest 'Classified manually' => sub {
is $snippet->{license}, 0, 'license';

$t->get_ok('/login')->status_is(302);
$t->post_ok('/snippet/decision/2?mark-non-license=1')->status_is(200);
$t->post_ok('/snippet/decision/2?mark-non-license=1&hash=3c376fca10ff8a41d0d51c9d46a3bdae')->status_is(200);

$snippet = $t->app->pg->db->select('snippets', '*', {id => 1})->hash;
is $snippet->{id}, 1, 'right id';
Expand All @@ -114,7 +114,7 @@ subtest 'Classified manually' => sub {
is $snippet->{classified}, 1, 'classified';
is $snippet->{license}, 0, 'license';

$t->post_ok('/snippet/decision/1?mark-non-license=1')->status_is(200);
$t->post_ok('/snippet/decision/1?mark-non-license=1&hash=81efb065de14988c4bd808697de1df51')->status_is(200);
$snippet = $t->app->pg->db->select('snippets', '*', {id => 1})->hash;
is $snippet->{id}, 1, 'right id';
is $snippet->{classified}, 1, 'classified';
Expand Down
24 changes: 23 additions & 1 deletion t/proposal.t
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ subtest 'Pattern creation' => sub {
edited => 0
}
)->status_is(403);
$t->post_ok('/snippet/decision/1' => form => {'mark-non-license' => 1})->status_is(403);
$t->post_ok('/snippet/decision/1' => form => {'mark-non-license' => 1, hash => '39e8204ddebdc31a4d0e77aa647f4241'})
->status_is(403);

$t->app->users->add_role(2, 'contributor');
$t->post_ok('/snippet/decision/1' => form =>
Expand Down Expand Up @@ -188,6 +189,27 @@ subtest 'Pattern creation' => sub {
is $ignore->{contributor}, 2, 'right contributor';
};

subtest 'From proposal to not a license snippet' => sub {
is $t->app->pg->db->query('SELECT * FROM snippets WHERE id = 3')->hash->{classified}, 0, 'not classified';
my $form = {
'propose-ignore' => 1,
hash => '399908965a4311ddd48a9440a66365e0',
from => 'perl-Mojolicious',
pattern => "Now complex: The license might",
edited => 0,
'highlighted-keywords' => 1,
'highlighted-licenses' => 0
};
$t->post_ok('/snippet/decision/1' => form => $form)->status_is(200)
->content_like(qr/Your change has been proposed/);
$t->get_ok('/licenses/proposed/meta')->status_is(200)->json_has('/changes/0');

my $ignore_form = {'mark-non-license' => 1, hash => '399908965a4311ddd48a9440a66365e0'};
$t->post_ok('/snippet/decision/1' => form => $ignore_form)->status_is(200)->content_like(qr/Reindexing 1 package/);
is $t->app->pg->db->query('SELECT * FROM snippets WHERE id = 3')->hash->{classified}, 1, 'classified';
$t->get_ok('/licenses/proposed/meta')->status_is(200)->json_hasnt('/changes/0');
};

subtest 'Pattern performance' => sub {
$t->get_ok('/licenses/recent/meta')->status_is(200)->json_is('/patterns/0/id', 5)
->json_is('/patterns/0/pattern', "The license might be\nsomething cool")
Expand Down

0 comments on commit f870b19

Please sign in to comment.