X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2Fstemmaweb%2FController%2FRelation.pm;h=89a7d23781e4d4c36bcbab077dce6ca737c025af;hb=2be76d3f155342740db9bf4653059c0cb119c2e6;hp=22a1d0701a7654b3cb04133fffbaad4491eabc0d;hpb=19f0f822616e0e8c160392dda4452a11b17444d6;p=scpubgit%2Fstemmaweb.git diff --git a/lib/stemmaweb/Controller/Relation.pm b/lib/stemmaweb/Controller/Relation.pm index 22a1d07..89a7d23 100644 --- a/lib/stemmaweb/Controller/Relation.pm +++ b/lib/stemmaweb/Controller/Relation.pm @@ -64,6 +64,11 @@ sub text :Chained('/') :PathPart('relation') :CaptureArgs(1) { $tradition->collation->_set_tradition( $tradition ); $c->model('Directory')->save( $tradition ); } + # Check permissions. Will return 403 if denied, otherwise will + # put the appropriate value in the stash. + my $ok = _check_permission( $c, $tradition ); + return unless $ok; + # See how big the tradition is. Edges are more important than nodes # when it comes to rendering difficulty. my $numnodes = scalar $tradition->collation->readings; @@ -172,6 +177,8 @@ success or 403 on error. sub relationships :Chained('text') :PathPart :Args(0) { my( $self, $c ) = @_; my $tradition = delete $c->stash->{'tradition'}; + my $ok = _check_permission( $c, $tradition ); + return unless $ok; my $collation = $tradition->collation; my $m = $c->model('Directory'); if( $c->request->method eq 'GET' ) { @@ -187,37 +194,50 @@ sub relationships :Chained('text') :PathPart :Args(0) { push( @all_relations, $relhash ); } $c->stash->{'result'} = \@all_relations; - } elsif( $c->request->method eq 'POST' ) { - my $node = $c->request->param('source_id'); - my $target = $c->request->param('target_id'); - my $relation = $c->request->param('rel_type'); - my $note = $c->request->param('note'); - my $scope = $c->request->param('scope'); - - my $opts = { 'type' => $relation, - 'scope' => $scope }; - $opts->{'annotation'} = $note if $note; - - try { - my @vectors = $collation->add_relationship( $node, $target, $opts ); - $c->stash->{'result'} = \@vectors; - $m->save( $tradition ); - } catch( Text::Tradition::Error $e ) { + } else { + # Check write permissions first of all + if( $c->stash->{'permission'} ne 'full' ) { $c->response->status( '403' ); - $c->stash->{'result'} = { 'error' => $e->message }; + $c->stash->{'result'} = { + 'error' => 'You do not have permission to view this tradition.' }; + } elsif( $c->request->method eq 'POST' ) { + unless( $c->stash->{'permission'} eq 'full' ) { + $c->response->status( '403' ); + $c->stash->{'result'} = { + 'error' => 'You do not have permission to view this tradition.' }; + $c->detach( 'View::JSON' ); + } + my $node = $c->request->param('source_id'); + my $target = $c->request->param('target_id'); + my $relation = $c->request->param('rel_type'); + my $note = $c->request->param('note'); + my $scope = $c->request->param('scope'); + + my $opts = { 'type' => $relation, + 'scope' => $scope }; + $opts->{'annotation'} = $note if $note; + + try { + my @vectors = $collation->add_relationship( $node, $target, $opts ); + $c->stash->{'result'} = \@vectors; + $m->save( $tradition ); + } catch( Text::Tradition::Error $e ) { + $c->response->status( '403' ); + $c->stash->{'result'} = { 'error' => $e->message }; + } + } elsif( $c->request->method eq 'DELETE' ) { + my $node = $c->request->param('source_id'); + my $target = $c->request->param('target_id'); + + try { + my @vectors = $collation->del_relationship( $node, $target ); + $m->save( $tradition ); + $c->stash->{'result'} = \@vectors; + } catch( Text::Tradition::Error $e ) { + $c->response->status( '403' ); + $c->stash->{'result'} = { 'error' => $e->message }; + } } - } elsif( $c->request->method eq 'DELETE' ) { - my $node = $c->request->param('source_id'); - my $target = $c->request->param('target_id'); - - try { - my @vectors = $collation->del_relationship( $node, $target ); - $m->save( $tradition ); - $c->stash->{'result'} = \@vectors; - } catch( Text::Tradition::Error $e ) { - $c->response->status( '403' ); - $c->stash->{'result'} = { 'error' => $e->message }; - } } $c->forward('View::JSON'); } @@ -244,9 +264,9 @@ sub _reading_struct { # Return a JSONable struct of the useful keys. Keys meant to be writable # have a true value; read-only keys have a false value. my $struct = {}; - map { $struct->{$_} = $reading->$_ } keys( %read_write_keys ); + map { $struct->{$_} = $reading->$_ if $reading->can( $_ ) } keys( %read_write_keys ); # Special case - $struct->{'lexemes'} = [ $reading->lexemes ]; + $struct->{'lexemes'} = $reading->can( 'lexemes' ) ? [ $reading->lexemes ] : []; # Look up any words related via spelling or orthography my $sameword = sub { my $t = $_[0]->type; @@ -263,6 +283,8 @@ sub _reading_struct { sub readings :Chained('text') :PathPart :Args(0) { my( $self, $c ) = @_; my $tradition = delete $c->stash->{'tradition'}; + my $ok = _check_permission( $c, $tradition ); + return unless $ok; my $collation = $tradition->collation; my $m = $c->model('Directory'); if( $c->request->method eq 'GET' ) { @@ -298,6 +320,12 @@ sub reading :Chained('text') :PathPart :Args(1) { $c->stash->{'result'} = $rdg ? _reading_struct( $rdg ) : { 'error' => "No reading with ID $reading_id" }; } elsif ( $c->request->method eq 'POST' ) { + if( $c->stash->{'permission'} ne 'full' ) { + $c->response->status( '403' ); + $c->stash->{'result'} = { + 'error' => 'You do not have permission to view this tradition.' }; + $c->detach('View::JSON'); + } my $errmsg; # Are we re-lemmatizing? if( $c->request->param('relemmatize') ) { @@ -313,20 +341,23 @@ sub reading :Chained('text') :PathPart :Args(1) { foreach my $p ( keys %{$c->request->params} ) { if( $p =~ /^morphology_(\d+)$/ ) { # Set the form on the correct lexeme + my $morphval = $c->request->param( $p ); + next unless $morphval; my $midx = $1; - $c->log->debug( "Fetching lexeme $midx" ); my $lx = $rdg->lexeme( $midx ); - my $strrep = $rdg->language . ' // ' - . $c->request->param( $p ); + my $strrep = $rdg->language . ' // ' . $morphval; my $idx = $lx->has_form( $strrep ); unless( defined $idx ) { # Make the word form and add it to the lexeme. - $c->log->debug("Adding new form for $strrep"); try { $idx = $lx->add_matching_form( $strrep ) - 1; } catch( Text::Tradition::Error $e ) { $c->response->status( '403' ); $errmsg = $e->message; + } catch { + # Something else went wrong, probably a Moose error + $c->response->status( '403' ); + $errmsg = 'Something went wrong with the request'; } } $lx->disambiguate( $idx ) if defined $idx; @@ -345,6 +376,29 @@ sub reading :Chained('text') :PathPart :Args(1) { } +sub _check_permission { + my( $c, $tradition ) = @_; + my $user = $c->user_exists ? $c->user->get_object : undef; + # Does this user have access? + if( $user ) { + if( $user->is_admin || + ( $tradition->has_user && $tradition->user->id eq $user->id ) ) { + $c->stash->{'permission'} = 'full'; + return 1; + } + } + # Is it public? + if( $tradition->public ) { + $c->stash->{'permission'} = 'readonly'; + return 1; + } + # Forbidden! + $c->response->status( 403 ); + $c->response->body( 'You do not have permission to view this tradition.' ); + $c->detach( 'View::Plain' ); + return 0; +} + sub _clean_booleans { my( $rdg, $param, $val ) = @_; if( $rdg->meta->get_attribute( $param )->type_constraint->name eq 'Bool' ) {