question

Kamil avatar image
Kamil asked

Groups: Can I create roles with specific permissions on create group?

Hello,

I want to create several roles with specific permissions for each group, which is being created. Groups are created from my game in Unity, so I want to do that with code in C#.

I saw question from Darius Vu on 19th July (Mentioned question), so I know how to create new role using CreateGroupRoleRequest and I can do this when OnCreateGroup method is invoked, but I would like to assign specific permissions for a given role right away.

What could be the best way to do that? I read that using PlayFab Admins API to update policy isn't good idea from client (server for my game will be probably on Photon Cloud, so I don't create code for server-side).

Thank you in advance for your answer.

unity3d
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Gosen Gao avatar image
Gosen Gao answered

Would you please try the code below? I have tested it and it works.

handlers.CModifyProfilePolicyWhileCreateGroup = function(args, context) {
    let permissions = entity.GetProfile({Entity:{
        Id:args.GroupId,
        Type:args.GroupType
    }}).Profile.Permissions;
    permissions.push({
        "Action": "*",
        "Effect": "Deny",
        "Resource": "pfrn:data--*!*/Profile/Objects",
        "Principal": {
            "MemberOf": {
                "RoleId": "*"
            }
        },
        "Comment": "Deny Objects access",
        "Condition": null
    });
    let result = entity.SetProfilePolicy({
        Entity:{
            Id:args.GroupId,
            Type:args.GroupType
        },
        Statements:permissions
    })
    return result;
};
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Kamil avatar image Kamil commented ·

I tested your code right away and it works perfectly. Thank you very much!

1 Like 1 ·
Gosen Gao avatar image
Gosen Gao answered

According to your description, I think what you need is API SetProfilePolicy. This API can modify the Policy of Group. You can see this Policy in [Game Manager]->[Groups]->[Policy].

You may need to implement a Cloud Script/Azure Function to handle all process in one execution. This CSAF should include the following features.

  • Create Group
  • Create Rule
  • Set Profile Policy

It is important to note that the policies you write in parameter Statements will overwrite the original Policy. API GetProfile returns the original Policy.

For more information about Set Profile Policy please refer to Set Profile Policy.

In terms of Cloud Script, please refer to CloudScript quickstart.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Kamil avatar image
Kamil answered

Thank you for your answer.

So far I have made two functions in CloudScript to get old policy for a group and to set new permissions for a new role. Function to get policy works perfectly. For both functions I attach the code below:

handlers.createRoleInGroupWithSpecificPermissions = function (args, context) {


    // The profile of the entity specified in the 'ExecuteEntityCloudScript' request.
    // Defaults to the authenticated entity in the X-EntityToken header.
    var entityProfile = args;


    // The pre-defined 'entity' object has functions corresponding to each PlayFab Entity API,
    // including 'SetObjects' (https://api.playfab.com/documentation/Data/method/SetObjects).
    
    let stringStatementsInJSON = entityProfile.OldListOfPermissions;
    
    var request = 
    {
        Entity: {
            Id: entityProfile.Id,
            Type: entityProfile.Type,
            TypeString: entityProfile.TypeString
        },
        Statements: [
            stringStatementsInJSON,
            {
                Action: "*",
                Effect: "Allow",
                Resource: "pfrn:group--group!*/Applications/*",
                Principal: {
                    MemberOf: {
                        RoleId: "viceadmins"
                    },
                    ChildOf: {
                        EntityType: "title",
                        EntityId: "5ACE5"
                    }
               },
                Comment: "Vicedmins access to invitations",
                Condition: null
            }
        ]
    };
        
    var result = entity.SetProfilePolicy(request);//GetProfile(request);
    return result;
};


handlers.getGroupPolicy = function (args, context) {


    // The profile of the entity specified in the 'ExecuteEntityCloudScript' request.
    // Defaults to the authenticated entity in the X-EntityToken header.
    var entityProfile = args;


    // The pre-defined 'entity' object has functions corresponding to each PlayFab Entity API,
    // including 'SetObjects' (https://api.playfab.com/documentation/Data/method/SetObjects).
    var request = {
        Entity: {
            Id: entityProfile.Id,
            Type: entityProfile.Type,
            TypeString: entityProfile.TypeString
        },
        DataAsObject: false
    };
    var result = entity.GetProfile(request);
    return result;
};

I have a problem with passing existing permissions to request to set new ones (due to the fact that SetProfilePolicy overwrites everything as you mentioned).

My code in C# to get actual policy:

PlayFabClientAPI.ExecuteCloudScript(new PlayFab.ClientModels.ExecuteCloudScriptRequest()
            {
                FunctionName = "getGroupPolicy",
                RevisionSelection = PlayFab.ClientModels.CloudScriptRevisionOption.Live,
                GeneratePlayStreamEvent = true,
                FunctionParameter = new
                {
                    Id = groupEntity.Id,
                    Type = groupEntity.Type,
                    TypeString = groupEntity.Type
                }
            }, OnExecuteCloudScript, OnSharedError);


private void OnExecuteCloudScript(PlayFab.ClientModels.ExecuteCloudScriptResult result)
        {
            JsonObject jsonResult = (JsonObject)result.FunctionResult;
            jsonResult.TryGetValue("Profile", out object profileNode);
            JsonObject testJsonObj = (JsonObject)PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer).DeserializeObject(profileNode.ToString());
            testJsonObj.TryGetValue("Permissions", out object oldListOfPermissionsTemp);
            oldListOfPermissions = oldListOfPermissionsTemp.ToString().Trim(new char[] { '[', ']' });

And to set new policy:

PlayFabClientAPI.ExecuteCloudScript(new PlayFab.ClientModels.ExecuteCloudScriptRequest()
            {
                FunctionName = "createRoleInGroupWithSpecificPermissions",
                RevisionSelection = PlayFab.ClientModels.CloudScriptRevisionOption.Live,
                GeneratePlayStreamEvent = true,
                FunctionParameter = new
                {
                    Id = groupEntity.Id,
                    Type = groupEntity.Type,
                    TypeString = groupEntity.Type,
                    OldListOfPermissions = oldListOfPermissions
                }
            }, OnExecuteSetCloudScript, OnSharedError);

private void OnExecuteSetCloudScript(PlayFab.ClientModels.ExecuteCloudScriptResult result)
        {
            JsonObject jsonResult = (JsonObject)result.FunctionResult;
            Debug.Log(jsonResult);

I invoke mentioned above ExectuteCloudScript on click one of two buttons for test.

When I invoked this method, I got an error to Unity Console with message "The Entity field is required". But when I paste old permissions directly to CloudScript function, everything is OK. I tried with re-serialization, JSON methods in CloudScript, but I still get the same error.

Do you have you any idea where the problem may be?

2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Seth Du avatar image Seth Du ♦ commented ·

Can you figure out in which step does this error occur? Can you print out the variable entityProfile.Id, entityProfile.Type and entityProfile.TypeString in function createRoleInGroupWithSpecificPermissions before the request is sent?

0 Likes 0 ·
Kamil avatar image Kamil Seth Du ♦ commented ·

I haven't tried, but the error message in the Unity console showed the entire request sent and it contained valid values for the Entity field before the permissions list. When I only passed a new permission to the request (written directly in the CloudScript function), everything worked fine. Therefore, I was surprised by the mentioned error. But the answer I accept as the Best Answer works so much better that it avoids a lot of transformations in C# of the response from the request.

By the way, I logged value of variable with old permissions (which is passed to request body), also from CloudScript, and the value itself was OK.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.