Sitecore extranet admins? - sitecore

Hi
I am devolping an application with multiple sites and each site has their own extranet, and this is all working beautifully, using Sitecore 6.4.
Now I need the editors (not admins) of each site to be able to create extranet users that is only able to access the extranet connected to the site, is this even possible?
Basically I am looking for at structure like this:
Sitecore\Editor (Local extranet admin)
Extranet\user

I would think you could make an Extranet Role for each of you "extranets", eg. Site1Admin.
And then make a page that enables them to create a user, giving that user the basic roles it needs.
This is code for Sitecore 6.0, though it should be the same for 6.4 afaik:
Sitecore.Security.Accounts.User user;
if (!Sitecore.Context.IsLoggedIn)
{
string domainUser = Sitecore.Context.Domain.GetFullName("youruser");
string txtPassword = "yourpass";
string txtEmail = "youremail";
if (Sitecore.Security.Accounts.User.Exists(domainUser))
return;
MembershipCreateStatus status;
Membership.CreateUser(domainUser, txtPassword, txtEmail, "Never?", "Always!", true, out status);
if (!status.Equals(MembershipCreateStatus.Success))
{
throw new MembershipCreateUserException(status.ToString());
}
user = //something to load the user, probably in Sitecore.Security.Accounts.User
}
var role = "extranet\\Site1User";
var roles = Roles.GetRolesForUser(); //this is probably only for the current context user
if (!roles.Contains(role))
{
try
{
Roles.AddUsersToRole(new string[] { "youruser" }, role);
}
catch(System.Configuration.Provider.ProviderException)
{
// do nothing, just move on
}
}
}
This is kinda simple, is based on some code I tried to hack together from some working code, that created a user and logged him in and should be adjusted to what you are doing, as there are probably some errors.

Related

Sharepoint 2013 - Web Application Permission Policy issue

In our sharepoint farm we have two groups:
Users - Contains ALL users of our application (including administrators)
Admins - Contains users with admin privileges
I'm currently trying to deny access to System Pages (_layouts/ files) for all users in the "Users" group to prevent modifying lists etc. without going through the corresponding webpart UI.
To do this I added a permission policy with DENY on View Application Pages. This works as its supposed to for normal users, but the problem is it also blocks the administrators from accessing lists etc.
I tried granting everything to the Admins group, but the deny still overrides it preventing access.
How can I grant access to the admins when their user is blocked in another group?
You could use JSOM solution, check user groups and admin by JSOM(sample script from this thread).
Below script contains logic to check is user admin.
function IsCurrentUserMemberOfGroups(groups, OnComplete) {
var currentContext = new SP.ClientContext.get_current();
var currentWeb = currentContext.get_web();
var currentUser = currentWeb.get_currentUser();
var isAdmin = currentUser.get_isSiteAdmin();
var oGroups = currentUser.get_groups();
currentContext.load(isAdmin);
currentContext.load(currentUser);
currentContext.load(oGroups);
currentContext.executeQueryAsync(OnSuccess, OnFailure);
function OnSuccess(sender, args) {
var userInGroup = false;
console.log('Admin check' + isAdmin);
if (!isAdmin) {
var groupEnumerator = oGroups.getEnumerator();
while (groupEnumerator.moveNext()) {
var oGroup = groupEnumerator.get_current();
var groupTitle = oGroup.get_title();
console.log(groupTitle);
$.each(groups, function (index, value) {
if (value == groupTitle) {
console.log('user in group ' + groupTitle);
userInGroup = true;
}
});
if (userInGroup)
break;
}
}
OnComplete(userInGroup);
}
function OnFailure(sender, args) {
OnComplete(false);
}
}
Then, redirect user to a friendly page.
Add the script to master page or add as javascript link as it need to be run globally.
SharePoint Custom JS file Best Practice

Sitecore Virtual User Login Experience Profile

