Index: src/report.c ================================================================== --- src/report.c +++ src/report.c @@ -873,11 +873,11 @@ Stmt q; char *zErr1 = 0; char *zErr2 = 0; login_check_credentials(); - if( !g.okRead ){ login_needed(); return; } + if( !g.okRdTkt ){ login_needed(); return; } rn = atoi(PD("rn","0")); if( rn==0 ){ cgi_redirect("reportlist"); return; } Index: src/search.c ================================================================== --- src/search.c +++ src/search.c @@ -175,11 +175,11 @@ ** Testing the search function. ** ** COMMAND: search ** %fossil search pattern... ** -** Search for timeline entrys matching the pattern. +** Search for timeline entries matching the pattern. */ void search_cmd(void){ Search *p; Blob pattern; int i; Index: src/skins.c ================================================================== --- src/skins.c +++ src/skins.c @@ -188,14 +188,16 @@ @ if {[hascap h]} { @ html "Files " @ } @ if {[hascap o]} { @ html "Leaves " -@ html "Timeline " @ html "Branches " @ html "Tags " @ } +@ if {[hascap h]} { +@ html "Timeline " +@ } @ if {[hascap r]} { @ html "Tickets " @ } @ if {[hascap j]} { @ html "Wiki " @@ -388,14 +390,16 @@ @ if {[hascap h]} { @ html "Files " @ } @ if {[hascap o]} { @ html "Leaves " -@ html "Timeline " @ html "Branches " @ html "Tags " @ } +@ if {[hascap h]} { +@ html "Timeline " +@ } @ if {[hascap r]} { @ html "Tickets " @ } @ if {[hascap j]} { @ html "Wiki " @@ -621,14 +625,16 @@ @ if {[hascap h]} { @ html "
  • Files
  • " @ } @ if {[hascap o]} { @ html "
  • Leaves
  • " -@ html "
  • Timeline
  • " @ html "
  • Branches
  • " @ html "
  • Tags
  • " @ } +@ if {[hascap h]} { +@ html "
  • Timeline
  • " +@ } @ if {[hascap r]} { @ html "
  • Tickets
  • " @ } @ if {[hascap j]} { @ html "
  • Wiki
  • " Index: src/style.c ================================================================== --- src/style.c +++ src/style.c @@ -210,14 +210,16 @@ @ if {[hascap h]} { @ html "Files " @ } @ if {[hascap o]} { @ html "Leaves " -@ html "Timeline " @ html "Branches " @ html "Tags " @ } +@ if {[hascap h]} { +@ html "Timeline " +@ } @ if {[hascap r]} { @ html "Tickets " @ } @ if {[hascap j]} { @ html "Wiki " Index: src/timeline.c ================================================================== --- src/timeline.c +++ src/timeline.c @@ -445,14 +445,20 @@ const char *zString = P("s"); /* String text search of comment and brief */ HQuery url; /* URL for various branch links */ int tagid; /* Tag ID */ int tmFlags; /* Timeline flags */ - /* To view the timeline, must have permission to read project data. - */ + /* To view the timeline, must have permission to project history.*/ login_check_credentials(); - if( !g.okRead ){ login_needed(); return; } + if( !g.okHistory ){ login_needed(); return; } + + /* Prevent them from getting an empty list due to security constraints */ + if( (p_rid || d_rid) && !g.okRead ){ login_needed(); return; } + if( zType[0]=='c' && zType[1]=='i' && !g.okRead){ login_needed(); return; } + if( zType[0]=='t' && !g.okRdTkt){ login_needed(); return; } + if( zType[0]=='w' && !g.okRdWiki){ login_needed(); return; } + if( zTagName ){ tagid = db_int(0, "SELECT tagid FROM tag WHERE tagname='sym-%q'", zTagName); }else{ tagid = 0; } @@ -467,10 +473,20 @@ timeline_temp_table(); blob_zero(&sql); blob_zero(&desc); blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1); blob_append(&sql, timeline_query_for_www(), -1); + /* limit the types of objects found in history */ + if( !g.okRead ){ + blob_appendf(&sql, " AND event.type<>'ci'"); + } + if( !g.okRdTkt ){ + blob_appendf(&sql, " AND event.type<>'t'"); + } + if( !g.okRdWiki ){ + blob_appendf(&sql, " AND event.type<>'w'"); + } if( p_rid || d_rid ){ /* If p= or d= is present, ignore all other parameters other than n= */ char *zUuid; int np, nd; @@ -636,17 +652,17 @@ free(zDate); }else if( tagid==0 ){ if( zType[0]!='a' ){ timeline_submenu(&url, "All Types", "y", "all", 0); } - if( zType[0]!='w' ){ + if( zType[0]!='w' && g.okRdWiki ){ timeline_submenu(&url, "Wiki Only", "y", "w", 0); } - if( zType[0]!='c' ){ + if( zType[0]!='c' && g.okRead ){ timeline_submenu(&url, "Checkins Only", "y", "ci", 0); } - if( zType[0]!='t' ){ + if( zType[0]!='t' && g.okRdTkt ){ timeline_submenu(&url, "Tickets Only", "y", "t", 0); } } if( nEntry>20 ){ timeline_submenu(&url, "20 Events", "n", "20", 0);