source: trunk/www/common/overview/info.jsp @ 7207

Last change on this file since 7207 was 7207, checked in by Nicklas Nordborg, 6 years ago

References #2033: Permissions for annotating items may be incorrectly implemented

Changes in the web interface (Overview tab) so that the "edit" icon is only visible if the user has permission to modify an annotation.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Date Id
File size: 18.6 KB
Line 
1<%-- $Id: info.jsp 7207 2016-10-19 08:42:45Z nicklas $
2  ------------------------------------------------------------------
3  Copyright (C) 2009 Nicklas Nordborg
4
5  This file is part of BASE - BioArray Software Environment.
6  Available at http://base.thep.lu.se/
7
8  BASE is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License
10  as published by the Free Software Foundation; either version 3
11  of the License, or (at your option) any later version.
12
13  BASE is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with BASE. If not, see <http://www.gnu.org/licenses/>.
20  ------------------------------------------------------------------
21--%>
22<%@ page pageEncoding="UTF-8" session="false"
23  import="net.sf.basedb.core.SessionControl"
24  import="net.sf.basedb.core.DbControl"
25  import="net.sf.basedb.core.Project"
26  import="net.sf.basedb.core.Item"
27  import="net.sf.basedb.core.BasicItem"
28  import="net.sf.basedb.core.Nameable"
29  import="net.sf.basedb.core.Annotatable"
30  import="net.sf.basedb.core.AnnotationSet"
31  import="net.sf.basedb.core.AnnotationType"
32  import="net.sf.basedb.core.Annotation"
33  import="net.sf.basedb.core.ItemSubtype"
34  import="net.sf.basedb.core.Subtypable"
35  import="net.sf.basedb.core.AnyToAny"
36  import="net.sf.basedb.core.Protocol"
37  import="net.sf.basedb.core.Unit"
38  import="net.sf.basedb.core.FileStoreEnabled"
39  import="net.sf.basedb.core.FileSetMember"
40  import="net.sf.basedb.core.File"
41  import="net.sf.basedb.core.DataFileType"
42  import="net.sf.basedb.core.ItemContext"
43  import="net.sf.basedb.core.Permission"
44  import="net.sf.basedb.core.PermissionDeniedException"
45  import="net.sf.basedb.core.ItemNotFoundException"
46  import="net.sf.basedb.core.snapshot.SnapshotManager"
47  import="net.sf.basedb.core.snapshot.AnnotationSetSnapshot"
48  import="net.sf.basedb.core.snapshot.AnnotationSnapshot"
49  import="net.sf.basedb.core.snapshot.AnnotationTypeFilter"
50  import="net.sf.basedb.core.snapshot.AnnotationFilter"
51  import="net.sf.basedb.clients.web.Base"
52  import="net.sf.basedb.clients.web.util.HTML"
53  import="net.sf.basedb.clients.web.extensions.section.SectionAction"
54  import="net.sf.basedb.clients.web.extensions.JspContext"
55  import="net.sf.basedb.clients.web.extensions.ExtensionsControl"
56  import="net.sf.basedb.clients.web.formatter.FormatterFactory"
57  import="net.sf.basedb.util.Values"
58  import="net.sf.basedb.util.NestedIterator"
59  import="net.sf.basedb.util.units.UnitConverter"
60  import="net.sf.basedb.util.formatter.Formatter"
61  import="net.sf.basedb.util.overview.GenericOverview"
62  import="net.sf.basedb.util.overview.OverviewUtil"
63  import="net.sf.basedb.util.overview.Node"
64  import="net.sf.basedb.util.overview.ValidationOptions"
65  import="net.sf.basedb.util.overview.Validator"
66  import="net.sf.basedb.util.overview.Severity"
67  import="net.sf.basedb.util.overview.Failure"
68  import="net.sf.basedb.util.overview.Fix"
69  import="net.sf.basedb.util.overview.extensions.ValidationRuleAction"
70  import="net.sf.basedb.util.extensions.ExtensionsInvoker"
71  import="java.util.ArrayList"
72  import="java.util.Date"
73  import="java.util.List"
74  import="java.util.LinkedList"
75  import="java.util.Iterator"
76  import="java.util.Collection"
77  import="java.util.Collections"
78%>
79<%@ taglib prefix="base" uri="/WEB-INF/base.tld" %>
80<%@ taglib prefix="t" uri="/WEB-INF/tab.tld" %>
81<%@ taglib prefix="tbl" uri="/WEB-INF/table.tld" %>
82<%@ taglib prefix="ext" uri="/WEB-INF/extensions.tld" %>
83<%!
84private String getPath(DbControl dc, String ID, Node node)
85{
86  Node parent = node.getParent();
87  if (parent == null) return "";
88  String path = getPath(dc, ID, parent);
89  if (parent.getNodeType() == Node.Type.FOLDER)
90  {
91    //path += "/" + HTML.encodeTags(parent.getTitle());
92  }
93  else
94  {
95    BasicItem item = parent.getItem();
96    if (path.length() > 0)
97    {
98      path += " <b>›</b> ";
99    }
100    path += Base.getLink(ID, parent.getTitle(), item.getType(), item.getId(), item.hasPermission(Permission.WRITE));
101   
102    if (item instanceof Subtypable)
103    {
104      ItemSubtype subtype = ((Subtypable)parent.getItem(dc)).getItemSubtype();
105      if (subtype != null)
106      {
107        path += " <span class=\"itemsubtype\">(" + Base.getLinkedName(ID, subtype, false, true) + ")</span>";
108      }
109    }
110  }
111  return path;
112}
113%>
114<%
115final SessionControl sc = Base.getExistingSessionControl(pageContext, true);
116final String ID = sc.getId();
117final float scale = Base.getScale(sc);
118final DbControl dc = sc.newDbControl();
119try
120{
121  final GenericOverview overview = OverviewUtil.getCurrentOverview(sc);
122  final ItemContext cc = sc.getCurrentContext(overview.getRootItem().getType());
123  final SnapshotManager snapshotManager = new SnapshotManager();
124  final AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter();
125  final AnnotationFilter annotationFilter = new AnnotationFilter();
126  ValidationOptions options = overview.getValidationOptions();
127  String nodeId = request.getParameter("nodeId");
128  Boolean showFailures = Values.getBoolean(request.getParameter("show_failures"), false);
129  Node node = overview.getNode(nodeId);
130  if (node == null) node = overview.getRootNode();
131
132  JspContext jspContext = ExtensionsControl.createContext(dc, pageContext, null, node);
133  ExtensionsInvoker<SectionAction> invoker = (ExtensionsInvoker<SectionAction>)ExtensionsControl.useExtensions(
134      jspContext, "net.sf.basedb.clients.web.overview.info-details");
135 
136  BasicItem item = node.getItem(dc);
137  List<Failure> failures = overview.getFailures();
138  if (failures == null) failures = new LinkedList<Failure>();
139 
140  Formatter<Date> dateTimeFormatter = FormatterFactory.getDateTimeFormatter(sc);
141
142  %>
143  <base:page title="" type="iframe">
144  <base:head styles="table.css" scripts="dragdrop.js,~info.js">
145    <ext:scripts context="<%=jspContext%>" />
146    <ext:stylesheets context="<%=jspContext%>" />
147  <style>
148  .itemsubtype .link
149  {
150    color: #777777;
151  }
152  .edit-annotation
153  {
154    float: right;
155  }
156  </style>
157  </base:head>
158
159    <base:body>
160      <div class="absolutefull auto-init" data-auto-init="drag-support">
161      <div>
162      <table class="fullform bottomborder outlined">
163      <tr>
164        <th>Path</th>
165        <td><%=getPath(dc, ID, node)%></td>
166      </tr>
167      <%
168      if (item instanceof FileSetMember)
169      {
170        FileSetMember member = null;
171        boolean notFound = false;
172        try
173        { 
174          member = FileSetMember.getById(dc, item.getId());
175        }
176        catch (ItemNotFoundException ex)
177        {
178          notFound = true;
179        }
180        File file = null;
181        DataFileType dft = null;
182        boolean deniedFile = false;
183        boolean deniedFileType = false;
184        if (member != null)
185        {
186          try
187          {
188            file = member.getFile();
189          }
190          catch (PermissionDeniedException ex)
191          {
192            deniedFile = true;
193          }
194          try
195          {
196            dft = member.getDataFileType();
197          }
198          catch (PermissionDeniedException ex)
199          {
200            deniedFileType = true;
201          }
202        }
203        if (dft != null || file != null)
204        {
205          %>
206          <tr>
207            <th><%=dft == null ? "Data file" : HTML.encodeTags(dft.getName())%></th>
208            <td>
209              <%=Base.getLinkedFile(ID, file, deniedFile, true, true, "../../")%>
210            </td>
211          </tr>
212          <%
213        }
214        else
215        {
216          %>
217          <tr>
218          <th><%=HTML.encodeTags(node.getTitle())%></th>
219          <td>
220            <%=notFound ? "<i>- not found -</i>" : "<i>- denied -</i>"%>
221          </td>
222          </tr>
223          <%
224        }
225      }
226      else if (item instanceof AnyToAny)
227      {
228        AnyToAny any = AnyToAny.getById(dc, item.getId());
229        String linkTo = null;
230        try
231        {
232          BasicItem to = any.getTo();
233          String name = to instanceof Nameable ? ((Nameable)to).getName() : to.toString();
234          linkTo = Base.getLink(ID, HTML.encodeTags(name), 
235              to.getType(), to.getId(), to.hasPermission(Permission.WRITE));
236        }
237        catch (PermissionDeniedException ex)
238        {
239          linkTo = any.getToType() + "[id=" + any.getToId() + "] (<i>denied</i>)";
240        }
241        catch (ItemNotFoundException ex)
242        {
243          linkTo = any.getToType() + "[id=" + any.getToId() + "] (<i>missing</i>)";
244        }
245        %>
246        <tr>
247          <th>Any-to-any link</th>
248          <td>
249            <table>
250            <tr>
251              <td><%=Base.getLinkedName(ID, any, false, true) %></td>
252              <td><base:icon image="bullet.png" /></td>
253              <td><%=linkTo%></td>
254            </tr>
255            </table>
256          </td>
257        </tr>
258        <%
259      }
260      else
261      {
262        %>
263        <tr>
264          <th><%=node.getNodeType() == Node.Type.FOLDER ? 
265              "Folder" : item != null ? item.getType().toString() : "Item"%></th>
266          <td>
267            <%
268            if (item != null)
269            {
270              %>
271              <%=Base.getLink(ID, node.getTitle(), item.getType(),item.getId(), item.hasPermission(Permission.WRITE))%>
272              <%
273              if (item instanceof Subtypable)
274              {
275                ItemSubtype subtype = ((Subtypable)item).getItemSubtype();
276                if (subtype != null)
277                {
278                  %>
279                  <span class="itemsubtype">(<%=Base.getLinkedName(ID, subtype, false, true)%>)</span>
280                  <%
281                }
282              }
283            }
284            else
285            {
286              %>
287              <%=HTML.encodeTags(node.getTitle())%>
288              <%
289            }
290            %>
291          </td>
292        </tr>
293        <%
294      }
295      %>
296      <tr>
297        <th>Errors (children)</th>
298        <%
299        if (showFailures)
300        {
301        %>
302          <td><%=node.getNumErrors()+node.getChildErrors()%> (<%=node.getChildErrors()%>)</td>
303        <%
304        }
305        else
306        {       
307        %>
308          <td><i>- n/a -</i></td>
309        <%
310        }
311        %>
312      </tr>
313      <tr>
314        <th>Warnings (children)</th>
315        <%
316        if (showFailures)
317        {
318        %>
319          <td><%=node.getNumWarnings()+node.getChildWarnings()%> (<%=node.getChildWarnings()%>)</td>
320        <%
321        }
322        else
323        {       
324        %>
325          <td><i>- n/a -</i></td>
326        <%
327        }
328        %>
329      </tr>
330      <%
331      if (item instanceof Nameable)
332      {
333        Nameable nameable = (Nameable)item;
334        %>
335        <tr>
336          <th>Description</th>
337          <td><%=HTML.niceFormat(nameable.getDescription())%></td>
338        </tr>
339        <%
340      }
341      %>
342      </table>
343      </div>
344      <%
345      List<AnnotationSnapshot> annotations = new LinkedList<AnnotationSnapshot>();
346      String annotationsTitle = "";
347      Annotatable annotatable = null;
348      if (item instanceof Annotation)
349      {
350        Annotation a = Annotation.getById(dc, item.getId());
351        AnnotationSetSnapshot snapshot = snapshotManager.getSnapshot(dc, a.getAnnotationSet().getId());
352        annotationFilter.setAnnotation(a);
353        annotations.addAll(snapshotManager.findAnnotations(dc, snapshot, annotationFilter, true));
354       
355        // Find the annotatable parent node
356        Node parentNode = node;
357        while (parentNode != null)
358        {
359          BasicItem parentItem = parentNode.getItem();
360          if (parentItem instanceof Annotatable)
361          {
362            annotatable = (Annotatable)parentItem;
363            break;
364          }
365          parentNode = parentNode.getParent();
366        }
367        annotationsTitle = "Annotation values";
368      }
369      else if (item instanceof AnnotationType)
370      {
371        // Find the annotatable parent
372        Node parentNode = node;
373        while (parentNode != null)
374        {
375          BasicItem parentItem = parentNode.getItem();
376          if (parentItem instanceof Annotatable && !(parentItem instanceof Protocol))
377          {
378            annotatable = (Annotatable)parentItem.getType().getById(dc, parentItem.getId());
379            if (annotatable.isAnnotated())
380            {
381              annotationTypeFilter.setAnnotationType((AnnotationType)item);
382              annotations.addAll(snapshotManager.findAnnotations(dc, annotatable, annotationTypeFilter, true));
383            }
384            annotationsTitle = "Annotation values";
385            break;
386          }
387          parentNode = parentNode.getParent();
388        }
389      }
390      else if (item instanceof Annotatable)
391      {
392        annotationsTitle = "Annotations &amp; protocol parameters";
393        annotatable = (Annotatable)item.getType().getById(dc, item.getId());
394        if (annotatable.isAnnotated())
395        {
396          annotations.addAll(snapshotManager.findAnnotations(dc, annotatable, null, true));
397        }
398       
399      }
400      if (annotations != null && annotations.size() > 0)
401      {
402        Collections.sort(annotations, AnnotationSnapshot.sortByAnnotationType(dc));
403        %>
404        <base:section
405          id="allAnnotations"
406          title="<%="Annotations &amp; parameters (" +  annotations.size() + ")"%>"
407          context="<%=cc %>">
408       
409        <tbl:table id="annotations">
410          <tbl:columndef id="annotation" title="Annotation/parameter" />
411          <tbl:columndef id="values" title="Values" />
412          <tbl:columndef 
413            id="item"
414            title="Parent item"
415          />
416          <tbl:columndef 
417            id="note"
418            title="Note"
419          />
420          <tbl:columndef
421            id="lastModified"
422            title="Last modified"
423            formatter="<%=dateTimeFormatter %>"
424          />
425          <tbl:data>
426            <tbl:headers>
427              <tbl:headerrow>
428                <tbl:columnheaders />
429              </tbl:headerrow>
430            </tbl:headers>
431            <tbl:rows>
432              <%
433              for (AnnotationSnapshot snapshot : annotations)
434              {
435                AnnotationType at = snapshot.getAnnotationType(dc);
436               
437                // Unit and formatter for the values
438                Formatter formatter = FormatterFactory.getTypeFormatter(sc, at.getValueType());
439                Unit unit = snapshot.getActualUnit(dc);
440                UnitConverter converter = null;
441                if (unit != null)
442                {
443                  converter = unit.getUnitConverter(at.getDefaultUnit());
444                  formatter = unit.getFormatter(formatter);
445                }
446                // Get values
447                List<?> values = snapshot.getActualValues(converter, at.getValueType());
448
449                // Inheritance information
450                Date lastModified = snapshot.getThisLastUpdate();
451                boolean isUpToDate = snapshot.isUpToDate();
452                AnnotationSnapshot inherited = snapshot.getInheritedFrom();
453                Annotatable inheritedFrom = null;
454                if (inherited != null)
455                {
456                  if (lastModified == null)
457                  {
458                    lastModified = inherited.getThisLastUpdate();
459                  }
460                  try
461                  {
462                    inheritedFrom = inherited.getThisItem(dc);
463                  }
464                  catch (Throwable t)
465                  {}
466                }
467               
468                String icon = at != null && at.isProtocolParameter() ? 
469                    "parameter.png" : "annotation.png";
470                boolean editPermission = snapshot.hasPermission(dc, Permission.WRITE);
471                %>
472                <tbl:row>
473                  <tbl:cell column="annotation"><base:icon image="<%=icon%>" />
474                    <%=Base.getLinkedName(ID, at, false, true)%>
475                  </tbl:cell>
476                  <tbl:cell column="values">
477                    <%=Values.getString(values, ", ", true, formatter)%>
478                    <base:icon id="<%=Integer.toString(snapshot.getThisAnnotationId())%>" 
479                      image="<%=isUpToDate ? "edit.png" : "edit-outofsync.png"%>" 
480                      subclass="edit-annotation auto-init" 
481                      data-auto-init="edit-annotation"
482                      data-item-type="<%=annotatable.getType().name()%>" 
483                      data-item-id="<%=annotatable.getId()%>" 
484                      data-annotation-type-id="<%=at.getId()%>"
485                      data-annotation-id="<%=snapshot.getThisAnnotationId()%>"
486                      tooltip="Edit this annotation" visible="<%=editPermission %>"/>
487                  </tbl:cell>
488                  <tbl:cell column="item">
489                    <%
490                    if (inheritedFrom != null)
491                    {
492                      String ownerName = inheritedFrom instanceof Nameable ?
493                          ((Nameable)inheritedFrom).getName() : inheritedFrom.toString();
494                      %>
495                      <%=Base.getLink(ID, ownerName, inheritedFrom.getType(), inheritedFrom.getId(), inheritedFrom.hasPermission(Permission.WRITE)) %>
496                      <%
497                    }
498                    else if (snapshot.getSource() == Annotation.Source.CLONED)
499                    {
500                      %>
501                      <i>- missing -</i>
502                      <%
503                    }
504                    %>
505                  </tbl:cell>
506                  <tbl:cell column="note"><%=snapshot.getSource() == Annotation.Source.CLONED ? "Cloned" + (isUpToDate ? "; up-to-date" : "; modified") : "" %></tbl:cell>
507                  <tbl:cell column="lastModified" value="<%=lastModified %>" />
508                </tbl:row>
509                <%
510              }
511              %>
512            </tbl:rows>
513          </tbl:data>       
514        </tbl:table>
515        </base:section>
516        <%
517      }     
518      if (showFailures)
519      {
520        %>
521        <base:section
522          id="failures"
523          title="<%="Failure details (" + (node.getNumErrors() + node.getNumWarnings()) + ")"%>"
524          context="<%=cc %>"
525          >
526        <table>
527        <%
528        int numFailures = 0;
529        for (Failure failure : failures)
530        {
531          ValidationRuleAction validator = failure.getValidator();
532          Severity severity = options.getSeverity(validator);
533          if (failure.getNode() == node && severity != Severity.IGNORE)
534          {
535            numFailures++;
536            List<Fix> fixes = failure.getFixes();
537            %>
538            <tr>
539              <td><base:icon image="<%=severity == Severity.ERROR ? "error.png" : "warning.png"%>" style="padding-right: 4px;"/></td>
540              <td><b><%=HTML.encodeTags(failure.getMessage())%></b></td>
541            </tr>
542            <tr>
543              <td></td>
544              <td style="padding-bottom: 0.3em;">
545                <%=HTML.encodeTags(validator.getDescription())%><br>
546                <%
547                if (fixes != null && fixes.size() > 0)
548                {
549                  for (Fix fix : fixes)
550                  {
551                    if (fix == null) continue;
552                    BasicItem fixItem = fix.getItem();
553                    AnnotationType at = fix.getAnnotationType();
554                    Annotation a = fix.getAnnotation();
555                    boolean enabled = a != null ? 
556                      a.hasPermission(Permission.WRITE) : fixItem.hasPermission(Permission.WRITE);
557                    String autoInit = "";
558                    if (enabled)
559                    {
560                      if (fix.isAnnotationFix())
561                      {
562                        autoInit = "edit-annotation";
563                      }
564                      else if (fix.isDataFileFix())
565                      {
566                        autoInit = "edit-data-file";
567                      }
568                      else
569                      {
570                        autoInit = "edit-item";
571                      }
572                    }
573                    %>
574                    <base:icon image="fixit.png" 
575                      style="padding-bottom: 4px;" 
576                      id="<%=Integer.toString(fix.hashCode())%>"
577                      enabled="<%=enabled %>"
578                      subclass="auto-init"
579                      data-auto-init="<%=autoInit%>"
580                      data-item-type="<%=fixItem.getType().name()%>"
581                      data-item-id="<%=fixItem.getId()%>"
582                      data-annotation-type-id="<%=at != null ? at.getId() : ""%>"
583                      data-annotation-id="<%=a != null ? a.getId() : "" %>"
584                      tooltip="<%=enabled ? "Edit this item to fix the problem" : "You do not have permission to modify this item" %>"
585                    ><%=HTML.encodeTags(fix.getMessage())%></base:icon><br>
586                    <%
587                  }
588                }
589                %>
590              </td>
591            </tr>
592            <%
593          }
594        }
595        %>
596        </table>
597        <%
598        if (numFailures == 0)
599        {
600          %>
601          <div class="messagecontainer note">
602          No validation failures on this item
603          </div>
604          <%
605        }
606        %>
607        </base:section>
608        <%
609      }
610     
611      for (SectionAction section : invoker)
612      {
613        %>
614        <base:section 
615          id="<%=section.getId() %>" 
616          showclazz="<%=section.getShowClazz() %>"
617          hideclazz="<%=section.getHideClazz() %>"
618          style="<%=section.getStyle() %>"
619          contentstyle="<%=section.getContentStyle() %>"
620          title="<%=section.getTitle() %>"
621          context="<%=cc %>"
622          ><%=section.getContent() %></base:section>
623        <%
624      }
625      %>
626      </div>
627    </base:body>
628  </base:page>
629  <%
630}
631finally
632{
633  if (dc != null) dc.close();
634}
635%>
Note: See TracBrowser for help on using the repository browser.