refactor(insights): nest CTA execution and dismissal as sub-resources

Move POST /v1/insights/:id/dismiss to /v1/insights/:id/dismissals
and POST /v1/insights/:id/ctas/:ctaId/trigger to
/v1/insights/:id/ctas/:ctaId/executions, with the corresponding
class moves into Http/Insights/Dismissal/Create.php and
Http/CTA/Execution/Create.php. Rename the response model to
InsightCtaExecution and update events.php to surface dismissal
and execution as resource events with create verbs. The reshape
matches the rest of the API where verbs hang off plural sub-resources.
This commit is contained in:
Jake Barnby
2026-05-01 14:04:31 +12:00
parent d15be21923
commit da5a137b98
7 changed files with 45 additions and 36 deletions
+14 -4
View File
@@ -440,15 +440,25 @@ return [
'delete' => [
'$description' => 'This event triggers when an insight is deleted.',
],
'dismiss' => [
'$description' => 'This event triggers when an insight is dismissed.',
'dismissals' => [
'$model' => Response::MODEL_INSIGHT,
'$resource' => true,
'$description' => 'This event triggers on any insight dismissal event.',
'create' => [
'$description' => 'This event triggers when an insight is dismissed.',
],
],
'ctas' => [
'$model' => Response::MODEL_INSIGHT_CTA,
'$resource' => true,
'$description' => 'This event triggers on any insight CTA event.',
'trigger' => [
'$description' => 'This event triggers when an insight CTA is executed.',
'executions' => [
'$model' => Response::MODEL_INSIGHT_CTA_EXECUTION,
'$resource' => true,
'$description' => 'This event triggers on any insight CTA execution event.',
'create' => [
'$description' => 'This event triggers when an insight CTA is executed.',
],
],
],
],
+2 -2
View File
@@ -92,7 +92,7 @@ use Appwrite\Utopia\Response\Model\Identity;
use Appwrite\Utopia\Response\Model\Index;
use Appwrite\Utopia\Response\Model\Insight;
use Appwrite\Utopia\Response\Model\InsightCta;
use Appwrite\Utopia\Response\Model\InsightCtaResult;
use Appwrite\Utopia\Response\Model\InsightCtaExecution;
use Appwrite\Utopia\Response\Model\Installation;
use Appwrite\Utopia\Response\Model\JWT;
use Appwrite\Utopia\Response\Model\Key;
@@ -511,7 +511,7 @@ Response::setModel(new MigrationReport());
Response::setModel(new MigrationFirebaseProject());
Response::setModel(new Insight());
Response::setModel(new InsightCta());
Response::setModel(new InsightCtaResult());
Response::setModel(new InsightCtaExecution());
// Tests (keep last)
Response::setModel(new Mock());
@@ -1,6 +1,6 @@
<?php
namespace Appwrite\Platform\Modules\Insights\Http\Cta;
namespace Appwrite\Platform\Modules\Insights\Http\CTA\Execution;
use Appwrite\Event\Database as EventDatabase;
use Appwrite\Event\Event;
@@ -19,26 +19,26 @@ use Utopia\Platform\Scope\HTTP;
use Utopia\Registry\Registry as UtopiaRegistry;
use Utopia\Validator\Text;
class Trigger extends Action
class Create extends Action
{
use HTTP;
public static function getName()
{
return 'triggerInsightCta';
return 'createInsightCtaExecution';
}
public function __construct()
{
$this
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/insights/:insightId/ctas/:ctaId/trigger')
->desc('Trigger insight CTA')
->setHttpPath('/v1/insights/:insightId/ctas/:ctaId/executions')
->desc('Create insight CTA execution')
->groups(['api', 'insights'])
->label('scope', 'insights.write')
->label('event', 'insights.[insightId].ctas.[ctaId].trigger')
->label('event', 'insights.[insightId].ctas.[ctaId].executions.create')
->label('resourceType', RESOURCE_TYPE_INSIGHTS)
->label('audits.event', 'insight.cta.trigger')
->label('audits.event', 'insight.cta.execution.create')
->label('audits.resource', 'insight/{request.insightId}')
->label('abuse-key', 'projectId:{projectId},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
@@ -46,15 +46,15 @@ class Trigger extends Action
->label('sdk', new Method(
namespace: 'insights',
group: 'insights',
name: 'triggerCta',
name: 'createCtaExecution',
description: <<<EOT
Trigger a CTA attached to an insight. Looks up the registered server-side action by name, validates the CTA params, and executes the action on behalf of the caller.
Execute a CTA attached to an insight. Looks up the registered server-side action by name, validates the CTA params, and runs the action on behalf of the caller.
EOT,
auth: [AuthType::ADMIN, AuthType::KEY],
responses: [
new SDKResponse(
code: Response::STATUS_CODE_OK,
model: Response::MODEL_INSIGHT_CTA_RESULT,
model: Response::MODEL_INSIGHT_CTA_EXECUTION,
),
]
))
@@ -167,6 +167,6 @@ class Trigger extends Action
'action' => $actionName,
'status' => $status,
'result' => $resultPayload,
]), Response::MODEL_INSIGHT_CTA_RESULT);
]), Response::MODEL_INSIGHT_CTA_EXECUTION);
}
}
@@ -1,6 +1,6 @@
<?php
namespace Appwrite\Platform\Modules\Insights\Http\Insights;
namespace Appwrite\Platform\Modules\Insights\Http\Insights\Dismissal;
use Appwrite\Event\Event;
use Appwrite\Extend\Exception;
@@ -15,26 +15,26 @@ use Utopia\Database\Validator\UID;
use Utopia\Platform\Action;
use Utopia\Platform\Scope\HTTP;
class Dismiss extends Action
class Create extends Action
{
use HTTP;
public static function getName()
{
return 'dismissInsight';
return 'createInsightDismissal';
}
public function __construct()
{
$this
->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST)
->setHttpPath('/v1/insights/:insightId/dismiss')
->desc('Dismiss insight')
->setHttpPath('/v1/insights/:insightId/dismissals')
->desc('Create insight dismissal')
->groups(['api', 'insights'])
->label('scope', 'insights.write')
->label('event', 'insights.[insightId].dismiss')
->label('event', 'insights.[insightId].dismissals.create')
->label('resourceType', RESOURCE_TYPE_INSIGHTS)
->label('audits.event', 'insight.dismiss')
->label('audits.event', 'insight.dismissal.create')
->label('audits.resource', 'insight/{response.$id}')
->label('abuse-key', 'projectId:{projectId},userId:{userId}')
->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT)
@@ -42,7 +42,7 @@ class Dismiss extends Action
->label('sdk', new Method(
namespace: 'insights',
group: 'insights',
name: 'dismiss',
name: 'createDismissal',
description: <<<EOT
Dismiss an insight. Stamps the current user and time on the insight without deleting it, so analyzers can see it has been acknowledged.
EOT,
@@ -2,10 +2,10 @@
namespace Appwrite\Platform\Modules\Insights\Services;
use Appwrite\Platform\Modules\Insights\Http\Cta\Trigger as TriggerCta;
use Appwrite\Platform\Modules\Insights\Http\CTA\Execution\Create as CreateInsightCtaExecution;
use Appwrite\Platform\Modules\Insights\Http\Insights\Create as CreateInsight;
use Appwrite\Platform\Modules\Insights\Http\Insights\Delete as DeleteInsight;
use Appwrite\Platform\Modules\Insights\Http\Insights\Dismiss as DismissInsight;
use Appwrite\Platform\Modules\Insights\Http\Insights\Dismissal\Create as CreateInsightDismissal;
use Appwrite\Platform\Modules\Insights\Http\Insights\Get as GetInsight;
use Appwrite\Platform\Modules\Insights\Http\Insights\Update as UpdateInsight;
use Appwrite\Platform\Modules\Insights\Http\Insights\XList as ListInsights;
@@ -21,9 +21,8 @@ class Http extends Service
$this->addAction(GetInsight::getName(), new GetInsight());
$this->addAction(ListInsights::getName(), new ListInsights());
$this->addAction(UpdateInsight::getName(), new UpdateInsight());
$this->addAction(DismissInsight::getName(), new DismissInsight());
$this->addAction(DeleteInsight::getName(), new DeleteInsight());
$this->addAction(TriggerCta::getName(), new TriggerCta());
$this->addAction(CreateInsightDismissal::getName(), new CreateInsightDismissal());
$this->addAction(CreateInsightCtaExecution::getName(), new CreateInsightCtaExecution());
}
}
+1 -1
View File
@@ -334,7 +334,7 @@ class Response extends SwooleResponse
public const MODEL_INSIGHT = 'insight';
public const MODEL_INSIGHT_LIST = 'insightList';
public const MODEL_INSIGHT_CTA = 'insightCta';
public const MODEL_INSIGHT_CTA_RESULT = 'insightCtaResult';
public const MODEL_INSIGHT_CTA_EXECUTION = 'insightCtaExecution';
// Console
public const MODEL_CONSOLE_VARIABLES = 'consoleVariables';
@@ -5,20 +5,20 @@ namespace Appwrite\Utopia\Response\Model;
use Appwrite\Utopia\Response;
use Appwrite\Utopia\Response\Model;
class InsightCtaResult extends Model
class InsightCtaExecution extends Model
{
public function __construct()
{
$this
->addRule('insightId', [
'type' => self::TYPE_STRING,
'description' => 'ID of the insight the CTA was triggered against.',
'description' => 'ID of the insight the CTA was executed against.',
'default' => '',
'example' => '5e5ea5c16897e',
])
->addRule('ctaId', [
'type' => self::TYPE_STRING,
'description' => 'ID of the CTA that was triggered.',
'description' => 'ID of the CTA that was executed.',
'default' => '',
'example' => 'createIndex',
])
@@ -44,11 +44,11 @@ class InsightCtaResult extends Model
public function getName(): string
{
return 'InsightCtaResult';
return 'InsightCtaExecution';
}
public function getType(): string
{
return Response::MODEL_INSIGHT_CTA_RESULT;
return Response::MODEL_INSIGHT_CTA_EXECUTION;
}
}