@@ -10,33 +10,37 @@ import akka.http.scaladsl.model.StatusCodes
10
10
import akka .http .scaladsl .util .FastFuture
11
11
import akka .stream .scaladsl .Source
12
12
import com .advancedtelematic .libats .data .DataType .Namespace
13
- import com .advancedtelematic .libats .data .ErrorCode
13
+ import com .advancedtelematic .libats .data .{ ErrorCode , PaginationResult }
14
14
import com .advancedtelematic .libats .http .Errors .{EntityAlreadyExists , MissingEntity , MissingEntityId , RawError }
15
15
import com .advancedtelematic .libtuf .data .TufDataType .{JsonSignedPayload , RepoId , RoleType , TargetFilename , validTargetFilename }
16
16
import com .advancedtelematic .libtuf .data .TufDataType .RoleType .RoleType
17
- import com .advancedtelematic .tuf .reposerver .data .RepoDataType ._
18
- import com .advancedtelematic .libtuf_server .repo .server .DataType ._
19
- import com .advancedtelematic .libats .slick .db .SlickExtensions ._
20
- import com .advancedtelematic .libats .slick .codecs .SlickRefined ._
21
- import com .advancedtelematic .libats .slick .db .SlickUUIDKey ._
22
- import com .advancedtelematic .libats .slick .db .SlickAnyVal ._
17
+ import com .advancedtelematic .tuf .reposerver .data .RepoDataType .*
18
+ import com .advancedtelematic .libtuf_server .repo .server .DataType .*
19
+ import com .advancedtelematic .libats .slick .db .SlickExtensions .*
20
+ import com .advancedtelematic .libats .slick .db .SlickPagination
21
+ import com .advancedtelematic .libats .slick .codecs .SlickRefined .*
22
+ import com .advancedtelematic .libats .slick .db .SlickUUIDKey .*
23
+ import com .advancedtelematic .libats .slick .db .SlickAnyVal .*
23
24
import com .advancedtelematic .libtuf .data .ClientDataType .{ClientTargetItem , DelegatedRoleName , DelegationFriendlyName , SnapshotRole , TargetCustom , TimestampRole , TufRole }
24
25
import com .advancedtelematic .libtuf_server .data .Requests .TargetComment
25
- import com .advancedtelematic .libtuf_server .data .TufSlickMappings ._
26
+ import com .advancedtelematic .libtuf_server .data .TufSlickMappings .*
26
27
import com .advancedtelematic .tuf .reposerver .db .DBDataType .{DbDelegation , DbSignedRole }
27
28
import com .advancedtelematic .tuf .reposerver .db .TargetItemRepositorySupport .MissingNamespaceException
28
- import com .advancedtelematic .tuf .reposerver .http .Errors ._
29
+ import com .advancedtelematic .tuf .reposerver .http .Errors .*
29
30
import com .advancedtelematic .libtuf_server .repo .server .Errors .SignedRoleNotFound
30
31
import SlickMappings .{delegatedRoleNameMapper , delegationFriendlyNameMapper }
31
32
import shapeless .ops .function .FnToProduct
32
33
import shapeless .{Generic , HList , Succ }
33
34
import com .advancedtelematic .libtuf_server .repo .server .SignedRoleProvider
34
35
import com .advancedtelematic .tuf .reposerver .data .RepoDataType .TargetItem
36
+ import com .advancedtelematic .tuf .reposerver .db .Schema .TargetItemTable
37
+ import com .advancedtelematic .tuf .reposerver .http .PaginationParams .PaginationResultOps
38
+ import slick .ast .Ordering
35
39
36
40
import scala .concurrent .{ExecutionContext , Future }
37
41
import scala .util .control .NoStackTrace
38
- import slick .jdbc .MySQLProfile .api ._
39
- import slick .lifted .AbstractTable
42
+ import slick .jdbc .MySQLProfile .api .*
43
+ import slick .lifted .{ AbstractTable , ColumnOrdered }
40
44
41
45
trait DatabaseSupport {
42
46
val ec : ExecutionContext
@@ -98,15 +102,37 @@ protected [db] class TargetItemRepository()(implicit db: Database, ec: Execution
98
102
}.transactionally
99
103
}
100
104
101
- def findFor (repoId : RepoId , nameContains : Option [String ] = None ): Future [Seq [TargetItem ]] = db.run {
105
+ def findForQuery (repoId : RepoId ,
106
+ nameContains : Option [String ] = None ): Query [TargetItemTable , TargetItem , Seq ] = {
102
107
nameContains match {
103
108
case Some (substring) =>
104
- targetItems.filter(_.repoId === repoId).filter(_.filename.mappedTo[String ].like(s " % ${substring}% " )).result
109
+ targetItems
110
+ .filter(_.repoId === repoId)
111
+ .filter(_.filename.mappedTo[String ].like(s " % ${substring}% " ))
105
112
case None =>
106
- targetItems.filter(_.repoId === repoId).result
113
+ targetItems.filter(_.repoId === repoId)
107
114
}
108
115
}
109
116
117
+ def findFor (
118
+ repoId : RepoId ,
119
+ nameContains : Option [String ] = None
120
+ ): Future [Seq [TargetItem ]] = db.run {
121
+ findForQuery(repoId, nameContains).result
122
+ }
123
+
124
+ def findForPaginated (repoId : RepoId ,
125
+ nameContains : Option [String ] = None ,
126
+ offset : Option [Long ] = None ,
127
+ limit : Option [Long ] = None ): Future [PaginationResult [TargetItem ]] = db.run {
128
+ val items = findForQuery(repoId, nameContains).sortBy(t => ColumnOrdered (t.updatedAt, Ordering ().asc))
129
+ val totalItemsLength = items.length.result
130
+ val actualOffset = offset.orDefaultOffset
131
+ val actualLimit = limit.orDefaultLimit
132
+ val page = items.drop(actualOffset).take(actualLimit).result
133
+ totalItemsLength.zip(page).map{ case (total, values) => PaginationResult (values, total, actualOffset, actualLimit) }
134
+ }
135
+
110
136
def exists (repoId : RepoId , filename : TargetFilename ): Future [Boolean ] = {
111
137
findByFilename(repoId, filename)
112
138
.transform {
@@ -313,13 +339,23 @@ protected [db] class FilenameCommentRepository()(implicit db: Database, ec: Exec
313
339
.failIfNone(CommentNotFound )
314
340
}
315
341
316
- def find (repoId : RepoId , nameContains : Option [String ] = None ): Future [Seq [(TargetFilename , TargetComment )]] = db.run {
342
+ def find (repoId : RepoId , nameContains : Option [String ] = None , offset : Option [ Long ], limit : Option [ Long ] ): Future [PaginationResult [(TargetFilename , TargetComment )]] = db.run {
317
343
val allFileNameComments = filenameComments.filter(_.repoId === repoId)
318
- val comments = if (nameContains.isDefined)
344
+ val comments = if (nameContains.isDefined) {
319
345
allFileNameComments.filter(_.filename.mappedTo[String ].like(s " % ${nameContains.get}% " ))
320
- else allFileNameComments
321
- comments.map(filenameComment => (filenameComment.filename, filenameComment.comment))
322
- .result
346
+ } else allFileNameComments
347
+
348
+ comments.sortBy(_.filename)
349
+ .map(filenameComment => (filenameComment.filename, filenameComment.comment))
350
+ .paginateResult(offset.orDefaultOffset, limit.orDefaultLimit)
351
+ }
352
+
353
+ def findForFilenames (repoId : RepoId , filenames : Seq [TargetFilename ]): Future [Seq [(TargetFilename , TargetComment )]] = {
354
+ val trueRep : Rep [Boolean ] = true
355
+ val result = db.run {
356
+ filenameComments.filter(_.repoId === repoId).filter( _.filename inSet filenames ).result
357
+ }
358
+ result.map(_.map{case (_, filename, comment) => (filename, comment)})
323
359
}
324
360
325
361
def deleteAction (repoId : RepoId , filename : TargetFilename ) =
0 commit comments