I need to validate user credentials from external service, therefore I'm using the VirtualUser authentication.
BuildVirtualUser, checking for the roles to set to him, saving the user Profile and then login with that name.
I'm facing a problem, that everyday that i login, with the same credentials Sitecore creates a new user in Experience Profile.
What i need to change in my code to assure that, with virtual user login, Sitecore gets the old experience profile of the user?
I was thinking in creating the user in sitecore with same generic password. Instead of using the virtual user, and authenticate directly with sitecore. Is that correct?
Here's my code:
Sitecore.Security.Accounts.User user = Sitecore.Security.Authentication.AuthenticationManager.BuildVirtualUser(sitecoreUser, true);
string roleName = #"newRole\User";
Sitecore.Security.Accounts.Role demoRole = Sitecore.Security.Accounts.Role.FromName(roleName);
if (Sitecore.Security.Accounts.Role.Exists(roleName) && !demoRole.IsMember(user, true, false))
{
user.Roles.Add(Sitecore.Security.Accounts.Role.FromName(roleName));
}
user.Profile.Name = name;
user.Profile.Email = email;
user.Profile.FullName = fullname;
user.Profile.Save();
Sitecore.Security.Authentication.AuthenticationManager.Login(user.Name);
Tracker.Initialize();
Code looks fine, but you miss one important thing: to identify your user/contact.
You need to add next line of code:
Tracker.Current.Session.Identify(email);
Please check next link to find more information about how to identify contacts:
https://doc.sitecore.net/sitecore_experience_platform/setting_up__maintaining/xdb/contacts/identifying_contacts

Retrieving Google User Photo

I am able to retrieve the thumbnailPhotoUrl from the user.list api of the google admin SDK. However, whenever I try to render the image, Google is redirecting to a static silhouette image. The URL that is retrieved via the API looks like
https://plus.google.com/_/focus/photos/private/AIbEiAIA....
As mentioned, this ends up getting redirected to:
https://ssl.gstatic.com/s2/profiles/images/silhouette200.png
However, with a little bit of reverse engineering, I can see the photo by adding /u/1/ to the beginning of the URL path, like this:
https://plus.google.com/u/1/_/focus/photos/private/AIbEiAIA...
From my research the /u/1 has something to do with multiple google accounts, so I'm afraid I wouldn't be able to rely on this method. Can anyone help me understand what's happening here?
Out of my own experience I figured out that if the thumbnailPhotoUrl has private on the URL then the photo is not public i.e. not viewable outside the domain, it could also be that the user hasn't activated their Google+ profile, which I believe makes their photo public anyway.
Best to avoid using the thumbnailPhotoUrl if the URL has a private path on it. I think it's more reliable to retrieve the photo as Web-safe base64 data using the Users.Photo API then encode it as an inline base64 CSS image.
This is the code snippet I usually use:
import com.google.common.io.BaseEncoding;
import com.google.api.services.admin.directory.model.User;
import com.google.api.services.admin.directory.model.UserPhoto;
public class PhotoUtils {
public void loadPhoto() {
// if the user have not signed up for Google+ yet then their thumbnail is private
String thumbnailUrl = user.getThumbnailPhotoUrl();
String photoData = "";
if((thumbnailUrl != null) && (thumbnailUrl.indexOf("private") > -1)) {
UserPhoto photo = getUserPhoto(user.getId());
if(photo != null) {
photoData = getBase64CssImage(photo.getPhotoData(), photo.getMimeType());
}
}
}
public static String getBase64CssImage(String urlSafeBase64Data, String mimeType) {
urlSafeBase64Data = new String(BaseEncoding.base64().encode(
BaseEncoding.base64Url().decode(urlSafeBase64Data)));
return "data:" + mimeType + ";base64," + urlSafeBase64Data;
}
public UserPhoto getUserPhoto(String userId) throws IOException {
UserPhoto photo = null;
try {
photo = this.getClient().users().photos().get(userId).execute();
} catch(GoogleJsonResponseException e) {
if(e.getMessage().indexOf(NOT_FOUND) == 0) {
log.warning("No photo is found for user: " + userId);
} else {
throw e;
}
}
return photo;
}
}
Here are my 10 cents...
Recently I've been working on building a G Suite User Picker for Angular and I ran into the same problem. Nonetheless, I kept testing and researching and in one of my tests I decided to call the directory api users list endpoint with a NON-ADMIN user. (Head Explodes 🤯) To my surprise, google permits this type of requests, although it provides non super admin data but enough to get a private thumbnail url for the user. At first I thought it was an unintended behaviour, some kind of bug if you will. That is when I ran into this documentation.
While user accounts can only be modified by administrators, any user on the domain can read user profiles. A non-admin user can make a users.get or users.list request with the viewType parameter equal to domain_public to retrieve a user's public profile. The scope https://www.googleapis.com/auth/admin.directory.user.readonly is ideal for this use case.
So it is an intended behaviour. That is when it hit me. The private url generated when retrieving the user data is intended to be used only by the requesting user. If you provide the url to other user, it will redirect to the anonymous silhouette.
From this I was able to conclude that if I need to retrieve a list of users and need the ability to view their photos, I need to call the directory api endpoint using the credentials of the user that needs to view the respective data. This serves my purpose with the G Suite User Picker widget I am building.

