cleanup and add user names services

sync2
Laurent 11 months ago
parent bd7ec4dcc9
commit cef665f166
  1. 1
      LeStorage/Codables/ApiCall.swift
  2. 1
      LeStorage/Codables/DataAccess.swift
  3. 1
      LeStorage/Codables/DataLog.swift
  4. 1
      LeStorage/Codables/FailedAPICall.swift
  5. 1
      LeStorage/Codables/GetSyncData.swift
  6. 1
      LeStorage/Codables/Log.swift
  7. 9
      LeStorage/Services.swift
  8. 7
      LeStorage/Storable.swift
  9. 6
      LeStorage/Store.swift
  10. 60
      LeStorage/StoreCenter.swift
  11. 2
      LeStorageTests/CollectionsTests.swift
  12. 2
      LeStorageTests/IdentifiableTests.swift
  13. 3
      LeStorageTests/StoredCollectionTests.swift

@ -17,7 +17,6 @@ class ApiCall<T: Storable>: ModelObject, Storable, SomeCall {
static func resourceName() -> String { return "apicalls_" + T.resourceName() } static func resourceName() -> String { return "apicalls_" + T.resourceName() }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
var id: String = Store.randomId() var id: String = Store.randomId()

@ -11,7 +11,6 @@ class DataAccess: SyncedModelObject, SyncedStorable {
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func resourceName() -> String { return "data-access" } static func resourceName() -> String { return "data-access" }
static func filterByStoreIdentifier() -> Bool { return false }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
var id: String = Store.randomId() var id: String = Store.randomId()

@ -11,7 +11,6 @@ class DataLog: ModelObject, Storable {
static func resourceName() -> String { return "data-logs" } static func resourceName() -> String { return "data-logs" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
var id: String = Store.randomId() var id: String = Store.randomId()

@ -11,7 +11,6 @@ class FailedAPICall: SyncedModelObject, SyncedStorable {
static func resourceName() -> String { return "failed-api-calls" } static func resourceName() -> String { return "failed-api-calls" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
var id: String = Store.randomId() var id: String = Store.randomId()

@ -9,7 +9,6 @@ import Foundation
class GetSyncData: SyncedModelObject, SyncedStorable, URLParameterConvertible { class GetSyncData: SyncedModelObject, SyncedStorable, URLParameterConvertible {
static func filterByStoreIdentifier() -> Bool { return false }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func resourceName() -> String { static func resourceName() -> String {

@ -11,7 +11,6 @@ class Log: SyncedModelObject, SyncedStorable {
static func resourceName() -> String { return "logs" } static func resourceName() -> String { return "logs" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
static func filterByStoreIdentifier() -> Bool { return false }
static func relationships() -> [Relationship] { return [] } static func relationships() -> [Relationship] { return [] }
var id: String = Store.randomId() var id: String = Store.randomId()

@ -34,8 +34,8 @@ let postDeviceTokenCall: ServiceCall = ServiceCall(
path: "device-token/", method: .post, requiresToken: true) path: "device-token/", method: .post, requiresToken: true)
let getUserDataAccessCall: ServiceCall = ServiceCall( let getUserDataAccessCall: ServiceCall = ServiceCall(
path: "user-data-access/", method: .get, requiresToken: true) path: "user-data-access/", method: .get, requiresToken: true)
let userSearchCall: ServiceCall = ServiceCall( let userNamesCall: ServiceCall = ServiceCall(
path: "users-search/", method: .get, requiresToken: true) path: "user-names/", method: .get, requiresToken: true)
/// A class used to send HTTP request to the django server /// A class used to send HTTP request to the django server
public class Services { public class Services {
@ -463,9 +463,8 @@ public class Services {
// MARK: - Others // MARK: - Others
public func searchUsers(string: String) async throws -> [ShortUser] { public func getUserNames() async throws -> [ShortUser] {
let baseRequest = try self._baseRequest(call: userSearchCall, getArguments: ["search": string]) return try await self._runRequest(serviceCall: userNamesCall)
return try await self._runRequest(baseRequest)
} }
// MARK: - Authentication // MARK: - Authentication

@ -17,11 +17,6 @@ public protocol Storable: Codable, Identifiable, NSObjectProtocol {
/// Also used as the name of the local file /// Also used as the name of the local file
static func resourceName() -> String static func resourceName() -> String
/// This method is only used if the instance store uses an identifier
/// This method should return true if the resources need to get filtered using the store identifier when performing a GET
/// Returning false won't filter the resources when performing a GET
static func filterByStoreIdentifier() -> Bool
/// A method that deletes the local dependencies of the resource /// A method that deletes the local dependencies of the resource
/// Mimics the behavior the cascading delete on the django server /// Mimics the behavior the cascading delete on the django server
/// Typically when we delete a resource, we automatically delete items that depends on it, /// Typically when we delete a resource, we automatically delete items that depends on it,
@ -42,7 +37,7 @@ extension Storable {
} }
/// Returns a string id for the instance /// Returns a string id for the instance
var stringId: String { public var stringId: String {
switch self.id { switch self.id {
case let sp as any StringProtocol: case let sp as any StringProtocol:
return String(sp) return String(sp)

@ -243,8 +243,6 @@ final public class Store {
count += collection.referenceCount(type: type, id: id) count += collection.referenceCount(type: type, id: id)
} }
return count return count
// let collection: StoredCollection<T> = try self.collection()
// collection.revokeByStringIdNoSync(id)
} }
// MARK: - Write // MARK: - Write
@ -292,8 +290,8 @@ final public class Store {
/// Retrieves all the items on the server /// Retrieves all the items on the server
public func getItems<T: SyncedStorable>() async throws -> [T] { public func getItems<T: SyncedStorable>() async throws -> [T] {
if T.filterByStoreIdentifier() { if let identifier = self.identifier {
return try await StoreCenter.main.getItems(identifier: self.identifier) return try await StoreCenter.main.getItems(identifier: identifier)
} else { } else {
return try await StoreCenter.main.getItems() return try await StoreCenter.main.getItems()
} }

@ -822,39 +822,55 @@ public class StoreCenter {
// MARK: - Data Access // MARK: - Data Access
public func giveUserAccess<T: SyncedStorable>(_ user: String, data: T) throws { // public func giveUserAccess<T: SyncedStorable>(_ user: String, data: T) throws {
// guard let dataAccessCollection = self._dataAccess else {
// throw LeStorageError.dataAccessCollectionNotDefined
// }
// guard let userId = self.userId else {
// throw LeStorageError.cantCreateDataAccessBecauseUserIdIsNil
// }
// let collection: StoredCollection<T> = try Store.main.collection()
// guard collection.findById(data.id) != nil else {
// throw LeStorageError.cantCreateDataAccessBecauseNotInMainStore
// }
//
// if let dataAccess = dataAccessCollection.first(where: { $0.modelId == data.stringId }) {
// dataAccess.sharedWith.append(user)
// dataAccessCollection.addOrUpdate(instance: dataAccess)
// } else {
// let dataAccess = DataAccess(owner: userId, sharedWith: [user], modelName: String(describing: type(of: data)), modelId: data.stringId)
// dataAccessCollection.addOrUpdate(instance: dataAccess)
// }
// }
public func authorizedUsers(for modelId: String) -> [String] {
guard let dataAccessCollection = self._dataAccess else { guard let dataAccessCollection = self._dataAccess else {
throw LeStorageError.dataAccessCollectionNotDefined return []
}
guard let userId = self.userId else {
throw LeStorageError.cantCreateDataAccessBecauseUserIdIsNil
} }
let collection: StoredCollection<T> = try Store.main.collection() if let dataAccess = dataAccessCollection.first(where: { $0.modelId == modelId }) {
guard collection.findById(data.id) != nil else { return dataAccess.sharedWith
throw LeStorageError.cantCreateDataAccessBecauseNotInMainStore
}
if let dataAccess = dataAccessCollection.first(where: { $0.modelId == data.stringId }) {
dataAccess.sharedWith.append(user)
dataAccessCollection.addOrUpdate(instance: dataAccess)
} else {
let dataAccess = DataAccess(owner: userId, sharedWith: [user], modelName: String(describing: type(of: data)), modelId: data.stringId)
dataAccessCollection.addOrUpdate(instance: dataAccess)
} }
return []
} }
public func removeUserAccess<T: SyncedStorable>(_ user: String, data: T) { public func setAuthorizedUsers<T: SyncedStorable>(for instance: T, users: [String]) throws {
guard let dataAccessCollection = self._dataAccess else { guard let dataAccessCollection = self._dataAccess else {
return return
} }
if let dataAccess = dataAccessCollection.first(where: { $0.modelId == data.stringId }) { guard let userId = self.userId else {
dataAccess.sharedWith.removeAll(where: { $0 == user }) throw LeStorageError.cantCreateDataAccessBecauseUserIdIsNil
}
if dataAccess.sharedWith.isEmpty {
if let dataAccess = dataAccessCollection.first(where: { $0.modelId == instance.stringId }) {
if users.isEmpty {
dataAccessCollection.delete(instance: dataAccess) dataAccessCollection.delete(instance: dataAccess)
} else { } else {
dataAccessCollection.addOrUpdate(instance: dataAccess) dataAccess.sharedWith.removeAll()
dataAccess.sharedWith = users
} }
} else {
let dataAccess = DataAccess(owner: userId, sharedWith: users, modelName: String(describing: type(of: instance)), modelId: instance.stringId)
dataAccessCollection.addOrUpdate(instance: dataAccess)
} }
} }

@ -13,7 +13,6 @@ class Car: ModelObject, Storable {
var id: String = Store.randomId() var id: String = Store.randomId()
static func resourceName() -> String { return "car" } static func resourceName() -> String { return "car" }
static func filterByStoreIdentifier() -> Bool { return false }
static var relationshipNames: [String] = [] static var relationshipNames: [String] = []
} }
@ -24,7 +23,6 @@ class Boat: ModelObject, SyncedStorable {
static func tokenExemptedMethods() -> [LeStorage.HTTPMethod] { return [] } static func tokenExemptedMethods() -> [LeStorage.HTTPMethod] { return [] }
static func resourceName() -> String { return "boat" } static func resourceName() -> String { return "boat" }
static func filterByStoreIdentifier() -> Bool { return false }
static var relationshipNames: [String] = [] static var relationshipNames: [String] = []
var storeId: String? { return nil } var storeId: String? { return nil }

@ -11,7 +11,6 @@ import LeStorage
class IntObject: ModelObject, Storable { class IntObject: ModelObject, Storable {
static func resourceName() -> String { "int" } static func resourceName() -> String { "int" }
static func tokenExemptedMethods() -> [LeStorage.HTTPMethod] { [] } static func tokenExemptedMethods() -> [LeStorage.HTTPMethod] { [] }
static func filterByStoreIdentifier() -> Bool { false }
static var relationshipNames: [String] = [] static var relationshipNames: [String] = []
var id: Int var id: Int
@ -26,7 +25,6 @@ class IntObject: ModelObject, Storable {
class StringObject: ModelObject, Storable { class StringObject: ModelObject, Storable {
static func resourceName() -> String { "string" } static func resourceName() -> String { "string" }
static func tokenExemptedMethods() -> [LeStorage.HTTPMethod] { [] } static func tokenExemptedMethods() -> [LeStorage.HTTPMethod] { [] }
static func filterByStoreIdentifier() -> Bool { false }
static var relationshipNames: [String] = [] static var relationshipNames: [String] = []
var id: String var id: String

@ -100,9 +100,6 @@ class StoredCollectionTests: XCTestCase {
// Mock Storable for testing purposes // Mock Storable for testing purposes
class MockStorable: ModelObject, Storable { class MockStorable: ModelObject, Storable {
static func filterByStoreIdentifier() -> Bool {
return false
}
var id: String = Store.randomId() var id: String = Store.randomId()
var name: String var name: String

Loading…
Cancel
Save