diff options
69 files changed, 863 insertions, 152 deletions
diff --git a/.github/workflows/oci.yml b/.github/workflows/oci.yml index ad6ad22..e9aada0 100644 --- a/.github/workflows/oci.yml +++ b/.github/workflows/oci.yml @@ -49,10 +49,6 @@ jobs: with: path: apps/${{ env.APP_NAME }} - - name: Set up PHPUnit - working-directory: apps/${{ env.APP_NAME }} - run: composer i - - name: Set up php ${{ matrix.php-versions }} uses: "shivammathur/setup-php@v2" with: @@ -61,6 +57,10 @@ jobs: tools: phpunit:8.5.2 coverage: none + - name: Set up PHPUnit + working-directory: apps/${{ env.APP_NAME }} + run: composer i + - name: Set up Nextcloud run: | mkdir data @@ -107,3 +107,23 @@ https://<nextcloud-fqdn>/ocs/v2.php/apps/serverinfo/api/v1/info ``` {"ocs":{"meta":{"status":"ok","statuscode":200,"message":"OK"},"data":{"nextcloud":{"system":{"version":"15.0.4.0","theme":"","enable_avatars":"yes","enable_previews":"yes","memcache.local":"OC\\Memcache\\APCu","memcache.distributed":"none","filelocking.enabled":"yes","memcache.locking":"OC\\Memcache\\Redis","debug":"no","freespace":48472944640,"cpuload":[0.84999999999999997779553950749686919152736663818359375,1.04000000000000003552713678800500929355621337890625,1.1699999999999999289457264239899814128875732421875],"mem_total":8183664,"mem_free":5877156,"swap_total":0,"swap_free":0,"apps":{"num_installed":53,"num_updates_available":1,"app_updates":{"files_antivirus":"2.0.1"}}},"storage":{"num_users":7,"num_files":708860,"num_storages":125,"num_storages_local":7,"num_storages_home":7,"num_storages_other":111},"shares":{"num_shares":1,"num_shares_user":0,"num_shares_groups":0,"num_shares_link":0,"num_shares_link_no_password":0,"num_fed_shares_sent":0,"num_fed_shares_received":0,"permissions_4_1":"1"}},"server":{"webserver":"Apache\/2.4","php":{"version":"7.2.14","memory_limit":536870912,"max_execution_time":3600,"upload_max_filesize":535822336},"database":{"type":"mysql","version":"10.2.21","size":331382784}},"activeUsers":{"last5minutes":2,"last1hour":3,"last24hours":5}}}} ``` + +## Configuration + +Since collecting storage statistics might take time and cause slow downs, they are updated in the background. A background job runs once every three hours to update the number of storages and files. The interval can be overridden per app settings (the value is specified in seconds): + +``php occ config:app:set --value=3600 serverinfo job_interval_storage_stats`` + +It is also possible to trigger the update manually per occ call. With verbose mode enabled, the current values are being printed. + +``` +php occ serverinfo:update-storage-statistics -v --output=json_pretty +{ + "num_users": 80, + "num_files": 3934, + "num_storages": 2545, + "num_storages_local": 2, + "num_storages_home": 2510, + "num_storages_other": 33 +} +``` diff --git a/appinfo/info.xml b/appinfo/info.xml index 66f77f3..61fe973 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -17,6 +17,12 @@ <dependencies> <nextcloud min-version="22" max-version="22" /> </dependencies> + <background-jobs> + <job>OCA\ServerInfo\Jobs\UpdateStorageStats</job> + </background-jobs> + <commands> + <command>OCA\ServerInfo\Commands\UpdateStorageStats</command> + </commands> <settings> <admin>OCA\ServerInfo\Settings\AdminSettings</admin> <admin-section>OCA\ServerInfo\Settings\AdminSection</admin-section> diff --git a/appinfo/routes.php b/appinfo/routes.php index 011dedf..7d06e7c 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -6,6 +6,7 @@ OC.L10N.register( "Users" : "Gebruikers", "Groups" : "Groepe", "Links" : "Skakels", + "1 hour" : "1 uur", "Copy" : "Kopieer", "Copied!" : "Gekopieer!", "Not supported!" : "Word nie ondersteun nie!", diff --git a/l10n/af.json b/l10n/af.json index 374fb35..3c5bbf5 100644 --- a/l10n/af.json +++ b/l10n/af.json @@ -4,6 +4,7 @@ "Users" : "Gebruikers", "Groups" : "Groepe", "Links" : "Skakels", + "1 hour" : "1 uur", "Copy" : "Kopieer", "Copied!" : "Gekopieer!", "Not supported!" : "Word nie ondersteun nie!", @@ -24,7 +24,7 @@ OC.L10N.register( "Press Ctrl-C to copy." : "Zkopírujete stisknutím Ctrl+C.", "System" : "Systém", "Monitoring" : "Dohledování", - "Monitoring app with useful server information" : "Dohledovací aplikace s užitečnými informacemi o serveru", + "Monitoring app with useful server information" : "Dohledovací aplikace, poskytující užitečné informace o serveru", "Provides useful server information, such as CPU load, RAM usage, disk usage, number of users, etc." : "Poskytuje užitečné informace o serveru, jako vytížení procesoru, využití operační paměti, obsazenost datového úložiště, počet uživatelů, atd.", "Operating System" : "Operační systém", "CPU" : "Procesor", @@ -64,7 +64,9 @@ OC.L10N.register( "Size:" : "Velikost:", "External monitoring tool" : "Externí nástroj pro dohledování", "You can connect an external monitoring tool by using this end point:" : "Externí dohledovací nástroj je možné napojit pomocí tohoto koncového bodu:", - "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Připojení \"?format=json\" na konec URL poskytne výsledek ve formátu JSON.", + "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Připojení „?format=json“ na konec URL poskytne výsledek ve formátu JSON.", + "To use an access token please generate one then set it using the following command:" : "Aby bylo možné použít přístupový token, vytvořte ho a nastavte pomocí následujícího příkazu:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Poté při dotazování výše uvedené URL předávejte se záhlavím „NC-Token“.", "Time Servers" : "Časové servery" }, "nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;"); diff --git a/l10n/cs.json b/l10n/cs.json index 36c5116..b7809b8 100644 --- a/l10n/cs.json +++ b/l10n/cs.json @@ -22,7 +22,7 @@ "Press Ctrl-C to copy." : "Zkopírujete stisknutím Ctrl+C.", "System" : "Systém", "Monitoring" : "Dohledování", - "Monitoring app with useful server information" : "Dohledovací aplikace s užitečnými informacemi o serveru", + "Monitoring app with useful server information" : "Dohledovací aplikace, poskytující užitečné informace o serveru", "Provides useful server information, such as CPU load, RAM usage, disk usage, number of users, etc." : "Poskytuje užitečné informace o serveru, jako vytížení procesoru, využití operační paměti, obsazenost datového úložiště, počet uživatelů, atd.", "Operating System" : "Operační systém", "CPU" : "Procesor", @@ -62,7 +62,9 @@ "Size:" : "Velikost:", "External monitoring tool" : "Externí nástroj pro dohledování", "You can connect an external monitoring tool by using this end point:" : "Externí dohledovací nástroj je možné napojit pomocí tohoto koncového bodu:", - "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Připojení \"?format=json\" na konec URL poskytne výsledek ve formátu JSON.", + "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Připojení „?format=json“ na konec URL poskytne výsledek ve formátu JSON.", + "To use an access token please generate one then set it using the following command:" : "Aby bylo možné použít přístupový token, vytvořte ho a nastavte pomocí následujícího příkazu:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Poté při dotazování výše uvedené URL předávejte se záhlavím „NC-Token“.", "Time Servers" : "Časové servery" },"pluralForm" :"nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Externes Überwachungsprogramm", "You can connect an external monitoring tool by using this end point:" : "Durch Verwendung des folgenden Zugangspunktes kann ein externes Überwachungsprogramm verwendet werden: ", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Wenn Du \"?format=json\" am Ende der URL anhängst, erhältst Du das Ergebnis in JSON.", + "To use an access token please generate one then set it using the following command:" : "Um einen Zugriffstoken zu verwenden, erzeuge bitte einen und setze ihn dann mit dem folgenden Befehl:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Übergebe dann das Token mit dem \"NC-Token\"-Header bei der Abfrage der obigen URL.", "Time Servers" : "Zeitserver" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/de.json b/l10n/de.json index baa439d..96ebe76 100644 --- a/l10n/de.json +++ b/l10n/de.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Externes Überwachungsprogramm", "You can connect an external monitoring tool by using this end point:" : "Durch Verwendung des folgenden Zugangspunktes kann ein externes Überwachungsprogramm verwendet werden: ", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Wenn Du \"?format=json\" am Ende der URL anhängst, erhältst Du das Ergebnis in JSON.", + "To use an access token please generate one then set it using the following command:" : "Um einen Zugriffstoken zu verwenden, erzeuge bitte einen und setze ihn dann mit dem folgenden Befehl:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Übergebe dann das Token mit dem \"NC-Token\"-Header bei der Abfrage der obigen URL.", "Time Servers" : "Zeitserver" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file diff --git a/l10n/de_DE.js b/l10n/de_DE.js index 5eb258e..5b4470a 100644 --- a/l10n/de_DE.js +++ b/l10n/de_DE.js @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Externes Überwachungsprogramm", "You can connect an external monitoring tool by using this end point:" : "Durch Verwendung des folgenden Zugangspunktes kann ein externes Überwachungsprogramm verwendet werden: ", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Wenn Sie \"?format=json\" am Ende der URL anhängen, erhalten Sie das Ergebnis in JSON.", + "To use an access token please generate one then set it using the following command:" : "Um ein Zugriffstoken zu verwenden, generieren Sie bitte eines und legen Sie es mit dem folgenden Befehl fest:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Übergeben Sie dann das Token mit dem Header \"NC-Token\" durch Aufrufen der obige URL.", "Time Servers" : "Zeitserver" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/de_DE.json b/l10n/de_DE.json index e85469f..7d16be9 100644 --- a/l10n/de_DE.json +++ b/l10n/de_DE.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Externes Überwachungsprogramm", "You can connect an external monitoring tool by using this end point:" : "Durch Verwendung des folgenden Zugangspunktes kann ein externes Überwachungsprogramm verwendet werden: ", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Wenn Sie \"?format=json\" am Ende der URL anhängen, erhalten Sie das Ergebnis in JSON.", + "To use an access token please generate one then set it using the following command:" : "Um ein Zugriffstoken zu verwenden, generieren Sie bitte eines und legen Sie es mit dem folgenden Befehl fest:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Übergeben Sie dann das Token mit dem Header \"NC-Token\" durch Aufrufen der obige URL.", "Time Servers" : "Zeitserver" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Herramienta externa de monitorización", "You can connect an external monitoring tool by using this end point:" : "Puedes conectar una herramienta de monitorización externa usando este endpoint:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Añadiendo \"?format=json\" al final de la URL, devuelve el resultado en formato JSON.", + "To use an access token please generate one then set it using the following command:" : "Para usar un token de acceso, por favor, genere uno y luego establézcalo usando el siguiente comando:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Luego pase el token en el header \"NC-Token\" cuando solicite la URL anterior.", "Time Servers" : "Servidores de hora" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/es.json b/l10n/es.json index 0cadda6..af20540 100644 --- a/l10n/es.json +++ b/l10n/es.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Herramienta externa de monitorización", "You can connect an external monitoring tool by using this end point:" : "Puedes conectar una herramienta de monitorización externa usando este endpoint:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Añadiendo \"?format=json\" al final de la URL, devuelve el resultado en formato JSON.", + "To use an access token please generate one then set it using the following command:" : "Para usar un token de acceso, por favor, genere uno y luego establézcalo usando el siguiente comando:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Luego pase el token en el header \"NC-Token\" cuando solicite la URL anterior.", "Time Servers" : "Servidores de hora" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Kanpo jarraipen tresna", "You can connect an external monitoring tool by using this end point:" : " Kanpoko kontrol-tresna konektatu daiteke amaiera-puntu hau erabiliz:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "URL-aren amaieran \"?format=json\" eransteak emaitza JSON-en ematen du.", + "To use an access token please generate one then set it using the following command:" : "Sarbide token bat erabiltzeko, sortu eta ezarri komando hau erabiliz:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Ondoren, pasatu token-a \"NC-Token\" goiburuarekin goiko URLa kontsultatzerakoan.", "Time Servers" : "Denbora-zerbitzariak" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/eu.json b/l10n/eu.json index ec2d067..0a4423d 100644 --- a/l10n/eu.json +++ b/l10n/eu.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Kanpo jarraipen tresna", "You can connect an external monitoring tool by using this end point:" : " Kanpoko kontrol-tresna konektatu daiteke amaiera-puntu hau erabiliz:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "URL-aren amaieran \"?format=json\" eransteak emaitza JSON-en ematen du.", + "To use an access token please generate one then set it using the following command:" : "Sarbide token bat erabiltzeko, sortu eta ezarri komando hau erabiliz:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Ondoren, pasatu token-a \"NC-Token\" goiburuarekin goiko URLa kontsultatzerakoan.", "Time Servers" : "Denbora-zerbitzariak" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Ferramenta externa de supervisión", "You can connect an external monitoring tool by using this end point:" : "Pode conectar unha ferramenta externa de seguimento usando este punto final:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Engadindo «?format=json» na fin do URL devolve o resultado en JSON.", + "To use an access token please generate one then set it using the following command:" : "Para usar un testemuño de acceso, xéreo e configúreo usando a seguinte orde:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "A continuación, pase o testemuño coa cabeceira «Token NC» ao consultar o URL anterior.", "Time Servers" : "Servidores de hora" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/gl.json b/l10n/gl.json index 01ac349..93a18fb 100644 --- a/l10n/gl.json +++ b/l10n/gl.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Ferramenta externa de supervisión", "You can connect an external monitoring tool by using this end point:" : "Pode conectar unha ferramenta externa de seguimento usando este punto final:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Engadindo «?format=json» na fin do URL devolve o resultado en JSON.", + "To use an access token please generate one then set it using the following command:" : "Para usar un testemuño de acceso, xéreo e configúreo usando a seguinte orde:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "A continuación, pase o testemuño coa cabeceira «Token NC» ao consultar o URL anterior.", "Time Servers" : "Servidores de hora" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Külső monitorozó eszköz", "You can connect an external monitoring tool by using this end point:" : "Ennek a végpontnak a használatával külső monitorozó eszközt csatlakoztathatsz:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Az URL végéhez \"?format=json\" hozzáfűzésével az eredményt JSON formátumban kapod meg!", + "To use an access token please generate one then set it using the following command:" : "Hozzáférési token használatához kérjük, hozzon létre egyet, majd állítsa be a következő paranccsal:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Ezután adja át a tokent az \"NC-Token\" fejléccel, amikor lekérdezi a fenti URL-t.", "Time Servers" : "Időkiszolgálók" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/hu.json b/l10n/hu.json index 589040f..7f7c0b8 100644 --- a/l10n/hu.json +++ b/l10n/hu.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Külső monitorozó eszköz", "You can connect an external monitoring tool by using this end point:" : "Ennek a végpontnak a használatával külső monitorozó eszközt csatlakoztathatsz:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Az URL végéhez \"?format=json\" hozzáfűzésével az eredményt JSON formátumban kapod meg!", + "To use an access token please generate one then set it using the following command:" : "Hozzáférési token használatához kérjük, hozzon létre egyet, majd állítsa be a következő paranccsal:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Ezután adja át a tokent az \"NC-Token\" fejléccel, amikor lekérdezi a fenti URL-t.", "Time Servers" : "Időkiszolgálók" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Strumento di controllo esterno", "You can connect an external monitoring tool by using this end point:" : "Puoi collegare uno strumento di controllo esterno utilizzando questo terminatore: ", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "L'aggiunta di \"?format=json\" alla fine dell'URL ti fornirà il risultato in JSON.", + "To use an access token please generate one then set it using the following command:" : "Per usare un token di accesso, generane uno e poi impostalo con il comando seguente:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Poi passa il token con l'intestazione \"NC-Token\" quando richiami l'URL qua sopra.", "Time Servers" : "Server dell'ora" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/it.json b/l10n/it.json index 84bad8b..216ebe6 100644 --- a/l10n/it.json +++ b/l10n/it.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Strumento di controllo esterno", "You can connect an external monitoring tool by using this end point:" : "Puoi collegare uno strumento di controllo esterno utilizzando questo terminatore: ", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "L'aggiunta di \"?format=json\" alla fine dell'URL ti fornirà il risultato in JSON.", + "To use an access token please generate one then set it using the following command:" : "Per usare un token di accesso, generane uno e poi impostalo con il comando seguente:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Poi passa il token con l'intestazione \"NC-Token\" quando richiami l'URL qua sopra.", "Time Servers" : "Server dell'ora" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file @@ -19,7 +19,7 @@ OC.L10N.register( "5 mins" : "5分", "Copy" : "コピー", "Copied!" : "コピー完了", - "Not supported!" : "未対応", + "Not supported!" : "対応していません!", "Press ⌘-C to copy." : "⌘-C でコピーします。", "Press Ctrl-C to copy." : "Ctrl-Cを押してコピーします。", "System" : "システム", @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "外部モニタリングツール", "You can connect an external monitoring tool by using this end point:" : "このエンドポイントを利用して外部モニタリングツールに接続することが可能です:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "URLの最後に \"?format=json\" を追加すると、JSONの結果が得られます。", + "To use an access token please generate one then set it using the following command:" : "アクセストークンを使用するには、トークンを生成してから、次のコマンドを使用して設定してください:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "次に、上記のURLをクエリするときに、\"NC-Token\" ヘッダーでトークンを渡します。", "Time Servers" : "タイムサーバー" }, "nplurals=1; plural=0;"); diff --git a/l10n/ja.json b/l10n/ja.json index 95b9208..5bdbf91 100644 --- a/l10n/ja.json +++ b/l10n/ja.json @@ -17,7 +17,7 @@ "5 mins" : "5分", "Copy" : "コピー", "Copied!" : "コピー完了", - "Not supported!" : "未対応", + "Not supported!" : "対応していません!", "Press ⌘-C to copy." : "⌘-C でコピーします。", "Press Ctrl-C to copy." : "Ctrl-Cを押してコピーします。", "System" : "システム", @@ -63,6 +63,8 @@ "External monitoring tool" : "外部モニタリングツール", "You can connect an external monitoring tool by using this end point:" : "このエンドポイントを利用して外部モニタリングツールに接続することが可能です:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "URLの最後に \"?format=json\" を追加すると、JSONの結果が得られます。", + "To use an access token please generate one then set it using the following command:" : "アクセストークンを使用するには、トークンを生成してから、次のコマンドを使用して設定してください:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "次に、上記のURLをクエリするときに、\"NC-Token\" ヘッダーでトークンを渡します。", "Time Servers" : "タイムサーバー" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Externe monitoring tool", "You can connect an external monitoring tool by using this end point:" : "Je kunt een externe monitor-tool verbinden door dit end point te gebruiken:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Wanneer je \"?format=json\" toevoegt aan het einde van de URL ontvang je het resultaat in JSON", + "To use an access token please generate one then set it using the following command:" : "Om een toegangstoken te gebruiken, genereer je er een en stel je deze in met behulp van de volgende opdracht:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Geef vervolgens het token met de \"NC-Token\" -header door bij het opvragen van de bovenstaande URL.", "Time Servers" : "Tijdservers" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/nl.json b/l10n/nl.json index cb5bfc7..80f6048 100644 --- a/l10n/nl.json +++ b/l10n/nl.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Externe monitoring tool", "You can connect an external monitoring tool by using this end point:" : "Je kunt een externe monitor-tool verbinden door dit end point te gebruiken:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Wanneer je \"?format=json\" toevoegt aan het einde van de URL ontvang je het resultaat in JSON", + "To use an access token please generate one then set it using the following command:" : "Om een toegangstoken te gebruiken, genereer je er een en stel je deze in met behulp van de volgende opdracht:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Geef vervolgens het token met de \"NC-Token\" -header door bij het opvragen van de bovenstaande URL.", "Time Servers" : "Tijdservers" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Zewnętrzne narzędzie monitorujące", "You can connect an external monitoring tool by using this end point:" : "Możesz połączyć się z zewnętrznym narzędziem monitorującym używając tej końcówki: ", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Dołączenie \"?format=json\" na końcu adresu URL daje wynik w formacie JSON.", + "To use an access token please generate one then set it using the following command:" : "Aby użyć tokena dostępu, wygeneruj go, a następnie ustaw za pomocą następującego polecenia:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Następnie przekaż token z nagłówkiem \"NC-Token\" podczas odpytywania powyższego adresu URL.", "Time Servers" : "Serwery czasu" }, "nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);"); diff --git a/l10n/pl.json b/l10n/pl.json index 7dba16d..e1a80ca 100644 --- a/l10n/pl.json +++ b/l10n/pl.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Zewnętrzne narzędzie monitorujące", "You can connect an external monitoring tool by using this end point:" : "Możesz połączyć się z zewnętrznym narzędziem monitorującym używając tej końcówki: ", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Dołączenie \"?format=json\" na końcu adresu URL daje wynik w formacie JSON.", + "To use an access token please generate one then set it using the following command:" : "Aby użyć tokena dostępu, wygeneruj go, a następnie ustaw za pomocą następującego polecenia:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Następnie przekaż token z nagłówkiem \"NC-Token\" podczas odpytywania powyższego adresu URL.", "Time Servers" : "Serwery czasu" },"pluralForm" :"nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);" }
\ No newline at end of file diff --git a/l10n/pt_BR.js b/l10n/pt_BR.js index 778516a..cf2b673 100644 --- a/l10n/pt_BR.js +++ b/l10n/pt_BR.js @@ -2,7 +2,7 @@ OC.L10N.register( "serverinfo", { "CPU info not available" : "Informação da CPU não disponível", - "Load average" : "Carregamento médio", + "Load average" : "Carga média", "Last minute" : "Último minuto", "Memory info not available" : "Informações de memória não disponíveis", "Total" : "Total", @@ -31,9 +31,9 @@ OC.L10N.register( "Memory" : "Memória", "Server time" : "Hora do servidor", "Uptime" : "Tempo ativo", - "Load" : "Carregar", + "Load" : "Carga", "Disk" : "Disco", - "Mount" : "Montar", + "Mount" : "Montagem", "Filesystem" : "Sistema de arquivos", "Size" : "Tamanho", "Available" : "Disponível", @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Ferramenta de monitoramento externo", "You can connect an external monitoring tool by using this end point:" : "Você pode conectar uma ferramenta de monitoramento externa usando este ponto final:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Adicionar \"?format=json\" no final da URL dá a você o resultado em JSON.", + "To use an access token please generate one then set it using the following command:" : "Para usar um token de acesso, gere um e defina-o usando o seguinte comando:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Em seguida, passe o token com o cabeçalho \"NC-Token\" ao consultar o URL acima.", "Time Servers" : "Servidores de Horário" }, "nplurals=2; plural=(n > 1);"); diff --git a/l10n/pt_BR.json b/l10n/pt_BR.json index 61a302e..b37764c 100644 --- a/l10n/pt_BR.json +++ b/l10n/pt_BR.json @@ -1,6 +1,6 @@ { "translations": { "CPU info not available" : "Informação da CPU não disponível", - "Load average" : "Carregamento médio", + "Load average" : "Carga média", "Last minute" : "Último minuto", "Memory info not available" : "Informações de memória não disponíveis", "Total" : "Total", @@ -29,9 +29,9 @@ "Memory" : "Memória", "Server time" : "Hora do servidor", "Uptime" : "Tempo ativo", - "Load" : "Carregar", + "Load" : "Carga", "Disk" : "Disco", - "Mount" : "Montar", + "Mount" : "Montagem", "Filesystem" : "Sistema de arquivos", "Size" : "Tamanho", "Available" : "Disponível", @@ -63,6 +63,8 @@ "External monitoring tool" : "Ferramenta de monitoramento externo", "You can connect an external monitoring tool by using this end point:" : "Você pode conectar uma ferramenta de monitoramento externa usando este ponto final:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Adicionar \"?format=json\" no final da URL dá a você o resultado em JSON.", + "To use an access token please generate one then set it using the following command:" : "Para usar um token de acesso, gere um e defina-o usando o seguinte comando:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Em seguida, passe o token com o cabeçalho \"NC-Token\" ao consultar o URL acima.", "Time Servers" : "Servidores de Horário" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/l10n/pt_PT.js b/l10n/pt_PT.js index befec57..2cbe18c 100644 --- a/l10n/pt_PT.js +++ b/l10n/pt_PT.js @@ -1,6 +1,7 @@ OC.L10N.register( "serverinfo", { + "CPU info not available" : "Informação do CPU indisponível", "Load average" : "Carga média", "Last minute" : "Ultimo minuto", "Memory info not available" : "Informação de memória não disponível", @@ -9,8 +10,13 @@ OC.L10N.register( "Users" : "Utilizadores", "Groups" : "Grupos", "Links" : "Hiperligações", + "Mails" : "Mensagens", + "Federated sent" : "Federada enviada", + "Federated received" : "Federada recebida", + "Talk conversations" : "Conversas no Talk", "24 hours" : "24 horas", "1 hour" : "1 hora", + "5 mins" : "5 minutos", "Copy" : "Copiar", "Copied!" : "Copiado!", "Not supported!" : "Não suportado!", @@ -18,11 +24,34 @@ OC.L10N.register( "Press Ctrl-C to copy." : "Pressionar Ctrl-C para copiar.", "System" : "Sistema", "Monitoring" : "Monitorização", + "Monitoring app with useful server information" : "Aplicação de monitorização com informação útil do servidor", + "Provides useful server information, such as CPU load, RAM usage, disk usage, number of users, etc." : "Disponibiliza informação útil do servidor como a carga do CPU, utilização da RAM, utilização do disco, número de utilizadores, etc.", + "Operating System" : "Sistema operativo", + "CPU" : "CPU", + "Memory" : "Memória", + "Server time" : "Hora do servidor", + "Uptime" : "Tempo de actividade", + "Load" : "Carga", + "Disk" : "Disco", + "Mount" : "Montagem", + "Filesystem" : "Sistema de ficheiros", "Size" : "Tamanho", + "Available" : "Disponível", + "Used" : "Usado", + "You will get a notification once one of your disks is nearly full." : "Receberá uma notificação logo que um dos seus discos esteja perto de estar cheio.", "Files:" : "Ficheiros:", + "Storages:" : "Armazenamentos:", + "Free Space:" : "Espaço livre:", + "Network" : "Rede", "Hostname" : "Nome do Anfitrião", + "DNS" : "DNS", "Status" : "Estado", + "Speed" : "velocidade", + "MAC" : "MAC", + "IPv4" : "IPv4", + "IPv6" : "IPv6", "Active users" : "Utilizadores activos", + "Total users:" : "Total de utilizadores:", "Shares" : "Partilhas", "PHP" : "PHP", "Version:" : "Versão:", @@ -32,6 +61,8 @@ OC.L10N.register( "Database" : "Base de dados", "Type:" : "Tipo:", "Size:" : "Tamanho:", - "External monitoring tool" : "Ferramenta externa de monitorização" + "External monitoring tool" : "Ferramenta externa de monitorização", + "You can connect an external monitoring tool by using this end point:" : "Pode ligar uma ferramenta de monitorização externa ao usar \"endpoint\":", + "Time Servers" : "Servidores de hora" }, "nplurals=2; plural=(n != 1);"); diff --git a/l10n/pt_PT.json b/l10n/pt_PT.json index 5214cb4..3b139e2 100644 --- a/l10n/pt_PT.json +++ b/l10n/pt_PT.json @@ -1,4 +1,5 @@ { "translations": { + "CPU info not available" : "Informação do CPU indisponível", "Load average" : "Carga média", "Last minute" : "Ultimo minuto", "Memory info not available" : "Informação de memória não disponível", @@ -7,8 +8,13 @@ "Users" : "Utilizadores", "Groups" : "Grupos", "Links" : "Hiperligações", + "Mails" : "Mensagens", + "Federated sent" : "Federada enviada", + "Federated received" : "Federada recebida", + "Talk conversations" : "Conversas no Talk", "24 hours" : "24 horas", "1 hour" : "1 hora", + "5 mins" : "5 minutos", "Copy" : "Copiar", "Copied!" : "Copiado!", "Not supported!" : "Não suportado!", @@ -16,11 +22,34 @@ "Press Ctrl-C to copy." : "Pressionar Ctrl-C para copiar.", "System" : "Sistema", "Monitoring" : "Monitorização", + "Monitoring app with useful server information" : "Aplicação de monitorização com informação útil do servidor", + "Provides useful server information, such as CPU load, RAM usage, disk usage, number of users, etc." : "Disponibiliza informação útil do servidor como a carga do CPU, utilização da RAM, utilização do disco, número de utilizadores, etc.", + "Operating System" : "Sistema operativo", + "CPU" : "CPU", + "Memory" : "Memória", + "Server time" : "Hora do servidor", + "Uptime" : "Tempo de actividade", + "Load" : "Carga", + "Disk" : "Disco", + "Mount" : "Montagem", + "Filesystem" : "Sistema de ficheiros", "Size" : "Tamanho", + "Available" : "Disponível", + "Used" : "Usado", + "You will get a notification once one of your disks is nearly full." : "Receberá uma notificação logo que um dos seus discos esteja perto de estar cheio.", "Files:" : "Ficheiros:", + "Storages:" : "Armazenamentos:", + "Free Space:" : "Espaço livre:", + "Network" : "Rede", "Hostname" : "Nome do Anfitrião", + "DNS" : "DNS", "Status" : "Estado", + "Speed" : "velocidade", + "MAC" : "MAC", + "IPv4" : "IPv4", + "IPv6" : "IPv6", "Active users" : "Utilizadores activos", + "Total users:" : "Total de utilizadores:", "Shares" : "Partilhas", "PHP" : "PHP", "Version:" : "Versão:", @@ -30,6 +59,8 @@ "Database" : "Base de dados", "Type:" : "Tipo:", "Size:" : "Tamanho:", - "External monitoring tool" : "Ferramenta externa de monitorização" + "External monitoring tool" : "Ferramenta externa de monitorização", + "You can connect an external monitoring tool by using this end point:" : "Pode ligar uma ferramenta de monitorização externa ao usar \"endpoint\":", + "Time Servers" : "Servidores de hora" },"pluralForm" :"nplurals=2; plural=(n != 1);" }
\ No newline at end of file @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Внешний мониторинг", "You can connect an external monitoring tool by using this end point:" : "Вы можете подключить внешний мониторинг используя этот адрес:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Если к строке URL добавить «?format=json», то ответ сервера будет в формате JSON.", + "To use an access token please generate one then set it using the following command:" : "Чтобы использовать токен доступа, сгенерируйте его, а затем установите с помощью следующей команды:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Затем передайте токен с заголовком «NC-Token» при запросе указанного выше URL.", "Time Servers" : "Серверы времени" }, "nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);"); diff --git a/l10n/ru.json b/l10n/ru.json index 4713860..07d53d3 100644 --- a/l10n/ru.json +++ b/l10n/ru.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Внешний мониторинг", "You can connect an external monitoring tool by using this end point:" : "Вы можете подключить внешний мониторинг используя этот адрес:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Если к строке URL добавить «?format=json», то ответ сервера будет в формате JSON.", + "To use an access token please generate one then set it using the following command:" : "Чтобы использовать токен доступа, сгенерируйте его, а затем установите с помощью следующей команды:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Затем передайте токен с заголовком «NC-Token» при запросе указанного выше URL.", "Time Servers" : "Серверы времени" },"pluralForm" :"nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);" }
\ No newline at end of file diff --git a/l10n/si_LK.js b/l10n/si_LK.js deleted file mode 100644 index d57a48b..0000000 --- a/l10n/si_LK.js +++ /dev/null @@ -1,14 +0,0 @@ -OC.L10N.register( - "serverinfo", - { - "Users" : "පරිශීලකයන්", - "Groups" : "කණ්ඩායම්", - "Copied!" : "පිටපත් කරා", - "Not supported!" : "සහාය දක්වන්නේ නැත.", - "Press ⌘-C to copy." : "පිටපත් කිරීම සදහා Ctrl + C ඔබන්න.", - "Press Ctrl-C to copy." : "පිටපත් කිරීම සදහා Ctrl + C ඔබන්න.", - "Size" : "ප්රමාණය", - "Type:" : "ගණය:", - "Size:" : "විශාලත්වය:" -}, -"nplurals=2; plural=(n != 1);"); diff --git a/l10n/si_LK.json b/l10n/si_LK.json deleted file mode 100644 index ae2e627..0000000 --- a/l10n/si_LK.json +++ /dev/null @@ -1,12 +0,0 @@ -{ "translations": { - "Users" : "පරිශීලකයන්", - "Groups" : "කණ්ඩායම්", - "Copied!" : "පිටපත් කරා", - "Not supported!" : "සහාය දක්වන්නේ නැත.", - "Press ⌘-C to copy." : "පිටපත් කිරීම සදහා Ctrl + C ඔබන්න.", - "Press Ctrl-C to copy." : "පිටපත් කිරීම සදහා Ctrl + C ඔබන්න.", - "Size" : "ප්රමාණය", - "Type:" : "ගණය:", - "Size:" : "විශාලත්වය:" -},"pluralForm" :"nplurals=2; plural=(n != 1);" -}
\ No newline at end of file diff --git a/l10n/ta_LK.js b/l10n/ta.js index efb8741..efb8741 100644 --- a/l10n/ta_LK.js +++ b/l10n/ta.js diff --git a/l10n/ta_LK.json b/l10n/ta.json index 15fcc53..15fcc53 100644 --- a/l10n/ta_LK.json +++ b/l10n/ta.json @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "Dış izleme aracı", "You can connect an external monitoring tool by using this end point:" : "Bu uç noktasını kullanarak bir dış izleme aracı bağlayabilirsiniz:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Adresin sonuna \"?format=json\" eklendiğinde sonuçlar JSON biçiminde alınabilir.", + "To use an access token please generate one then set it using the following command:" : "Kullanmak için erişim kodunu üretip şu komutu yürüterek ayarlayın:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Ardından yukarıdaki adresi sorgularken kodu \"NC-Token\" üst bilgisi ile gönderin.", "Time Servers" : "Saat Sunucuları" }, "nplurals=2; plural=(n > 1);"); diff --git a/l10n/tr.json b/l10n/tr.json index ae506f1..8ddfed9 100644 --- a/l10n/tr.json +++ b/l10n/tr.json @@ -63,6 +63,8 @@ "External monitoring tool" : "Dış izleme aracı", "You can connect an external monitoring tool by using this end point:" : "Bu uç noktasını kullanarak bir dış izleme aracı bağlayabilirsiniz:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "Adresin sonuna \"?format=json\" eklendiğinde sonuçlar JSON biçiminde alınabilir.", + "To use an access token please generate one then set it using the following command:" : "Kullanmak için erişim kodunu üretip şu komutu yürüterek ayarlayın:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "Ardından yukarıdaki adresi sorgularken kodu \"NC-Token\" üst bilgisi ile gönderin.", "Time Servers" : "Saat Sunucuları" },"pluralForm" :"nplurals=2; plural=(n > 1);" }
\ No newline at end of file diff --git a/l10n/zh_CN.js b/l10n/zh_CN.js index fba8dce..dd2072b 100644 --- a/l10n/zh_CN.js +++ b/l10n/zh_CN.js @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "外部监控工具", "You can connect an external monitoring tool by using this end point:" : "此地址可用于外部监控工具:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "在 URL 末尾附加 \"?format=json\" 会为您提供 JSON 结果。", + "To use an access token please generate one then set it using the following command:" : "要使用一个访问令牌,请生成一个,然后使用以下命令设置它:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "然后在查询上述 URL 时传递带有 “NC-Token” 头的令牌。", "Time Servers" : "时间服务器" }, "nplurals=1; plural=0;"); diff --git a/l10n/zh_CN.json b/l10n/zh_CN.json index 111597f..146fc68 100644 --- a/l10n/zh_CN.json +++ b/l10n/zh_CN.json @@ -63,6 +63,8 @@ "External monitoring tool" : "外部监控工具", "You can connect an external monitoring tool by using this end point:" : "此地址可用于外部监控工具:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "在 URL 末尾附加 \"?format=json\" 会为您提供 JSON 结果。", + "To use an access token please generate one then set it using the following command:" : "要使用一个访问令牌,请生成一个,然后使用以下命令设置它:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "然后在查询上述 URL 时传递带有 “NC-Token” 头的令牌。", "Time Servers" : "时间服务器" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/l10n/zh_HK.js b/l10n/zh_HK.js index 8bc67c8..2535f8a 100644 --- a/l10n/zh_HK.js +++ b/l10n/zh_HK.js @@ -20,8 +20,8 @@ OC.L10N.register( "Copy" : "複製", "Copied!" : "已複製!", "Not supported!" : "不支援!", - "Press ⌘-C to copy." : "請按⌘-C以複製。", - "Press Ctrl-C to copy." : "請按Ctrl-C以複製。", + "Press ⌘-C to copy." : "請按【⌘-C】以複製。", + "Press Ctrl-C to copy." : "請按【Ctrl-C】以複製。", "System" : "系統", "Monitoring" : "監控", "Monitoring app with useful server information" : "使用有用的伺服器訊息以監控應用程式", @@ -38,11 +38,11 @@ OC.L10N.register( "Size" : "大小", "Available" : "可用", "Used" : "已使用", - "You will get a notification once one of your disks is nearly full." : "你將在硬碟使用量快要用完前收到一次通知。", - "Files:" : "檔案:", + "You will get a notification once one of your disks is nearly full." : "你將在其中一個硬碟快滿前收到通知。", + "Files:" : "檔案:", "Storages:" : "儲存設備:", "Free Space:" : "可用空間:", - "Network" : "網路", + "Network" : "網絡", "Hostname" : "主機名稱", "DNS" : "DNS", "Gateway" : "網關", @@ -55,16 +55,18 @@ OC.L10N.register( "Total users:" : "總用戶:", "Shares" : "分享", "PHP" : "PHP", - "Version:" : "版本:", - "Memory Limit:" : "記憶體限制:", + "Version:" : "版本:", + "Memory Limit:" : "記憶體限制:", "Max Execution Time:" : "最長執行時間:", - "Upload max size:" : "上傳至多:", - "Database" : "資料庫", - "Type:" : "類型:", - "Size:" : "大小:", + "Upload max size:" : "上傳至多:", + "Database" : "數據庫", + "Type:" : "類型:", + "Size:" : "大小:", "External monitoring tool" : "外部監控工具", "You can connect an external monitoring tool by using this end point:" : "您可以使用此終端連接外部監視工具:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "在URL後面連接參數 \"?format=json\" 將會得到json格式的回傳結果。", + "To use an access token please generate one then set it using the following command:" : "要使用存取權杖,請生成一個權杖,然後使用以下命令對其進行設置:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "然後在查詢上述 URL 時將權杖與 “ NC-Token” 標頭一起傳遞。", "Time Servers" : "時間伺服器" }, "nplurals=1; plural=0;"); diff --git a/l10n/zh_HK.json b/l10n/zh_HK.json index 6fe7fa6..817b33b 100644 --- a/l10n/zh_HK.json +++ b/l10n/zh_HK.json @@ -18,8 +18,8 @@ "Copy" : "複製", "Copied!" : "已複製!", "Not supported!" : "不支援!", - "Press ⌘-C to copy." : "請按⌘-C以複製。", - "Press Ctrl-C to copy." : "請按Ctrl-C以複製。", + "Press ⌘-C to copy." : "請按【⌘-C】以複製。", + "Press Ctrl-C to copy." : "請按【Ctrl-C】以複製。", "System" : "系統", "Monitoring" : "監控", "Monitoring app with useful server information" : "使用有用的伺服器訊息以監控應用程式", @@ -36,11 +36,11 @@ "Size" : "大小", "Available" : "可用", "Used" : "已使用", - "You will get a notification once one of your disks is nearly full." : "你將在硬碟使用量快要用完前收到一次通知。", - "Files:" : "檔案:", + "You will get a notification once one of your disks is nearly full." : "你將在其中一個硬碟快滿前收到通知。", + "Files:" : "檔案:", "Storages:" : "儲存設備:", "Free Space:" : "可用空間:", - "Network" : "網路", + "Network" : "網絡", "Hostname" : "主機名稱", "DNS" : "DNS", "Gateway" : "網關", @@ -53,16 +53,18 @@ "Total users:" : "總用戶:", "Shares" : "分享", "PHP" : "PHP", - "Version:" : "版本:", - "Memory Limit:" : "記憶體限制:", + "Version:" : "版本:", + "Memory Limit:" : "記憶體限制:", "Max Execution Time:" : "最長執行時間:", - "Upload max size:" : "上傳至多:", - "Database" : "資料庫", - "Type:" : "類型:", - "Size:" : "大小:", + "Upload max size:" : "上傳至多:", + "Database" : "數據庫", + "Type:" : "類型:", + "Size:" : "大小:", "External monitoring tool" : "外部監控工具", "You can connect an external monitoring tool by using this end point:" : "您可以使用此終端連接外部監視工具:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "在URL後面連接參數 \"?format=json\" 將會得到json格式的回傳結果。", + "To use an access token please generate one then set it using the following command:" : "要使用存取權杖,請生成一個權杖,然後使用以下命令對其進行設置:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "然後在查詢上述 URL 時將權杖與 “ NC-Token” 標頭一起傳遞。", "Time Servers" : "時間伺服器" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/l10n/zh_TW.js b/l10n/zh_TW.js index e52a0f9..3f3866d 100644 --- a/l10n/zh_TW.js +++ b/l10n/zh_TW.js @@ -65,6 +65,8 @@ OC.L10N.register( "External monitoring tool" : "外部監控工具", "You can connect an external monitoring tool by using this end point:" : "您可以使用此終端連接外部監視工具:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "在URL後面連接參數 \"?format=json\" 將會得到json格式的回傳結果。", + "To use an access token please generate one then set it using the following command:" : "要使用存取權杖,請先生成一個,然後使用以下指令來設定:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "然後在查詢上面的 URL 時,將權杖與「NC-Token」標頭一起傳遞。", "Time Servers" : "時間伺服器" }, "nplurals=1; plural=0;"); diff --git a/l10n/zh_TW.json b/l10n/zh_TW.json index a0e1da8..99c648c 100644 --- a/l10n/zh_TW.json +++ b/l10n/zh_TW.json @@ -63,6 +63,8 @@ "External monitoring tool" : "外部監控工具", "You can connect an external monitoring tool by using this end point:" : "您可以使用此終端連接外部監視工具:", "Appending \"?format=json\" at the end of the URL gives you the result in JSON." : "在URL後面連接參數 \"?format=json\" 將會得到json格式的回傳結果。", + "To use an access token please generate one then set it using the following command:" : "要使用存取權杖,請先生成一個,然後使用以下指令來設定:", + "Then pass the token with the \"NC-Token\" header when querying the above URL." : "然後在查詢上面的 URL 時,將權杖與「NC-Token」標頭一起傳遞。", "Time Servers" : "時間伺服器" },"pluralForm" :"nplurals=1; plural=0;" }
\ No newline at end of file diff --git a/lib/Commands/UpdateStorageStats.php b/lib/Commands/UpdateStorageStats.php new file mode 100644 index 0000000..4fe77cc --- /dev/null +++ b/lib/Commands/UpdateStorageStats.php @@ -0,0 +1,60 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\ServerInfo\Commands; + +use OC\Core\Command\Base; +use OCA\ServerInfo\StorageStatistics; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class UpdateStorageStats extends Base { + /** @var StorageStatistics */ + private $storageStatistics; + + public function __construct(StorageStatistics $storageStatistics) { + parent::__construct(); + + $this->storageStatistics = $storageStatistics; + } + + public function configure(): void { + parent::configure(); + $this->setName('serverinfo:update-storage-statistics') + ->setDescription('Triggers an update of the counts related to storages used in serverinfo'); + } + + public function execute(InputInterface $input, OutputInterface $output): int { + if ($output->isVeryVerbose()) { + $this->writeMixedInOutputFormat($input, $output, 'Updating database counts. This might take a while.'); + } + $this->storageStatistics->updateStorageCounts(); + if ($output->isVerbose()) { + $this->writeArrayInOutputFormat($input, $output, $this->storageStatistics->getStorageStatistics()); + } + return 0; + } +} diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index e4d0be9..d9fc6fa 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -28,15 +31,28 @@ use OCA\ServerInfo\SessionStatistics; use OCA\ServerInfo\ShareStatistics; use OCA\ServerInfo\StorageStatistics; use OCA\ServerInfo\SystemStatistics; +use OCP\AppFramework\Http; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; +use OCP\IConfig; +use OCP\IGroupManager; use OCP\IRequest; +use OCP\IUserSession; class ApiController extends OCSController { /** @var Os */ private $os; + /** @var IConfig */ + private $config; + + /** @var IGroupManager */ + private $groupManager; + + /** @var IUserSession */ + private $userSession; + /** @var SystemStatistics */ private $systemStatistics; @@ -60,6 +76,9 @@ class ApiController extends OCSController { * * @param string $appName * @param IRequest $request + * @param IConfig $config + * @param IGroupManager $groupManager + * @param IUserSession $userSession * @param Os $os * @param SystemStatistics $systemStatistics * @param StorageStatistics $storageStatistics @@ -70,6 +89,9 @@ class ApiController extends OCSController { */ public function __construct($appName, IRequest $request, + IConfig $config, + IGroupManager $groupManager, + ?IUserSession $userSession, Os $os, SystemStatistics $systemStatistics, StorageStatistics $storageStatistics, @@ -79,6 +101,9 @@ class ApiController extends OCSController { SessionStatistics $sessionStatistics) { parent::__construct($appName, $request); + $this->config = $config; + $this->groupManager = $groupManager; + $this->userSession = $userSession; $this->os = $os; $this->systemStatistics = $systemStatistics; $this->storageStatistics = $storageStatistics; @@ -89,11 +114,47 @@ class ApiController extends OCSController { } /** + * Check if authorized to view serverinfo API. + * + * @return DataResponse + */ + private function checkAuthorized(): bool { + // check for monitoring privilege + $token = $this->request->getHeader('NC-Token'); + if (!empty($token)) { + $storedToken = $this->config->getAppValue('serverinfo', 'token', null); + if (hash_equals($storedToken, $token)) { + return true; + } + } + + // fallback to admin privilege + $userSession = $this->userSession; + if ($userSession === null) { + return false; + } + + $user = $userSession->getUser(); + if ($user === null) { + return false; + } + + return $this->groupManager->isAdmin($user->getUID()); + } + + /** * @NoCSRFRequired + * @NoAdminRequired + * @PublicPage * * @return DataResponse */ - public function info() { + public function info(): DataResponse { + if (!$this->checkAuthorized()) { + $response = new DataResponse(['message' => 'Unauthorized']); + $response->setStatus(Http::STATUS_UNAUTHORIZED); + return $response; + } return new DataResponse([ 'nextcloud' => [ 'system' => $this->systemStatistics->getSystemStatistics(), @@ -135,7 +196,7 @@ class ApiController extends OCSController { * * @return string */ - private function getWebserver() { + private function getWebserver(): string { if (isset($_SERVER['SERVER_SOFTWARE'])) { return $_SERVER['SERVER_SOFTWARE']; } diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index d85e45b..b4057a5 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -52,7 +55,7 @@ class PageController extends Controller { * * @return JSONResponse */ - public function update() { + public function update(): JSONResponse { $data = [ 'system' => $this->systemStatistics->getSystemStatistics() ]; diff --git a/lib/DatabaseStatistics.php b/lib/DatabaseStatistics.php index a955f7f..1f9f1e8 100644 --- a/lib/DatabaseStatistics.php +++ b/lib/DatabaseStatistics.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -44,9 +47,9 @@ class DatabaseStatistics { } /** - * @return array (string => string|int) + * @return array (string => string) */ - public function getDatabaseStatistics() { + public function getDatabaseStatistics(): array { return [ 'type' => $this->config->getSystemValue('dbtype'), 'version' => $this->databaseVersion(), @@ -54,7 +57,7 @@ class DatabaseStatistics { ]; } - protected function databaseVersion() { + protected function databaseVersion(): string { switch ($this->config->getSystemValue('dbtype')) { case 'sqlite': case 'sqlite3': @@ -88,9 +91,9 @@ class DatabaseStatistics { * @copyright (c) phpBB Limited <https://www.phpbb.com> * @license GNU General Public License, version 2 (GPL-2.0) * - * @return int|string + * @return string */ - protected function databaseSize() { + protected function databaseSize(): string { $database_size = false; // This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0 switch ($this->config->getSystemValue('dbtype')) { @@ -112,7 +115,7 @@ class DatabaseStatistics { if (file_exists($this->config->getSystemValue('dbhost'))) { $database_size = filesize($this->config->getSystemValue('dbhost')); } else { - $params = $this->connection->getParams(); + $params = $this->connection->getInner()->getParams(); if (file_exists($params['path'])) { $database_size = filesize($params['path']); } @@ -152,7 +155,7 @@ class DatabaseStatistics { $result->closeCursor(); break; } - return ($database_size !== false) ? $database_size : 'N/A'; + return ($database_size !== false) ? (string) $database_size : 'N/A'; } /** @@ -161,7 +164,7 @@ class DatabaseStatistics { * @param string $version E.g. `5.6.27-0ubuntu0.14.04.1` * @return string `5.6.27` */ - protected function cleanVersion($version) { + protected function cleanVersion(string $version): string { $matches = []; preg_match('/^(\d+)(\.\d+)(\.\d+)/', $version, $matches); if (isset($matches[0])) { diff --git a/lib/Jobs/UpdateStorageStats.php b/lib/Jobs/UpdateStorageStats.php new file mode 100644 index 0000000..2903518 --- /dev/null +++ b/lib/Jobs/UpdateStorageStats.php @@ -0,0 +1,52 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2020 Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @author Arthur Schiwon <blizzz@arthur-schiwon.de> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\ServerInfo\Jobs; + +use OCA\ServerInfo\StorageStatistics; +use OCP\AppFramework\Utility\ITimeFactory; +use OCP\BackgroundJob\TimedJob; +use OCP\IConfig; + +class UpdateStorageStats extends TimedJob { + + /** @var StorageStatistics */ + private $storageStatistics; + + public function __construct(ITimeFactory $time, StorageStatistics $storageStatistics, IConfig $config) { + $this->setInterval((int)$config->getAppValue('serverinfo', 'job_interval_storage_stats', (string)(60 * 60 * 3))); + parent::__construct($time); + + $this->storageStatistics = $storageStatistics; + } + + /** + * @inheritDoc + */ + protected function run($argument): void { + $this->storageStatistics->updateStorageCounts(); + } +} diff --git a/lib/OperatingSystems/DefaultOs.php b/lib/OperatingSystems/DefaultOs.php index 0465357..9ea272a 100644 --- a/lib/OperatingSystems/DefaultOs.php +++ b/lib/OperatingSystems/DefaultOs.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @author Frank Karlitschek <frank@nextcloud.com> * @@ -107,9 +110,9 @@ class DefaultOs implements IOperatingSystem { /** * @return string */ - public function getTime() { - $uptime = shell_exec('date'); - return $uptime; + public function getTime(): string { + $date = shell_exec('date'); + return $date; } public function getUptime(): int { @@ -127,9 +130,9 @@ class DefaultOs implements IOperatingSystem { } /** - * @return string + * @return array */ - public function getNetworkInfo() { + public function getNetworkInfo(): array { $result = []; $result['hostname'] = \gethostname(); $dns = shell_exec('cat /etc/resolv.conf |grep -i \'^nameserver\'|head -n1|cut -d \' \' -f2'); @@ -140,9 +143,9 @@ class DefaultOs implements IOperatingSystem { } /** - * @return string + * @return array */ - public function getNetworkInterfaces() { + public function getNetworkInterfaces(): array { $interfaces = glob('/sys/class/net/*'); $result = []; @@ -188,7 +191,7 @@ class DefaultOs implements IOperatingSystem { } $matches = []; - $pattern = '/^(?<Filesystem>[\S]+)\s*(?<Type>\w+)\s*(?<Blocks>\d+)\s*(?<Used>\d+)\s*(?<Available>\d+)\s*(?<Capacity>\d+%)\s*(?<Mounted>[\w\/-]+)$/m'; + $pattern = '/^(?<Filesystem>[\S]+)\s*(?<Type>[\S]+)\s*(?<Blocks>\d+)\s*(?<Used>\d+)\s*(?<Available>\d+)\s*(?<Capacity>\d+%)\s*(?<Mounted>[\w\/-]+)$/m'; $result = preg_match_all($pattern, $disks, $matches); if ($result === 0 || $result === false) { @@ -196,7 +199,7 @@ class DefaultOs implements IOperatingSystem { } foreach ($matches['Filesystem'] as $i => $filesystem) { - if (in_array($matches['Type'][$i], ['tmpfs', 'devtmpfs'], false)) { + if (in_array($matches['Type'][$i], ['tmpfs', 'devtmpfs', 'squashfs', 'overlay'], false)) { continue; } diff --git a/lib/OperatingSystems/FreeBSD.php b/lib/OperatingSystems/FreeBSD.php index 9c4b5a2..6ef4cfb 100644 --- a/lib/OperatingSystems/FreeBSD.php +++ b/lib/OperatingSystems/FreeBSD.php @@ -1,6 +1,7 @@ <?php declare(strict_types=1); + /** * @author Matthew Wener <matthew@wener.org> * @@ -97,7 +98,7 @@ class FreeBSD implements IOperatingSystem { /** * @return string */ - public function getTime() { + public function getTime(): string { $time = ''; try { @@ -123,9 +124,9 @@ class FreeBSD implements IOperatingSystem { } /** - * @return string + * @return array */ - public function getNetworkInfo() { + public function getNetworkInfo(): array { $result = []; $result['hostname'] = \gethostname(); @@ -144,9 +145,9 @@ class FreeBSD implements IOperatingSystem { } /** - * @return string + * @return array */ - public function getNetworkInterfaces() { + public function getNetworkInterfaces(): array { $result = []; $ifconfig = $this->executeCommand('/sbin/ifconfig -a'); diff --git a/lib/OperatingSystems/IOperatingSystem.php b/lib/OperatingSystems/IOperatingSystem.php index 5238e96..ed7e386 100644 --- a/lib/OperatingSystems/IOperatingSystem.php +++ b/lib/OperatingSystems/IOperatingSystem.php @@ -1,6 +1,7 @@ <?php declare(strict_types=1); + /** * @copyright Copyright (c) 2020 Daniel Kesselberg <mail@danielkesselberg.de> * @@ -29,8 +30,10 @@ use OCA\ServerInfo\Resources\Disk; use OCA\ServerInfo\Resources\Memory; interface IOperatingSystem { + public function supported(): bool; + /** - * Get name of the processor + * Get name of the processor. * * @return string */ @@ -51,6 +54,45 @@ interface IOperatingSystem { public function getMemory(): Memory; /** + * Get info about network connection. + * + * [ + * 'dns' => string, + * 'gateway' => string, + * 'hostname' => string, + * ] + * + * @return array + */ + public function getNetworkInfo(): array; + + /** + * Get info about available network interfaces. + * + * [ + * [ + * 'duplex' => string, + * 'interface' => string, + * 'ipv4' => string, + * 'ipv6' => string, + * 'mac' => string, + * 'speed' => string, + * 'status' => string, + * ], + * ] + * + * @return array + */ + public function getNetworkInterfaces(): array; + + /** + * Get system time and timezone. + * + * @return Memory + */ + public function getTime(): string; + + /** * Get the total number of seconds the system has been up or -1 on failure. * * @return int @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @author Frank Karlitschek <frank@nextcloud.com> * @@ -27,7 +30,7 @@ use OCA\ServerInfo\Resources\Memory; class Os implements IOperatingSystem { - /** @var */ + /** @var IOperatingSystem */ protected $backend; /** @@ -44,7 +47,7 @@ class Os implements IOperatingSystem { /** * @return bool */ - public function supported() { + public function supported(): bool { $data = $this->backend->supported(); return $data; } @@ -52,21 +55,29 @@ class Os implements IOperatingSystem { /** * @return string */ - public function getHostname() { + public function getHostname(): string { return (string)gethostname(); } /** + * Get name of the operating system. + * * @return string */ public function getOSName(): string { return PHP_OS . ' ' . php_uname('r') . ' ' . php_uname('m'); } + /** + * @return Memory + */ public function getMemory(): Memory { return $this->backend->getMemory(); } + /** + * @return string + */ public function getCpuName(): string { return $this->backend->getCpuName(); } @@ -74,15 +85,21 @@ class Os implements IOperatingSystem { /** * @return string */ - public function getTime() { + public function getTime(): string { $data = $this->backend->getTime(); return $data; } + /** + * @return string + */ public function getUptime(): int { return $this->backend->getUptime(); } + /** + * @return array + */ public function getDiskInfo(): array { return $this->backend->getDiskInfo(); } @@ -110,17 +127,17 @@ class Os implements IOperatingSystem { } /** - * @return string + * @return array */ - public function getNetworkInfo() { + public function getNetworkInfo(): array { $data = $this->backend->getNetworkInfo(); return $data; } /** - * @return string + * @return array */ - public function getNetworkInterfaces() { + public function getNetworkInterfaces(): array { $data = $this->backend->getNetworkInterfaces(); return $data; } diff --git a/lib/PhpStatistics.php b/lib/PhpStatistics.php index b794a91..a4c5d8d 100644 --- a/lib/PhpStatistics.php +++ b/lib/PhpStatistics.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -41,7 +44,7 @@ class PhpStatistics { $this->phpIni = $phpIni; } - public function getPhpStatistics() { + public function getPhpStatistics(): array { return [ 'version' => PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION, 'memory_limit' => $this->phpIni->getBytes('memory_limit'), diff --git a/lib/SessionStatistics.php b/lib/SessionStatistics.php index 05ea1fe..02194ff 100644 --- a/lib/SessionStatistics.php +++ b/lib/SessionStatistics.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -34,6 +37,9 @@ use OCP\IDBConnection; * @package OCA\ServerInfo */ class SessionStatistics { + private const OFFSET_5MIN = 300; + private const OFFSET_1HOUR = 3600; + private const OFFSET_1DAY = 86400; /** @var IDBConnection */ private $connection; @@ -41,12 +47,6 @@ class SessionStatistics { /** @var ITimeFactory */ private $timeFactory; - private $offset5Minutes = 300; - - private $offset1Hour = 3600; - - private $offset1Day = 86400; - /** * SessionStatistics constructor. * @@ -58,12 +58,11 @@ class SessionStatistics { $this->timeFactory = $timeFactory; } - - public function getSessionStatistics() { + public function getSessionStatistics(): array { return [ - 'last5minutes' => $this->getNumberOfActiveUsers($this->offset5Minutes), - 'last1hour' => $this->getNumberOfActiveUsers($this->offset1Hour), - 'last24hours' => $this->getNumberOfActiveUsers($this->offset1Day) + 'last5minutes' => $this->getNumberOfActiveUsers(self::OFFSET_5MIN), + 'last1hour' => $this->getNumberOfActiveUsers(self::OFFSET_1HOUR), + 'last24hours' => $this->getNumberOfActiveUsers(self::OFFSET_1DAY), ]; } @@ -73,7 +72,7 @@ class SessionStatistics { * @param int $offset seconds * @return int */ - private function getNumberOfActiveUsers($offset) { + private function getNumberOfActiveUsers(int $offset): int { $query = $this->connection->getQueryBuilder(); $query->select('uid') ->from('authtoken') diff --git a/lib/Settings/AdminSection.php b/lib/Settings/AdminSection.php index ab6ac20..8584a22 100644 --- a/lib/Settings/AdminSection.php +++ b/lib/Settings/AdminSection.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -43,7 +46,7 @@ class AdminSection implements IIconSection { * * @returns string */ - public function getID() { + public function getID(): string { return 'serverinfo'; } @@ -53,7 +56,7 @@ class AdminSection implements IIconSection { * * @return string */ - public function getName() { + public function getName(): string { return $this->l->t('System'); } @@ -64,14 +67,14 @@ class AdminSection implements IIconSection { * * keep the server setting at the top, right after "overview" and "basic settings" */ - public function getPriority() { + public function getPriority(): int { return 90; } /** * {@inheritdoc} */ - public function getIcon() { + public function getIcon(): string { return $this->url->imagePath('serverinfo', 'app-dark.svg'); } } diff --git a/lib/Settings/AdminSettings.php b/lib/Settings/AdminSettings.php index bde6270..ce95619 100644 --- a/lib/Settings/AdminSettings.php +++ b/lib/Settings/AdminSettings.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -99,7 +102,7 @@ class AdminSettings implements ISettings { /** * @return TemplateResponse */ - public function getForm() { + public function getForm(): TemplateResponse { $monitoringEndPoint = $this->urlGenerator->getAbsoluteURL('ocs/v2.php/apps/serverinfo/api/v1/info'); $params = [ 'hostname' => $this->os->getHostname(), @@ -124,7 +127,7 @@ class AdminSettings implements ISettings { /** * @return string the section ID, e.g. 'sharing' */ - public function getSection() { + public function getSection(): string { return 'serverinfo'; } @@ -135,7 +138,7 @@ class AdminSettings implements ISettings { * * keep the server setting at the top, right after "server settings" */ - public function getPriority() { + public function getPriority(): int { return 0; } } diff --git a/lib/ShareStatistics.php b/lib/ShareStatistics.php index c1be78b..b885efc 100644 --- a/lib/ShareStatistics.php +++ b/lib/ShareStatistics.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -45,7 +48,7 @@ class ShareStatistics { /** * @return array (string => string|int) */ - public function getShareStatistics() { + public function getShareStatistics(): array { $query = $this->connection->getQueryBuilder(); $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') ->addSelect(['permissions', 'share_type']) @@ -77,7 +80,7 @@ class ShareStatistics { * @param string $tableName * @return int */ - protected function countEntries($tableName) { + protected function countEntries(string $tableName): int { $query = $this->connection->getQueryBuilder(); $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') ->from($tableName); @@ -93,7 +96,7 @@ class ShareStatistics { * @param bool $noPassword * @return int */ - protected function countShares($type, $noPassword = false) { + protected function countShares(int $type, bool $noPassword = false): int { $query = $this->connection->getQueryBuilder(); $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') ->from('share') diff --git a/lib/StorageStatistics.php b/lib/StorageStatistics.php index ce5586b..02aa673 100644 --- a/lib/StorageStatistics.php +++ b/lib/StorageStatistics.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -22,27 +25,34 @@ namespace OCA\ServerInfo; +use OCP\IConfig; use OCP\IDBConnection; class StorageStatistics { - /** @var IDBConnection */ + /** @var IDBConnection */ private $connection; + /** @var IConfig */ + private $config; /** * SystemStatistics constructor. * * @param IDBConnection $connection */ - public function __construct(IDBConnection $connection) { + public function __construct(IDBConnection $connection, IConfig $config) { $this->connection = $connection; + $this->config = $config; } - public function getStorageStatistics() { + /** + * @return array + */ + public function getStorageStatistics(): array { return [ 'num_users' => $this->countUserEntries(), - 'num_files' => $this->countEntries('filecache'), - 'num_storages' => $this->countEntries('storages'), + 'num_files' => $this->getCountOf('filecache'), + 'num_storages' => $this->getCountOf('storages'), 'num_storages_local' => $this->countStorages('local'), 'num_storages_home' => $this->countStorages('home'), 'num_storages_other' => $this->countStorages('other'), @@ -54,7 +64,7 @@ class StorageStatistics { * * @return int */ - protected function countUserEntries() { + protected function countUserEntries(): int { $query = $this->connection->getQueryBuilder(); $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') ->from('preferences') @@ -65,25 +75,41 @@ class StorageStatistics { return (int) $row['num_entries']; } - /** - * @param string $tableName - * @return int - */ - protected function countEntries($tableName) { - $query = $this->connection->getQueryBuilder(); - $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') - ->from($tableName); - $result = $query->execute(); - $row = $result->fetch(); - $result->closeCursor(); - return (int) $row['num_entries']; + protected function getCountOf(string $table): int { + return (int)$this->config->getAppValue('serverinfo', 'cached_count_' . $table, '0'); + } + + public function updateStorageCounts(): void { + $storageCount = 0; + $fileCount = 0; + + $fileQuery = $this->connection->getQueryBuilder(); + $fileQuery->select($fileQuery->func()->count()) + ->from('filecache') + ->where($fileQuery->expr()->eq('storage', $fileQuery->createParameter('storageId'))); + + $storageQuery = $this->connection->getQueryBuilder(); + $storageQuery->selectAlias('numeric_id', 'id') + ->from('storages'); + $storageResult = $storageQuery->execute(); + while ($storageRow = $storageResult->fetch()) { + $storageCount++; + $fileQuery->setParameter('storageId', $storageRow['id']); + $fileResult = $fileQuery->execute(); + $fileCount += (int)$fileResult->fetchOne(); + $fileResult->closeCursor(); + } + $storageResult->closeCursor(); + + $this->config->setAppValue('serverinfo', 'cached_count_filecache' , (string)$fileCount); + $this->config->setAppValue('serverinfo', 'cached_count_storages', (string)$storageCount); } /** * @param string $type * @return int */ - protected function countStorages($type) { + protected function countStorages(string $type): int { $query = $this->connection->getQueryBuilder(); $query->selectAlias($query->createFunction('COUNT(*)'), 'num_entries') ->from('storages'); diff --git a/lib/SystemStatistics.php b/lib/SystemStatistics.php index f3ce072..c1b8448 100644 --- a/lib/SystemStatistics.php +++ b/lib/SystemStatistics.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -24,6 +27,7 @@ namespace OCA\ServerInfo; use OC\Files\View; use OC\Installer; +use OCP\Files\FileInfo; use OCP\IConfig; use OCP\App\IAppManager; use bantu\IniGetWrapper\IniGetWrapper; @@ -64,7 +68,7 @@ class SystemStatistics { * @return array with with of data * @throws \OCP\Files\InvalidPathException */ - public function getSystemStatistics() { + public function getSystemStatistics(): array { $processorUsage = $this->getProcessorUsage(); $memoryUsage = $this->getMemoryUsage(); return [ @@ -77,7 +81,7 @@ class SystemStatistics { 'filelocking.enabled' => $this->config->getSystemValue('filelocking.enabled', true) ? 'yes' : 'no', 'memcache.locking' => $this->config->getSystemValue('memcache.locking', 'none'), 'debug' => $this->config->getSystemValue('debug', false) ? 'yes' : 'no', - 'freespace' => $this->view->free_space(), + 'freespace' => $this->getFreeSpace(), 'cpuload' => $processorUsage['loadavg'], 'mem_total' => $memoryUsage['mem_total'], 'mem_free' => $memoryUsage['mem_free'], @@ -92,7 +96,7 @@ class SystemStatistics { * * @return array with the two values 'mem_free' and 'mem_total' */ - protected function getMemoryUsage() { + protected function getMemoryUsage(): array { $memoryUsage = false; if (@is_readable('/proc/meminfo')) { // read meminfo from OS @@ -158,7 +162,7 @@ class SystemStatistics { * * @return array data about apps */ - protected function getAppsInfo() { + protected function getAppsInfo(): array { // sekeleton about the data we return back $info = [ @@ -192,7 +196,7 @@ class SystemStatistics { * @param string $function_name * @return bool */ - public function is_function_enabled($function_name) { + public function is_function_enabled(string $function_name): bool { if (!function_exists($function_name)) { return false; } @@ -207,7 +211,7 @@ class SystemStatistics { * * @return array load average with three values, 1/5/15 minutes average. */ - protected function getProcessorUsage() { + protected function getProcessorUsage(): array { // get current system load average. $loadavg = sys_getloadavg(); @@ -222,4 +226,20 @@ class SystemStatistics { 'loadavg' => $loadavg ]; } + + /** + * Get free space if it can be calculated. + * + * @return mixed free space or null + * @throws \OCP\Files\InvalidPathException + */ + protected function getFreeSpace() { + $free_space = $this->view->free_space(); + if ($free_space === FileInfo::SPACE_UNKNOWN + || $free_space === FileInfo::SPACE_UNLIMITED + || $free_space === FileInfo::SPACE_NOT_COMPUTED) { + return null; + } + return $free_space; + } } diff --git a/templates/settings-admin.php b/templates/settings-admin.php index 6eeefdd..2067866 100644 --- a/templates/settings-admin.php +++ b/templates/settings-admin.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * @@ -25,7 +28,7 @@ script('serverinfo', 'Chart.min'); style('serverinfo', 'style'); -function FormatMegabytes($byte) { +function FormatMegabytes(int $byte): string { $unim = ['MB', 'GB', 'TB', 'PB']; $count = 0; while ($byte >= 1024) { @@ -151,8 +154,9 @@ $disks = $_['diskinfo']; <p><?php p($l->t('Files:')); ?> <strong id="numFilesStorage"><?php p($_['storage']['num_files']); ?></strong></p> <p><?php p($l->t('Storages:')); ?> <strong id="numFilesStorages"><?php p($_['storage']['num_storages']); ?></strong></p> - <p><?php p($l->t('Free Space:')); ?> <strong id="systemDiskFreeSpace"><?php p($_['system']['freespace']); ?></strong> - </p> + <?php if ($_['system']['freespace'] !== null): ?> + <p><?php p($l->t('Free Space:')); ?> <strong id="systemDiskFreeSpace"><?php p($_['system']['freespace']); ?></strong></p> + <?php endif; ?> </div> <!-- NETWORK --> @@ -333,6 +337,13 @@ $disks = $_['diskinfo']; <p class="settings-hint"> <?php p($l->t('Appending "?format=json" at the end of the URL gives you the result in JSON.')); ?> </p> + <p> + <?php p($l->t('To use an access token please generate one then set it using the following command:')); ?> + <div><i>occ config:app:set serverinfo token --value yourtoken</i></div> + </p> + <p> + <?php p($l->t('Then pass the token with the "NC-Token" header when querying the above URL.')); ?> + </p> </div> </div> </div> diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 6509885..28a1987 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,5 +1,7 @@ <?php +declare(strict_types=1); + if (!defined('PHPUNIT_RUN')) { define('PHPUNIT_RUN', 1); } diff --git a/tests/data/df_tp b/tests/data/df_tp index 4d9cbb3..c330e56 100644 --- a/tests/data/df_tp +++ b/tests/data/df_tp @@ -10,3 +10,4 @@ vagrant vboxsf 958123168 614831132 343292036 home_vagrant_code vboxsf 958123168 614831132 343292036 65% /home/vagrant/code tmpfs tmpfs 816800 0 816800 0% /run/user/1000 nfs.example.com:/export nfs4 14820 0 1230 0% /nfs +198.51.100.42:/storage fuse.sshfs 47929956 53116 45419052 1% /mnt/sshfs diff --git a/tests/lib/ApiControllerTest.php b/tests/lib/ApiControllerTest.php new file mode 100644 index 0000000..d675b9b --- /dev/null +++ b/tests/lib/ApiControllerTest.php @@ -0,0 +1,246 @@ +<?php + +declare(strict_types=1); + +/** + * @copyright Copyright (c) 2021 Vincent Petry <vincent@nextcloud.com> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +namespace OCA\ServerInfo\Tests; + +use OCA\ServerInfo\Controller\ApiController; +use OCA\ServerInfo\DatabaseStatistics; +use OCA\ServerInfo\Os; +use OCA\ServerInfo\PhpStatistics; +use OCA\ServerInfo\SessionStatistics; +use OCA\ServerInfo\ShareStatistics; +use OCA\ServerInfo\StorageStatistics; +use OCA\ServerInfo\SystemStatistics; +use OCP\AppFramework\Http; +use OCP\IConfig; +use OCP\IGroupManager; +use OCP\IRequest; +use OCP\IUser; +use OCP\IUserSession; + +class ApiControllerTest extends \Test\TestCase { + /** @var Os|\PHPUnit\Framework\MockObject\MockObject */ + private $os; + + /** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */ + private $request; + + /** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */ + private $config; + + /** @var IGroupManager|\PHPUnit\Framework\MockObject\MockObject */ + private $groupManager; + + /** @var SystemStatistics|\PHPUnit\Framework\MockObject\MockObject */ + private $systemStatistics; + + /** @var StorageStatistics|\PHPUnit\Framework\MockObject\MockObject */ + private $storageStatistics; + + /** @var PhpStatistics|\PHPUnit\Framework\MockObject\MockObject */ + private $phpStatistics; + + /** @var DatabaseStatistics|\PHPUnit\Framework\MockObject\MockObject */ + private $databaseStatistics; + + /** @var ShareStatistics|\PHPUnit\Framework\MockObject\MockObject */ + private $shareStatistics; + + /** @var SessionStatistics|\PHPUnit\Framework\MockObject\MockObject */ + private $sessionStatistics; + + protected function setUp(): void { + parent::setUp(); + + $this->request = $this->createMock(IRequest::class); + $this->config = $this->createMock(IConfig::class); + $this->groupManager = $this->createMock(IGroupManager::class); + $this->os = $this->createMock(Os::class); + $this->systemStatistics = $this->createMock(SystemStatistics::class); + $this->storageStatistics = $this->createMock(StorageStatistics::class); + $this->phpStatistics = $this->createMock(PhpStatistics::class); + $this->databaseStatistics = $this->createMock(DatabaseStatistics::class); + $this->shareStatistics = $this->createMock(ShareStatistics::class); + $this->sessionStatistics = $this->createMock(SessionStatistics::class); + } + + private function getController($userSession) { + return new ApiController( + 'serverinfo', + $this->request, + $this->config, + $this->groupManager, + $userSession, + $this->os, + $this->systemStatistics, + $this->storageStatistics, + $this->phpStatistics, + $this->databaseStatistics, + $this->shareStatistics, + $this->sessionStatistics + ); + } + + public function testAuthFailureNoSession() { + $response = $this->getController(null)->info(); + + $this->assertEquals(['message' => 'Unauthorized'], $response->getData()); + $this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus()); + } + + public function testAuthFailureNoUser() { + $userSession = $this->createMock(IUserSession::class); + $userSession->method('getUser')->willReturn(null); + + $response = $this->getController($userSession)->info(); + + $this->assertEquals(['message' => 'Unauthorized'], $response->getData()); + $this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus()); + } + + public function testAuthFailureNoAdmin() { + $userSession = $this->createMock(IUserSession::class); + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('nonadmin'); + $userSession->method('getUser')->willReturn($user); + $this->groupManager->expects($this->once()) + ->method('isAdmin') + ->with('nonadmin') + ->willReturn(false); + + $response = $this->getController($userSession)->info(); + + $this->assertEquals(['message' => 'Unauthorized'], $response->getData()); + $this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus()); + } + + public function testAuthSuccessWithAdmin() { + $userSession = $this->createMock(IUserSession::class); + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('admin'); + $userSession->method('getUser')->willReturn($user); + $this->groupManager->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->willReturn(true); + + $response = $this->getController($userSession)->info(); + + $this->assertEquals(Http::STATUS_OK, $response->getStatus()); + } + + public function testAuthFailureWithToken() { + $this->request->expects($this->once()) + ->method('getHeader') + ->with('NC-Token') + ->willReturn('invalidtoken'); + + $this->config->expects($this->once()) + ->method('getAppValue') + ->with('serverinfo', 'token', null) + ->willReturn('megatoken'); + $response = $this->getController(null)->info(); + + $this->assertEquals(['message' => 'Unauthorized'], $response->getData()); + $this->assertEquals(Http::STATUS_UNAUTHORIZED, $response->getStatus()); + } + + public function testAuthSuccessWithToken() { + $this->request->expects($this->once()) + ->method('getHeader') + ->with('NC-Token') + ->willReturn('megatoken'); + + $this->config->expects($this->once()) + ->method('getAppValue') + ->with('serverinfo', 'token', null) + ->willReturn('megatoken'); + $response = $this->getController(null)->info(); + + $this->assertEquals(Http::STATUS_OK, $response->getStatus()); + } + + public function testIn() { + $this->request->expects($this->once()) + ->method('getHeader') + ->with('NC-Token') + ->willReturn('megatoken'); + + $this->config->expects($this->once()) + ->method('getAppValue') + ->with('serverinfo', 'token', null) + ->willReturn('megatoken'); + $response = $this->getController(null)->info(); + + $this->assertEquals(Http::STATUS_OK, $response->getStatus()); + } + + public function testInfo() { + $userSession = $this->createMock(IUserSession::class); + $user = $this->createMock(IUser::class); + $user->method('getUID')->willReturn('admin'); + $userSession->method('getUser')->willReturn($user); + $this->groupManager->expects($this->once()) + ->method('isAdmin') + ->with('admin') + ->willReturn(true); + + $this->systemStatistics->expects($this->once()) + ->method('getSystemStatistics') + ->willReturn(['some_system' => 'some_value']); + $this->storageStatistics->expects($this->once()) + ->method('getStorageStatistics') + ->willReturn(['some_storage' => 'some_value']); + $this->shareStatistics->expects($this->once()) + ->method('getShareStatistics') + ->willReturn(['some_shares' => 'some_value']); + $this->phpStatistics->expects($this->once()) + ->method('getPhpStatistics') + ->willReturn(['some_php' => 'some_value']); + $this->databaseStatistics->expects($this->once()) + ->method('getDatabaseStatistics') + ->willReturn(['some_database' => 'some_value']); + $this->sessionStatistics->expects($this->once()) + ->method('getSessionStatistics') + ->willReturn(['some_user' => 'some_value']); + + $response = $this->getController($userSession)->info(); + + $this->assertEquals(Http::STATUS_OK, $response->getStatus()); + + $this->assertEquals([ + 'nextcloud' => [ + 'system' => ['some_system' => 'some_value'], + 'storage' => ['some_storage' => 'some_value'], + 'shares' => ['some_shares' => 'some_value'], + ], + 'server' => [ + 'webserver' => 'unknown', + 'php' => ['some_php' => 'some_value'], + 'database' => ['some_database' => 'some_value'], + ], + 'activeUsers' => ['some_user' => 'some_value'], + ], $response->getData()); + } +} diff --git a/tests/lib/DefaultOsTest.php b/tests/lib/DefaultOsTest.php index 1fb58d3..6ceee7d 100644 --- a/tests/lib/DefaultOsTest.php +++ b/tests/lib/DefaultOsTest.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2020 Daniel Kesselberg <mail@danielkesselberg.de> * @@ -174,7 +177,15 @@ class DefaultOsTest extends TestCase { $disk5->setPercent('0%'); $disk5->setMount('/nfs'); - $this->assertEquals([$disk1, $disk2, $disk3, $disk4, $disk5], $this->os->getDiskInfo()); + $disk6 = new Disk(); + $disk6->setDevice('198.51.100.42:/storage'); + $disk6->setFs('fuse.sshfs'); + $disk6->setUsed(51); + $disk6->setAvailable(44354); + $disk6->setPercent('1%'); + $disk6->setMount('/mnt/sshfs'); + + $this->assertEquals([$disk1, $disk2, $disk3, $disk4, $disk5, $disk6], $this->os->getDiskInfo()); } public function testGetDiskInfoNoCommandOutput(): void { diff --git a/tests/lib/FreeBSDTest.php b/tests/lib/FreeBSDTest.php index 671540a..d986972 100644 --- a/tests/lib/FreeBSDTest.php +++ b/tests/lib/FreeBSDTest.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2020 Daniel Kesselberg <mail@danielkesselberg.de> * diff --git a/tests/lib/SessionStatisticsTest.php b/tests/lib/SessionStatisticsTest.php index 96b6beb..8daa06a 100644 --- a/tests/lib/SessionStatisticsTest.php +++ b/tests/lib/SessionStatisticsTest.php @@ -1,4 +1,7 @@ <?php + +declare(strict_types=1); + /** * @copyright Copyright (c) 2016 Bjoern Schiessle <bjoern@schiessle.org> * |