Skip to content

Commit cba9f5d

Browse files
committed
grant shares to users
Signed-off-by: Robert Landers <landers.robert@gmail.com>
1 parent 9f3b9fd commit cba9f5d

4 files changed

Lines changed: 115 additions & 3 deletions

File tree

cli/lib/api.go

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,13 +315,13 @@ func Startup(ctx context.Context, js jetstream.JetStream, logger *zap.Logger, po
315315
}
316316
}
317317

318-
// POST /entity/{name}/{id}/share/{userid}: share ownership of the resource with another user
318+
// PUT /entity/{name}/{id}/share/{userid}: share ownership of the resource with another user
319319
r.HandleFunc("/entity/{name}/{id}/share/{userid}", func(writer http.ResponseWriter, request *http.Request) {
320320
if stop := handleCors(writer, request); stop {
321321
return
322322
}
323323

324-
if request.Method != "POST" {
324+
if request.Method != "PUT" {
325325
http.Error(writer, "Method Not Allowed", http.StatusMethodNotAllowed)
326326
return
327327
}
@@ -355,6 +355,77 @@ func Startup(ctx context.Context, js jetstream.JetStream, logger *zap.Logger, po
355355
logger.Error("Failed to share ownership", zap.Error(err))
356356
http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
357357
}
358+
359+
err = r.Update(ctx, logger)
360+
if err != nil {
361+
logger.Error("Failed to update resource", zap.Error(err))
362+
http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
363+
}
364+
365+
logger.Info("Shared ownership", zap.String("id", id.String()), zap.String("newUser", newUser))
366+
http.Error(writer, "", http.StatusOK)
367+
})
368+
369+
// PUT /entity/{name}/{id}/grant/{user}/{operation}
370+
r.HandleFunc("/entity/{name}/{id}/grant/{type}/{user}/{operation}", func(writer http.ResponseWriter, request *http.Request) {
371+
if stop := handleCors(writer, request); stop {
372+
return
373+
}
374+
375+
vars := mux.Vars(request)
376+
id := &glue.EntityId{
377+
Name: strings.TrimSpace(vars["name"]),
378+
Id: strings.TrimSpace(vars["id"]),
379+
}
380+
stateId := id.ToStateId()
381+
382+
operation := auth.Owner
383+
switch strings.ToLower(vars["operation"]) {
384+
case "signal":
385+
operation = auth.Signal
386+
break
387+
case "completion":
388+
operation = auth.Completion
389+
break
390+
case "output":
391+
operation = auth.Output
392+
case "call":
393+
operation = auth.Call
394+
case "lock":
395+
operation = auth.Lock
396+
case "sharePlus":
397+
operation = auth.SharePlus
398+
case "shareMinus":
399+
operation = auth.ShareMinus
400+
default:
401+
http.Error(writer, "", http.StatusBadRequest)
402+
return
403+
}
404+
405+
r, err := rm.DiscoverResource(ctx, stateId, logger, true)
406+
if err != nil {
407+
logger.Error("Failed to discover resource", zap.Error(err))
408+
http.Error(writer, "", http.StatusNotFound)
409+
}
410+
411+
switch vars["type"] {
412+
case "user":
413+
err = r.GrantUser(auth.UserId(vars["user"]), operation, ctx)
414+
case "role":
415+
err = r.GrantRole(auth.Role(vars["user"]), operation, ctx)
416+
}
417+
if err != nil {
418+
logger.Error("Failed to grant resource", zap.Error(err))
419+
http.Error(writer, "", http.StatusForbidden)
420+
}
421+
422+
err = r.Update(ctx, logger)
423+
if err != nil {
424+
logger.Error("Failed to update resource", zap.Error(err))
425+
http.Error(writer, "", http.StatusInternalServerError)
426+
}
427+
428+
http.Error(writer, "", http.StatusOK)
358429
})
359430

360431
// GET /entity/{name}/{id}

src/DurableClient.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
namespace Bottledcode\DurablePhp;
2626

2727
use Amp\Http\Client\HttpClientBuilder;
28+
use Bottledcode\DurablePhp\Events\Shares\Operation;
2829
use Bottledcode\DurablePhp\Search\EntityFilter;
2930
use Bottledcode\DurablePhp\State\EntityId;
3031
use Bottledcode\DurablePhp\State\EntityState;
@@ -147,4 +148,14 @@ public function shareEntityOwnership(EntityId $id, string $with): void
147148
{
148149
$this->entityClient->shareEntityOwnership($id, $with);
149150
}
151+
152+
public function grantEntityAccessToUser(EntityId $id, string $user, Operation $operation): void
153+
{
154+
$this->entityClient->grantEntityAccessToUser($id, $user, $operation);
155+
}
156+
157+
public function grantEntityAccessToRole(EntityId $id, string $role, Operation $operation): void
158+
{
159+
$this->entityClient->grantEntityAccessToRole($id, $role, $operation);
160+
}
150161
}

