Skip to content

Commit c6500f9

Browse files
committed
Merge in project-search fixes
2 parents 158b64c + 15161e1 commit c6500f9

File tree

8 files changed

+77
-12
lines changed

8 files changed

+77
-12
lines changed

package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ description: Please see the README on GitHub at <https://github.com/gith
2020
ghc-options:
2121
- -Wall
2222
- -Werror
23-
- -Wno-name-shadowing
23+
- -Wname-shadowing
2424
- -Wno-type-defaults
2525
- -Wno-missing-pattern-synonym-signatures
2626
- -fprint-expanded-synonyms

share-api.cabal

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ library
192192
QuasiQuotes
193193
ImportQualifiedPost
194194
OverloadedRecordDot
195-
ghc-options: -Wall -Werror -Wno-name-shadowing -Wno-type-defaults -Wno-missing-pattern-synonym-signatures -fprint-expanded-synonyms -fwrite-ide-info -O2 -funbox-strict-fields
195+
ghc-options: -Wall -Werror -Wname-shadowing -Wno-type-defaults -Wno-missing-pattern-synonym-signatures -fprint-expanded-synonyms -fwrite-ide-info -O2 -funbox-strict-fields
196196
build-depends:
197197
Diff
198198
, MonadRandom
@@ -335,7 +335,7 @@ executable share-api
335335
QuasiQuotes
336336
ImportQualifiedPost
337337
OverloadedRecordDot
338-
ghc-options: -Wall -Werror -Wno-name-shadowing -Wno-type-defaults -Wno-missing-pattern-synonym-signatures -fprint-expanded-synonyms -fwrite-ide-info -O2 -funbox-strict-fields -threaded -rtsopts "-with-rtsopts=-N -A32m -qn2 -T"
338+
ghc-options: -Wall -Werror -Wname-shadowing -Wno-type-defaults -Wno-missing-pattern-synonym-signatures -fprint-expanded-synonyms -fwrite-ide-info -O2 -funbox-strict-fields -threaded -rtsopts "-with-rtsopts=-N -A32m -qn2 -T"
339339
build-depends:
340340
Diff
341341
, MonadRandom

src/Share/App.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,11 @@ runAppM env (AppM m) = runReaderT m env
2727

2828
instance Logging.MonadLogger (AppM ()) where
2929
logMsg msg = do
30-
log <- asks Env.logger
30+
log' <- asks Env.logger
3131
minSeverity <- asks Env.minLogSeverity
3232
when (Logging.severity msg >= minSeverity) $ do
3333
timestamp <- asks timeCache >>= liftIO
34-
liftIO . log . Logging.logFmtFormatter timestamp $ msg
34+
liftIO . log' . Logging.logFmtFormatter timestamp $ msg
3535

3636
instance Cryptonite.MonadRandom (AppM reqCtx) where
3737
getRandomBytes =

