Skip to content

fix: use default ACL on newly created ParseObjects #284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

### main

[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.2.5...main)
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.2.6...main)
* _Contributing to this repo? Add info about your change here to be included in the next release_

### 2.2.6
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.2.5...2.2.6)

__Fixes__
- Use default ACL automatically on newley created ParseObject's if a default ACL is available ([#283](https://github.com/parse-community/Parse-Swift/pull/283)), thanks to [Corey Baker](https://github.com/cbaker6).

### 2.2.5
[Full Changelog](https://github.com/parse-community/Parse-Swift/compare/2.2.4...2.2.5)

Expand Down
8 changes: 8 additions & 0 deletions ParseSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@
70170A4E2656EBA50070C905 /* ParseAnalyticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70170A4D2656EBA50070C905 /* ParseAnalyticsTests.swift */; };
70170A4F2656EBA50070C905 /* ParseAnalyticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70170A4D2656EBA50070C905 /* ParseAnalyticsTests.swift */; };
70170A502656EBA50070C905 /* ParseAnalyticsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 70170A4D2656EBA50070C905 /* ParseAnalyticsTests.swift */; };
7023800F2747FCCD00EFC443 /* ExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7023800E2747FCCD00EFC443 /* ExtensionsTests.swift */; };
702380102747FCCD00EFC443 /* ExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7023800E2747FCCD00EFC443 /* ExtensionsTests.swift */; };
702380112747FCCD00EFC443 /* ExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7023800E2747FCCD00EFC443 /* ExtensionsTests.swift */; };
7028373426BD8883007688C9 /* ParseObject+async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7028373326BD8883007688C9 /* ParseObject+async.swift */; };
7028373526BD8883007688C9 /* ParseObject+async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7028373326BD8883007688C9 /* ParseObject+async.swift */; };
7028373626BD8883007688C9 /* ParseObject+async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7028373326BD8883007688C9 /* ParseObject+async.swift */; };
Expand Down Expand Up @@ -828,6 +831,7 @@
70170A432656B02C0070C905 /* ParseAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseAnalytics.swift; sourceTree = "<group>"; };
70170A482656E2FE0070C905 /* ParseAnalytics+combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseAnalytics+combine.swift"; sourceTree = "<group>"; };
70170A4D2656EBA50070C905 /* ParseAnalyticsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseAnalyticsTests.swift; sourceTree = "<group>"; };
7023800E2747FCCD00EFC443 /* ExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionsTests.swift; sourceTree = "<group>"; };
7028373326BD8883007688C9 /* ParseObject+async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseObject+async.swift"; sourceTree = "<group>"; };
7028373826BD8C89007688C9 /* ParseUser+async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseUser+async.swift"; sourceTree = "<group>"; };
7033ECB025584A83009770F3 /* TestHostTV.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestHostTV.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -1139,6 +1143,7 @@
children = (
4AA8076D1F794C1C008CD551 /* Info.plist */,
911DB12D24C4837E0027F3C7 /* APICommandTests.swift */,
7023800E2747FCCD00EFC443 /* ExtensionsTests.swift */,
7003957525A0EE770052CB31 /* BatchUtilsTests.swift */,
70DFEA892618E77800F8EB4B /* InitializeSDKTests.swift */,
709B40C0268F999000ED2EAC /* IOS13Tests.swift */,
Expand Down Expand Up @@ -2233,6 +2238,7 @@
705A99F9259807F900B3547F /* ParseFileManagerTests.swift in Sources */,
7044C20625C5D6780011F6E7 /* ParseQueryCombineTests.swift in Sources */,
70C5508525B4A68700B5DBC2 /* ParseOperationTests.swift in Sources */,
7023800F2747FCCD00EFC443 /* ExtensionsTests.swift in Sources */,
917BA43E2703E84000F8D747 /* ParseOperationAsyncTests.swift in Sources */,
7037DAB226384DE1005D7E62 /* TestParseEncoder.swift in Sources */,
7004C24D25B69207005E0AD9 /* ParseRoleTests.swift in Sources */,
Expand Down Expand Up @@ -2457,6 +2463,7 @@
705A99FB259807F900B3547F /* ParseFileManagerTests.swift in Sources */,
7044C20825C5D6780011F6E7 /* ParseQueryCombineTests.swift in Sources */,
70C5508725B4A68700B5DBC2 /* ParseOperationTests.swift in Sources */,
702380112747FCCD00EFC443 /* ExtensionsTests.swift in Sources */,
917BA4402703E84000F8D747 /* ParseOperationAsyncTests.swift in Sources */,
7037DAB426384DE1005D7E62 /* TestParseEncoder.swift in Sources */,
7004C26125B6920B005E0AD9 /* ParseRoleTests.swift in Sources */,
Expand Down Expand Up @@ -2544,6 +2551,7 @@
705A99FA259807F900B3547F /* ParseFileManagerTests.swift in Sources */,
7044C20725C5D6780011F6E7 /* ParseQueryCombineTests.swift in Sources */,
70C5508625B4A68700B5DBC2 /* ParseOperationTests.swift in Sources */,
702380102747FCCD00EFC443 /* ExtensionsTests.swift in Sources */,
917BA43F2703E84000F8D747 /* ParseOperationAsyncTests.swift in Sources */,
7037DAB326384DE1005D7E62 /* TestParseEncoder.swift in Sources */,
7004C25725B6920A005E0AD9 /* ParseRoleTests.swift in Sources */,
Expand Down
5 changes: 5 additions & 0 deletions Sources/ParseSwift/API/API+Command.swift
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,11 @@ internal extension API.Command {

// MARK: Saving ParseObjects - private
private static func create<T>(_ object: T) -> API.Command<T, T> where T: ParseObject {
var object = object
if object.ACL == nil,
let acl = try? ParseACL.defaultACL() {
object.ACL = acl
}
let mapper = { (data) -> T in
try ParseCoding.jsonDecoder().decode(SaveResponse.self, from: data).apply(to: object)
}
Expand Down
47 changes: 25 additions & 22 deletions Sources/ParseSwift/Coding/ParseEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -318,32 +318,35 @@ private class _ParseEncoder: JSONEncoder, Encoder {
} else {
valueToEncode = pointer
}
} else if let object = value as? Objectable,
let pointer = try? PointerType(object) {
if let uniquePointer = self.uniquePointer,
uniquePointer.hasSameObjectId(as: pointer) {
throw ParseError(code: .unknownError,
message: "Found a circular dependency when encoding.")
}
if !self.collectChildren && codingPath.count > 0 {
valueToEncode = value
} else if let object = value as? Objectable {
if let pointer = try? PointerType(object) {
if let uniquePointer = self.uniquePointer,
uniquePointer.hasSameObjectId(as: pointer) {
throw ParseError(code: .unknownError,
message: "Found a circular dependency when encoding.")
}
if !self.collectChildren && codingPath.count > 0 {
valueToEncode = value
} else {
valueToEncode = pointer
}
} else {
valueToEncode = pointer
}
} else {
let hashOfCurrentObject = try BaseObjectable.createHash(value)
if self.collectChildren {
var object = object
if object.ACL == nil,
let acl = try? ParseACL.defaultACL() {
object.ACL = acl
}
let hashOfCurrentObject = try BaseObjectable.createHash(object)
valueToEncode = object
if let pointerForCurrentObject = self.objectsSavedBeforeThisOne?[hashOfCurrentObject] {
valueToEncode = pointerForCurrentObject
} else {
//New object needs to be saved before it can be pointed to
self.newObjects.append(value)
} else if self.collectChildren {
// New object needs to be saved before it can be pointed to
self.newObjects.append(object)
} else if dictionary.count > 0 {
// Only top level objects can be saved without a pointer
throw ParseError(code: .unknownError, message: "Error. Couldn't resolve unsaved object while encoding.")
}
} else if let pointerForCurrentObject = self.objectsSavedBeforeThisOne?[hashOfCurrentObject] {
valueToEncode = pointerForCurrentObject
} else if dictionary.count > 0 {
//Only top level objects can be saved without a pointer
throw ParseError(code: .unknownError, message: "Error. Couldn't resolve unsaved object while encoding.")
}
}
return valueToEncode
Expand Down
9 changes: 7 additions & 2 deletions Sources/ParseSwift/Objects/ParseInstallation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -598,12 +598,17 @@ extension ParseInstallation {

// MARK: Saving ParseObjects - private
private func createCommand() -> API.Command<Self, Self> {
var object = self
if object.ACL == nil,
let acl = try? ParseACL.defaultACL() {
object.ACL = acl
}
let mapper = { (data) -> Self in
try ParseCoding.jsonDecoder().decode(SaveResponse.self, from: data).apply(to: self)
try ParseCoding.jsonDecoder().decode(SaveResponse.self, from: data).apply(to: object)
}
return API.Command<Self, Self>(method: .POST,
path: endpoint(.POST),
body: self,
body: object,
mapper: mapper)
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/ParseSwift/Objects/ParseObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -792,10 +792,10 @@ extension ParseObject {
try waitingToBeSaved.forEach { parseType in

if let parseFile = parseType as? ParseFile {
//ParseFiles can be saved now
// ParseFiles can be saved now
savableFiles.append(parseFile)
} else if let parseObject = parseType as? Objectable {
//This is a ParseObject
// This is a ParseObject
let waitingObjectInfo = try ParseCoding
.parseEncoder()
.encode(parseObject,
Expand Down
9 changes: 7 additions & 2 deletions Sources/ParseSwift/Objects/ParseUser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -979,12 +979,17 @@ extension ParseUser {

// MARK: Saving ParseObjects - private
private func createCommand() -> API.Command<Self, Self> {
var object = self
if object.ACL == nil,
let acl = try? ParseACL.defaultACL() {
object.ACL = acl
}
let mapper = { (data) -> Self in
try ParseCoding.jsonDecoder().decode(SaveResponse.self, from: data).apply(to: self)
try ParseCoding.jsonDecoder().decode(SaveResponse.self, from: data).apply(to: object)
}
return API.Command<Self, Self>(method: .POST,
path: endpoint(.POST),
body: self,
body: object,
mapper: mapper)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/ParseSwift/ParseConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Foundation

enum ParseConstants {
static let sdk = "swift"
static let version = "2.2.5"
static let version = "2.2.6"
static let fileManagementDirectory = "parse/"
static let fileManagementPrivateDocumentsDirectory = "Private Documents/"
static let fileManagementLibraryDirectory = "Library/"
Expand Down
42 changes: 24 additions & 18 deletions Sources/ParseSwift/Types/ParseACL.swift
Original file line number Diff line number Diff line change
Expand Up @@ -303,32 +303,38 @@ extension ParseACL {
*/
public static func defaultACL() throws -> Self {

let aclController: DefaultACL?
let aclController: DefaultACL!

#if !os(Linux) && !os(Android) && !os(Windows)
aclController = try? KeychainStore.shared.get(valueFor: ParseStorage.Keys.defaultACL)
if let controller: DefaultACL = try? KeychainStore.shared.get(valueFor: ParseStorage.Keys.defaultACL) {
aclController = controller
} else {
throw ParseError(code: .unknownError,
message: "Default ACL can't be found in Keychain. You should `setDefaultACL` first")
}
#else
aclController = try? ParseStorage.shared.get(valueFor: ParseStorage.Keys.defaultACL)
if let controller: DefaultACL = try? ParseStorage.shared.get(valueFor: ParseStorage.Keys.defaultACL) {
aclController = controller
} else {
throw ParseError(code: .unknownError,
message: "Default ACL can't be found in Keychain. You should `setDefaultACL` first")
}
#endif

if let acl = aclController {
if !acl.useCurrentUser {
return acl.defaultACL
} else {
guard let userObjectId = BaseParseUser.current?.objectId else {
return acl.defaultACL
}

guard let lastCurrentUserObjectId = acl.lastCurrentUserObjectId,
userObjectId == lastCurrentUserObjectId else {
return try setDefaultACL(ParseACL(), withAccessForCurrentUser: true)
}
if !aclController.useCurrentUser {
return aclController.defaultACL
} else {
guard let userObjectId = BaseParseUser.current?.objectId else {
return aclController.defaultACL
}

return acl.defaultACL
guard let lastCurrentUserObjectId = aclController.lastCurrentUserObjectId,
userObjectId == lastCurrentUserObjectId else {
return try setDefaultACL(ParseACL(), withAccessForCurrentUser: true)
}
}

return try setDefaultACL(ParseACL(), withAccessForCurrentUser: true)
return aclController.defaultACL
}
}

/**
Expand Down
42 changes: 42 additions & 0 deletions Tests/ParseSwiftTests/ExtensionsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// ExtensionsTests.swift
// ParseSwift
//
// Created by Corey Baker on 11/19/21.
// Copyright © 2021 Parse Community. All rights reserved.
//

import Foundation
import XCTest
@testable import ParseSwift

class ExtensionsTests: XCTestCase {
override func setUpWithError() throws {
try super.setUpWithError()
guard let url = URL(string: "http://localhost:1337/1") else {
XCTFail("Should create valid URL")
return
}
ParseSwift.initialize(applicationId: "applicationId",
clientKey: "clientKey",
masterKey: "masterKey",
serverURL: url,
testing: true)
}

override func tearDownWithError() throws {
try super.tearDownWithError()
MockURLProtocol.removeAll()
#if !os(Linux) && !os(Android) && !os(Windows)
try KeychainStore.shared.deleteAll()
#endif
try ParseStorage.shared.deleteAll()
}

#if !os(Linux) && !os(Android) && !os(Windows)
func testURLSession() throws {
ParseSwift.configuration.isTestingSDK = false
XCTAssertNotNil(URLSession.parse.configuration.urlCache)
}
#endif
}
8 changes: 5 additions & 3 deletions Tests/ParseSwiftTests/ParseACLTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@ class ParseACLTests: XCTestCase {
}
}

func testNoDefaultACL() {
XCTAssertThrowsError(try ParseACL.defaultACL())
}

func testDefaultACL() {
let loginResponse = LoginSignupResponse()
let loginUserName = "hello10"
Expand Down Expand Up @@ -276,10 +280,8 @@ class ParseACLTests: XCTestCase {
newACL.publicRead = true
newACL.publicWrite = true
do {
var defaultACL = try ParseACL.defaultACL()
XCTAssertNotEqual(newACL, defaultACL)
_ = try ParseACL.setDefaultACL(newACL, withAccessForCurrentUser: true)
defaultACL = try ParseACL.defaultACL()
let defaultACL = try ParseACL.defaultACL()
XCTAssertEqual(newACL.publicRead, defaultACL.publicRead)
XCTAssertEqual(newACL.publicWrite, defaultACL.publicWrite)
XCTAssertTrue(defaultACL.getReadAccess(objectId: userObjectId))
Expand Down
1 change: 0 additions & 1 deletion Tests/ParseSwiftTests/ParseAnalyticsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ class ParseAnalyticsTests: XCTestCase {
func testTrackAppOpenedNotAuthorized() {
if #available(macOS 11.0, iOS 14.0, macCatalyst 14.0, tvOS 14.0, *) {
ParseSwift.configuration.isTestingSDK = false //Allow authorization check

let expectation = XCTestExpectation(description: "Analytics save")
ParseAnalytics.trackAppOpened(dimensions: ["stop": "drop"]) { result in

Expand Down
4 changes: 2 additions & 2 deletions Tests/ParseSwiftTests/ParseInstallationAsyncTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ class ParseInstallationAsyncTests: XCTestCase { // swiftlint:disable:this type_b
}

do {
let saved = try Installation.current!.save()
guard let newCurrentInstallation = Installation.current else {
guard let saved = try Installation.current?.save(),
let newCurrentInstallation = Installation.current else {
XCTFail("Should have a new current installation")
return
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/ParseSwiftTests/ParseInstallationCombineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ class ParseInstallationCombineTests: XCTestCase { // swiftlint:disable:this type
}

do {
let saved = try Installation.current!.save()
guard let newCurrentInstallation = Installation.current else {
guard let saved = try Installation.current?.save(),
let newCurrentInstallation = Installation.current else {
XCTFail("Should have a new current installation")
return
}
Expand Down
Loading