@@ -220,53 +220,80 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
220220 * - 500 Internal Server Error
221221 */
222222 override def create (user : Identity , entityName : FullyQualifiedEntityName )(implicit transid : TransactionId ) = {
223- parameter(' overwrite ? false , ' deleteOld ? false ) { (overwrite, deleteOld) =>
224- entity(as[WhiskActionPut ]) { content =>
225- val request = content.resolve(user.namespace)
226- val checkAdditionalPrivileges = entitleReferencedEntities(user, Privilege .READ , request.exec).flatMap {
227- case _ => entitlementProvider.check(user, content.exec)
228- }
229-
230- onComplete(checkAdditionalPrivileges) {
231- case Success (_) =>
232- onComplete(WhiskActionVersionList .get(entityName, entityStore, false )) {
233- case Success (result) if (result.versions.size >= actionMaxVersionLimit && ! deleteOld) =>
234- terminate(
235- Forbidden ,
236- s " [PUT] entity has ${result.versions.size} versions exist which exceed $actionMaxVersionLimit, delete one of them before create new one or pass deleteOld=true to delete oldest version automatically " )
237- case Success (result) =>
238- val id = result.matchedDocId(None ).getOrElse(entityName.toDocId)
239- putEntity(
240- WhiskAction ,
241- entityStore,
242- id,
243- true ,
244- update(user, request) _,
245- () => {
246- make(user, entityName, request)
247- },
248- postProcess = Some { action : WhiskAction =>
249- // delete oldest version when created successfully
250- if (result.versions.size >= actionMaxVersionLimit) {
251- val id = result.versions.minBy(_._1)._2
252- WhiskAction .get(entityStore, DocId (id)) flatMap { entity =>
253- WhiskAction .del(entityStore, DocInfo ! (id, entity.rev.rev)).map(_ => entity)
254- } andThen {
255- case _ =>
256- WhiskActionVersionList .deleteCache(entityName)
257- }
258- } else {
223+ parameter(' overwrite ? false , ' deleteOld ? false , ' defaultVersion .as[String ] ? " " ) {
224+ (overwrite, deleteOld, defaultVersion) =>
225+ entity(as[WhiskActionPut ]) { content =>
226+ Try {
227+ SemVer (defaultVersion)
228+ } match {
229+ case Success (version) =>
230+ onComplete(WhiskActionVersionList .get(entityName, entityStore, false )) {
231+ case Success (result) if (result.versions.keys.toVector.contains(version)) =>
232+ val dv = WhiskActionDefaultVersion (entityName.path, entityName.name, Some (version))
233+ putEntity(
234+ WhiskActionDefaultVersion ,
235+ entityStore,
236+ dv.docid,
237+ true ,
238+ (old : WhiskActionDefaultVersion ) =>
239+ Future .successful(dv.revision[WhiskActionDefaultVersion ](old.rev)),
240+ () => Future .successful(dv),
241+ postProcess = Some { version : WhiskActionDefaultVersion =>
259242 WhiskActionVersionList .deleteCache(entityName)
260- }
261- complete(OK , action)
262- })
263- case Failure (f) =>
264- terminate(InternalServerError )
265- }
266- case Failure (f) =>
267- super .handleEntitlementFailure(f)
243+ complete(OK , version)
244+ })
245+ case Success (_) =>
246+ terminate(Forbidden , s " [PUT] entity doesn't has version $version" )
247+ case Failure (_) =>
248+ terminate(InternalServerError )
249+ }
250+ case Failure (_) =>
251+ val request = content.resolve(user.namespace)
252+ val checkAdditionalPrivileges = entitleReferencedEntities(user, Privilege .READ , request.exec).flatMap {
253+ case _ => entitlementProvider.check(user, content.exec)
254+ }
255+
256+ onComplete(checkAdditionalPrivileges) {
257+ case Success (_) =>
258+ onComplete(WhiskActionVersionList .get(entityName, entityStore, false )) {
259+ case Success (result) if (result.versions.size >= actionMaxVersionLimit && ! deleteOld) =>
260+ terminate(
261+ Forbidden ,
262+ s " [PUT] entity has ${result.versions.size} versions exist which exceed $actionMaxVersionLimit, delete one of them before create new one or pass deleteOld=true to delete oldest version automatically " )
263+ case Success (result) =>
264+ val id = result.matchedDocId(None ).getOrElse(entityName.toDocId)
265+ putEntity(
266+ WhiskAction ,
267+ entityStore,
268+ id,
269+ true ,
270+ update(user, request) _,
271+ () => {
272+ make(user, entityName, request)
273+ },
274+ postProcess = Some { action : WhiskAction =>
275+ // delete oldest version when created successfully
276+ if (result.versions.size >= actionMaxVersionLimit) {
277+ val id = result.versions.minBy(_._1)._2
278+ WhiskAction .get(entityStore, DocId (id)) flatMap { entity =>
279+ WhiskAction .del(entityStore, DocInfo ! (id, entity.rev.rev)).map(_ => entity)
280+ } andThen {
281+ case _ =>
282+ WhiskActionVersionList .deleteCache(entityName)
283+ }
284+ } else {
285+ WhiskActionVersionList .deleteCache(entityName)
286+ }
287+ complete(OK , action)
288+ })
289+ case Failure (f) =>
290+ terminate(InternalServerError )
291+ }
292+ case Failure (f) =>
293+ super .handleEntitlementFailure(f)
294+ }
295+ }
268296 }
269- }
270297 }
271298 }
272299
@@ -388,10 +415,14 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
388415 docId,
389416 (a : WhiskAction ) => Future .successful({}),
390417 postProcess = Some { action : WhiskAction =>
418+ // when default version is deleted or all versions are deleted, delete the default version entity
419+ if (version == results.defaultVersion || results.versions.size == 1 )
420+ deleteDefaultVersion(
421+ WhiskActionDefaultVersion (entityName.path, entityName.name, results.defaultVersion))
391422 WhiskActionVersionList .deleteCache(entityName)
392423 complete(OK , action)
393424 })
394- case None if ( ! deleteAll && results.versions.size > 1 ) =>
425+ case None if ! deleteAll && results.versions.size > 1 =>
395426 terminate(
396427 Forbidden ,
397428 s " [DEL] entity version not provided, you need to specify deleteAll=true to delete all versions for action $entityName" )
@@ -412,6 +443,10 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
412443 case _ =>
413444 WhiskActionVersionList
414445 .deleteCache(entityName) // invalidate version list cache after all deletion completed
446+ deleteDefaultVersion(WhiskActionDefaultVersion (
447+ entityName.path,
448+ entityName.name,
449+ results.defaultVersion)) // delete default version entity since all versions are deleted
415450 }
416451
417452 onComplete(deleteFuture) {
@@ -443,6 +478,19 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
443478 }
444479 }
445480
481+ private def deleteDefaultVersion (defaultVersion : WhiskActionDefaultVersion )(implicit transid : TransactionId ): Unit = {
482+ WhiskActionDefaultVersion .get(entityStore, defaultVersion.docid) map { entity =>
483+ WhiskActionDefaultVersion .del(entityStore, defaultVersion.docid.asDocInfo(entity.rev)) andThen {
484+ case Success (_) =>
485+ logging.info(this , s " [DEL] default version for ${defaultVersion.fullyQualifiedName(false )} is deleted " )
486+ case Failure (t) =>
487+ logging.error(
488+ this ,
489+ s " [DEL] failed to delete default version for ${defaultVersion.fullyQualifiedName(false )}, error: $t" )
490+ }
491+ }
492+ }
493+
446494 /** Checks for package binding case. we don't want to allow get for a package binding in shared package */
447495 private def fetchEntity (entityName : FullyQualifiedEntityName ,
448496 env : Option [Parameters ],
@@ -499,10 +547,17 @@ trait WhiskActionsApi extends WhiskCollectionAPI with PostActionActivation with
499547 */
500548 override def fetch (user : Identity , entityName : FullyQualifiedEntityName , env : Option [Parameters ])(
501549 implicit transid : TransactionId ) = {
502- parameter(' code ? true , ' version .as[SemVer ] ? ) { (code, version) =>
503- // check if execute only is enabled, and if there is a discrepancy between the current user's namespace
504- // and that of the entity we are trying to fetch
505- if (executeOnly && user.namespace.name != entityName.namespace) {
550+ parameter(' code ? true , ' version .as[SemVer ] ? , ' showVersions ? false ) { (code, version, showVersions) =>
551+ if (showVersions) {
552+ onComplete(WhiskActionVersionList .get(entityName, entityStore)) {
553+ case Success (res) =>
554+ complete(OK , res)
555+ case Failure (t) =>
556+ terminate(Forbidden , forbiddenGetAction(entityName.path.asString))
557+ }
558+ // check if execute only is enabled, and if there is a discrepancy between the current user's namespace
559+ // and that of the entity we are trying to fetch
560+ } else if (executeOnly && user.namespace.name != entityName.namespace) {
506561 terminate(Forbidden , forbiddenGetAction(entityName.path.asString))
507562 } else {
508563 fetchEntity(entityName, env, code, version)
0 commit comments