Add shares export script, better notification for shares and moderate refactor

master
Florian Charlaix 9 months ago
parent 5a41c9b365
commit 164a5b6168
  1. 2
      l10n/fr.js
  2. 2
      l10n/fr.json
  3. 35
      lib/Exceptions/TooManyUserEmail.php
  4. 2
      lib/Migration/Notifier.php
  5. 3
      lib/Migration/Utils.php
  6. 149
      scripts/shares_export.py

@ -18,6 +18,6 @@ OC.L10N.register(
"Shares migration scheduled": "Migration des partages planifiée",
"Shares migration started": "Vos partages seront bientôt disponibles",
"Shares migration complete": "Migration des partages terminée",
"%s shares migrated, waiting for %s users, %s missing files, %s errors": "%s partages migrés, attente de %s utilisateurs, %s fichiers manquants, %s erreurs"
"%s shares migrated, %s shares waiting for users, %s missing files, %s errors": "%s partages migrés, %s partages en attente d'utilisateurs, %s fichiers manquants, %s erreurs"
},
"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;");

@ -16,6 +16,6 @@
"Shares migration scheduled": "Migration des partages planifiée",
"Shares migration started": "Vos partages seront bientôt disponibles",
"Shares migration complete": "Migration des partages terminée",
"%s shares migrated, waiting for %s users, %s missing files, %s errors": "%s partages migrés, attente de %s utilisateurs, %s fichiers manquants, %s erreurs"
"%s shares migrated, %s shares waiting for users, %s missing files, %s errors": "%s partages migrés, %s partages en attente d'utilisateurs, %s fichiers manquants, %s erreurs"
},"pluralForm" :"nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;"
}

