Commit fb2bcbe5 authored by Rob Commeren's avatar Rob Commeren 🐒
Browse files

Merge branch '2.0' into 'master'

Further cleanup and rewriting

See merge request extensions/wsspaces!1
parents fa43565c df2adb6c
Pipeline #429 passed with stages
in 15 seconds
......@@ -10,8 +10,6 @@ WSSpaces has two configuration variable.
* `$wgWSSpacesEnableSpaceArchiving` (boolean, default: true) Whether to allow archiving of spaces
* `$wgWSSpacesAutoAddAdminsToUserGroups` (boolean, default: false) Whether to automatically add space admins to a user group. Eg. An admin for a space with id 50000 will get added to a group called '50000Admin'. Will additionally add admins to a general 'SpaceAdmin' group that can be used to assign rights to all space admins.
* `$wgWSSpacesAllowNoAdmins` (boolean, default: false) If set to true, this will disable the validation check that at least one admin must be set for this space. This is not recommended.
* `$wgWSSpacesForceNamedGroup` (boolean, default: false) If set to true, this will force the message sent to MediaWiki to involve the Space key, rather than the Space id.
To enable Semantic MediaWiki for the created namespace, place the following code in between the initialization of Semantic MediaWiki and WSSpaces in LocalSettings.php:
......@@ -32,15 +30,7 @@ WSSpaces defines several hooks to alter or extend its behaviour.
public static function onWSSpacesAfterCreateSpace( \WSS\Space $space ) {}
```
Gets called once directly after a space has been created. NOTE: The space has not been initialized with the Wiki at this point. Therefore, you cannot create a page in this namespace (use a job instead).
### `WSSpacesBeforeInitializeSpace`
```php
public static function onWSSpacesBeforeInitializeSpace( \WSS\Space $space ) {}
```
Gets called on each page load after the space has been initialized into `$wgCanonicalNamespaces`.
Gets called once directly after a space has been created. NOTE: The space has not been initialized with the Wiki at this point. Therefore, you cannot create a page in this namespace (use a job instead). Similarly, this space is at this point unaware of the admins that it has as they are only set after this hook is called.
### `WSSpacesCustomApiExceptionHandler`
......@@ -72,6 +62,10 @@ Whether the user can add new spaces to the wiki or not.
Whether the user can archive existing spaces or not. This right does not affect the behaviour or
`$wgWSSpacesEnableSpaceArchiving`.
### `wss-view-space-admins`
Whether the user is able to view the admins for a space or not.
### `wss-view-spaces-overview`
Whether the user is able to view the overview of spaces or not.
......@@ -89,4 +83,5 @@ available:
Furthermore, the following API list (`?action=query`) modules are available:
* `spaces`
\ No newline at end of file
* `spaces`
* `spaceadmins`
\ No newline at end of file
......@@ -2,5 +2,5 @@
$magicWords = [];
$magicWords['en'] = [
'spaceadmins' => [ 0, "spaceadmins"],
];
\ No newline at end of file
'spaceadmins' => [ 0, "spaceadmins" ],
];
{
"name": "WSSpaces",
"version": "1.6.10",
"version": "2.0.1",
"namemsg": "wss-extensionname",
"url": "https://wikibase-solutions.com",
"type": "csp",
......@@ -10,7 +10,7 @@
"descriptionmsg": "wss-desc",
"license-name": "GPL-2.0-or-later",
"requires": {
"MediaWiki": ">= 1.31.0"
"MediaWiki": ">= 1.35.0"
},
"MessagesDirs": {
"WSSpaces": [
......@@ -40,6 +40,7 @@
"wss-edit-all-spaces",
"wss-add-space",
"wss-archive-space",
"wss-view-space-admins",
"wss-view-spaces-overview"
],
"GroupPermissions": {
......@@ -47,12 +48,14 @@
"wss-edit-all-spaces": true,
"wss-add-space": true,
"wss-archive-space": true,
"wss-view-space-admins": true,
"wss-view-spaces-overview": true
},
"spacemaster": {
"wss-edit-all-spaces": true,
"wss-add-space": true,
"wss-archive-space": true,
"wss-view-space-admins": true,
"wss-view-spaces-overview": true
}
},
......@@ -117,12 +120,6 @@
},
"WSSpacesAutoAddAdminsToUserGroups": {
"value": false
},
"WSSpacesAllowNoAdmins": {
"value": false
},
"WSSpacesForceNamedGroup": {
"value": false
}
},
"APIModules": {
......
......@@ -74,7 +74,8 @@
"wss-invalid-namespace": "A namespace may only consist of letters.",
"wss-invalid-namespace-name": "A namespace name may only consist of letters, numbers and spaces.",
"wss-namespace-name-in-use": "This namespace name is already in use. Please choose a different name.",
"version-contentmanagement": "Content management extensions",
"wss-unsupported-dbms": "WSSpaces does not support database type '$1'. Please use 'mysql', 'postgres' or 'sqlite'.",
"version-csp": "Content Services Platform",
"specialpages-group-wss-spaces": "Space management",
"log-name-space": "Space log",
"log-description-space": "This page lists all transactions to spaces, and spaces that were created.",
......@@ -108,5 +109,8 @@
"apihelp-query-example-archived": "Query all spaces that are archived.",
"apihelp-query-example-namespace-admins": "Query all admins belonging to a namespace.",
"wss-permission-denied": "You do not have permission to view the $1 list.",
"wss-permission-denied-spaceadmins": "You do not have permission to view the spaceadmins list."
"wss-permission-denied-spaceadmins": "You do not have permission to view the spaceadmins list.",
"wss-pf-invalid-number": "The namespace parameter must be a positive number.",
"wss-pf-no-admins-found": "No admins were found for namespace: $1",
"wss-pf-no-valid-admins": "None of the admins for namespace: $1 are valid MediaWiki Users."
}
\ No newline at end of file
<?php
namespace WSS\API;
use ApiUsageException;
......@@ -12,189 +11,152 @@ use WSS\Space;
use WSS\Validation\AddSpaceValidationCallback;
class ApiAddSpace extends ApiBase {
/**
* Evaluates the parameters, performs the requested query, and sets up
* the result. Concrete implementations of ApiBase must override this
* method to provide whatever functionality their module offers.
* Implementations must not produce any output on their own and are not
* expected to handle any errors.
*
* The execute() method will be invoked directly by ApiMain immediately
* before the result of the module is output. Aside from the
* constructor, implementations should assume that no other methods
* will be called externally on the module before the result is
* processed.
*
* The result data should be stored in the ApiResult object available
* through getResult().
*
* @throws ApiUsageException
* @throws MWException
*/
public function execute() {
$this->checkUserRightsAny( 'wss-add-space' );
$this->validateParameters();
$request_params = $this->extractRequestParams();
/**
* @var string
*/
$ns_key = $request_params["nskey"];
/**
* @var string
*/
$ns_name = $request_params["nsname"];
/**
* @var string
*/
$ns_description = $request_params["nsdescription"];
/**
* @var array
*/
$ns_admins = $request_params["nsadmins"];
$ns_admins = explode( ",", $ns_admins );
/**
* @var User
*/
$current_user = \RequestContext::getMain()->getUser();
// // Add the current user to the list of namespace admins
// $current_user_name = $current_user->getName();
// if ( !in_array( $current_user, $ns_admins ) ) {
// $ns_admins[] = $current_user_name;
// }
// If no admins were given, add current user to the list of admins.
if (!$ns_admins || empty($ns_admins)) {
$current_user_name = $current_user->getName();
$ns_admins[] = $current_user_name;
}
$space = Space::newFromValues( $ns_key, $ns_name, $ns_description, $current_user );
$namespace_repository = new NamespaceRepository();
$namespace_id = $namespace_repository->addSpace( $space );
// Update the list of namespace admins
$old_space = Space::newFromConstant( $namespace_id );
$new_space = Space::newFromConstant( $namespace_id );
$new_space->setSpaceAdministrators( $ns_admins );
$namespace_repository->updateSpace( $old_space, $new_space );
$this->getResult()->addValue( [], "result", "success" );
$this->getResult()->addValue( [ "namespace" ], "id", $namespace_id );
}
/**
* Evaluates the parameters given to the API module and throws an exception if the
* validation fails.
*
* @throws ApiUsageException
*/
private function validateParameters() {
$request_params = $this->extractRequestParams();
$ns_key = isset( $request_params["nskey"] ) ? $request_params["nskey"] : false;
if ( $ns_key === false ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nskey" ) );
}
$ns_name = isset( $request_params["nsname"] ) ? $request_params["nsname"] : false;
if ( $ns_name === false ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nsname" ) );
}
$ns_description = isset( $request_params["nsdescription"] ) ? $request_params["nsdescription"] : false;
if ( $ns_description === false ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nsdescription" ) );
}
$ns_admins = isset( $request_params["nsadmins"] ) ? $request_params["nsadmins"] : false;
if ( $ns_admins === false ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nsadmins" ) );
}
// Although this validation is made for HTMLForm, we use it here to avoid repeating ourselves
$add_space_validation_callback = new AddSpaceValidationCallback();
$request_data = [
"namespace" => $ns_key,
"namespace_name" => $ns_name,
"description" => $ns_description
];
// Validate "nskey"
$error_or_true = $add_space_validation_callback->validateField( "namespace", $ns_key, $request_data );
if ( $error_or_true !== true ) {
$this->dieWithError( wfMessage( "wss-api-invalid-param-detailed-nskey", $error_or_true ) );
}
// Validate "nsname"
$error_or_true = $add_space_validation_callback->validateField( "namespace_name", $ns_name, $request_data );
if ( $error_or_true !== true ) {
$this->dieWithError( wfMessage( "wss-api-invalid-param-detailed-nsname", $error_or_true ) );
}
// Validate "nsdescription"
if ( $add_space_validation_callback->validateRequired( $ns_description ) !== true ) {
$this->dieWithError( wfMessage( "wss-api-invalid-param-nsdescription" ) );
}
$ns_admins = explode( ",", $ns_admins );
if (!MediaWikiServices::getInstance()->getMainConfig()->get( "WSSpacesAllowNoAdmins" )) {
// Validate "nsadmins"
foreach ($ns_admins as $ns_admin_name) {
$user = User::newFromName($ns_admin_name);
if (!$user instanceof User || $user->isAnon()) {
$this->dieWithError(wfMessage("wss-api-invalid-param-nsadmins"));
}
}
}
}
/**
* @inheritDoc
*/
public function getAllowedParams(): array {
return [
'nskey' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nskey-param"
],
'nsname' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nsname-param"
],
'nsdescription' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nsdescription-param"
],
'nsadmins' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nsadmins-param"
]
];
}
/**
* @inheritDoc
*/
public function getExamplesMessages() {
return [
"action=addspace&nskey=Foo&nsname=Foo&nsdescription=Lorem ipsum&nsadmins=Admin,Foobar" =>
"apihelp-addspace-example-foo"
];
}
}
\ No newline at end of file
/**
* Evaluates the parameters, performs the requested query, and sets up
* the result. Concrete implementations of ApiBase must override this
* method to provide whatever functionality their module offers.
* Implementations must not produce any output on their own and are not
* expected to handle any errors.
*
* The execute() method will be invoked directly by ApiMain immediately
* before the result of the module is output. Aside from the
* constructor, implementations should assume that no other methods
* will be called externally on the module before the result is
* processed.
*
* The result data should be stored in the ApiResult object available
* through getResult().
*
* @throws ApiUsageException
* @throws MWException
*/
public function execute() {
$this->checkUserRightsAny( 'wss-add-space' );
$this->validateParameters();
$request_params = $this->extractRequestParams();
$ns_key = $request_params["nskey"];
$ns_name = $request_params["nsname"];
$ns_description = $request_params["nsdescription"];
$ns_admins = $request_params["nsadmins"];
$ns_admins = explode( ",", $ns_admins );
$current_user = \RequestContext::getMain()->getUser();
// If no admins were given, add current user to the list of admins.
if ( !$ns_admins || empty( $ns_admins ) ) {
$current_user_name = $current_user->getName();
$ns_admins[] = $current_user_name;
}
$space = Space::newFromValues( $ns_key, $ns_name, $ns_description, $current_user );
$namespace_repository = new NamespaceRepository();
$namespace_id = $namespace_repository->addSpace( $space );
// Update the list of namespace admins
$old_space = Space::newFromConstant( $namespace_id );
$new_space = clone $old_space;
$new_space->setSpaceAdministrators( $ns_admins );
$namespace_repository->updateSpace( $old_space, $new_space );
$this->getResult()->addValue( [], "result", "success" );
$this->getResult()->addValue( [ "namespace" ], "id", $namespace_id );
}
/**
* Evaluates the parameters given to the API module and throws an exception if the
* validation fails.
*
* @throws ApiUsageException
*/
private function validateParameters() {
$request_params = $this->extractRequestParams();
$ns_key = isset( $request_params["nskey"] ) ? $request_params["nskey"] : false;
if ( $ns_key === false ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nskey" ) );
}
$ns_name = isset( $request_params["nsname"] ) ? $request_params["nsname"] : false;
if ( $ns_name === false ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nsname" ) );
}
$ns_description = isset( $request_params["nsdescription"] ) ? $request_params["nsdescription"] : false;
if ( $ns_description === false ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nsdescription" ) );
}
$ns_admins = isset( $request_params["nsadmins"] ) ? $request_params["nsadmins"] : false;
if ( $ns_admins === false ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nsadmins" ) );
}
// Although this validation is made for HTMLForm, we use it here to avoid repeating ourselves
$add_space_validation_callback = new AddSpaceValidationCallback();
$request_data = [
"namespace" => $ns_key,
"namespace_name" => $ns_name,
"description" => $ns_description
];
// Validate "nskey"
$error_or_true = $add_space_validation_callback->validateField( "namespace", $ns_key, $request_data );
if ( $error_or_true !== true ) {
$this->dieWithError( wfMessage( "wss-api-invalid-param-detailed-nskey", $error_or_true ) );
}
// Validate "nsname"
$error_or_true = $add_space_validation_callback->validateField( "namespace_name", $ns_name, $request_data );
if ( $error_or_true !== true ) {
$this->dieWithError( wfMessage( "wss-api-invalid-param-detailed-nsname", $error_or_true ) );
}
// Validate "nsdescription"
if ( $add_space_validation_callback->validateRequired( $ns_description ) !== true ) {
$this->dieWithError( wfMessage( "wss-api-invalid-param-nsdescription" ) );
}
}
/**
* @inheritDoc
*/
public function getAllowedParams(): array {
return [
'nskey' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nskey-param"
],
'nsname' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nsname-param"
],
'nsdescription' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nsdescription-param"
],
'nsadmins' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nsadmins-param"
]
];
}
/**
* @inheritDoc
*/
public function getExamplesMessages() {
return [
"action=addspace&nskey=Foo&nsname=Foo&nsdescription=Lorem ipsum&nsadmins=Admin,Foobar" =>
"apihelp-addspace-example-foo"
];
}
}
<?php
namespace WSS\API;
use ApiUsageException;
......@@ -8,73 +7,73 @@ use WSS\NamespaceRepository;
use WSS\Space;
class ApiArchiveSpace extends ApiBase {
/**
* Evaluates the parameters, performs the requested query, and sets up
* the result. Concrete implementations of ApiBase must override this
* method to provide whatever functionality their module offers.
* Implementations must not produce any output on their own and are not
* expected to handle any errors.
*
* The execute() method will be invoked directly by ApiMain immediately
* before the result of the module is output. Aside from the
* constructor, implementations should assume that no other methods
* will be called externally on the module before the result is
* processed.
*
* The result data should be stored in the ApiResult object available
* through getResult().
*
* @throws ApiUsageException
* @throws \MWException
* @throws \PermissionsError
*/
public function execute() {
if ( !Space::canArchive() ) {
$this->dieWithError( [ 'apierror-permissiondenied', $this->msg( "action-wss-archive-space" ) ] );
}
/**
* Evaluates the parameters, performs the requested query, and sets up
* the result. Concrete implementations of ApiBase must override this
* method to provide whatever functionality their module offers.
* Implementations must not produce any output on their own and are not
* expected to handle any errors.
*
* The execute() method will be invoked directly by ApiMain immediately
* before the result of the module is output. Aside from the
* constructor, implementations should assume that no other methods
* will be called externally on the module before the result is
* processed.
*
* The result data should be stored in the ApiResult object available
* through getResult().
*
* @throws ApiUsageException
* @throws \MWException
* @throws \PermissionsError
*/
public function execute() {
if ( !Space::canArchive() ) {
$this->dieWithError( [ 'apierror-permissiondenied', $this->msg( "action-wss-archive-space" ) ] );
}
$request_params = $this->extractRequestParams();
$request_params = $this->extractRequestParams();
if ( !isset( $request_params["nskey"] ) ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nskey" ) );
}
if ( !isset( $request_params["nsid"] ) ) {
$this->dieWithError( wfMessage( "wss-api-missing-param-nsid" ) );
}
$space = Space::newFromKey( $request_params["nskey"] );
$space = Space::newFromConstant( $request_params["nsid"] );
if ( !$space instanceof Space ) {
$this->dieWithError(
wfMessage(
"wss-api-invalid-param-detailed-nskey",
wfMessage( "wss-api-space-does-not-exist", $request_params["nskey"] )->parse()
)
);
}
if ( !$space instanceof Space ) {
$this->dieWithError(
wfMessage(
"wss-api-invalid-param-detailed-nsid",
wfMessage( "wss-api-space-does-not-exist", $request_params["nsid"] )->parse()
)->parse()
);
}
$namespace_repository = new NamespaceRepository();
$namespace_repository->archiveSpace( $space );
$namespace_repository = new NamespaceRepository();
$namespace_repository->archiveSpace( $space );
$this->getResult()->addValue( [], "result", "success" );
}
$this->getResult()->addValue( [], "result", "success" );
}
/**
* @inheritDoc
*/
public function getAllowedParams(): array {
return [
'nskey' => [
ApiBase::PARAM_TYPE => "string",
ApiBase::PARAM_HELP_MSG => "wss-api-nskey-param"
]
];
}
/**
* @inheritDoc
*/
public function getAllowedParams(): array {
return [
'nsid' => [
ApiBase::PARAM_TYPE => "integer",
ApiBase::PARAM_HELP_MSG => "wss-api-nsid-param"
]
];
}
/**
* @inheritDoc
*/
public function getExamplesMessages() {
return [
"action=archivespace&nskey=Foo" =>
"apihelp-archivespace-example-foo"
];
}
}
\ No newline at end of file
/**
* @inheritDoc
*/
public function getExamplesMessages() {
return [
"action=archivespace&nsid=50000" =>
"apihelp-archivespace-example-foo"
];
}
}
<?php
namespace WSS\API;
use ApiUsageException;
use MediaWiki\MediaWikiServices;