diff --git a/admin_scripts/migrate_to_9.5.php b/admin_scripts/migrate_to_9.5.php index 007d9472..f416600a 100755 --- a/admin_scripts/migrate_to_9.5.php +++ b/admin_scripts/migrate_to_9.5.php @@ -27,7 +27,7 @@ $dbDriver->query('UPDATE ' . $dbDriver->targetSchema . '.user SET name = \'anonymous\' || (floor(random() * 1000 + 1)::int)::TEXT WHERE name IS NULL'); $dbDriver->query('ALTER TABLE ' . $dbDriver->commonSchema . '.user RENAME name TO username'); $dbDriver->query('ALTER TABLE ' . $dbDriver->commonSchema . '.user ADD UNIQUE (username)'); - $dbDriver->query('ALTER TABLE ' . $dbDriver->commonSchema . '.user ALTER COLUMN settings SET DEFAULT \'{"notifyOnAddFeature":true,"notifyOnNewFollower":true,"notifyOnLikeFeature":true,"notifyOnAddComment":true,"showBio":true,"showIdentity":true,"showTopics":true,"showEmail":false,"profileNeedReview":true}\''); + $dbDriver->query('ALTER TABLE ' . $dbDriver->commonSchema . '.user ALTER COLUMN settings SET DEFAULT \'{"createdCatalogIsPublic":true,"createdCollectionIsPublic":true,"createdItemIsPublic":true,"notifyOnAddFeature":true,"notifyOnNewFollower":true,"notifyOnLikeFeature":true,"notifyOnAddComment":true,"showBio":true,"showIdentity":true,"showTopics":true,"showEmail":false,"profileNeedReview":true}\''); // Create private group per user $dbDriver->query('DROP INDEX IF EXISTS ' . $dbDriver->commonSchema . '.idx_uname_group'); diff --git a/app/resto/core/RestoCollection.php b/app/resto/core/RestoCollection.php index 5e6e248f..99ee6dec 100755 --- a/app/resto/core/RestoCollection.php +++ b/app/resto/core/RestoCollection.php @@ -658,7 +658,7 @@ public function __construct($id, $context, $user) $this->id = $id; $this->context = $context; $this->user = $user; - $this->visibility = RestoUtil::getDefaultVisibility($this->user, $this->context->core['defaultCollectionVisibility']); + $this->visibility = RestoUtil::getDefaultVisibility($this->user, isset($this->user->profile['settings']['createdCollectionIsPublic']) ? $this->user->profile['settings']['createdCollectionIsPublic'] : true); } /** diff --git a/app/resto/core/RestoConstants.php b/app/resto/core/RestoConstants.php index 0ada97b2..b7f617de 100644 --- a/app/resto/core/RestoConstants.php +++ b/app/resto/core/RestoConstants.php @@ -20,7 +20,7 @@ class RestoConstants // [IMPORTANT] Starting resto 7.x, default routes are defined in RestoRouter class // resto version - const VERSION = '9.5.0'; + const VERSION = '9.5.2'; /* ============================================================ * NEVER EVER TOUCH THESE VALUES diff --git a/app/resto/core/RestoContext.php b/app/resto/core/RestoContext.php index e5a9aa7c..d2c97bc7 100755 --- a/app/resto/core/RestoContext.php +++ b/app/resto/core/RestoContext.php @@ -59,11 +59,6 @@ class RestoContext // Default model applied to POST collection 'defaultModel' => 'DefaultModel', - // Default visibility applied to collection, catalog and item created by non admin user - 'defaultCollectionVisibility' => 'public', - 'defaultCatalogVisibility' => 'public', - 'defaultItemVisibility' => 'public', - // Use cache 'useCache' => false, diff --git a/app/resto/core/api/ServicesAPI.php b/app/resto/core/api/ServicesAPI.php index b50d749a..cd419395 100755 --- a/app/resto/core/api/ServicesAPI.php +++ b/app/resto/core/api/ServicesAPI.php @@ -33,8 +33,8 @@ public function __construct($context, $user) { $this->context = $context; $this->user = $user; - $this->title = getenv('STAC_ROOT_TITLE') ?? $this->title; - $this->description = getenv('STAC_ROOT_DESCRIPTION') ?? $this->description; + $this->title = getenv('STAC_ROOT_TITLE') && !empty(getenv('STAC_ROOT_TITLE')) ? getenv('STAC_ROOT_TITLE') : $this->title; + $this->description = getenv('STAC_ROOT_DESCRIPTION') && !empty(getenv('STAC_ROOT_DESCRIPTION')) ? getenv('STAC_ROOT_DESCRIPTION') : $this->description; } /** diff --git a/app/resto/core/api/UsersAPI.php b/app/resto/core/api/UsersAPI.php index 26489ebf..afdb52dc 100755 --- a/app/resto/core/api/UsersAPI.php +++ b/app/resto/core/api/UsersAPI.php @@ -517,7 +517,23 @@ public function updateUserProfile($params, $body) // name cannot be updated if ( isset($body['username']) ) { - RestoLogUtil::httpError(400, 'Property username cannot be updated'); + RestoLogUtil::httpError(400, 'Property username cannot be updated from this endpoint'); + } + + // Special case - settings are merged with existing settings + if ( isset($body['settings']) ) { + + // Forbidden settings cannot be changed + $forbiddenSettings = array( + 'profileNeedReview' + ); + for ($i = count($forbiddenSettings); $i--;) { + if ( isset($body['settings'][$forbiddenSettings[$i]])) { + RestoLogUtil::httpError(400, 'Property *' . $forbiddenSettings[$i] . '* in settings is protected and cannot be updated'); + } + } + // Merge input settings with user settings + $body['settings'] = array_merge($this->user->profile['settings'], $body['settings']); } /* diff --git a/app/resto/core/dbfunctions/CatalogsFunctions.php b/app/resto/core/dbfunctions/CatalogsFunctions.php index 4cca5ee9..8eea8075 100755 --- a/app/resto/core/dbfunctions/CatalogsFunctions.php +++ b/app/resto/core/dbfunctions/CatalogsFunctions.php @@ -607,7 +607,7 @@ private function storeCatalog($catalog, $user, $context, $collectionId, $feature $catalog['visibility'] = array(RestoConstants::GROUP_DEFAULT_ID); } if ( !isset($catalog['visibility']) ) { - $catalog['visibility'] = RestoUtil::getDefaultVisibility($user, $context->core['defaultCatalogVisibility']); + $catalog['visibility'] = RestoUtil::getDefaultVisibility($user, isset($user->profile['settings']['createdCatalogIsPublic']) ? $user->profile['settings']['createdCatalogIsPublic'] : true); } $insert = '(id, title, description, level, counters, owner, visibility, rtype, properties, created) SELECT $1,$2,$3,$4,$5,$6,$7,$8,$9,now()'; $values = array( diff --git a/app/resto/core/dbfunctions/FeaturesFunctions.php b/app/resto/core/dbfunctions/FeaturesFunctions.php index 531f9772..7611fd09 100755 --- a/app/resto/core/dbfunctions/FeaturesFunctions.php +++ b/app/resto/core/dbfunctions/FeaturesFunctions.php @@ -312,7 +312,7 @@ public function storeFeature($id, $collection, $featureArray) { // Default visibility - $visibility = RestoUtil::getDefaultVisibility($collection->user, $collection->context->core['defaultItemVisibility']); + $visibility = RestoUtil::getDefaultVisibility($collection->user, isset($collection->user->profile['settings']['createdItemIsPublic']) ? $collection->user->profile['settings']['createdItemIsPublic'] : true); $keysAndValues = $this->featureArrayToKeysValues( $collection, $featureArray, diff --git a/app/resto/core/dbfunctions/GroupsFunctions.php b/app/resto/core/dbfunctions/GroupsFunctions.php index 067f2ae0..f374d221 100755 --- a/app/resto/core/dbfunctions/GroupsFunctions.php +++ b/app/resto/core/dbfunctions/GroupsFunctions.php @@ -43,7 +43,7 @@ public function __construct($dbDriver) public function getGroups($params = array()) { $where = array( - 'private <> 1'/*, + /*'private <> 1', 'name NOT IN (\'admin\', \'default\')'*/ ); @@ -72,14 +72,14 @@ public function getGroups($params = array()) $where[] = 'owner=' . $this->dbDriver->escape_string( $params['owner']); } - $results = $this->dbDriver->fetch($this->dbDriver->query('SELECT name, description, id, to_iso8601(created) as created FROM ' . $this->dbDriver->commonSchema . '.group' . (count($where) > 0 ? ' WHERE ' . join(' AND ', $where) : '') . ' ORDER BY id DESC')); + $results = $this->dbDriver->fetch($this->dbDriver->query('SELECT name, description, id, to_iso8601(created) as created, private FROM ' . $this->dbDriver->commonSchema . '.group' . (count($where) > 0 ? ' WHERE ' . join(' AND ', $where) : '') . ' ORDER BY id DESC')); return empty($results) ? array() : $results; } /** - * List all groups + * Get group * * @return array * @throws Exception @@ -91,11 +91,11 @@ public function getGroup($name) } $query = join(' ', array( - 'SELECT g.name, g.description, g.owner, g.id, to_iso8601(g.created) as created, COALESCE(ARRAY_REMOVE(ARRAY_AGG(u.username ORDER BY u.username), NULL), \'{}\') AS members', + 'SELECT g.name, g.description, g.owner, g.id, to_iso8601(g.created) as created, g.private, COALESCE(ARRAY_REMOVE(ARRAY_AGG(u.username ORDER BY u.username), NULL), \'{}\') AS members', 'FROM ' . $this->dbDriver->commonSchema . '.group g LEFT JOIN ' . $this->dbDriver->commonSchema . '.group_member gm ON g.id = gm.groupid', 'LEFT JOIN ' . $this->dbDriver->commonSchema . '.user u ON gm.userid = u.id', 'WHERE private <> 1 AND g.name = \'' . $this->dbDriver->escape_string($name) . '\'', - 'GROUP BY g.name,g.description,g.owner,g.id,g.created ORDER BY g.name' + 'GROUP BY g.name,g.description,g.owner,g.id,g.created,g.private ORDER BY g.name' )); return $this->formatGroup($this->dbDriver->fetch($this->dbDriver->query($query))); @@ -264,6 +264,7 @@ private function formatGroup($rawGroup) } catch(Exception $e) { // Don't break } + $rawGroup[0]['private'] = (integer) $rawGroup[0]['private']; $rawGroup[0]['members'] = RestoUtil::SQLTextArrayToPHP($rawGroup[0]['members']); return $rawGroup[0]; } diff --git a/app/resto/core/utils/RestoUtil.php b/app/resto/core/utils/RestoUtil.php index 552ee397..deb1bd88 100755 --- a/app/resto/core/utils/RestoUtil.php +++ b/app/resto/core/utils/RestoUtil.php @@ -569,14 +569,15 @@ public static function isValidVisibility($visibility) * Return visibility for user * * @param RestoUser $user - * @param string $groupId + * @param boolean $createdResourceIsPublic */ - public static function getDefaultVisibility($user, $groupId) + public static function getDefaultVisibility($user, $createdResourceIsPublic) { - if ( $groupId === 'owner' ) { + if ( !$createdResourceIsPublic ) { $ownedGroups = $user->getOwnedGroups(); for ($i = 0, $ii = count($ownedGroups); $i < $ii; $i++) { - if ( $ownedGroups[$i]['private'] === 1 ) { + if ( $ownedGroups[$i]['private'] === "1" ) { + return array($ownedGroups[$i]['id']); } } diff --git a/build/resto/config.php.template b/build/resto/config.php.template index 9b081104..10c1bddc 100755 --- a/build/resto/config.php.template +++ b/build/resto/config.php.template @@ -13,9 +13,6 @@ return array( 'collectionMinMatch' => ${COLLECTION_MINMATCH:-0}, 'countCatalogs' => ${COUNT_CATALOGS:-false}, 'defaultModel' => '${DEFAULT_COLLECTION_MODEL:-DefaultModel}', - 'defaultCollectionVisibility' => '${DEFAULT_COLLECTION_VISIBILITY:-public}', - 'defaultCatalogVisibility' => '${DEFAULT_CATALOG_VISIBILITY:-public}', - 'defaultItemVisibility' => '${DEFAULT_ITEM_VISIBILITY:-public}', 'timezone' => '${TIMEZONE:-Europe/Paris}', 'tokenDuration' => ${JWT_DURATION:-8640000}, 'userAutoValidation' => ${USER_AUTOVALIDATION:-true}, diff --git a/config.env b/config.env index 407b6841..60c2a78a 100644 --- a/config.env +++ b/config.env @@ -27,12 +27,6 @@ RESTO_EXPOSED_PORT=5252 ### Default Model applied to collection #DEFAULT_COLLECTION_MODEL=DefaultModel -### Default GROUP visibility applied to collection,catalog and items -### when they are created with a non admin user. Should be one of "public" or "owner" -#DEFAULT_COLLECTION_VISIBILITY=public -#DEFAULT_CATALOG_VISIBILITY=public -#DEFAULT_ITEM_VISIBILITY=public - ### Permanent storage directory to store/retrieve files (e.g. user's avatar picture) ### Relative to PUBLIC_ENDPOINT if not starting with http #STORAGE_PUBLIC_ENDPOINT=/static diff --git a/examples/users/johnDoe_update_settings.json b/examples/users/johnDoe_update_settings.json new file mode 100644 index 00000000..74a045e1 --- /dev/null +++ b/examples/users/johnDoe_update_settings.json @@ -0,0 +1,5 @@ +{ + "settings": { + "createdCollectionIsPublic":false + } +} \ No newline at end of file diff --git a/resto-database-model/02_resto_common_model.sql b/resto-database-model/02_resto_common_model.sql index 97489583..6ee67035 100644 --- a/resto-database-model/02_resto_common_model.sql +++ b/resto-database-model/02_resto_common_model.sql @@ -82,7 +82,7 @@ CREATE TABLE IF NOT EXISTS __DATABASE_COMMON_SCHEMA__.user ( externalidp JSON, -- Free application settings - settings JSON DEFAULT '{"notifyOnAddFeature":true,"notifyOnNewFollower":true,"notifyOnLikeFeature":true,"notifyOnAddComment":true,"showBio":true,"showIdentity":true,"showTopics":true,"showEmail":false,"profileNeedReview":true}' + settings JSON DEFAULT '{"createdCatalogIsPublic":true,"createdCollectionIsPublic":true,"createdItemIsPublic":true,"notifyOnAddFeature":true,"notifyOnNewFollower":true,"notifyOnLikeFeature":true,"notifyOnAddComment":true,"showBio":true,"showIdentity":true,"showTopics":true,"showEmail":false,"profileNeedReview":true}' );