1
0
Fork 0
mirror of synced 2024-05-20 20:52:36 +12:00

Fixed document not being unique

This commit is contained in:
Eldad Fux 2020-03-21 23:10:06 +02:00
parent 97ee872c05
commit 4f11e171db
13 changed files with 136 additions and 69 deletions

View file

@ -1,3 +1,10 @@
# Version 0.5.3 (PRE-RELEASE)
## Bug Fixes
* Fixed bug where multiple unique attribute were allowed
* Blocked forms from being submitted unlimited times
# Version 0.5.2 (PRE-RELEASE)
## Bug Fixes

View file

@ -18,6 +18,7 @@ use Auth\Auth;
use Auth\Validator\Password;
use Database\Database;
use Database\Document;
use Database\Exception\Duplicate;
use Database\Validator\UID;
use Database\Validator\Authorization;
use DeviceDetector\DeviceDetector;
@ -88,21 +89,25 @@ $utopia->post('/v1/account')
Authorization::disable();
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash($password),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
]);
try {
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash($password),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
], ['email' => $email]);
} catch (Duplicate $th) {
throw new Exception('Account already exists', 409);
}
Authorization::enable();
@ -391,18 +396,22 @@ $utopia->get('/v1/account/sessions/oauth2/:provider/redirect')
if (!$user || empty($user->getId())) { // Last option -> create user alone, generate random password
Authorization::disable();
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => ['read' => ['*'], 'write' => ['user:{self}']],
'email' => $email,
'emailVerification' => true,
'status' => Auth::USER_STATUS_ACTIVATED, // Email should already be authenticated by OAuth2 provider
'password' => Auth::passwordHash(Auth::passwordGenerator()),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
]);
try {
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => ['read' => ['*'], 'write' => ['user:{self}']],
'email' => $email,
'emailVerification' => true,
'status' => Auth::USER_STATUS_ACTIVATED, // Email should already be authenticated by OAuth2 provider
'password' => Auth::passwordHash(Auth::passwordGenerator()),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
], ['email' => $email]);
} catch (Duplicate $th) {
throw new Exception('Account already exists', 409);
}
Authorization::enable();

View file

@ -15,6 +15,7 @@ use Database\Database;
use Database\Document;
use Database\Validator\UID;
use Database\Validator\Authorization;
use Database\Exception\Duplicate;
use Template\Template;
use Auth\Auth;
@ -243,22 +244,26 @@ $utopia->post('/v1/teams/:teamId/memberships')
Authorization::disable();
$invitee = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['user:{self}', '*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash(Auth::passwordGenerator()),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
'tokens' => [],
]);
try {
$invitee = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['user:{self}', '*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash(Auth::passwordGenerator()),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
'tokens' => [],
], ['email' => $email]);
} catch (Duplicate $th) {
throw new Exception('Account already exists', 409);
}
Authorization::reset();

View file

@ -15,6 +15,7 @@ use Utopia\Audit\Audit;
use Utopia\Audit\Adapters\MySQL as AuditAdapter;
use Utopia\Locale\Locale;
use Database\Database;
use Database\Exception\Duplicate;
use Database\Validator\UID;
use DeviceDetector\DeviceDetector;
use GeoIp2\Database\Reader;
@ -46,21 +47,25 @@ $utopia->post('/v1/users')
throw new Exception('User already registered', 409);
}
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash($password),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
]);
try {
$user = $projectDB->createDocument([
'$collection' => Database::SYSTEM_COLLECTION_USERS,
'$permissions' => [
'read' => ['*'],
'write' => ['user:{self}'],
],
'email' => $email,
'emailVerification' => false,
'status' => Auth::USER_STATUS_UNACTIVATED,
'password' => Auth::passwordHash($password),
'password-update' => time(),
'registration' => time(),
'reset' => false,
'name' => $name,
], ['email' => $email]);
} catch (Duplicate $th) {
throw new Exception('Account already exists', 409);
}
$oauth2Keys = [];

View file

