2019-05-09 18:54:39 +12:00
< ? php
2019-08-11 17:18:10 +12:00
global $utopia , $register , $request , $response , $projectDB , $project , $user , $audit , $mode , $clients ;
2019-05-09 18:54:39 +12:00
use Utopia\Exception ;
2019-06-09 20:51:10 +12:00
use Utopia\Response ;
2019-05-09 18:54:39 +12:00
use Utopia\Validator\Email ;
use Utopia\Validator\Text ;
use Utopia\Validator\Host ;
use Utopia\Validator\Range ;
use Utopia\Validator\ArrayList ;
use Utopia\Validator\WhiteList ;
use Utopia\Locale\Locale ;
use Database\Database ;
use Database\Document ;
use Database\Validator\UID ;
use Database\Validator\Authorization ;
use Template\Template ;
use Auth\Auth ;
2019-12-15 16:03:43 +13:00
include_once '../shared/api.php' ;
2019-11-30 07:26:06 +13:00
2019-05-09 18:54:39 +12:00
$utopia -> get ( '/v1/teams' )
-> desc ( 'List Teams' )
-> label ( 'scope' , 'teams.read' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'listTeams' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/list-teams.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'search' , '' , function () { return new Text ( 256 ); }, 'Search term to filter your list results.' , true )
-> param ( 'limit' , 25 , function () { return new Range ( 0 , 100 ); }, 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.' , true )
-> param ( 'offset' , 0 , function () { return new Range ( 0 , 2000 ); }, 'Results offset. The default value is 0. Use this param to manage pagination.' , true )
-> param ( 'orderType' , 'ASC' , function () { return new WhiteList ([ 'ASC' , 'DESC' ]); }, 'Order result by ASC or DESC order.' , true )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $search , $limit , $offset , $orderType ) use ( $response , $projectDB ) {
2019-05-09 18:54:39 +12:00
$results = $projectDB -> getCollection ([
'limit' => $limit ,
'offset' => $offset ,
'orderField' => 'dateCreated' ,
'orderType' => $orderType ,
'orderCast' => 'int' ,
'search' => $search ,
'filters' => [
2019-09-07 05:10:41 +12:00
'$collection=' . Database :: SYSTEM_COLLECTION_TEAMS ,
2019-05-09 18:54:39 +12:00
],
]);
$response -> json ([ 'sum' => $projectDB -> getSum (), 'teams' => $results ]);
}
);
$utopia -> get ( '/v1/teams/:teamId' )
-> desc ( 'Get Team' )
-> label ( 'scope' , 'teams.read' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'getTeam' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/get-team.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'teamId' , '' , function () { return new UID (); }, 'Team unique ID.' )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $teamId ) use ( $response , $projectDB ) {
2019-05-09 18:54:39 +12:00
$team = $projectDB -> getDocument ( $teamId );
2019-09-07 05:10:41 +12:00
if ( empty ( $team -> getUid ()) || Database :: SYSTEM_COLLECTION_TEAMS != $team -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team not found' , 404 );
}
$response -> json ( $team -> getArrayCopy ([]));
}
);
$utopia -> get ( '/v1/teams/:teamId/members' )
-> desc ( 'Get Team Members' )
-> label ( 'scope' , 'teams.read' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'getTeamMembers' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/get-team-members.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'teamId' , '' , function () { return new UID (); }, 'Team unique ID.' )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $teamId ) use ( $response , $projectDB ) {
2019-05-09 18:54:39 +12:00
$team = $projectDB -> getDocument ( $teamId );
2019-09-07 05:10:41 +12:00
if ( empty ( $team -> getUid ()) || Database :: SYSTEM_COLLECTION_TEAMS != $team -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team not found' , 404 );
}
$memberships = $projectDB -> getCollection ([
'limit' => 50 ,
'offset' => 0 ,
'filters' => [
2019-09-07 05:10:41 +12:00
'$collection=' . Database :: SYSTEM_COLLECTION_MEMBERSHIPS ,
'teamId=' . $teamId ,
],
2019-05-09 18:54:39 +12:00
]);
$users = [];
foreach ( $memberships as $member ) {
2019-09-07 05:10:41 +12:00
if ( empty ( $member -> getAttribute ( 'userId' , null ))) {
2019-05-09 18:54:39 +12:00
continue ;
}
$temp = $projectDB -> getDocument ( $member -> getAttribute ( 'userId' , null )) -> getArrayCopy ([ '$uid' , 'email' , 'name' ]);
$temp [ 'inviteId' ] = $member -> getUid ();
$temp [ 'roles' ] = $member -> getAttribute ( 'roles' , []);
$temp [ 'confirm' ] = $member -> getAttribute ( 'confirm' , false );
$temp [ 'joined' ] = $member -> getAttribute ( 'joined' , 0 );
$users [] = $temp ;
}
usort ( $users , function ( $a , $b ) {
2019-09-07 05:10:41 +12:00
if ( $a [ 'joined' ] === 0 || $b [ 'joined' ] === 0 ) {
2019-05-09 18:54:39 +12:00
return $b [ 'joined' ] - $a [ 'joined' ];
}
2019-09-07 05:10:41 +12:00
2019-05-09 18:54:39 +12:00
return $a [ 'joined' ] - $b [ 'joined' ];
});
$response -> json ( $users );
}
);
$utopia -> post ( '/v1/teams' )
-> desc ( 'Create Team' )
-> label ( 'scope' , 'teams.write' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'createTeam' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/create-team.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'name' , null , function () { return new Text ( 100 ); }, 'Team name.' )
-> param ( 'roles' , [ 'owner' ], function () { return new ArrayList ( new Text ( 128 )); }, 'User roles array. Use this param to set the roles in the team for the user who created the team. The default role is **owner**, a role can be any string.' , true )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $name , $roles ) use ( $response , $projectDB , $user , $mode ) {
2019-05-09 18:54:39 +12:00
Authorization :: disable ();
$team = $projectDB -> createDocument ([
'$collection' => Database :: SYSTEM_COLLECTION_TEAMS ,
2019-09-07 05:10:41 +12:00
'$permissions' => [
'read' => [ 'team:{self}' ],
'write' => [ 'team:{self}/owner' ],
2019-05-09 18:54:39 +12:00
],
'name' => $name ,
'sum' => ( $mode !== APP_MODE_ADMIN ) ? 1 : 0 ,
'dateCreated' => time (),
]);
Authorization :: enable ();
2019-09-07 05:10:41 +12:00
if ( false === $team ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed saving team to DB' , 500 );
}
2019-09-07 05:10:41 +12:00
if ( $mode !== APP_MODE_ADMIN ) { // Don't add user on admin mode
2019-05-09 18:54:39 +12:00
$membership = new Document ([
'$collection' => Database :: SYSTEM_COLLECTION_MEMBERSHIPS ,
2019-09-07 05:10:41 +12:00
'$permissions' => [
'read' => [ 'user:' . $user -> getUid (), 'team:' . $team -> getUid ()],
'write' => [ 'user:' . $user -> getUid (), 'team:' . $team -> getUid () . '/owner' ],
2019-05-09 18:54:39 +12:00
],
'userId' => $user -> getUid (),
'teamId' => $team -> getUid (),
'roles' => $roles ,
'invited' => time (),
'joined' => time (),
'confirm' => true ,
'secret' => '' ,
]);
// Attach user to team
$user -> setAttribute ( 'memberships' , $membership , Document :: SET_TYPE_APPEND );
$user = $projectDB -> updateDocument ( $user -> getArrayCopy ());
2019-09-07 05:10:41 +12:00
if ( false === $user ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed saving user to DB' , 500 );
}
}
2019-06-09 20:51:10 +12:00
$response
-> setStatusCode ( Response :: STATUS_CODE_CREATED )
-> json ( $team -> getArrayCopy ())
;
2019-05-09 18:54:39 +12:00
}
);
$utopia -> put ( '/v1/teams/:teamId' )
-> desc ( 'Update Team' )
-> label ( 'scope' , 'teams.write' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'updateTeam' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/update-team.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'teamId' , '' , function () { return new UID (); }, 'Team unique ID.' )
-> param ( 'name' , null , function () { return new Text ( 100 ); }, 'Team name.' )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $teamId , $name ) use ( $response , $projectDB ) {
2019-05-09 18:54:39 +12:00
$team = $projectDB -> getDocument ( $teamId );
2019-09-07 05:10:41 +12:00
if ( empty ( $team -> getUid ()) || Database :: SYSTEM_COLLECTION_TEAMS != $team -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team not found' , 404 );
}
$team = $projectDB -> updateDocument ( array_merge ( $team -> getArrayCopy (), [
'name' => $name ,
]));
2019-09-07 05:10:41 +12:00
if ( false === $team ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed saving team to DB' , 500 );
}
$response -> json ( $team -> getArrayCopy ());
}
);
$utopia -> delete ( '/v1/teams/:teamId' )
-> desc ( 'Delete Team' )
-> label ( 'scope' , 'teams.write' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'deleteTeam' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/delete-team.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'teamId' , '' , function () { return new UID (); }, 'Team unique ID.' )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $teamId ) use ( $response , $projectDB ) {
2019-05-09 18:54:39 +12:00
$team = $projectDB -> getDocument ( $teamId );
2019-09-07 05:10:41 +12:00
if ( empty ( $team -> getUid ()) || Database :: SYSTEM_COLLECTION_TEAMS != $team -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team not found' , 404 );
}
$memberships = $projectDB -> getCollection ([
'limit' => 2000 , // TODO add members limit
'offset' => 0 ,
'filters' => [
2019-09-07 05:10:41 +12:00
'$collection=' . Database :: SYSTEM_COLLECTION_MEMBERSHIPS ,
'teamId=' . $teamId ,
],
2019-05-09 18:54:39 +12:00
]);
foreach ( $memberships as $member ) {
2019-09-07 05:10:41 +12:00
if ( ! $projectDB -> deleteDocument ( $member )) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed to remove membership for team from DB' , 500 );
}
}
2019-09-07 05:10:41 +12:00
if ( ! $projectDB -> deleteDocument ( $teamId )) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed to remove team from DB' , 500 );
}
$response -> noContent ();
}
);
// Memberships
$utopia -> post ( '/v1/teams/:teamId/memberships' )
-> desc ( 'Create Team Membership' )
-> label ( 'scope' , 'account' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'createTeamMembership' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/create-team-membership.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'teamId' , '' , function () { return new UID (); }, 'Team unique ID.' )
-> param ( 'email' , '' , function () { return new Email (); }, 'New team member email address.' )
-> param ( 'name' , '' , function () { return new Text ( 100 ); }, 'New team member name.' , true )
-> param ( 'roles' , [], function () { return new ArrayList ( new Text ( 128 )); }, 'Invite roles array. Learn more about [roles and permissions](/docs/permissions).' )
-> param ( 'redirect' , '' , function () use ( $clients ) { return new Host ( $clients ); }, 'Reset page to redirect user back to your app from the invitation email.' )
2019-05-09 18:54:39 +12:00
-> action (
2019-11-03 18:06:29 +13:00
function ( $teamId , $email , $name , $roles , $redirect ) use ( $response , $register , $project , $user , $audit , $projectDB ) {
2019-05-09 18:54:39 +12:00
$name = ( empty ( $name )) ? $email : $name ;
$team = $projectDB -> getDocument ( $teamId );
2019-09-07 05:10:41 +12:00
if ( empty ( $team -> getUid ()) || Database :: SYSTEM_COLLECTION_TEAMS != $team -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team not found' , 404 );
}
$memberships = $projectDB -> getCollection ([
'limit' => 50 ,
'offset' => 0 ,
'filters' => [
2019-09-07 05:10:41 +12:00
'$collection=' . Database :: SYSTEM_COLLECTION_MEMBERSHIPS ,
'teamId=' . $team -> getUid (),
],
2019-05-09 18:54:39 +12:00
]);
$invitee = $projectDB -> getCollection ([ // Get user by email address
'limit' => 1 ,
'first' => true ,
'filters' => [
2019-09-07 05:10:41 +12:00
'$collection=' . Database :: SYSTEM_COLLECTION_USERS ,
'email=' . $email ,
],
2019-05-09 18:54:39 +12:00
]);
2019-09-07 05:10:41 +12:00
if ( empty ( $invitee )) { // Create new user if no user with same email found
2019-05-09 18:54:39 +12:00
Authorization :: disable ();
$invitee = $projectDB -> createDocument ([
'$collection' => Database :: SYSTEM_COLLECTION_USERS ,
'$permissions' => [
'read' => [ 'user:{self}' , '*' ],
'write' => [ 'user:{self}' ],
],
'email' => $email ,
'status' => Auth :: USER_STATUS_UNACTIVATED ,
'password' => Auth :: passwordHash ( Auth :: passwordGenerator ()),
'password-update' => time (),
'registration' => time (),
'confirm' => false ,
'reset' => false ,
'name' => $name ,
2019-09-07 05:10:41 +12:00
'tokens' => [],
2019-05-09 18:54:39 +12:00
]);
Authorization :: enable ();
2019-09-07 05:10:41 +12:00
if ( false === $invitee ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed saving user to DB' , 500 );
}
}
$isOwner = false ;
foreach ( $memberships as $member ) {
2019-09-07 05:10:41 +12:00
if ( $member -> getAttribute ( 'userId' ) == $invitee -> getUid ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'User has already been invited or is already a member of this team' , 400 );
}
2019-09-07 05:10:41 +12:00
if ( $member -> getAttribute ( 'userId' ) == $user -> getUid () && in_array ( 'owner' , $member -> getAttribute ( 'roles' , []))) {
2019-05-09 18:54:39 +12:00
$isOwner = true ;
}
}
2019-09-07 05:10:41 +12:00
if ( ! $isOwner ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'User is not allowed to send invitations for this team' , 401 );
}
$secret = Auth :: tokenGenerator ();
$membership = new Document ([
'$collection' => Database :: SYSTEM_COLLECTION_MEMBERSHIPS ,
2019-09-07 05:10:41 +12:00
'$permissions' => [
'read' => [ '*' ],
'write' => [ 'user:' . $invitee -> getUid (), 'team:' . $team -> getUid () . '/owner' ],
2019-05-09 18:54:39 +12:00
],
'userId' => $invitee -> getUid (),
'teamId' => $team -> getUid (),
'roles' => $roles ,
'invited' => time (),
'joined' => 0 ,
'confirm' => false ,
'secret' => Auth :: hash ( $secret ),
]);
$membership = $projectDB -> createDocument ( $membership -> getArrayCopy ());
2019-09-07 05:10:41 +12:00
if ( false === $membership ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed saving membership to DB' , 500 );
}
$redirect = Template :: parseURL ( $redirect );
$redirect [ 'query' ] = Template :: mergeQuery ((( isset ( $redirect [ 'query' ])) ? $redirect [ 'query' ] : '' ), [ 'inviteId' => $membership -> getUid (), 'teamId' => $team -> getUid (), 'userId' => $invitee -> getUid (), 'secret' => $secret ]);
$redirect = Template :: unParseURL ( $redirect );
2019-10-25 08:20:47 +13:00
$body = new Template ( __DIR__ . '/../config/locales/templates/' . Locale :: getText ( 'auth.emails.invitation.body' ));
2019-05-09 18:54:39 +12:00
$body
-> setParam ( '{{direction}}' , Locale :: getText ( 'settings.direction' ))
-> setParam ( '{{project}}' , $project -> getAttribute ( 'name' , [ '[APP-NAME]' ]))
-> setParam ( '{{team}}' , $team -> getAttribute ( 'name' , '[TEAM-NAME]' ))
-> setParam ( '{{owner}}' , $user -> getAttribute ( 'name' , '' ))
-> setParam ( '{{redirect}}' , $redirect )
;
2019-08-31 18:02:21 +12:00
$mail = $register -> get ( 'smtp' ); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */
2019-05-09 18:54:39 +12:00
2019-08-09 09:49:46 +12:00
$mail -> addAddress ( $email , $name );
$mail -> Subject = sprintf ( Locale :: getText ( 'auth.emails.invitation.title' ), $team -> getAttribute ( 'name' , '[TEAM-NAME]' ), $project -> getAttribute ( 'name' , [ '[APP-NAME]' ]));
2019-09-07 05:10:41 +12:00
$mail -> Body = $body -> render ();
2019-08-09 09:49:46 +12:00
$mail -> AltBody = strip_tags ( $body -> render ());
2019-05-09 18:54:39 +12:00
2019-08-09 09:49:46 +12:00
try {
$mail -> send ();
2019-09-07 05:10:41 +12:00
} catch ( \Exception $error ) {
2019-08-25 17:16:17 +12:00
//throw new Exception('Problem sending mail: ' . $error->getError(), 500);
2019-05-09 18:54:39 +12:00
}
$audit
-> setParam ( 'userId' , $invitee -> getUid ())
-> setParam ( 'event' , 'auth.invite' )
;
2019-06-09 20:51:10 +12:00
$response
//->setStatusCode(Response::STATUS_CODE_CREATED) TODO change response of this endpoint
-> noContent ();
2019-05-09 18:54:39 +12:00
}
);
$utopia -> post ( '/v1/teams/:teamId/memberships/:inviteId/resend' )
2019-08-25 18:41:03 +12:00
-> desc ( 'Create Team Membership (Resend)' )
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'account' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'createTeamMembershipResend' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/create-team-membership-resend.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'teamId' , '' , function () { return new UID (); }, 'Team unique ID.' )
-> param ( 'inviteId' , '' , function () { return new UID (); }, 'Invite unique ID.' )
-> param ( 'redirect' , '' , function () use ( $clients ) { return new Host ( $clients ); }, 'Reset page to redirect user back to your app from the invitation email.' )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $teamId , $inviteId , $redirect ) use ( $response , $register , $project , $user , $audit , $projectDB ) {
2019-05-09 18:54:39 +12:00
$membership = $projectDB -> getDocument ( $inviteId );
2019-09-07 05:10:41 +12:00
if ( empty ( $membership -> getUid ()) || Database :: SYSTEM_COLLECTION_MEMBERSHIPS != $membership -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Membership not found' , 404 );
}
$team = $projectDB -> getDocument ( $membership -> getAttribute ( 'teamId' ));
2019-09-07 05:10:41 +12:00
if ( empty ( $team -> getUid ()) || Database :: SYSTEM_COLLECTION_TEAMS != $team -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team not found' , 404 );
}
2019-09-07 05:10:41 +12:00
if ( $team -> getUid () !== $teamId ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team IDs don\'t match' , 404 );
}
$invitee = $projectDB -> getDocument ( $membership -> getAttribute ( 'userId' ));
2019-09-07 05:10:41 +12:00
if ( empty ( $invitee -> getUid ()) || Database :: SYSTEM_COLLECTION_USERS != $invitee -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'User not found' , 404 );
}
$secret = Auth :: tokenGenerator ();
$membership = $projectDB -> updateDocument ( array_merge ( $membership -> getArrayCopy (), [ 'secret' => Auth :: hash ( $secret )]));
2019-09-07 05:10:41 +12:00
if ( false === $membership ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed updating membership to DB' , 500 );
}
$redirect = Template :: parseURL ( $redirect );
$redirect [ 'query' ] = Template :: mergeQuery ((( isset ( $redirect [ 'query' ])) ? $redirect [ 'query' ] : '' ), [ 'inviteId' => $membership -> getUid (), 'userId' => $membership -> getAttribute ( 'userId' ), 'secret' => $secret ]);
$redirect = Template :: unParseURL ( $redirect );
2019-10-25 08:20:47 +13:00
$body = new Template ( __DIR__ . '/../config/locales/templates/' . Locale :: getText ( 'auth.emails.invitation.body' ));
2019-05-09 18:54:39 +12:00
$body
-> setParam ( '{{direction}}' , Locale :: getText ( 'settings.direction' ))
-> setParam ( '{{project}}' , $project -> getAttribute ( 'name' , [ '[APP-NAME]' ]))
-> setParam ( '{{team}}' , $team -> getAttribute ( 'name' , '[TEAM-NAME]' ))
-> setParam ( '{{owner}}' , $user -> getAttribute ( 'name' , '' ))
-> setParam ( '{{redirect}}' , $redirect )
;
2019-08-31 18:02:21 +12:00
$mail = $register -> get ( 'smtp' ); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */
2019-05-09 18:54:39 +12:00
2019-08-09 09:49:46 +12:00
$mail -> addAddress ( $invitee -> getAttribute ( 'email' ), $invitee -> getAttribute ( 'name' ));
2019-05-09 18:54:39 +12:00
2019-08-09 09:49:46 +12:00
$mail -> Subject = sprintf ( Locale :: getText ( 'auth.emails.invitation.title' ), $team -> getAttribute ( 'name' , '[TEAM-NAME]' ), $project -> getAttribute ( 'name' , [ '[APP-NAME]' ]));
2019-09-07 05:10:41 +12:00
$mail -> Body = $body -> render ();
2019-08-09 09:49:46 +12:00
$mail -> AltBody = strip_tags ( $body -> render ());
try {
$mail -> send ();
2019-09-07 05:10:41 +12:00
} catch ( \Exception $error ) {
2019-08-25 17:16:17 +12:00
//throw new Exception('Problem sending mail: ' . $error->getError(), 500);
2019-05-09 18:54:39 +12:00
}
2019-09-07 05:10:41 +12:00
2019-05-09 18:54:39 +12:00
$audit
-> setParam ( 'userId' , $user -> getUid ())
-> setParam ( 'event' , 'auth.invite.resend' )
;
2019-06-09 20:51:10 +12:00
$response
// ->setStatusCode(Response::STATUS_CODE_CREATED) TODO change response of this endpoint
-> noContent ()
;
2019-05-09 18:54:39 +12:00
}
);
$utopia -> patch ( '/v1/teams/:teamId/memberships/:inviteId/status' )
-> desc ( 'Update Team Membership Status' )
-> label ( 'scope' , 'auth' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'updateTeamMembershipStatus' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/update-team-membership-status.md' )
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.cookies' , true )
2019-10-07 09:10:52 +13:00
-> param ( 'teamId' , '' , function () { return new UID (); }, 'Team unique ID.' )
-> param ( 'inviteId' , '' , function () { return new UID (); }, 'Invite unique ID' )
-> param ( 'userId' , '' , function () { return new UID (); }, 'User unique ID' )
-> param ( 'secret' , '' , function () { return new Text ( 256 ); }, 'Secret Key' )
-> param ( 'success' , null , function () use ( $clients ) { return new Host ( $clients ); }, 'Redirect when registration succeed' , true )
-> param ( 'failure' , null , function () use ( $clients ) { return new Host ( $clients ); }, 'Redirect when registration failed' , true )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $teamId , $inviteId , $userId , $secret , $success , $failure ) use ( $response , $request , $user , $audit , $projectDB ) {
2019-05-09 18:54:39 +12:00
$invite = $projectDB -> getDocument ( $inviteId );
2019-09-07 05:10:41 +12:00
if ( empty ( $invite -> getUid ()) || Database :: SYSTEM_COLLECTION_MEMBERSHIPS != $invite -> getCollection ()) {
if ( $failure ) {
2019-05-09 18:54:39 +12:00
$response -> redirect ( $failure );
2019-09-07 05:10:41 +12:00
2019-05-09 18:54:39 +12:00
return ;
}
throw new Exception ( 'Invite not found' , 404 );
}
2019-09-07 05:10:41 +12:00
if ( $invite -> getAttribute ( 'teamId' ) -> getUid () !== $teamId ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team IDs don\'t match' , 404 );
}
$team = $projectDB -> getDocument ( $teamId );
2019-09-07 05:10:41 +12:00
if ( empty ( $team -> getUid ()) || Database :: SYSTEM_COLLECTION_TEAMS != $team -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team not found' , 404 );
}
2019-09-07 05:10:41 +12:00
if ( Auth :: hash ( $secret ) !== $invite -> getAttribute ( 'secret' )) {
if ( $failure ) {
2019-05-09 18:54:39 +12:00
$response -> redirect ( $failure );
2019-09-07 05:10:41 +12:00
2019-05-09 18:54:39 +12:00
return ;
}
throw new Exception ( 'Secret key not valid' , 401 );
}
2019-09-07 05:10:41 +12:00
if ( $userId != $invite -> getAttribute ( 'userId' )) {
if ( $failure ) {
2019-05-09 18:54:39 +12:00
$response -> redirect ( $failure );
2019-09-07 05:10:41 +12:00
2019-05-09 18:54:39 +12:00
return ;
}
2019-09-07 05:10:41 +12:00
throw new Exception ( 'Invite not belong to current user (' . $user -> getAttribute ( 'email' ) . ')' , 401 );
2019-05-09 18:54:39 +12:00
}
2019-09-07 05:10:41 +12:00
if ( empty ( $user -> getUid ())) {
2019-05-09 18:54:39 +12:00
$user = $projectDB -> getCollection ([ // Get user
'limit' => 1 ,
'first' => true ,
'filters' => [
2019-09-07 05:10:41 +12:00
'$collection=' . Database :: SYSTEM_COLLECTION_USERS ,
'$uid=' . $userId ,
],
2019-05-09 18:54:39 +12:00
]);
}
2019-09-07 05:10:41 +12:00
if ( $invite -> getAttribute ( 'userId' ) !== $user -> getUid ()) {
if ( $failure ) {
2019-05-09 18:54:39 +12:00
$response -> redirect ( $failure );
2019-09-07 05:10:41 +12:00
2019-05-09 18:54:39 +12:00
return ;
}
2019-09-07 05:10:41 +12:00
throw new Exception ( 'Invite not belong to current user (' . $user -> getAttribute ( 'email' ) . ')' , 401 );
2019-05-09 18:54:39 +12:00
}
$invite // Attach user to team
-> setAttribute ( 'joined' , time ())
-> setAttribute ( 'confirm' , true )
;
$user
-> setAttribute ( 'confirm' , true )
-> setAttribute ( 'memberships' , $invite , Document :: SET_TYPE_APPEND );
// Log user in
$expiry = time () + Auth :: TOKEN_EXPIRATION_LOGIN_LONG ;
$secret = Auth :: tokenGenerator ();
$user -> setAttribute ( 'tokens' , new Document ([
'$collection' => Database :: SYSTEM_COLLECTION_TOKENS ,
2019-09-07 05:10:41 +12:00
'$permissions' => [ 'read' => [ 'user:' . $user -> getUid ()], 'write' => [ 'user:' . $user -> getUid ()]],
2019-05-09 18:54:39 +12:00
'type' => Auth :: TOKEN_TYPE_LOGIN ,
'secret' => Auth :: hash ( $secret ), // On way hash encryption to protect DB leak
'expire' => $expiry ,
'userAgent' => $request -> getServer ( 'HTTP_USER_AGENT' , 'UNKNOWN' ),
'ip' => $request -> getIP (),
2019-09-07 05:10:41 +12:00
]), Document :: SET_TYPE_APPEND );
2019-05-09 18:54:39 +12:00
2019-09-07 05:10:41 +12:00
Authorization :: setRole ( 'user:' . $userId );
2019-05-09 18:54:39 +12:00
$user = $projectDB -> updateDocument ( $user -> getArrayCopy ());
2019-09-07 05:10:41 +12:00
if ( false === $user ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed saving user to DB' , 500 );
}
$team = $projectDB -> updateDocument ( array_merge ( $team -> getArrayCopy (), [
'sum' => $team -> getAttribute ( 'sum' , 0 ) + 1 ,
]));
2019-09-07 05:10:41 +12:00
if ( false === $team ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed saving team to DB' , 500 );
}
$audit
-> setParam ( 'userId' , $user -> getUid ())
-> setParam ( 'event' , 'auth.join' )
;
2019-11-13 07:42:58 +13:00
$response -> addCookie ( Auth :: $cookieName , Auth :: encodeSession ( $user -> getUid (), $secret ), $expiry , '/' , COOKIE_DOMAIN , ( 'https' == $request -> getServer ( 'REQUEST_SCHEME' , 'https' )), true , COOKIE_SAMESITE );
2019-05-09 18:54:39 +12:00
2019-09-07 05:10:41 +12:00
if ( $success ) {
2019-05-09 18:54:39 +12:00
$response -> redirect ( $success );
}
$response -> json ( array ( 'result' => 'success' ));
}
);
$utopia -> delete ( '/v1/teams/:teamId/memberships/:inviteId' )
-> desc ( 'Delete Team Membership' )
-> label ( 'scope' , 'account' )
-> label ( 'sdk.namespace' , 'teams' )
-> label ( 'sdk.method' , 'deleteTeamMembership' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/teams/delete-team-membership.md' )
2019-10-07 09:10:52 +13:00
-> param ( 'teamId' , '' , function () { return new UID (); }, 'Team unique ID.' )
-> param ( 'inviteId' , '' , function () { return new UID (); }, 'Invite unique ID' )
2019-05-09 18:54:39 +12:00
-> action (
2019-09-07 05:10:41 +12:00
function ( $teamId , $inviteId ) use ( $response , $projectDB , $audit ) {
2019-05-09 18:54:39 +12:00
$invite = $projectDB -> getDocument ( $inviteId );
2019-09-07 05:10:41 +12:00
if ( empty ( $invite -> getUid ()) || Database :: SYSTEM_COLLECTION_MEMBERSHIPS != $invite -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Invite not found' , 404 );
}
2019-09-07 05:10:41 +12:00
if ( $invite -> getAttribute ( 'teamId' ) !== $teamId ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team IDs don\'t match' , 404 );
}
$team = $projectDB -> getDocument ( $teamId );
2019-09-07 05:10:41 +12:00
if ( empty ( $team -> getUid ()) || Database :: SYSTEM_COLLECTION_TEAMS != $team -> getCollection ()) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Team not found' , 404 );
}
2019-09-07 05:10:41 +12:00
if ( ! $projectDB -> deleteDocument ( $invite -> getUid ())) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed to remove membership from DB' , 500 );
}
$team = $projectDB -> updateDocument ( array_merge ( $team -> getArrayCopy (), [
'sum' => $team -> getAttribute ( 'sum' , 0 ) - 1 ,
]));
2019-09-07 05:10:41 +12:00
if ( false === $team ) {
2019-05-09 18:54:39 +12:00
throw new Exception ( 'Failed saving team to DB' , 500 );
}
$audit
-> setParam ( 'userId' , $invite -> getAttribute ( 'userId' ))
-> setParam ( 'event' , 'auth.leave' )
;
$response -> noContent ();
}
2019-09-07 05:10:41 +12:00
);