src/EntityClientInterface.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
namespace Bottledcode\DurablePhp;
2626

27+
use Bottledcode\DurablePhp\Events\Shares\Operation;
2728
use Bottledcode\DurablePhp\Search\EntityFilter;
2829
use Bottledcode\DurablePhp\State\EntityId;
2930
use Bottledcode\DurablePhp\State\EntityState;
@@ -82,4 +83,8 @@ public function getEntitySnapshot(EntityId $entityId): ?EntityState;
8283
public function deleteEntity(EntityId $entityId): void;
8384

8485
public function shareEntityOwnership(EntityId $id, string $with): void;
86+
87+
public function grantEntityAccessToUser(EntityId $id, string $user, Operation $operation): void;
88+
89+
public function grantEntityAccessToRole(EntityId $id, string $role, Operation $operation): void;
8590
}

src/RemoteEntityClient.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
use Amp\Http\Client\HttpClient;
2828
use Amp\Http\Client\Request;
29+
use Bottledcode\DurablePhp\Events\Shares\Operation;
2930
use Bottledcode\DurablePhp\Proxy\SpyException;
3031
use Bottledcode\DurablePhp\Proxy\SpyProxy;
3132
use Bottledcode\DurablePhp\Search\EntityFilter;
@@ -166,7 +167,7 @@ public function deleteEntity(EntityId $entityId): void
166167

167168
public function shareEntityOwnership(EntityId $id, string $with): void
168169
{
169-
$req = new Request("{$this->apiHost}/entity/{$id->name}/{$id->id}/share/{$with}", 'POST');
170+
$req = new Request("{$this->apiHost}/entity/{$id->name}/{$id->id}/share/{$with}", 'PUT');
170171
if ($this->userToken) {
171172
$req->setHeader('Authorization', 'Bearer ' . $this->userToken);
172173
}
@@ -175,4 +176,28 @@ public function shareEntityOwnership(EntityId $id, string $with): void
175176
throw new Exception('Failed to share ownership');
176177
}
177178
}
179+
180+
public function grantEntityAccessToUser(EntityId $id, string $user, Operation $operation): void
181+
{
182+
$req = new Request("{$this->apiHost}/entity/{$id->name}/{$id->id}/grant/user/{$user}/{$operation->value}", 'PUT');
183+
if ($this->userToken) {
184+
$req->setHeader('Authorization', 'Bearer ' . $this->userToken);
185+
}
186+
$result = $this->client->request($req);
187+
if ($result->getStatus() !== 200) {
188+
throw new Exception('Failed to grant access');
189+
}
190+
}
191+
192+
public function grantEntityAccessToRole(EntityId $id, string $role, Operation $operation): void
193+
{
194+
$req = new Request("{$this->apiHost}/entity/{$id->name}/{$id->id}/grant/role/{$role}/{$operation->value}", 'PUT');
195+
if ($this->userToken) {
196+
$req->setHeader('Authorization', 'Bearer ' . $this->userToken);
197+
}
198+
$result = $this->client->request($req);
199+
if ($result->getStatus() !== 200) {
200+
throw new Exception('Failed to grant access');
201+
}
202+
}
178203
}

0 commit comments

Comments
 (0)