@@ -33,55 +33,55 @@ |
||
33 | 33 | use OCP\Migration\SimpleMigrationStep; |
34 | 34 | |
35 | 35 | class Version1010Date20200630192639 extends SimpleMigrationStep { |
36 | - /** |
|
37 | - * @param IOutput $output |
|
38 | - * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` |
|
39 | - * @param array $options |
|
40 | - * @return null|ISchemaWrapper |
|
41 | - */ |
|
42 | - public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { |
|
43 | - /** @var ISchemaWrapper $schema */ |
|
44 | - $schema = $schemaClosure(); |
|
36 | + /** |
|
37 | + * @param IOutput $output |
|
38 | + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` |
|
39 | + * @param array $options |
|
40 | + * @return null|ISchemaWrapper |
|
41 | + */ |
|
42 | + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) { |
|
43 | + /** @var ISchemaWrapper $schema */ |
|
44 | + $schema = $schemaClosure(); |
|
45 | 45 | |
46 | - if (!$schema->hasTable('files_trash')) { |
|
47 | - $table = $schema->createTable('files_trash'); |
|
48 | - $table->addColumn('auto_id', Types::BIGINT, [ |
|
49 | - 'autoincrement' => true, |
|
50 | - 'notnull' => true, |
|
51 | - ]); |
|
52 | - $table->addColumn('id', Types::STRING, [ |
|
53 | - 'notnull' => true, |
|
54 | - 'length' => 250, |
|
55 | - 'default' => '', |
|
56 | - ]); |
|
57 | - $table->addColumn('user', Types::STRING, [ |
|
58 | - 'notnull' => true, |
|
59 | - 'length' => 64, |
|
60 | - 'default' => '', |
|
61 | - ]); |
|
62 | - $table->addColumn('timestamp', Types::STRING, [ |
|
63 | - 'notnull' => true, |
|
64 | - 'length' => 12, |
|
65 | - 'default' => '', |
|
66 | - ]); |
|
67 | - $table->addColumn('location', Types::STRING, [ |
|
68 | - 'notnull' => true, |
|
69 | - 'length' => 512, |
|
70 | - 'default' => '', |
|
71 | - ]); |
|
72 | - $table->addColumn('type', Types::STRING, [ |
|
73 | - 'notnull' => false, |
|
74 | - 'length' => 4, |
|
75 | - ]); |
|
76 | - $table->addColumn('mime', Types::STRING, [ |
|
77 | - 'notnull' => false, |
|
78 | - 'length' => 255, |
|
79 | - ]); |
|
80 | - $table->setPrimaryKey(['auto_id']); |
|
81 | - $table->addIndex(['id'], 'id_index'); |
|
82 | - $table->addIndex(['timestamp'], 'timestamp_index'); |
|
83 | - $table->addIndex(['user'], 'user_index'); |
|
84 | - } |
|
85 | - return $schema; |
|
86 | - } |
|
46 | + if (!$schema->hasTable('files_trash')) { |
|
47 | + $table = $schema->createTable('files_trash'); |
|
48 | + $table->addColumn('auto_id', Types::BIGINT, [ |
|
49 | + 'autoincrement' => true, |
|
50 | + 'notnull' => true, |
|
51 | + ]); |
|
52 | + $table->addColumn('id', Types::STRING, [ |
|
53 | + 'notnull' => true, |
|
54 | + 'length' => 250, |
|
55 | + 'default' => '', |
|
56 | + ]); |
|
57 | + $table->addColumn('user', Types::STRING, [ |
|
58 | + 'notnull' => true, |
|
59 | + 'length' => 64, |
|
60 | + 'default' => '', |
|
61 | + ]); |
|
62 | + $table->addColumn('timestamp', Types::STRING, [ |
|
63 | + 'notnull' => true, |
|
64 | + 'length' => 12, |
|
65 | + 'default' => '', |
|
66 | + ]); |
|
67 | + $table->addColumn('location', Types::STRING, [ |
|
68 | + 'notnull' => true, |
|
69 | + 'length' => 512, |
|
70 | + 'default' => '', |
|
71 | + ]); |
|
72 | + $table->addColumn('type', Types::STRING, [ |
|
73 | + 'notnull' => false, |
|
74 | + 'length' => 4, |
|
75 | + ]); |
|
76 | + $table->addColumn('mime', Types::STRING, [ |
|
77 | + 'notnull' => false, |
|
78 | + 'length' => 255, |
|
79 | + ]); |
|
80 | + $table->setPrimaryKey(['auto_id']); |
|
81 | + $table->addIndex(['id'], 'id_index'); |
|
82 | + $table->addIndex(['timestamp'], 'timestamp_index'); |
|
83 | + $table->addIndex(['user'], 'user_index'); |
|
84 | + } |
|
85 | + return $schema; |
|
86 | + } |
|
87 | 87 | } |
@@ -34,37 +34,37 @@ |
||
34 | 34 | use OCP\Migration\SimpleMigrationStep; |
35 | 35 | |
36 | 36 | class Version21000Date20201223143245 extends SimpleMigrationStep { |
37 | - public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { |
|
38 | - /** @var ISchemaWrapper $schema */ |
|
39 | - $schema = $schemaClosure(); |
|
37 | + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { |
|
38 | + /** @var ISchemaWrapper $schema */ |
|
39 | + $schema = $schemaClosure(); |
|
40 | 40 | |
41 | - if ($schema->hasTable('share_external')) { |
|
42 | - $table = $schema->getTable('share_external'); |
|
43 | - $changed = false; |
|
44 | - if (!$table->hasColumn('parent')) { |
|
45 | - $table->addColumn('parent', Types::BIGINT, [ |
|
46 | - 'notnull' => false, |
|
47 | - 'default' => -1, |
|
48 | - ]); |
|
49 | - $changed = true; |
|
50 | - } |
|
51 | - if (!$table->hasColumn('share_type')) { |
|
52 | - $table->addColumn('share_type', Types::INTEGER, [ |
|
53 | - 'notnull' => false, |
|
54 | - 'length' => 4, |
|
55 | - ]); |
|
56 | - $changed = true; |
|
57 | - } |
|
58 | - if ($table->hasColumn('lastscan')) { |
|
59 | - $table->dropColumn('lastscan'); |
|
60 | - $changed = true; |
|
61 | - } |
|
41 | + if ($schema->hasTable('share_external')) { |
|
42 | + $table = $schema->getTable('share_external'); |
|
43 | + $changed = false; |
|
44 | + if (!$table->hasColumn('parent')) { |
|
45 | + $table->addColumn('parent', Types::BIGINT, [ |
|
46 | + 'notnull' => false, |
|
47 | + 'default' => -1, |
|
48 | + ]); |
|
49 | + $changed = true; |
|
50 | + } |
|
51 | + if (!$table->hasColumn('share_type')) { |
|
52 | + $table->addColumn('share_type', Types::INTEGER, [ |
|
53 | + 'notnull' => false, |
|
54 | + 'length' => 4, |
|
55 | + ]); |
|
56 | + $changed = true; |
|
57 | + } |
|
58 | + if ($table->hasColumn('lastscan')) { |
|
59 | + $table->dropColumn('lastscan'); |
|
60 | + $changed = true; |
|
61 | + } |
|
62 | 62 | |
63 | - if ($changed) { |
|
64 | - return $schema; |
|
65 | - } |
|
66 | - } |
|
63 | + if ($changed) { |
|
64 | + return $schema; |
|
65 | + } |
|
66 | + } |
|
67 | 67 | |
68 | - return null; |
|
69 | - } |
|
68 | + return null; |
|
69 | + } |
|
70 | 70 | } |
@@ -74,7 +74,7 @@ |
||
74 | 74 | $query->select($query->func()->max('cardid')) |
75 | 75 | ->from('cards_properties') |
76 | 76 | ->where($query->expr()->eq('name', $query->createNamedParameter('X-SOCIALPROFILE'))); |
77 | - $maxId = (int)$query->execute()->fetchOne(); |
|
77 | + $maxId = (int) $query->execute()->fetchOne(); |
|
78 | 78 | |
79 | 79 | if ($maxId === 0) { |
80 | 80 | return; |
@@ -13,52 +13,52 @@ |
||
13 | 13 | |
14 | 14 | class BuildSocialSearchIndex implements IRepairStep { |
15 | 15 | |
16 | - /** |
|
17 | - * @param IDBConnection $db |
|
18 | - * @param IJobList $jobList |
|
19 | - * @param IConfig $config |
|
20 | - */ |
|
21 | - public function __construct( |
|
22 | - private IDBConnection $db, |
|
23 | - private IJobList $jobList, |
|
24 | - private IConfig $config, |
|
25 | - ) { |
|
26 | - } |
|
16 | + /** |
|
17 | + * @param IDBConnection $db |
|
18 | + * @param IJobList $jobList |
|
19 | + * @param IConfig $config |
|
20 | + */ |
|
21 | + public function __construct( |
|
22 | + private IDBConnection $db, |
|
23 | + private IJobList $jobList, |
|
24 | + private IConfig $config, |
|
25 | + ) { |
|
26 | + } |
|
27 | 27 | |
28 | - /** |
|
29 | - * @return string |
|
30 | - */ |
|
31 | - public function getName() { |
|
32 | - return 'Register building of social profile search index as background job'; |
|
33 | - } |
|
28 | + /** |
|
29 | + * @return string |
|
30 | + */ |
|
31 | + public function getName() { |
|
32 | + return 'Register building of social profile search index as background job'; |
|
33 | + } |
|
34 | 34 | |
35 | - /** |
|
36 | - * @param IOutput $output |
|
37 | - */ |
|
38 | - public function run(IOutput $output) { |
|
39 | - // only run once |
|
40 | - if ($this->config->getAppValue('dav', 'builtSocialSearchIndex') === 'yes') { |
|
41 | - $output->info('Repair step already executed'); |
|
42 | - return; |
|
43 | - } |
|
35 | + /** |
|
36 | + * @param IOutput $output |
|
37 | + */ |
|
38 | + public function run(IOutput $output) { |
|
39 | + // only run once |
|
40 | + if ($this->config->getAppValue('dav', 'builtSocialSearchIndex') === 'yes') { |
|
41 | + $output->info('Repair step already executed'); |
|
42 | + return; |
|
43 | + } |
|
44 | 44 | |
45 | - $query = $this->db->getQueryBuilder(); |
|
46 | - $query->select($query->func()->max('cardid')) |
|
47 | - ->from('cards_properties') |
|
48 | - ->where($query->expr()->eq('name', $query->createNamedParameter('X-SOCIALPROFILE'))); |
|
49 | - $maxId = (int)$query->execute()->fetchOne(); |
|
45 | + $query = $this->db->getQueryBuilder(); |
|
46 | + $query->select($query->func()->max('cardid')) |
|
47 | + ->from('cards_properties') |
|
48 | + ->where($query->expr()->eq('name', $query->createNamedParameter('X-SOCIALPROFILE'))); |
|
49 | + $maxId = (int)$query->execute()->fetchOne(); |
|
50 | 50 | |
51 | - if ($maxId === 0) { |
|
52 | - return; |
|
53 | - } |
|
51 | + if ($maxId === 0) { |
|
52 | + return; |
|
53 | + } |
|
54 | 54 | |
55 | - $output->info('Add background job'); |
|
56 | - $this->jobList->add(BuildSocialSearchIndexBackgroundJob::class, [ |
|
57 | - 'offset' => 0, |
|
58 | - 'stopAt' => $maxId |
|
59 | - ]); |
|
55 | + $output->info('Add background job'); |
|
56 | + $this->jobList->add(BuildSocialSearchIndexBackgroundJob::class, [ |
|
57 | + 'offset' => 0, |
|
58 | + 'stopAt' => $maxId |
|
59 | + ]); |
|
60 | 60 | |
61 | - // no need to redo the repair during next upgrade |
|
62 | - $this->config->setAppValue('dav', 'builtSocialSearchIndex', 'yes'); |
|
63 | - } |
|
61 | + // no need to redo the repair during next upgrade |
|
62 | + $this->config->setAppValue('dav', 'builtSocialSearchIndex', 'yes'); |
|
63 | + } |
|
64 | 64 | } |
@@ -31,42 +31,42 @@ |
||
31 | 31 | use Doctrine\DBAL\Events; |
32 | 32 | |
33 | 33 | class SQLiteSessionInit implements EventSubscriber { |
34 | - /** |
|
35 | - * @var bool |
|
36 | - */ |
|
37 | - private $caseSensitiveLike; |
|
34 | + /** |
|
35 | + * @var bool |
|
36 | + */ |
|
37 | + private $caseSensitiveLike; |
|
38 | 38 | |
39 | - /** |
|
40 | - * @var string |
|
41 | - */ |
|
42 | - private $journalMode; |
|
39 | + /** |
|
40 | + * @var string |
|
41 | + */ |
|
42 | + private $journalMode; |
|
43 | 43 | |
44 | - /** |
|
45 | - * Configure case sensitive like for each connection |
|
46 | - * |
|
47 | - * @param bool $caseSensitiveLike |
|
48 | - * @param string $journalMode |
|
49 | - */ |
|
50 | - public function __construct($caseSensitiveLike, $journalMode) { |
|
51 | - $this->caseSensitiveLike = $caseSensitiveLike; |
|
52 | - $this->journalMode = $journalMode; |
|
53 | - } |
|
44 | + /** |
|
45 | + * Configure case sensitive like for each connection |
|
46 | + * |
|
47 | + * @param bool $caseSensitiveLike |
|
48 | + * @param string $journalMode |
|
49 | + */ |
|
50 | + public function __construct($caseSensitiveLike, $journalMode) { |
|
51 | + $this->caseSensitiveLike = $caseSensitiveLike; |
|
52 | + $this->journalMode = $journalMode; |
|
53 | + } |
|
54 | 54 | |
55 | - /** |
|
56 | - * @param ConnectionEventArgs $args |
|
57 | - * @return void |
|
58 | - */ |
|
59 | - public function postConnect(ConnectionEventArgs $args) { |
|
60 | - $sensitive = $this->caseSensitiveLike ? 'true' : 'false'; |
|
61 | - $args->getConnection()->executeUpdate('PRAGMA case_sensitive_like = ' . $sensitive); |
|
62 | - $args->getConnection()->executeUpdate('PRAGMA journal_mode = ' . $this->journalMode); |
|
63 | - /** @var \Doctrine\DBAL\Driver\PDO\Connection $connection */ |
|
64 | - $connection = $args->getConnection()->getWrappedConnection(); |
|
65 | - $pdo = $connection->getWrappedConnection(); |
|
66 | - $pdo->sqliteCreateFunction('md5', 'md5', 1); |
|
67 | - } |
|
55 | + /** |
|
56 | + * @param ConnectionEventArgs $args |
|
57 | + * @return void |
|
58 | + */ |
|
59 | + public function postConnect(ConnectionEventArgs $args) { |
|
60 | + $sensitive = $this->caseSensitiveLike ? 'true' : 'false'; |
|
61 | + $args->getConnection()->executeUpdate('PRAGMA case_sensitive_like = ' . $sensitive); |
|
62 | + $args->getConnection()->executeUpdate('PRAGMA journal_mode = ' . $this->journalMode); |
|
63 | + /** @var \Doctrine\DBAL\Driver\PDO\Connection $connection */ |
|
64 | + $connection = $args->getConnection()->getWrappedConnection(); |
|
65 | + $pdo = $connection->getWrappedConnection(); |
|
66 | + $pdo->sqliteCreateFunction('md5', 'md5', 1); |
|
67 | + } |
|
68 | 68 | |
69 | - public function getSubscribedEvents() { |
|
70 | - return [Events::postConnect]; |
|
71 | - } |
|
69 | + public function getSubscribedEvents() { |
|
70 | + return [Events::postConnect]; |
|
71 | + } |
|
72 | 72 | } |
@@ -58,8 +58,8 @@ |
||
58 | 58 | */ |
59 | 59 | public function postConnect(ConnectionEventArgs $args) { |
60 | 60 | $sensitive = $this->caseSensitiveLike ? 'true' : 'false'; |
61 | - $args->getConnection()->executeUpdate('PRAGMA case_sensitive_like = ' . $sensitive); |
|
62 | - $args->getConnection()->executeUpdate('PRAGMA journal_mode = ' . $this->journalMode); |
|
61 | + $args->getConnection()->executeUpdate('PRAGMA case_sensitive_like = '.$sensitive); |
|
62 | + $args->getConnection()->executeUpdate('PRAGMA journal_mode = '.$this->journalMode); |
|
63 | 63 | /** @var \Doctrine\DBAL\Driver\PDO\Connection $connection */ |
64 | 64 | $connection = $args->getConnection()->getWrappedConnection(); |
65 | 65 | $pdo = $connection->getWrappedConnection(); |
@@ -134,7 +134,7 @@ discard block |
||
134 | 134 | $this->input = $input; |
135 | 135 | $this->output = $output; |
136 | 136 | |
137 | - $headline = 'Encrypt all files with the ' . Encryption::DISPLAY_NAME; |
|
137 | + $headline = 'Encrypt all files with the '.Encryption::DISPLAY_NAME; |
|
138 | 138 | $this->output->writeln("\n"); |
139 | 139 | $this->output->writeln($headline); |
140 | 140 | $this->output->writeln(str_pad('', strlen($headline), '=')); |
@@ -190,7 +190,7 @@ discard block |
||
190 | 190 | $users = $backend->getUsers('', $limit, $offset); |
191 | 191 | foreach ($users as $user) { |
192 | 192 | if ($this->keyManager->userHasKeys($user) === false) { |
193 | - $progress->setMessage('Create key-pair for ' . $user); |
|
193 | + $progress->setMessage('Create key-pair for '.$user); |
|
194 | 194 | $progress->advance(); |
195 | 195 | $this->setupUserFS($user); |
196 | 196 | $password = $this->generateOneTimePassword($user); |
@@ -264,12 +264,12 @@ discard block |
||
264 | 264 | protected function encryptUsersFiles($uid, ProgressBar $progress, $userCount) { |
265 | 265 | $this->setupUserFS($uid); |
266 | 266 | $directories = []; |
267 | - $directories[] = '/' . $uid . '/files'; |
|
267 | + $directories[] = '/'.$uid.'/files'; |
|
268 | 268 | |
269 | 269 | while ($root = array_pop($directories)) { |
270 | 270 | $content = $this->rootView->getDirectoryContent($root); |
271 | 271 | foreach ($content as $file) { |
272 | - $path = $root . '/' . $file['name']; |
|
272 | + $path = $root.'/'.$file['name']; |
|
273 | 273 | if ($this->rootView->is_dir($path)) { |
274 | 274 | $directories[] = $path; |
275 | 275 | continue; |
@@ -300,7 +300,7 @@ discard block |
||
300 | 300 | } |
301 | 301 | |
302 | 302 | $source = $path; |
303 | - $target = $path . '.encrypted.' . time(); |
|
303 | + $target = $path.'.encrypted.'.time(); |
|
304 | 304 | |
305 | 305 | try { |
306 | 306 | $this->rootView->copy($source, $target); |
@@ -29,382 +29,382 @@ |
||
29 | 29 | |
30 | 30 | class EncryptAll { |
31 | 31 | |
32 | - /** @var array */ |
|
33 | - protected $userPasswords; |
|
34 | - |
|
35 | - /** @var OutputInterface */ |
|
36 | - protected $output; |
|
37 | - |
|
38 | - /** @var InputInterface */ |
|
39 | - protected $input; |
|
40 | - |
|
41 | - public function __construct( |
|
42 | - protected Setup $userSetup, |
|
43 | - protected IUserManager $userManager, |
|
44 | - protected View $rootView, |
|
45 | - protected KeyManager $keyManager, |
|
46 | - protected Util $util, |
|
47 | - protected IConfig $config, |
|
48 | - protected IMailer $mailer, |
|
49 | - protected IL10N $l, |
|
50 | - protected IFactory $l10nFactory, |
|
51 | - protected QuestionHelper $questionHelper, |
|
52 | - protected ISecureRandom $secureRandom, |
|
53 | - ) { |
|
54 | - // store one time passwords for the users |
|
55 | - $this->userPasswords = []; |
|
56 | - } |
|
57 | - |
|
58 | - /** |
|
59 | - * start to encrypt all files |
|
60 | - * |
|
61 | - * @param InputInterface $input |
|
62 | - * @param OutputInterface $output |
|
63 | - */ |
|
64 | - public function encryptAll(InputInterface $input, OutputInterface $output) { |
|
65 | - $this->input = $input; |
|
66 | - $this->output = $output; |
|
67 | - |
|
68 | - $headline = 'Encrypt all files with the ' . Encryption::DISPLAY_NAME; |
|
69 | - $this->output->writeln("\n"); |
|
70 | - $this->output->writeln($headline); |
|
71 | - $this->output->writeln(str_pad('', strlen($headline), '=')); |
|
72 | - $this->output->writeln("\n"); |
|
73 | - |
|
74 | - if ($this->util->isMasterKeyEnabled()) { |
|
75 | - $this->output->writeln('Use master key to encrypt all files.'); |
|
76 | - $this->keyManager->validateMasterKey(); |
|
77 | - } else { |
|
78 | - //create private/public keys for each user and store the private key password |
|
79 | - $this->output->writeln('Create key-pair for every user'); |
|
80 | - $this->output->writeln('------------------------------'); |
|
81 | - $this->output->writeln(''); |
|
82 | - $this->output->writeln('This module will encrypt all files in the users files folder initially.'); |
|
83 | - $this->output->writeln('Already existing versions and files in the trash bin will not be encrypted.'); |
|
84 | - $this->output->writeln(''); |
|
85 | - $this->createKeyPairs(); |
|
86 | - } |
|
87 | - |
|
88 | - |
|
89 | - // output generated encryption key passwords |
|
90 | - if ($this->util->isMasterKeyEnabled() === false) { |
|
91 | - //send-out or display password list and write it to a file |
|
92 | - $this->output->writeln("\n"); |
|
93 | - $this->output->writeln('Generated encryption key passwords'); |
|
94 | - $this->output->writeln('----------------------------------'); |
|
95 | - $this->output->writeln(''); |
|
96 | - $this->outputPasswords(); |
|
97 | - } |
|
98 | - |
|
99 | - //setup users file system and encrypt all files one by one (take should encrypt setting of storage into account) |
|
100 | - $this->output->writeln("\n"); |
|
101 | - $this->output->writeln('Start to encrypt users files'); |
|
102 | - $this->output->writeln('----------------------------'); |
|
103 | - $this->output->writeln(''); |
|
104 | - $this->encryptAllUsersFiles(); |
|
105 | - $this->output->writeln("\n"); |
|
106 | - } |
|
107 | - |
|
108 | - /** |
|
109 | - * create key-pair for every user |
|
110 | - */ |
|
111 | - protected function createKeyPairs() { |
|
112 | - $this->output->writeln("\n"); |
|
113 | - $progress = new ProgressBar($this->output); |
|
114 | - $progress->setFormat(" %message% \n [%bar%]"); |
|
115 | - $progress->start(); |
|
116 | - |
|
117 | - foreach ($this->userManager->getBackends() as $backend) { |
|
118 | - $limit = 500; |
|
119 | - $offset = 0; |
|
120 | - do { |
|
121 | - $users = $backend->getUsers('', $limit, $offset); |
|
122 | - foreach ($users as $user) { |
|
123 | - if ($this->keyManager->userHasKeys($user) === false) { |
|
124 | - $progress->setMessage('Create key-pair for ' . $user); |
|
125 | - $progress->advance(); |
|
126 | - $this->setupUserFS($user); |
|
127 | - $password = $this->generateOneTimePassword($user); |
|
128 | - $this->userSetup->setupUser($user, $password); |
|
129 | - } else { |
|
130 | - // users which already have a key-pair will be stored with a |
|
131 | - // empty password and filtered out later |
|
132 | - $this->userPasswords[$user] = ''; |
|
133 | - } |
|
134 | - } |
|
135 | - $offset += $limit; |
|
136 | - } while (count($users) >= $limit); |
|
137 | - } |
|
138 | - |
|
139 | - $progress->setMessage('Key-pair created for all users'); |
|
140 | - $progress->finish(); |
|
141 | - } |
|
142 | - |
|
143 | - /** |
|
144 | - * iterate over all user and encrypt their files |
|
145 | - */ |
|
146 | - protected function encryptAllUsersFiles() { |
|
147 | - $this->output->writeln("\n"); |
|
148 | - $progress = new ProgressBar($this->output); |
|
149 | - $progress->setFormat(" %message% \n [%bar%]"); |
|
150 | - $progress->start(); |
|
151 | - $numberOfUsers = count($this->userPasswords); |
|
152 | - $userNo = 1; |
|
153 | - if ($this->util->isMasterKeyEnabled()) { |
|
154 | - $this->encryptAllUserFilesWithMasterKey($progress); |
|
155 | - } else { |
|
156 | - foreach ($this->userPasswords as $uid => $password) { |
|
157 | - $userCount = "$uid ($userNo of $numberOfUsers)"; |
|
158 | - $this->encryptUsersFiles($uid, $progress, $userCount); |
|
159 | - $userNo++; |
|
160 | - } |
|
161 | - } |
|
162 | - $progress->setMessage('all files encrypted'); |
|
163 | - $progress->finish(); |
|
164 | - } |
|
165 | - |
|
166 | - /** |
|
167 | - * encrypt all user files with the master key |
|
168 | - * |
|
169 | - * @param ProgressBar $progress |
|
170 | - */ |
|
171 | - protected function encryptAllUserFilesWithMasterKey(ProgressBar $progress) { |
|
172 | - $userNo = 1; |
|
173 | - foreach ($this->userManager->getBackends() as $backend) { |
|
174 | - $limit = 500; |
|
175 | - $offset = 0; |
|
176 | - do { |
|
177 | - $users = $backend->getUsers('', $limit, $offset); |
|
178 | - foreach ($users as $user) { |
|
179 | - $userCount = "$user ($userNo)"; |
|
180 | - $this->encryptUsersFiles($user, $progress, $userCount); |
|
181 | - $userNo++; |
|
182 | - } |
|
183 | - $offset += $limit; |
|
184 | - } while (count($users) >= $limit); |
|
185 | - } |
|
186 | - } |
|
187 | - |
|
188 | - /** |
|
189 | - * encrypt files from the given user |
|
190 | - * |
|
191 | - * @param string $uid |
|
192 | - * @param ProgressBar $progress |
|
193 | - * @param string $userCount |
|
194 | - */ |
|
195 | - protected function encryptUsersFiles($uid, ProgressBar $progress, $userCount) { |
|
196 | - $this->setupUserFS($uid); |
|
197 | - $directories = []; |
|
198 | - $directories[] = '/' . $uid . '/files'; |
|
199 | - |
|
200 | - while ($root = array_pop($directories)) { |
|
201 | - $content = $this->rootView->getDirectoryContent($root); |
|
202 | - foreach ($content as $file) { |
|
203 | - $path = $root . '/' . $file['name']; |
|
204 | - if ($this->rootView->is_dir($path)) { |
|
205 | - $directories[] = $path; |
|
206 | - continue; |
|
207 | - } else { |
|
208 | - $progress->setMessage("encrypt files for user $userCount: $path"); |
|
209 | - $progress->advance(); |
|
210 | - if ($this->encryptFile($path) === false) { |
|
211 | - $progress->setMessage("encrypt files for user $userCount: $path (already encrypted)"); |
|
212 | - $progress->advance(); |
|
213 | - } |
|
214 | - } |
|
215 | - } |
|
216 | - } |
|
217 | - } |
|
218 | - |
|
219 | - /** |
|
220 | - * encrypt file |
|
221 | - * |
|
222 | - * @param string $path |
|
223 | - * @return bool |
|
224 | - */ |
|
225 | - protected function encryptFile($path) { |
|
226 | - |
|
227 | - // skip already encrypted files |
|
228 | - $fileInfo = $this->rootView->getFileInfo($path); |
|
229 | - if ($fileInfo !== false && $fileInfo->isEncrypted()) { |
|
230 | - return true; |
|
231 | - } |
|
232 | - |
|
233 | - $source = $path; |
|
234 | - $target = $path . '.encrypted.' . time(); |
|
235 | - |
|
236 | - try { |
|
237 | - $this->rootView->copy($source, $target); |
|
238 | - $this->rootView->rename($target, $source); |
|
239 | - } catch (DecryptionFailedException $e) { |
|
240 | - if ($this->rootView->file_exists($target)) { |
|
241 | - $this->rootView->unlink($target); |
|
242 | - } |
|
243 | - return false; |
|
244 | - } |
|
245 | - |
|
246 | - return true; |
|
247 | - } |
|
248 | - |
|
249 | - /** |
|
250 | - * output one-time encryption passwords |
|
251 | - */ |
|
252 | - protected function outputPasswords() { |
|
253 | - $table = new Table($this->output); |
|
254 | - $table->setHeaders(['Username', 'Private key password']); |
|
255 | - |
|
256 | - //create rows |
|
257 | - $newPasswords = []; |
|
258 | - $unchangedPasswords = []; |
|
259 | - foreach ($this->userPasswords as $uid => $password) { |
|
260 | - if (empty($password)) { |
|
261 | - $unchangedPasswords[] = $uid; |
|
262 | - } else { |
|
263 | - $newPasswords[] = [$uid, $password]; |
|
264 | - } |
|
265 | - } |
|
266 | - |
|
267 | - if (empty($newPasswords)) { |
|
268 | - $this->output->writeln("\nAll users already had a key-pair, no further action needed.\n"); |
|
269 | - return; |
|
270 | - } |
|
271 | - |
|
272 | - $table->setRows($newPasswords); |
|
273 | - $table->render(); |
|
274 | - |
|
275 | - if (!empty($unchangedPasswords)) { |
|
276 | - $this->output->writeln("\nThe following users already had a key-pair which was reused without setting a new password:\n"); |
|
277 | - foreach ($unchangedPasswords as $uid) { |
|
278 | - $this->output->writeln(" $uid"); |
|
279 | - } |
|
280 | - } |
|
281 | - |
|
282 | - $this->writePasswordsToFile($newPasswords); |
|
283 | - |
|
284 | - $this->output->writeln(''); |
|
285 | - $question = new ConfirmationQuestion('Do you want to send the passwords directly to the users by mail? (y/n) ', false); |
|
286 | - if ($this->questionHelper->ask($this->input, $this->output, $question)) { |
|
287 | - $this->sendPasswordsByMail(); |
|
288 | - } |
|
289 | - } |
|
290 | - |
|
291 | - /** |
|
292 | - * write one-time encryption passwords to a csv file |
|
293 | - * |
|
294 | - * @param array $passwords |
|
295 | - */ |
|
296 | - protected function writePasswordsToFile(array $passwords) { |
|
297 | - $fp = $this->rootView->fopen('oneTimeEncryptionPasswords.csv', 'w'); |
|
298 | - foreach ($passwords as $pwd) { |
|
299 | - fputcsv($fp, $pwd); |
|
300 | - } |
|
301 | - fclose($fp); |
|
302 | - $this->output->writeln("\n"); |
|
303 | - $this->output->writeln('A list of all newly created passwords was written to data/oneTimeEncryptionPasswords.csv'); |
|
304 | - $this->output->writeln(''); |
|
305 | - $this->output->writeln('Each of these users need to login to the web interface, go to the'); |
|
306 | - $this->output->writeln('personal settings section "basic encryption module" and'); |
|
307 | - $this->output->writeln('update the private key password to match the login password again by'); |
|
308 | - $this->output->writeln('entering the one-time password into the "old log-in password" field'); |
|
309 | - $this->output->writeln('and their current login password'); |
|
310 | - } |
|
311 | - |
|
312 | - /** |
|
313 | - * setup user file system |
|
314 | - * |
|
315 | - * @param string $uid |
|
316 | - */ |
|
317 | - protected function setupUserFS($uid) { |
|
318 | - \OC_Util::tearDownFS(); |
|
319 | - \OC_Util::setupFS($uid); |
|
320 | - } |
|
321 | - |
|
322 | - /** |
|
323 | - * generate one time password for the user and store it in a array |
|
324 | - * |
|
325 | - * @param string $uid |
|
326 | - * @return string password |
|
327 | - */ |
|
328 | - protected function generateOneTimePassword($uid) { |
|
329 | - $password = $this->secureRandom->generate(16, ISecureRandom::CHAR_HUMAN_READABLE); |
|
330 | - $this->userPasswords[$uid] = $password; |
|
331 | - return $password; |
|
332 | - } |
|
333 | - |
|
334 | - /** |
|
335 | - * send encryption key passwords to the users by mail |
|
336 | - */ |
|
337 | - protected function sendPasswordsByMail() { |
|
338 | - $noMail = []; |
|
339 | - |
|
340 | - $this->output->writeln(''); |
|
341 | - $progress = new ProgressBar($this->output, count($this->userPasswords)); |
|
342 | - $progress->start(); |
|
343 | - |
|
344 | - foreach ($this->userPasswords as $uid => $password) { |
|
345 | - $progress->advance(); |
|
346 | - if (!empty($password)) { |
|
347 | - $recipient = $this->userManager->get($uid); |
|
348 | - if (!$recipient instanceof IUser) { |
|
349 | - continue; |
|
350 | - } |
|
351 | - |
|
352 | - $recipientDisplayName = $recipient->getDisplayName(); |
|
353 | - $to = $recipient->getEMailAddress(); |
|
354 | - |
|
355 | - if ($to === '' || $to === null) { |
|
356 | - $noMail[] = $uid; |
|
357 | - continue; |
|
358 | - } |
|
359 | - |
|
360 | - $l = $this->l10nFactory->get('encryption', $this->l10nFactory->getUserLanguage($recipient)); |
|
361 | - |
|
362 | - $template = $this->mailer->createEMailTemplate('encryption.encryptAllPassword', [ |
|
363 | - 'user' => $recipient->getUID(), |
|
364 | - 'password' => $password, |
|
365 | - ]); |
|
366 | - |
|
367 | - $template->setSubject($l->t('one-time password for server-side-encryption')); |
|
368 | - // 'Hey there,<br><br>The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br> |
|
369 | - // Please login to the web interface, go to the section "Basic encryption module" of your personal settings and update your encryption password by entering this password into the "Old log-in password" field and your current login-password.<br><br>' |
|
370 | - $template->addHeader(); |
|
371 | - $template->addHeading($l->t('Encryption password')); |
|
372 | - $template->addBodyText( |
|
373 | - $l->t('The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.', [htmlspecialchars($password)]), |
|
374 | - $l->t('The administration enabled server-side-encryption. Your files were encrypted using the password "%s".', $password) |
|
375 | - ); |
|
376 | - $template->addBodyText( |
|
377 | - $l->t('Please login to the web interface, go to the "Security" section of your personal settings and update your encryption password by entering this password into the "Old login password" field and your current login password.') |
|
378 | - ); |
|
379 | - $template->addFooter(); |
|
380 | - |
|
381 | - // send it out now |
|
382 | - try { |
|
383 | - $message = $this->mailer->createMessage(); |
|
384 | - $message->setTo([$to => $recipientDisplayName]); |
|
385 | - $message->useTemplate($template); |
|
386 | - $message->setAutoSubmitted(AutoSubmitted::VALUE_AUTO_GENERATED); |
|
387 | - $this->mailer->send($message); |
|
388 | - } catch (\Exception $e) { |
|
389 | - $noMail[] = $uid; |
|
390 | - } |
|
391 | - } |
|
392 | - } |
|
393 | - |
|
394 | - $progress->finish(); |
|
395 | - |
|
396 | - if (empty($noMail)) { |
|
397 | - $this->output->writeln("\n\nPassword successfully send to all users"); |
|
398 | - } else { |
|
399 | - $table = new Table($this->output); |
|
400 | - $table->setHeaders(['Username', 'Private key password']); |
|
401 | - $this->output->writeln("\n\nCould not send password to following users:\n"); |
|
402 | - $rows = []; |
|
403 | - foreach ($noMail as $uid) { |
|
404 | - $rows[] = [$uid, $this->userPasswords[$uid]]; |
|
405 | - } |
|
406 | - $table->setRows($rows); |
|
407 | - $table->render(); |
|
408 | - } |
|
409 | - } |
|
32 | + /** @var array */ |
|
33 | + protected $userPasswords; |
|
34 | + |
|
35 | + /** @var OutputInterface */ |
|
36 | + protected $output; |
|
37 | + |
|
38 | + /** @var InputInterface */ |
|
39 | + protected $input; |
|
40 | + |
|
41 | + public function __construct( |
|
42 | + protected Setup $userSetup, |
|
43 | + protected IUserManager $userManager, |
|
44 | + protected View $rootView, |
|
45 | + protected KeyManager $keyManager, |
|
46 | + protected Util $util, |
|
47 | + protected IConfig $config, |
|
48 | + protected IMailer $mailer, |
|
49 | + protected IL10N $l, |
|
50 | + protected IFactory $l10nFactory, |
|
51 | + protected QuestionHelper $questionHelper, |
|
52 | + protected ISecureRandom $secureRandom, |
|
53 | + ) { |
|
54 | + // store one time passwords for the users |
|
55 | + $this->userPasswords = []; |
|
56 | + } |
|
57 | + |
|
58 | + /** |
|
59 | + * start to encrypt all files |
|
60 | + * |
|
61 | + * @param InputInterface $input |
|
62 | + * @param OutputInterface $output |
|
63 | + */ |
|
64 | + public function encryptAll(InputInterface $input, OutputInterface $output) { |
|
65 | + $this->input = $input; |
|
66 | + $this->output = $output; |
|
67 | + |
|
68 | + $headline = 'Encrypt all files with the ' . Encryption::DISPLAY_NAME; |
|
69 | + $this->output->writeln("\n"); |
|
70 | + $this->output->writeln($headline); |
|
71 | + $this->output->writeln(str_pad('', strlen($headline), '=')); |
|
72 | + $this->output->writeln("\n"); |
|
73 | + |
|
74 | + if ($this->util->isMasterKeyEnabled()) { |
|
75 | + $this->output->writeln('Use master key to encrypt all files.'); |
|
76 | + $this->keyManager->validateMasterKey(); |
|
77 | + } else { |
|
78 | + //create private/public keys for each user and store the private key password |
|
79 | + $this->output->writeln('Create key-pair for every user'); |
|
80 | + $this->output->writeln('------------------------------'); |
|
81 | + $this->output->writeln(''); |
|
82 | + $this->output->writeln('This module will encrypt all files in the users files folder initially.'); |
|
83 | + $this->output->writeln('Already existing versions and files in the trash bin will not be encrypted.'); |
|
84 | + $this->output->writeln(''); |
|
85 | + $this->createKeyPairs(); |
|
86 | + } |
|
87 | + |
|
88 | + |
|
89 | + // output generated encryption key passwords |
|
90 | + if ($this->util->isMasterKeyEnabled() === false) { |
|
91 | + //send-out or display password list and write it to a file |
|
92 | + $this->output->writeln("\n"); |
|
93 | + $this->output->writeln('Generated encryption key passwords'); |
|
94 | + $this->output->writeln('----------------------------------'); |
|
95 | + $this->output->writeln(''); |
|
96 | + $this->outputPasswords(); |
|
97 | + } |
|
98 | + |
|
99 | + //setup users file system and encrypt all files one by one (take should encrypt setting of storage into account) |
|
100 | + $this->output->writeln("\n"); |
|
101 | + $this->output->writeln('Start to encrypt users files'); |
|
102 | + $this->output->writeln('----------------------------'); |
|
103 | + $this->output->writeln(''); |
|
104 | + $this->encryptAllUsersFiles(); |
|
105 | + $this->output->writeln("\n"); |
|
106 | + } |
|
107 | + |
|
108 | + /** |
|
109 | + * create key-pair for every user |
|
110 | + */ |
|
111 | + protected function createKeyPairs() { |
|
112 | + $this->output->writeln("\n"); |
|
113 | + $progress = new ProgressBar($this->output); |
|
114 | + $progress->setFormat(" %message% \n [%bar%]"); |
|
115 | + $progress->start(); |
|
116 | + |
|
117 | + foreach ($this->userManager->getBackends() as $backend) { |
|
118 | + $limit = 500; |
|
119 | + $offset = 0; |
|
120 | + do { |
|
121 | + $users = $backend->getUsers('', $limit, $offset); |
|
122 | + foreach ($users as $user) { |
|
123 | + if ($this->keyManager->userHasKeys($user) === false) { |
|
124 | + $progress->setMessage('Create key-pair for ' . $user); |
|
125 | + $progress->advance(); |
|
126 | + $this->setupUserFS($user); |
|
127 | + $password = $this->generateOneTimePassword($user); |
|
128 | + $this->userSetup->setupUser($user, $password); |
|
129 | + } else { |
|
130 | + // users which already have a key-pair will be stored with a |
|
131 | + // empty password and filtered out later |
|
132 | + $this->userPasswords[$user] = ''; |
|
133 | + } |
|
134 | + } |
|
135 | + $offset += $limit; |
|
136 | + } while (count($users) >= $limit); |
|
137 | + } |
|
138 | + |
|
139 | + $progress->setMessage('Key-pair created for all users'); |
|
140 | + $progress->finish(); |
|
141 | + } |
|
142 | + |
|
143 | + /** |
|
144 | + * iterate over all user and encrypt their files |
|
145 | + */ |
|
146 | + protected function encryptAllUsersFiles() { |
|
147 | + $this->output->writeln("\n"); |
|
148 | + $progress = new ProgressBar($this->output); |
|
149 | + $progress->setFormat(" %message% \n [%bar%]"); |
|
150 | + $progress->start(); |
|
151 | + $numberOfUsers = count($this->userPasswords); |
|
152 | + $userNo = 1; |
|
153 | + if ($this->util->isMasterKeyEnabled()) { |
|
154 | + $this->encryptAllUserFilesWithMasterKey($progress); |
|
155 | + } else { |
|
156 | + foreach ($this->userPasswords as $uid => $password) { |
|
157 | + $userCount = "$uid ($userNo of $numberOfUsers)"; |
|
158 | + $this->encryptUsersFiles($uid, $progress, $userCount); |
|
159 | + $userNo++; |
|
160 | + } |
|
161 | + } |
|
162 | + $progress->setMessage('all files encrypted'); |
|
163 | + $progress->finish(); |
|
164 | + } |
|
165 | + |
|
166 | + /** |
|
167 | + * encrypt all user files with the master key |
|
168 | + * |
|
169 | + * @param ProgressBar $progress |
|
170 | + */ |
|
171 | + protected function encryptAllUserFilesWithMasterKey(ProgressBar $progress) { |
|
172 | + $userNo = 1; |
|
173 | + foreach ($this->userManager->getBackends() as $backend) { |
|
174 | + $limit = 500; |
|
175 | + $offset = 0; |
|
176 | + do { |
|
177 | + $users = $backend->getUsers('', $limit, $offset); |
|
178 | + foreach ($users as $user) { |
|
179 | + $userCount = "$user ($userNo)"; |
|
180 | + $this->encryptUsersFiles($user, $progress, $userCount); |
|
181 | + $userNo++; |
|
182 | + } |
|
183 | + $offset += $limit; |
|
184 | + } while (count($users) >= $limit); |
|
185 | + } |
|
186 | + } |
|
187 | + |
|
188 | + /** |
|
189 | + * encrypt files from the given user |
|
190 | + * |
|
191 | + * @param string $uid |
|
192 | + * @param ProgressBar $progress |
|
193 | + * @param string $userCount |
|
194 | + */ |
|
195 | + protected function encryptUsersFiles($uid, ProgressBar $progress, $userCount) { |
|
196 | + $this->setupUserFS($uid); |
|
197 | + $directories = []; |
|
198 | + $directories[] = '/' . $uid . '/files'; |
|
199 | + |
|
200 | + while ($root = array_pop($directories)) { |
|
201 | + $content = $this->rootView->getDirectoryContent($root); |
|
202 | + foreach ($content as $file) { |
|
203 | + $path = $root . '/' . $file['name']; |
|
204 | + if ($this->rootView->is_dir($path)) { |
|
205 | + $directories[] = $path; |
|
206 | + continue; |
|
207 | + } else { |
|
208 | + $progress->setMessage("encrypt files for user $userCount: $path"); |
|
209 | + $progress->advance(); |
|
210 | + if ($this->encryptFile($path) === false) { |
|
211 | + $progress->setMessage("encrypt files for user $userCount: $path (already encrypted)"); |
|
212 | + $progress->advance(); |
|
213 | + } |
|
214 | + } |
|
215 | + } |
|
216 | + } |
|
217 | + } |
|
218 | + |
|
219 | + /** |
|
220 | + * encrypt file |
|
221 | + * |
|
222 | + * @param string $path |
|
223 | + * @return bool |
|
224 | + */ |
|
225 | + protected function encryptFile($path) { |
|
226 | + |
|
227 | + // skip already encrypted files |
|
228 | + $fileInfo = $this->rootView->getFileInfo($path); |
|
229 | + if ($fileInfo !== false && $fileInfo->isEncrypted()) { |
|
230 | + return true; |
|
231 | + } |
|
232 | + |
|
233 | + $source = $path; |
|
234 | + $target = $path . '.encrypted.' . time(); |
|
235 | + |
|
236 | + try { |
|
237 | + $this->rootView->copy($source, $target); |
|
238 | + $this->rootView->rename($target, $source); |
|
239 | + } catch (DecryptionFailedException $e) { |
|
240 | + if ($this->rootView->file_exists($target)) { |
|
241 | + $this->rootView->unlink($target); |
|
242 | + } |
|
243 | + return false; |
|
244 | + } |
|
245 | + |
|
246 | + return true; |
|
247 | + } |
|
248 | + |
|
249 | + /** |
|
250 | + * output one-time encryption passwords |
|
251 | + */ |
|
252 | + protected function outputPasswords() { |
|
253 | + $table = new Table($this->output); |
|
254 | + $table->setHeaders(['Username', 'Private key password']); |
|
255 | + |
|
256 | + //create rows |
|
257 | + $newPasswords = []; |
|
258 | + $unchangedPasswords = []; |
|
259 | + foreach ($this->userPasswords as $uid => $password) { |
|
260 | + if (empty($password)) { |
|
261 | + $unchangedPasswords[] = $uid; |
|
262 | + } else { |
|
263 | + $newPasswords[] = [$uid, $password]; |
|
264 | + } |
|
265 | + } |
|
266 | + |
|
267 | + if (empty($newPasswords)) { |
|
268 | + $this->output->writeln("\nAll users already had a key-pair, no further action needed.\n"); |
|
269 | + return; |
|
270 | + } |
|
271 | + |
|
272 | + $table->setRows($newPasswords); |
|
273 | + $table->render(); |
|
274 | + |
|
275 | + if (!empty($unchangedPasswords)) { |
|
276 | + $this->output->writeln("\nThe following users already had a key-pair which was reused without setting a new password:\n"); |
|
277 | + foreach ($unchangedPasswords as $uid) { |
|
278 | + $this->output->writeln(" $uid"); |
|
279 | + } |
|
280 | + } |
|
281 | + |
|
282 | + $this->writePasswordsToFile($newPasswords); |
|
283 | + |
|
284 | + $this->output->writeln(''); |
|
285 | + $question = new ConfirmationQuestion('Do you want to send the passwords directly to the users by mail? (y/n) ', false); |
|
286 | + if ($this->questionHelper->ask($this->input, $this->output, $question)) { |
|
287 | + $this->sendPasswordsByMail(); |
|
288 | + } |
|
289 | + } |
|
290 | + |
|
291 | + /** |
|
292 | + * write one-time encryption passwords to a csv file |
|
293 | + * |
|
294 | + * @param array $passwords |
|
295 | + */ |
|
296 | + protected function writePasswordsToFile(array $passwords) { |
|
297 | + $fp = $this->rootView->fopen('oneTimeEncryptionPasswords.csv', 'w'); |
|
298 | + foreach ($passwords as $pwd) { |
|
299 | + fputcsv($fp, $pwd); |
|
300 | + } |
|
301 | + fclose($fp); |
|
302 | + $this->output->writeln("\n"); |
|
303 | + $this->output->writeln('A list of all newly created passwords was written to data/oneTimeEncryptionPasswords.csv'); |
|
304 | + $this->output->writeln(''); |
|
305 | + $this->output->writeln('Each of these users need to login to the web interface, go to the'); |
|
306 | + $this->output->writeln('personal settings section "basic encryption module" and'); |
|
307 | + $this->output->writeln('update the private key password to match the login password again by'); |
|
308 | + $this->output->writeln('entering the one-time password into the "old log-in password" field'); |
|
309 | + $this->output->writeln('and their current login password'); |
|
310 | + } |
|
311 | + |
|
312 | + /** |
|
313 | + * setup user file system |
|
314 | + * |
|
315 | + * @param string $uid |
|
316 | + */ |
|
317 | + protected function setupUserFS($uid) { |
|
318 | + \OC_Util::tearDownFS(); |
|
319 | + \OC_Util::setupFS($uid); |
|
320 | + } |
|
321 | + |
|
322 | + /** |
|
323 | + * generate one time password for the user and store it in a array |
|
324 | + * |
|
325 | + * @param string $uid |
|
326 | + * @return string password |
|
327 | + */ |
|
328 | + protected function generateOneTimePassword($uid) { |
|
329 | + $password = $this->secureRandom->generate(16, ISecureRandom::CHAR_HUMAN_READABLE); |
|
330 | + $this->userPasswords[$uid] = $password; |
|
331 | + return $password; |
|
332 | + } |
|
333 | + |
|
334 | + /** |
|
335 | + * send encryption key passwords to the users by mail |
|
336 | + */ |
|
337 | + protected function sendPasswordsByMail() { |
|
338 | + $noMail = []; |
|
339 | + |
|
340 | + $this->output->writeln(''); |
|
341 | + $progress = new ProgressBar($this->output, count($this->userPasswords)); |
|
342 | + $progress->start(); |
|
343 | + |
|
344 | + foreach ($this->userPasswords as $uid => $password) { |
|
345 | + $progress->advance(); |
|
346 | + if (!empty($password)) { |
|
347 | + $recipient = $this->userManager->get($uid); |
|
348 | + if (!$recipient instanceof IUser) { |
|
349 | + continue; |
|
350 | + } |
|
351 | + |
|
352 | + $recipientDisplayName = $recipient->getDisplayName(); |
|
353 | + $to = $recipient->getEMailAddress(); |
|
354 | + |
|
355 | + if ($to === '' || $to === null) { |
|
356 | + $noMail[] = $uid; |
|
357 | + continue; |
|
358 | + } |
|
359 | + |
|
360 | + $l = $this->l10nFactory->get('encryption', $this->l10nFactory->getUserLanguage($recipient)); |
|
361 | + |
|
362 | + $template = $this->mailer->createEMailTemplate('encryption.encryptAllPassword', [ |
|
363 | + 'user' => $recipient->getUID(), |
|
364 | + 'password' => $password, |
|
365 | + ]); |
|
366 | + |
|
367 | + $template->setSubject($l->t('one-time password for server-side-encryption')); |
|
368 | + // 'Hey there,<br><br>The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.<br><br> |
|
369 | + // Please login to the web interface, go to the section "Basic encryption module" of your personal settings and update your encryption password by entering this password into the "Old log-in password" field and your current login-password.<br><br>' |
|
370 | + $template->addHeader(); |
|
371 | + $template->addHeading($l->t('Encryption password')); |
|
372 | + $template->addBodyText( |
|
373 | + $l->t('The administration enabled server-side-encryption. Your files were encrypted using the password <strong>%s</strong>.', [htmlspecialchars($password)]), |
|
374 | + $l->t('The administration enabled server-side-encryption. Your files were encrypted using the password "%s".', $password) |
|
375 | + ); |
|
376 | + $template->addBodyText( |
|
377 | + $l->t('Please login to the web interface, go to the "Security" section of your personal settings and update your encryption password by entering this password into the "Old login password" field and your current login password.') |
|
378 | + ); |
|
379 | + $template->addFooter(); |
|
380 | + |
|
381 | + // send it out now |
|
382 | + try { |
|
383 | + $message = $this->mailer->createMessage(); |
|
384 | + $message->setTo([$to => $recipientDisplayName]); |
|
385 | + $message->useTemplate($template); |
|
386 | + $message->setAutoSubmitted(AutoSubmitted::VALUE_AUTO_GENERATED); |
|
387 | + $this->mailer->send($message); |
|
388 | + } catch (\Exception $e) { |
|
389 | + $noMail[] = $uid; |
|
390 | + } |
|
391 | + } |
|
392 | + } |
|
393 | + |
|
394 | + $progress->finish(); |
|
395 | + |
|
396 | + if (empty($noMail)) { |
|
397 | + $this->output->writeln("\n\nPassword successfully send to all users"); |
|
398 | + } else { |
|
399 | + $table = new Table($this->output); |
|
400 | + $table->setHeaders(['Username', 'Private key password']); |
|
401 | + $this->output->writeln("\n\nCould not send password to following users:\n"); |
|
402 | + $rows = []; |
|
403 | + foreach ($noMail as $uid) { |
|
404 | + $rows[] = [$uid, $this->userPasswords[$uid]]; |
|
405 | + } |
|
406 | + $table->setRows($rows); |
|
407 | + $table->render(); |
|
408 | + } |
|
409 | + } |
|
410 | 410 | } |
@@ -35,21 +35,21 @@ |
||
35 | 35 | * Auto-generated migration step: Please modify to your needs! |
36 | 36 | */ |
37 | 37 | class Version21000Date20210119195004 extends SimpleMigrationStep { |
38 | - /** |
|
39 | - * @param IOutput $output |
|
40 | - * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` |
|
41 | - * @param array $options |
|
42 | - * @return null|ISchemaWrapper |
|
43 | - */ |
|
44 | - public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { |
|
45 | - /** @var ISchemaWrapper $schema */ |
|
46 | - $schema = $schemaClosure(); |
|
38 | + /** |
|
39 | + * @param IOutput $output |
|
40 | + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` |
|
41 | + * @param array $options |
|
42 | + * @return null|ISchemaWrapper |
|
43 | + */ |
|
44 | + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { |
|
45 | + /** @var ISchemaWrapper $schema */ |
|
46 | + $schema = $schemaClosure(); |
|
47 | 47 | |
48 | - $table = $schema->getTable('authtoken'); |
|
49 | - if ($table->hasIndex('authtoken_version_index')) { |
|
50 | - $table->dropIndex('authtoken_version_index'); |
|
51 | - } |
|
48 | + $table = $schema->getTable('authtoken'); |
|
49 | + if ($table->hasIndex('authtoken_version_index')) { |
|
50 | + $table->dropIndex('authtoken_version_index'); |
|
51 | + } |
|
52 | 52 | |
53 | - return $schema; |
|
54 | - } |
|
53 | + return $schema; |
|
54 | + } |
|
55 | 55 | } |
@@ -31,24 +31,24 @@ |
||
31 | 31 | use OCP\Migration\SimpleMigrationStep; |
32 | 32 | |
33 | 33 | class Version14000Date20180518120534 extends SimpleMigrationStep { |
34 | - public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { |
|
35 | - /** @var ISchemaWrapper $schema */ |
|
36 | - $schema = $schemaClosure(); |
|
34 | + public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) { |
|
35 | + /** @var ISchemaWrapper $schema */ |
|
36 | + $schema = $schemaClosure(); |
|
37 | 37 | |
38 | - $table = $schema->getTable('authtoken'); |
|
39 | - $table->addColumn('private_key', 'text', [ |
|
40 | - 'notnull' => false, |
|
41 | - ]); |
|
42 | - $table->addColumn('public_key', 'text', [ |
|
43 | - 'notnull' => false, |
|
44 | - ]); |
|
45 | - $table->addColumn('version', 'smallint', [ |
|
46 | - 'notnull' => true, |
|
47 | - 'default' => 1, |
|
48 | - 'unsigned' => true, |
|
49 | - ]); |
|
50 | - $table->addIndex(['uid'], 'authtoken_uid_index'); |
|
38 | + $table = $schema->getTable('authtoken'); |
|
39 | + $table->addColumn('private_key', 'text', [ |
|
40 | + 'notnull' => false, |
|
41 | + ]); |
|
42 | + $table->addColumn('public_key', 'text', [ |
|
43 | + 'notnull' => false, |
|
44 | + ]); |
|
45 | + $table->addColumn('version', 'smallint', [ |
|
46 | + 'notnull' => true, |
|
47 | + 'default' => 1, |
|
48 | + 'unsigned' => true, |
|
49 | + ]); |
|
50 | + $table->addIndex(['uid'], 'authtoken_uid_index'); |
|
51 | 51 | |
52 | - return $schema; |
|
53 | - } |
|
52 | + return $schema; |
|
53 | + } |
|
54 | 54 | } |
@@ -35,37 +35,37 @@ |
||
35 | 35 | * @see \OCP\AppFramework\Services\IInitialState |
36 | 36 | */ |
37 | 37 | interface IInitialStateService { |
38 | - /** |
|
39 | - * Allows an app to provide its initial state to the template system. |
|
40 | - * Use this if you know your initial state sill be used for example if |
|
41 | - * you are in the render function of you controller. |
|
42 | - * |
|
43 | - * @since 16.0.0 |
|
44 | - * |
|
45 | - * @param string $appName |
|
46 | - * @param string $key |
|
47 | - * @param bool|int|float|string|array|\JsonSerializable $data |
|
48 | - * |
|
49 | - * @deprecated 21 Use OCP\AppFramework\Services\IInitialState or OCP\AppFramework\Services\InitialStateProvider |
|
50 | - * @see \OCP\AppFramework\Services\IInitialState::provideInitialState() |
|
51 | - */ |
|
52 | - public function provideInitialState(string $appName, string $key, $data): void; |
|
38 | + /** |
|
39 | + * Allows an app to provide its initial state to the template system. |
|
40 | + * Use this if you know your initial state sill be used for example if |
|
41 | + * you are in the render function of you controller. |
|
42 | + * |
|
43 | + * @since 16.0.0 |
|
44 | + * |
|
45 | + * @param string $appName |
|
46 | + * @param string $key |
|
47 | + * @param bool|int|float|string|array|\JsonSerializable $data |
|
48 | + * |
|
49 | + * @deprecated 21 Use OCP\AppFramework\Services\IInitialState or OCP\AppFramework\Services\InitialStateProvider |
|
50 | + * @see \OCP\AppFramework\Services\IInitialState::provideInitialState() |
|
51 | + */ |
|
52 | + public function provideInitialState(string $appName, string $key, $data): void; |
|
53 | 53 | |
54 | - /** |
|
55 | - * Allows an app to provide its initial state via a lazy method. |
|
56 | - * This will call the closure when the template is being generated. |
|
57 | - * Use this if your app is injected into pages. Since then the render method |
|
58 | - * is not called explicitly. But we do not want to load the state on webdav |
|
59 | - * requests for example. |
|
60 | - * |
|
61 | - * @since 16.0.0 |
|
62 | - * |
|
63 | - * @param string $appName |
|
64 | - * @param string $key |
|
65 | - * @param Closure $closure returns a primitive or an object that implements JsonSerializable |
|
66 | - * |
|
67 | - * @deprecated 21 Use OCP\AppFramework\Services\IInitialState or OCP\AppFramework\Services\InitialStateProvider |
|
68 | - * @see \OCP\AppFramework\Services\IInitialState::provideLazyInitialState() |
|
69 | - */ |
|
70 | - public function provideLazyInitialState(string $appName, string $key, Closure $closure): void; |
|
54 | + /** |
|
55 | + * Allows an app to provide its initial state via a lazy method. |
|
56 | + * This will call the closure when the template is being generated. |
|
57 | + * Use this if your app is injected into pages. Since then the render method |
|
58 | + * is not called explicitly. But we do not want to load the state on webdav |
|
59 | + * requests for example. |
|
60 | + * |
|
61 | + * @since 16.0.0 |
|
62 | + * |
|
63 | + * @param string $appName |
|
64 | + * @param string $key |
|
65 | + * @param Closure $closure returns a primitive or an object that implements JsonSerializable |
|
66 | + * |
|
67 | + * @deprecated 21 Use OCP\AppFramework\Services\IInitialState or OCP\AppFramework\Services\InitialStateProvider |
|
68 | + * @see \OCP\AppFramework\Services\IInitialState::provideLazyInitialState() |
|
69 | + */ |
|
70 | + public function provideLazyInitialState(string $appName, string $key, Closure $closure): void; |
|
71 | 71 | } |
@@ -74,7 +74,7 @@ discard block |
||
74 | 74 | $qb = $this->dbc->getQueryBuilder(); |
75 | 75 | $qb->select(['id', 'principaluri']) |
76 | 76 | ->from('dav_shares') |
77 | - ->where($qb->expr()->like('principaluri', $qb->createNamedParameter(self::GROUP_PRINCIPAL_PREFIX . '%'))); |
|
77 | + ->where($qb->expr()->like('principaluri', $qb->createNamedParameter(self::GROUP_PRINCIPAL_PREFIX.'%'))); |
|
78 | 78 | |
79 | 79 | $updateQuery = $this->dbc->getQueryBuilder(); |
80 | 80 | $updateQuery->update('dav_shares') |
@@ -100,7 +100,7 @@ discard block |
||
100 | 100 | // + AND there are no ambivalent groups |
101 | 101 | |
102 | 102 | try { |
103 | - $fixedPrincipal = self::GROUP_PRINCIPAL_PREFIX . $encodedGid; |
|
103 | + $fixedPrincipal = self::GROUP_PRINCIPAL_PREFIX.$encodedGid; |
|
104 | 104 | $logParameters = [ |
105 | 105 | 'app' => 'core', |
106 | 106 | 'id' => $share['id'], |
@@ -21,89 +21,89 @@ |
||
21 | 21 | use function urlencode; |
22 | 22 | |
23 | 23 | class RepairDavShares implements IRepairStep { |
24 | - protected const GROUP_PRINCIPAL_PREFIX = 'principals/groups/'; |
|
24 | + protected const GROUP_PRINCIPAL_PREFIX = 'principals/groups/'; |
|
25 | 25 | |
26 | - /** @var bool */ |
|
27 | - private $hintInvalidShares = false; |
|
26 | + /** @var bool */ |
|
27 | + private $hintInvalidShares = false; |
|
28 | 28 | |
29 | - public function __construct( |
|
30 | - private IConfig $config, |
|
31 | - private IDBConnection $dbc, |
|
32 | - private IGroupManager $groupManager, |
|
33 | - private LoggerInterface $logger, |
|
34 | - ) { |
|
35 | - } |
|
29 | + public function __construct( |
|
30 | + private IConfig $config, |
|
31 | + private IDBConnection $dbc, |
|
32 | + private IGroupManager $groupManager, |
|
33 | + private LoggerInterface $logger, |
|
34 | + ) { |
|
35 | + } |
|
36 | 36 | |
37 | - /** |
|
38 | - * @inheritDoc |
|
39 | - */ |
|
40 | - public function getName() { |
|
41 | - return 'Repair DAV shares'; |
|
42 | - } |
|
37 | + /** |
|
38 | + * @inheritDoc |
|
39 | + */ |
|
40 | + public function getName() { |
|
41 | + return 'Repair DAV shares'; |
|
42 | + } |
|
43 | 43 | |
44 | - protected function repairUnencodedGroupShares() { |
|
45 | - $qb = $this->dbc->getQueryBuilder(); |
|
46 | - $qb->select(['id', 'principaluri']) |
|
47 | - ->from('dav_shares') |
|
48 | - ->where($qb->expr()->like('principaluri', $qb->createNamedParameter(self::GROUP_PRINCIPAL_PREFIX . '%'))); |
|
44 | + protected function repairUnencodedGroupShares() { |
|
45 | + $qb = $this->dbc->getQueryBuilder(); |
|
46 | + $qb->select(['id', 'principaluri']) |
|
47 | + ->from('dav_shares') |
|
48 | + ->where($qb->expr()->like('principaluri', $qb->createNamedParameter(self::GROUP_PRINCIPAL_PREFIX . '%'))); |
|
49 | 49 | |
50 | - $updateQuery = $this->dbc->getQueryBuilder(); |
|
51 | - $updateQuery->update('dav_shares') |
|
52 | - ->set('principaluri', $updateQuery->createParameter('updatedPrincipalUri')) |
|
53 | - ->where($updateQuery->expr()->eq('id', $updateQuery->createParameter('shareId'))); |
|
50 | + $updateQuery = $this->dbc->getQueryBuilder(); |
|
51 | + $updateQuery->update('dav_shares') |
|
52 | + ->set('principaluri', $updateQuery->createParameter('updatedPrincipalUri')) |
|
53 | + ->where($updateQuery->expr()->eq('id', $updateQuery->createParameter('shareId'))); |
|
54 | 54 | |
55 | - $statement = $qb->execute(); |
|
56 | - while ($share = $statement->fetch()) { |
|
57 | - $gid = substr($share['principaluri'], strlen(self::GROUP_PRINCIPAL_PREFIX)); |
|
58 | - $decodedGid = urldecode($gid); |
|
59 | - $encodedGid = urlencode($gid); |
|
60 | - if ($gid === $encodedGid |
|
61 | - || !$this->groupManager->groupExists($gid) |
|
62 | - || ($gid !== $decodedGid && $this->groupManager->groupExists($decodedGid)) |
|
63 | - ) { |
|
64 | - $this->hintInvalidShares = $this->hintInvalidShares || $gid !== $encodedGid; |
|
65 | - continue; |
|
66 | - } |
|
55 | + $statement = $qb->execute(); |
|
56 | + while ($share = $statement->fetch()) { |
|
57 | + $gid = substr($share['principaluri'], strlen(self::GROUP_PRINCIPAL_PREFIX)); |
|
58 | + $decodedGid = urldecode($gid); |
|
59 | + $encodedGid = urlencode($gid); |
|
60 | + if ($gid === $encodedGid |
|
61 | + || !$this->groupManager->groupExists($gid) |
|
62 | + || ($gid !== $decodedGid && $this->groupManager->groupExists($decodedGid)) |
|
63 | + ) { |
|
64 | + $this->hintInvalidShares = $this->hintInvalidShares || $gid !== $encodedGid; |
|
65 | + continue; |
|
66 | + } |
|
67 | 67 | |
68 | - // Repair when |
|
69 | - // + the group name needs encoding |
|
70 | - // + AND it is not encoded yet |
|
71 | - // + AND there are no ambivalent groups |
|
68 | + // Repair when |
|
69 | + // + the group name needs encoding |
|
70 | + // + AND it is not encoded yet |
|
71 | + // + AND there are no ambivalent groups |
|
72 | 72 | |
73 | - try { |
|
74 | - $fixedPrincipal = self::GROUP_PRINCIPAL_PREFIX . $encodedGid; |
|
75 | - $logParameters = [ |
|
76 | - 'app' => 'core', |
|
77 | - 'id' => $share['id'], |
|
78 | - 'old' => $share['principaluri'], |
|
79 | - 'new' => $fixedPrincipal, |
|
80 | - ]; |
|
81 | - $updateQuery |
|
82 | - ->setParameter('updatedPrincipalUri', $fixedPrincipal) |
|
83 | - ->setParameter('shareId', $share['id']) |
|
84 | - ->execute(); |
|
85 | - $this->logger->info('Repaired principal for dav share {id} from {old} to {new}', $logParameters); |
|
86 | - } catch (Exception $e) { |
|
87 | - $logParameters['message'] = $e->getMessage(); |
|
88 | - $logParameters['exception'] = $e; |
|
89 | - $this->logger->info('Could not repair principal for dav share {id} from {old} to {new}: {message}', $logParameters); |
|
90 | - } |
|
91 | - } |
|
92 | - return true; |
|
93 | - } |
|
73 | + try { |
|
74 | + $fixedPrincipal = self::GROUP_PRINCIPAL_PREFIX . $encodedGid; |
|
75 | + $logParameters = [ |
|
76 | + 'app' => 'core', |
|
77 | + 'id' => $share['id'], |
|
78 | + 'old' => $share['principaluri'], |
|
79 | + 'new' => $fixedPrincipal, |
|
80 | + ]; |
|
81 | + $updateQuery |
|
82 | + ->setParameter('updatedPrincipalUri', $fixedPrincipal) |
|
83 | + ->setParameter('shareId', $share['id']) |
|
84 | + ->execute(); |
|
85 | + $this->logger->info('Repaired principal for dav share {id} from {old} to {new}', $logParameters); |
|
86 | + } catch (Exception $e) { |
|
87 | + $logParameters['message'] = $e->getMessage(); |
|
88 | + $logParameters['exception'] = $e; |
|
89 | + $this->logger->info('Could not repair principal for dav share {id} from {old} to {new}: {message}', $logParameters); |
|
90 | + } |
|
91 | + } |
|
92 | + return true; |
|
93 | + } |
|
94 | 94 | |
95 | - /** |
|
96 | - * @inheritDoc |
|
97 | - */ |
|
98 | - public function run(IOutput $output) { |
|
99 | - $versionFromBeforeUpdate = $this->config->getSystemValueString('version', '0.0.0'); |
|
100 | - if (version_compare($versionFromBeforeUpdate, '20.0.8', '<') |
|
101 | - && $this->repairUnencodedGroupShares() |
|
102 | - ) { |
|
103 | - $output->info('Repaired DAV group shares'); |
|
104 | - if ($this->hintInvalidShares) { |
|
105 | - $output->info('Invalid shares might be left in the database, running "occ dav:remove-invalid-shares" can remove them.'); |
|
106 | - } |
|
107 | - } |
|
108 | - } |
|
95 | + /** |
|
96 | + * @inheritDoc |
|
97 | + */ |
|
98 | + public function run(IOutput $output) { |
|
99 | + $versionFromBeforeUpdate = $this->config->getSystemValueString('version', '0.0.0'); |
|
100 | + if (version_compare($versionFromBeforeUpdate, '20.0.8', '<') |
|
101 | + && $this->repairUnencodedGroupShares() |
|
102 | + ) { |
|
103 | + $output->info('Repaired DAV group shares'); |
|
104 | + if ($this->hintInvalidShares) { |
|
105 | + $output->info('Invalid shares might be left in the database, running "occ dav:remove-invalid-shares" can remove them.'); |
|
106 | + } |
|
107 | + } |
|
108 | + } |
|
109 | 109 | } |