@ -0,0 +1,35 @@
<?php
/**
* @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.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\FirstRunMigrate\Exceptions;
class TooManyUserEmail extends \Exception {
protected string $email;
public function __construct(string $email) {
parent::__construct("Multiples users with the same email: '$email'");
$this->email = $email;
}
public function getEmail() : string {
return $this->email;
}
}

@ -128,7 +128,7 @@ class Notifier implements INotifier {
break;
case 'share_finished':
$subject = $l->t('Shares migration complete');
$message = $l->t('%s shares migrated, waiting for %s users, %s missing files, %s errors',
$message = $l->t('%s shares migrated, %s shares waiting for users, %s missing files, %s errors',
$notify_parameters);
break;
default:

@ -6,6 +6,7 @@ use Exception;
use OCP\IConfig;
use OCP\IUser;
use OCA\FirstRunMigrate\AppInfo\Application;
use OCA\FirstRunMigrate\Exceptions\TooManyUserEmail;
use OCP\IUserManager;
use OCP\Notification\IManager as INotificationManager;
@ -60,7 +61,7 @@ class Utils {
}
if (count($users) > 1) {
throw new \Exception("Multiples users with the same email");
throw new TooManyUserEmail($id);
}
return $users[0];

@ -0,0 +1,149 @@
from json import loads, dump
from subprocess import run, PIPE
from argparse import ArgumentParser
from pathlib import Path
def main(path : str, php :str, output_shares_path : str):
output_shares = Path(output_shares_path)
out = run([php, "occ", "config:list", "--private", "--output", "json"], cwd=path, check=True,
stdout=PIPE, stderr=PIPE)
config = loads(out.stdout.decode().strip())
db_type = config["system"]["dbtype"]
db_socket = None
db_host, db_port = config["system"]["dbhost"].split(":")
if db_port and not db_port.isdigit():
db_socket = db_port
db_port = None
elif not db_port:
db_port = config["system"]["dbport"]
db_user = config["system"]["dbuser"]
db_password = config["system"]["dbpassword"]
db_name = config["system"]["dbname"]
db_prefix = config["system"]["dbtableprefix"]
shares = []
if db_type == "mysql":
query = f"""SELECT
JSON_ARRAYAGG(
JSON_OBJECT(
'type', s.share_type,
'permissions', s.permissions,
'by', p_initiator.configvalue,
'owner', p_owner.configvalue,
'path', REGEXP_REPLACE(fc.path, '^files/', ''),
'target', s.file_target,
'with', CASE
WHEN s.share_type = 0
THEN p_with.configvalue
WHEN s.share_type = 1
THEN s.share_with
ELSE null
END,
'attributes', s.attributes,
'expiration', s.expiration,
'note', s.note,
'accepted', s.accepted,
'group_users_accepted', CASE
WHEN s.share_type = 1
THEN (
SELECT
JSON_OBJECTAGG(
ss_with.configvalue,
JSON_OBJECT(
'accepted', ss.accepted,
'target', ss.file_target
)
)
FROM {db_prefix}share ss
INNER JOIN {db_prefix}preferences ss_with ON ss_with.userid = ss.share_with AND ss_with.appid = 'settings' AND ss_with.configkey = 'email'
WHERE ss.parent = s.id
)
ELSE null
END
)
)
FROM {db_prefix}share s
INNER JOIN {db_prefix}preferences p_initiator ON p_initiator.userid = s.uid_initiator AND p_initiator.appid = 'settings' AND p_initiator.configkey = 'email'
INNER JOIN {db_prefix}preferences p_owner ON p_owner.userid = s.uid_owner AND p_owner.appid = 'settings' AND p_owner.configkey = 'email'
INNER JOIN {db_prefix}filecache fc ON fc.fileid = file_source
LEFT JOIN {db_prefix}preferences p_with ON p_with.userid = s.share_with AND p_with.appid = 'settings' AND p_with.configkey = 'email'
WHERE s.share_type IN (0, 1);
"""
args = ["mysql", "-B", "-r", "--disable-column-names", "-h", db_host]
if db_port:
args += ["-P", db_port]
elif db_socket:
args += ["-S", db_socket]
args += ["-u", db_user, f"-p{db_password}", "-e", query, db_name]
out = run(args, cwd=path, check=True, stdout=PIPE, text=True)
shares = loads(out.stdout)
elif db_type == "psql":
query = f"""SELECT
jsonb_agg(
jsonb_build_object(
'type', s.share_type,
'permissions', s.permissions,
'by', p_initiator.configvalue,
'owner', p_owner.configvalue,
'path', regexp_replace(fc.path, '^files/', ''),
'target', s.file_target,
'with', CASE
WHEN s.share_type = 0
THEN p_with.configvalue
WHEN s.share_type = 1
THEN s.share_with
ELSE null
END,
'attributes', s.attributes,
'expiration', s.expiration,
'note', s.note,
'accepted', s.accepted,
'group_users_accepted', CASE
WHEN s.share_type = 1
THEN (
SELECT
JSONB_OBJECT_AGG(
ss_with.configvalue,
jsonb_build_object(
'accepted', ss.accepted,
'target', ss.file_target
)
)
FROM {db_prefix}share ss
INNER JOIN {db_prefix}preferences ss_with ON ss_with.userid = ss.share_with AND ss_with.appid = 'settings' AND ss_with.configkey = 'email'
WHERE ss.parent = s.id
)
ELSE null
END
)
)
FROM {db_prefix}share s
INNER JOIN {db_prefix}preferences p_initiator ON p_initiator.userid = s.uid_initiator AND p_initiator.appid = 'settings' AND p_initiator.configkey = 'email'
INNER JOIN {db_prefix}preferences p_owner ON p_owner.userid = s.uid_owner AND p_owner.appid = 'settings' AND p_owner.configkey = 'email'
INNER JOIN {db_prefix}filecache fc ON fc.fileid = file_source
LEFT JOIN {db_prefix}preferences p_with ON p_with.userid = s.share_with AND p_with.appid = 'settings' AND p_with.configkey = 'email'
WHERE s.share_type IN (0, 1);
"""
pass
elif db_type == "sqlite":
pass
print(f"Got {len(shares)} shares")
with output_shares.open("w", encoding="UTF-8") as file:
dump(shares, file)
if __name__ == '__main__':
parser = ArgumentParser(prog="shares_export")
parser.add_argument("--path", "-p", default="/var/www/nextcloud")
parser.add_argument("--php", "-P", default="php")
parser.add_argument("--output-shares", "-s", default="shares.json")
args = parser.parse_args()
main(args.path, args.php, args.output_shares)
Loading…
Cancel
Save