src/Share/Postgres/Queries.hs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,24 @@ searchUsersByNameOrHandlePrefix (Query prefix) (Limit limit) = do
274274
--
275275
-- The PG.queryListRows accepts strings as web search queries, see
276276
-- https://www.postgresql.org/docs/current/textsearch-controls.html
277-
searchProjectsByUserQuery :: Maybe UserId -> Query -> Limit -> PG.Transaction e [(Project, UserHandle)]
278-
searchProjectsByUserQuery caller (Query query) limit = do
277+
searchProjects :: Maybe UserId -> Maybe UserId -> Query -> Limit -> PG.Transaction e [(Project, UserHandle)]
278+
-- Don't search with an empty query
279+
searchProjects _caller Nothing (Query "") _limit = pure []
280+
searchProjects caller (Just userId) (Query "") limit = do
281+
-- If we have a userId filter but no query, just return all the projects owned by that user
282+
-- which the caller has access to.
283+
PG.queryListRows @(Project PG.:. PG.Only UserHandle)
284+
[PG.sql|
285+
SELECT p.id, p.owner_user_id, p.slug, p.summary, p.tags, p.private, p.created_at, p.updated_at, owner.handle
286+
FROM projects p
287+
JOIN users owner ON p.owner_user_id = owner.id
288+
WHERE p.owner_user_id = #{userId}
289+
AND ((NOT p.private) OR (#{caller} IS NOT NULL AND EXISTS (SELECT FROM accessible_private_projects WHERE user_id = #{caller} AND project_id = p.id)))
290+
ORDER BY p.created_at DESC
291+
LIMIT #{limit}
292+
|]
293+
<&> fmap \(project PG.:. PG.Only handle) -> (project, handle)
294+
searchProjects caller userIdFilter (Query query) limit = do
279295
let prefixQuery =
280296
query
281297
-- Remove any chars with special meaning for tsqueries.
@@ -294,6 +310,7 @@ searchProjectsByUserQuery caller (Query query) limit = do
294310
JOIN users AS owner ON p.owner_user_id = owner.id
295311
WHERE (webquery @@ p.project_text_document OR prefixquery @@ p.project_text_document)
296312
AND (NOT p.private OR (#{caller} IS NOT NULL AND EXISTS (SELECT FROM accessible_private_projects WHERE user_id = #{caller} AND project_id = p.id)))
313+
AND (#{userIdFilter} IS NULL OR p.owner_user_id = #{userIdFilter})
297314
ORDER BY (ts_rank_cd(p.project_text_document, webquery), ts_rank_cd(p.project_text_document, prefixquery)) DESC
298315
LIMIT #{limit}
299316
|]

src/Share/Web/Share/Impl.hs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66

77
module Share.Web.Share.Impl where
88

9-
import Control.Lens
9+
import Data.Text qualified as Text
1010
import Servant
11+
import Control.Lens
1112
import Share.Codebase qualified as Codebase
1213
import Share.Codebase.Types qualified as Codebase
13-
import Share.IDs (TourId, UserHandle)
14+
import Share.IDs (TourId, UserHandle (..))
1415
import Share.IDs qualified as IDs
1516
import Share.JWT qualified as JWT
1617
import Share.OAuth.Session
@@ -27,6 +28,7 @@ import Share.Prelude
2728
import Share.Project (Project (..))
2829
import Share.Release (Release (..))
2930
import Share.User (User (..))
31+
import Share.User qualified as User
3032
import Share.UserProfile (UserProfile (..))
3133
import Share.Utils.API
3234
import Share.Utils.Caching
@@ -340,13 +342,23 @@ getUserReadmeEndpoint (AuthN.MaybeAuthedUserID callerUserId) userHandle = do
340342
-- all private users in the PG query itself.
341343
searchEndpoint :: Maybe Session -> Query -> Maybe Limit -> WebApp [SearchResult]
342344
searchEndpoint _caller (Query "") _limit = pure []
343-
searchEndpoint (MaybeAuthedUserID callerUserId) query (fromMaybe (Limit 20) -> limit) = do
345+
searchEndpoint (MaybeAuthedUserID callerUserId) (Query query) (fromMaybe (Limit 20) -> limit) = do
346+
(userQuery :: Query, (projectUserFilter :: Maybe UserId, projectQuery :: Query)) <-
347+
fromMaybe query (Text.stripPrefix "@" query)
348+
& Text.splitOn "/"
349+
& \case
350+
(userQuery : projectQueryText : _rest) -> do
351+
mayUserId <- PG.runTransaction $ fmap User.user_id <$> Q.userByHandle (UserHandle userQuery)
352+
pure (Query query, (mayUserId, Query projectQueryText))
353+
[projectOrUserQuery] -> pure (Query projectOrUserQuery, (Nothing, Query projectOrUserQuery))
354+
-- This is impossible
355+
[] -> pure (Query query, (Nothing, Query query))
344356
-- We don't have a great way to order users and projects together, so we just limit to a max
345357
-- of 5 users (who match the query as a prefix), then return the rest of the results from
346358
-- projects.
347359
(users, projects) <- PG.runTransaction $ do
348-
users <- Q.searchUsersByNameOrHandlePrefix query (Limit 5)
349-
projects <- Q.searchProjectsByUserQuery callerUserId query limit
360+
users <- Q.searchUsersByNameOrHandlePrefix userQuery (Limit 5)
361+
projects <- Q.searchProjects callerUserId projectUserFilter projectQuery limit
350362
pure (users, projects)
351363
let userResults =
352364
users
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"body": [
3+
{
4+
"projectRef": "@test/publictestproject",
5+
"summary": "test project summary",
6+
"tag": "Project",
7+
"visibility": "public"
8+
}
9+
],
10+
"status": [
11+
{
12+
"status_code": 200
13+
}
14+
]
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"body": [
3+
{
4+
"projectRef": "@test/publictestproject",
5+
"summary": "test project summary",
6+
"tag": "Project",
7+
"visibility": "public"
8+
}
9+
],
10+
"status": [
11+
{
12+
"status_code": 200
13+
}
14+
]
15+
}

transcripts/share-apis/projects-flow/run.zsh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ fetch "$transcript_user" GET project-catalog-get '/catalog'
7878
# Should find projects we have access to (e.g. Unison's private project), but none that we don't.
7979
fetch "$transcript_user" GET project-search '/search?query=test'
8080

81+
# Should filter project search by user if provided a full valid handle:
82+
fetch "$transcript_user" GET project-search-with-user-and-project-query '/search?query=@test/public'
83+
84+
# Should return all projects in a user if provided a full valid handle, but no project query:
85+
fetch "$transcript_user" GET project-search-with-only-user '/search?query=@test/'
86+
8187
# Transcript user should not find 'test' user's private project
8288
fetch "$transcript_user" GET project-search-inaccessible '/search?query=privatetestproject'
8389

0 commit comments

Comments
 (0)