@@ -321,26 +321,31 @@ public enum Queries {
321321 /// A page of an issue's comments, ordered by (created, id); a backward
322322 /// page flips the order. `start` is the cursor row.
323323 public static let commentsPage = defineQuery ( " commentsPage " ) {
324- ( args : CommentsPageArgs , _ : AuthData ? ) in
324+ ( args : CommentsPageArgs , auth : AuthData ? ) in
325325 let dir : AST . Direction = args . dir == . forward ? . asc : . desc
326- var q = zql . comment
327- . related ( \. creator )
328- . related ( \. emoji ) { $0 . related ( \. creator ) }
329- . where ( \. issueID , args . issueID )
330- . orderBy ( \. created , dir )
331- . orderBy ( \. id , dir )
326+ var q = applyCommentPermissions (
327+ zql . comment
328+ . related ( \. creator )
329+ . related ( \. emoji ) { $0 . related ( \. creator ) }
330+ . where ( \. issueID , args . issueID ) ,
331+ auth ? . role
332+ )
333+ . orderBy ( \. created , dir )
334+ . orderBy ( \. id , dir )
332335 if let start = args . start {
333336 q = q . start ( [ \. id : start . id , \. created : start . created ] , inclusive : args . inclusive )
334337 }
335338 return q . limit ( args . limit )
336339 }
337340
338- public static let comment = defineQuery ( " comment " ) { ( id : String , _ : AuthData ? ) in
339- zql . comment
340- . related ( \. creator )
341- . related ( \. emoji ) { $0 . related ( \. creator ) }
342- . where ( \. id , id )
343- . one ( )
341+ public static let comment = defineQuery ( " comment " ) { ( id : String , auth : AuthData ? ) in
342+ applyCommentPermissions (
343+ zql . comment
344+ . related ( \. creator )
345+ . related ( \. emoji ) { $0 . related ( \. creator ) }
346+ . where ( \. id , id ) ,
347+ auth ? . role
348+ ) . one ( )
344349 }
345350
346351 public static let issueDetail = defineQuery ( " issueDetail " ) {
@@ -396,10 +401,19 @@ public enum Queries {
396401 . one ( )
397402 }
398403
399- public static let emojiChange = defineQuery ( " emojiChange " ) { ( subjectID : String , _ : AuthData ? ) in
400- zql . emoji
401- . where ( \. subjectID , subjectID )
402- . related ( \. creator ) { $0 . one ( ) }
404+ public static let emojiChange = defineQuery ( " emojiChange " ) {
405+ ( subjectID : String , auth : AuthData ? ) in
406+ let role = auth ? . role
407+ var q = zql . emoji . where ( \. subjectID , subjectID )
408+ if role != . crew {
409+ // The subject is an issue or a comment.
410+ q = q . where { emoji in
411+ emoji . or (
412+ emoji . exists ( \. issue ) { applyIssuePermissions ( $0 , role ) } ,
413+ emoji . exists ( \. comment ) { applyCommentPermissions ( $0 , role ) } )
414+ }
415+ }
416+ return q . related ( \. creator ) { $0 . one ( ) }
403417 }
404418
405419 /// Deprecated in zbugs.
@@ -454,6 +468,17 @@ where Result.Row == Issue {
454468 role == . crew ? q : q . where ( \. visibility , . public )
455469}
456470
471+ /// Narrows a comment query to comments whose issue `role` may see. Comments
472+ /// and emoji are fetched by id, so each of those queries applies the issue's
473+ /// visibility itself.
474+ func applyCommentPermissions < Result : QueryResult > (
475+ _ q : Query < Comment , Result > , _ role : Role ?
476+ )
477+ -> Query < Comment , Result >
478+ where Result . Row == Comment {
479+ role == . crew ? q : q . whereExists ( \. issue ) { applyIssuePermissions ( $0 , role ) }
480+ }
481+
457482func labelsQuery ( _ projectName : String , _ orderBy : AST . Direction ? ) -> Query < Label , [ Label ] > {
458483 var q = zql . label . whereExists ( \. project , scalar : true ) {
459484 $0 . where ( \. lowerCaseName , projectName . lowercased ( ) )
0 commit comments