@@ -858,11 +858,11 @@ StorePathSet LocalStore::queryAllValidPaths()
858858}
859859
860860
861- void LocalStore::queryReferrers (State & state, const StorePath & path, StorePathSet & referrers)
861+ void LocalStore::queryReferrers (State & state, const StorePath & path, StorePathSet & referrers, bool accessCheck )
862862{
863863 auto useQueryReferrers (state.stmts ->QueryReferrers .use ()(printStorePath (path)));
864864
865- if (!canAccess (path)) throw AccessDenied (" Access Denied" );
865+ if (accessCheck && !canAccess (path)) throw AccessDenied (" Access Denied" );
866866
867867 while (useQueryReferrers.next ())
868868 referrers.insert (parseStorePath (useQueryReferrers.getStr (0 )));
@@ -1086,7 +1086,7 @@ void LocalStore::setCurrentAccessStatus(const Path & path, const LocalStore::Acc
10861086
10871087 auto info = promise.get_future ().get ();
10881088
1089- if (info){
1089+ if (info) {
10901090 for (auto reference : info->references ) {
10911091 if (reference == storePath) continue ;
10921092 auto otherStatus = getCurrentAccessStatus (printStorePath (reference));
@@ -1103,6 +1103,28 @@ void LocalStore::setCurrentAccessStatus(const Path & path, const LocalStore::Acc
11031103 }
11041104 }
11051105 }
1106+
1107+ StorePathSet referrers;
1108+ retrySQLite<void >([&]() {
1109+ auto state (_state.lock ());
1110+ queryReferrers (*state, storePath, referrers, false );
1111+ });
1112+
1113+ for (auto referrer : referrers) {
1114+ if (referrer == storePath) continue ;
1115+ auto otherStatus = getAccessStatus (referrer);
1116+ if (!status.isProtected ) continue ;
1117+ if (!otherStatus.isProtected )
1118+ throw AccessDenied (" can not make %s protected because it is referenced by a non-protected path %s" , path, printStorePath (referrer));
1119+ std::vector<AccessControlEntity> difference;
1120+ std::set_difference (otherStatus.entities .begin (), otherStatus.entities .end (), status.entities .begin (), status.entities .end (),std::inserter (difference, difference.begin ()));
1121+
1122+ if (! difference.empty ()) {
1123+ std::string entities;
1124+ for (auto entity : difference) entities += ACL::printTag (entity) + " , " ;
1125+ throw AccessDenied (" can not deny %s access to %s because it is referenced by a path %s to which they do not have access" , entities.substr (0 , entities.size ()-2 ), path, printStorePath (referrer));
1126+ }
1127+ }
11061128 }
11071129 }
11081130
0 commit comments