8
8
*/
9
9
package com .parse ;
10
10
11
+ import android .os .Parcel ;
12
+ import android .os .Parcelable ;
13
+
11
14
import org .json .JSONException ;
12
15
import org .json .JSONObject ;
13
16
14
17
import java .lang .ref .WeakReference ;
15
18
import java .util .HashMap ;
16
19
import java .util .Map ;
20
+ import java .util .Set ;
17
21
18
22
/**
19
23
* A {@code ParseACL} is used to control which users can access or modify a particular object. Each
22
26
* permissions to "the public" so that, for example, any user could read a particular object but
23
27
* only a particular set of users could write to that object.
24
28
*/
25
- public class ParseACL {
29
+ public class ParseACL implements Parcelable {
26
30
private static final String PUBLIC_KEY = "*" ;
27
31
private final static String UNRESOLVED_KEY = "*unresolved" ;
28
32
private static final String KEY_ROLE_PREFIX = "role:" ;
@@ -61,6 +65,11 @@ private static class Permissions {
61
65
return json ;
62
66
}
63
67
68
+ /* package */ void toParcel (Parcel parcel ) {
69
+ parcel .writeByte (readPermission ? (byte ) 1 : 0 );
70
+ parcel .writeByte (writePermission ? (byte ) 1 : 0 );
71
+ }
72
+
64
73
/* package */ boolean getReadPermission () {
65
74
return readPermission ;
66
75
}
@@ -74,6 +83,10 @@ private static class Permissions {
74
83
boolean write = object .optBoolean (WRITE_PERMISSION , false );
75
84
return new Permissions (read , write );
76
85
}
86
+
87
+ /* package */ static Permissions createPermissionsFromParcel (Parcel parcel ) {
88
+ return new Permissions (parcel .readByte () == 1 , parcel .readByte () == 1 );
89
+ }
77
90
}
78
91
79
92
private static ParseDefaultACLController getDefaultACLController () {
@@ -205,7 +218,7 @@ public ParseACL(ParseUser owner) {
205
218
}
206
219
207
220
/* package for tests */ void resolveUser (ParseUser user ) {
208
- if (user != unresolvedUser ) {
221
+ if (! isUnresolvedUser ( user ) ) {
209
222
return ;
210
223
}
211
224
if (permissionsById .containsKey (UNRESOLVED_KEY )) {
@@ -336,20 +349,27 @@ private void setUnresolvedWriteAccess(ParseUser user, boolean allowed) {
336
349
private void prepareUnresolvedUser (ParseUser user ) {
337
350
// Registers a listener for the user so that when it is saved, the
338
351
// unresolved ACL will be resolved.
339
- if (this . unresolvedUser != user ) {
352
+ if (! isUnresolvedUser ( user ) ) {
340
353
permissionsById .remove (UNRESOLVED_KEY );
341
354
unresolvedUser = user ;
342
- user .registerSaveListener (new UserResolutionListener (this ));
355
+ unresolvedUser .registerSaveListener (new UserResolutionListener (this ));
343
356
}
344
357
}
345
358
359
+ private boolean isUnresolvedUser (ParseUser other ) {
360
+ // This might be a different instance, but if they have the same local id, assume it's correct.
361
+ if (other == null || unresolvedUser == null ) return false ;
362
+ return other == unresolvedUser || (other .getObjectId () == null &&
363
+ other .getOrCreateLocalId ().equals (unresolvedUser .getOrCreateLocalId ()));
364
+ }
365
+
346
366
/**
347
367
* Get whether the given user id is *explicitly* allowed to read this object. Even if this returns
348
368
* {@code false}, the user may still be able to access it if getPublicReadAccess returns
349
369
* {@code true} or a role that the user belongs to has read access.
350
370
*/
351
371
public boolean getReadAccess (ParseUser user ) {
352
- if (user == unresolvedUser ) {
372
+ if (isUnresolvedUser ( user ) ) {
353
373
return getReadAccess (UNRESOLVED_KEY );
354
374
}
355
375
if (user .isLazy ()) {
@@ -381,7 +401,7 @@ public void setWriteAccess(ParseUser user, boolean allowed) {
381
401
* {@code true} or a role that the user belongs to has write access.
382
402
*/
383
403
public boolean getWriteAccess (ParseUser user ) {
384
- if (user == unresolvedUser ) {
404
+ if (isUnresolvedUser ( user ) ) {
385
405
return getWriteAccess (UNRESOLVED_KEY );
386
406
}
387
407
if (user .isLazy ()) {
@@ -536,4 +556,56 @@ public void done(ParseObject object, ParseException e) {
536
556
/* package for tests */ Map <String , Permissions > getPermissionsById () {
537
557
return permissionsById ;
538
558
}
559
+
560
+ @ Override
561
+ public int describeContents () {
562
+ return 0 ;
563
+ }
564
+
565
+ @ Override
566
+ public void writeToParcel (Parcel dest , int flags ) {
567
+ writeToParcel (dest , new ParseObjectParcelEncoder ());
568
+ }
569
+
570
+ /* package */ void writeToParcel (Parcel dest , ParseParcelEncoder encoder ) {
571
+ dest .writeByte (shared ? (byte ) 1 : 0 );
572
+ dest .writeInt (permissionsById .size ());
573
+ Set <String > keys = permissionsById .keySet ();
574
+ for (String key : keys ) {
575
+ dest .writeString (key );
576
+ Permissions permissions = permissionsById .get (key );
577
+ permissions .toParcel (dest );
578
+ }
579
+ dest .writeByte (unresolvedUser != null ? (byte ) 1 : 0 );
580
+ if (unresolvedUser != null ) {
581
+ // Encoder will create a local id for unresolvedUser, so we recognize it after unparcel.
582
+ encoder .encode (unresolvedUser , dest );
583
+ }
584
+ }
585
+
586
+ public final static Creator <ParseACL > CREATOR = new Creator <ParseACL >() {
587
+ @ Override
588
+ public ParseACL createFromParcel (Parcel source ) {
589
+ return new ParseACL (source , new ParseObjectParcelDecoder ());
590
+ }
591
+
592
+ @ Override
593
+ public ParseACL [] newArray (int size ) {
594
+ return new ParseACL [size ];
595
+ }
596
+ };
597
+
598
+ /* package */ ParseACL (Parcel source , ParseParcelDecoder decoder ) {
599
+ shared = source .readByte () == 1 ;
600
+ int size = source .readInt ();
601
+ for (int i = 0 ; i < size ; i ++) {
602
+ String key = source .readString ();
603
+ Permissions permissions = Permissions .createPermissionsFromParcel (source );
604
+ permissionsById .put (key , permissions );
605
+ }
606
+ if (source .readByte () == 1 ) {
607
+ unresolvedUser = (ParseUser ) decoder .decode (source );
608
+ unresolvedUser .registerSaveListener (new UserResolutionListener (this ));
609
+ }
610
+ }
539
611
}
0 commit comments