Sitecore non administrator user show hidden items

I have created some Sitecore users who are not administrators and assigned them few roles. When these users access the Sitecore portal as default they are not shown hidden items and they have to go to view tab and configure it manually. Is there a way I can configure these users to view hidden items by default by doing some configurations to a user role shared between these users.
This information is retrieved by Sitecore.Shell.UserOptions.View.ShowHiddenItems property which gets this data from UserProfile (or from RegistryCache if the profile was already loaded).
User profile information is stored for every user separately and saved in database in binary column. There is no way of getting this option from user role.
Still you can write a script that will loop through all users in the role you mentioned and set the value in profile of those users:
public static void SetHiddenItemsValue(User user)
{
string key = "/Current_User/UserOptions.View.ShowHiddenItems";
string value = "true";
if (!(user != null))
return;
key = StringUtil.Left(key, 250);
key = key.Replace("Current_User", user.Name);
user.Profile[key] = value;
user.Profile.Save();
RegistryCache registryCache = CacheManager.GetRegistryCache(Sitecore.Context.Site);
if (registryCache == null)
return;
registryCache.Clear();
}
An alternative option from Maras is you could possibly hook into the security:loggedin event and set that value.
Your class needs to inherit from Sitecore.Pipelines.LoggedIn.LoggedInProcessor
That'll need to do something like the following:
public override void Process(LoggedInArgs args)
{
var user = Sitecore.Security.Accounts.User.FromName(args.Username, true);
var key = "/" + args.Username + "/UserOptions.View.ShowHiddenItems";
// if user needs to be in a specific role only, check that here
// if (user.IsInRole("yourrolename"))
if (String.IsNullOrEmpty(user.Profile[key]))
{
user.Profile[key] = "true";
user.Profile.Save();
}
}

Why Sitecore create virtual users with all extranet roles?

I am not sure about BuildVirtualUser method behavior in Sitecore 6.6 update 3
I have the following code:
bool isAuthenticated = true;
string userName = string.Format("{0}\\{1}", "extranet", user.Login);
SC.Security.Accounts.User virtualUser = SC.Security.Authentication.AuthenticationManager.BuildVirtualUser(userName, isAuthenticated);
but after BuildVirtualUser method call virtualUser variable contain all extranet roles.
I expect that just my following code should attach role to user.
foreach(var role in user.Permissions)
{
string domainRole = string.Format("{0}\\{1}", "extranet", "USER_EDIT");
if (SC.Security.Accounts.Role.Exists(domainRole))
{
virtualUser.RuntimeSettings.AddedRoles.Add(domainRole);
}
}
Why does it happening? What do I need to do to fix it?
Update 1
I have discovered that first time BuildVirtualUser creates user with 0 roles,
roles can be succesfully added, but after logout and login procedure with the same user name, roles that were added during first time automaticaly attaching to new user. In my opinion this bahavior is not good, in case someone can edit user roles in external system.
Try this:
user.Roles.Add(Sitecore.Security.Accounts.Role.FromName(domainRole));
from:
http://sdn.sitecore.net/upload/sitecore6/sc61keywords/security_api_cookbook_usletter.pdf
I am not sure what your for each loop is, but it's kind of redundant your not doing anything with each 'role'.
SC.Security.Accounts.User virtualUser = SC.Security.Authentication.AuthenticationManager.BuildVirtualUser(userName, true);
virtualUser.RuntimeSettings.AddedRoles.Clear();
virtualUser.Roles.RemoveAll();
this code is help to update user roles dynamicly.
But I still not undetstend why sitecore cache roles for virtual users.