NCManageDatabase+Capabilities.swift 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. //
  2. // NCManageDatabase+Capabilities.swift
  3. // Nextcloud
  4. //
  5. // Created by Marino Faggiana on 29/05/23.
  6. // Copyright © 2023 Marino Faggiana. All rights reserved.
  7. //
  8. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. import Foundation
  24. import UIKit
  25. import RealmSwift
  26. import NextcloudKit
  27. class tableCapabilities: Object {
  28. @objc dynamic var account = ""
  29. @objc dynamic var jsondata: Data?
  30. override static func primaryKey() -> String {
  31. return "account"
  32. }
  33. }
  34. extension NCManageDatabase {
  35. func addCapabilitiesJSon(_ data: Data, account: String) {
  36. do {
  37. let realm = try Realm()
  38. try realm.write {
  39. let addObject = tableCapabilities()
  40. addObject.account = account
  41. addObject.jsondata = data
  42. realm.add(addObject, update: .all)
  43. }
  44. } catch let error {
  45. NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not write to database: \(error)")
  46. }
  47. }
  48. func getCapabilities(account: String) -> Data? {
  49. do {
  50. let realm = try Realm()
  51. realm.refresh()
  52. guard let result = realm.objects(tableCapabilities.self).filter("account == %@", account).first else { return nil }
  53. return result.jsondata
  54. } catch let error as NSError {
  55. NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
  56. }
  57. return nil
  58. }
  59. @discardableResult
  60. func setCapabilities(account: String, data: Data? = nil) -> NCCapabilities.Capabilities? {
  61. let jsonData: Data?
  62. struct CapabilityNextcloud: Codable {
  63. struct Ocs: Codable {
  64. let meta: Meta
  65. let data: Data
  66. struct Meta: Codable {
  67. let status: String?
  68. let message: String?
  69. let statuscode: Int?
  70. }
  71. struct Data: Codable {
  72. let version: Version
  73. let capabilities: Capabilities
  74. struct Version: Codable {
  75. let string: String
  76. let major: Int
  77. }
  78. struct Capabilities: Codable {
  79. let filessharing: FilesSharing?
  80. let theming: Theming?
  81. let endtoendencryption: EndToEndEncryption?
  82. let richdocuments: RichDocuments?
  83. let activity: Activity?
  84. let notifications: Notifications?
  85. let files: Files?
  86. let userstatus: UserStatus?
  87. let external: External?
  88. let groupfolders: GroupFolders?
  89. let securityguard: SecurityGuard?
  90. let assistant: Assistant?
  91. enum CodingKeys: String, CodingKey {
  92. case filessharing = "files_sharing"
  93. case theming
  94. case endtoendencryption = "end-to-end-encryption"
  95. case richdocuments, activity, notifications, files
  96. case userstatus = "user_status"
  97. case external, groupfolders
  98. case securityguard = "security_guard"
  99. case assistant
  100. }
  101. struct FilesSharing: Codable {
  102. let apienabled: Bool?
  103. let groupsharing: Bool?
  104. let resharing: Bool?
  105. let defaultpermissions: Int?
  106. let ncpublic: Public?
  107. enum CodingKeys: String, CodingKey {
  108. case apienabled = "api_enabled"
  109. case groupsharing = "group_sharing"
  110. case resharing
  111. case defaultpermissions = "default_permissions"
  112. case ncpublic = "public"
  113. }
  114. struct Public: Codable {
  115. let enabled: Bool
  116. let upload: Bool?
  117. let password: Password?
  118. let sendmail: Bool?
  119. let uploadfilesdrop: Bool?
  120. let multiplelinks: Bool?
  121. let expiredate: ExpireDate?
  122. let expiredateinternal: ExpireDate?
  123. let expiredateremote: ExpireDate?
  124. enum CodingKeys: String, CodingKey {
  125. case upload, enabled, password
  126. case sendmail = "send_mail"
  127. case uploadfilesdrop = "upload_files_drop"
  128. case multiplelinks = "multiple_links"
  129. case expiredate = "expire_date"
  130. case expiredateinternal = "expire_date_internal"
  131. case expiredateremote = "expire_date_remote"
  132. }
  133. struct Password: Codable {
  134. let enforced: Bool?
  135. let askForOptionalPassword: Bool?
  136. }
  137. struct ExpireDate: Codable {
  138. let enforced: Bool?
  139. let days: Int?
  140. }
  141. }
  142. }
  143. struct Theming: Codable {
  144. let color: String?
  145. let colorelement: String?
  146. let colortext: String?
  147. let colorelementbright: String?
  148. let backgrounddefault: Bool?
  149. let backgroundplain: Bool?
  150. let colorelementdark: String?
  151. let name: String?
  152. let slogan: String?
  153. let url: String?
  154. let logo: String?
  155. let background: String?
  156. let logoheader: String?
  157. let favicon: String?
  158. enum CodingKeys: String, CodingKey {
  159. case color
  160. case colorelement = "color-element"
  161. case colortext = "color-text"
  162. case colorelementbright = "color-element-bright"
  163. case backgrounddefault = "background-default"
  164. case backgroundplain = "background-plain"
  165. case colorelementdark = "color-element-dark"
  166. case name, slogan, url, logo, background, logoheader, favicon
  167. }
  168. }
  169. struct EndToEndEncryption: Codable {
  170. let enabled: Bool?
  171. let apiversion: String?
  172. let keysexist: Bool?
  173. enum CodingKeys: String, CodingKey {
  174. case enabled
  175. case apiversion = "api-version"
  176. case keysexist = "keys-exist"
  177. }
  178. }
  179. struct RichDocuments: Codable {
  180. let mimetypes: [String]?
  181. let directediting: Bool?
  182. enum CodingKeys: String, CodingKey {
  183. case mimetypes
  184. case directediting = "direct_editing"
  185. }
  186. }
  187. struct Activity: Codable {
  188. let apiv2: [String]?
  189. }
  190. struct Notifications: Codable {
  191. let ocsendpoints: [String]?
  192. enum CodingKeys: String, CodingKey {
  193. case ocsendpoints = "ocs-endpoints"
  194. }
  195. }
  196. struct Files: Codable {
  197. let undelete: Bool?
  198. let locking: String?
  199. let comments: Bool?
  200. let versioning: Bool?
  201. let directEditing: DirectEditing?
  202. let bigfilechunking: Bool?
  203. let versiondeletion: Bool?
  204. let versionlabeling: Bool?
  205. let forbiddenFileNames: [String]?
  206. let forbiddenFileNameBasenames: [String]?
  207. let forbiddenFileNameCharacters: [String]?
  208. let forbiddenFileNameExtensions: [String]?
  209. enum CodingKeys: String, CodingKey {
  210. case undelete, locking, comments, versioning, directEditing, bigfilechunking
  211. case versiondeletion = "version_deletion"
  212. case versionlabeling = "version_labeling"
  213. case forbiddenFileNames = "forbidden_filenames"
  214. case forbiddenFileNameBasenames = "forbidden_filename_basenames"
  215. case forbiddenFileNameCharacters = "forbidden_filename_characters"
  216. case forbiddenFileNameExtensions = "forbidden_filename_extensions"
  217. }
  218. struct DirectEditing: Codable {
  219. let url: String?
  220. let etag: String?
  221. let supportsFileId: Bool?
  222. }
  223. }
  224. struct UserStatus: Codable {
  225. let enabled: Bool?
  226. let restore: Bool?
  227. let supportsemoji: Bool?
  228. enum CodingKeys: String, CodingKey {
  229. case enabled, restore
  230. case supportsemoji = "supports_emoji"
  231. }
  232. }
  233. struct External: Codable {
  234. let v1: [String]?
  235. }
  236. struct GroupFolders: Codable {
  237. let hasGroupFolders: Bool?
  238. }
  239. struct SecurityGuard: Codable {
  240. let diagnostics: Bool?
  241. }
  242. struct Assistant: Codable {
  243. let enabled: Bool?
  244. let version: String?
  245. }
  246. }
  247. }
  248. }
  249. let ocs: Ocs
  250. }
  251. if let data {
  252. jsonData = data
  253. } else {
  254. do {
  255. let realm = try Realm()
  256. guard let result = realm.objects(tableCapabilities.self).filter("account == %@", account).first,
  257. let data = result.jsondata else {
  258. return nil
  259. }
  260. jsonData = data
  261. } catch let error as NSError {
  262. NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
  263. return nil
  264. }
  265. }
  266. guard let jsonData = jsonData else {
  267. return nil
  268. }
  269. do {
  270. let json = try JSONDecoder().decode(CapabilityNextcloud.self, from: jsonData)
  271. let data = json.ocs.data
  272. let capabilities = NCCapabilities.Capabilities()
  273. capabilities.capabilityServerVersion = data.version.string
  274. capabilities.capabilityServerVersionMajor = data.version.major
  275. if capabilities.capabilityServerVersionMajor > 0 {
  276. NextcloudKit.shared.updateSession(account: account, nextcloudVersion: capabilities.capabilityServerVersionMajor)
  277. }
  278. capabilities.capabilityFileSharingApiEnabled = data.capabilities.filessharing?.apienabled ?? false
  279. capabilities.capabilityFileSharingDefaultPermission = data.capabilities.filessharing?.defaultpermissions ?? 0
  280. capabilities.capabilityFileSharingPubPasswdEnforced = data.capabilities.filessharing?.ncpublic?.password?.enforced ?? false
  281. capabilities.capabilityFileSharingPubExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredate?.enforced ?? false
  282. capabilities.capabilityFileSharingPubExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredate?.days ?? 0
  283. capabilities.capabilityFileSharingInternalExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredateinternal?.enforced ?? false
  284. capabilities.capabilityFileSharingInternalExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredateinternal?.days ?? 0
  285. capabilities.capabilityFileSharingRemoteExpireDateEnforced = data.capabilities.filessharing?.ncpublic?.expiredateremote?.enforced ?? false
  286. capabilities.capabilityFileSharingRemoteExpireDateDays = data.capabilities.filessharing?.ncpublic?.expiredateremote?.days ?? 0
  287. capabilities.capabilityThemingColor = data.capabilities.theming?.color ?? ""
  288. capabilities.capabilityThemingColorElement = data.capabilities.theming?.colorelement ?? ""
  289. capabilities.capabilityThemingColorText = data.capabilities.theming?.colortext ?? ""
  290. capabilities.capabilityThemingName = data.capabilities.theming?.name ?? ""
  291. capabilities.capabilityThemingSlogan = data.capabilities.theming?.slogan ?? ""
  292. capabilities.capabilityE2EEEnabled = data.capabilities.endtoendencryption?.enabled ?? false
  293. capabilities.capabilityE2EEApiVersion = data.capabilities.endtoendencryption?.apiversion ?? ""
  294. capabilities.capabilityRichDocumentsEnabled = json.ocs.data.capabilities.richdocuments?.directediting ?? false
  295. capabilities.capabilityRichDocumentsMimetypes.removeAll()
  296. if let mimetypes = data.capabilities.richdocuments?.mimetypes {
  297. for mimetype in mimetypes {
  298. capabilities.capabilityRichDocumentsMimetypes.append(mimetype)
  299. }
  300. }
  301. capabilities.capabilityAssistantEnabled = data.capabilities.assistant?.enabled ?? false
  302. capabilities.capabilityActivity.removeAll()
  303. if let activities = data.capabilities.activity?.apiv2 {
  304. for activity in activities {
  305. capabilities.capabilityActivity.append(activity)
  306. }
  307. }
  308. capabilities.capabilityNotification.removeAll()
  309. if let notifications = data.capabilities.notifications?.ocsendpoints {
  310. for notification in notifications {
  311. capabilities.capabilityNotification.append(notification)
  312. }
  313. }
  314. capabilities.capabilityFilesUndelete = data.capabilities.files?.undelete ?? false
  315. capabilities.capabilityFilesLockVersion = data.capabilities.files?.locking ?? ""
  316. capabilities.capabilityFilesComments = data.capabilities.files?.comments ?? false
  317. capabilities.capabilityFilesBigfilechunking = data.capabilities.files?.bigfilechunking ?? false
  318. capabilities.capabilityUserStatusEnabled = data.capabilities.userstatus?.enabled ?? false
  319. if data.capabilities.external != nil {
  320. capabilities.capabilityExternalSites = true
  321. }
  322. capabilities.capabilityGroupfoldersEnabled = data.capabilities.groupfolders?.hasGroupFolders ?? false
  323. if capabilities.capabilityServerVersionMajor >= NCGlobal.shared.nextcloudVersion28 {
  324. capabilities.isLivePhotoServerAvailable = true
  325. }
  326. capabilities.capabilitySecurityGuardDiagnostics = data.capabilities.securityguard?.diagnostics ?? false
  327. capabilities.capabilityForbiddenFileNames = data.capabilities.files?.forbiddenFileNames ?? []
  328. capabilities.capabilityForbiddenFileNameBasenames = data.capabilities.files?.forbiddenFileNameBasenames ?? []
  329. capabilities.capabilityForbiddenFileNameCharacters = data.capabilities.files?.forbiddenFileNameCharacters ?? []
  330. capabilities.capabilityForbiddenFileNameExtensions = data.capabilities.files?.forbiddenFileNameExtensions ?? []
  331. NCCapabilities.shared.appendCapabilities(account: account, capabilities: capabilities)
  332. return capabilities
  333. } catch let error as NSError {
  334. NextcloudKit.shared.nkCommonInstance.writeLog("[ERROR] Could not access database: \(error)")
  335. return nil
  336. }
  337. }
  338. }