@ -5,7 +5,7 @@ USE `appwrite`;
CREATE TABLE IF NOT EXISTS `template.abuse.abuse` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`_key` varchar(255) NOT NULL,
`_time` varchar(45) NOT NULL,
`_time` int(11) NOT NULL,
`_count` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `unique1` (`_key`,`_time`),
@ -15,7 +15,6 @@ CREATE TABLE IF NOT EXISTS `template.abuse.abuse` (
CREATE TABLE IF NOT EXISTS `template.audit.audit` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userId` varchar(45) NOT NULL,
`userType` int(11) NOT NULL,
`event` varchar(45) NOT NULL,
`resource` varchar(45) DEFAULT NULL,
`userAgent` text NOT NULL,
@ -25,7 +24,7 @@ CREATE TABLE IF NOT EXISTS `template.audit.audit` (
`data` longtext DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
KEY `index_1` (`userId`,`userType`),
KEY `index_1` (`userId`),
KEY `index_2` (`event`),
KEY `index_3` (`resource`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
@ -74,10 +73,18 @@ CREATE TABLE IF NOT EXISTS `template.database.relationships` (
KEY `relationships_end_nodes_id_idx` (`end`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `template.database.unique` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`key` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index1` (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
/* Default App */
CREATE TABLE IF NOT EXISTS `app_console.database.documents` LIKE `template.database.documents`;
CREATE TABLE IF NOT EXISTS `app_console.database.properties` LIKE `template.database.properties`;
CREATE TABLE IF NOT EXISTS `app_console.database.relationships` LIKE `template.database.relationships`;
CREATE TABLE IF NOT EXISTS `app_console.database.unique` LIKE `template.database.unique`;
CREATE TABLE IF NOT EXISTS `app_console.audit.audit` LIKE `template.audit.audit`;
CREATE TABLE IF NOT EXISTS `app_console.abuse.abuse` LIKE `template.abuse.abuse`;

View file

@ -26,7 +26,7 @@ const APP_USERAGENT = APP_NAME.'-Server v%s. Please report abuse at %s';
const APP_MODE_ADMIN = 'admin';
const APP_PAGING_LIMIT = 15;
const APP_CACHE_BUSTER = 55;
const APP_VERSION_STABLE = '0.5.2';
const APP_VERSION_STABLE = '0.5.3';
const APP_STORAGE_UPLOADS = '/storage/uploads';
const APP_STORAGE_CACHE = '/storage/cache';
const APP_STORAGE_CERTIFICATES = '/storage/certificates';

View file

@ -68,6 +68,15 @@ $callbacks = [
try {
$statement = $db->prepare("
CREATE TABLE IF NOT EXISTS `template.database.unique` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`key` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index1` (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `{$schema}`.`app_{$project->getId()}.database.unique` LIKE `template.database.unique`;
ALTER TABLE `{$schema}`.`app_{$project->getId()}.audit.audit` DROP COLUMN IF EXISTS `userType`;
ALTER TABLE `{$schema}`.`app_{$project->getId()}.audit.audit` DROP INDEX IF EXISTS `index_1`;
ALTER TABLE `{$schema}`.`app_{$project->getId()}.audit.audit` ADD INDEX IF NOT EXISTS `index_1` (`userId` ASC);

View file

@ -84,7 +84,7 @@ services:
- _APP_SMTP_PORT=25
mariadb:
image: appwrite/mariadb:1.0.2 # fix issues when upgrading using: mysql_upgrade -u root -p
image: appwrite/mariadb:1.0.3 # fix issues when upgrading using: mysql_upgrade -u root -p
restart: unless-stopped
networks:
- appwrite

View file

@ -68,7 +68,7 @@ abstract class Adapter
*
* @return array
*/
abstract public function createDocument(array $data);
abstract public function createDocument(array $data, array $unique);
/**
* Update Document.

View file

@ -7,6 +7,7 @@ use Exception;
use PDO;
use Redis as Client;
use Database\Adapter;
use Database\Exception\Duplicate;
use Database\Validator\Authorization;
class MySQL extends Adapter
@ -150,7 +151,7 @@ class MySQL extends Adapter
*
* @return array
*/
public function createDocument(array $data = [])
public function createDocument(array $data = [], array $unique = [])
{
$order = 0;
$data = array_merge(['$id' => null, '$permissions' => []], $data); // Merge data with default params
@ -178,6 +179,21 @@ class MySQL extends Adapter
}
}
/**
* Check Unique Keys
*/
foreach($unique as $key => $value) {
$st = $this->getPDO()->prepare('INSERT INTO `'.$this->getNamespace().'.database.unique`
SET `key` = :key;
');
$st->bindValue(':key', md5($data['$collection'].':'.$key.'='.$value), PDO::PARAM_STR);
if(!$st->execute()) {
throw new Duplicate('Duplicated Property: '.$key.'='.$value);
}
}
// Add or update fields abstraction level
$st1 = $this->getPDO()->prepare('INSERT INTO `'.$this->getNamespace().'.database.documents`
SET uid = :uid, createdAt = :createdAt, updatedAt = :updatedAt, signature = :signature, revision = :revision, permissions = :permissions, status = 0
@ -397,6 +413,7 @@ class MySQL extends Adapter
$documents = 'app_'.$namespace.'.database.documents';
$properties = 'app_'.$namespace.'.database.properties';
$relationships = 'app_'.$namespace.'.database.relationships';
$unique = 'app_'.$namespace.'.database.unique';
$audit = 'app_'.$namespace.'.audit.audit';
$abuse = 'app_'.$namespace.'.abuse.abuse';
@ -404,6 +421,7 @@ class MySQL extends Adapter
$this->getPDO()->prepare('CREATE TABLE `'.$documents.'` LIKE `template.database.documents`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$properties.'` LIKE `template.database.properties`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$relationships.'` LIKE `template.database.relationships`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$unique.'` LIKE `template.database.unique`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$audit.'` LIKE `template.audit.audit`;')->execute();
$this->getPDO()->prepare('CREATE TABLE `'.$abuse.'` LIKE `template.abuse.abuse`;')->execute();
} catch (Exception $e) {

View file

@ -105,9 +105,9 @@ class Redis extends Adapter
*
* @throws Exception
*/
public function createDocument(array $data = [])
public function createDocument(array $data = [], array $unique = [])
{
$data = $this->adapter->createDocument($data);
$data = $this->adapter->createDocument($data, $unique);
$this->getRedis()->expire($this->getNamespace().':document-'.$data['$id'], 0);
$this->getRedis()->expire($this->getNamespace().':document-'.$data['$id'], 0);

View file

@ -182,7 +182,7 @@ class Database
* @throws AuthorizationException
* @throws StructureException
*/
public function createDocument(array $data)
public function createDocument(array $data, array $unique = [])
{
$document = new Document($data);
@ -198,7 +198,7 @@ class Database
throw new StructureException($validator->getDescription()); // var_dump($validator->getDescription()); return false;
}
return new Document($this->adapter->createDocument($data));
return new Document($this->adapter->createDocument($data, $unique));
}
/**

View file

@ -0,0 +1,7 @@
<?php
namespace Database\Exception;
class Duplicate extends \Exception
{
}