2019-05-09 18:54:39 +12:00
< ? php
2021-05-07 10:31:05 +12:00
use Appwrite\Auth\Auth ;
use Appwrite\Auth\Validator\Password ;
use Appwrite\Utopia\Response ;
2020-06-29 05:31:21 +12:00
use Utopia\App ;
2019-05-09 18:54:39 +12:00
use Utopia\Exception ;
2020-01-20 09:38:00 +13:00
use Utopia\Validator\Assoc ;
2019-05-09 18:54:39 +12:00
use Utopia\Validator\WhiteList ;
2021-03-25 06:47:43 +13:00
use Appwrite\Network\Validator\Email ;
2019-05-09 18:54:39 +12:00
use Utopia\Validator\Text ;
use Utopia\Validator\Range ;
2021-05-30 19:03:51 +12:00
use Utopia\Validator\Boolean ;
2019-12-29 22:47:55 +13:00
use Utopia\Audit\Audit ;
2021-05-07 10:31:05 +12:00
use Utopia\Database\Document ;
use Utopia\Database\Exception\Duplicate ;
use Utopia\Database\Validator\UID ;
2021-12-13 06:55:38 +13:00
use Appwrite\Detector\Detector ;
2021-07-05 23:35:15 +12:00
use Appwrite\Database\Validator\CustomId ;
2021-09-01 08:55:13 +12:00
use Utopia\Config\Config ;
2021-08-20 21:57:46 +12:00
use Utopia\Database\Database ;
use Utopia\Database\Query ;
2021-08-29 04:25:48 +12:00
use Utopia\Database\Validator\Authorization ;
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: post ( '/v1/users' )
2020-02-05 19:31:34 +13:00
-> desc ( 'Create User' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2020-10-31 08:53:27 +13:00
-> label ( 'event' , 'users.create' )
2020-02-05 19:31:34 +13:00
-> label ( 'scope' , 'users.write' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2020-02-05 19:31:34 +13:00
-> label ( 'sdk.namespace' , 'users' )
-> label ( 'sdk.method' , 'create' )
-> label ( 'sdk.description' , '/docs/references/users/create-user.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_CREATED )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_USER )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new CustomId (), 'User ID. Choose your own unique ID or pass the string `unique()` to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can\'t start with a special char. Max length is 36 chars.' )
2020-09-11 02:40:14 +12:00
-> param ( 'email' , '' , new Email (), 'User email.' )
2021-11-26 09:07:54 +13:00
-> param ( 'password' , '' , new Password (), 'User password. Must be at least 8 chars.' )
2020-09-11 02:40:14 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'User name. Max length: 128 chars.' , true )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $email , $password , $name , $response , $dbForInternal , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2020-02-05 19:31:34 +13:00
2021-06-04 01:03:51 +12:00
$email = \strtolower ( $email );
2020-02-05 19:31:34 +13:00
2020-06-30 23:09:28 +12:00
try {
2021-07-06 18:23:33 +12:00
$userId = $userId == 'unique()' ? $dbForInternal -> getId () : $userId ;
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> createDocument ( 'users' , new Document ([
'$id' => $userId ,
2021-06-12 06:23:16 +12:00
'$read' => [ 'role:all' ],
2021-05-07 10:31:05 +12:00
'$write' => [ 'user:' . $userId ],
2020-06-30 23:09:28 +12:00
'email' => $email ,
'emailVerification' => false ,
2021-07-14 23:02:12 +12:00
'status' => true ,
2020-06-30 23:09:28 +12:00
'password' => Auth :: passwordHash ( $password ),
2021-01-15 01:04:16 +13:00
'passwordUpdate' => \time (),
2020-06-30 23:09:28 +12:00
'registration' => \time (),
'reset' => false ,
'name' => $name ,
2021-05-07 10:31:05 +12:00
'prefs' => [],
'sessions' => [],
'tokens' => [],
'memberships' => [],
2021-08-15 06:56:28 +12:00
'search' => implode ( ' ' , [ $userId , $email , $name ]),
2021-09-21 23:18:54 +12:00
'deleted' => false
2021-05-07 10:31:05 +12:00
]));
2020-06-30 23:09:28 +12:00
} catch ( Duplicate $th ) {
throw new Exception ( 'Account already exists' , 409 );
}
2020-02-05 19:31:34 +13:00
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.create' , 1 )
;
2021-05-07 10:31:05 +12:00
$response -> setStatusCode ( Response :: STATUS_CODE_CREATED );
2021-07-26 02:47:18 +12:00
$response -> dynamic ( $user , Response :: MODEL_USER );
2020-12-27 05:54:42 +13:00
});
2020-02-05 19:31:34 +13:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/users' )
2019-05-09 18:54:39 +12:00
-> desc ( 'List Users' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'users.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'list' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/users/list-users.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_USER_LIST )
2020-09-11 02:40:14 +12:00
-> param ( 'search' , '' , new Text ( 256 ), 'Search term to filter your list results. Max length: 256 chars.' , true )
2021-12-15 00:21:44 +13:00
-> param ( 'limit' , 25 , new Range ( 0 , 100 ), 'Maximum number of users to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.' , true )
-> param ( 'offset' , 0 , new Range ( 0 , APP_LIMIT_COUNT ), 'Offset value. The default value is 0. Use this param to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)' , true )
-> param ( 'cursor' , '' , new UID (), 'ID of the user used as the starting point for the query, excluding the user itself. Should be used for efficient pagination when working with large sets of data. [learn more about pagination](https://appwrite.io/docs/pagination)' , true )
2021-10-05 23:30:33 +13:00
-> param ( 'cursorDirection' , Database :: CURSOR_AFTER , new WhiteList ([ Database :: CURSOR_AFTER , Database :: CURSOR_BEFORE ]), 'Direction of the cursor.' , true )
2020-09-11 02:40:14 +12:00
-> param ( 'orderType' , 'ASC' , new WhiteList ([ 'ASC' , 'DESC' ], true ), 'Order result by ASC or DESC order.' , true )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
2021-10-05 23:30:33 +13:00
-> action ( function ( $search , $limit , $offset , $cursor , $cursorDirection , $orderType , $response , $dbForInternal , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2021-05-07 10:31:05 +12:00
2021-10-05 23:30:33 +13:00
if ( ! empty ( $cursor )) {
$cursorUser = $dbForInternal -> getDocument ( 'users' , $cursor );
2021-08-07 00:36:48 +12:00
2021-10-05 23:30:33 +13:00
if ( $cursorUser -> isEmpty ()) {
2021-10-08 23:59:28 +13:00
throw new Exception ( " User ' { $cursor } ' for the 'cursor' value not found. " , 400 );
2021-08-07 00:36:48 +12:00
}
}
2021-10-07 01:56:44 +13:00
$queries = [
new Query ( 'deleted' , Query :: TYPE_EQUAL , [ false ])
];
2021-08-15 06:56:28 +12:00
if ( ! empty ( $search )) {
$queries [] = new Query ( 'search' , Query :: TYPE_SEARCH , [ $search ]);
}
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.read' , 1 )
;
2020-06-30 23:09:28 +12:00
2021-07-26 02:47:18 +12:00
$response -> dynamic ( new Document ([
2021-10-07 03:11:04 +13:00
'users' => $dbForInternal -> find ( 'users' , $queries , $limit , $offset , [], [ $orderType ], $cursorUser ? ? null , $cursorDirection ),
2021-10-06 05:10:02 +13:00
'sum' => $dbForInternal -> count ( 'users' , $queries , APP_LIMIT_COUNT ),
2020-10-31 08:53:27 +13:00
]), Response :: MODEL_USER_LIST );
2020-12-27 05:54:42 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/users/:userId' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Get User' )
2020-06-29 00:18:16 +12:00
-> groups ([ 'api' , 'users' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'users.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2020-06-29 00:18:16 +12:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'get' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/users/get-user.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_USER )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $response , $dbForInternal , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2020-06-29 00:18:16 +12:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2020-07-03 09:48:37 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-06-30 23:09:28 +12:00
throw new Exception ( 'User not found' , 404 );
}
2020-07-03 09:48:37 +12:00
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.read' , 1 )
;
2021-07-26 02:47:18 +12:00
$response -> dynamic ( $user , Response :: MODEL_USER );
2020-12-27 05:54:42 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/users/:userId/prefs' )
2020-01-23 19:27:19 +13:00
-> desc ( 'Get User Preferences' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'users.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'getPrefs' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/users/get-user-prefs.md' )
2020-11-13 00:54:16 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
2021-04-22 01:37:51 +12:00
-> label ( 'sdk.response.model' , Response :: MODEL_PREFERENCES )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $response , $dbForInternal , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2019-05-09 18:54:39 +12:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2019-05-09 18:54:39 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-06-30 23:09:28 +12:00
throw new Exception ( 'User not found' , 404 );
}
2019-05-09 18:54:39 +12:00
2021-01-11 00:55:59 +13:00
$prefs = $user -> getAttribute ( 'prefs' , new \stdClass ());
2019-05-09 18:54:39 +12:00
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.read' , 1 )
;
2021-07-26 02:47:18 +12:00
$response -> dynamic ( new Document ( $prefs ), Response :: MODEL_PREFERENCES );
2020-12-27 05:54:42 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/users/:userId/sessions' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Get User Sessions' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'users.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'getSessions' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/users/get-user-sessions.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_SESSION_LIST )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2020-12-27 05:54:42 +13:00
-> inject ( 'locale' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $response , $dbForInternal , $locale , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2020-06-30 23:09:28 +12:00
/** @var Utopia\Locale\Locale $locale */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2019-05-09 18:54:39 +12:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2020-06-30 23:09:28 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-06-30 23:09:28 +12:00
throw new Exception ( 'User not found' , 404 );
}
2019-05-09 18:54:39 +12:00
2021-02-20 01:12:47 +13:00
$sessions = $user -> getAttribute ( 'sessions' , []);
2020-06-30 23:09:28 +12:00
2021-02-20 01:12:47 +13:00
foreach ( $sessions as $key => $session ) {
/** @var Document $session */
2019-05-09 18:54:39 +12:00
2021-07-23 08:15:01 +12:00
$countryName = $locale -> getText ( 'countries.' . strtolower ( $session -> getAttribute ( 'countryCode' )), $locale -> getText ( 'locale.country.unknown' ));
$session -> setAttribute ( 'countryName' , $countryName );
2021-02-20 01:12:47 +13:00
$session -> setAttribute ( 'current' , false );
2019-05-09 18:54:39 +12:00
2021-02-20 01:12:47 +13:00
$sessions [ $key ] = $session ;
2019-05-09 18:54:39 +12:00
}
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.read' , 1 )
;
2021-07-26 02:47:18 +12:00
$response -> dynamic ( new Document ([
2021-05-27 22:09:14 +12:00
'sessions' => $sessions ,
2020-10-31 08:53:27 +13:00
'sum' => count ( $sessions ),
]), Response :: MODEL_SESSION_LIST );
2021-05-07 10:31:05 +12:00
}, [ 'response' , 'dbForInternal' , 'locale' ]);
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: get ( '/v1/users/:userId/logs' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Get User Logs' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'users.read' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'getLogs' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/users/get-user-logs.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_LOG_LIST )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
2021-12-15 00:21:44 +13:00
-> param ( 'limit' , 25 , new Range ( 0 , 100 ), 'Maximum number of logs to return in response. By default will return maximum 25 results. Maximum of 100 results allowed per request.' , true )
-> param ( 'offset' , 0 , new Range ( 0 , APP_LIMIT_COUNT ), 'Offset value. The default value is 0. Use this value to manage pagination. [learn more about pagination](https://appwrite.io/docs/pagination)' , true )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2020-12-27 05:54:42 +13:00
-> inject ( 'locale' )
-> inject ( 'geodb' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
2021-11-17 02:37:33 +13:00
-> action ( function ( $userId , $limit , $offset , $response , $dbForInternal , $locale , $geodb , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-07-26 02:47:18 +12:00
/** @var Utopia\Database\Document $project */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2020-06-30 23:09:28 +12:00
/** @var Utopia\Locale\Locale $locale */
2020-10-25 19:15:36 +13:00
/** @var MaxMind\Db\Reader $geodb */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2020-06-30 23:09:28 +12:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2020-06-30 23:09:28 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-06-30 23:09:28 +12:00
throw new Exception ( 'User not found' , 404 );
}
2019-05-09 18:54:39 +12:00
2021-06-07 17:17:29 +12:00
$audit = new Audit ( $dbForInternal );
2021-11-17 03:54:29 +13:00
$auditEvents = [
2020-06-30 23:09:28 +12:00
'account.create' ,
'account.delete' ,
'account.update.name' ,
'account.update.email' ,
'account.update.password' ,
'account.update.prefs' ,
'account.sessions.create' ,
'account.sessions.delete' ,
'account.recovery.create' ,
'account.recovery.update' ,
'account.verification.create' ,
'account.verification.update' ,
'teams.membership.create' ,
'teams.membership.update' ,
'teams.membership.delete' ,
2021-11-17 03:54:29 +13:00
];
$logs = $audit -> getLogsByUserAndEvents ( $user -> getId (), $auditEvents , $limit , $offset );
2020-06-30 23:09:28 +12:00
$output = [];
foreach ( $logs as $i => & $log ) {
$log [ 'userAgent' ] = ( ! empty ( $log [ 'userAgent' ])) ? $log [ 'userAgent' ] : 'UNKNOWN' ;
2021-12-13 06:55:38 +13:00
$detector = new Detector ( $log [ 'userAgent' ]);
$detector -> skipBotDetection (); // OPTIONAL: If called, bot detection will completely be skipped (bots will be detected as regular devices then)
2020-06-30 23:09:28 +12:00
2021-12-13 06:55:38 +13:00
$os = $detector -> getOS ();
$client = $detector -> getClient ();
$device = $detector -> getDevice ();
2020-10-31 08:53:27 +13:00
$output [ $i ] = new Document ([
2020-06-30 23:09:28 +12:00
'event' => $log [ 'event' ],
'ip' => $log [ 'ip' ],
2021-06-13 06:39:59 +12:00
'time' => $log [ 'time' ],
2021-12-13 06:55:38 +13:00
'osCode' => $os [ 'osCode' ],
'osName' => $os [ 'osName' ],
'osVersion' => $os [ 'osVersion' ],
'clientType' => $client [ 'clientType' ],
'clientCode' => $client [ 'clientCode' ],
'clientName' => $client [ 'clientName' ],
'clientVersion' => $client [ 'clientVersion' ],
'clientEngine' => $client [ 'clientEngine' ],
'clientEngineVersion' => $client [ 'clientEngineVersion' ],
'deviceName' => $device [ 'deviceName' ],
'deviceBrand' => $device [ 'deviceBrand' ],
2021-12-13 06:59:12 +13:00
'deviceModel' => $device [ 'deviceModel' ]
2020-10-31 08:53:27 +13:00
]);
$record = $geodb -> get ( $log [ 'ip' ]);
if ( $record ) {
2021-07-26 19:05:08 +12:00
$output [ $i ][ 'countryCode' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), false ) ? \strtolower ( $record [ 'country' ][ 'iso_code' ]) : '--' ;
2021-07-23 08:15:01 +12:00
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'countries.' . strtolower ( $record [ 'country' ][ 'iso_code' ]), $locale -> getText ( 'locale.country.unknown' ));
2020-10-31 08:53:27 +13:00
} else {
$output [ $i ][ 'countryCode' ] = '--' ;
$output [ $i ][ 'countryName' ] = $locale -> getText ( 'locale.country.unknown' );
2019-05-09 18:54:39 +12:00
}
}
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.read' , 1 )
;
2021-11-17 03:54:29 +13:00
$response -> dynamic ( new Document ([
2021-11-18 23:33:42 +13:00
'sum' => $audit -> countLogsByUserAndEvents ( $user -> getId (), $auditEvents ),
2021-11-17 03:54:29 +13:00
'logs' => $output ,
]), Response :: MODEL_LOG_LIST );
2020-12-27 05:54:42 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: patch ( '/v1/users/:userId/status' )
2019-10-10 16:52:59 +13:00
-> desc ( 'Update User Status' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2020-10-31 08:53:27 +13:00
-> label ( 'event' , 'users.update.status' )
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'users.write' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'updateStatus' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/users/update-user-status.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_USER )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
-> param ( 'status' , null , new Boolean ( true ), 'User Status. To activate the user pass `true` and to block the user pass `false`.' )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $status , $response , $dbForInternal , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2019-05-09 18:54:39 +12:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2019-05-09 18:54:39 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-06-30 23:09:28 +12:00
throw new Exception ( 'User not found' , 404 );
}
2019-05-09 18:54:39 +12:00
2021-07-14 23:02:12 +12:00
$user = $dbForInternal -> updateDocument ( 'users' , $user -> getId (), $user -> setAttribute ( 'status' , ( bool ) $status ));
2019-10-21 19:01:07 +13:00
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.update' , 1 )
;
2021-07-26 02:47:18 +12:00
$response -> dynamic ( $user , Response :: MODEL_USER );
2020-12-27 05:54:42 +13:00
});
2019-05-09 18:54:39 +12:00
2021-05-30 19:03:51 +12:00
App :: patch ( '/v1/users/:userId/verification' )
-> desc ( 'Update Email Verification' )
-> groups ([ 'api' , 'users' ])
-> label ( 'event' , 'users.update.verification' )
-> label ( 'scope' , 'users.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'users' )
-> label ( 'sdk.method' , 'updateVerification' )
-> label ( 'sdk.description' , '/docs/references/users/update-user-verification.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_USER )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
-> param ( 'emailVerification' , false , new Boolean (), 'User email verification status.' )
2021-05-30 19:03:51 +12:00
-> inject ( 'response' )
2021-06-12 06:23:16 +12:00
-> inject ( 'dbForInternal' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $emailVerification , $response , $dbForInternal , $usage ) {
2021-05-30 19:03:51 +12:00
/** @var Appwrite\Utopia\Response $response */
2021-06-12 00:04:15 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2021-05-30 19:03:51 +12:00
2021-06-12 00:04:15 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2021-05-30 19:03:51 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2021-05-30 19:03:51 +12:00
throw new Exception ( 'User not found' , 404 );
}
2021-06-12 00:04:15 +12:00
$user = $dbForInternal -> updateDocument ( 'users' , $user -> getId (), $user -> setAttribute ( 'emailVerification' , $emailVerification ));
2019-05-09 18:54:39 +12:00
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.update' , 1 )
;
2021-07-26 02:47:18 +12:00
$response -> dynamic ( $user , Response :: MODEL_USER );
2020-12-27 05:54:42 +13:00
});
2019-05-09 18:54:39 +12:00
2021-08-29 23:13:58 +12:00
App :: patch ( '/v1/users/:userId/name' )
-> desc ( 'Update Name' )
-> groups ([ 'api' , 'users' ])
-> label ( 'event' , 'users.update.name' )
-> label ( 'scope' , 'users.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'users' )
-> label ( 'sdk.method' , 'updateName' )
-> label ( 'sdk.description' , '/docs/references/users/update-user-name.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_USER )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
2021-08-29 23:13:58 +12:00
-> param ( 'name' , '' , new Text ( 128 ), 'User name. Max length: 128 chars.' )
-> inject ( 'response' )
-> inject ( 'dbForInternal' )
-> inject ( 'audits' )
-> action ( function ( $userId , $name , $response , $dbForInternal , $audits ) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Appwrite\Event\Event $audits */
2021-10-08 21:39:37 +13:00
2021-08-29 23:13:58 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2021-08-29 23:13:58 +12:00
throw new Exception ( 'User not found' , 404 );
}
$user = $dbForInternal -> updateDocument ( 'users' , $user -> getId (), $user -> setAttribute ( 'name' , $name ));
$audits
-> setParam ( 'userId' , $user -> getId ())
-> setParam ( 'event' , 'users.update.name' )
2021-08-30 00:06:33 +12:00
-> setParam ( 'resource' , 'user/' . $user -> getId ())
2021-08-29 23:13:58 +12:00
;
$response -> dynamic ( $user , Response :: MODEL_USER );
});
App :: patch ( '/v1/users/:userId/password' )
-> desc ( 'Update Password' )
-> groups ([ 'api' , 'users' ])
-> label ( 'event' , 'users.update.password' )
-> label ( 'scope' , 'users.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'users' )
-> label ( 'sdk.method' , 'updatePassword' )
-> label ( 'sdk.description' , '/docs/references/users/update-user-password.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_USER )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
-> param ( 'password' , '' , new Password (), 'New user password. Must be at least 8 chars.' )
2021-08-29 23:13:58 +12:00
-> inject ( 'response' )
-> inject ( 'dbForInternal' )
-> inject ( 'audits' )
-> action ( function ( $userId , $password , $response , $dbForInternal , $audits ) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Appwrite\Event\Event $audits */
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2021-08-29 23:13:58 +12:00
throw new Exception ( 'User not found' , 404 );
}
2021-10-08 21:39:37 +13:00
$user
-> setAttribute ( 'password' , Auth :: passwordHash ( $password ))
-> setAttribute ( 'passwordUpdate' , \time ());
$user = $dbForInternal -> updateDocument ( 'users' , $user -> getId (), $user );
2021-08-29 23:13:58 +12:00
$audits
-> setParam ( 'userId' , $user -> getId ())
-> setParam ( 'event' , 'users.update.password' )
2021-08-30 00:06:33 +12:00
-> setParam ( 'resource' , 'user/' . $user -> getId ())
2021-08-29 23:13:58 +12:00
;
$response -> dynamic ( $user , Response :: MODEL_USER );
});
App :: patch ( '/v1/users/:userId/email' )
-> desc ( 'Update Email' )
-> groups ([ 'api' , 'users' ])
-> label ( 'event' , 'users.update.email' )
-> label ( 'scope' , 'users.write' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
-> label ( 'sdk.namespace' , 'users' )
-> label ( 'sdk.method' , 'updateEmail' )
-> label ( 'sdk.description' , '/docs/references/users/update-user-email.md' )
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
-> label ( 'sdk.response.model' , Response :: MODEL_USER )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
2021-08-29 23:13:58 +12:00
-> param ( 'email' , '' , new Email (), 'User email.' )
-> inject ( 'response' )
-> inject ( 'dbForInternal' )
-> inject ( 'audits' )
-> action ( function ( $userId , $email , $response , $dbForInternal , $audits ) {
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
/** @var Appwrite\Event\Event $audits */
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2021-08-29 23:13:58 +12:00
throw new Exception ( 'User not found' , 404 );
}
2021-10-08 06:57:23 +13:00
$isAnonymousUser = is_null ( $user -> getAttribute ( 'email' )) && is_null ( $user -> getAttribute ( 'password' )); // Check if request is from an anonymous account for converting
if ( ! $isAnonymousUser ) {
2021-10-08 21:39:37 +13:00
//TODO: Remove previous unique ID.
2021-10-08 06:57:23 +13:00
}
$email = \strtolower ( $email );
2021-08-30 00:00:25 +12:00
try {
$user = $dbForInternal -> updateDocument ( 'users' , $user -> getId (), $user -> setAttribute ( 'email' , $email ));
} catch ( Duplicate $th ) {
2021-08-29 23:13:58 +12:00
throw new Exception ( 'Email already exists' , 409 );
}
$audits
-> setParam ( 'userId' , $user -> getId ())
2021-10-08 06:57:23 +13:00
-> setParam ( 'event' , 'users.update.email' )
2021-08-30 00:06:33 +12:00
-> setParam ( 'resource' , 'user/' . $user -> getId ())
2021-08-29 23:13:58 +12:00
;
$response -> dynamic ( $user , Response :: MODEL_USER );
});
2020-06-29 05:31:21 +12:00
App :: patch ( '/v1/users/:userId/prefs' )
2020-01-23 19:27:19 +13:00
-> desc ( 'Update User Preferences' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2021-03-05 06:18:50 +13:00
-> label ( 'event' , 'users.update.prefs' )
2019-10-05 10:04:49 +13:00
-> label ( 'scope' , 'users.write' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2019-10-05 10:04:49 +13:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'updatePrefs' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/users/update-user-prefs.md' )
2020-11-13 00:54:16 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
2021-04-22 01:37:51 +12:00
-> label ( 'sdk.response.model' , Response :: MODEL_PREFERENCES )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
2020-09-11 02:40:14 +12:00
-> param ( 'prefs' , '' , new Assoc (), 'Prefs key-value JSON object.' )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $prefs , $response , $dbForInternal , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2019-10-05 10:04:49 +13:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2019-10-05 10:04:49 +13:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-06-30 23:09:28 +12:00
throw new Exception ( 'User not found' , 404 );
}
2020-01-20 09:38:00 +13:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> updateDocument ( 'users' , $user -> getId (), $user -> setAttribute ( 'prefs' , $prefs ));
2019-10-21 19:01:07 +13:00
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.update' , 1 )
;
2021-07-26 02:47:18 +12:00
$response -> dynamic ( new Document ( $prefs ), Response :: MODEL_PREFERENCES );
2020-12-27 05:54:42 +13:00
});
2019-10-05 10:04:49 +13:00
2020-06-29 05:31:21 +12:00
App :: delete ( '/v1/users/:userId/sessions/:sessionId' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Delete User Session' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2020-10-31 08:53:27 +13:00
-> label ( 'event' , 'users.sessions.delete' )
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'users.write' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'deleteSession' )
2019-10-08 20:09:35 +13:00
-> label ( 'sdk.description' , '/docs/references/users/delete-user-session.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_NOCONTENT )
-> label ( 'sdk.response.model' , Response :: MODEL_NONE )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
-> param ( 'sessionId' , null , new UID (), 'Session ID.' )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2020-12-27 05:54:42 +13:00
-> inject ( 'events' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $sessionId , $response , $dbForInternal , $events , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2020-12-07 11:14:57 +13:00
/** @var Appwrite\Event\Event $events */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2019-05-09 18:54:39 +12:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2019-05-09 18:54:39 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-06-30 23:09:28 +12:00
throw new Exception ( 'User not found' , 404 );
}
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:36 +13:00
$sessions = $user -> getAttribute ( 'sessions' , []);
2021-07-17 22:04:43 +12:00
foreach ( $sessions as $key => $session ) { /** @var Document $session */
2019-05-09 18:54:39 +12:00
2021-02-20 02:59:36 +13:00
if ( $sessionId == $session -> getId ()) {
2021-05-07 10:31:05 +12:00
unset ( $sessions [ $key ]);
2020-10-31 08:53:27 +13:00
2021-07-17 22:04:43 +12:00
$dbForInternal -> deleteDocument ( 'sessions' , $session -> getId ());
2021-05-07 10:31:05 +12:00
$user -> setAttribute ( 'sessions' , $sessions );
2021-10-08 06:57:23 +13:00
2020-12-07 11:14:57 +13:00
$events
2021-07-26 02:47:18 +12:00
-> setParam ( 'eventData' , $response -> output ( $user , Response :: MODEL_USER ))
2020-10-31 08:53:27 +13:00
;
2021-05-07 10:31:05 +12:00
$dbForInternal -> updateDocument ( 'users' , $user -> getId (), $user );
2019-05-09 18:54:39 +12:00
}
}
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.update' , 1 )
-> setParam ( 'users.sessions.delete' , 1 )
;
2020-10-31 08:53:27 +13:00
$response -> noContent ();
2020-12-27 05:54:42 +13:00
});
2019-05-09 18:54:39 +12:00
2020-06-29 05:31:21 +12:00
App :: delete ( '/v1/users/:userId/sessions' )
2019-05-09 18:54:39 +12:00
-> desc ( 'Delete User Sessions' )
2020-06-26 06:32:12 +12:00
-> groups ([ 'api' , 'users' ])
2020-10-31 08:53:27 +13:00
-> label ( 'event' , 'users.sessions.delete' )
2019-05-09 18:54:39 +12:00
-> label ( 'scope' , 'users.write' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2019-05-09 18:54:39 +12:00
-> label ( 'sdk.namespace' , 'users' )
2020-01-31 05:18:46 +13:00
-> label ( 'sdk.method' , 'deleteSessions' )
2019-10-09 21:31:51 +13:00
-> label ( 'sdk.description' , '/docs/references/users/delete-user-sessions.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_NOCONTENT )
-> label ( 'sdk.response.model' , Response :: MODEL_NONE )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , new UID (), 'User ID.' )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2020-12-27 05:54:42 +13:00
-> inject ( 'events' )
2021-08-16 19:56:18 +12:00
-> inject ( 'usage' )
-> action ( function ( $userId , $response , $dbForInternal , $events , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2020-12-07 11:14:57 +13:00
/** @var Appwrite\Event\Event $events */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2019-05-09 18:54:39 +12:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2019-05-09 18:54:39 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-06-30 23:09:28 +12:00
throw new Exception ( 'User not found' , 404 );
}
2019-05-09 18:54:39 +12:00
2021-07-17 22:04:43 +12:00
$sessions = $user -> getAttribute ( 'sessions' , []);
foreach ( $sessions as $key => $session ) { /** @var Document $session */
$dbForInternal -> deleteDocument ( 'sessions' , $session -> getId ());
}
2021-12-14 22:32:45 +13:00
$dbForInternal -> updateDocument ( 'users' , $user -> getId (), $user -> setAttribute ( 'sessions' , []));
2019-05-09 18:54:39 +12:00
2020-12-07 11:14:57 +13:00
$events
2021-07-26 02:47:18 +12:00
-> setParam ( 'eventData' , $response -> output ( $user , Response :: MODEL_USER ))
2020-10-31 08:53:27 +13:00
;
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.update' , 1 )
-> setParam ( 'users.sessions.delete' , 1 )
;
2020-10-31 08:53:27 +13:00
$response -> noContent ();
2020-12-27 05:54:42 +13:00
});
2020-08-30 08:40:40 +12:00
App :: delete ( '/v1/users/:userId' )
-> desc ( 'Delete User' )
-> groups ([ 'api' , 'users' ])
2020-10-31 08:53:27 +13:00
-> label ( 'event' , 'users.delete' )
2020-08-30 08:40:40 +12:00
-> label ( 'scope' , 'users.write' )
2021-04-16 19:22:17 +12:00
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_KEY ])
2020-08-30 08:40:40 +12:00
-> label ( 'sdk.namespace' , 'users' )
2021-04-13 23:01:33 +12:00
-> label ( 'sdk.method' , 'delete' )
-> label ( 'sdk.description' , '/docs/references/users/delete.md' )
2020-11-12 10:02:24 +13:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_NOCONTENT )
-> label ( 'sdk.response.model' , Response :: MODEL_NONE )
2021-12-11 01:27:11 +13:00
-> param ( 'userId' , '' , function () { return new UID ();}, 'User ID.' )
2020-12-27 05:54:42 +13:00
-> inject ( 'response' )
2021-05-07 10:31:05 +12:00
-> inject ( 'dbForInternal' )
2020-12-27 05:54:42 +13:00
-> inject ( 'events' )
-> inject ( 'deletes' )
2021-08-16 20:53:34 +12:00
-> inject ( 'usage' )
2021-08-16 19:56:18 +12:00
-> action ( function ( $userId , $response , $dbForInternal , $events , $deletes , $usage ) {
2020-10-30 02:50:49 +13:00
/** @var Appwrite\Utopia\Response $response */
2021-05-07 10:31:05 +12:00
/** @var Utopia\Database\Database $dbForInternal */
2020-12-07 11:14:57 +13:00
/** @var Appwrite\Event\Event $events */
2020-08-30 08:40:40 +12:00
/** @var Appwrite\Event\Event $deletes */
2021-08-16 19:56:18 +12:00
/** @var Appwrite\Stats\Stats $usage */
2020-08-30 08:40:40 +12:00
2021-05-07 10:31:05 +12:00
$user = $dbForInternal -> getDocument ( 'users' , $userId );
2020-08-30 08:40:40 +12:00
2021-09-21 23:18:54 +12:00
if ( $user -> isEmpty () || $user -> getAttribute ( 'deleted' )) {
2020-08-30 08:40:40 +12:00
throw new Exception ( 'User not found' , 404 );
}
2021-10-06 03:29:43 +13:00
// clone user object to send to workers
$clone = clone $user ;
$user
-> setAttribute ( " name " , null )
2021-10-06 09:37:17 +13:00
-> setAttribute ( " email " , null )
-> setAttribute ( " password " , null )
2021-10-06 03:29:43 +13:00
-> setAttribute ( " deleted " , true )
;
2021-09-21 23:18:54 +12:00
2021-10-06 03:29:43 +13:00
$dbForInternal -> updateDocument ( 'users' , $userId , $user );
2020-08-30 08:40:40 +12:00
2020-10-31 08:53:27 +13:00
$deletes
2020-12-19 03:05:15 +13:00
-> setParam ( 'type' , DELETE_TYPE_DOCUMENT )
2021-10-06 03:29:43 +13:00
-> setParam ( 'document' , $clone )
2020-10-31 08:53:27 +13:00
;
2020-12-07 11:14:57 +13:00
$events
2021-10-06 03:29:43 +13:00
-> setParam ( 'eventData' , $response -> output ( $clone , Response :: MODEL_USER ))
2020-10-31 08:53:27 +13:00
;
2020-08-30 08:40:40 +12:00
2021-08-16 19:56:18 +12:00
$usage
-> setParam ( 'users.delete' , 1 )
;
2021-10-06 03:29:43 +13:00
2020-08-30 08:40:40 +12:00
$response -> noContent ();
2020-12-27 05:54:42 +13:00
});
2021-08-20 21:57:46 +12:00
App :: get ( '/v1/users/usage' )
2021-08-21 00:10:52 +12:00
-> desc ( 'Get usage stats for the users API' )
2021-08-20 21:57:46 +12:00
-> groups ([ 'api' , 'users' ])
-> label ( 'scope' , 'users.read' )
-> label ( 'sdk.auth' , [ APP_AUTH_TYPE_ADMIN ])
-> label ( 'sdk.namespace' , 'users' )
-> label ( 'sdk.method' , 'getUsage' )
2021-08-27 06:53:55 +12:00
-> label ( 'sdk.response.code' , Response :: STATUS_CODE_OK )
-> label ( 'sdk.response.type' , Response :: CONTENT_TYPE_JSON )
2021-08-28 05:34:43 +12:00
-> label ( 'sdk.response.model' , Response :: MODEL_USAGE_USERS )
2021-08-20 21:57:46 +12:00
-> param ( 'range' , '30d' , new WhiteList ([ '24h' , '7d' , '30d' , '90d' ], true ), 'Date range.' , true )
2021-09-01 08:55:13 +12:00
-> param ( 'provider' , '' , new WhiteList ( \array_merge ([ 'email' , 'anonymous' ], \array_map ( function ( $value ) { return " oauth- " . $value ; }, \array_keys ( Config :: getParam ( 'providers' , [])))), true ), 'Provider Name.' , true )
2021-08-20 21:57:46 +12:00
-> inject ( 'response' )
-> inject ( 'dbForInternal' )
-> inject ( 'register' )
2021-08-29 17:30:37 +12:00
-> action ( function ( $range , $provider , $response , $dbForInternal ) {
2021-08-20 21:57:46 +12:00
/** @var Appwrite\Utopia\Response $response */
/** @var Utopia\Database\Database $dbForInternal */
2021-08-27 06:53:55 +12:00
$usage = [];
2021-08-20 21:57:46 +12:00
if ( App :: getEnv ( '_APP_USAGE_STATS' , 'enabled' ) == 'enabled' ) {
2021-10-28 11:17:15 +13:00
$periods = [
2021-08-20 21:57:46 +12:00
'24h' => [
2021-09-06 18:43:20 +12:00
'period' => '30m' ,
2021-08-20 21:57:46 +12:00
'limit' => 48 ,
],
'7d' => [
'period' => '1d' ,
'limit' => 7 ,
],
'30d' => [
'period' => '1d' ,
'limit' => 30 ,
],
'90d' => [
'period' => '1d' ,
'limit' => 90 ,
],
];
$metrics = [
2021-08-27 06:53:55 +12:00
" users.count " ,
2021-08-20 21:57:46 +12:00
" users.create " ,
" users.read " ,
" users.update " ,
" users.delete " ,
" users.sessions.create " ,
2021-08-29 17:30:37 +12:00
" users.sessions. $provider .create " ,
2021-08-20 21:57:46 +12:00
" users.sessions.delete "
];
2021-08-27 06:53:55 +12:00
$stats = [];
2021-08-29 04:25:48 +12:00
2021-10-28 11:17:15 +13:00
Authorization :: skip ( function () use ( $dbForInternal , $periods , $range , $metrics , & $stats ) {
2021-08-29 04:25:48 +12:00
foreach ( $metrics as $metric ) {
2021-10-28 11:17:15 +13:00
$limit = $periods [ $range ][ 'limit' ];
$period = $periods [ $range ][ 'period' ];
2021-10-28 08:57:20 +13:00
2021-08-29 04:25:48 +12:00
$requestDocs = $dbForInternal -> find ( 'stats' , [
2021-10-28 08:57:20 +13:00
new Query ( 'period' , Query :: TYPE_EQUAL , [ $period ]),
2021-08-29 04:25:48 +12:00
new Query ( 'metric' , Query :: TYPE_EQUAL , [ $metric ]),
2021-10-28 08:57:20 +13:00
], $limit , 0 , [ 'time' ], [ Database :: ORDER_DESC ]);
2021-08-29 04:25:48 +12:00
$stats [ $metric ] = [];
foreach ( $requestDocs as $requestDoc ) {
$stats [ $metric ][] = [
'value' => $requestDoc -> getAttribute ( 'value' ),
'date' => $requestDoc -> getAttribute ( 'time' ),
];
}
2021-10-28 08:57:20 +13:00
// backfill metrics with empty values for graphs
$backfill = $limit - \count ( $requestDocs );
while ( $backfill > 0 ) {
2021-10-28 11:17:51 +13:00
2021-10-28 08:57:20 +13:00
$last = $limit - $backfill - 1 ; // array index of last added metric
$diff = match ( $period ) { // convert period to seconds for unix timestamp math
'30m' => 1800 ,
'1d' => 86400 ,
};
$stats [ $metric ][] = [
'value' => 0 ,
2021-10-28 11:17:51 +13:00
'date' => ( $stats [ $metric ][ $last ][ 'date' ] ? ? \time ()) - $diff , // time of last metric minus period
2021-10-28 08:57:20 +13:00
];
$backfill -- ;
}
2021-08-29 04:25:48 +12:00
$stats [ $metric ] = array_reverse ( $stats [ $metric ]);
}
});
2021-08-20 21:57:46 +12:00
2021-08-27 06:53:55 +12:00
$usage = new Document ([
2021-08-20 21:57:46 +12:00
'range' => $range ,
2021-10-27 02:19:28 +13:00
'usersCount' => $stats [ " users.count " ],
'usersCreate' => $stats [ " users.create " ],
'usersRead' => $stats [ " users.read " ],
'usersUpdate' => $stats [ " users.update " ],
'usersDelete' => $stats [ " users.delete " ],
'sessionsCreate' => $stats [ " users.sessions.create " ],
'sessionsProviderCreate' => $stats [ " users.sessions. $provider .create " ],
'sessionsDelete' => $stats [ " users.sessions.delete " ]
2021-08-20 21:57:46 +12:00
]);
2021-08-27 06:53:55 +12:00
2021-08-20 21:57:46 +12:00
}
2021-08-27 06:53:55 +12:00
2021-08-28 05:34:43 +12:00
$response -> dynamic ( $usage , Response :: MODEL_USAGE_USERS );
2021-08-20 21:57:46 +12:00
});