Compare commits

...
6 changed files with 62 additions and 2 deletions
+3
View File
@@ -3,6 +3,9 @@
## Bugs
- Fix license detection for Flutter and Dart SDKs [#4435](https://github.com/appwrite/appwrite/pull/4435)
## Version 1.0.4
- Add secret to membership return model [#4445](https://github.com/appwrite/appwrite/pull/4445)
# Version 1.0.3
## Bugs
- Fix document audit deletion [#4429](https://github.com/appwrite/appwrite/pull/4429)
+34 -1
View File
@@ -449,8 +449,19 @@ App::post('/v1/teams/:teamId/memberships')
$events
->setParam('teamId', $team->getId())
->setParam('membershipId', $membership->getId())
->setPayload($response->output(
$membership
->setAttribute('teamName', $team->getAttribute('name'))
->setAttribute('userName', $invitee->getAttribute('name'))
->setAttribute('userEmail', $invitee->getAttribute('email'))
->setAttribute('secret', $secret),
Response::MODEL_MEMBERSHIP
))
;
// Hide secret for clients
$membership->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $secret : '');
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->dynamic(
@@ -486,6 +497,9 @@ App::get('/v1/teams/:teamId/memberships')
throw new Exception(Exception::TEAM_NOT_FOUND);
}
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$isAppUser = Auth::isAppUser(Authorization::getRoles());
$queries = Query::parseQueries($queries);
if (!empty($search)) {
@@ -525,7 +539,11 @@ App::get('/v1/teams/:teamId/memberships')
$memberships = array_filter($memberships, fn(Document $membership) => !empty($membership->getAttribute('userId')));
$memberships = array_map(function ($membership) use ($dbForProject, $team) {
$memberships = array_map(function ($membership) use ($dbForProject, $team, $isPrivilegedUser, $isAppUser) {
// Hide secret for clients
$membership->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $membership->getAttribute('secret') : '');
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
$membership
@@ -572,8 +590,14 @@ App::get('/v1/teams/:teamId/memberships/:membershipId')
throw new Exception(Exception::MEMBERSHIP_NOT_FOUND);
}
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$isAppUser = Auth::isAppUser(Authorization::getRoles());
$user = $dbForProject->getDocument('users', $membership->getAttribute('userId'));
// Hide secret for clients
$membership->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $membership->getAttribute('secret') : '');
$membership
->setAttribute('teamName', $team->getAttribute('name'))
->setAttribute('userName', $user->getAttribute('name'))
@@ -645,6 +669,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId')
->setParam('teamId', $team->getId())
->setParam('membershipId', $membership->getId());
// Hide secret for clients
$membership->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $membership->getAttribute('secret') : '');
$response->dynamic(
$membership
->setAttribute('teamName', $team->getAttribute('name'))
@@ -718,6 +745,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
throw new Exception(Exception::MEMBERSHIP_ALREADY_CONFIRMED);
}
$isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles());
$isAppUser = Auth::isAppUser(Authorization::getRoles());
$membership // Attach user to team
->setAttribute('joined', DateTime::now())
->setAttribute('confirm', true)
@@ -779,6 +809,9 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status')
->addCookie(Auth::$cookieName, Auth::encodeSession($user->getId(), $secret), (new \DateTime($expire))->getTimestamp(), '/', Config::getParam('cookieDomain'), ('https' == $protocol), true, Config::getParam('cookieSamesite'))
;
// Hide secret for clients
$membership->setAttribute('secret', ($isPrivilegedUser || $isAppUser) ? $membership->getAttribute('secret') : '');
$response->dynamic(
$membership
->setAttribute('teamName', $team->getAttribute('name'))
@@ -83,6 +83,12 @@ class Membership extends Model
'example' => 'admin',
'array' => true,
])
->addRule('secret', [
'type' => self::TYPE_STRING,
'description' => 'Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.',
'default' => '',
'example' => '',
])
;
}
@@ -32,6 +32,7 @@ trait TeamsBaseClient
$this->assertEquals($teamName, $response['body']['memberships'][0]['teamName']);
$this->assertContains('owner', $response['body']['memberships'][0]['roles']);
$this->assertContains('player', $response['body']['memberships'][0]['roles']);
$this->assertEmpty($response['body']['memberships'][0]['secret']);
$membershipId = $response['body']['memberships'][0]['$id'];
@@ -205,6 +206,7 @@ trait TeamsBaseClient
$this->assertCount(2, $response['body']['roles']);
$this->assertEquals(false, DateTime::isValid($response['body']['joined'])); // is null in DB
$this->assertEquals(false, $response['body']['confirm']);
$this->assertEmpty($response['body']['secret']);
$lastEmail = $this->getLastEmail();
+16 -1
View File
@@ -2,6 +2,7 @@
namespace Tests\E2E\Services\Teams;
use Appwrite\Auth\Auth;
use Tests\E2E\Client;
use Utopia\Database\Database;
use Utopia\Database\DateTime;
@@ -59,6 +60,7 @@ trait TeamsBaseServer
$this->assertCount(2, $response['body']['roles']);
$this->assertEquals(true, DateTime::isValid($response['body']['joined'])); // is null in DB
$this->assertEquals(true, $response['body']['confirm']);
$this->assertNotEmpty(true, $response['body']['secret']);
/**
* Test for FAILURE
@@ -110,9 +112,22 @@ trait TeamsBaseServer
$this->assertCount(2, $response['body']['roles']);
$this->assertEquals(true, DateTime::isValid($response['body']['joined']));
$this->assertEquals(true, $response['body']['confirm']);
$this->assertNotEmpty(true, $response['body']['secret']);
$userUid = $response['body']['userId'];
$membershipUid = $response['body']['$id'];
$membershipSecret = $response['body']['secret'];
// Ensure secret is present on GET too, but hashed
$response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals(200, $response['headers']['status-code']);
$this->assertEquals($membershipUid, $response['body']['$id']);
$this->assertNotEmpty(true, $response['body']['secret']);
$this->assertEquals(Auth::hash($membershipSecret), $response['body']['secret']);
// $response = $this->client->call(Client::METHOD_GET, '/users/'.$userUid, array_merge([
// 'content-type' => 'application/json',
@@ -211,7 +226,7 @@ trait TeamsBaseServer
$this->assertEquals($roles[0], $response['body']['roles'][0]);
$this->assertEquals($roles[1], $response['body']['roles'][1]);
$this->assertEquals($roles[2], $response['body']['roles'][2]);
$this->assertNotEmpty(true, $response['body']['secret']);
/**
* Test for FAILURE
@@ -101,6 +101,7 @@ class TeamsConsoleClientTest extends Scope
]);
$this->assertEquals(201, $response['headers']['status-code']);
$this->assertEmpty($response['body']['secret']);
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',