1<?php
2/**
3 * Nextcloud - passman
4 *
5 * @copyright Copyright (c) 2016, Sander Brand (brantje@gmail.com)
6 * @copyright Copyright (c) 2016, Marcos Zuriaga Miguel (wolfi@wolfi.es)
7 * @license GNU AGPL version 3 or any later version
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24namespace OCA\Passman\Service;
25
26use OCA\Passman\Activity;
27use OCA\Passman\Db\Credential;
28use OCA\Passman\Db\CredentialMapper;
29use OCA\Passman\Db\SharingACL;
30use OCA\Passman\Db\SharingACLMapper;
31use OCP\AppFramework\Db\DoesNotExistException;
32use OCP\AppFramework\Db\Entity;
33use OCP\AppFramework\Db\MultipleObjectsReturnedException;
34use OCP\IConfig;
35
36
37class CredentialService {
38
39	private CredentialMapper $credentialMapper;
40	private SharingACLMapper $sharingACL;
41	private ActivityService $activityService;
42	private ShareService $shareService;
43	private EncryptService $encryptService;
44	private CredentialRevisionService $credentialRevisionService;
45	private $server_key;
46
47	public function __construct(CredentialMapper          $credentialMapper,
48	                            SharingACLMapper          $sharingACL,
49	                            ActivityService           $activityService,
50	                            ShareService              $shareService,
51	                            EncryptService            $encryptService,
52	                            CredentialRevisionService $credentialRevisionService,
53	                            IConfig                   $config) {
54		$this->credentialMapper = $credentialMapper;
55		$this->sharingACL = $sharingACL;
56		$this->activityService = $activityService;
57		$this->shareService = $shareService;
58		$this->encryptService = $encryptService;
59		$this->credentialRevisionService = $credentialRevisionService;
60		$this->server_key = $config->getSystemValue('passwordsalt', '');
61	}
62
63	/**
64	 * Create a new credential
65	 *
66	 * @param array $credential
67	 * @return Credential
68	 * @throws \Exception
69	 */
70	public function createCredential(array $credential) {
71		$credential = $this->encryptService->encryptCredential($credential);
72		return $this->credentialMapper->create($credential);
73	}
74
75	/**
76	 * Update credential
77	 *
78	 * @param array $credential
79	 * @param false $useRawUser
80	 * @return Credential|Entity
81	 * @throws DoesNotExistException
82	 * @throws MultipleObjectsReturnedException
83	 */
84	public function updateCredential(array $credential, $useRawUser = false) {
85		$credential = $this->encryptService->encryptCredential($credential);
86		return $this->credentialMapper->updateCredential($credential, $useRawUser);
87	}
88
89	/**
90	 * Update credential
91	 *
92	 * @param Credential $credential
93	 * @return Credential|Entity
94	 * @throws DoesNotExistException
95	 * @throws MultipleObjectsReturnedException
96	 */
97	public function upd(Credential $credential) {
98		$credential = $this->encryptService->encryptCredential($credential);
99		return $this->credentialMapper->updateCredential($credential->jsonSerialize(), false);
100	}
101
102	/**
103	 * Delete credential
104	 *
105	 * @param Credential $credential
106	 * @return Entity
107	 */
108	public function deleteCredential(Credential $credential) {
109		$this->shareService->unshareCredential($credential->getGuid());
110		return $this->credentialMapper->deleteCredential($credential);
111	}
112
113	/**
114	 * Delete leftovers from a credential
115	 * @param Credential $credential
116	 * @throws \Exception
117	 */
118	public function deleteCredentialParts(Credential $credential, $userId) {
119		$this->activityService->add(
120			'item_destroyed_self', array($credential->getLabel()),
121			'', array(),
122			'', $userId, Activity::TYPE_ITEM_ACTION);
123		$this->shareService->unshareCredential($credential->getGuid());
124		foreach ($this->credentialRevisionService->getRevisions($credential->getId()) as $revision) {
125			$id = $revision['revision_id'];
126			if (isset($id)) {
127				$this->credentialRevisionService->deleteRevision($id, $userId);
128			}
129		}
130	}
131
132	/**
133	 * Get credentials by vault id
134	 *
135	 * @param int $vault_id
136	 * @param string $user_id
137	 * @return Entity[]
138	 * @throws \Exception
139	 */
140	public function getCredentialsByVaultId(int $vault_id, string $user_id) {
141		$credentials = $this->credentialMapper->getCredentialsByVaultId($vault_id, $user_id);
142		foreach ($credentials as $index => $credential) {
143			$credentials[$index] = $this->encryptService->decryptCredential($credential);
144		}
145		return $credentials;
146	}
147
148	/**
149	 * Get a random credential from given vault
150	 *
151	 * @param int $vault_id
152	 * @param string $user_id
153	 * @return mixed
154	 */
155	public function getRandomCredentialByVaultId(int $vault_id, string $user_id) {
156		$credentials = $this->credentialMapper->getRandomCredentialByVaultId($vault_id, $user_id);
157		foreach ($credentials as $index => $credential) {
158			$credentials[$index] = $this->encryptService->decryptCredential($credential);
159		}
160		return array_pop($credentials);
161	}
162
163	/**
164	 * Get expired credentials.
165	 *
166	 * @param int $timestamp
167	 * @return Entity[]
168	 * @throws \Exception
169	 */
170	public function getExpiredCredentials(int $timestamp) {
171		$credentials = $this->credentialMapper->getExpiredCredentials($timestamp);
172		foreach ($credentials as $index => $credential) {
173			$credentials[$index] = $this->encryptService->decryptCredential($credential);
174		}
175		return $credentials;
176	}
177
178	/**
179	 * Get a single credential.
180	 *
181	 * @param int $credential_id
182	 * @param string $user_id
183	 * @return array|Credential
184	 * @throws DoesNotExistException
185	 * @throws MultipleObjectsReturnedException
186	 */
187	public function getCredentialById(int $credential_id, ?string $user_id) {
188		$credential = $this->credentialMapper->getCredentialById($credential_id);
189		if ($credential->getUserId() === $user_id) {
190			return $this->encryptService->decryptCredential($credential);
191		} else {
192			$acl = $this->sharingACL->getItemACL($user_id, $credential->getGuid());
193			if ($acl->hasPermission(SharingACL::READ)) {
194				return $this->encryptService->decryptCredential($credential);
195			} else {
196				throw new DoesNotExistException("Did expect one result but found none when executing");
197			}
198		}
199	}
200
201	/**
202	 * Get credential label by credential id.
203	 *
204	 * @param int $credential_id
205	 * @return array|Credential
206	 * @throws DoesNotExistException
207	 * @throws MultipleObjectsReturnedException
208	 */
209	public function getCredentialLabelById(int $credential_id) {
210		$credential = $this->credentialMapper->getCredentialLabelById($credential_id);
211		return $this->encryptService->decryptCredential($credential);
212	}
213
214	/**
215	 * Get credential by guid
216	 *
217	 * @param string $credential_guid
218	 * @param string|null $user_id
219	 * @return array|Credential
220	 * @throws DoesNotExistException
221	 * @throws MultipleObjectsReturnedException
222	 */
223	public function getCredentialByGUID(string $credential_guid, string $user_id = null) {
224		$credential = $this->credentialMapper->getCredentialByGUID($credential_guid, $user_id);
225		return $this->encryptService->decryptCredential($credential);
226	}
227}
228