"run as" for AddUserToRole

I have a widget that posts to a web service, and if the web service call succeeds, I want to then call $core_v2_roleUsers.AddUserToRole to add the user to the role returned by the web service. The problem is that the user making the call doesn't have the ability to add themselves (it returns a permission error).

If I call the equivalent from my C# code, will that work? (Phrased another way, does my widget extension run with elevated privileges or does it run as the accessing user)

Is there a better, more idiomatic way to allow users to self-add to a role?

Parents
  • You can't execute widget code as another user, you could do it on the server side using the in-process API, but you need to wrap that call in Apis.Get<IUsers>.RunAsUser(...)

    community.telligent.com/.../users-in-process-api-service

  • I'm assuming this hasn't changed in v11 or v12? I.e. we can't run any script APIs as a different user & need to do a widget extension in C#?

  • From what I've seen this is correct.  Only possible workaround is via the use of Automations...you can execute the script as the user that triggers the automation or the service account which could bypass some security.  So if you can extract your logic from a traditional widget and make it work within an automation which is triggered by a platform event or on an interval it might work.

    For a work-around you could maybe make your web service call and if it is successful, update a bit on the user profile extended attributes.  Create an automation that runs on a user update event and check that flag - if it exists, you can add them to the group if you execute the automation as the service account then reset the flag.

  • Thanks for the ideas Slight smile (and confirming that there's no way to do this in Velocity).

    I've been having a go coding this up as a widget extension in C# and have had some luck. Here's some code in case anyone else is trying to do this & wants a head start;

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Diagnostics;
    using System.Linq;
    using Telligent.Evolution.Caching.Services;
    using Telligent.Evolution.Components;
    using Telligent.Evolution.Extensibility;
    using Telligent.Evolution.Extensibility.Api;
    using Telligent.Evolution.Extensibility.Api.Version1;
    using Telligent.Evolution.Extensibility.Version1;
    
    namespace My.Utilities
    {
    	[Documentation(Category = "MyStuff")]
    
    	public class UtilsAPI : IApi
    	{
    		public Telligent.Evolution.Extensibility.Api.Entities.Version1.SearchResults searchResultsList(IDictionary options)
            {
    			Telligent.Evolution.Extensibility.Api.Entities.Version1.SearchResults results = null;
    
    			Apis.Get<IUsers>().RunAsUser("admin", () =>
    			{
    				SearchResultsListOptions searchOptions = new SearchResultsListOptions();
    				
    				// Ideally need a nice way to covert 'IDictionary options' (coming in from Velocity) into 'SearchResultsListOptions searchOptions'..
    				// This gets to be a long messy list the more options you want to expose. Is there a better way to do this?
    				searchOptions.Query = (string)options["Query"];
    				searchOptions.ContainerId = (Guid)options["ContainerId"];
    				// ..... There are loads more options you could set!! :(
    
    				results = Apis.Get<ISearchResults>().List(searchOptions);
    			});
    
    			return results;
    		}
    	}
    }

    This seems to work, but the way it deals with all the options for the List operation isn't ideal. Is there a better way to do this?

Reply
  • Thanks for the ideas Slight smile (and confirming that there's no way to do this in Velocity).

    I've been having a go coding this up as a widget extension in C# and have had some luck. Here's some code in case anyone else is trying to do this & wants a head start;

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Diagnostics;
    using System.Linq;
    using Telligent.Evolution.Caching.Services;
    using Telligent.Evolution.Components;
    using Telligent.Evolution.Extensibility;
    using Telligent.Evolution.Extensibility.Api;
    using Telligent.Evolution.Extensibility.Api.Version1;
    using Telligent.Evolution.Extensibility.Version1;
    
    namespace My.Utilities
    {
    	[Documentation(Category = "MyStuff")]
    
    	public class UtilsAPI : IApi
    	{
    		public Telligent.Evolution.Extensibility.Api.Entities.Version1.SearchResults searchResultsList(IDictionary options)
            {
    			Telligent.Evolution.Extensibility.Api.Entities.Version1.SearchResults results = null;
    
    			Apis.Get<IUsers>().RunAsUser("admin", () =>
    			{
    				SearchResultsListOptions searchOptions = new SearchResultsListOptions();
    				
    				// Ideally need a nice way to covert 'IDictionary options' (coming in from Velocity) into 'SearchResultsListOptions searchOptions'..
    				// This gets to be a long messy list the more options you want to expose. Is there a better way to do this?
    				searchOptions.Query = (string)options["Query"];
    				searchOptions.ContainerId = (Guid)options["ContainerId"];
    				// ..... There are loads more options you could set!! :(
    
    				results = Apis.Get<ISearchResults>().List(searchOptions);
    			});
    
    			return results;
    		}
    	}
    }

    This seems to work, but the way it deals with all the options for the List operation isn't ideal. Is there a better way to do this?

Children